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