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