1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi * NIST SP800-38D compliant GCM implementation
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi */
7*62c56f98SSadaf Ebrahimi
8*62c56f98SSadaf Ebrahimi /*
9*62c56f98SSadaf Ebrahimi * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
10*62c56f98SSadaf Ebrahimi *
11*62c56f98SSadaf Ebrahimi * See also:
12*62c56f98SSadaf Ebrahimi * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
13*62c56f98SSadaf Ebrahimi *
14*62c56f98SSadaf Ebrahimi * We use the algorithm described as Shoup's method with 4-bit tables in
15*62c56f98SSadaf Ebrahimi * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
16*62c56f98SSadaf Ebrahimi */
17*62c56f98SSadaf Ebrahimi
18*62c56f98SSadaf Ebrahimi #include "common.h"
19*62c56f98SSadaf Ebrahimi
20*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_GCM_C)
21*62c56f98SSadaf Ebrahimi
22*62c56f98SSadaf Ebrahimi #include "mbedtls/gcm.h"
23*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
24*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
25*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
26*62c56f98SSadaf Ebrahimi #include "mbedtls/constant_time.h"
27*62c56f98SSadaf Ebrahimi
28*62c56f98SSadaf Ebrahimi #include <string.h>
29*62c56f98SSadaf Ebrahimi
30*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_AESNI_C)
31*62c56f98SSadaf Ebrahimi #include "aesni.h"
32*62c56f98SSadaf Ebrahimi #endif
33*62c56f98SSadaf Ebrahimi
34*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_AESCE_C)
35*62c56f98SSadaf Ebrahimi #include "aesce.h"
36*62c56f98SSadaf Ebrahimi #endif
37*62c56f98SSadaf Ebrahimi
38*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_GCM_ALT)
39*62c56f98SSadaf Ebrahimi
40*62c56f98SSadaf Ebrahimi /*
41*62c56f98SSadaf Ebrahimi * Initialize a context
42*62c56f98SSadaf Ebrahimi */
mbedtls_gcm_init(mbedtls_gcm_context * ctx)43*62c56f98SSadaf Ebrahimi void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
44*62c56f98SSadaf Ebrahimi {
45*62c56f98SSadaf Ebrahimi memset(ctx, 0, sizeof(mbedtls_gcm_context));
46*62c56f98SSadaf Ebrahimi }
47*62c56f98SSadaf Ebrahimi
48*62c56f98SSadaf Ebrahimi /*
49*62c56f98SSadaf Ebrahimi * Precompute small multiples of H, that is set
50*62c56f98SSadaf Ebrahimi * HH[i] || HL[i] = H times i,
51*62c56f98SSadaf Ebrahimi * where i is seen as a field element as in [MGV], ie high-order bits
52*62c56f98SSadaf Ebrahimi * correspond to low powers of P. The result is stored in the same way, that
53*62c56f98SSadaf Ebrahimi * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
54*62c56f98SSadaf Ebrahimi * corresponds to P^127.
55*62c56f98SSadaf Ebrahimi */
gcm_gen_table(mbedtls_gcm_context * ctx)56*62c56f98SSadaf Ebrahimi static int gcm_gen_table(mbedtls_gcm_context *ctx)
57*62c56f98SSadaf Ebrahimi {
58*62c56f98SSadaf Ebrahimi int ret, i, j;
59*62c56f98SSadaf Ebrahimi uint64_t hi, lo;
60*62c56f98SSadaf Ebrahimi uint64_t vl, vh;
61*62c56f98SSadaf Ebrahimi unsigned char h[16];
62*62c56f98SSadaf Ebrahimi size_t olen = 0;
63*62c56f98SSadaf Ebrahimi
64*62c56f98SSadaf Ebrahimi memset(h, 0, 16);
65*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
66*62c56f98SSadaf Ebrahimi return ret;
67*62c56f98SSadaf Ebrahimi }
68*62c56f98SSadaf Ebrahimi
69*62c56f98SSadaf Ebrahimi /* pack h as two 64-bits ints, big-endian */
70*62c56f98SSadaf Ebrahimi hi = MBEDTLS_GET_UINT32_BE(h, 0);
71*62c56f98SSadaf Ebrahimi lo = MBEDTLS_GET_UINT32_BE(h, 4);
72*62c56f98SSadaf Ebrahimi vh = (uint64_t) hi << 32 | lo;
73*62c56f98SSadaf Ebrahimi
74*62c56f98SSadaf Ebrahimi hi = MBEDTLS_GET_UINT32_BE(h, 8);
75*62c56f98SSadaf Ebrahimi lo = MBEDTLS_GET_UINT32_BE(h, 12);
76*62c56f98SSadaf Ebrahimi vl = (uint64_t) hi << 32 | lo;
77*62c56f98SSadaf Ebrahimi
78*62c56f98SSadaf Ebrahimi /* 8 = 1000 corresponds to 1 in GF(2^128) */
79*62c56f98SSadaf Ebrahimi ctx->HL[8] = vl;
80*62c56f98SSadaf Ebrahimi ctx->HH[8] = vh;
81*62c56f98SSadaf Ebrahimi
82*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_AESNI_HAVE_CODE)
83*62c56f98SSadaf Ebrahimi /* With CLMUL support, we need only h, not the rest of the table */
84*62c56f98SSadaf Ebrahimi if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
85*62c56f98SSadaf Ebrahimi return 0;
86*62c56f98SSadaf Ebrahimi }
87*62c56f98SSadaf Ebrahimi #endif
88*62c56f98SSadaf Ebrahimi
89*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_AESCE_HAVE_CODE)
90*62c56f98SSadaf Ebrahimi if (MBEDTLS_AESCE_HAS_SUPPORT()) {
91*62c56f98SSadaf Ebrahimi return 0;
92*62c56f98SSadaf Ebrahimi }
93*62c56f98SSadaf Ebrahimi #endif
94*62c56f98SSadaf Ebrahimi
95*62c56f98SSadaf Ebrahimi /* 0 corresponds to 0 in GF(2^128) */
96*62c56f98SSadaf Ebrahimi ctx->HH[0] = 0;
97*62c56f98SSadaf Ebrahimi ctx->HL[0] = 0;
98*62c56f98SSadaf Ebrahimi
99*62c56f98SSadaf Ebrahimi for (i = 4; i > 0; i >>= 1) {
100*62c56f98SSadaf Ebrahimi uint32_t T = (vl & 1) * 0xe1000000U;
101*62c56f98SSadaf Ebrahimi vl = (vh << 63) | (vl >> 1);
102*62c56f98SSadaf Ebrahimi vh = (vh >> 1) ^ ((uint64_t) T << 32);
103*62c56f98SSadaf Ebrahimi
104*62c56f98SSadaf Ebrahimi ctx->HL[i] = vl;
105*62c56f98SSadaf Ebrahimi ctx->HH[i] = vh;
106*62c56f98SSadaf Ebrahimi }
107*62c56f98SSadaf Ebrahimi
108*62c56f98SSadaf Ebrahimi for (i = 2; i <= 8; i *= 2) {
109*62c56f98SSadaf Ebrahimi uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
110*62c56f98SSadaf Ebrahimi vh = *HiH;
111*62c56f98SSadaf Ebrahimi vl = *HiL;
112*62c56f98SSadaf Ebrahimi for (j = 1; j < i; j++) {
113*62c56f98SSadaf Ebrahimi HiH[j] = vh ^ ctx->HH[j];
114*62c56f98SSadaf Ebrahimi HiL[j] = vl ^ ctx->HL[j];
115*62c56f98SSadaf Ebrahimi }
116*62c56f98SSadaf Ebrahimi }
117*62c56f98SSadaf Ebrahimi
118*62c56f98SSadaf Ebrahimi return 0;
119*62c56f98SSadaf Ebrahimi }
120*62c56f98SSadaf Ebrahimi
mbedtls_gcm_setkey(mbedtls_gcm_context * ctx,mbedtls_cipher_id_t cipher,const unsigned char * key,unsigned int keybits)121*62c56f98SSadaf Ebrahimi int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
122*62c56f98SSadaf Ebrahimi mbedtls_cipher_id_t cipher,
123*62c56f98SSadaf Ebrahimi const unsigned char *key,
124*62c56f98SSadaf Ebrahimi unsigned int keybits)
125*62c56f98SSadaf Ebrahimi {
126*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
127*62c56f98SSadaf Ebrahimi const mbedtls_cipher_info_t *cipher_info;
128*62c56f98SSadaf Ebrahimi
129*62c56f98SSadaf Ebrahimi if (keybits != 128 && keybits != 192 && keybits != 256) {
130*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_BAD_INPUT;
131*62c56f98SSadaf Ebrahimi }
132*62c56f98SSadaf Ebrahimi
133*62c56f98SSadaf Ebrahimi cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
134*62c56f98SSadaf Ebrahimi MBEDTLS_MODE_ECB);
135*62c56f98SSadaf Ebrahimi if (cipher_info == NULL) {
136*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_BAD_INPUT;
137*62c56f98SSadaf Ebrahimi }
138*62c56f98SSadaf Ebrahimi
139*62c56f98SSadaf Ebrahimi if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
140*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_BAD_INPUT;
141*62c56f98SSadaf Ebrahimi }
142*62c56f98SSadaf Ebrahimi
143*62c56f98SSadaf Ebrahimi mbedtls_cipher_free(&ctx->cipher_ctx);
144*62c56f98SSadaf Ebrahimi
145*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
146*62c56f98SSadaf Ebrahimi return ret;
147*62c56f98SSadaf Ebrahimi }
148*62c56f98SSadaf Ebrahimi
149*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
150*62c56f98SSadaf Ebrahimi MBEDTLS_ENCRYPT)) != 0) {
151*62c56f98SSadaf Ebrahimi return ret;
152*62c56f98SSadaf Ebrahimi }
153*62c56f98SSadaf Ebrahimi
154*62c56f98SSadaf Ebrahimi if ((ret = gcm_gen_table(ctx)) != 0) {
155*62c56f98SSadaf Ebrahimi return ret;
156*62c56f98SSadaf Ebrahimi }
157*62c56f98SSadaf Ebrahimi
158*62c56f98SSadaf Ebrahimi return 0;
159*62c56f98SSadaf Ebrahimi }
160*62c56f98SSadaf Ebrahimi
161*62c56f98SSadaf Ebrahimi /*
162*62c56f98SSadaf Ebrahimi * Shoup's method for multiplication use this table with
163*62c56f98SSadaf Ebrahimi * last4[x] = x times P^128
164*62c56f98SSadaf Ebrahimi * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
165*62c56f98SSadaf Ebrahimi */
166*62c56f98SSadaf Ebrahimi static const uint16_t last4[16] =
167*62c56f98SSadaf Ebrahimi {
168*62c56f98SSadaf Ebrahimi 0x0000, 0x1c20, 0x3840, 0x2460,
169*62c56f98SSadaf Ebrahimi 0x7080, 0x6ca0, 0x48c0, 0x54e0,
170*62c56f98SSadaf Ebrahimi 0xe100, 0xfd20, 0xd940, 0xc560,
171*62c56f98SSadaf Ebrahimi 0x9180, 0x8da0, 0xa9c0, 0xb5e0
172*62c56f98SSadaf Ebrahimi };
173*62c56f98SSadaf Ebrahimi
174*62c56f98SSadaf Ebrahimi /*
175*62c56f98SSadaf Ebrahimi * Sets output to x times H using the precomputed tables.
176*62c56f98SSadaf Ebrahimi * x and output are seen as elements of GF(2^128) as in [MGV].
177*62c56f98SSadaf Ebrahimi */
gcm_mult(mbedtls_gcm_context * ctx,const unsigned char x[16],unsigned char output[16])178*62c56f98SSadaf Ebrahimi static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
179*62c56f98SSadaf Ebrahimi unsigned char output[16])
180*62c56f98SSadaf Ebrahimi {
181*62c56f98SSadaf Ebrahimi int i = 0;
182*62c56f98SSadaf Ebrahimi unsigned char lo, hi, rem;
183*62c56f98SSadaf Ebrahimi uint64_t zh, zl;
184*62c56f98SSadaf Ebrahimi
185*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_AESNI_HAVE_CODE)
186*62c56f98SSadaf Ebrahimi if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
187*62c56f98SSadaf Ebrahimi unsigned char h[16];
188*62c56f98SSadaf Ebrahimi
189*62c56f98SSadaf Ebrahimi /* mbedtls_aesni_gcm_mult needs big-endian input */
190*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
191*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
192*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
193*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
194*62c56f98SSadaf Ebrahimi
195*62c56f98SSadaf Ebrahimi mbedtls_aesni_gcm_mult(output, x, h);
196*62c56f98SSadaf Ebrahimi return;
197*62c56f98SSadaf Ebrahimi }
198*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_AESNI_HAVE_CODE */
199*62c56f98SSadaf Ebrahimi
200*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_AESCE_HAVE_CODE)
201*62c56f98SSadaf Ebrahimi if (MBEDTLS_AESCE_HAS_SUPPORT()) {
202*62c56f98SSadaf Ebrahimi unsigned char h[16];
203*62c56f98SSadaf Ebrahimi
204*62c56f98SSadaf Ebrahimi /* mbedtls_aesce_gcm_mult needs big-endian input */
205*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
206*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
207*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
208*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
209*62c56f98SSadaf Ebrahimi
210*62c56f98SSadaf Ebrahimi mbedtls_aesce_gcm_mult(output, x, h);
211*62c56f98SSadaf Ebrahimi return;
212*62c56f98SSadaf Ebrahimi }
213*62c56f98SSadaf Ebrahimi #endif
214*62c56f98SSadaf Ebrahimi
215*62c56f98SSadaf Ebrahimi lo = x[15] & 0xf;
216*62c56f98SSadaf Ebrahimi
217*62c56f98SSadaf Ebrahimi zh = ctx->HH[lo];
218*62c56f98SSadaf Ebrahimi zl = ctx->HL[lo];
219*62c56f98SSadaf Ebrahimi
220*62c56f98SSadaf Ebrahimi for (i = 15; i >= 0; i--) {
221*62c56f98SSadaf Ebrahimi lo = x[i] & 0xf;
222*62c56f98SSadaf Ebrahimi hi = (x[i] >> 4) & 0xf;
223*62c56f98SSadaf Ebrahimi
224*62c56f98SSadaf Ebrahimi if (i != 15) {
225*62c56f98SSadaf Ebrahimi rem = (unsigned char) zl & 0xf;
226*62c56f98SSadaf Ebrahimi zl = (zh << 60) | (zl >> 4);
227*62c56f98SSadaf Ebrahimi zh = (zh >> 4);
228*62c56f98SSadaf Ebrahimi zh ^= (uint64_t) last4[rem] << 48;
229*62c56f98SSadaf Ebrahimi zh ^= ctx->HH[lo];
230*62c56f98SSadaf Ebrahimi zl ^= ctx->HL[lo];
231*62c56f98SSadaf Ebrahimi
232*62c56f98SSadaf Ebrahimi }
233*62c56f98SSadaf Ebrahimi
234*62c56f98SSadaf Ebrahimi rem = (unsigned char) zl & 0xf;
235*62c56f98SSadaf Ebrahimi zl = (zh << 60) | (zl >> 4);
236*62c56f98SSadaf Ebrahimi zh = (zh >> 4);
237*62c56f98SSadaf Ebrahimi zh ^= (uint64_t) last4[rem] << 48;
238*62c56f98SSadaf Ebrahimi zh ^= ctx->HH[hi];
239*62c56f98SSadaf Ebrahimi zl ^= ctx->HL[hi];
240*62c56f98SSadaf Ebrahimi }
241*62c56f98SSadaf Ebrahimi
242*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
243*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(zh, output, 4);
244*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
245*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE(zl, output, 12);
246*62c56f98SSadaf Ebrahimi }
247*62c56f98SSadaf Ebrahimi
mbedtls_gcm_starts(mbedtls_gcm_context * ctx,int mode,const unsigned char * iv,size_t iv_len)248*62c56f98SSadaf Ebrahimi int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
249*62c56f98SSadaf Ebrahimi int mode,
250*62c56f98SSadaf Ebrahimi const unsigned char *iv, size_t iv_len)
251*62c56f98SSadaf Ebrahimi {
252*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
253*62c56f98SSadaf Ebrahimi unsigned char work_buf[16];
254*62c56f98SSadaf Ebrahimi const unsigned char *p;
255*62c56f98SSadaf Ebrahimi size_t use_len, olen = 0;
256*62c56f98SSadaf Ebrahimi uint64_t iv_bits;
257*62c56f98SSadaf Ebrahimi
258*62c56f98SSadaf Ebrahimi /* IV is limited to 2^64 bits, so 2^61 bytes */
259*62c56f98SSadaf Ebrahimi /* IV is not allowed to be zero length */
260*62c56f98SSadaf Ebrahimi if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
261*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_BAD_INPUT;
262*62c56f98SSadaf Ebrahimi }
263*62c56f98SSadaf Ebrahimi
264*62c56f98SSadaf Ebrahimi memset(ctx->y, 0x00, sizeof(ctx->y));
265*62c56f98SSadaf Ebrahimi memset(ctx->buf, 0x00, sizeof(ctx->buf));
266*62c56f98SSadaf Ebrahimi
267*62c56f98SSadaf Ebrahimi ctx->mode = mode;
268*62c56f98SSadaf Ebrahimi ctx->len = 0;
269*62c56f98SSadaf Ebrahimi ctx->add_len = 0;
270*62c56f98SSadaf Ebrahimi
271*62c56f98SSadaf Ebrahimi if (iv_len == 12) {
272*62c56f98SSadaf Ebrahimi memcpy(ctx->y, iv, iv_len);
273*62c56f98SSadaf Ebrahimi ctx->y[15] = 1;
274*62c56f98SSadaf Ebrahimi } else {
275*62c56f98SSadaf Ebrahimi memset(work_buf, 0x00, 16);
276*62c56f98SSadaf Ebrahimi iv_bits = (uint64_t) iv_len * 8;
277*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
278*62c56f98SSadaf Ebrahimi
279*62c56f98SSadaf Ebrahimi p = iv;
280*62c56f98SSadaf Ebrahimi while (iv_len > 0) {
281*62c56f98SSadaf Ebrahimi use_len = (iv_len < 16) ? iv_len : 16;
282*62c56f98SSadaf Ebrahimi
283*62c56f98SSadaf Ebrahimi mbedtls_xor(ctx->y, ctx->y, p, use_len);
284*62c56f98SSadaf Ebrahimi
285*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->y, ctx->y);
286*62c56f98SSadaf Ebrahimi
287*62c56f98SSadaf Ebrahimi iv_len -= use_len;
288*62c56f98SSadaf Ebrahimi p += use_len;
289*62c56f98SSadaf Ebrahimi }
290*62c56f98SSadaf Ebrahimi
291*62c56f98SSadaf Ebrahimi mbedtls_xor(ctx->y, ctx->y, work_buf, 16);
292*62c56f98SSadaf Ebrahimi
293*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->y, ctx->y);
294*62c56f98SSadaf Ebrahimi }
295*62c56f98SSadaf Ebrahimi
296*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
297*62c56f98SSadaf Ebrahimi ctx->base_ectr, &olen)) != 0) {
298*62c56f98SSadaf Ebrahimi return ret;
299*62c56f98SSadaf Ebrahimi }
300*62c56f98SSadaf Ebrahimi
301*62c56f98SSadaf Ebrahimi return 0;
302*62c56f98SSadaf Ebrahimi }
303*62c56f98SSadaf Ebrahimi
304*62c56f98SSadaf Ebrahimi /**
305*62c56f98SSadaf Ebrahimi * mbedtls_gcm_context::buf contains the partial state of the computation of
306*62c56f98SSadaf Ebrahimi * the authentication tag.
307*62c56f98SSadaf Ebrahimi * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
308*62c56f98SSadaf Ebrahimi * different stages of the computation:
309*62c56f98SSadaf Ebrahimi * * len == 0 && add_len == 0: initial state
310*62c56f98SSadaf Ebrahimi * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
311*62c56f98SSadaf Ebrahimi * a partial block of AD that has been
312*62c56f98SSadaf Ebrahimi * xored in but not yet multiplied in.
313*62c56f98SSadaf Ebrahimi * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
314*62c56f98SSadaf Ebrahimi * the data ends now.
315*62c56f98SSadaf Ebrahimi * * len % 16 != 0: the first `len % 16` bytes have
316*62c56f98SSadaf Ebrahimi * a partial block of ciphertext that has
317*62c56f98SSadaf Ebrahimi * been xored in but not yet multiplied in.
318*62c56f98SSadaf Ebrahimi * * len > 0 && len % 16 == 0: the authentication tag is correct if
319*62c56f98SSadaf Ebrahimi * the data ends now.
320*62c56f98SSadaf Ebrahimi */
mbedtls_gcm_update_ad(mbedtls_gcm_context * ctx,const unsigned char * add,size_t add_len)321*62c56f98SSadaf Ebrahimi int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
322*62c56f98SSadaf Ebrahimi const unsigned char *add, size_t add_len)
323*62c56f98SSadaf Ebrahimi {
324*62c56f98SSadaf Ebrahimi const unsigned char *p;
325*62c56f98SSadaf Ebrahimi size_t use_len, offset;
326*62c56f98SSadaf Ebrahimi
327*62c56f98SSadaf Ebrahimi /* IV is limited to 2^64 bits, so 2^61 bytes */
328*62c56f98SSadaf Ebrahimi if ((uint64_t) add_len >> 61 != 0) {
329*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_BAD_INPUT;
330*62c56f98SSadaf Ebrahimi }
331*62c56f98SSadaf Ebrahimi
332*62c56f98SSadaf Ebrahimi offset = ctx->add_len % 16;
333*62c56f98SSadaf Ebrahimi p = add;
334*62c56f98SSadaf Ebrahimi
335*62c56f98SSadaf Ebrahimi if (offset != 0) {
336*62c56f98SSadaf Ebrahimi use_len = 16 - offset;
337*62c56f98SSadaf Ebrahimi if (use_len > add_len) {
338*62c56f98SSadaf Ebrahimi use_len = add_len;
339*62c56f98SSadaf Ebrahimi }
340*62c56f98SSadaf Ebrahimi
341*62c56f98SSadaf Ebrahimi mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
342*62c56f98SSadaf Ebrahimi
343*62c56f98SSadaf Ebrahimi if (offset + use_len == 16) {
344*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->buf, ctx->buf);
345*62c56f98SSadaf Ebrahimi }
346*62c56f98SSadaf Ebrahimi
347*62c56f98SSadaf Ebrahimi ctx->add_len += use_len;
348*62c56f98SSadaf Ebrahimi add_len -= use_len;
349*62c56f98SSadaf Ebrahimi p += use_len;
350*62c56f98SSadaf Ebrahimi }
351*62c56f98SSadaf Ebrahimi
352*62c56f98SSadaf Ebrahimi ctx->add_len += add_len;
353*62c56f98SSadaf Ebrahimi
354*62c56f98SSadaf Ebrahimi while (add_len >= 16) {
355*62c56f98SSadaf Ebrahimi mbedtls_xor(ctx->buf, ctx->buf, p, 16);
356*62c56f98SSadaf Ebrahimi
357*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->buf, ctx->buf);
358*62c56f98SSadaf Ebrahimi
359*62c56f98SSadaf Ebrahimi add_len -= 16;
360*62c56f98SSadaf Ebrahimi p += 16;
361*62c56f98SSadaf Ebrahimi }
362*62c56f98SSadaf Ebrahimi
363*62c56f98SSadaf Ebrahimi if (add_len > 0) {
364*62c56f98SSadaf Ebrahimi mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
365*62c56f98SSadaf Ebrahimi }
366*62c56f98SSadaf Ebrahimi
367*62c56f98SSadaf Ebrahimi return 0;
368*62c56f98SSadaf Ebrahimi }
369*62c56f98SSadaf Ebrahimi
370*62c56f98SSadaf Ebrahimi /* Increment the counter. */
gcm_incr(unsigned char y[16])371*62c56f98SSadaf Ebrahimi static void gcm_incr(unsigned char y[16])
372*62c56f98SSadaf Ebrahimi {
373*62c56f98SSadaf Ebrahimi size_t i;
374*62c56f98SSadaf Ebrahimi for (i = 16; i > 12; i--) {
375*62c56f98SSadaf Ebrahimi if (++y[i - 1] != 0) {
376*62c56f98SSadaf Ebrahimi break;
377*62c56f98SSadaf Ebrahimi }
378*62c56f98SSadaf Ebrahimi }
379*62c56f98SSadaf Ebrahimi }
380*62c56f98SSadaf Ebrahimi
381*62c56f98SSadaf Ebrahimi /* Calculate and apply the encryption mask. Process use_len bytes of data,
382*62c56f98SSadaf Ebrahimi * 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)383*62c56f98SSadaf Ebrahimi static int gcm_mask(mbedtls_gcm_context *ctx,
384*62c56f98SSadaf Ebrahimi unsigned char ectr[16],
385*62c56f98SSadaf Ebrahimi size_t offset, size_t use_len,
386*62c56f98SSadaf Ebrahimi const unsigned char *input,
387*62c56f98SSadaf Ebrahimi unsigned char *output)
388*62c56f98SSadaf Ebrahimi {
389*62c56f98SSadaf Ebrahimi size_t olen = 0;
390*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
391*62c56f98SSadaf Ebrahimi
392*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
393*62c56f98SSadaf Ebrahimi &olen)) != 0) {
394*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(ectr, 16);
395*62c56f98SSadaf Ebrahimi return ret;
396*62c56f98SSadaf Ebrahimi }
397*62c56f98SSadaf Ebrahimi
398*62c56f98SSadaf Ebrahimi if (ctx->mode == MBEDTLS_GCM_DECRYPT) {
399*62c56f98SSadaf Ebrahimi mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len);
400*62c56f98SSadaf Ebrahimi }
401*62c56f98SSadaf Ebrahimi mbedtls_xor(output, ectr + offset, input, use_len);
402*62c56f98SSadaf Ebrahimi if (ctx->mode == MBEDTLS_GCM_ENCRYPT) {
403*62c56f98SSadaf Ebrahimi mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len);
404*62c56f98SSadaf Ebrahimi }
405*62c56f98SSadaf Ebrahimi
406*62c56f98SSadaf Ebrahimi return 0;
407*62c56f98SSadaf Ebrahimi }
408*62c56f98SSadaf Ebrahimi
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)409*62c56f98SSadaf Ebrahimi int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
410*62c56f98SSadaf Ebrahimi const unsigned char *input, size_t input_length,
411*62c56f98SSadaf Ebrahimi unsigned char *output, size_t output_size,
412*62c56f98SSadaf Ebrahimi size_t *output_length)
413*62c56f98SSadaf Ebrahimi {
414*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
415*62c56f98SSadaf Ebrahimi const unsigned char *p = input;
416*62c56f98SSadaf Ebrahimi unsigned char *out_p = output;
417*62c56f98SSadaf Ebrahimi size_t offset;
418*62c56f98SSadaf Ebrahimi unsigned char ectr[16] = { 0 };
419*62c56f98SSadaf Ebrahimi
420*62c56f98SSadaf Ebrahimi if (output_size < input_length) {
421*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
422*62c56f98SSadaf Ebrahimi }
423*62c56f98SSadaf Ebrahimi *output_length = input_length;
424*62c56f98SSadaf Ebrahimi
425*62c56f98SSadaf Ebrahimi /* Exit early if input_length==0 so that we don't do any pointer arithmetic
426*62c56f98SSadaf Ebrahimi * on a potentially null pointer.
427*62c56f98SSadaf Ebrahimi * Returning early also means that the last partial block of AD remains
428*62c56f98SSadaf Ebrahimi * untouched for mbedtls_gcm_finish */
429*62c56f98SSadaf Ebrahimi if (input_length == 0) {
430*62c56f98SSadaf Ebrahimi return 0;
431*62c56f98SSadaf Ebrahimi }
432*62c56f98SSadaf Ebrahimi
433*62c56f98SSadaf Ebrahimi if (output > input && (size_t) (output - input) < input_length) {
434*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_BAD_INPUT;
435*62c56f98SSadaf Ebrahimi }
436*62c56f98SSadaf Ebrahimi
437*62c56f98SSadaf Ebrahimi /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
438*62c56f98SSadaf Ebrahimi * Also check for possible overflow */
439*62c56f98SSadaf Ebrahimi if (ctx->len + input_length < ctx->len ||
440*62c56f98SSadaf Ebrahimi (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
441*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_BAD_INPUT;
442*62c56f98SSadaf Ebrahimi }
443*62c56f98SSadaf Ebrahimi
444*62c56f98SSadaf Ebrahimi if (ctx->len == 0 && ctx->add_len % 16 != 0) {
445*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->buf, ctx->buf);
446*62c56f98SSadaf Ebrahimi }
447*62c56f98SSadaf Ebrahimi
448*62c56f98SSadaf Ebrahimi offset = ctx->len % 16;
449*62c56f98SSadaf Ebrahimi if (offset != 0) {
450*62c56f98SSadaf Ebrahimi size_t use_len = 16 - offset;
451*62c56f98SSadaf Ebrahimi if (use_len > input_length) {
452*62c56f98SSadaf Ebrahimi use_len = input_length;
453*62c56f98SSadaf Ebrahimi }
454*62c56f98SSadaf Ebrahimi
455*62c56f98SSadaf Ebrahimi if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
456*62c56f98SSadaf Ebrahimi return ret;
457*62c56f98SSadaf Ebrahimi }
458*62c56f98SSadaf Ebrahimi
459*62c56f98SSadaf Ebrahimi if (offset + use_len == 16) {
460*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->buf, ctx->buf);
461*62c56f98SSadaf Ebrahimi }
462*62c56f98SSadaf Ebrahimi
463*62c56f98SSadaf Ebrahimi ctx->len += use_len;
464*62c56f98SSadaf Ebrahimi input_length -= use_len;
465*62c56f98SSadaf Ebrahimi p += use_len;
466*62c56f98SSadaf Ebrahimi out_p += use_len;
467*62c56f98SSadaf Ebrahimi }
468*62c56f98SSadaf Ebrahimi
469*62c56f98SSadaf Ebrahimi ctx->len += input_length;
470*62c56f98SSadaf Ebrahimi
471*62c56f98SSadaf Ebrahimi while (input_length >= 16) {
472*62c56f98SSadaf Ebrahimi gcm_incr(ctx->y);
473*62c56f98SSadaf Ebrahimi if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
474*62c56f98SSadaf Ebrahimi return ret;
475*62c56f98SSadaf Ebrahimi }
476*62c56f98SSadaf Ebrahimi
477*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->buf, ctx->buf);
478*62c56f98SSadaf Ebrahimi
479*62c56f98SSadaf Ebrahimi input_length -= 16;
480*62c56f98SSadaf Ebrahimi p += 16;
481*62c56f98SSadaf Ebrahimi out_p += 16;
482*62c56f98SSadaf Ebrahimi }
483*62c56f98SSadaf Ebrahimi
484*62c56f98SSadaf Ebrahimi if (input_length > 0) {
485*62c56f98SSadaf Ebrahimi gcm_incr(ctx->y);
486*62c56f98SSadaf Ebrahimi if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
487*62c56f98SSadaf Ebrahimi return ret;
488*62c56f98SSadaf Ebrahimi }
489*62c56f98SSadaf Ebrahimi }
490*62c56f98SSadaf Ebrahimi
491*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(ectr, sizeof(ectr));
492*62c56f98SSadaf Ebrahimi return 0;
493*62c56f98SSadaf Ebrahimi }
494*62c56f98SSadaf Ebrahimi
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)495*62c56f98SSadaf Ebrahimi int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
496*62c56f98SSadaf Ebrahimi unsigned char *output, size_t output_size,
497*62c56f98SSadaf Ebrahimi size_t *output_length,
498*62c56f98SSadaf Ebrahimi unsigned char *tag, size_t tag_len)
499*62c56f98SSadaf Ebrahimi {
500*62c56f98SSadaf Ebrahimi unsigned char work_buf[16];
501*62c56f98SSadaf Ebrahimi uint64_t orig_len;
502*62c56f98SSadaf Ebrahimi uint64_t orig_add_len;
503*62c56f98SSadaf Ebrahimi
504*62c56f98SSadaf Ebrahimi /* We never pass any output in finish(). The output parameter exists only
505*62c56f98SSadaf Ebrahimi * for the sake of alternative implementations. */
506*62c56f98SSadaf Ebrahimi (void) output;
507*62c56f98SSadaf Ebrahimi (void) output_size;
508*62c56f98SSadaf Ebrahimi *output_length = 0;
509*62c56f98SSadaf Ebrahimi
510*62c56f98SSadaf Ebrahimi orig_len = ctx->len * 8;
511*62c56f98SSadaf Ebrahimi orig_add_len = ctx->add_len * 8;
512*62c56f98SSadaf Ebrahimi
513*62c56f98SSadaf Ebrahimi if (ctx->len == 0 && ctx->add_len % 16 != 0) {
514*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->buf, ctx->buf);
515*62c56f98SSadaf Ebrahimi }
516*62c56f98SSadaf Ebrahimi
517*62c56f98SSadaf Ebrahimi if (tag_len > 16 || tag_len < 4) {
518*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_BAD_INPUT;
519*62c56f98SSadaf Ebrahimi }
520*62c56f98SSadaf Ebrahimi
521*62c56f98SSadaf Ebrahimi if (ctx->len % 16 != 0) {
522*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->buf, ctx->buf);
523*62c56f98SSadaf Ebrahimi }
524*62c56f98SSadaf Ebrahimi
525*62c56f98SSadaf Ebrahimi memcpy(tag, ctx->base_ectr, tag_len);
526*62c56f98SSadaf Ebrahimi
527*62c56f98SSadaf Ebrahimi if (orig_len || orig_add_len) {
528*62c56f98SSadaf Ebrahimi memset(work_buf, 0x00, 16);
529*62c56f98SSadaf Ebrahimi
530*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
531*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
532*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
533*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
534*62c56f98SSadaf Ebrahimi
535*62c56f98SSadaf Ebrahimi mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
536*62c56f98SSadaf Ebrahimi
537*62c56f98SSadaf Ebrahimi gcm_mult(ctx, ctx->buf, ctx->buf);
538*62c56f98SSadaf Ebrahimi
539*62c56f98SSadaf Ebrahimi mbedtls_xor(tag, tag, ctx->buf, tag_len);
540*62c56f98SSadaf Ebrahimi }
541*62c56f98SSadaf Ebrahimi
542*62c56f98SSadaf Ebrahimi return 0;
543*62c56f98SSadaf Ebrahimi }
544*62c56f98SSadaf Ebrahimi
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)545*62c56f98SSadaf Ebrahimi int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
546*62c56f98SSadaf Ebrahimi int mode,
547*62c56f98SSadaf Ebrahimi size_t length,
548*62c56f98SSadaf Ebrahimi const unsigned char *iv,
549*62c56f98SSadaf Ebrahimi size_t iv_len,
550*62c56f98SSadaf Ebrahimi const unsigned char *add,
551*62c56f98SSadaf Ebrahimi size_t add_len,
552*62c56f98SSadaf Ebrahimi const unsigned char *input,
553*62c56f98SSadaf Ebrahimi unsigned char *output,
554*62c56f98SSadaf Ebrahimi size_t tag_len,
555*62c56f98SSadaf Ebrahimi unsigned char *tag)
556*62c56f98SSadaf Ebrahimi {
557*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
558*62c56f98SSadaf Ebrahimi size_t olen;
559*62c56f98SSadaf Ebrahimi
560*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
561*62c56f98SSadaf Ebrahimi return ret;
562*62c56f98SSadaf Ebrahimi }
563*62c56f98SSadaf Ebrahimi
564*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
565*62c56f98SSadaf Ebrahimi return ret;
566*62c56f98SSadaf Ebrahimi }
567*62c56f98SSadaf Ebrahimi
568*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_gcm_update(ctx, input, length,
569*62c56f98SSadaf Ebrahimi output, length, &olen)) != 0) {
570*62c56f98SSadaf Ebrahimi return ret;
571*62c56f98SSadaf Ebrahimi }
572*62c56f98SSadaf Ebrahimi
573*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
574*62c56f98SSadaf Ebrahimi return ret;
575*62c56f98SSadaf Ebrahimi }
576*62c56f98SSadaf Ebrahimi
577*62c56f98SSadaf Ebrahimi return 0;
578*62c56f98SSadaf Ebrahimi }
579*62c56f98SSadaf Ebrahimi
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)580*62c56f98SSadaf Ebrahimi int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
581*62c56f98SSadaf Ebrahimi size_t length,
582*62c56f98SSadaf Ebrahimi const unsigned char *iv,
583*62c56f98SSadaf Ebrahimi size_t iv_len,
584*62c56f98SSadaf Ebrahimi const unsigned char *add,
585*62c56f98SSadaf Ebrahimi size_t add_len,
586*62c56f98SSadaf Ebrahimi const unsigned char *tag,
587*62c56f98SSadaf Ebrahimi size_t tag_len,
588*62c56f98SSadaf Ebrahimi const unsigned char *input,
589*62c56f98SSadaf Ebrahimi unsigned char *output)
590*62c56f98SSadaf Ebrahimi {
591*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
592*62c56f98SSadaf Ebrahimi unsigned char check_tag[16];
593*62c56f98SSadaf Ebrahimi int diff;
594*62c56f98SSadaf Ebrahimi
595*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
596*62c56f98SSadaf Ebrahimi iv, iv_len, add, add_len,
597*62c56f98SSadaf Ebrahimi input, output, tag_len, check_tag)) != 0) {
598*62c56f98SSadaf Ebrahimi return ret;
599*62c56f98SSadaf Ebrahimi }
600*62c56f98SSadaf Ebrahimi
601*62c56f98SSadaf Ebrahimi /* Check tag in "constant-time" */
602*62c56f98SSadaf Ebrahimi diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
603*62c56f98SSadaf Ebrahimi
604*62c56f98SSadaf Ebrahimi if (diff != 0) {
605*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(output, length);
606*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_GCM_AUTH_FAILED;
607*62c56f98SSadaf Ebrahimi }
608*62c56f98SSadaf Ebrahimi
609*62c56f98SSadaf Ebrahimi return 0;
610*62c56f98SSadaf Ebrahimi }
611*62c56f98SSadaf Ebrahimi
mbedtls_gcm_free(mbedtls_gcm_context * ctx)612*62c56f98SSadaf Ebrahimi void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
613*62c56f98SSadaf Ebrahimi {
614*62c56f98SSadaf Ebrahimi if (ctx == NULL) {
615*62c56f98SSadaf Ebrahimi return;
616*62c56f98SSadaf Ebrahimi }
617*62c56f98SSadaf Ebrahimi mbedtls_cipher_free(&ctx->cipher_ctx);
618*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
619*62c56f98SSadaf Ebrahimi }
620*62c56f98SSadaf Ebrahimi
621*62c56f98SSadaf Ebrahimi #endif /* !MBEDTLS_GCM_ALT */
622*62c56f98SSadaf Ebrahimi
623*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
624*62c56f98SSadaf Ebrahimi /*
625*62c56f98SSadaf Ebrahimi * AES-GCM test vectors from:
626*62c56f98SSadaf Ebrahimi *
627*62c56f98SSadaf Ebrahimi * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
628*62c56f98SSadaf Ebrahimi */
629*62c56f98SSadaf Ebrahimi #define MAX_TESTS 6
630*62c56f98SSadaf Ebrahimi
631*62c56f98SSadaf Ebrahimi static const int key_index_test_data[MAX_TESTS] =
632*62c56f98SSadaf Ebrahimi { 0, 0, 1, 1, 1, 1 };
633*62c56f98SSadaf Ebrahimi
634*62c56f98SSadaf Ebrahimi static const unsigned char key_test_data[][32] =
635*62c56f98SSadaf Ebrahimi {
636*62c56f98SSadaf Ebrahimi { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637*62c56f98SSadaf Ebrahimi 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638*62c56f98SSadaf Ebrahimi 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639*62c56f98SSadaf Ebrahimi 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
640*62c56f98SSadaf Ebrahimi { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
641*62c56f98SSadaf Ebrahimi 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
642*62c56f98SSadaf Ebrahimi 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
643*62c56f98SSadaf Ebrahimi 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
644*62c56f98SSadaf Ebrahimi };
645*62c56f98SSadaf Ebrahimi
646*62c56f98SSadaf Ebrahimi static const size_t iv_len_test_data[MAX_TESTS] =
647*62c56f98SSadaf Ebrahimi { 12, 12, 12, 12, 8, 60 };
648*62c56f98SSadaf Ebrahimi
649*62c56f98SSadaf Ebrahimi static const int iv_index_test_data[MAX_TESTS] =
650*62c56f98SSadaf Ebrahimi { 0, 0, 1, 1, 1, 2 };
651*62c56f98SSadaf Ebrahimi
652*62c56f98SSadaf Ebrahimi static const unsigned char iv_test_data[][64] =
653*62c56f98SSadaf Ebrahimi {
654*62c56f98SSadaf Ebrahimi { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655*62c56f98SSadaf Ebrahimi 0x00, 0x00, 0x00, 0x00 },
656*62c56f98SSadaf Ebrahimi { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
657*62c56f98SSadaf Ebrahimi 0xde, 0xca, 0xf8, 0x88 },
658*62c56f98SSadaf Ebrahimi { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
659*62c56f98SSadaf Ebrahimi 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
660*62c56f98SSadaf Ebrahimi 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
661*62c56f98SSadaf Ebrahimi 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
662*62c56f98SSadaf Ebrahimi 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
663*62c56f98SSadaf Ebrahimi 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
664*62c56f98SSadaf Ebrahimi 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
665*62c56f98SSadaf Ebrahimi 0xa6, 0x37, 0xb3, 0x9b },
666*62c56f98SSadaf Ebrahimi };
667*62c56f98SSadaf Ebrahimi
668*62c56f98SSadaf Ebrahimi static const size_t add_len_test_data[MAX_TESTS] =
669*62c56f98SSadaf Ebrahimi { 0, 0, 0, 20, 20, 20 };
670*62c56f98SSadaf Ebrahimi
671*62c56f98SSadaf Ebrahimi static const int add_index_test_data[MAX_TESTS] =
672*62c56f98SSadaf Ebrahimi { 0, 0, 0, 1, 1, 1 };
673*62c56f98SSadaf Ebrahimi
674*62c56f98SSadaf Ebrahimi static const unsigned char additional_test_data[][64] =
675*62c56f98SSadaf Ebrahimi {
676*62c56f98SSadaf Ebrahimi { 0x00 },
677*62c56f98SSadaf Ebrahimi { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
678*62c56f98SSadaf Ebrahimi 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
679*62c56f98SSadaf Ebrahimi 0xab, 0xad, 0xda, 0xd2 },
680*62c56f98SSadaf Ebrahimi };
681*62c56f98SSadaf Ebrahimi
682*62c56f98SSadaf Ebrahimi static const size_t pt_len_test_data[MAX_TESTS] =
683*62c56f98SSadaf Ebrahimi { 0, 16, 64, 60, 60, 60 };
684*62c56f98SSadaf Ebrahimi
685*62c56f98SSadaf Ebrahimi static const int pt_index_test_data[MAX_TESTS] =
686*62c56f98SSadaf Ebrahimi { 0, 0, 1, 1, 1, 1 };
687*62c56f98SSadaf Ebrahimi
688*62c56f98SSadaf Ebrahimi static const unsigned char pt_test_data[][64] =
689*62c56f98SSadaf Ebrahimi {
690*62c56f98SSadaf Ebrahimi { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691*62c56f98SSadaf Ebrahimi 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
692*62c56f98SSadaf Ebrahimi { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
693*62c56f98SSadaf Ebrahimi 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
694*62c56f98SSadaf Ebrahimi 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
695*62c56f98SSadaf Ebrahimi 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
696*62c56f98SSadaf Ebrahimi 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
697*62c56f98SSadaf Ebrahimi 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
698*62c56f98SSadaf Ebrahimi 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
699*62c56f98SSadaf Ebrahimi 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
700*62c56f98SSadaf Ebrahimi };
701*62c56f98SSadaf Ebrahimi
702*62c56f98SSadaf Ebrahimi static const unsigned char ct_test_data[][64] =
703*62c56f98SSadaf Ebrahimi {
704*62c56f98SSadaf Ebrahimi { 0x00 },
705*62c56f98SSadaf Ebrahimi { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
706*62c56f98SSadaf Ebrahimi 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
707*62c56f98SSadaf Ebrahimi { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
708*62c56f98SSadaf Ebrahimi 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
709*62c56f98SSadaf Ebrahimi 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
710*62c56f98SSadaf Ebrahimi 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
711*62c56f98SSadaf Ebrahimi 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
712*62c56f98SSadaf Ebrahimi 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
713*62c56f98SSadaf Ebrahimi 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
714*62c56f98SSadaf Ebrahimi 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
715*62c56f98SSadaf Ebrahimi { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
716*62c56f98SSadaf Ebrahimi 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
717*62c56f98SSadaf Ebrahimi 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
718*62c56f98SSadaf Ebrahimi 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
719*62c56f98SSadaf Ebrahimi 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
720*62c56f98SSadaf Ebrahimi 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
721*62c56f98SSadaf Ebrahimi 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
722*62c56f98SSadaf Ebrahimi 0x3d, 0x58, 0xe0, 0x91 },
723*62c56f98SSadaf Ebrahimi { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
724*62c56f98SSadaf Ebrahimi 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
725*62c56f98SSadaf Ebrahimi 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
726*62c56f98SSadaf Ebrahimi 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
727*62c56f98SSadaf Ebrahimi 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
728*62c56f98SSadaf Ebrahimi 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
729*62c56f98SSadaf Ebrahimi 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
730*62c56f98SSadaf Ebrahimi 0xc2, 0x3f, 0x45, 0x98 },
731*62c56f98SSadaf Ebrahimi { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
732*62c56f98SSadaf Ebrahimi 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
733*62c56f98SSadaf Ebrahimi 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
734*62c56f98SSadaf Ebrahimi 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
735*62c56f98SSadaf Ebrahimi 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
736*62c56f98SSadaf Ebrahimi 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
737*62c56f98SSadaf Ebrahimi 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
738*62c56f98SSadaf Ebrahimi 0x4c, 0x34, 0xae, 0xe5 },
739*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
740*62c56f98SSadaf Ebrahimi { 0x00 },
741*62c56f98SSadaf Ebrahimi { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
742*62c56f98SSadaf Ebrahimi 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
743*62c56f98SSadaf Ebrahimi { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
744*62c56f98SSadaf Ebrahimi 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
745*62c56f98SSadaf Ebrahimi 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
746*62c56f98SSadaf Ebrahimi 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
747*62c56f98SSadaf Ebrahimi 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
748*62c56f98SSadaf Ebrahimi 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
749*62c56f98SSadaf Ebrahimi 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
750*62c56f98SSadaf Ebrahimi 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
751*62c56f98SSadaf Ebrahimi { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
752*62c56f98SSadaf Ebrahimi 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
753*62c56f98SSadaf Ebrahimi 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
754*62c56f98SSadaf Ebrahimi 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
755*62c56f98SSadaf Ebrahimi 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
756*62c56f98SSadaf Ebrahimi 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
757*62c56f98SSadaf Ebrahimi 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
758*62c56f98SSadaf Ebrahimi 0xcc, 0xda, 0x27, 0x10 },
759*62c56f98SSadaf Ebrahimi { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
760*62c56f98SSadaf Ebrahimi 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
761*62c56f98SSadaf Ebrahimi 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
762*62c56f98SSadaf Ebrahimi 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
763*62c56f98SSadaf Ebrahimi 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
764*62c56f98SSadaf Ebrahimi 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
765*62c56f98SSadaf Ebrahimi 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
766*62c56f98SSadaf Ebrahimi 0xa0, 0xf0, 0x62, 0xf7 },
767*62c56f98SSadaf Ebrahimi { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
768*62c56f98SSadaf Ebrahimi 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
769*62c56f98SSadaf Ebrahimi 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
770*62c56f98SSadaf Ebrahimi 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
771*62c56f98SSadaf Ebrahimi 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
772*62c56f98SSadaf Ebrahimi 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
773*62c56f98SSadaf Ebrahimi 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
774*62c56f98SSadaf Ebrahimi 0xe9, 0xb7, 0x37, 0x3b },
775*62c56f98SSadaf Ebrahimi { 0x00 },
776*62c56f98SSadaf Ebrahimi { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
777*62c56f98SSadaf Ebrahimi 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
778*62c56f98SSadaf Ebrahimi { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
779*62c56f98SSadaf Ebrahimi 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
780*62c56f98SSadaf Ebrahimi 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
781*62c56f98SSadaf Ebrahimi 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
782*62c56f98SSadaf Ebrahimi 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
783*62c56f98SSadaf Ebrahimi 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
784*62c56f98SSadaf Ebrahimi 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
785*62c56f98SSadaf Ebrahimi 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
786*62c56f98SSadaf Ebrahimi { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
787*62c56f98SSadaf Ebrahimi 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
788*62c56f98SSadaf Ebrahimi 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
789*62c56f98SSadaf Ebrahimi 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
790*62c56f98SSadaf Ebrahimi 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
791*62c56f98SSadaf Ebrahimi 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
792*62c56f98SSadaf Ebrahimi 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
793*62c56f98SSadaf Ebrahimi 0xbc, 0xc9, 0xf6, 0x62 },
794*62c56f98SSadaf Ebrahimi { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
795*62c56f98SSadaf Ebrahimi 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
796*62c56f98SSadaf Ebrahimi 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
797*62c56f98SSadaf Ebrahimi 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
798*62c56f98SSadaf Ebrahimi 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
799*62c56f98SSadaf Ebrahimi 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
800*62c56f98SSadaf Ebrahimi 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
801*62c56f98SSadaf Ebrahimi 0xf4, 0x7c, 0x9b, 0x1f },
802*62c56f98SSadaf Ebrahimi { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
803*62c56f98SSadaf Ebrahimi 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
804*62c56f98SSadaf Ebrahimi 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
805*62c56f98SSadaf Ebrahimi 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
806*62c56f98SSadaf Ebrahimi 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
807*62c56f98SSadaf Ebrahimi 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
808*62c56f98SSadaf Ebrahimi 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
809*62c56f98SSadaf Ebrahimi 0x44, 0xae, 0x7e, 0x3f },
810*62c56f98SSadaf Ebrahimi #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
811*62c56f98SSadaf Ebrahimi };
812*62c56f98SSadaf Ebrahimi
813*62c56f98SSadaf Ebrahimi static const unsigned char tag_test_data[][16] =
814*62c56f98SSadaf Ebrahimi {
815*62c56f98SSadaf Ebrahimi { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
816*62c56f98SSadaf Ebrahimi 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
817*62c56f98SSadaf Ebrahimi { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
818*62c56f98SSadaf Ebrahimi 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
819*62c56f98SSadaf Ebrahimi { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
820*62c56f98SSadaf Ebrahimi 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
821*62c56f98SSadaf Ebrahimi { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
822*62c56f98SSadaf Ebrahimi 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
823*62c56f98SSadaf Ebrahimi { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
824*62c56f98SSadaf Ebrahimi 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
825*62c56f98SSadaf Ebrahimi { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
826*62c56f98SSadaf Ebrahimi 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
827*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
828*62c56f98SSadaf Ebrahimi { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
829*62c56f98SSadaf Ebrahimi 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
830*62c56f98SSadaf Ebrahimi { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
831*62c56f98SSadaf Ebrahimi 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
832*62c56f98SSadaf Ebrahimi { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
833*62c56f98SSadaf Ebrahimi 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
834*62c56f98SSadaf Ebrahimi { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
835*62c56f98SSadaf Ebrahimi 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
836*62c56f98SSadaf Ebrahimi { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
837*62c56f98SSadaf Ebrahimi 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
838*62c56f98SSadaf Ebrahimi { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
839*62c56f98SSadaf Ebrahimi 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
840*62c56f98SSadaf Ebrahimi { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
841*62c56f98SSadaf Ebrahimi 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
842*62c56f98SSadaf Ebrahimi { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
843*62c56f98SSadaf Ebrahimi 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
844*62c56f98SSadaf Ebrahimi { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
845*62c56f98SSadaf Ebrahimi 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
846*62c56f98SSadaf Ebrahimi { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
847*62c56f98SSadaf Ebrahimi 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
848*62c56f98SSadaf Ebrahimi { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
849*62c56f98SSadaf Ebrahimi 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
850*62c56f98SSadaf Ebrahimi { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
851*62c56f98SSadaf Ebrahimi 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
852*62c56f98SSadaf Ebrahimi #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
853*62c56f98SSadaf Ebrahimi };
854*62c56f98SSadaf Ebrahimi
mbedtls_gcm_self_test(int verbose)855*62c56f98SSadaf Ebrahimi int mbedtls_gcm_self_test(int verbose)
856*62c56f98SSadaf Ebrahimi {
857*62c56f98SSadaf Ebrahimi mbedtls_gcm_context ctx;
858*62c56f98SSadaf Ebrahimi unsigned char buf[64];
859*62c56f98SSadaf Ebrahimi unsigned char tag_buf[16];
860*62c56f98SSadaf Ebrahimi int i, j, ret;
861*62c56f98SSadaf Ebrahimi mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
862*62c56f98SSadaf Ebrahimi size_t olen;
863*62c56f98SSadaf Ebrahimi
864*62c56f98SSadaf Ebrahimi if (verbose != 0) {
865*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_GCM_ALT)
866*62c56f98SSadaf Ebrahimi mbedtls_printf(" GCM note: alternative implementation.\n");
867*62c56f98SSadaf Ebrahimi #else /* MBEDTLS_GCM_ALT */
868*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_AESNI_HAVE_CODE)
869*62c56f98SSadaf Ebrahimi if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
870*62c56f98SSadaf Ebrahimi mbedtls_printf(" GCM note: using AESNI.\n");
871*62c56f98SSadaf Ebrahimi } else
872*62c56f98SSadaf Ebrahimi #endif
873*62c56f98SSadaf Ebrahimi
874*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_AESCE_HAVE_CODE)
875*62c56f98SSadaf Ebrahimi if (MBEDTLS_AESCE_HAS_SUPPORT()) {
876*62c56f98SSadaf Ebrahimi mbedtls_printf(" GCM note: using AESCE.\n");
877*62c56f98SSadaf Ebrahimi } else
878*62c56f98SSadaf Ebrahimi #endif
879*62c56f98SSadaf Ebrahimi
880*62c56f98SSadaf Ebrahimi mbedtls_printf(" GCM note: built-in implementation.\n");
881*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_GCM_ALT */
882*62c56f98SSadaf Ebrahimi }
883*62c56f98SSadaf Ebrahimi
884*62c56f98SSadaf Ebrahimi static const int loop_limit =
885*62c56f98SSadaf Ebrahimi (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
886*62c56f98SSadaf Ebrahimi
887*62c56f98SSadaf Ebrahimi for (j = 0; j < loop_limit; j++) {
888*62c56f98SSadaf Ebrahimi int key_len = 128 + 64 * j;
889*62c56f98SSadaf Ebrahimi
890*62c56f98SSadaf Ebrahimi for (i = 0; i < MAX_TESTS; i++) {
891*62c56f98SSadaf Ebrahimi if (verbose != 0) {
892*62c56f98SSadaf Ebrahimi mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
893*62c56f98SSadaf Ebrahimi key_len, i, "enc");
894*62c56f98SSadaf Ebrahimi }
895*62c56f98SSadaf Ebrahimi
896*62c56f98SSadaf Ebrahimi mbedtls_gcm_init(&ctx);
897*62c56f98SSadaf Ebrahimi
898*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_setkey(&ctx, cipher,
899*62c56f98SSadaf Ebrahimi key_test_data[key_index_test_data[i]],
900*62c56f98SSadaf Ebrahimi key_len);
901*62c56f98SSadaf Ebrahimi /*
902*62c56f98SSadaf Ebrahimi * AES-192 is an optional feature that may be unavailable when
903*62c56f98SSadaf Ebrahimi * there is an alternative underlying implementation i.e. when
904*62c56f98SSadaf Ebrahimi * MBEDTLS_AES_ALT is defined.
905*62c56f98SSadaf Ebrahimi */
906*62c56f98SSadaf Ebrahimi if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
907*62c56f98SSadaf Ebrahimi mbedtls_printf("skipped\n");
908*62c56f98SSadaf Ebrahimi break;
909*62c56f98SSadaf Ebrahimi } else if (ret != 0) {
910*62c56f98SSadaf Ebrahimi goto exit;
911*62c56f98SSadaf Ebrahimi }
912*62c56f98SSadaf Ebrahimi
913*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
914*62c56f98SSadaf Ebrahimi pt_len_test_data[i],
915*62c56f98SSadaf Ebrahimi iv_test_data[iv_index_test_data[i]],
916*62c56f98SSadaf Ebrahimi iv_len_test_data[i],
917*62c56f98SSadaf Ebrahimi additional_test_data[add_index_test_data[i]],
918*62c56f98SSadaf Ebrahimi add_len_test_data[i],
919*62c56f98SSadaf Ebrahimi pt_test_data[pt_index_test_data[i]],
920*62c56f98SSadaf Ebrahimi buf, 16, tag_buf);
921*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_GCM_ALT)
922*62c56f98SSadaf Ebrahimi /* Allow alternative implementations to only support 12-byte nonces. */
923*62c56f98SSadaf Ebrahimi if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
924*62c56f98SSadaf Ebrahimi iv_len_test_data[i] != 12) {
925*62c56f98SSadaf Ebrahimi mbedtls_printf("skipped\n");
926*62c56f98SSadaf Ebrahimi break;
927*62c56f98SSadaf Ebrahimi }
928*62c56f98SSadaf Ebrahimi #endif /* defined(MBEDTLS_GCM_ALT) */
929*62c56f98SSadaf Ebrahimi if (ret != 0) {
930*62c56f98SSadaf Ebrahimi goto exit;
931*62c56f98SSadaf Ebrahimi }
932*62c56f98SSadaf Ebrahimi
933*62c56f98SSadaf Ebrahimi if (memcmp(buf, ct_test_data[j * 6 + i],
934*62c56f98SSadaf Ebrahimi pt_len_test_data[i]) != 0 ||
935*62c56f98SSadaf Ebrahimi memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
936*62c56f98SSadaf Ebrahimi ret = 1;
937*62c56f98SSadaf Ebrahimi goto exit;
938*62c56f98SSadaf Ebrahimi }
939*62c56f98SSadaf Ebrahimi
940*62c56f98SSadaf Ebrahimi mbedtls_gcm_free(&ctx);
941*62c56f98SSadaf Ebrahimi
942*62c56f98SSadaf Ebrahimi if (verbose != 0) {
943*62c56f98SSadaf Ebrahimi mbedtls_printf("passed\n");
944*62c56f98SSadaf Ebrahimi }
945*62c56f98SSadaf Ebrahimi
946*62c56f98SSadaf Ebrahimi mbedtls_gcm_init(&ctx);
947*62c56f98SSadaf Ebrahimi
948*62c56f98SSadaf Ebrahimi if (verbose != 0) {
949*62c56f98SSadaf Ebrahimi mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
950*62c56f98SSadaf Ebrahimi key_len, i, "dec");
951*62c56f98SSadaf Ebrahimi }
952*62c56f98SSadaf Ebrahimi
953*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_setkey(&ctx, cipher,
954*62c56f98SSadaf Ebrahimi key_test_data[key_index_test_data[i]],
955*62c56f98SSadaf Ebrahimi key_len);
956*62c56f98SSadaf Ebrahimi if (ret != 0) {
957*62c56f98SSadaf Ebrahimi goto exit;
958*62c56f98SSadaf Ebrahimi }
959*62c56f98SSadaf Ebrahimi
960*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
961*62c56f98SSadaf Ebrahimi pt_len_test_data[i],
962*62c56f98SSadaf Ebrahimi iv_test_data[iv_index_test_data[i]],
963*62c56f98SSadaf Ebrahimi iv_len_test_data[i],
964*62c56f98SSadaf Ebrahimi additional_test_data[add_index_test_data[i]],
965*62c56f98SSadaf Ebrahimi add_len_test_data[i],
966*62c56f98SSadaf Ebrahimi ct_test_data[j * 6 + i], buf, 16, tag_buf);
967*62c56f98SSadaf Ebrahimi
968*62c56f98SSadaf Ebrahimi if (ret != 0) {
969*62c56f98SSadaf Ebrahimi goto exit;
970*62c56f98SSadaf Ebrahimi }
971*62c56f98SSadaf Ebrahimi
972*62c56f98SSadaf Ebrahimi if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
973*62c56f98SSadaf Ebrahimi pt_len_test_data[i]) != 0 ||
974*62c56f98SSadaf Ebrahimi memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
975*62c56f98SSadaf Ebrahimi ret = 1;
976*62c56f98SSadaf Ebrahimi goto exit;
977*62c56f98SSadaf Ebrahimi }
978*62c56f98SSadaf Ebrahimi
979*62c56f98SSadaf Ebrahimi mbedtls_gcm_free(&ctx);
980*62c56f98SSadaf Ebrahimi
981*62c56f98SSadaf Ebrahimi if (verbose != 0) {
982*62c56f98SSadaf Ebrahimi mbedtls_printf("passed\n");
983*62c56f98SSadaf Ebrahimi }
984*62c56f98SSadaf Ebrahimi
985*62c56f98SSadaf Ebrahimi mbedtls_gcm_init(&ctx);
986*62c56f98SSadaf Ebrahimi
987*62c56f98SSadaf Ebrahimi if (verbose != 0) {
988*62c56f98SSadaf Ebrahimi mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
989*62c56f98SSadaf Ebrahimi key_len, i, "enc");
990*62c56f98SSadaf Ebrahimi }
991*62c56f98SSadaf Ebrahimi
992*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_setkey(&ctx, cipher,
993*62c56f98SSadaf Ebrahimi key_test_data[key_index_test_data[i]],
994*62c56f98SSadaf Ebrahimi key_len);
995*62c56f98SSadaf Ebrahimi if (ret != 0) {
996*62c56f98SSadaf Ebrahimi goto exit;
997*62c56f98SSadaf Ebrahimi }
998*62c56f98SSadaf Ebrahimi
999*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
1000*62c56f98SSadaf Ebrahimi iv_test_data[iv_index_test_data[i]],
1001*62c56f98SSadaf Ebrahimi iv_len_test_data[i]);
1002*62c56f98SSadaf Ebrahimi if (ret != 0) {
1003*62c56f98SSadaf Ebrahimi goto exit;
1004*62c56f98SSadaf Ebrahimi }
1005*62c56f98SSadaf Ebrahimi
1006*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_update_ad(&ctx,
1007*62c56f98SSadaf Ebrahimi additional_test_data[add_index_test_data[i]],
1008*62c56f98SSadaf Ebrahimi add_len_test_data[i]);
1009*62c56f98SSadaf Ebrahimi if (ret != 0) {
1010*62c56f98SSadaf Ebrahimi goto exit;
1011*62c56f98SSadaf Ebrahimi }
1012*62c56f98SSadaf Ebrahimi
1013*62c56f98SSadaf Ebrahimi if (pt_len_test_data[i] > 32) {
1014*62c56f98SSadaf Ebrahimi size_t rest_len = pt_len_test_data[i] - 32;
1015*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_update(&ctx,
1016*62c56f98SSadaf Ebrahimi pt_test_data[pt_index_test_data[i]],
1017*62c56f98SSadaf Ebrahimi 32,
1018*62c56f98SSadaf Ebrahimi buf, sizeof(buf), &olen);
1019*62c56f98SSadaf Ebrahimi if (ret != 0) {
1020*62c56f98SSadaf Ebrahimi goto exit;
1021*62c56f98SSadaf Ebrahimi }
1022*62c56f98SSadaf Ebrahimi if (olen != 32) {
1023*62c56f98SSadaf Ebrahimi goto exit;
1024*62c56f98SSadaf Ebrahimi }
1025*62c56f98SSadaf Ebrahimi
1026*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_update(&ctx,
1027*62c56f98SSadaf Ebrahimi pt_test_data[pt_index_test_data[i]] + 32,
1028*62c56f98SSadaf Ebrahimi rest_len,
1029*62c56f98SSadaf Ebrahimi buf + 32, sizeof(buf) - 32, &olen);
1030*62c56f98SSadaf Ebrahimi if (ret != 0) {
1031*62c56f98SSadaf Ebrahimi goto exit;
1032*62c56f98SSadaf Ebrahimi }
1033*62c56f98SSadaf Ebrahimi if (olen != rest_len) {
1034*62c56f98SSadaf Ebrahimi goto exit;
1035*62c56f98SSadaf Ebrahimi }
1036*62c56f98SSadaf Ebrahimi } else {
1037*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_update(&ctx,
1038*62c56f98SSadaf Ebrahimi pt_test_data[pt_index_test_data[i]],
1039*62c56f98SSadaf Ebrahimi pt_len_test_data[i],
1040*62c56f98SSadaf Ebrahimi buf, sizeof(buf), &olen);
1041*62c56f98SSadaf Ebrahimi if (ret != 0) {
1042*62c56f98SSadaf Ebrahimi goto exit;
1043*62c56f98SSadaf Ebrahimi }
1044*62c56f98SSadaf Ebrahimi if (olen != pt_len_test_data[i]) {
1045*62c56f98SSadaf Ebrahimi goto exit;
1046*62c56f98SSadaf Ebrahimi }
1047*62c56f98SSadaf Ebrahimi }
1048*62c56f98SSadaf Ebrahimi
1049*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1050*62c56f98SSadaf Ebrahimi if (ret != 0) {
1051*62c56f98SSadaf Ebrahimi goto exit;
1052*62c56f98SSadaf Ebrahimi }
1053*62c56f98SSadaf Ebrahimi
1054*62c56f98SSadaf Ebrahimi if (memcmp(buf, ct_test_data[j * 6 + i],
1055*62c56f98SSadaf Ebrahimi pt_len_test_data[i]) != 0 ||
1056*62c56f98SSadaf Ebrahimi memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
1057*62c56f98SSadaf Ebrahimi ret = 1;
1058*62c56f98SSadaf Ebrahimi goto exit;
1059*62c56f98SSadaf Ebrahimi }
1060*62c56f98SSadaf Ebrahimi
1061*62c56f98SSadaf Ebrahimi mbedtls_gcm_free(&ctx);
1062*62c56f98SSadaf Ebrahimi
1063*62c56f98SSadaf Ebrahimi if (verbose != 0) {
1064*62c56f98SSadaf Ebrahimi mbedtls_printf("passed\n");
1065*62c56f98SSadaf Ebrahimi }
1066*62c56f98SSadaf Ebrahimi
1067*62c56f98SSadaf Ebrahimi mbedtls_gcm_init(&ctx);
1068*62c56f98SSadaf Ebrahimi
1069*62c56f98SSadaf Ebrahimi if (verbose != 0) {
1070*62c56f98SSadaf Ebrahimi mbedtls_printf(" AES-GCM-%3d #%d split (%s): ",
1071*62c56f98SSadaf Ebrahimi key_len, i, "dec");
1072*62c56f98SSadaf Ebrahimi }
1073*62c56f98SSadaf Ebrahimi
1074*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_setkey(&ctx, cipher,
1075*62c56f98SSadaf Ebrahimi key_test_data[key_index_test_data[i]],
1076*62c56f98SSadaf Ebrahimi key_len);
1077*62c56f98SSadaf Ebrahimi if (ret != 0) {
1078*62c56f98SSadaf Ebrahimi goto exit;
1079*62c56f98SSadaf Ebrahimi }
1080*62c56f98SSadaf Ebrahimi
1081*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
1082*62c56f98SSadaf Ebrahimi iv_test_data[iv_index_test_data[i]],
1083*62c56f98SSadaf Ebrahimi iv_len_test_data[i]);
1084*62c56f98SSadaf Ebrahimi if (ret != 0) {
1085*62c56f98SSadaf Ebrahimi goto exit;
1086*62c56f98SSadaf Ebrahimi }
1087*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_update_ad(&ctx,
1088*62c56f98SSadaf Ebrahimi additional_test_data[add_index_test_data[i]],
1089*62c56f98SSadaf Ebrahimi add_len_test_data[i]);
1090*62c56f98SSadaf Ebrahimi if (ret != 0) {
1091*62c56f98SSadaf Ebrahimi goto exit;
1092*62c56f98SSadaf Ebrahimi }
1093*62c56f98SSadaf Ebrahimi
1094*62c56f98SSadaf Ebrahimi if (pt_len_test_data[i] > 32) {
1095*62c56f98SSadaf Ebrahimi size_t rest_len = pt_len_test_data[i] - 32;
1096*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_update(&ctx,
1097*62c56f98SSadaf Ebrahimi ct_test_data[j * 6 + i], 32,
1098*62c56f98SSadaf Ebrahimi buf, sizeof(buf), &olen);
1099*62c56f98SSadaf Ebrahimi if (ret != 0) {
1100*62c56f98SSadaf Ebrahimi goto exit;
1101*62c56f98SSadaf Ebrahimi }
1102*62c56f98SSadaf Ebrahimi if (olen != 32) {
1103*62c56f98SSadaf Ebrahimi goto exit;
1104*62c56f98SSadaf Ebrahimi }
1105*62c56f98SSadaf Ebrahimi
1106*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_update(&ctx,
1107*62c56f98SSadaf Ebrahimi ct_test_data[j * 6 + i] + 32,
1108*62c56f98SSadaf Ebrahimi rest_len,
1109*62c56f98SSadaf Ebrahimi buf + 32, sizeof(buf) - 32, &olen);
1110*62c56f98SSadaf Ebrahimi if (ret != 0) {
1111*62c56f98SSadaf Ebrahimi goto exit;
1112*62c56f98SSadaf Ebrahimi }
1113*62c56f98SSadaf Ebrahimi if (olen != rest_len) {
1114*62c56f98SSadaf Ebrahimi goto exit;
1115*62c56f98SSadaf Ebrahimi }
1116*62c56f98SSadaf Ebrahimi } else {
1117*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_update(&ctx,
1118*62c56f98SSadaf Ebrahimi ct_test_data[j * 6 + i],
1119*62c56f98SSadaf Ebrahimi pt_len_test_data[i],
1120*62c56f98SSadaf Ebrahimi buf, sizeof(buf), &olen);
1121*62c56f98SSadaf Ebrahimi if (ret != 0) {
1122*62c56f98SSadaf Ebrahimi goto exit;
1123*62c56f98SSadaf Ebrahimi }
1124*62c56f98SSadaf Ebrahimi if (olen != pt_len_test_data[i]) {
1125*62c56f98SSadaf Ebrahimi goto exit;
1126*62c56f98SSadaf Ebrahimi }
1127*62c56f98SSadaf Ebrahimi }
1128*62c56f98SSadaf Ebrahimi
1129*62c56f98SSadaf Ebrahimi ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
1130*62c56f98SSadaf Ebrahimi if (ret != 0) {
1131*62c56f98SSadaf Ebrahimi goto exit;
1132*62c56f98SSadaf Ebrahimi }
1133*62c56f98SSadaf Ebrahimi
1134*62c56f98SSadaf Ebrahimi if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
1135*62c56f98SSadaf Ebrahimi pt_len_test_data[i]) != 0 ||
1136*62c56f98SSadaf Ebrahimi memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
1137*62c56f98SSadaf Ebrahimi ret = 1;
1138*62c56f98SSadaf Ebrahimi goto exit;
1139*62c56f98SSadaf Ebrahimi }
1140*62c56f98SSadaf Ebrahimi
1141*62c56f98SSadaf Ebrahimi mbedtls_gcm_free(&ctx);
1142*62c56f98SSadaf Ebrahimi
1143*62c56f98SSadaf Ebrahimi if (verbose != 0) {
1144*62c56f98SSadaf Ebrahimi mbedtls_printf("passed\n");
1145*62c56f98SSadaf Ebrahimi }
1146*62c56f98SSadaf Ebrahimi }
1147*62c56f98SSadaf Ebrahimi }
1148*62c56f98SSadaf Ebrahimi
1149*62c56f98SSadaf Ebrahimi if (verbose != 0) {
1150*62c56f98SSadaf Ebrahimi mbedtls_printf("\n");
1151*62c56f98SSadaf Ebrahimi }
1152*62c56f98SSadaf Ebrahimi
1153*62c56f98SSadaf Ebrahimi ret = 0;
1154*62c56f98SSadaf Ebrahimi
1155*62c56f98SSadaf Ebrahimi exit:
1156*62c56f98SSadaf Ebrahimi if (ret != 0) {
1157*62c56f98SSadaf Ebrahimi if (verbose != 0) {
1158*62c56f98SSadaf Ebrahimi mbedtls_printf("failed\n");
1159*62c56f98SSadaf Ebrahimi }
1160*62c56f98SSadaf Ebrahimi mbedtls_gcm_free(&ctx);
1161*62c56f98SSadaf Ebrahimi }
1162*62c56f98SSadaf Ebrahimi
1163*62c56f98SSadaf Ebrahimi return ret;
1164*62c56f98SSadaf Ebrahimi }
1165*62c56f98SSadaf Ebrahimi
1166*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
1167*62c56f98SSadaf Ebrahimi
1168*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_GCM_C */
1169