xref: /aosp_15_r20/external/mbedtls/library/gcm.c (revision 62c56f9862f102b96d72393aff6076c951fb8148)
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