1817466cbSJens Wiklander /*
2817466cbSJens Wiklander * NIST SP800-38D compliant GCM implementation
3817466cbSJens Wiklander *
47901324dSJerome Forissier * Copyright The Mbed TLS Contributors
5*b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6817466cbSJens Wiklander */
7817466cbSJens Wiklander
8817466cbSJens Wiklander /*
9817466cbSJens Wiklander * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
10817466cbSJens Wiklander *
11817466cbSJens Wiklander * See also:
12817466cbSJens Wiklander * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
13817466cbSJens Wiklander *
14817466cbSJens Wiklander * We use the algorithm described as Shoup's method with 4-bit tables in
15817466cbSJens Wiklander * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
16817466cbSJens Wiklander */
17817466cbSJens Wiklander
187901324dSJerome Forissier #include "common.h"
19817466cbSJens Wiklander
20817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C)
21817466cbSJens Wiklander
22817466cbSJens Wiklander #include "mbedtls/gcm.h"
2332b31808SJens Wiklander #include "mbedtls/platform.h"
243d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
2511fa71b9SJerome Forissier #include "mbedtls/error.h"
26*b0563631STom Van Eyck #include "mbedtls/constant_time.h"
27*b0563631STom Van Eyck
28*b0563631STom Van Eyck #if defined(MBEDTLS_BLOCK_CIPHER_C)
29*b0563631STom Van Eyck #include "block_cipher_internal.h"
30*b0563631STom Van Eyck #endif
31817466cbSJens Wiklander
32817466cbSJens Wiklander #include <string.h>
33817466cbSJens Wiklander
34817466cbSJens Wiklander #if defined(MBEDTLS_AESNI_C)
3532b31808SJens Wiklander #include "aesni.h"
36817466cbSJens Wiklander #endif
37817466cbSJens Wiklander
3832b31808SJens Wiklander #if defined(MBEDTLS_AESCE_C)
3932b31808SJens Wiklander #include "aesce.h"
4032b31808SJens Wiklander #endif
41817466cbSJens Wiklander
423d3b0591SJens Wiklander #if !defined(MBEDTLS_GCM_ALT)
433d3b0591SJens Wiklander
44*b0563631STom Van Eyck /* Used to select the acceleration mechanism */
45*b0563631STom Van Eyck #define MBEDTLS_GCM_ACC_SMALLTABLE 0
46*b0563631STom Van Eyck #define MBEDTLS_GCM_ACC_LARGETABLE 1
47*b0563631STom Van Eyck #define MBEDTLS_GCM_ACC_AESNI 2
48*b0563631STom Van Eyck #define MBEDTLS_GCM_ACC_AESCE 3
49*b0563631STom Van Eyck
50817466cbSJens Wiklander /*
51817466cbSJens Wiklander * Initialize a context
52817466cbSJens Wiklander */
mbedtls_gcm_init(mbedtls_gcm_context * ctx)53817466cbSJens Wiklander void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
54817466cbSJens Wiklander {
55817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_gcm_context));
56817466cbSJens Wiklander }
57817466cbSJens Wiklander
gcm_set_acceleration(mbedtls_gcm_context * ctx)58*b0563631STom Van Eyck static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx)
59*b0563631STom Van Eyck {
60*b0563631STom Van Eyck #if defined(MBEDTLS_GCM_LARGE_TABLE)
61*b0563631STom Van Eyck ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE;
62*b0563631STom Van Eyck #else
63*b0563631STom Van Eyck ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE;
64*b0563631STom Van Eyck #endif
65*b0563631STom Van Eyck
66*b0563631STom Van Eyck #if defined(MBEDTLS_AESNI_HAVE_CODE)
67*b0563631STom Van Eyck /* With CLMUL support, we need only h, not the rest of the table */
68*b0563631STom Van Eyck if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
69*b0563631STom Van Eyck ctx->acceleration = MBEDTLS_GCM_ACC_AESNI;
70*b0563631STom Van Eyck }
71*b0563631STom Van Eyck #endif
72*b0563631STom Van Eyck
73*b0563631STom Van Eyck #if defined(MBEDTLS_AESCE_HAVE_CODE)
74*b0563631STom Van Eyck if (MBEDTLS_AESCE_HAS_SUPPORT()) {
75*b0563631STom Van Eyck ctx->acceleration = MBEDTLS_GCM_ACC_AESCE;
76*b0563631STom Van Eyck }
77*b0563631STom Van Eyck #endif
78*b0563631STom Van Eyck }
79*b0563631STom Van Eyck
gcm_gen_table_rightshift(uint64_t dst[2],const uint64_t src[2])80*b0563631STom Van Eyck static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2])
81*b0563631STom Van Eyck {
82*b0563631STom Van Eyck uint8_t *u8Dst = (uint8_t *) dst;
83*b0563631STom Van Eyck uint8_t *u8Src = (uint8_t *) src;
84*b0563631STom Van Eyck
85*b0563631STom Van Eyck MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0);
86*b0563631STom Van Eyck u8Dst[8] |= (u8Src[7] & 0x01) << 7;
87*b0563631STom Van Eyck MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0);
88*b0563631STom Van Eyck u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0;
89*b0563631STom Van Eyck }
90*b0563631STom Van Eyck
91817466cbSJens Wiklander /*
92817466cbSJens Wiklander * Precompute small multiples of H, that is set
93817466cbSJens Wiklander * HH[i] || HL[i] = H times i,
94817466cbSJens Wiklander * where i is seen as a field element as in [MGV], ie high-order bits
95817466cbSJens Wiklander * correspond to low powers of P. The result is stored in the same way, that
96817466cbSJens Wiklander * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
97817466cbSJens Wiklander * corresponds to P^127.
98817466cbSJens Wiklander */
gcm_gen_table(mbedtls_gcm_context * ctx)99817466cbSJens Wiklander static int gcm_gen_table(mbedtls_gcm_context *ctx)
100817466cbSJens Wiklander {
101817466cbSJens Wiklander int ret, i, j;
102*b0563631STom Van Eyck uint64_t u64h[2] = { 0 };
103*b0563631STom Van Eyck uint8_t *h = (uint8_t *) u64h;
104817466cbSJens Wiklander
105*b0563631STom Van Eyck #if defined(MBEDTLS_BLOCK_CIPHER_C)
106*b0563631STom Van Eyck ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);
107*b0563631STom Van Eyck #else
108*b0563631STom Van Eyck size_t olen = 0;
109*b0563631STom Van Eyck ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen);
110*b0563631STom Van Eyck #endif
111*b0563631STom Van Eyck if (ret != 0) {
11232b31808SJens Wiklander return ret;
11332b31808SJens Wiklander }
114817466cbSJens Wiklander
115*b0563631STom Van Eyck gcm_set_acceleration(ctx);
116817466cbSJens Wiklander
117*b0563631STom Van Eyck /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */
118*b0563631STom Van Eyck ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0];
119*b0563631STom Van Eyck ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1];
120817466cbSJens Wiklander
121*b0563631STom Van Eyck switch (ctx->acceleration) {
12232b31808SJens Wiklander #if defined(MBEDTLS_AESNI_HAVE_CODE)
123*b0563631STom Van Eyck case MBEDTLS_GCM_ACC_AESNI:
12432b31808SJens Wiklander return 0;
12532b31808SJens Wiklander #endif
12632b31808SJens Wiklander
127*b0563631STom Van Eyck #if defined(MBEDTLS_AESCE_HAVE_CODE)
128*b0563631STom Van Eyck case MBEDTLS_GCM_ACC_AESCE:
12932b31808SJens Wiklander return 0;
130817466cbSJens Wiklander #endif
131817466cbSJens Wiklander
132*b0563631STom Van Eyck default:
133817466cbSJens Wiklander /* 0 corresponds to 0 in GF(2^128) */
134*b0563631STom Van Eyck ctx->H[0][0] = 0;
135*b0563631STom Van Eyck ctx->H[0][1] = 0;
136817466cbSJens Wiklander
137*b0563631STom Van Eyck for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {
138*b0563631STom Van Eyck gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);
139817466cbSJens Wiklander }
140817466cbSJens Wiklander
141*b0563631STom Van Eyck #if !defined(MBEDTLS_GCM_LARGE_TABLE)
142*b0563631STom Van Eyck /* pack elements of H as 64-bits ints, big-endian */
143*b0563631STom Van Eyck for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) {
144*b0563631STom Van Eyck MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0);
145*b0563631STom Van Eyck MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0);
146*b0563631STom Van Eyck }
147*b0563631STom Van Eyck #endif
148*b0563631STom Van Eyck
149*b0563631STom Van Eyck for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) {
15032b31808SJens Wiklander for (j = 1; j < i; j++) {
151*b0563631STom Van Eyck mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j],
152*b0563631STom Van Eyck (unsigned char *) ctx->H[i],
153*b0563631STom Van Eyck (unsigned char *) ctx->H[j],
154*b0563631STom Van Eyck 16);
155*b0563631STom Van Eyck }
156817466cbSJens Wiklander }
157817466cbSJens Wiklander }
158817466cbSJens Wiklander
15932b31808SJens Wiklander return 0;
160817466cbSJens Wiklander }
161817466cbSJens Wiklander
mbedtls_gcm_setkey(mbedtls_gcm_context * ctx,mbedtls_cipher_id_t cipher,const unsigned char * key,unsigned int keybits)162817466cbSJens Wiklander int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
163817466cbSJens Wiklander mbedtls_cipher_id_t cipher,
164817466cbSJens Wiklander const unsigned char *key,
165817466cbSJens Wiklander unsigned int keybits)
166817466cbSJens Wiklander {
16711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
168817466cbSJens Wiklander
16932b31808SJens Wiklander if (keybits != 128 && keybits != 192 && keybits != 256) {
17032b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT;
17132b31808SJens Wiklander }
1723d3b0591SJens Wiklander
173*b0563631STom Van Eyck #if defined(MBEDTLS_BLOCK_CIPHER_C)
174*b0563631STom Van Eyck mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
175*b0563631STom Van Eyck
176*b0563631STom Van Eyck if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) {
177*b0563631STom Van Eyck return ret;
178*b0563631STom Van Eyck }
179*b0563631STom Van Eyck
180*b0563631STom Van Eyck if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) {
181*b0563631STom Van Eyck return ret;
182*b0563631STom Van Eyck }
183*b0563631STom Van Eyck #else
184*b0563631STom Van Eyck const mbedtls_cipher_info_t *cipher_info;
185*b0563631STom Van Eyck
18611fa71b9SJerome Forissier cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
18711fa71b9SJerome Forissier MBEDTLS_MODE_ECB);
18832b31808SJens Wiklander if (cipher_info == NULL) {
18932b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT;
19032b31808SJens Wiklander }
191817466cbSJens Wiklander
192*b0563631STom Van Eyck if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
19332b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT;
19432b31808SJens Wiklander }
195817466cbSJens Wiklander
196817466cbSJens Wiklander mbedtls_cipher_free(&ctx->cipher_ctx);
197817466cbSJens Wiklander
19832b31808SJens Wiklander if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
19932b31808SJens Wiklander return ret;
200817466cbSJens Wiklander }
201817466cbSJens Wiklander
20232b31808SJens Wiklander if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
20332b31808SJens Wiklander MBEDTLS_ENCRYPT)) != 0) {
20432b31808SJens Wiklander return ret;
20532b31808SJens Wiklander }
206*b0563631STom Van Eyck #endif
207817466cbSJens Wiklander
20832b31808SJens Wiklander if ((ret = gcm_gen_table(ctx)) != 0) {
20932b31808SJens Wiklander return ret;
21032b31808SJens Wiklander }
21132b31808SJens Wiklander
21232b31808SJens Wiklander return 0;
213817466cbSJens Wiklander }
214817466cbSJens Wiklander
215*b0563631STom Van Eyck #if defined(MBEDTLS_GCM_LARGE_TABLE)
216*b0563631STom Van Eyck static const uint16_t last8[256] = {
217*b0563631STom Van Eyck 0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05,
218*b0563631STom Van Eyck 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b,
219*b0563631STom Van Eyck 0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19,
220*b0563631STom Van Eyck 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17,
221*b0563631STom Van Eyck 0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d,
222*b0563631STom Van Eyck 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33,
223*b0563631STom Van Eyck 0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21,
224*b0563631STom Van Eyck 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f,
225*b0563631STom Van Eyck 0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75,
226*b0563631STom Van Eyck 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b,
227*b0563631STom Van Eyck 0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69,
228*b0563631STom Van Eyck 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67,
229*b0563631STom Van Eyck 0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d,
230*b0563631STom Van Eyck 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43,
231*b0563631STom Van Eyck 0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51,
232*b0563631STom Van Eyck 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f,
233*b0563631STom Van Eyck 0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4,
234*b0563631STom Van Eyck 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea,
235*b0563631STom Van Eyck 0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8,
236*b0563631STom Van Eyck 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6,
237*b0563631STom Van Eyck 0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc,
238*b0563631STom Van Eyck 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2,
239*b0563631STom Van Eyck 0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0,
240*b0563631STom Van Eyck 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece,
241*b0563631STom Van Eyck 0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94,
242*b0563631STom Van Eyck 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a,
243*b0563631STom Van Eyck 0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88,
244*b0563631STom Van Eyck 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86,
245*b0563631STom Van Eyck 0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac,
246*b0563631STom Van Eyck 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2,
247*b0563631STom Van Eyck 0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0,
248*b0563631STom Van Eyck 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe
249*b0563631STom Van Eyck };
250*b0563631STom Van Eyck
gcm_mult_largetable(uint8_t * output,const uint8_t * x,uint64_t H[256][2])251*b0563631STom Van Eyck static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2])
252*b0563631STom Van Eyck {
253*b0563631STom Van Eyck int i;
254*b0563631STom Van Eyck uint64_t u64z[2];
255*b0563631STom Van Eyck uint16_t *u16z = (uint16_t *) u64z;
256*b0563631STom Van Eyck uint8_t *u8z = (uint8_t *) u64z;
257*b0563631STom Van Eyck uint8_t rem;
258*b0563631STom Van Eyck
259*b0563631STom Van Eyck u64z[0] = 0;
260*b0563631STom Van Eyck u64z[1] = 0;
261*b0563631STom Van Eyck
262*b0563631STom Van Eyck if (MBEDTLS_IS_BIG_ENDIAN) {
263*b0563631STom Van Eyck for (i = 15; i > 0; i--) {
264*b0563631STom Van Eyck mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
265*b0563631STom Van Eyck rem = u8z[15];
266*b0563631STom Van Eyck
267*b0563631STom Van Eyck u64z[1] >>= 8;
268*b0563631STom Van Eyck u8z[8] = u8z[7];
269*b0563631STom Van Eyck u64z[0] >>= 8;
270*b0563631STom Van Eyck
271*b0563631STom Van Eyck u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0);
272*b0563631STom Van Eyck }
273*b0563631STom Van Eyck } else {
274*b0563631STom Van Eyck for (i = 15; i > 0; i--) {
275*b0563631STom Van Eyck mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
276*b0563631STom Van Eyck rem = u8z[15];
277*b0563631STom Van Eyck
278*b0563631STom Van Eyck u64z[1] <<= 8;
279*b0563631STom Van Eyck u8z[8] = u8z[7];
280*b0563631STom Van Eyck u64z[0] <<= 8;
281*b0563631STom Van Eyck
282*b0563631STom Van Eyck u16z[0] ^= last8[rem];
283*b0563631STom Van Eyck }
284*b0563631STom Van Eyck }
285*b0563631STom Van Eyck
286*b0563631STom Van Eyck mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16);
287*b0563631STom Van Eyck }
288*b0563631STom Van Eyck #else
289817466cbSJens Wiklander /*
290817466cbSJens Wiklander * Shoup's method for multiplication use this table with
291817466cbSJens Wiklander * last4[x] = x times P^128
292817466cbSJens Wiklander * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
293817466cbSJens Wiklander */
294*b0563631STom Van Eyck static const uint16_t last4[16] =
295817466cbSJens Wiklander {
296817466cbSJens Wiklander 0x0000, 0x1c20, 0x3840, 0x2460,
297817466cbSJens Wiklander 0x7080, 0x6ca0, 0x48c0, 0x54e0,
298817466cbSJens Wiklander 0xe100, 0xfd20, 0xd940, 0xc560,
299817466cbSJens Wiklander 0x9180, 0x8da0, 0xa9c0, 0xb5e0
300817466cbSJens Wiklander };
301817466cbSJens Wiklander
gcm_mult_smalltable(uint8_t * output,const uint8_t * x,uint64_t H[16][2])302*b0563631STom Van Eyck static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2])
303*b0563631STom Van Eyck {
304*b0563631STom Van Eyck int i = 0;
305*b0563631STom Van Eyck unsigned char lo, hi, rem;
306*b0563631STom Van Eyck uint64_t u64z[2];
307*b0563631STom Van Eyck const uint64_t *pu64z = NULL;
308*b0563631STom Van Eyck uint8_t *u8z = (uint8_t *) u64z;
309*b0563631STom Van Eyck
310*b0563631STom Van Eyck lo = x[15] & 0xf;
311*b0563631STom Van Eyck hi = (x[15] >> 4) & 0xf;
312*b0563631STom Van Eyck
313*b0563631STom Van Eyck pu64z = H[lo];
314*b0563631STom Van Eyck
315*b0563631STom Van Eyck rem = (unsigned char) pu64z[1] & 0xf;
316*b0563631STom Van Eyck u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4);
317*b0563631STom Van Eyck u64z[0] = (pu64z[0] >> 4);
318*b0563631STom Van Eyck u64z[0] ^= (uint64_t) last4[rem] << 48;
319*b0563631STom Van Eyck mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
320*b0563631STom Van Eyck
321*b0563631STom Van Eyck for (i = 14; i >= 0; i--) {
322*b0563631STom Van Eyck lo = x[i] & 0xf;
323*b0563631STom Van Eyck hi = (x[i] >> 4) & 0xf;
324*b0563631STom Van Eyck
325*b0563631STom Van Eyck rem = (unsigned char) u64z[1] & 0xf;
326*b0563631STom Van Eyck u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
327*b0563631STom Van Eyck u64z[0] = (u64z[0] >> 4);
328*b0563631STom Van Eyck u64z[0] ^= (uint64_t) last4[rem] << 48;
329*b0563631STom Van Eyck mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16);
330*b0563631STom Van Eyck
331*b0563631STom Van Eyck rem = (unsigned char) u64z[1] & 0xf;
332*b0563631STom Van Eyck u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
333*b0563631STom Van Eyck u64z[0] = (u64z[0] >> 4);
334*b0563631STom Van Eyck u64z[0] ^= (uint64_t) last4[rem] << 48;
335*b0563631STom Van Eyck mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
336*b0563631STom Van Eyck }
337*b0563631STom Van Eyck
338*b0563631STom Van Eyck MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0);
339*b0563631STom Van Eyck MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8);
340*b0563631STom Van Eyck }
341*b0563631STom Van Eyck #endif
342*b0563631STom Van Eyck
343817466cbSJens Wiklander /*
344817466cbSJens Wiklander * Sets output to x times H using the precomputed tables.
345817466cbSJens Wiklander * x and output are seen as elements of GF(2^128) as in [MGV].
346817466cbSJens Wiklander */
gcm_mult(mbedtls_gcm_context * ctx,const unsigned char x[16],unsigned char output[16])347817466cbSJens Wiklander static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
348817466cbSJens Wiklander unsigned char output[16])
349817466cbSJens Wiklander {
350*b0563631STom Van Eyck switch (ctx->acceleration) {
35132b31808SJens Wiklander #if defined(MBEDTLS_AESNI_HAVE_CODE)
352*b0563631STom Van Eyck case MBEDTLS_GCM_ACC_AESNI:
353*b0563631STom Van Eyck mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
354*b0563631STom Van Eyck break;
35532b31808SJens Wiklander #endif
356817466cbSJens Wiklander
357*b0563631STom Van Eyck #if defined(MBEDTLS_AESCE_HAVE_CODE)
358*b0563631STom Van Eyck case MBEDTLS_GCM_ACC_AESCE:
359*b0563631STom Van Eyck mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
360*b0563631STom Van Eyck break;
361*b0563631STom Van Eyck #endif
362817466cbSJens Wiklander
363*b0563631STom Van Eyck #if defined(MBEDTLS_GCM_LARGE_TABLE)
364*b0563631STom Van Eyck case MBEDTLS_GCM_ACC_LARGETABLE:
365*b0563631STom Van Eyck gcm_mult_largetable(output, x, ctx->H);
366*b0563631STom Van Eyck break;
367*b0563631STom Van Eyck #else
368*b0563631STom Van Eyck case MBEDTLS_GCM_ACC_SMALLTABLE:
369*b0563631STom Van Eyck gcm_mult_smalltable(output, x, ctx->H);
370*b0563631STom Van Eyck break;
371*b0563631STom Van Eyck #endif
372817466cbSJens Wiklander }
373817466cbSJens Wiklander
374*b0563631STom Van Eyck return;
375817466cbSJens Wiklander }
376817466cbSJens Wiklander
mbedtls_gcm_starts(mbedtls_gcm_context * ctx,int mode,const unsigned char * iv,size_t iv_len)377817466cbSJens Wiklander int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
378817466cbSJens Wiklander int mode,
37932b31808SJens Wiklander const unsigned char *iv, size_t iv_len)
380817466cbSJens Wiklander {
38111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
382817466cbSJens Wiklander unsigned char work_buf[16];
383817466cbSJens Wiklander const unsigned char *p;
384*b0563631STom Van Eyck size_t use_len;
385039e02dfSJerome Forissier uint64_t iv_bits;
386*b0563631STom Van Eyck #if !defined(MBEDTLS_BLOCK_CIPHER_C)
387*b0563631STom Van Eyck size_t olen = 0;
388*b0563631STom Van Eyck #endif
389817466cbSJens Wiklander
39032b31808SJens Wiklander /* IV is limited to 2^64 bits, so 2^61 bytes */
391817466cbSJens Wiklander /* IV is not allowed to be zero length */
39232b31808SJens Wiklander if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
39332b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT;
394817466cbSJens Wiklander }
395817466cbSJens Wiklander
396817466cbSJens Wiklander memset(ctx->y, 0x00, sizeof(ctx->y));
397817466cbSJens Wiklander memset(ctx->buf, 0x00, sizeof(ctx->buf));
398817466cbSJens Wiklander
399817466cbSJens Wiklander ctx->mode = mode;
400817466cbSJens Wiklander ctx->len = 0;
401817466cbSJens Wiklander ctx->add_len = 0;
402817466cbSJens Wiklander
40332b31808SJens Wiklander if (iv_len == 12) {
404817466cbSJens Wiklander memcpy(ctx->y, iv, iv_len);
405817466cbSJens Wiklander ctx->y[15] = 1;
40632b31808SJens Wiklander } else {
407817466cbSJens Wiklander memset(work_buf, 0x00, 16);
408039e02dfSJerome Forissier iv_bits = (uint64_t) iv_len * 8;
409039e02dfSJerome Forissier MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
410817466cbSJens Wiklander
411817466cbSJens Wiklander p = iv;
41232b31808SJens Wiklander while (iv_len > 0) {
413817466cbSJens Wiklander use_len = (iv_len < 16) ? iv_len : 16;
414817466cbSJens Wiklander
415*b0563631STom Van Eyck #if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
416*b0563631STom Van Eyck #pragma GCC diagnostic push
417*b0563631STom Van Eyck #pragma GCC diagnostic warning "-Wstringop-overflow=0"
418*b0563631STom Van Eyck #endif
419*b0563631STom Van Eyck
42032b31808SJens Wiklander mbedtls_xor(ctx->y, ctx->y, p, use_len);
421817466cbSJens Wiklander
422*b0563631STom Van Eyck #if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
423*b0563631STom Van Eyck #pragma GCC diagnostic pop
424*b0563631STom Van Eyck #endif
425*b0563631STom Van Eyck
426817466cbSJens Wiklander gcm_mult(ctx, ctx->y, ctx->y);
427817466cbSJens Wiklander
428817466cbSJens Wiklander iv_len -= use_len;
429817466cbSJens Wiklander p += use_len;
430817466cbSJens Wiklander }
431817466cbSJens Wiklander
43232b31808SJens Wiklander mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
433817466cbSJens Wiklander
434817466cbSJens Wiklander gcm_mult(ctx, ctx->y, ctx->y);
435817466cbSJens Wiklander }
436817466cbSJens Wiklander
437*b0563631STom Van Eyck
438*b0563631STom Van Eyck #if defined(MBEDTLS_BLOCK_CIPHER_C)
439*b0563631STom Van Eyck ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr);
440*b0563631STom Van Eyck #else
441*b0563631STom Van Eyck ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen);
442*b0563631STom Van Eyck #endif
443*b0563631STom Van Eyck if (ret != 0) {
44432b31808SJens Wiklander return ret;
445817466cbSJens Wiklander }
446817466cbSJens Wiklander
44732b31808SJens Wiklander return 0;
44832b31808SJens Wiklander }
44932b31808SJens Wiklander
45032b31808SJens Wiklander /**
45132b31808SJens Wiklander * mbedtls_gcm_context::buf contains the partial state of the computation of
45232b31808SJens Wiklander * the authentication tag.
45332b31808SJens Wiklander * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
45432b31808SJens Wiklander * different stages of the computation:
45532b31808SJens Wiklander * * len == 0 && add_len == 0: initial state
45632b31808SJens Wiklander * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
45732b31808SJens Wiklander * a partial block of AD that has been
45832b31808SJens Wiklander * xored in but not yet multiplied in.
45932b31808SJens Wiklander * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
46032b31808SJens Wiklander * the data ends now.
46132b31808SJens Wiklander * * len % 16 != 0: the first `len % 16` bytes have
46232b31808SJens Wiklander * a partial block of ciphertext that has
46332b31808SJens Wiklander * been xored in but not yet multiplied in.
46432b31808SJens Wiklander * * len > 0 && len % 16 == 0: the authentication tag is correct if
46532b31808SJens Wiklander * the data ends now.
46632b31808SJens Wiklander */
mbedtls_gcm_update_ad(mbedtls_gcm_context * ctx,const unsigned char * add,size_t add_len)46732b31808SJens Wiklander int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
46832b31808SJens Wiklander const unsigned char *add, size_t add_len)
469817466cbSJens Wiklander {
47032b31808SJens Wiklander const unsigned char *p;
47132b31808SJens Wiklander size_t use_len, offset;
472*b0563631STom Van Eyck uint64_t new_add_len;
473817466cbSJens Wiklander
474*b0563631STom Van Eyck /* AD is limited to 2^64 bits, ie 2^61 bytes
475*b0563631STom Van Eyck * Also check for possible overflow */
476*b0563631STom Van Eyck #if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL
477*b0563631STom Van Eyck if (add_len > 0xFFFFFFFFFFFFFFFFULL) {
478*b0563631STom Van Eyck return MBEDTLS_ERR_GCM_BAD_INPUT;
479*b0563631STom Van Eyck }
480*b0563631STom Van Eyck #endif
481*b0563631STom Van Eyck new_add_len = ctx->add_len + (uint64_t) add_len;
482*b0563631STom Van Eyck if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
48332b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT;
48432b31808SJens Wiklander }
485817466cbSJens Wiklander
48632b31808SJens Wiklander offset = ctx->add_len % 16;
48732b31808SJens Wiklander p = add;
48832b31808SJens Wiklander
48932b31808SJens Wiklander if (offset != 0) {
49032b31808SJens Wiklander use_len = 16 - offset;
49132b31808SJens Wiklander if (use_len > add_len) {
49232b31808SJens Wiklander use_len = add_len;
49332b31808SJens Wiklander }
49432b31808SJens Wiklander
49532b31808SJens Wiklander mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
49632b31808SJens Wiklander
49732b31808SJens Wiklander if (offset + use_len == 16) {
498817466cbSJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf);
49932b31808SJens Wiklander }
500817466cbSJens Wiklander
50132b31808SJens Wiklander ctx->add_len += use_len;
502817466cbSJens Wiklander add_len -= use_len;
503817466cbSJens Wiklander p += use_len;
504817466cbSJens Wiklander }
505817466cbSJens Wiklander
50632b31808SJens Wiklander ctx->add_len += add_len;
507817466cbSJens Wiklander
50832b31808SJens Wiklander while (add_len >= 16) {
50932b31808SJens Wiklander mbedtls_xor(ctx->buf, ctx->buf, p, 16);
510817466cbSJens Wiklander
511817466cbSJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf);
512817466cbSJens Wiklander
51332b31808SJens Wiklander add_len -= 16;
51432b31808SJens Wiklander p += 16;
51532b31808SJens Wiklander }
51632b31808SJens Wiklander
51732b31808SJens Wiklander if (add_len > 0) {
51832b31808SJens Wiklander mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
51932b31808SJens Wiklander }
52032b31808SJens Wiklander
52132b31808SJens Wiklander return 0;
52232b31808SJens Wiklander }
52332b31808SJens Wiklander
52432b31808SJens Wiklander /* Increment the counter. */
gcm_incr(unsigned char y[16])52532b31808SJens Wiklander static void gcm_incr(unsigned char y[16])
52632b31808SJens Wiklander {
527*b0563631STom Van Eyck uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12);
528*b0563631STom Van Eyck x++;
529*b0563631STom Van Eyck MBEDTLS_PUT_UINT32_BE(x, y, 12);
53032b31808SJens Wiklander }
53132b31808SJens Wiklander
53232b31808SJens Wiklander /* Calculate and apply the encryption mask. Process use_len bytes of data,
53332b31808SJens Wiklander * starting at position offset in the mask block. */
gcm_mask(mbedtls_gcm_context * ctx,unsigned char ectr[16],size_t offset,size_t use_len,const unsigned char * input,unsigned char * output)53432b31808SJens Wiklander static int gcm_mask(mbedtls_gcm_context *ctx,
53532b31808SJens Wiklander unsigned char ectr[16],
53632b31808SJens Wiklander size_t offset, size_t use_len,
53732b31808SJens Wiklander const unsigned char *input,
53832b31808SJens Wiklander unsigned char *output)
53932b31808SJens Wiklander {
54032b31808SJens Wiklander int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
54132b31808SJens Wiklander
542*b0563631STom Van Eyck #if defined(MBEDTLS_BLOCK_CIPHER_C)
543*b0563631STom Van Eyck ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr);
544*b0563631STom Van Eyck #else
545*b0563631STom Van Eyck size_t olen = 0;
546*b0563631STom Van Eyck ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen);
547*b0563631STom Van Eyck #endif
548*b0563631STom Van Eyck if (ret != 0) {
54932b31808SJens Wiklander mbedtls_platform_zeroize(ectr, 16);
55032b31808SJens Wiklander return ret;
55132b31808SJens Wiklander }
55232b31808SJens Wiklander
55332b31808SJens Wiklander if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
55432b31808SJens Wiklander mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
55532b31808SJens Wiklander }
55632b31808SJens Wiklander mbedtls_xor(output, ectr + offset, input, use_len);
55732b31808SJens Wiklander if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
55832b31808SJens Wiklander mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
55932b31808SJens Wiklander }
56032b31808SJens Wiklander
56132b31808SJens Wiklander return 0;
56232b31808SJens Wiklander }
56332b31808SJens Wiklander
mbedtls_gcm_update(mbedtls_gcm_context * ctx,const unsigned char * input,size_t input_length,unsigned char * output,size_t output_size,size_t * output_length)56432b31808SJens Wiklander int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
56532b31808SJens Wiklander const unsigned char *input, size_t input_length,
56632b31808SJens Wiklander unsigned char *output, size_t output_size,
56732b31808SJens Wiklander size_t *output_length)
56832b31808SJens Wiklander {
56932b31808SJens Wiklander int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
57032b31808SJens Wiklander const unsigned char *p = input;
57132b31808SJens Wiklander unsigned char *out_p = output;
57232b31808SJens Wiklander size_t offset;
57332b31808SJens Wiklander unsigned char ectr[16] = { 0 };
57432b31808SJens Wiklander
57532b31808SJens Wiklander if (output_size < input_length) {
57632b31808SJens Wiklander return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
57732b31808SJens Wiklander }
57832b31808SJens Wiklander *output_length = input_length;
57932b31808SJens Wiklander
58032b31808SJens Wiklander /* Exit early if input_length==0 so that we don't do any pointer arithmetic
58132b31808SJens Wiklander * on a potentially null pointer.
58232b31808SJens Wiklander * Returning early also means that the last partial block of AD remains
58332b31808SJens Wiklander * untouched for mbedtls_gcm_finish */
58432b31808SJens Wiklander if (input_length == 0) {
58532b31808SJens Wiklander return 0;
58632b31808SJens Wiklander }
58732b31808SJens Wiklander
58832b31808SJens Wiklander if (output > input && (size_t) (output - input) < input_length) {
58932b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT;
59032b31808SJens Wiklander }
59132b31808SJens Wiklander
59232b31808SJens Wiklander /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
59332b31808SJens Wiklander * Also check for possible overflow */
59432b31808SJens Wiklander if (ctx->len + input_length < ctx->len ||
59532b31808SJens Wiklander (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
59632b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT;
59732b31808SJens Wiklander }
59832b31808SJens Wiklander
59932b31808SJens Wiklander if (ctx->len == 0 && ctx->add_len % 16 != 0) {
60032b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf);
60132b31808SJens Wiklander }
60232b31808SJens Wiklander
60332b31808SJens Wiklander offset = ctx->len % 16;
60432b31808SJens Wiklander if (offset != 0) {
60532b31808SJens Wiklander size_t use_len = 16 - offset;
60632b31808SJens Wiklander if (use_len > input_length) {
60732b31808SJens Wiklander use_len = input_length;
60832b31808SJens Wiklander }
60932b31808SJens Wiklander
61032b31808SJens Wiklander if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
61132b31808SJens Wiklander return ret;
61232b31808SJens Wiklander }
61332b31808SJens Wiklander
61432b31808SJens Wiklander if (offset + use_len == 16) {
61532b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf);
61632b31808SJens Wiklander }
61732b31808SJens Wiklander
61832b31808SJens Wiklander ctx->len += use_len;
61932b31808SJens Wiklander input_length -= use_len;
620817466cbSJens Wiklander p += use_len;
621817466cbSJens Wiklander out_p += use_len;
622817466cbSJens Wiklander }
623817466cbSJens Wiklander
62432b31808SJens Wiklander ctx->len += input_length;
62532b31808SJens Wiklander
62632b31808SJens Wiklander while (input_length >= 16) {
62732b31808SJens Wiklander gcm_incr(ctx->y);
62832b31808SJens Wiklander if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
62932b31808SJens Wiklander return ret;
63032b31808SJens Wiklander }
63132b31808SJens Wiklander
63232b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf);
63332b31808SJens Wiklander
63432b31808SJens Wiklander input_length -= 16;
63532b31808SJens Wiklander p += 16;
63632b31808SJens Wiklander out_p += 16;
63732b31808SJens Wiklander }
63832b31808SJens Wiklander
63932b31808SJens Wiklander if (input_length > 0) {
64032b31808SJens Wiklander gcm_incr(ctx->y);
64132b31808SJens Wiklander if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
64232b31808SJens Wiklander return ret;
64332b31808SJens Wiklander }
64432b31808SJens Wiklander }
64532b31808SJens Wiklander
64632b31808SJens Wiklander mbedtls_platform_zeroize(ectr, sizeof(ectr));
64732b31808SJens Wiklander return 0;
648817466cbSJens Wiklander }
649817466cbSJens Wiklander
mbedtls_gcm_finish(mbedtls_gcm_context * ctx,unsigned char * output,size_t output_size,size_t * output_length,unsigned char * tag,size_t tag_len)650817466cbSJens Wiklander int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
65132b31808SJens Wiklander unsigned char *output, size_t output_size,
65232b31808SJens Wiklander size_t *output_length,
65332b31808SJens Wiklander unsigned char *tag, size_t tag_len)
654817466cbSJens Wiklander {
655817466cbSJens Wiklander unsigned char work_buf[16];
6563d3b0591SJens Wiklander uint64_t orig_len;
6573d3b0591SJens Wiklander uint64_t orig_add_len;
6583d3b0591SJens Wiklander
65932b31808SJens Wiklander /* We never pass any output in finish(). The output parameter exists only
66032b31808SJens Wiklander * for the sake of alternative implementations. */
66132b31808SJens Wiklander (void) output;
66232b31808SJens Wiklander (void) output_size;
66332b31808SJens Wiklander *output_length = 0;
6643d3b0591SJens Wiklander
665*b0563631STom Van Eyck /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
666*b0563631STom Van Eyck * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of
667*b0563631STom Van Eyck * the two multiplications would overflow. */
6683d3b0591SJens Wiklander orig_len = ctx->len * 8;
6693d3b0591SJens Wiklander orig_add_len = ctx->add_len * 8;
670817466cbSJens Wiklander
67132b31808SJens Wiklander if (ctx->len == 0 && ctx->add_len % 16 != 0) {
67232b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf);
67332b31808SJens Wiklander }
67432b31808SJens Wiklander
67532b31808SJens Wiklander if (tag_len > 16 || tag_len < 4) {
67632b31808SJens Wiklander return MBEDTLS_ERR_GCM_BAD_INPUT;
67732b31808SJens Wiklander }
67832b31808SJens Wiklander
67932b31808SJens Wiklander if (ctx->len % 16 != 0) {
68032b31808SJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf);
68132b31808SJens Wiklander }
682817466cbSJens Wiklander
683817466cbSJens Wiklander memcpy(tag, ctx->base_ectr, tag_len);
684817466cbSJens Wiklander
68532b31808SJens Wiklander if (orig_len || orig_add_len) {
686817466cbSJens Wiklander memset(work_buf, 0x00, 16);
687817466cbSJens Wiklander
688039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
689039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
690039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
691039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
692817466cbSJens Wiklander
69332b31808SJens Wiklander mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
694817466cbSJens Wiklander
695817466cbSJens Wiklander gcm_mult(ctx, ctx->buf, ctx->buf);
696817466cbSJens Wiklander
69732b31808SJens Wiklander mbedtls_xor(tag, tag, ctx->buf, tag_len);
698817466cbSJens Wiklander }
699817466cbSJens Wiklander
70032b31808SJens Wiklander return 0;
701817466cbSJens Wiklander }
702817466cbSJens Wiklander
mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context * ctx,int mode,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,size_t tag_len,unsigned char * tag)703817466cbSJens Wiklander int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
704817466cbSJens Wiklander int mode,
705817466cbSJens Wiklander size_t length,
706817466cbSJens Wiklander const unsigned char *iv,
707817466cbSJens Wiklander size_t iv_len,
708817466cbSJens Wiklander const unsigned char *add,
709817466cbSJens Wiklander size_t add_len,
710817466cbSJens Wiklander const unsigned char *input,
711817466cbSJens Wiklander unsigned char *output,
712817466cbSJens Wiklander size_t tag_len,
713817466cbSJens Wiklander unsigned char *tag)
714817466cbSJens Wiklander {
71511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
71632b31808SJens Wiklander size_t olen;
717817466cbSJens Wiklander
71832b31808SJens Wiklander if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
71932b31808SJens Wiklander return ret;
72032b31808SJens Wiklander }
7213d3b0591SJens Wiklander
72232b31808SJens Wiklander if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
72332b31808SJens Wiklander return ret;
72432b31808SJens Wiklander }
725817466cbSJens Wiklander
72632b31808SJens Wiklander if ((ret = mbedtls_gcm_update(ctx, input, length,
72732b31808SJens Wiklander output, length, &olen)) != 0) {
72832b31808SJens Wiklander return ret;
72932b31808SJens Wiklander }
730817466cbSJens Wiklander
73132b31808SJens Wiklander if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
73232b31808SJens Wiklander return ret;
73332b31808SJens Wiklander }
734817466cbSJens Wiklander
73532b31808SJens Wiklander return 0;
736817466cbSJens Wiklander }
737817466cbSJens Wiklander
mbedtls_gcm_auth_decrypt(mbedtls_gcm_context * ctx,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * tag,size_t tag_len,const unsigned char * input,unsigned char * output)738817466cbSJens Wiklander int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
739817466cbSJens Wiklander size_t length,
740817466cbSJens Wiklander const unsigned char *iv,
741817466cbSJens Wiklander size_t iv_len,
742817466cbSJens Wiklander const unsigned char *add,
743817466cbSJens Wiklander size_t add_len,
744817466cbSJens Wiklander const unsigned char *tag,
745817466cbSJens Wiklander size_t tag_len,
746817466cbSJens Wiklander const unsigned char *input,
747817466cbSJens Wiklander unsigned char *output)
748817466cbSJens Wiklander {
74911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
750817466cbSJens Wiklander unsigned char check_tag[16];
751817466cbSJens Wiklander int diff;
752817466cbSJens Wiklander
753817466cbSJens Wiklander if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
754817466cbSJens Wiklander iv, iv_len, add, add_len,
75532b31808SJens Wiklander input, output, tag_len, check_tag)) != 0) {
75632b31808SJens Wiklander return ret;
757817466cbSJens Wiklander }
758817466cbSJens Wiklander
759817466cbSJens Wiklander /* Check tag in "constant-time" */
760*b0563631STom Van Eyck diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
761817466cbSJens Wiklander
76232b31808SJens Wiklander if (diff != 0) {
76332b31808SJens Wiklander mbedtls_platform_zeroize(output, length);
76432b31808SJens Wiklander return MBEDTLS_ERR_GCM_AUTH_FAILED;
76532b31808SJens Wiklander }
76632b31808SJens Wiklander
76732b31808SJens Wiklander return 0;
768817466cbSJens Wiklander }
769817466cbSJens Wiklander
mbedtls_gcm_free(mbedtls_gcm_context * ctx)770817466cbSJens Wiklander void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
771817466cbSJens Wiklander {
77232b31808SJens Wiklander if (ctx == NULL) {
7733d3b0591SJens Wiklander return;
77432b31808SJens Wiklander }
775*b0563631STom Van Eyck #if defined(MBEDTLS_BLOCK_CIPHER_C)
776*b0563631STom Van Eyck mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
777*b0563631STom Van Eyck #else
778817466cbSJens Wiklander mbedtls_cipher_free(&ctx->cipher_ctx);
779*b0563631STom Van Eyck #endif
7803d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
781817466cbSJens Wiklander }
782817466cbSJens Wiklander
7833d3b0591SJens Wiklander #endif /* !MBEDTLS_GCM_ALT */
7843d3b0591SJens Wiklander
785*b0563631STom Van Eyck #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
786817466cbSJens Wiklander /*
787817466cbSJens Wiklander * AES-GCM test vectors from:
788817466cbSJens Wiklander *
789817466cbSJens Wiklander * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
790817466cbSJens Wiklander */
791817466cbSJens Wiklander #define MAX_TESTS 6
792817466cbSJens Wiklander
79311fa71b9SJerome Forissier static const int key_index_test_data[MAX_TESTS] =
794817466cbSJens Wiklander { 0, 0, 1, 1, 1, 1 };
795817466cbSJens Wiklander
796*b0563631STom Van Eyck static const unsigned char key_test_data[][32] =
797817466cbSJens Wiklander {
798817466cbSJens Wiklander { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
799817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
800817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
801817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
802817466cbSJens Wiklander { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
803817466cbSJens Wiklander 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
804817466cbSJens Wiklander 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
805817466cbSJens Wiklander 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
806817466cbSJens Wiklander };
807817466cbSJens Wiklander
80811fa71b9SJerome Forissier static const size_t iv_len_test_data[MAX_TESTS] =
809817466cbSJens Wiklander { 12, 12, 12, 12, 8, 60 };
810817466cbSJens Wiklander
81111fa71b9SJerome Forissier static const int iv_index_test_data[MAX_TESTS] =
812817466cbSJens Wiklander { 0, 0, 1, 1, 1, 2 };
813817466cbSJens Wiklander
814*b0563631STom Van Eyck static const unsigned char iv_test_data[][64] =
815817466cbSJens Wiklander {
816817466cbSJens Wiklander { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00 },
818817466cbSJens Wiklander { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
819817466cbSJens Wiklander 0xde, 0xca, 0xf8, 0x88 },
820817466cbSJens Wiklander { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
821817466cbSJens Wiklander 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
822817466cbSJens Wiklander 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
823817466cbSJens Wiklander 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
824817466cbSJens Wiklander 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
825817466cbSJens Wiklander 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
826817466cbSJens Wiklander 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
827817466cbSJens Wiklander 0xa6, 0x37, 0xb3, 0x9b },
828817466cbSJens Wiklander };
829817466cbSJens Wiklander
83011fa71b9SJerome Forissier static const size_t add_len_test_data[MAX_TESTS] =
831817466cbSJens Wiklander { 0, 0, 0, 20, 20, 20 };
832817466cbSJens Wiklander
83311fa71b9SJerome Forissier static const int add_index_test_data[MAX_TESTS] =
834817466cbSJens Wiklander { 0, 0, 0, 1, 1, 1 };
835817466cbSJens Wiklander
836*b0563631STom Van Eyck static const unsigned char additional_test_data[][64] =
837817466cbSJens Wiklander {
838817466cbSJens Wiklander { 0x00 },
839817466cbSJens Wiklander { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
840817466cbSJens Wiklander 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
841817466cbSJens Wiklander 0xab, 0xad, 0xda, 0xd2 },
842817466cbSJens Wiklander };
843817466cbSJens Wiklander
84411fa71b9SJerome Forissier static const size_t pt_len_test_data[MAX_TESTS] =
845817466cbSJens Wiklander { 0, 16, 64, 60, 60, 60 };
846817466cbSJens Wiklander
84711fa71b9SJerome Forissier static const int pt_index_test_data[MAX_TESTS] =
848817466cbSJens Wiklander { 0, 0, 1, 1, 1, 1 };
849817466cbSJens Wiklander
850*b0563631STom Van Eyck static const unsigned char pt_test_data[][64] =
851817466cbSJens Wiklander {
852817466cbSJens Wiklander { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
854817466cbSJens Wiklander { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
855817466cbSJens Wiklander 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
856817466cbSJens Wiklander 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
857817466cbSJens Wiklander 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
858817466cbSJens Wiklander 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
859817466cbSJens Wiklander 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
860817466cbSJens Wiklander 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
861817466cbSJens Wiklander 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
862817466cbSJens Wiklander };
863817466cbSJens Wiklander
864*b0563631STom Van Eyck static const unsigned char ct_test_data[][64] =
865817466cbSJens Wiklander {
866817466cbSJens Wiklander { 0x00 },
867817466cbSJens Wiklander { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
868817466cbSJens Wiklander 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
869817466cbSJens Wiklander { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
870817466cbSJens Wiklander 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
871817466cbSJens Wiklander 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
872817466cbSJens Wiklander 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
873817466cbSJens Wiklander 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
874817466cbSJens Wiklander 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
875817466cbSJens Wiklander 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
876817466cbSJens Wiklander 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
877817466cbSJens Wiklander { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
878817466cbSJens Wiklander 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
879817466cbSJens Wiklander 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
880817466cbSJens Wiklander 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
881817466cbSJens Wiklander 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
882817466cbSJens Wiklander 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
883817466cbSJens Wiklander 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
884817466cbSJens Wiklander 0x3d, 0x58, 0xe0, 0x91 },
885817466cbSJens Wiklander { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
886817466cbSJens Wiklander 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
887817466cbSJens Wiklander 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
888817466cbSJens Wiklander 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
889817466cbSJens Wiklander 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
890817466cbSJens Wiklander 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
891817466cbSJens Wiklander 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
892817466cbSJens Wiklander 0xc2, 0x3f, 0x45, 0x98 },
893817466cbSJens Wiklander { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
894817466cbSJens Wiklander 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
895817466cbSJens Wiklander 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
896817466cbSJens Wiklander 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
897817466cbSJens Wiklander 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
898817466cbSJens Wiklander 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
899817466cbSJens Wiklander 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
900817466cbSJens Wiklander 0x4c, 0x34, 0xae, 0xe5 },
901*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
902817466cbSJens Wiklander { 0x00 },
903817466cbSJens Wiklander { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
904817466cbSJens Wiklander 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
905817466cbSJens Wiklander { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
906817466cbSJens Wiklander 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
907817466cbSJens Wiklander 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
908817466cbSJens Wiklander 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
909817466cbSJens Wiklander 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
910817466cbSJens Wiklander 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
911817466cbSJens Wiklander 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
912817466cbSJens Wiklander 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
913817466cbSJens Wiklander { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
914817466cbSJens Wiklander 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
915817466cbSJens Wiklander 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
916817466cbSJens Wiklander 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
917817466cbSJens Wiklander 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
918817466cbSJens Wiklander 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
919817466cbSJens Wiklander 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
920817466cbSJens Wiklander 0xcc, 0xda, 0x27, 0x10 },
921817466cbSJens Wiklander { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
922817466cbSJens Wiklander 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
923817466cbSJens Wiklander 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
924817466cbSJens Wiklander 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
925817466cbSJens Wiklander 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
926817466cbSJens Wiklander 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
927817466cbSJens Wiklander 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
928817466cbSJens Wiklander 0xa0, 0xf0, 0x62, 0xf7 },
929817466cbSJens Wiklander { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
930817466cbSJens Wiklander 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
931817466cbSJens Wiklander 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
932817466cbSJens Wiklander 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
933817466cbSJens Wiklander 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
934817466cbSJens Wiklander 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
935817466cbSJens Wiklander 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
936817466cbSJens Wiklander 0xe9, 0xb7, 0x37, 0x3b },
937817466cbSJens Wiklander { 0x00 },
938817466cbSJens Wiklander { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
939817466cbSJens Wiklander 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
940817466cbSJens Wiklander { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
941817466cbSJens Wiklander 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
942817466cbSJens Wiklander 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
943817466cbSJens Wiklander 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
944817466cbSJens Wiklander 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
945817466cbSJens Wiklander 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
946817466cbSJens Wiklander 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
947817466cbSJens Wiklander 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
948817466cbSJens Wiklander { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
949817466cbSJens Wiklander 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
950817466cbSJens Wiklander 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
951817466cbSJens Wiklander 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
952817466cbSJens Wiklander 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
953817466cbSJens Wiklander 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
954817466cbSJens Wiklander 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
955817466cbSJens Wiklander 0xbc, 0xc9, 0xf6, 0x62 },
956817466cbSJens Wiklander { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
957817466cbSJens Wiklander 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
958817466cbSJens Wiklander 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
959817466cbSJens Wiklander 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
960817466cbSJens Wiklander 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
961817466cbSJens Wiklander 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
962817466cbSJens Wiklander 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
963817466cbSJens Wiklander 0xf4, 0x7c, 0x9b, 0x1f },
964817466cbSJens Wiklander { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
965817466cbSJens Wiklander 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
966817466cbSJens Wiklander 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
967817466cbSJens Wiklander 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
968817466cbSJens Wiklander 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
969817466cbSJens Wiklander 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
970817466cbSJens Wiklander 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
971817466cbSJens Wiklander 0x44, 0xae, 0x7e, 0x3f },
972*b0563631STom Van Eyck #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
973817466cbSJens Wiklander };
974817466cbSJens Wiklander
975*b0563631STom Van Eyck static const unsigned char tag_test_data[][16] =
976817466cbSJens Wiklander {
977817466cbSJens Wiklander { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
978817466cbSJens Wiklander 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
979817466cbSJens Wiklander { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
980817466cbSJens Wiklander 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
981817466cbSJens Wiklander { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
982817466cbSJens Wiklander 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
983817466cbSJens Wiklander { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
984817466cbSJens Wiklander 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
985817466cbSJens Wiklander { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
986817466cbSJens Wiklander 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
987817466cbSJens Wiklander { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
988817466cbSJens Wiklander 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
989*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
990817466cbSJens Wiklander { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
991817466cbSJens Wiklander 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
992817466cbSJens Wiklander { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
993817466cbSJens Wiklander 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
994817466cbSJens Wiklander { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
995817466cbSJens Wiklander 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
996817466cbSJens Wiklander { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
997817466cbSJens Wiklander 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
998817466cbSJens Wiklander { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
999817466cbSJens Wiklander 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
1000817466cbSJens Wiklander { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
1001817466cbSJens Wiklander 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
1002817466cbSJens Wiklander { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
1003817466cbSJens Wiklander 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
1004817466cbSJens Wiklander { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
1005817466cbSJens Wiklander 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
1006817466cbSJens Wiklander { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
1007817466cbSJens Wiklander 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
1008817466cbSJens Wiklander { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
1009817466cbSJens Wiklander 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
1010817466cbSJens Wiklander { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
1011817466cbSJens Wiklander 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
1012817466cbSJens Wiklander { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
1013817466cbSJens Wiklander 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
1014*b0563631STom Van Eyck #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
1015817466cbSJens Wiklander };
1016817466cbSJens Wiklander
mbedtls_gcm_self_test(int verbose)1017817466cbSJens Wiklander int mbedtls_gcm_self_test(int verbose)
1018817466cbSJens Wiklander {
1019817466cbSJens Wiklander mbedtls_gcm_context ctx;
1020817466cbSJens Wiklander unsigned char buf[64];
1021817466cbSJens Wiklander unsigned char tag_buf[16];
1022817466cbSJens Wiklander int i, j, ret;
1023817466cbSJens Wiklander mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
102432b31808SJens Wiklander size_t olen;
1025817466cbSJens Wiklander
102632b31808SJens Wiklander if (verbose != 0) {
102732b31808SJens Wiklander #if defined(MBEDTLS_GCM_ALT)
102832b31808SJens Wiklander mbedtls_printf(" GCM note: alternative implementation.\n");
102932b31808SJens Wiklander #else /* MBEDTLS_GCM_ALT */
103032b31808SJens Wiklander #if defined(MBEDTLS_AESNI_HAVE_CODE)
103132b31808SJens Wiklander if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
103232b31808SJens Wiklander mbedtls_printf(" GCM note: using AESNI.\n");
103332b31808SJens Wiklander } else
103432b31808SJens Wiklander #endif
1035*b0563631STom Van Eyck
1036*b0563631STom Van Eyck #if defined(MBEDTLS_AESCE_HAVE_CODE)
1037*b0563631STom Van Eyck if (MBEDTLS_AESCE_HAS_SUPPORT()) {
1038*b0563631STom Van Eyck mbedtls_printf(" GCM note: using AESCE.\n");
1039*b0563631STom Van Eyck } else
1040*b0563631STom Van Eyck #endif
1041*b0563631STom Van Eyck
104232b31808SJens Wiklander mbedtls_printf(" GCM note: built-in implementation.\n");
104332b31808SJens Wiklander #endif /* MBEDTLS_GCM_ALT */
104432b31808SJens Wiklander }
104532b31808SJens Wiklander
1046*b0563631STom Van Eyck static const int loop_limit =
1047*b0563631STom Van Eyck (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
1048*b0563631STom Van Eyck
1049*b0563631STom Van Eyck for (j = 0; j < loop_limit; j++) {
1050817466cbSJens Wiklander int key_len = 128 + 64 * j;
1051817466cbSJens Wiklander
105232b31808SJens Wiklander for (i = 0; i < MAX_TESTS; i++) {
105332b31808SJens Wiklander if (verbose != 0) {
1054817466cbSJens Wiklander mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1055817466cbSJens Wiklander key_len, i, "enc");
105632b31808SJens Wiklander }
1057817466cbSJens Wiklander
1058*b0563631STom Van Eyck mbedtls_gcm_init(&ctx);
1059*b0563631STom Van Eyck
106011fa71b9SJerome Forissier ret = mbedtls_gcm_setkey(&ctx, cipher,
106111fa71b9SJerome Forissier key_test_data[key_index_test_data[i]],
10623d3b0591SJens Wiklander key_len);
10633d3b0591SJens Wiklander /*
10643d3b0591SJens Wiklander * AES-192 is an optional feature that may be unavailable when
10653d3b0591SJens Wiklander * there is an alternative underlying implementation i.e. when
10663d3b0591SJens Wiklander * MBEDTLS_AES_ALT is defined.
10673d3b0591SJens Wiklander */
106832b31808SJens Wiklander if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
10693d3b0591SJens Wiklander mbedtls_printf("skipped\n");
10703d3b0591SJens Wiklander break;
107132b31808SJens Wiklander } else if (ret != 0) {
10723d3b0591SJens Wiklander goto exit;
10733d3b0591SJens Wiklander }
1074817466cbSJens Wiklander
1075817466cbSJens Wiklander ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
107611fa71b9SJerome Forissier pt_len_test_data[i],
107711fa71b9SJerome Forissier iv_test_data[iv_index_test_data[i]],
107811fa71b9SJerome Forissier iv_len_test_data[i],
107911fa71b9SJerome Forissier additional_test_data[add_index_test_data[i]],
108011fa71b9SJerome Forissier add_len_test_data[i],
108111fa71b9SJerome Forissier pt_test_data[pt_index_test_data[i]],
108211fa71b9SJerome Forissier buf, 16, tag_buf);
10837901324dSJerome Forissier #if defined(MBEDTLS_GCM_ALT)
10847901324dSJerome Forissier /* Allow alternative implementations to only support 12-byte nonces. */
10857901324dSJerome Forissier if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
108632b31808SJens Wiklander iv_len_test_data[i] != 12) {
10877901324dSJerome Forissier mbedtls_printf("skipped\n");
10887901324dSJerome Forissier break;
10897901324dSJerome Forissier }
10907901324dSJerome Forissier #endif /* defined(MBEDTLS_GCM_ALT) */
109132b31808SJens Wiklander if (ret != 0) {
10923d3b0591SJens Wiklander goto exit;
109332b31808SJens Wiklander }
1094817466cbSJens Wiklander
109511fa71b9SJerome Forissier if (memcmp(buf, ct_test_data[j * 6 + i],
109611fa71b9SJerome Forissier pt_len_test_data[i]) != 0 ||
109732b31808SJens Wiklander memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
10983d3b0591SJens Wiklander ret = 1;
10993d3b0591SJens Wiklander goto exit;
1100817466cbSJens Wiklander }
1101817466cbSJens Wiklander
1102817466cbSJens Wiklander mbedtls_gcm_free(&ctx);
1103817466cbSJens Wiklander
110432b31808SJens Wiklander if (verbose != 0) {
1105817466cbSJens Wiklander mbedtls_printf("passed\n");
110632b31808SJens Wiklander }
1107817466cbSJens Wiklander
11083d3b0591SJens Wiklander mbedtls_gcm_init(&ctx);
11093d3b0591SJens Wiklander
111032b31808SJens Wiklander if (verbose != 0) {
1111817466cbSJens Wiklander mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
1112817466cbSJens Wiklander key_len, i, "dec");
111332b31808SJens Wiklander }
1114817466cbSJens Wiklander
111511fa71b9SJerome Forissier ret = mbedtls_gcm_setkey(&ctx, cipher,
111611fa71b9SJerome Forissier key_test_data[key_index_test_data[i]],
11173d3b0591SJens Wiklander key_len);
111832b31808SJens Wiklander if (ret != 0) {
11193d3b0591SJens Wiklander goto exit;
112032b31808SJens Wiklander }
1121817466cbSJens Wiklander
1122817466cbSJens Wiklander ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
112311fa71b9SJerome Forissier pt_len_test_data[i],
112411fa71b9SJerome Forissier iv_test_data[iv_index_test_data[i]],
112511fa71b9SJerome Forissier iv_len_test_data[i],
112611fa71b9SJerome Forissier additional_test_data[add_index_test_data[i]],
112711fa71b9SJerome Forissier add_len_test_data[i],
112811fa71b9SJerome Forissier ct_test_data[j * 6 + i], buf, 16, tag_buf);
1129817466cbSJens Wiklander
113032b31808SJens Wiklander if (ret != 0) {
11313d3b0591SJens Wiklander goto exit;
113232b31808SJens Wiklander }
11333d3b0591SJens Wiklander
113411fa71b9SJerome Forissier if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
113511fa71b9SJerome Forissier pt_len_test_data[i]) != 0 ||
113632b31808SJens Wiklander memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
11373d3b0591SJens Wiklander ret = 1;
11383d3b0591SJens Wiklander goto exit;
1139817466cbSJens Wiklander }
1140817466cbSJens Wiklander
1141817466cbSJens Wiklander mbedtls_gcm_free(&ctx);
1142817466cbSJens Wiklander
114332b31808SJens Wiklander if (verbose != 0) {
1144817466cbSJens Wiklander mbedtls_printf("passed\n");
114532b31808SJens Wiklander }
1146817466cbSJens Wiklander
11473d3b0591SJens Wiklander mbedtls_gcm_init(&ctx);
11483d3b0591SJens Wiklander
114932b31808SJens Wiklander if (verbose != 0) {
1150817466cbSJens Wiklander mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1151817466cbSJens Wiklander key_len, i, "enc");
115232b31808SJens Wiklander }
1153817466cbSJens Wiklander
115411fa71b9SJerome Forissier ret = mbedtls_gcm_setkey(&ctx, cipher,
115511fa71b9SJerome Forissier key_test_data[key_index_test_data[i]],
11563d3b0591SJens Wiklander key_len);
115732b31808SJens Wiklander if (ret != 0) {
11583d3b0591SJens Wiklander goto exit;
115932b31808SJens Wiklander }
1160817466cbSJens Wiklander
1161817466cbSJens Wiklander ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
116211fa71b9SJerome Forissier iv_test_data[iv_index_test_data[i]],
116332b31808SJens Wiklander iv_len_test_data[i]);
116432b31808SJens Wiklander if (ret != 0) {
116532b31808SJens Wiklander goto exit;
116632b31808SJens Wiklander }
116732b31808SJens Wiklander
116832b31808SJens Wiklander ret = mbedtls_gcm_update_ad(&ctx,
116911fa71b9SJerome Forissier additional_test_data[add_index_test_data[i]],
117011fa71b9SJerome Forissier add_len_test_data[i]);
117132b31808SJens Wiklander if (ret != 0) {
11723d3b0591SJens Wiklander goto exit;
117332b31808SJens Wiklander }
1174817466cbSJens Wiklander
117532b31808SJens Wiklander if (pt_len_test_data[i] > 32) {
117611fa71b9SJerome Forissier size_t rest_len = pt_len_test_data[i] - 32;
117732b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx,
117811fa71b9SJerome Forissier pt_test_data[pt_index_test_data[i]],
117932b31808SJens Wiklander 32,
118032b31808SJens Wiklander buf, sizeof(buf), &olen);
118132b31808SJens Wiklander if (ret != 0) {
11823d3b0591SJens Wiklander goto exit;
118332b31808SJens Wiklander }
118432b31808SJens Wiklander if (olen != 32) {
118532b31808SJens Wiklander goto exit;
118632b31808SJens Wiklander }
1187817466cbSJens Wiklander
118832b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx,
118911fa71b9SJerome Forissier pt_test_data[pt_index_test_data[i]] + 32,
119032b31808SJens Wiklander rest_len,
119132b31808SJens Wiklander buf + 32, sizeof(buf) - 32, &olen);
119232b31808SJens Wiklander if (ret != 0) {
11933d3b0591SJens Wiklander goto exit;
1194817466cbSJens Wiklander }
119532b31808SJens Wiklander if (olen != rest_len) {
11963d3b0591SJens Wiklander goto exit;
1197817466cbSJens Wiklander }
119832b31808SJens Wiklander } else {
119932b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx,
120032b31808SJens Wiklander pt_test_data[pt_index_test_data[i]],
120132b31808SJens Wiklander pt_len_test_data[i],
120232b31808SJens Wiklander buf, sizeof(buf), &olen);
120332b31808SJens Wiklander if (ret != 0) {
120432b31808SJens Wiklander goto exit;
120532b31808SJens Wiklander }
120632b31808SJens Wiklander if (olen != pt_len_test_data[i]) {
120732b31808SJens Wiklander goto exit;
120832b31808SJens Wiklander }
120932b31808SJens Wiklander }
1210817466cbSJens Wiklander
121132b31808SJens Wiklander ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
121232b31808SJens Wiklander if (ret != 0) {
12133d3b0591SJens Wiklander goto exit;
121432b31808SJens Wiklander }
12153d3b0591SJens Wiklander
121611fa71b9SJerome Forissier if (memcmp(buf, ct_test_data[j * 6 + i],
121711fa71b9SJerome Forissier pt_len_test_data[i]) != 0 ||
121832b31808SJens Wiklander memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
12193d3b0591SJens Wiklander ret = 1;
12203d3b0591SJens Wiklander goto exit;
1221817466cbSJens Wiklander }
1222817466cbSJens Wiklander
1223817466cbSJens Wiklander mbedtls_gcm_free(&ctx);
1224817466cbSJens Wiklander
122532b31808SJens Wiklander if (verbose != 0) {
1226817466cbSJens Wiklander mbedtls_printf("passed\n");
122732b31808SJens Wiklander }
1228817466cbSJens Wiklander
12293d3b0591SJens Wiklander mbedtls_gcm_init(&ctx);
12303d3b0591SJens Wiklander
123132b31808SJens Wiklander if (verbose != 0) {
1232817466cbSJens Wiklander mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1233817466cbSJens Wiklander key_len, i, "dec");
123432b31808SJens Wiklander }
1235817466cbSJens Wiklander
123611fa71b9SJerome Forissier ret = mbedtls_gcm_setkey(&ctx, cipher,
123711fa71b9SJerome Forissier key_test_data[key_index_test_data[i]],
12383d3b0591SJens Wiklander key_len);
123932b31808SJens Wiklander if (ret != 0) {
12403d3b0591SJens Wiklander goto exit;
124132b31808SJens Wiklander }
1242817466cbSJens Wiklander
1243817466cbSJens Wiklander ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
124411fa71b9SJerome Forissier iv_test_data[iv_index_test_data[i]],
124532b31808SJens Wiklander iv_len_test_data[i]);
124632b31808SJens Wiklander if (ret != 0) {
124732b31808SJens Wiklander goto exit;
124832b31808SJens Wiklander }
124932b31808SJens Wiklander ret = mbedtls_gcm_update_ad(&ctx,
125011fa71b9SJerome Forissier additional_test_data[add_index_test_data[i]],
125111fa71b9SJerome Forissier add_len_test_data[i]);
125232b31808SJens Wiklander if (ret != 0) {
12533d3b0591SJens Wiklander goto exit;
125432b31808SJens Wiklander }
1255817466cbSJens Wiklander
125632b31808SJens Wiklander if (pt_len_test_data[i] > 32) {
125711fa71b9SJerome Forissier size_t rest_len = pt_len_test_data[i] - 32;
125832b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx,
125932b31808SJens Wiklander ct_test_data[j * 6 + i], 32,
126032b31808SJens Wiklander buf, sizeof(buf), &olen);
126132b31808SJens Wiklander if (ret != 0) {
12623d3b0591SJens Wiklander goto exit;
126332b31808SJens Wiklander }
126432b31808SJens Wiklander if (olen != 32) {
126532b31808SJens Wiklander goto exit;
126632b31808SJens Wiklander }
1267817466cbSJens Wiklander
126832b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx,
126911fa71b9SJerome Forissier ct_test_data[j * 6 + i] + 32,
127032b31808SJens Wiklander rest_len,
127132b31808SJens Wiklander buf + 32, sizeof(buf) - 32, &olen);
127232b31808SJens Wiklander if (ret != 0) {
12733d3b0591SJens Wiklander goto exit;
1274817466cbSJens Wiklander }
127532b31808SJens Wiklander if (olen != rest_len) {
12763d3b0591SJens Wiklander goto exit;
1277817466cbSJens Wiklander }
127832b31808SJens Wiklander } else {
127932b31808SJens Wiklander ret = mbedtls_gcm_update(&ctx,
128032b31808SJens Wiklander ct_test_data[j * 6 + i],
128132b31808SJens Wiklander pt_len_test_data[i],
128232b31808SJens Wiklander buf, sizeof(buf), &olen);
128332b31808SJens Wiklander if (ret != 0) {
128432b31808SJens Wiklander goto exit;
128532b31808SJens Wiklander }
128632b31808SJens Wiklander if (olen != pt_len_test_data[i]) {
128732b31808SJens Wiklander goto exit;
128832b31808SJens Wiklander }
128932b31808SJens Wiklander }
1290817466cbSJens Wiklander
129132b31808SJens Wiklander ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
129232b31808SJens Wiklander if (ret != 0) {
12933d3b0591SJens Wiklander goto exit;
129432b31808SJens Wiklander }
12953d3b0591SJens Wiklander
129611fa71b9SJerome Forissier if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
129711fa71b9SJerome Forissier pt_len_test_data[i]) != 0 ||
129832b31808SJens Wiklander memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
12993d3b0591SJens Wiklander ret = 1;
13003d3b0591SJens Wiklander goto exit;
1301817466cbSJens Wiklander }
1302817466cbSJens Wiklander
1303817466cbSJens Wiklander mbedtls_gcm_free(&ctx);
1304817466cbSJens Wiklander
130532b31808SJens Wiklander if (verbose != 0) {
1306817466cbSJens Wiklander mbedtls_printf("passed\n");
1307817466cbSJens Wiklander }
1308817466cbSJens Wiklander }
130932b31808SJens Wiklander }
1310817466cbSJens Wiklander
131132b31808SJens Wiklander if (verbose != 0) {
1312817466cbSJens Wiklander mbedtls_printf("\n");
131332b31808SJens Wiklander }
1314817466cbSJens Wiklander
13153d3b0591SJens Wiklander ret = 0;
13163d3b0591SJens Wiklander
13173d3b0591SJens Wiklander exit:
131832b31808SJens Wiklander if (ret != 0) {
131932b31808SJens Wiklander if (verbose != 0) {
13203d3b0591SJens Wiklander mbedtls_printf("failed\n");
132132b31808SJens Wiklander }
13223d3b0591SJens Wiklander mbedtls_gcm_free(&ctx);
13233d3b0591SJens Wiklander }
13243d3b0591SJens Wiklander
132532b31808SJens Wiklander return ret;
1326817466cbSJens Wiklander }
1327817466cbSJens Wiklander
1328817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
1329817466cbSJens Wiklander
1330817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */
1331