2 * NIST SP800-38D compliant GCM implementation
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * This file is part of mbed TLS (https://tls.mbed.org)
23 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
26 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
28 * We use the algorithm described as Shoup's method with 4-bit tables in
29 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
32 #if !defined(MBEDTLS_CONFIG_FILE)
33 #include "mbedtls/config.h"
35 #include MBEDTLS_CONFIG_FILE
38 #if defined(MBEDTLS_GCM_C)
40 #include "mbedtls/gcm.h"
44 #if defined(MBEDTLS_AESNI_C)
45 #include "mbedtls/aesni.h"
48 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
49 #if defined(MBEDTLS_PLATFORM_C)
50 #include "mbedtls/platform.h"
53 #define mbedtls_printf printf
54 #endif /* MBEDTLS_PLATFORM_C */
55 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
58 * 32-bit integer manipulation macros (big endian)
61 #define GET_UINT32_BE(n,b,i) \
63 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
64 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
65 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
66 | ( (uint32_t) (b)[(i) + 3] ); \
71 #define PUT_UINT32_BE(n,b,i) \
73 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
74 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
75 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
76 (b)[(i) + 3] = (unsigned char) ( (n) ); \
80 /* Implementation that should never be optimized out by the compiler */
81 static void mbedtls_zeroize( void *v
, size_t n
) {
82 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
86 * Initialize a context
88 void mbedtls_gcm_init( mbedtls_gcm_context
*ctx
)
90 memset( ctx
, 0, sizeof( mbedtls_gcm_context
) );
94 * Precompute small multiples of H, that is set
95 * HH[i] || HL[i] = H times i,
96 * where i is seen as a field element as in [MGV], ie high-order bits
97 * correspond to low powers of P. The result is stored in the same way, that
98 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
99 * corresponds to P^127.
101 static int gcm_gen_table( mbedtls_gcm_context
*ctx
)
110 if( ( ret
= mbedtls_cipher_update( &ctx
->cipher_ctx
, h
, 16, h
, &olen
) ) != 0 )
113 /* pack h as two 64-bits ints, big-endian */
114 GET_UINT32_BE( hi
, h
, 0 );
115 GET_UINT32_BE( lo
, h
, 4 );
116 vh
= (uint64_t) hi
<< 32 | lo
;
118 GET_UINT32_BE( hi
, h
, 8 );
119 GET_UINT32_BE( lo
, h
, 12 );
120 vl
= (uint64_t) hi
<< 32 | lo
;
122 /* 8 = 1000 corresponds to 1 in GF(2^128) */
126 #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
127 /* With CLMUL support, we need only h, not the rest of the table */
128 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL
) )
132 /* 0 corresponds to 0 in GF(2^128) */
136 for( i
= 4; i
> 0; i
>>= 1 )
138 uint32_t T
= ( vl
& 1 ) * 0xe1000000U
;
139 vl
= ( vh
<< 63 ) | ( vl
>> 1 );
140 vh
= ( vh
>> 1 ) ^ ( (uint64_t) T
<< 32);
146 for( i
= 2; i
<= 8; i
*= 2 )
148 uint64_t *HiL
= ctx
->HL
+ i
, *HiH
= ctx
->HH
+ i
;
151 for( j
= 1; j
< i
; j
++ )
153 HiH
[j
] = vh
^ ctx
->HH
[j
];
154 HiL
[j
] = vl
^ ctx
->HL
[j
];
161 int mbedtls_gcm_setkey( mbedtls_gcm_context
*ctx
,
162 mbedtls_cipher_id_t cipher
,
163 const unsigned char *key
,
164 unsigned int keybits
)
167 const mbedtls_cipher_info_t
*cipher_info
;
169 cipher_info
= mbedtls_cipher_info_from_values( cipher
, keybits
, MBEDTLS_MODE_ECB
);
170 if( cipher_info
== NULL
)
171 return( MBEDTLS_ERR_GCM_BAD_INPUT
);
173 if( cipher_info
->block_size
!= 16 )
174 return( MBEDTLS_ERR_GCM_BAD_INPUT
);
176 mbedtls_cipher_free( &ctx
->cipher_ctx
);
178 if( ( ret
= mbedtls_cipher_setup( &ctx
->cipher_ctx
, cipher_info
) ) != 0 )
181 if( ( ret
= mbedtls_cipher_setkey( &ctx
->cipher_ctx
, key
, keybits
,
182 MBEDTLS_ENCRYPT
) ) != 0 )
187 if( ( ret
= gcm_gen_table( ctx
) ) != 0 )
194 * Shoup's method for multiplication use this table with
195 * last4[x] = x times P^128
196 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
198 static const uint64_t last4
[16] =
200 0x0000, 0x1c20, 0x3840, 0x2460,
201 0x7080, 0x6ca0, 0x48c0, 0x54e0,
202 0xe100, 0xfd20, 0xd940, 0xc560,
203 0x9180, 0x8da0, 0xa9c0, 0xb5e0
207 * Sets output to x times H using the precomputed tables.
208 * x and output are seen as elements of GF(2^128) as in [MGV].
210 static void gcm_mult( mbedtls_gcm_context
*ctx
, const unsigned char x
[16],
211 unsigned char output
[16] )
214 unsigned char lo
, hi
, rem
;
217 #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
218 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL
) ) {
221 PUT_UINT32_BE( ctx
->HH
[8] >> 32, h
, 0 );
222 PUT_UINT32_BE( ctx
->HH
[8], h
, 4 );
223 PUT_UINT32_BE( ctx
->HL
[8] >> 32, h
, 8 );
224 PUT_UINT32_BE( ctx
->HL
[8], h
, 12 );
226 mbedtls_aesni_gcm_mult( output
, x
, h
);
229 #endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
236 for( i
= 15; i
>= 0; i
-- )
243 rem
= (unsigned char) zl
& 0xf;
244 zl
= ( zh
<< 60 ) | ( zl
>> 4 );
246 zh
^= (uint64_t) last4
[rem
] << 48;
252 rem
= (unsigned char) zl
& 0xf;
253 zl
= ( zh
<< 60 ) | ( zl
>> 4 );
255 zh
^= (uint64_t) last4
[rem
] << 48;
260 PUT_UINT32_BE( zh
>> 32, output
, 0 );
261 PUT_UINT32_BE( zh
, output
, 4 );
262 PUT_UINT32_BE( zl
>> 32, output
, 8 );
263 PUT_UINT32_BE( zl
, output
, 12 );
266 int mbedtls_gcm_starts( mbedtls_gcm_context
*ctx
,
268 const unsigned char *iv
,
270 const unsigned char *add
,
274 unsigned char work_buf
[16];
276 const unsigned char *p
;
277 size_t use_len
, olen
= 0;
279 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
280 if( ( (uint64_t) iv_len
) >> 61 != 0 ||
281 ( (uint64_t) add_len
) >> 61 != 0 )
283 return( MBEDTLS_ERR_GCM_BAD_INPUT
);
286 memset( ctx
->y
, 0x00, sizeof(ctx
->y
) );
287 memset( ctx
->buf
, 0x00, sizeof(ctx
->buf
) );
295 memcpy( ctx
->y
, iv
, iv_len
);
300 memset( work_buf
, 0x00, 16 );
301 PUT_UINT32_BE( iv_len
* 8, work_buf
, 12 );
306 use_len
= ( iv_len
< 16 ) ? iv_len
: 16;
308 for( i
= 0; i
< use_len
; i
++ )
311 gcm_mult( ctx
, ctx
->y
, ctx
->y
);
317 for( i
= 0; i
< 16; i
++ )
318 ctx
->y
[i
] ^= work_buf
[i
];
320 gcm_mult( ctx
, ctx
->y
, ctx
->y
);
323 if( ( ret
= mbedtls_cipher_update( &ctx
->cipher_ctx
, ctx
->y
, 16, ctx
->base_ectr
,
329 ctx
->add_len
= add_len
;
333 use_len
= ( add_len
< 16 ) ? add_len
: 16;
335 for( i
= 0; i
< use_len
; i
++ )
338 gcm_mult( ctx
, ctx
->buf
, ctx
->buf
);
347 int mbedtls_gcm_update( mbedtls_gcm_context
*ctx
,
349 const unsigned char *input
,
350 unsigned char *output
)
353 unsigned char ectr
[16];
355 const unsigned char *p
;
356 unsigned char *out_p
= output
;
357 size_t use_len
, olen
= 0;
359 if( output
> input
&& (size_t) ( output
- input
) < length
)
360 return( MBEDTLS_ERR_GCM_BAD_INPUT
);
362 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
363 * Also check for possible overflow */
364 if( ctx
->len
+ length
< ctx
->len
||
365 (uint64_t) ctx
->len
+ length
> 0xFFFFFFFE0ull
)
367 return( MBEDTLS_ERR_GCM_BAD_INPUT
);
375 use_len
= ( length
< 16 ) ? length
: 16;
377 for( i
= 16; i
> 12; i
-- )
378 if( ++ctx
->y
[i
- 1] != 0 )
381 if( ( ret
= mbedtls_cipher_update( &ctx
->cipher_ctx
, ctx
->y
, 16, ectr
,
387 for( i
= 0; i
< use_len
; i
++ )
389 if( ctx
->mode
== MBEDTLS_GCM_DECRYPT
)
391 out_p
[i
] = ectr
[i
] ^ p
[i
];
392 if( ctx
->mode
== MBEDTLS_GCM_ENCRYPT
)
393 ctx
->buf
[i
] ^= out_p
[i
];
396 gcm_mult( ctx
, ctx
->buf
, ctx
->buf
);
406 int mbedtls_gcm_finish( mbedtls_gcm_context
*ctx
,
410 unsigned char work_buf
[16];
412 uint64_t orig_len
= ctx
->len
* 8;
413 uint64_t orig_add_len
= ctx
->add_len
* 8;
415 if( tag_len
> 16 || tag_len
< 4 )
416 return( MBEDTLS_ERR_GCM_BAD_INPUT
);
419 memcpy( tag
, ctx
->base_ectr
, tag_len
);
421 if( orig_len
|| orig_add_len
)
423 memset( work_buf
, 0x00, 16 );
425 PUT_UINT32_BE( ( orig_add_len
>> 32 ), work_buf
, 0 );
426 PUT_UINT32_BE( ( orig_add_len
), work_buf
, 4 );
427 PUT_UINT32_BE( ( orig_len
>> 32 ), work_buf
, 8 );
428 PUT_UINT32_BE( ( orig_len
), work_buf
, 12 );
430 for( i
= 0; i
< 16; i
++ )
431 ctx
->buf
[i
] ^= work_buf
[i
];
433 gcm_mult( ctx
, ctx
->buf
, ctx
->buf
);
435 for( i
= 0; i
< tag_len
; i
++ )
436 tag
[i
] ^= ctx
->buf
[i
];
442 int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context
*ctx
,
445 const unsigned char *iv
,
447 const unsigned char *add
,
449 const unsigned char *input
,
450 unsigned char *output
,
456 if( ( ret
= mbedtls_gcm_starts( ctx
, mode
, iv
, iv_len
, add
, add_len
) ) != 0 )
459 if( ( ret
= mbedtls_gcm_update( ctx
, length
, input
, output
) ) != 0 )
462 if( ( ret
= mbedtls_gcm_finish( ctx
, tag
, tag_len
) ) != 0 )
468 int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context
*ctx
,
470 const unsigned char *iv
,
472 const unsigned char *add
,
474 const unsigned char *tag
,
476 const unsigned char *input
,
477 unsigned char *output
)
480 unsigned char check_tag
[16];
484 if( ( ret
= mbedtls_gcm_crypt_and_tag( ctx
, MBEDTLS_GCM_DECRYPT
, length
,
485 iv
, iv_len
, add
, add_len
,
486 input
, output
, tag_len
, check_tag
) ) != 0 )
491 /* Check tag in "constant-time" */
492 for( diff
= 0, i
= 0; i
< tag_len
; i
++ )
493 diff
|= tag
[i
] ^ check_tag
[i
];
497 mbedtls_zeroize( output
, length
);
498 return( MBEDTLS_ERR_GCM_AUTH_FAILED
);
504 void mbedtls_gcm_free( mbedtls_gcm_context
*ctx
)
506 mbedtls_cipher_free( &ctx
->cipher_ctx
);
507 mbedtls_zeroize( ctx
, sizeof( mbedtls_gcm_context
) );
510 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
512 * AES-GCM test vectors from:
514 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
518 static const int key_index
[MAX_TESTS
] =
519 { 0, 0, 1, 1, 1, 1 };
521 static const unsigned char key
[MAX_TESTS
][32] =
523 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
527 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
528 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
529 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
530 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
533 static const size_t iv_len
[MAX_TESTS
] =
534 { 12, 12, 12, 12, 8, 60 };
536 static const int iv_index
[MAX_TESTS
] =
537 { 0, 0, 1, 1, 1, 2 };
539 static const unsigned char iv
[MAX_TESTS
][64] =
541 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00 },
543 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
544 0xde, 0xca, 0xf8, 0x88 },
545 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
546 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
547 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
548 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
549 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
550 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
551 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
552 0xa6, 0x37, 0xb3, 0x9b },
555 static const size_t add_len
[MAX_TESTS
] =
556 { 0, 0, 0, 20, 20, 20 };
558 static const int add_index
[MAX_TESTS
] =
559 { 0, 0, 0, 1, 1, 1 };
561 static const unsigned char additional
[MAX_TESTS
][64] =
564 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
565 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
566 0xab, 0xad, 0xda, 0xd2 },
569 static const size_t pt_len
[MAX_TESTS
] =
570 { 0, 16, 64, 60, 60, 60 };
572 static const int pt_index
[MAX_TESTS
] =
573 { 0, 0, 1, 1, 1, 1 };
575 static const unsigned char pt
[MAX_TESTS
][64] =
577 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
579 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
580 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
581 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
582 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
583 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
584 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
585 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
586 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
589 static const unsigned char ct
[MAX_TESTS
* 3][64] =
592 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
593 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
594 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
595 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
596 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
597 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
598 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
599 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
600 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
601 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
602 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
603 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
604 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
605 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
606 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
607 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
608 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
609 0x3d, 0x58, 0xe0, 0x91 },
610 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
611 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
612 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
613 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
614 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
615 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
616 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
617 0xc2, 0x3f, 0x45, 0x98 },
618 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
619 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
620 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
621 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
622 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
623 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
624 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
625 0x4c, 0x34, 0xae, 0xe5 },
627 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
628 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
629 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
630 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
631 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
632 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
633 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
634 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
635 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
636 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
637 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
638 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
639 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
640 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
641 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
642 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
643 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
644 0xcc, 0xda, 0x27, 0x10 },
645 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
646 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
647 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
648 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
649 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
650 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
651 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
652 0xa0, 0xf0, 0x62, 0xf7 },
653 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
654 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
655 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
656 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
657 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
658 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
659 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
660 0xe9, 0xb7, 0x37, 0x3b },
662 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
663 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
664 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
665 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
666 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
667 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
668 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
669 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
670 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
671 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
672 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
673 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
674 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
675 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
676 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
677 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
678 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
679 0xbc, 0xc9, 0xf6, 0x62 },
680 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
681 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
682 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
683 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
684 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
685 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
686 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
687 0xf4, 0x7c, 0x9b, 0x1f },
688 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
689 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
690 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
691 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
692 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
693 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
694 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
695 0x44, 0xae, 0x7e, 0x3f },
698 static const unsigned char tag
[MAX_TESTS
* 3][16] =
700 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
701 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
702 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
703 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
704 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
705 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
706 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
707 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
708 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
709 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
710 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
711 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
712 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
713 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
714 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
715 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
716 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
717 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
718 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
719 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
720 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
721 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
722 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
723 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
724 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
725 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
726 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
727 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
728 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
729 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
730 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
731 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
732 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
733 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
734 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
735 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
738 int mbedtls_gcm_self_test( int verbose
)
740 mbedtls_gcm_context ctx
;
741 unsigned char buf
[64];
742 unsigned char tag_buf
[16];
744 mbedtls_cipher_id_t cipher
= MBEDTLS_CIPHER_ID_AES
;
746 mbedtls_gcm_init( &ctx
);
748 for( j
= 0; j
< 3; j
++ )
750 int key_len
= 128 + 64 * j
;
752 for( i
= 0; i
< MAX_TESTS
; i
++ )
755 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
758 mbedtls_gcm_setkey( &ctx
, cipher
, key
[key_index
[i
]], key_len
);
760 ret
= mbedtls_gcm_crypt_and_tag( &ctx
, MBEDTLS_GCM_ENCRYPT
,
762 iv
[iv_index
[i
]], iv_len
[i
],
763 additional
[add_index
[i
]], add_len
[i
],
764 pt
[pt_index
[i
]], buf
, 16, tag_buf
);
767 memcmp( buf
, ct
[j
* 6 + i
], pt_len
[i
] ) != 0 ||
768 memcmp( tag_buf
, tag
[j
* 6 + i
], 16 ) != 0 )
771 mbedtls_printf( "failed\n" );
776 mbedtls_gcm_free( &ctx
);
779 mbedtls_printf( "passed\n" );
782 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
785 mbedtls_gcm_setkey( &ctx
, cipher
, key
[key_index
[i
]], key_len
);
787 ret
= mbedtls_gcm_crypt_and_tag( &ctx
, MBEDTLS_GCM_DECRYPT
,
789 iv
[iv_index
[i
]], iv_len
[i
],
790 additional
[add_index
[i
]], add_len
[i
],
791 ct
[j
* 6 + i
], buf
, 16, tag_buf
);
794 memcmp( buf
, pt
[pt_index
[i
]], pt_len
[i
] ) != 0 ||
795 memcmp( tag_buf
, tag
[j
* 6 + i
], 16 ) != 0 )
798 mbedtls_printf( "failed\n" );
803 mbedtls_gcm_free( &ctx
);
806 mbedtls_printf( "passed\n" );
809 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
812 mbedtls_gcm_setkey( &ctx
, cipher
, key
[key_index
[i
]], key_len
);
814 ret
= mbedtls_gcm_starts( &ctx
, MBEDTLS_GCM_ENCRYPT
,
815 iv
[iv_index
[i
]], iv_len
[i
],
816 additional
[add_index
[i
]], add_len
[i
] );
820 mbedtls_printf( "failed\n" );
827 size_t rest_len
= pt_len
[i
] - 32;
828 ret
= mbedtls_gcm_update( &ctx
, 32, pt
[pt_index
[i
]], buf
);
832 mbedtls_printf( "failed\n" );
837 ret
= mbedtls_gcm_update( &ctx
, rest_len
, pt
[pt_index
[i
]] + 32,
842 mbedtls_printf( "failed\n" );
849 ret
= mbedtls_gcm_update( &ctx
, pt_len
[i
], pt
[pt_index
[i
]], buf
);
853 mbedtls_printf( "failed\n" );
859 ret
= mbedtls_gcm_finish( &ctx
, tag_buf
, 16 );
861 memcmp( buf
, ct
[j
* 6 + i
], pt_len
[i
] ) != 0 ||
862 memcmp( tag_buf
, tag
[j
* 6 + i
], 16 ) != 0 )
865 mbedtls_printf( "failed\n" );
870 mbedtls_gcm_free( &ctx
);
873 mbedtls_printf( "passed\n" );
876 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
879 mbedtls_gcm_setkey( &ctx
, cipher
, key
[key_index
[i
]], key_len
);
881 ret
= mbedtls_gcm_starts( &ctx
, MBEDTLS_GCM_DECRYPT
,
882 iv
[iv_index
[i
]], iv_len
[i
],
883 additional
[add_index
[i
]], add_len
[i
] );
887 mbedtls_printf( "failed\n" );
894 size_t rest_len
= pt_len
[i
] - 32;
895 ret
= mbedtls_gcm_update( &ctx
, 32, ct
[j
* 6 + i
], buf
);
899 mbedtls_printf( "failed\n" );
904 ret
= mbedtls_gcm_update( &ctx
, rest_len
, ct
[j
* 6 + i
] + 32,
909 mbedtls_printf( "failed\n" );
916 ret
= mbedtls_gcm_update( &ctx
, pt_len
[i
], ct
[j
* 6 + i
], buf
);
920 mbedtls_printf( "failed\n" );
926 ret
= mbedtls_gcm_finish( &ctx
, tag_buf
, 16 );
928 memcmp( buf
, pt
[pt_index
[i
]], pt_len
[i
] ) != 0 ||
929 memcmp( tag_buf
, tag
[j
* 6 + i
], 16 ) != 0 )
932 mbedtls_printf( "failed\n" );
937 mbedtls_gcm_free( &ctx
);
940 mbedtls_printf( "passed\n" );
946 mbedtls_printf( "\n" );
951 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
953 #endif /* MBEDTLS_GCM_C */