blob: de766bc764ad8297670c9c7a5418baeed7eb2894 [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,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200272 int mode,
273 const unsigned char *iv,
274 size_t iv_len,
275 const unsigned char *add,
276 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000277{
Janos Follath24eed8d2019-11-22 13:21:35 +0000278 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000279 unsigned char work_buf[16];
280 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000281 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200282 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000283
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100284 GCM_VALIDATE_RET( ctx != NULL );
285 GCM_VALIDATE_RET( iv != NULL );
286 GCM_VALIDATE_RET( add_len == 0 || add != NULL );
287
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200288 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200289 /* IV is not allowed to be zero length */
290 if( iv_len == 0 ||
291 ( (uint64_t) iv_len ) >> 61 != 0 ||
292 ( (uint64_t) add_len ) >> 61 != 0 )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200293 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200295 }
296
Paul Bakker52cf16c2013-07-26 13:55:38 +0200297 memset( ctx->y, 0x00, sizeof(ctx->y) );
298 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
299
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200300 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200301 ctx->len = 0;
302 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000303
304 if( iv_len == 12 )
305 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200306 memcpy( ctx->y, iv, iv_len );
307 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000308 }
309 else
310 {
311 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000312 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000313
314 p = iv;
315 while( iv_len > 0 )
316 {
317 use_len = ( iv_len < 16 ) ? iv_len : 16;
318
Paul Bakker67f9d532012-10-23 11:49:05 +0000319 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200320 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200321
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200322 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000323
324 iv_len -= use_len;
325 p += use_len;
326 }
327
Paul Bakker67f9d532012-10-23 11:49:05 +0000328 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200329 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000330
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200331 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000332 }
333
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500334 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16,
335 ctx->base_ectr, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200336 {
337 return( ret );
338 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000339
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200340 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000341 p = add;
342 while( add_len > 0 )
343 {
344 use_len = ( add_len < 16 ) ? add_len : 16;
345
Paul Bakker67f9d532012-10-23 11:49:05 +0000346 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200347 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200348
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200349 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000350
351 add_len -= use_len;
352 p += use_len;
353 }
354
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200355 return( 0 );
356}
357
Gilles Peskine58fc2722021-04-13 15:58:27 +0200358/* Increment the counter. */
359static void gcm_incr( unsigned char y[16] )
360{
361 size_t i;
362 for( i = 16; i > 12; i-- )
363 if( ++y[i - 1] != 0 )
364 break;
365}
366
367/* Calculate and apply the encryption mask. Process use_len bytes of data,
368 * starting at position offset in the mask block. */
369static int gcm_mask( mbedtls_gcm_context *ctx,
370 unsigned char ectr[16],
371 size_t offset, size_t use_len,
372 const unsigned char *input,
373 unsigned char *output )
374{
375 size_t i;
376 size_t olen = 0;
377 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
378
379 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
380 &olen ) ) != 0 )
381 {
382 mbedtls_platform_zeroize( ectr, 16 );
383 return( ret );
384 }
385
386 for( i = 0; i < use_len; i++ )
387 {
388 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
389 ctx->buf[offset + i] ^= input[i];
390 output[i] = ectr[offset + i] ^ input[i];
391 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
392 ctx->buf[offset + i] ^= output[i];
393 }
394 return( 0 );
395}
396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200398 size_t length,
399 const unsigned char *input,
400 unsigned char *output )
401{
Janos Follath24eed8d2019-11-22 13:21:35 +0000402 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200403 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200404 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200405 size_t offset;
406 unsigned char ectr[16];
407
408 /* Exit early if length==0 so that we don't do any pointer arithmetic on
409 * a potentially null pointer. */
410 if( length == 0 )
411 return( 0 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200412
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100413 GCM_VALIDATE_RET( ctx != NULL );
Gilles Peskine58fc2722021-04-13 15:58:27 +0200414 GCM_VALIDATE_RET( input != NULL );
415 GCM_VALIDATE_RET( output != NULL );
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100416
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200417 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200419
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200420 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
421 * Also check for possible overflow */
422 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard1e075622015-12-10 14:46:25 +0100423 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200424 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200426 }
427
Gilles Peskine58fc2722021-04-13 15:58:27 +0200428 offset = ctx->len % 16;
429 if( offset != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000430 {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200431 size_t use_len = 16 - offset;
432 if( use_len > length )
433 use_len = length;
Paul Bakker89e80c92012-03-20 13:50:09 +0000434
Gilles Peskine58fc2722021-04-13 15:58:27 +0200435 if( ( ret = gcm_mask( ctx, ectr, offset, use_len, p, out_p ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200436 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000437
Gilles Peskine58fc2722021-04-13 15:58:27 +0200438 if( offset + use_len == 16 )
439 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200440
Gilles Peskine58fc2722021-04-13 15:58:27 +0200441 ctx->len += use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000442 length -= use_len;
443 p += use_len;
444 out_p += use_len;
445 }
446
Gilles Peskine58fc2722021-04-13 15:58:27 +0200447 ctx->len += length;
448
449 while( length >= 16 )
450 {
451 gcm_incr( ctx->y );
452 if( ( ret = gcm_mask( ctx, ectr, 0, 16, p, out_p ) ) != 0 )
453 return( ret );
454
455 gcm_mult( ctx, ctx->buf, ctx->buf );
456
457 length -= 16;
458 p += 16;
459 out_p += 16;
460 }
461
462 if( length > 0 )
463 {
464 gcm_incr( ctx->y );
465 if( ( ret = gcm_mask( ctx, ectr, 0, length, p, out_p ) ) != 0 )
466 return( ret );
467 }
468
469 mbedtls_platform_zeroize( ectr, sizeof( ectr ) );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200470 return( 0 );
471}
472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Gilles Peskine9461e452021-04-15 16:48:32 +0200474 unsigned char *output, size_t output_len,
475 unsigned char *tag, size_t tag_len )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200476{
477 unsigned char work_buf[16];
478 size_t i;
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100479 uint64_t orig_len;
480 uint64_t orig_add_len;
481
482 GCM_VALIDATE_RET( ctx != NULL );
483 GCM_VALIDATE_RET( tag != NULL );
484
Gilles Peskine9461e452021-04-15 16:48:32 +0200485 /* We never pass any output in finish(). The output parameter exists only
486 * for the sake of alternative implementations. */
487 (void) output;
488 (void) output_len;
489
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100490 orig_len = ctx->len * 8;
491 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200492
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200493 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200495
Gilles Peskine58fc2722021-04-13 15:58:27 +0200496 if( ctx->len % 16 != 0 )
497 gcm_mult( ctx, ctx->buf, ctx->buf );
498
Andres AG821da842016-09-26 10:09:30 +0100499 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200500
Paul Bakker89e80c92012-03-20 13:50:09 +0000501 if( orig_len || orig_add_len )
502 {
503 memset( work_buf, 0x00, 16 );
504
Paul Bakker0ecdb232013-04-09 11:36:42 +0200505 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
506 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
507 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
508 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000509
Paul Bakker67f9d532012-10-23 11:49:05 +0000510 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200511 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000512
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200513 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000514
Paul Bakker67f9d532012-10-23 11:49:05 +0000515 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200516 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000517 }
518
519 return( 0 );
520}
521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200523 int mode,
524 size_t length,
525 const unsigned char *iv,
526 size_t iv_len,
527 const unsigned char *add,
528 size_t add_len,
529 const unsigned char *input,
530 unsigned char *output,
531 size_t tag_len,
532 unsigned char *tag )
533{
Janos Follath24eed8d2019-11-22 13:21:35 +0000534 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200535
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100536 GCM_VALIDATE_RET( ctx != NULL );
537 GCM_VALIDATE_RET( iv != NULL );
538 GCM_VALIDATE_RET( add_len == 0 || add != NULL );
539 GCM_VALIDATE_RET( length == 0 || input != NULL );
540 GCM_VALIDATE_RET( length == 0 || output != NULL );
541 GCM_VALIDATE_RET( tag != NULL );
542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200544 return( ret );
545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200547 return( ret );
548
Gilles Peskine9461e452021-04-15 16:48:32 +0200549 if( ( ret = mbedtls_gcm_finish( ctx, NULL, 0, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200550 return( ret );
551
552 return( 0 );
553}
554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000556 size_t length,
557 const unsigned char *iv,
558 size_t iv_len,
559 const unsigned char *add,
560 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200561 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000562 size_t tag_len,
563 const unsigned char *input,
564 unsigned char *output )
565{
Janos Follath24eed8d2019-11-22 13:21:35 +0000566 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000567 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200568 size_t i;
569 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000570
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100571 GCM_VALIDATE_RET( ctx != NULL );
572 GCM_VALIDATE_RET( iv != NULL );
573 GCM_VALIDATE_RET( add_len == 0 || add != NULL );
574 GCM_VALIDATE_RET( tag != NULL );
575 GCM_VALIDATE_RET( length == 0 || input != NULL );
576 GCM_VALIDATE_RET( length == 0 || output != NULL );
577
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100579 iv, iv_len, add, add_len,
580 input, output, tag_len, check_tag ) ) != 0 )
581 {
582 return( ret );
583 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000584
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200585 /* Check tag in "constant-time" */
586 for( diff = 0, i = 0; i < tag_len; i++ )
587 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000588
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200589 if( diff != 0 )
590 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500591 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200593 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000594
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200595 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000596}
597
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200598void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200599{
k-stachowiak21298a22018-12-13 17:11:58 +0100600 if( ctx == NULL )
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100601 return;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 mbedtls_cipher_free( &ctx->cipher_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500603 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200604}
605
Jaeden Amero15263302017-09-21 12:53:48 +0100606#endif /* !MBEDTLS_GCM_ALT */
607
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000609/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200610 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 *
612 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
613 */
614#define MAX_TESTS 6
615
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100616static const int key_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 { 0, 0, 1, 1, 1, 1 };
618
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100619static const unsigned char key_test_data[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000620{
621 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
625 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
626 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
627 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200628 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000629};
630
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100631static const size_t iv_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000632 { 12, 12, 12, 12, 8, 60 };
633
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100634static const int iv_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000635 { 0, 0, 1, 1, 1, 2 };
636
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100637static const unsigned char iv_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000638{
639 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00 },
641 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
642 0xde, 0xca, 0xf8, 0x88 },
643 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200644 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000645 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200646 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000647 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200648 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000649 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200650 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000651};
652
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100653static const size_t add_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 { 0, 0, 0, 20, 20, 20 };
655
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100656static const int add_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000657 { 0, 0, 0, 1, 1, 1 };
658
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100659static const unsigned char additional_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000660{
661 { 0x00 },
662 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200663 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000664 0xab, 0xad, 0xda, 0xd2 },
665};
666
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100667static const size_t pt_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000668 { 0, 16, 64, 60, 60, 60 };
669
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100670static const int pt_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000671 { 0, 0, 1, 1, 1, 1 };
672
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100673static const unsigned char pt_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000674{
675 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
677 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
678 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
679 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
680 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
681 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
682 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
683 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
684 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
685};
686
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100687static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000688{
689 { 0x00 },
690 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
691 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
692 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200693 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000694 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200695 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000696 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200697 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000698 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
699 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
700 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200701 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000702 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200703 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000704 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200705 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000706 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
707 0x3d, 0x58, 0xe0, 0x91 },
708 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200709 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000710 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200711 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000712 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200713 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000714 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
715 0xc2, 0x3f, 0x45, 0x98 },
716 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200717 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000718 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200719 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000720 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200721 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000722 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
723 0x4c, 0x34, 0xae, 0xe5 },
724 { 0x00 },
725 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
734 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
735 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200736 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000737 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200738 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
739 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
740 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000741 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200742 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000743 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200744 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000745 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200746 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000747 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200748 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000749 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200750 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000751 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200752 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000753 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200754 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000755 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200756 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000757 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200758 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000759 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200760 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
761 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
762 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
763 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
764 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
765 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
766 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
767 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
768 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
769 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
770 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
771 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
772 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
773 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
774 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
775 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
776 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
777 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000778 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200779 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000780 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200781 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000782 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200783 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000784 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200785 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000786 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200787 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000788 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200789 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000790 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200791 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000792 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200793 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000794};
795
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100796static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000797{
798 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
799 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
800 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
801 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
802 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200803 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000804 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
805 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
806 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
807 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
808 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
809 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
810 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
811 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
812 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200813 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000814 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
815 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
816 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200817 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000818 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200819 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000820 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200821 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000822 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200823 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000824 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200825 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000826 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200827 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000828 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200829 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000830 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200831 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000832 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200833 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000834};
835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200836int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000837{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000839 unsigned char buf[64];
840 unsigned char tag_buf[16];
841 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000843
844 for( j = 0; j < 3; j++ )
845 {
846 int key_len = 128 + 64 * j;
847
848 for( i = 0; i < MAX_TESTS; i++ )
849 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100850 mbedtls_gcm_init( &ctx );
851
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200852 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100854 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200855
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500856 ret = mbedtls_gcm_setkey( &ctx, cipher,
857 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100858 key_len );
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100859 /*
860 * AES-192 is an optional feature that may be unavailable when
861 * there is an alternative underlying implementation i.e. when
862 * MBEDTLS_AES_ALT is defined.
863 */
Ron Eldor9924bdc2018-10-04 10:59:13 +0300864 if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100865 {
866 mbedtls_printf( "skipped\n" );
867 break;
868 }
869 else if( ret != 0 )
870 {
871 goto exit;
872 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500875 pt_len_test_data[i],
876 iv_test_data[iv_index_test_data[i]],
877 iv_len_test_data[i],
878 additional_test_data[add_index_test_data[i]],
879 add_len_test_data[i],
880 pt_test_data[pt_index_test_data[i]],
881 buf, 16, tag_buf );
Steven Cooreman2222d682021-01-11 18:45:22 +0100882#if defined(MBEDTLS_GCM_ALT)
883 /* Allow alternative implementations to only support 12-byte nonces. */
884 if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
885 iv_len_test_data[i] != 12 )
886 {
887 mbedtls_printf( "skipped\n" );
888 break;
889 }
890#endif /* defined(MBEDTLS_GCM_ALT) */
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100891 if( ret != 0 )
892 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000893
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500894 if ( memcmp( buf, ct_test_data[j * 6 + i],
895 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100896 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000897 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100898 ret = 1;
899 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000900 }
901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200903
Paul Bakker89e80c92012-03-20 13:50:09 +0000904 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000906
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100907 mbedtls_gcm_init( &ctx );
908
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200909 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100911 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200912
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500913 ret = mbedtls_gcm_setkey( &ctx, cipher,
914 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100915 key_len );
916 if( ret != 0 )
917 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000918
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500920 pt_len_test_data[i],
921 iv_test_data[iv_index_test_data[i]],
922 iv_len_test_data[i],
923 additional_test_data[add_index_test_data[i]],
924 add_len_test_data[i],
925 ct_test_data[j * 6 + i], buf, 16, tag_buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000926
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100927 if( ret != 0 )
928 goto exit;
929
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100930 if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
931 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100932 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000933 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100934 ret = 1;
935 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000936 }
937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200938 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200939
Paul Bakker89e80c92012-03-20 13:50:09 +0000940 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200942
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100943 mbedtls_gcm_init( &ctx );
944
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200945 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100947 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200948
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500949 ret = mbedtls_gcm_setkey( &ctx, cipher,
950 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100951 key_len );
952 if( ret != 0 )
953 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200955 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500956 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] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200960 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100961 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200962
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100963 if( pt_len_test_data[i] > 32 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200964 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100965 size_t rest_len = pt_len_test_data[i] - 32;
966 ret = mbedtls_gcm_update( &ctx, 32,
967 pt_test_data[pt_index_test_data[i]],
968 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200969 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100970 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200971
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100972 ret = mbedtls_gcm_update( &ctx, rest_len,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500973 pt_test_data[pt_index_test_data[i]] + 32,
974 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200975 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100976 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200977 }
978 else
979 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100980 ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i],
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500981 pt_test_data[pt_index_test_data[i]],
982 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200983 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100984 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200985 }
986
Gilles Peskine9461e452021-04-15 16:48:32 +0200987 ret = mbedtls_gcm_finish( &ctx, NULL, 0, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100988 if( ret != 0 )
989 goto exit;
990
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500991 if( memcmp( buf, ct_test_data[j * 6 + i],
992 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100993 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200994 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100995 ret = 1;
996 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200997 }
998
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200999 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001000
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001001 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001002 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001003
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001004 mbedtls_gcm_init( &ctx );
1005
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001006 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001008 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001009
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001010 ret = mbedtls_gcm_setkey( &ctx, cipher,
1011 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001012 key_len );
1013 if( ret != 0 )
1014 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001017 iv_test_data[iv_index_test_data[i]],
1018 iv_len_test_data[i],
1019 additional_test_data[add_index_test_data[i]],
1020 add_len_test_data[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001021 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001022 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001023
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001024 if( pt_len_test_data[i] > 32 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001025 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001026 size_t rest_len = pt_len_test_data[i] - 32;
Andrzej Kurekee3c4352019-01-10 03:10:02 -05001027 ret = mbedtls_gcm_update( &ctx, 32, ct_test_data[j * 6 + i],
1028 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001029 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001030 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001031
Andrzej Kurekee3c4352019-01-10 03:10:02 -05001032 ret = mbedtls_gcm_update( &ctx, rest_len,
1033 ct_test_data[j * 6 + i] + 32,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001034 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001035 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001036 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001037 }
1038 else
1039 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001040 ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i],
1041 ct_test_data[j * 6 + i],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001042 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001043 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001044 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001045 }
1046
Gilles Peskine9461e452021-04-15 16:48:32 +02001047 ret = mbedtls_gcm_finish( &ctx, NULL, 0, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001048 if( ret != 0 )
1049 goto exit;
1050
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001051 if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
1052 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +01001053 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001054 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001055 ret = 1;
1056 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001057 }
1058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001059 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001060
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001061 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +00001063 }
1064 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001065
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001066 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001067 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +00001068
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001069 ret = 0;
1070
1071exit:
1072 if( ret != 0 )
1073 {
1074 if( verbose != 0 )
1075 mbedtls_printf( "failed\n" );
1076 mbedtls_gcm_free( &ctx );
1077 }
1078
1079 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +00001080}
1081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001084#endif /* MBEDTLS_GCM_C */