blob: 2bd907115ec571fff571c32b3622da2d898b794a [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * 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.
Paul Bakker89e80c92012-03-20 13:50:09 +000018 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010019
Paul Bakker89e80c92012-03-20 13:50:09 +000020/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010021 * 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.
Paul Bakker89e80c92012-03-20 13:50:09 +000028 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010029
Gilles Peskinedb09ef62020-06-03 01:43:33 +020030#include "common.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000033
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/gcm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050035#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000036#include "mbedtls/error.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_AESNI_C)
Chris Jones187782f2021-03-09 17:28:35 +000041#include "aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010042#endif
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +010045#include "mbedtls/aes.h"
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Ron Eldor9924bdc2018-10-04 10:59:13 +030047#if !defined(MBEDTLS_PLATFORM_C)
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_printf printf
50#endif /* MBEDTLS_PLATFORM_C */
51#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010052
Jaeden Amero15263302017-09-21 12:53:48 +010053#if !defined(MBEDTLS_GCM_ALT)
54
k-stachowiak8ffc92a2018-12-12 14:21:59 +010055/* Parameter validation macros */
56#define GCM_VALIDATE_RET( cond ) \
57 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT )
58#define GCM_VALIDATE( cond ) \
59 MBEDTLS_INTERNAL_VALIDATE( cond )
60
Paul Bakker89e80c92012-03-20 13:50:09 +000061/*
62 * 32-bit integer manipulation macros (big endian)
63 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000064#ifndef GET_UINT32_BE
65#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000066{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000067 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
68 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
69 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
70 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000071}
72#endif
73
Paul Bakker5c2364c2012-10-01 14:41:15 +000074#ifndef PUT_UINT32_BE
75#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000076{ \
77 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
78 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
79 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
80 (b)[(i) + 3] = (unsigned char) ( (n) ); \
81}
82#endif
83
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010084/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020085 * Initialize a context
86 */
87void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
88{
k-stachowiak8ffc92a2018-12-12 14:21:59 +010089 GCM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020090 memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
91}
92
93/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010094 * 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.
100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +0000102{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200103 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +0000104 uint64_t hi, lo;
105 uint64_t vl, vh;
106 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200107 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200108
Paul Bakker89e80c92012-03-20 13:50:09 +0000109 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200111 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000112
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100113 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000114 GET_UINT32_BE( hi, h, 0 );
115 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000116 vh = (uint64_t) hi << 32 | lo;
117
Paul Bakker5c2364c2012-10-01 14:41:15 +0000118 GET_UINT32_BE( hi, h, 8 );
119 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000120 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200121
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100122 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000123 ctx->HL[8] = vl;
124 ctx->HH[8] = vh;
125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100127 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100128 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100129 return( 0 );
130#endif
131
132 /* 0 corresponds to 0 in GF(2^128) */
133 ctx->HH[0] = 0;
134 ctx->HL[0] = 0;
135
Paul Bakker89e80c92012-03-20 13:50:09 +0000136 for( i = 4; i > 0; i >>= 1 )
137 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200138 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000139 vl = ( vh << 63 ) | ( vl >> 1 );
140 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
141
142 ctx->HL[i] = vl;
143 ctx->HH[i] = vh;
144 }
145
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000146 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000147 {
148 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
149 vh = *HiH;
150 vl = *HiL;
151 for( j = 1; j < i; j++ )
152 {
153 HiH[j] = vh ^ ctx->HH[j];
154 HiL[j] = vl ^ ctx->HL[j];
155 }
156 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200157
158 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000159}
160
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200161int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
162 mbedtls_cipher_id_t cipher,
163 const unsigned char *key,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200164 unsigned int keybits )
Paul Bakker89e80c92012-03-20 13:50:09 +0000165{
Janos Follath24eed8d2019-11-22 13:21:35 +0000166 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000168
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100169 GCM_VALIDATE_RET( ctx != NULL );
170 GCM_VALIDATE_RET( key != NULL );
171 GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 );
172
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500173 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
174 MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200175 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200177
Paul Bakkera0558e02013-09-10 14:25:51 +0200178 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200180
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200181 mbedtls_cipher_free( &ctx->cipher_ctx );
182
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200183 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000184 return( ret );
185
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200186 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200188 {
189 return( ret );
190 }
191
192 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
193 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000194
195 return( 0 );
196}
197
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100198/*
199 * Shoup's method for multiplication use this table with
200 * last4[x] = x times P^128
201 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
202 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000203static const uint64_t last4[16] =
204{
205 0x0000, 0x1c20, 0x3840, 0x2460,
206 0x7080, 0x6ca0, 0x48c0, 0x54e0,
207 0xe100, 0xfd20, 0xd940, 0xc560,
208 0x9180, 0x8da0, 0xa9c0, 0xb5e0
209};
210
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100211/*
212 * Sets output to x times H using the precomputed tables.
213 * x and output are seen as elements of GF(2^128) as in [MGV].
214 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200216 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000217{
218 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000219 unsigned char lo, hi, rem;
220 uint64_t zh, zl;
221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100223 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100224 unsigned char h[16];
225
226 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
227 PUT_UINT32_BE( ctx->HH[8], h, 4 );
228 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
229 PUT_UINT32_BE( ctx->HL[8], h, 12 );
230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100232 return;
233 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100235
Paul Bakker89e80c92012-03-20 13:50:09 +0000236 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000237
238 zh = ctx->HH[lo];
239 zl = ctx->HL[lo];
240
241 for( i = 15; i >= 0; i-- )
242 {
243 lo = x[i] & 0xf;
k-stachowiak67badb42019-10-22 13:25:06 +0200244 hi = ( x[i] >> 4 ) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000245
246 if( i != 15 )
247 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000248 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000249 zl = ( zh << 60 ) | ( zl >> 4 );
250 zh = ( zh >> 4 );
251 zh ^= (uint64_t) last4[rem] << 48;
252 zh ^= ctx->HH[lo];
253 zl ^= ctx->HL[lo];
254
255 }
256
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000257 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000258 zl = ( zh << 60 ) | ( zl >> 4 );
259 zh = ( zh >> 4 );
260 zh ^= (uint64_t) last4[rem] << 48;
261 zh ^= ctx->HH[hi];
262 zl ^= ctx->HL[hi];
263 }
264
Paul Bakker5c2364c2012-10-01 14:41:15 +0000265 PUT_UINT32_BE( zh >> 32, output, 0 );
266 PUT_UINT32_BE( zh, output, 4 );
267 PUT_UINT32_BE( zl >> 32, output, 8 );
268 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000269}
270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Gilles Peskine295fc132021-04-15 18:32:23 +0200272 int mode,
273 const unsigned char *iv, size_t iv_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000274{
Janos Follath24eed8d2019-11-22 13:21:35 +0000275 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000276 unsigned char work_buf[16];
277 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000278 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200279 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000280
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100281 GCM_VALIDATE_RET( ctx != NULL );
282 GCM_VALIDATE_RET( iv != NULL );
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100283
Gilles Peskine295fc132021-04-15 18:32:23 +0200284 /* IV is are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200285 /* IV is not allowed to be zero length */
Gilles Peskine295fc132021-04-15 18:32:23 +0200286 if( iv_len == 0 || (uint64_t) iv_len >> 61 != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200288
Paul Bakker52cf16c2013-07-26 13:55:38 +0200289 memset( ctx->y, 0x00, sizeof(ctx->y) );
290 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
291
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200292 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200293 ctx->len = 0;
294 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000295
296 if( iv_len == 12 )
297 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200298 memcpy( ctx->y, iv, iv_len );
299 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000300 }
301 else
302 {
303 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000304 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000305
306 p = iv;
307 while( iv_len > 0 )
308 {
309 use_len = ( iv_len < 16 ) ? iv_len : 16;
310
Paul Bakker67f9d532012-10-23 11:49:05 +0000311 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200312 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200313
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200314 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000315
316 iv_len -= use_len;
317 p += use_len;
318 }
319
Paul Bakker67f9d532012-10-23 11:49:05 +0000320 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200321 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000322
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200323 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000324 }
325
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500326 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16,
327 ctx->base_ectr, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200328 {
329 return( ret );
330 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000331
Gilles Peskine295fc132021-04-15 18:32:23 +0200332 return( 0 );
333}
334
335
336int mbedtls_gcm_update_ad( mbedtls_gcm_context *ctx,
337 const unsigned char *add, size_t add_len )
338{
339 const unsigned char *p;
340 size_t use_len, i;
341
342 GCM_VALIDATE_RET( add_len == 0 || add != NULL );
343
344 /* IV is are limited to 2^64 bits, so 2^61 bytes */
345 if( (uint64_t) add_len >> 61 != 0 )
346 return( MBEDTLS_ERR_GCM_BAD_INPUT );
347
348 /* Calling update_ad multiple times is not yet supported */
349 if( ctx->add_len != 0 )
350 return( MBEDTLS_ERR_GCM_BAD_INPUT );
351
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200352 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000353 p = add;
354 while( add_len > 0 )
355 {
356 use_len = ( add_len < 16 ) ? add_len : 16;
357
Paul Bakker67f9d532012-10-23 11:49:05 +0000358 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200359 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200360
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200361 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000362
363 add_len -= use_len;
364 p += use_len;
365 }
366
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200367 return( 0 );
368}
369
Gilles Peskine58fc2722021-04-13 15:58:27 +0200370/* Increment the counter. */
371static void gcm_incr( unsigned char y[16] )
372{
373 size_t i;
374 for( i = 16; i > 12; i-- )
375 if( ++y[i - 1] != 0 )
376 break;
377}
378
379/* Calculate and apply the encryption mask. Process use_len bytes of data,
380 * starting at position offset in the mask block. */
381static int gcm_mask( mbedtls_gcm_context *ctx,
382 unsigned char ectr[16],
383 size_t offset, size_t use_len,
384 const unsigned char *input,
385 unsigned char *output )
386{
387 size_t i;
388 size_t olen = 0;
389 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
390
391 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
392 &olen ) ) != 0 )
393 {
394 mbedtls_platform_zeroize( ectr, 16 );
395 return( ret );
396 }
397
398 for( i = 0; i < use_len; i++ )
399 {
400 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
401 ctx->buf[offset + i] ^= input[i];
402 output[i] = ectr[offset + i] ^ input[i];
403 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
404 ctx->buf[offset + i] ^= output[i];
405 }
406 return( 0 );
407}
408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Gilles Peskinea56c4482021-04-15 17:22:35 +0200410 const unsigned char *input, size_t input_length,
411 unsigned char *output, size_t output_size,
412 size_t *output_length )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200413{
Janos Follath24eed8d2019-11-22 13:21:35 +0000414 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200415 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200416 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200417 size_t offset;
418 unsigned char ectr[16];
419
Gilles Peskinea56c4482021-04-15 17:22:35 +0200420 if( output_size < input_length )
421 return( MBEDTLS_ERR_GCM_BAD_INPUT );
422 GCM_VALIDATE_RET( output_length != NULL );
423 *output_length = input_length;
424
425 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
426 * on a potentially null pointer. */
427 if( input_length == 0 )
Gilles Peskine58fc2722021-04-13 15:58:27 +0200428 return( 0 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200429
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100430 GCM_VALIDATE_RET( ctx != NULL );
Gilles Peskine58fc2722021-04-13 15:58:27 +0200431 GCM_VALIDATE_RET( input != NULL );
432 GCM_VALIDATE_RET( output != NULL );
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100433
Gilles Peskinea56c4482021-04-15 17:22:35 +0200434 if( output > input && (size_t) ( output - input ) < input_length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200436
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200437 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
438 * Also check for possible overflow */
Gilles Peskinea56c4482021-04-15 17:22:35 +0200439 if( ctx->len + input_length < ctx->len ||
440 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200441 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200443 }
444
Gilles Peskine58fc2722021-04-13 15:58:27 +0200445 offset = ctx->len % 16;
446 if( offset != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000447 {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200448 size_t use_len = 16 - offset;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200449 if( use_len > input_length )
450 use_len = input_length;
Paul Bakker89e80c92012-03-20 13:50:09 +0000451
Gilles Peskine58fc2722021-04-13 15:58:27 +0200452 if( ( ret = gcm_mask( ctx, ectr, offset, use_len, p, out_p ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200453 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000454
Gilles Peskine58fc2722021-04-13 15:58:27 +0200455 if( offset + use_len == 16 )
456 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200457
Gilles Peskine58fc2722021-04-13 15:58:27 +0200458 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200459 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000460 p += use_len;
461 out_p += use_len;
462 }
463
Gilles Peskinea56c4482021-04-15 17:22:35 +0200464 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200465
Gilles Peskinea56c4482021-04-15 17:22:35 +0200466 while( input_length >= 16 )
Gilles Peskine58fc2722021-04-13 15:58:27 +0200467 {
468 gcm_incr( ctx->y );
469 if( ( ret = gcm_mask( ctx, ectr, 0, 16, p, out_p ) ) != 0 )
470 return( ret );
471
472 gcm_mult( ctx, ctx->buf, ctx->buf );
473
Gilles Peskinea56c4482021-04-15 17:22:35 +0200474 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200475 p += 16;
476 out_p += 16;
477 }
478
Gilles Peskinea56c4482021-04-15 17:22:35 +0200479 if( input_length > 0 )
Gilles Peskine58fc2722021-04-13 15:58:27 +0200480 {
481 gcm_incr( ctx->y );
Gilles Peskinea56c4482021-04-15 17:22:35 +0200482 if( ( ret = gcm_mask( ctx, ectr, 0, input_length, p, out_p ) ) != 0 )
Gilles Peskine58fc2722021-04-13 15:58:27 +0200483 return( ret );
484 }
485
486 mbedtls_platform_zeroize( ectr, sizeof( ectr ) );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200487 return( 0 );
488}
489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200491 unsigned char *output, size_t output_size,
Gilles Peskine9461e452021-04-15 16:48:32 +0200492 unsigned char *tag, size_t tag_len )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200493{
494 unsigned char work_buf[16];
495 size_t i;
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100496 uint64_t orig_len;
497 uint64_t orig_add_len;
498
499 GCM_VALIDATE_RET( ctx != NULL );
500 GCM_VALIDATE_RET( tag != NULL );
501
Gilles Peskine9461e452021-04-15 16:48:32 +0200502 /* We never pass any output in finish(). The output parameter exists only
503 * for the sake of alternative implementations. */
504 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200505 (void) output_size;
Gilles Peskine9461e452021-04-15 16:48:32 +0200506
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100507 orig_len = ctx->len * 8;
508 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200509
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200510 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200512
Gilles Peskine58fc2722021-04-13 15:58:27 +0200513 if( ctx->len % 16 != 0 )
514 gcm_mult( ctx, ctx->buf, ctx->buf );
515
Andres AG821da842016-09-26 10:09:30 +0100516 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200517
Paul Bakker89e80c92012-03-20 13:50:09 +0000518 if( orig_len || orig_add_len )
519 {
520 memset( work_buf, 0x00, 16 );
521
Paul Bakker0ecdb232013-04-09 11:36:42 +0200522 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
523 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
524 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
525 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000526
Paul Bakker67f9d532012-10-23 11:49:05 +0000527 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200528 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000529
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200530 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000531
Paul Bakker67f9d532012-10-23 11:49:05 +0000532 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200533 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000534 }
535
536 return( 0 );
537}
538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200540 int mode,
541 size_t length,
542 const unsigned char *iv,
543 size_t iv_len,
544 const unsigned char *add,
545 size_t add_len,
546 const unsigned char *input,
547 unsigned char *output,
548 size_t tag_len,
549 unsigned char *tag )
550{
Janos Follath24eed8d2019-11-22 13:21:35 +0000551 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200552 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200553
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100554 GCM_VALIDATE_RET( ctx != NULL );
555 GCM_VALIDATE_RET( iv != NULL );
556 GCM_VALIDATE_RET( add_len == 0 || add != NULL );
557 GCM_VALIDATE_RET( length == 0 || input != NULL );
558 GCM_VALIDATE_RET( length == 0 || output != NULL );
559 GCM_VALIDATE_RET( tag != NULL );
560
Gilles Peskine295fc132021-04-15 18:32:23 +0200561 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len ) ) != 0 )
562 return( ret );
563
564 if( ( ret = mbedtls_gcm_update_ad( ctx, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200565 return( ret );
566
Gilles Peskinea56c4482021-04-15 17:22:35 +0200567 if( ( ret = mbedtls_gcm_update( ctx, input, length,
568 output, length, &olen ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200569 return( ret );
570
Gilles Peskine9461e452021-04-15 16:48:32 +0200571 if( ( ret = mbedtls_gcm_finish( ctx, NULL, 0, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200572 return( ret );
573
574 return( 0 );
575}
576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000578 size_t length,
579 const unsigned char *iv,
580 size_t iv_len,
581 const unsigned char *add,
582 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200583 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000584 size_t tag_len,
585 const unsigned char *input,
586 unsigned char *output )
587{
Janos Follath24eed8d2019-11-22 13:21:35 +0000588 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000589 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200590 size_t i;
591 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000592
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100593 GCM_VALIDATE_RET( ctx != NULL );
594 GCM_VALIDATE_RET( iv != NULL );
595 GCM_VALIDATE_RET( add_len == 0 || add != NULL );
596 GCM_VALIDATE_RET( tag != NULL );
597 GCM_VALIDATE_RET( length == 0 || input != NULL );
598 GCM_VALIDATE_RET( length == 0 || output != NULL );
599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100601 iv, iv_len, add, add_len,
602 input, output, tag_len, check_tag ) ) != 0 )
603 {
604 return( ret );
605 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000606
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200607 /* Check tag in "constant-time" */
608 for( diff = 0, i = 0; i < tag_len; i++ )
609 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000610
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200611 if( diff != 0 )
612 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500613 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200615 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000616
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200617 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000618}
619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200621{
k-stachowiak21298a22018-12-13 17:11:58 +0100622 if( ctx == NULL )
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100623 return;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624 mbedtls_cipher_free( &ctx->cipher_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500625 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200626}
627
Jaeden Amero15263302017-09-21 12:53:48 +0100628#endif /* !MBEDTLS_GCM_ALT */
629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000631/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200632 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000633 *
634 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
635 */
636#define MAX_TESTS 6
637
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100638static const int key_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000639 { 0, 0, 1, 1, 1, 1 };
640
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100641static const unsigned char key_test_data[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000642{
643 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
647 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
648 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
649 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200650 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000651};
652
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100653static const size_t iv_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 { 12, 12, 12, 12, 8, 60 };
655
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100656static const int iv_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000657 { 0, 0, 1, 1, 1, 2 };
658
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100659static const unsigned char iv_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000660{
661 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
662 0x00, 0x00, 0x00, 0x00 },
663 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
664 0xde, 0xca, 0xf8, 0x88 },
665 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200666 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000667 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200668 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000669 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200670 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000671 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200672 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000673};
674
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100675static const size_t add_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000676 { 0, 0, 0, 20, 20, 20 };
677
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100678static const int add_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000679 { 0, 0, 0, 1, 1, 1 };
680
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100681static const unsigned char additional_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000682{
683 { 0x00 },
684 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200685 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000686 0xab, 0xad, 0xda, 0xd2 },
687};
688
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100689static const size_t pt_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000690 { 0, 16, 64, 60, 60, 60 };
691
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100692static const int pt_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 { 0, 0, 1, 1, 1, 1 };
694
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100695static const unsigned char pt_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000696{
697 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
699 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
700 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
701 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
702 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
703 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
704 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
705 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
706 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
707};
708
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100709static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000710{
711 { 0x00 },
712 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
713 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
714 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200715 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000716 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200717 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000718 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200719 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000720 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
721 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
722 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200723 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000724 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200725 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000726 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200727 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000728 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
729 0x3d, 0x58, 0xe0, 0x91 },
730 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200731 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000732 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200733 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000734 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200735 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000736 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
737 0xc2, 0x3f, 0x45, 0x98 },
738 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200739 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000740 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200741 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000742 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200743 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000744 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
745 0x4c, 0x34, 0xae, 0xe5 },
746 { 0x00 },
747 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200748 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000749 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200750 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000751 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200752 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000753 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200754 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000755 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
756 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
757 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200758 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000759 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200760 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
761 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
762 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000763 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200764 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000765 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200766 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000767 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200768 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000769 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200770 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000771 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200772 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000773 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200774 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000775 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200776 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000777 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200778 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000779 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200780 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000781 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200782 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
783 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
784 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
785 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
786 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
787 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
788 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
789 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
790 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
791 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
792 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
793 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
794 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
795 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
796 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
797 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
798 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
799 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000800 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200801 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000802 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200803 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000804 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200805 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000806 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200807 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000808 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200809 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000810 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200811 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000812 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200813 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000814 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200815 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000816};
817
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100818static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000819{
820 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
821 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
822 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
823 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
824 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200825 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000826 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
827 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
828 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
829 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
830 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
831 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
832 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
833 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
834 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200835 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000836 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
837 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
838 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200839 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000840 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200841 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000842 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200843 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000844 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200845 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000846 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200847 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000848 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200849 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000850 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200851 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000852 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200853 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000854 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200855 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000856};
857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000859{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000861 unsigned char buf[64];
862 unsigned char tag_buf[16];
863 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200865 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +0000866
867 for( j = 0; j < 3; j++ )
868 {
869 int key_len = 128 + 64 * j;
870
871 for( i = 0; i < MAX_TESTS; i++ )
872 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100873 mbedtls_gcm_init( &ctx );
874
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200875 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100877 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200878
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500879 ret = mbedtls_gcm_setkey( &ctx, cipher,
880 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100881 key_len );
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100882 /*
883 * AES-192 is an optional feature that may be unavailable when
884 * there is an alternative underlying implementation i.e. when
885 * MBEDTLS_AES_ALT is defined.
886 */
Ron Eldor9924bdc2018-10-04 10:59:13 +0300887 if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100888 {
889 mbedtls_printf( "skipped\n" );
890 break;
891 }
892 else if( ret != 0 )
893 {
894 goto exit;
895 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000896
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200897 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500898 pt_len_test_data[i],
899 iv_test_data[iv_index_test_data[i]],
900 iv_len_test_data[i],
901 additional_test_data[add_index_test_data[i]],
902 add_len_test_data[i],
903 pt_test_data[pt_index_test_data[i]],
904 buf, 16, tag_buf );
Steven Cooreman2222d682021-01-11 18:45:22 +0100905#if defined(MBEDTLS_GCM_ALT)
906 /* Allow alternative implementations to only support 12-byte nonces. */
907 if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
908 iv_len_test_data[i] != 12 )
909 {
910 mbedtls_printf( "skipped\n" );
911 break;
912 }
913#endif /* defined(MBEDTLS_GCM_ALT) */
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100914 if( ret != 0 )
915 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000916
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500917 if ( memcmp( buf, ct_test_data[j * 6 + i],
918 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100919 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000920 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100921 ret = 1;
922 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000923 }
924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200926
Paul Bakker89e80c92012-03-20 13:50:09 +0000927 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000929
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100930 mbedtls_gcm_init( &ctx );
931
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200932 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100934 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200935
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500936 ret = mbedtls_gcm_setkey( &ctx, cipher,
937 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100938 key_len );
939 if( ret != 0 )
940 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000941
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200942 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500943 pt_len_test_data[i],
944 iv_test_data[iv_index_test_data[i]],
945 iv_len_test_data[i],
946 additional_test_data[add_index_test_data[i]],
947 add_len_test_data[i],
948 ct_test_data[j * 6 + i], buf, 16, tag_buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000949
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100950 if( ret != 0 )
951 goto exit;
952
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100953 if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
954 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100955 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000956 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100957 ret = 1;
958 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000959 }
960
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200961 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200962
Paul Bakker89e80c92012-03-20 13:50:09 +0000963 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200965
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100966 mbedtls_gcm_init( &ctx );
967
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200968 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100970 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200971
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500972 ret = mbedtls_gcm_setkey( &ctx, cipher,
973 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100974 key_len );
975 if( ret != 0 )
976 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200977
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200978 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Gilles Peskine295fc132021-04-15 18:32:23 +0200979 iv_test_data[iv_index_test_data[i]],
980 iv_len_test_data[i] );
981 if( ret != 0 )
982 goto exit;
983
984 ret = mbedtls_gcm_update_ad( &ctx,
985 additional_test_data[add_index_test_data[i]],
986 add_len_test_data[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200987 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100988 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200989
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100990 if( pt_len_test_data[i] > 32 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200991 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100992 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200993 ret = mbedtls_gcm_update( &ctx,
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100994 pt_test_data[pt_index_test_data[i]],
Gilles Peskinea56c4482021-04-15 17:22:35 +0200995 32,
996 buf, sizeof( buf ), &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200997 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100998 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200999 if( olen != 32 )
1000 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001001
Gilles Peskinea56c4482021-04-15 17:22:35 +02001002 ret = mbedtls_gcm_update( &ctx,
1003 pt_test_data[pt_index_test_data[i]] + 32,
1004 rest_len,
1005 buf + 32, sizeof( buf ) - 32, &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001006 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001007 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001008 if( olen != rest_len )
1009 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001010 }
1011 else
1012 {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001013 ret = mbedtls_gcm_update( &ctx,
Andrzej Kurekee3c4352019-01-10 03:10:02 -05001014 pt_test_data[pt_index_test_data[i]],
Gilles Peskinea56c4482021-04-15 17:22:35 +02001015 pt_len_test_data[i],
1016 buf, sizeof( buf ), &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001017 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001018 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001019 if( olen != pt_len_test_data[i] )
1020 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001021 }
1022
Gilles Peskine9461e452021-04-15 16:48:32 +02001023 ret = mbedtls_gcm_finish( &ctx, NULL, 0, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001024 if( ret != 0 )
1025 goto exit;
1026
Andrzej Kurekee3c4352019-01-10 03:10:02 -05001027 if( memcmp( buf, ct_test_data[j * 6 + i],
1028 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +01001029 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001030 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001031 ret = 1;
1032 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001033 }
1034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001036
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001037 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001038 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001039
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001040 mbedtls_gcm_init( &ctx );
1041
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001042 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001043 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001044 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001045
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001046 ret = mbedtls_gcm_setkey( &ctx, cipher,
1047 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001048 key_len );
1049 if( ret != 0 )
1050 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Gilles Peskine295fc132021-04-15 18:32:23 +02001053 iv_test_data[iv_index_test_data[i]],
1054 iv_len_test_data[i] );
1055 if( ret != 0 )
1056 goto exit;
1057 ret = mbedtls_gcm_update_ad( &ctx,
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001058 additional_test_data[add_index_test_data[i]],
1059 add_len_test_data[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001060 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001061 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001062
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001063 if( pt_len_test_data[i] > 32 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001064 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001065 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001066 ret = mbedtls_gcm_update( &ctx,
1067 ct_test_data[j * 6 + i], 32,
1068 buf, sizeof( buf ), &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001069 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001070 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001071 if( olen != 32 )
1072 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001073
Gilles Peskinea56c4482021-04-15 17:22:35 +02001074 ret = mbedtls_gcm_update( &ctx,
Andrzej Kurekee3c4352019-01-10 03:10:02 -05001075 ct_test_data[j * 6 + i] + 32,
Gilles Peskinea56c4482021-04-15 17:22:35 +02001076 rest_len,
1077 buf + 32, sizeof( buf ) - 32, &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001078 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001079 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001080 if( olen != rest_len )
1081 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001082 }
1083 else
1084 {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001085 ret = mbedtls_gcm_update( &ctx,
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001086 ct_test_data[j * 6 + i],
Gilles Peskinea56c4482021-04-15 17:22:35 +02001087 pt_len_test_data[i],
1088 buf, sizeof( buf ), &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001089 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001090 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001091 if( olen != pt_len_test_data[i] )
1092 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001093 }
1094
Gilles Peskine9461e452021-04-15 16:48:32 +02001095 ret = mbedtls_gcm_finish( &ctx, NULL, 0, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001096 if( ret != 0 )
1097 goto exit;
1098
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001099 if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
1100 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +01001101 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001102 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001103 ret = 1;
1104 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001105 }
1106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001108
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001109 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001110 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +00001111 }
1112 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001113
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001114 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +00001116
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001117 ret = 0;
1118
1119exit:
1120 if( ret != 0 )
1121 {
1122 if( verbose != 0 )
1123 mbedtls_printf( "failed\n" );
1124 mbedtls_gcm_free( &ctx );
1125 }
1126
1127 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +00001128}
1129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001132#endif /* MBEDTLS_GCM_C */