blob: 37f07f823920adc0e5c95fc482452ce20acf9181 [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/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020062 * Initialize a context
63 */
64void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
65{
66 memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
67}
68
69/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010070 * Precompute small multiples of H, that is set
71 * HH[i] || HL[i] = H times i,
72 * where i is seen as a field element as in [MGV], ie high-order bits
73 * correspond to low powers of P. The result is stored in the same way, that
74 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
75 * corresponds to P^127.
76 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +000078{
Paul Bakker43aff2a2013-09-09 00:10:27 +020079 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000080 uint64_t hi, lo;
81 uint64_t vl, vh;
82 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +020083 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +020084
Paul Bakker89e80c92012-03-20 13:50:09 +000085 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +020087 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +000088
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010089 /* pack h as two 64-bits ints, big-endian */
Joe Subbiani6a506312021-07-07 16:56:29 +010090 hi = MBEDTLS_GET_UINT32_BE( h, 0 );
91 lo = MBEDTLS_GET_UINT32_BE( h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +000092 vh = (uint64_t) hi << 32 | lo;
93
Joe Subbiani6a506312021-07-07 16:56:29 +010094 hi = MBEDTLS_GET_UINT32_BE( h, 8 );
95 lo = MBEDTLS_GET_UINT32_BE( h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +000096 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +020097
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010098 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +000099 ctx->HL[8] = vl;
100 ctx->HH[8] = vh;
101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100103 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100104 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100105 return( 0 );
106#endif
107
108 /* 0 corresponds to 0 in GF(2^128) */
109 ctx->HH[0] = 0;
110 ctx->HL[0] = 0;
111
Paul Bakker89e80c92012-03-20 13:50:09 +0000112 for( i = 4; i > 0; i >>= 1 )
113 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200114 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000115 vl = ( vh << 63 ) | ( vl >> 1 );
116 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
117
118 ctx->HL[i] = vl;
119 ctx->HH[i] = vh;
120 }
121
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000122 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000123 {
124 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
125 vh = *HiH;
126 vl = *HiL;
127 for( j = 1; j < i; j++ )
128 {
129 HiH[j] = vh ^ ctx->HH[j];
130 HiL[j] = vl ^ ctx->HL[j];
131 }
132 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200133
134 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000135}
136
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200137int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
138 mbedtls_cipher_id_t cipher,
139 const unsigned char *key,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200140 unsigned int keybits )
Paul Bakker89e80c92012-03-20 13:50:09 +0000141{
Janos Follath24eed8d2019-11-22 13:21:35 +0000142 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200143 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000144
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100145 GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 );
146
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500147 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
148 MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200149 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200151
Paul Bakkera0558e02013-09-10 14:25:51 +0200152 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200154
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200155 mbedtls_cipher_free( &ctx->cipher_ctx );
156
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200157 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000158 return( ret );
159
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200160 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200162 {
163 return( ret );
164 }
165
166 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
167 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000168
169 return( 0 );
170}
171
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100172/*
173 * Shoup's method for multiplication use this table with
174 * last4[x] = x times P^128
175 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
176 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000177static const uint64_t last4[16] =
178{
179 0x0000, 0x1c20, 0x3840, 0x2460,
180 0x7080, 0x6ca0, 0x48c0, 0x54e0,
181 0xe100, 0xfd20, 0xd940, 0xc560,
182 0x9180, 0x8da0, 0xa9c0, 0xb5e0
183};
184
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100185/*
186 * Sets output to x times H using the precomputed tables.
187 * x and output are seen as elements of GF(2^128) as in [MGV].
188 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200190 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000191{
192 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000193 unsigned char lo, hi, rem;
194 uint64_t zh, zl;
195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100197 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100198 unsigned char h[16];
199
Joe Subbiani5ecac212021-06-24 13:00:03 +0100200 MBEDTLS_PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
201 MBEDTLS_PUT_UINT32_BE( ctx->HH[8], h, 4 );
202 MBEDTLS_PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
203 MBEDTLS_PUT_UINT32_BE( ctx->HL[8], h, 12 );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100204
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100206 return;
207 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100209
Paul Bakker89e80c92012-03-20 13:50:09 +0000210 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000211
212 zh = ctx->HH[lo];
213 zl = ctx->HL[lo];
214
215 for( i = 15; i >= 0; i-- )
216 {
217 lo = x[i] & 0xf;
k-stachowiak67badb42019-10-22 13:25:06 +0200218 hi = ( x[i] >> 4 ) & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000219
220 if( i != 15 )
221 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000222 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000223 zl = ( zh << 60 ) | ( zl >> 4 );
224 zh = ( zh >> 4 );
225 zh ^= (uint64_t) last4[rem] << 48;
226 zh ^= ctx->HH[lo];
227 zl ^= ctx->HL[lo];
228
229 }
230
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000231 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000232 zl = ( zh << 60 ) | ( zl >> 4 );
233 zh = ( zh >> 4 );
234 zh ^= (uint64_t) last4[rem] << 48;
235 zh ^= ctx->HH[hi];
236 zl ^= ctx->HL[hi];
237 }
238
Joe Subbiani5ecac212021-06-24 13:00:03 +0100239 MBEDTLS_PUT_UINT32_BE( zh >> 32, output, 0 );
240 MBEDTLS_PUT_UINT32_BE( zh, output, 4 );
241 MBEDTLS_PUT_UINT32_BE( zl >> 32, output, 8 );
242 MBEDTLS_PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000243}
244
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Gilles Peskine295fc132021-04-15 18:32:23 +0200246 int mode,
247 const unsigned char *iv, size_t iv_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000248{
Janos Follath24eed8d2019-11-22 13:21:35 +0000249 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000250 unsigned char work_buf[16];
251 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000252 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200253 size_t use_len, olen = 0;
openluopworldeab65ac2021-09-22 23:59:42 +0800254 uint64_t iv_bits;
Paul Bakker89e80c92012-03-20 13:50:09 +0000255
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200256 /* IV is limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200257 /* IV is not allowed to be zero length */
Gilles Peskine295fc132021-04-15 18:32:23 +0200258 if( iv_len == 0 || (uint64_t) iv_len >> 61 != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200260
Paul Bakker52cf16c2013-07-26 13:55:38 +0200261 memset( ctx->y, 0x00, sizeof(ctx->y) );
262 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
263
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200264 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200265 ctx->len = 0;
266 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000267
268 if( iv_len == 12 )
269 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200270 memcpy( ctx->y, iv, iv_len );
271 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000272 }
273 else
274 {
275 memset( work_buf, 0x00, 16 );
openluopworldeab65ac2021-09-22 23:59:42 +0800276 iv_bits = (uint64_t)iv_len * 8;
277 MBEDTLS_PUT_UINT64_BE( iv_bits, work_buf, 8 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000278
279 p = iv;
280 while( iv_len > 0 )
281 {
282 use_len = ( iv_len < 16 ) ? iv_len : 16;
283
Paul Bakker67f9d532012-10-23 11:49:05 +0000284 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200285 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200286
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200287 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000288
289 iv_len -= use_len;
290 p += use_len;
291 }
292
Paul Bakker67f9d532012-10-23 11:49:05 +0000293 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200294 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000295
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200296 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000297 }
298
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500299 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16,
300 ctx->base_ectr, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200301 {
302 return( ret );
303 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000304
Gilles Peskine295fc132021-04-15 18:32:23 +0200305 return( 0 );
306}
307
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200308/**
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200309 * mbedtls_gcm_context::buf contains the partial state of the computation of
310 * the authentication tag.
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200311 * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
312 * different stages of the computation:
Mateusz Starzyk3d0bbee2021-06-15 14:26:53 +0200313 * * len == 0 && add_len == 0: initial state
314 * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
315 * a partial block of AD that has been
316 * xored in but not yet multiplied in.
317 * * len == 0 && add_len % 16 == 0: the authentication tag is correct if
318 * the data ends now.
319 * * len % 16 != 0: the first `len % 16` bytes have
320 * a partial block of ciphertext that has
321 * been xored in but not yet multiplied in.
322 * * len > 0 && len % 16 == 0: the authentication tag is correct if
323 * the data ends now.
Mateusz Starzykb45b57e2021-06-07 15:44:18 +0200324 */
Gilles Peskine295fc132021-04-15 18:32:23 +0200325int mbedtls_gcm_update_ad( mbedtls_gcm_context *ctx,
326 const unsigned char *add, size_t add_len )
327{
328 const unsigned char *p;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200329 size_t use_len, i, offset;
Gilles Peskine295fc132021-04-15 18:32:23 +0200330
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200331 /* IV is limited to 2^64 bits, so 2^61 bytes */
Gilles Peskine295fc132021-04-15 18:32:23 +0200332 if( (uint64_t) add_len >> 61 != 0 )
333 return( MBEDTLS_ERR_GCM_BAD_INPUT );
334
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200335 offset = ctx->add_len % 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000336 p = add;
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200337
Mateusz Starzyk333f48f2021-06-07 14:42:27 +0200338 if( offset != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000339 {
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200340 use_len = 16 - offset;
341 if( use_len > add_len )
342 use_len = add_len;
343
Mateusz Starzyk939a54c2021-06-22 11:12:28 +0200344 for( i = 0; i < use_len; i++ )
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200345 ctx->buf[i+offset] ^= p[i];
346
347 if( offset + use_len == 16 )
348 gcm_mult( ctx, ctx->buf, ctx->buf );
349
350 ctx->add_len += use_len;
351 add_len -= use_len;
352 p += use_len;
353 }
354
355 ctx->add_len += add_len;
356
357 while( add_len >= 16 )
358 {
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200359 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200360 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200361
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200362 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000363
Mateusz Starzyk25a571e2021-06-15 13:22:42 +0200364 add_len -= 16;
365 p += 16;
Paul Bakker89e80c92012-03-20 13:50:09 +0000366 }
367
Mateusz Starzyk333f48f2021-06-07 14:42:27 +0200368 if( add_len > 0 )
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200369 {
370 for( i = 0; i < add_len; i++ )
371 ctx->buf[i] ^= p[i];
372 }
373
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200374 return( 0 );
375}
376
Gilles Peskine58fc2722021-04-13 15:58:27 +0200377/* Increment the counter. */
378static void gcm_incr( unsigned char y[16] )
379{
380 size_t i;
381 for( i = 16; i > 12; i-- )
382 if( ++y[i - 1] != 0 )
383 break;
384}
385
386/* Calculate and apply the encryption mask. Process use_len bytes of data,
387 * starting at position offset in the mask block. */
388static int gcm_mask( mbedtls_gcm_context *ctx,
389 unsigned char ectr[16],
390 size_t offset, size_t use_len,
391 const unsigned char *input,
392 unsigned char *output )
393{
394 size_t i;
395 size_t olen = 0;
396 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
397
398 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
399 &olen ) ) != 0 )
400 {
401 mbedtls_platform_zeroize( ectr, 16 );
402 return( ret );
403 }
404
405 for( i = 0; i < use_len; i++ )
406 {
407 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
408 ctx->buf[offset + i] ^= input[i];
409 output[i] = ectr[offset + i] ^ input[i];
410 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
411 ctx->buf[offset + i] ^= output[i];
412 }
413 return( 0 );
414}
415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Gilles Peskinea56c4482021-04-15 17:22:35 +0200417 const unsigned char *input, size_t input_length,
418 unsigned char *output, size_t output_size,
419 size_t *output_length )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200420{
Janos Follath24eed8d2019-11-22 13:21:35 +0000421 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200422 const unsigned char *p = input;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200423 unsigned char *out_p = output;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200424 size_t offset;
Leonid Rozenboima3008e72022-04-21 17:28:18 -0700425 unsigned char ectr[16] = {0};
Gilles Peskine58fc2722021-04-13 15:58:27 +0200426
Gilles Peskinea56c4482021-04-15 17:22:35 +0200427 if( output_size < input_length )
Mateusz Starzykc48f43b2021-10-04 13:46:38 +0200428 return( MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL );
Gilles Peskinea56c4482021-04-15 17:22:35 +0200429 *output_length = input_length;
430
431 /* Exit early if input_length==0 so that we don't do any pointer arithmetic
Mateusz Starzyk3443bd22021-06-07 16:03:27 +0200432 * on a potentially null pointer.
433 * Returning early also means that the last partial block of AD remains
434 * untouched for mbedtls_gcm_finish */
Gilles Peskinea56c4482021-04-15 17:22:35 +0200435 if( input_length == 0 )
Gilles Peskine58fc2722021-04-13 15:58:27 +0200436 return( 0 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200437
Gilles Peskinea56c4482021-04-15 17:22:35 +0200438 if( output > input && (size_t) ( output - input ) < input_length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200440
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200441 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
442 * Also check for possible overflow */
Gilles Peskinea56c4482021-04-15 17:22:35 +0200443 if( ctx->len + input_length < ctx->len ||
444 (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200445 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200447 }
448
Mateusz Starzyk333f48f2021-06-07 14:42:27 +0200449 if( ctx->len == 0 && ctx->add_len % 16 != 0 )
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200450 {
451 gcm_mult( ctx, ctx->buf, ctx->buf );
452 }
453
Gilles Peskine58fc2722021-04-13 15:58:27 +0200454 offset = ctx->len % 16;
455 if( offset != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000456 {
Gilles Peskine58fc2722021-04-13 15:58:27 +0200457 size_t use_len = 16 - offset;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200458 if( use_len > input_length )
459 use_len = input_length;
Paul Bakker89e80c92012-03-20 13:50:09 +0000460
Gilles Peskine58fc2722021-04-13 15:58:27 +0200461 if( ( ret = gcm_mask( ctx, ectr, offset, use_len, p, out_p ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200462 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000463
Gilles Peskine58fc2722021-04-13 15:58:27 +0200464 if( offset + use_len == 16 )
465 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200466
Gilles Peskine58fc2722021-04-13 15:58:27 +0200467 ctx->len += use_len;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200468 input_length -= use_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000469 p += use_len;
470 out_p += use_len;
471 }
472
Gilles Peskinea56c4482021-04-15 17:22:35 +0200473 ctx->len += input_length;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200474
Gilles Peskinea56c4482021-04-15 17:22:35 +0200475 while( input_length >= 16 )
Gilles Peskine58fc2722021-04-13 15:58:27 +0200476 {
477 gcm_incr( ctx->y );
478 if( ( ret = gcm_mask( ctx, ectr, 0, 16, p, out_p ) ) != 0 )
479 return( ret );
480
481 gcm_mult( ctx, ctx->buf, ctx->buf );
482
Gilles Peskinea56c4482021-04-15 17:22:35 +0200483 input_length -= 16;
Gilles Peskine58fc2722021-04-13 15:58:27 +0200484 p += 16;
485 out_p += 16;
486 }
487
Gilles Peskinea56c4482021-04-15 17:22:35 +0200488 if( input_length > 0 )
Gilles Peskine58fc2722021-04-13 15:58:27 +0200489 {
490 gcm_incr( ctx->y );
Gilles Peskinea56c4482021-04-15 17:22:35 +0200491 if( ( ret = gcm_mask( ctx, ectr, 0, input_length, p, out_p ) ) != 0 )
Gilles Peskine58fc2722021-04-13 15:58:27 +0200492 return( ret );
493 }
494
495 mbedtls_platform_zeroize( ectr, sizeof( ectr ) );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200496 return( 0 );
497}
498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200500 unsigned char *output, size_t output_size,
Gilles Peskine5a7be102021-06-23 21:51:32 +0200501 size_t *output_length,
Gilles Peskine9461e452021-04-15 16:48:32 +0200502 unsigned char *tag, size_t tag_len )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200503{
504 unsigned char work_buf[16];
505 size_t i;
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100506 uint64_t orig_len;
507 uint64_t orig_add_len;
508
Gilles Peskine9461e452021-04-15 16:48:32 +0200509 /* We never pass any output in finish(). The output parameter exists only
510 * for the sake of alternative implementations. */
511 (void) output;
Gilles Peskineb7bb06872021-05-18 22:31:53 +0200512 (void) output_size;
Gilles Peskine5a7be102021-06-23 21:51:32 +0200513 *output_length = 0;
Gilles Peskine9461e452021-04-15 16:48:32 +0200514
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100515 orig_len = ctx->len * 8;
516 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200517
Mateusz Starzyk333f48f2021-06-07 14:42:27 +0200518 if( ctx->len == 0 && ctx->add_len % 16 != 0 )
Mateusz Starzykbd513bb2021-05-26 14:25:39 +0200519 {
520 gcm_mult( ctx, ctx->buf, ctx->buf );
521 }
522
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200523 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200525
Gilles Peskine58fc2722021-04-13 15:58:27 +0200526 if( ctx->len % 16 != 0 )
527 gcm_mult( ctx, ctx->buf, ctx->buf );
528
Andres AG821da842016-09-26 10:09:30 +0100529 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200530
Paul Bakker89e80c92012-03-20 13:50:09 +0000531 if( orig_len || orig_add_len )
532 {
533 memset( work_buf, 0x00, 16 );
534
Joe Subbiani5ecac212021-06-24 13:00:03 +0100535 MBEDTLS_PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
536 MBEDTLS_PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
537 MBEDTLS_PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
538 MBEDTLS_PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000539
Paul Bakker67f9d532012-10-23 11:49:05 +0000540 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200541 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000542
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200543 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000544
Paul Bakker67f9d532012-10-23 11:49:05 +0000545 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200546 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000547 }
548
549 return( 0 );
550}
551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200553 int mode,
554 size_t length,
555 const unsigned char *iv,
556 size_t iv_len,
557 const unsigned char *add,
558 size_t add_len,
559 const unsigned char *input,
560 unsigned char *output,
561 size_t tag_len,
562 unsigned char *tag )
563{
Janos Follath24eed8d2019-11-22 13:21:35 +0000564 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200565 size_t olen;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200566
Gilles Peskine295fc132021-04-15 18:32:23 +0200567 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len ) ) != 0 )
568 return( ret );
569
570 if( ( ret = mbedtls_gcm_update_ad( ctx, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200571 return( ret );
572
Gilles Peskinea56c4482021-04-15 17:22:35 +0200573 if( ( ret = mbedtls_gcm_update( ctx, input, length,
574 output, length, &olen ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200575 return( ret );
576
Gilles Peskine5a7be102021-06-23 21:51:32 +0200577 if( ( ret = mbedtls_gcm_finish( ctx, NULL, 0, &olen, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200578 return( ret );
579
580 return( 0 );
581}
582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000584 size_t length,
585 const unsigned char *iv,
586 size_t iv_len,
587 const unsigned char *add,
588 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200589 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000590 size_t tag_len,
591 const unsigned char *input,
592 unsigned char *output )
593{
Janos Follath24eed8d2019-11-22 13:21:35 +0000594 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000595 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200596 size_t i;
597 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100600 iv, iv_len, add, add_len,
601 input, output, tag_len, check_tag ) ) != 0 )
602 {
603 return( ret );
604 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000605
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200606 /* Check tag in "constant-time" */
607 for( diff = 0, i = 0; i < tag_len; i++ )
608 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000609
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200610 if( diff != 0 )
611 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500612 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200614 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000615
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200616 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000617}
618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200620{
k-stachowiak21298a22018-12-13 17:11:58 +0100621 if( ctx == NULL )
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100622 return;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 mbedtls_cipher_free( &ctx->cipher_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500624 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200625}
626
Jaeden Amero15263302017-09-21 12:53:48 +0100627#endif /* !MBEDTLS_GCM_ALT */
628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000630/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200631 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000632 *
633 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
634 */
635#define MAX_TESTS 6
636
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100637static const int key_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 { 0, 0, 1, 1, 1, 1 };
639
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100640static const unsigned char key_test_data[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000641{
642 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
647 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
648 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000650};
651
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100652static const size_t iv_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000653 { 12, 12, 12, 12, 8, 60 };
654
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100655static const int iv_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000656 { 0, 0, 1, 1, 1, 2 };
657
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100658static const unsigned char iv_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000659{
660 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
661 0x00, 0x00, 0x00, 0x00 },
662 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
663 0xde, 0xca, 0xf8, 0x88 },
664 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200665 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000666 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200667 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000668 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200669 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000670 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200671 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000672};
673
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100674static const size_t add_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000675 { 0, 0, 0, 20, 20, 20 };
676
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100677static const int add_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000678 { 0, 0, 0, 1, 1, 1 };
679
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100680static const unsigned char additional_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000681{
682 { 0x00 },
683 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200684 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 0xab, 0xad, 0xda, 0xd2 },
686};
687
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100688static const size_t pt_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000689 { 0, 16, 64, 60, 60, 60 };
690
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100691static const int pt_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000692 { 0, 0, 1, 1, 1, 1 };
693
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100694static const unsigned char pt_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000695{
696 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
697 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
698 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
699 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
700 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
701 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
702 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
703 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
704 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
705 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
706};
707
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100708static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000709{
710 { 0x00 },
711 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
712 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
713 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200714 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000715 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200716 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000717 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200718 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000719 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
720 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
721 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
728 0x3d, 0x58, 0xe0, 0x91 },
729 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000735 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
736 0xc2, 0x3f, 0x45, 0x98 },
737 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200738 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000739 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200740 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000741 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200742 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000743 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
744 0x4c, 0x34, 0xae, 0xe5 },
745 { 0x00 },
746 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200747 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000748 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200749 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000750 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200751 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000752 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200753 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000754 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
755 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
756 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200757 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000758 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200759 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
760 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
761 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000762 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200763 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000764 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200765 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000766 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200767 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000768 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200769 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000770 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200771 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000772 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200773 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000774 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200775 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000776 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200777 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000778 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200779 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000780 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200781 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
782 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
783 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
784 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
785 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
786 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
787 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
788 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
789 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
790 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
791 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
792 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
793 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
794 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
795 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
796 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
797 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
798 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000799 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200800 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000801 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200802 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000803 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200804 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000805 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200806 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000807 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200808 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000809 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200810 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000811 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200812 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000813 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200814 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000815};
816
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100817static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000818{
819 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
820 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
821 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
822 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
823 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200824 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000825 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
826 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
827 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
828 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
829 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
830 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
831 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
832 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
833 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200834 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000835 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
836 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
837 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200838 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000839 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200840 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000841 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200842 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000843 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200844 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000845 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200846 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000847 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200848 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000849 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200850 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000851 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200852 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000853 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200854 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000855};
856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000858{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200859 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000860 unsigned char buf[64];
861 unsigned char tag_buf[16];
862 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200863 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200864 size_t olen;
Paul Bakker89e80c92012-03-20 13:50:09 +0000865
866 for( j = 0; j < 3; j++ )
867 {
868 int key_len = 128 + 64 * j;
869
870 for( i = 0; i < MAX_TESTS; i++ )
871 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100872 mbedtls_gcm_init( &ctx );
873
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200874 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100876 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200877
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500878 ret = mbedtls_gcm_setkey( &ctx, cipher,
879 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100880 key_len );
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100881 /*
882 * AES-192 is an optional feature that may be unavailable when
883 * there is an alternative underlying implementation i.e. when
884 * MBEDTLS_AES_ALT is defined.
885 */
Ron Eldor9924bdc2018-10-04 10:59:13 +0300886 if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100887 {
888 mbedtls_printf( "skipped\n" );
889 break;
890 }
891 else if( ret != 0 )
892 {
893 goto exit;
894 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500897 pt_len_test_data[i],
898 iv_test_data[iv_index_test_data[i]],
899 iv_len_test_data[i],
900 additional_test_data[add_index_test_data[i]],
901 add_len_test_data[i],
902 pt_test_data[pt_index_test_data[i]],
903 buf, 16, tag_buf );
Steven Cooreman2222d682021-01-11 18:45:22 +0100904#if defined(MBEDTLS_GCM_ALT)
905 /* Allow alternative implementations to only support 12-byte nonces. */
906 if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
907 iv_len_test_data[i] != 12 )
908 {
909 mbedtls_printf( "skipped\n" );
910 break;
911 }
912#endif /* defined(MBEDTLS_GCM_ALT) */
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100913 if( ret != 0 )
914 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000915
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500916 if ( memcmp( buf, ct_test_data[j * 6 + i],
917 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100918 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000919 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100920 ret = 1;
921 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000922 }
923
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200925
Paul Bakker89e80c92012-03-20 13:50:09 +0000926 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000928
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100929 mbedtls_gcm_init( &ctx );
930
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200931 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100933 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200934
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500935 ret = mbedtls_gcm_setkey( &ctx, cipher,
936 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100937 key_len );
938 if( ret != 0 )
939 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500942 pt_len_test_data[i],
943 iv_test_data[iv_index_test_data[i]],
944 iv_len_test_data[i],
945 additional_test_data[add_index_test_data[i]],
946 add_len_test_data[i],
947 ct_test_data[j * 6 + i], buf, 16, tag_buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000948
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100949 if( ret != 0 )
950 goto exit;
951
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100952 if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
953 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100954 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000955 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100956 ret = 1;
957 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000958 }
959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200961
Paul Bakker89e80c92012-03-20 13:50:09 +0000962 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200963 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200964
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100965 mbedtls_gcm_init( &ctx );
966
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200967 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100969 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200970
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500971 ret = mbedtls_gcm_setkey( &ctx, cipher,
972 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100973 key_len );
974 if( ret != 0 )
975 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Gilles Peskine295fc132021-04-15 18:32:23 +0200978 iv_test_data[iv_index_test_data[i]],
979 iv_len_test_data[i] );
980 if( ret != 0 )
981 goto exit;
982
983 ret = mbedtls_gcm_update_ad( &ctx,
984 additional_test_data[add_index_test_data[i]],
985 add_len_test_data[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200986 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100987 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200988
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100989 if( pt_len_test_data[i] > 32 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200990 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100991 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200992 ret = mbedtls_gcm_update( &ctx,
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100993 pt_test_data[pt_index_test_data[i]],
Gilles Peskinea56c4482021-04-15 17:22:35 +0200994 32,
995 buf, sizeof( buf ), &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200996 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100997 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +0200998 if( olen != 32 )
999 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001000
Gilles Peskinea56c4482021-04-15 17:22:35 +02001001 ret = mbedtls_gcm_update( &ctx,
1002 pt_test_data[pt_index_test_data[i]] + 32,
1003 rest_len,
1004 buf + 32, sizeof( buf ) - 32, &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001005 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001006 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001007 if( olen != rest_len )
1008 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001009 }
1010 else
1011 {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001012 ret = mbedtls_gcm_update( &ctx,
Andrzej Kurekee3c4352019-01-10 03:10:02 -05001013 pt_test_data[pt_index_test_data[i]],
Gilles Peskinea56c4482021-04-15 17:22:35 +02001014 pt_len_test_data[i],
1015 buf, sizeof( buf ), &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001016 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001017 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001018 if( olen != pt_len_test_data[i] )
1019 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001020 }
1021
Gilles Peskine5a7be102021-06-23 21:51:32 +02001022 ret = mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001023 if( ret != 0 )
1024 goto exit;
1025
Andrzej Kurekee3c4352019-01-10 03:10:02 -05001026 if( memcmp( buf, ct_test_data[j * 6 + i],
1027 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +01001028 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001029 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001030 ret = 1;
1031 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001032 }
1033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001035
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001036 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001037 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001038
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001039 mbedtls_gcm_init( &ctx );
1040
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001041 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001043 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001044
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001045 ret = mbedtls_gcm_setkey( &ctx, cipher,
1046 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001047 key_len );
1048 if( ret != 0 )
1049 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001051 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Gilles Peskine295fc132021-04-15 18:32:23 +02001052 iv_test_data[iv_index_test_data[i]],
1053 iv_len_test_data[i] );
1054 if( ret != 0 )
1055 goto exit;
1056 ret = mbedtls_gcm_update_ad( &ctx,
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001057 additional_test_data[add_index_test_data[i]],
1058 add_len_test_data[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001059 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001060 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001061
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001062 if( pt_len_test_data[i] > 32 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001063 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001064 size_t rest_len = pt_len_test_data[i] - 32;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001065 ret = mbedtls_gcm_update( &ctx,
1066 ct_test_data[j * 6 + i], 32,
1067 buf, sizeof( buf ), &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001068 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001069 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001070 if( olen != 32 )
1071 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001072
Gilles Peskinea56c4482021-04-15 17:22:35 +02001073 ret = mbedtls_gcm_update( &ctx,
Andrzej Kurekee3c4352019-01-10 03:10:02 -05001074 ct_test_data[j * 6 + i] + 32,
Gilles Peskinea56c4482021-04-15 17:22:35 +02001075 rest_len,
1076 buf + 32, sizeof( buf ) - 32, &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001077 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001078 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001079 if( olen != rest_len )
1080 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001081 }
1082 else
1083 {
Gilles Peskinea56c4482021-04-15 17:22:35 +02001084 ret = mbedtls_gcm_update( &ctx,
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001085 ct_test_data[j * 6 + i],
Gilles Peskinea56c4482021-04-15 17:22:35 +02001086 pt_len_test_data[i],
1087 buf, sizeof( buf ), &olen );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001088 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001089 goto exit;
Gilles Peskinea56c4482021-04-15 17:22:35 +02001090 if( olen != pt_len_test_data[i] )
1091 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001092 }
1093
Gilles Peskine5a7be102021-06-23 21:51:32 +02001094 ret = mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001095 if( ret != 0 )
1096 goto exit;
1097
Michał Janiszewskic79e92b2018-10-31 20:43:05 +01001098 if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
1099 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +01001100 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001101 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001102 ret = 1;
1103 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001104 }
1105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +02001107
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001108 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001109 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +00001110 }
1111 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001112
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001113 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +00001115
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001116 ret = 0;
1117
1118exit:
1119 if( ret != 0 )
1120 {
1121 if( verbose != 0 )
1122 mbedtls_printf( "failed\n" );
1123 mbedtls_gcm_free( &ctx );
1124 }
1125
1126 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +00001127}
1128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001130
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001131#endif /* MBEDTLS_GCM_C */