blob: 300521ecdd55d631f7bf2a581ecef6febe6e72e1 [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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200359 size_t length,
360 const unsigned char *input,
361 unsigned char *output )
362{
Janos Follath24eed8d2019-11-22 13:21:35 +0000363 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200364 unsigned char ectr[16];
365 size_t i;
366 const unsigned char *p;
367 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200368 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200369
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100370 GCM_VALIDATE_RET( ctx != NULL );
371 GCM_VALIDATE_RET( length == 0 || input != NULL );
372 GCM_VALIDATE_RET( length == 0 || output != NULL );
373
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200374 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200376
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200377 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
378 * Also check for possible overflow */
379 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard1e075622015-12-10 14:46:25 +0100380 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200383 }
384
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200385 ctx->len += length;
386
Paul Bakker89e80c92012-03-20 13:50:09 +0000387 p = input;
388 while( length > 0 )
389 {
390 use_len = ( length < 16 ) ? length : 16;
391
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100392 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200393 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000394 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200397 &olen ) ) != 0 )
398 {
399 return( ret );
400 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000401
Paul Bakker67f9d532012-10-23 11:49:05 +0000402 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000403 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200405 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000406 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200408 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000409 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200410
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200411 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200412
Paul Bakker89e80c92012-03-20 13:50:09 +0000413 length -= use_len;
414 p += use_len;
415 out_p += use_len;
416 }
417
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200418 return( 0 );
419}
420
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200422 unsigned char *tag,
423 size_t tag_len )
424{
425 unsigned char work_buf[16];
426 size_t i;
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100427 uint64_t orig_len;
428 uint64_t orig_add_len;
429
430 GCM_VALIDATE_RET( ctx != NULL );
431 GCM_VALIDATE_RET( tag != NULL );
432
433 orig_len = ctx->len * 8;
434 orig_add_len = ctx->add_len * 8;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200435
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200436 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200438
Andres AG821da842016-09-26 10:09:30 +0100439 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200440
Paul Bakker89e80c92012-03-20 13:50:09 +0000441 if( orig_len || orig_add_len )
442 {
443 memset( work_buf, 0x00, 16 );
444
Paul Bakker0ecdb232013-04-09 11:36:42 +0200445 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
446 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
447 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
448 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000449
Paul Bakker67f9d532012-10-23 11:49:05 +0000450 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200451 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000452
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200453 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000454
Paul Bakker67f9d532012-10-23 11:49:05 +0000455 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200456 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000457 }
458
459 return( 0 );
460}
461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200463 int mode,
464 size_t length,
465 const unsigned char *iv,
466 size_t iv_len,
467 const unsigned char *add,
468 size_t add_len,
469 const unsigned char *input,
470 unsigned char *output,
471 size_t tag_len,
472 unsigned char *tag )
473{
Janos Follath24eed8d2019-11-22 13:21:35 +0000474 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200475
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100476 GCM_VALIDATE_RET( ctx != NULL );
477 GCM_VALIDATE_RET( iv != NULL );
478 GCM_VALIDATE_RET( add_len == 0 || add != NULL );
479 GCM_VALIDATE_RET( length == 0 || input != NULL );
480 GCM_VALIDATE_RET( length == 0 || output != NULL );
481 GCM_VALIDATE_RET( tag != NULL );
482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200484 return( ret );
485
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200487 return( ret );
488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200490 return( ret );
491
492 return( 0 );
493}
494
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000496 size_t length,
497 const unsigned char *iv,
498 size_t iv_len,
499 const unsigned char *add,
500 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200501 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000502 size_t tag_len,
503 const unsigned char *input,
504 unsigned char *output )
505{
Janos Follath24eed8d2019-11-22 13:21:35 +0000506 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker89e80c92012-03-20 13:50:09 +0000507 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200508 size_t i;
509 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000510
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100511 GCM_VALIDATE_RET( ctx != NULL );
512 GCM_VALIDATE_RET( iv != NULL );
513 GCM_VALIDATE_RET( add_len == 0 || add != NULL );
514 GCM_VALIDATE_RET( tag != NULL );
515 GCM_VALIDATE_RET( length == 0 || input != NULL );
516 GCM_VALIDATE_RET( length == 0 || output != NULL );
517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100519 iv, iv_len, add, add_len,
520 input, output, tag_len, check_tag ) ) != 0 )
521 {
522 return( ret );
523 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000524
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200525 /* Check tag in "constant-time" */
526 for( diff = 0, i = 0; i < tag_len; i++ )
527 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000528
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200529 if( diff != 0 )
530 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500531 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200533 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000534
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200535 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000536}
537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200539{
k-stachowiak21298a22018-12-13 17:11:58 +0100540 if( ctx == NULL )
k-stachowiak8ffc92a2018-12-12 14:21:59 +0100541 return;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 mbedtls_cipher_free( &ctx->cipher_ctx );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500543 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200544}
545
Jaeden Amero15263302017-09-21 12:53:48 +0100546#endif /* !MBEDTLS_GCM_ALT */
547
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000549/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200550 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000551 *
552 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
553 */
554#define MAX_TESTS 6
555
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100556static const int key_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000557 { 0, 0, 1, 1, 1, 1 };
558
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100559static const unsigned char key_test_data[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000560{
561 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
565 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
566 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
567 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200568 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000569};
570
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100571static const size_t iv_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000572 { 12, 12, 12, 12, 8, 60 };
573
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100574static const int iv_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000575 { 0, 0, 1, 1, 1, 2 };
576
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100577static const unsigned char iv_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000578{
579 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00 },
581 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
582 0xde, 0xca, 0xf8, 0x88 },
583 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200584 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000585 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200586 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000587 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200588 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000589 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200590 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000591};
592
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100593static const size_t add_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000594 { 0, 0, 0, 20, 20, 20 };
595
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100596static const int add_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000597 { 0, 0, 0, 1, 1, 1 };
598
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100599static const unsigned char additional_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000600{
601 { 0x00 },
602 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200603 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000604 0xab, 0xad, 0xda, 0xd2 },
605};
606
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100607static const size_t pt_len_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000608 { 0, 16, 64, 60, 60, 60 };
609
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100610static const int pt_index_test_data[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 { 0, 0, 1, 1, 1, 1 };
612
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100613static const unsigned char pt_test_data[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000614{
615 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
617 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
618 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
619 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
620 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
621 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
622 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
623 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
624 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
625};
626
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100627static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000628{
629 { 0x00 },
630 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
631 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
632 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200633 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000634 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200635 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000636 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200637 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
639 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
640 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200641 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000642 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200645 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000646 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
647 0x3d, 0x58, 0xe0, 0x91 },
648 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
655 0xc2, 0x3f, 0x45, 0x98 },
656 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
663 0x4c, 0x34, 0xae, 0xe5 },
664 { 0x00 },
665 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200666 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000667 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200668 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000669 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200670 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000671 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200672 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000673 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
674 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
675 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200676 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000677 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200678 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
679 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
680 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000681 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200682 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000683 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200684 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200686 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000687 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200688 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000689 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200690 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200694 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000695 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200696 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000697 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200698 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000699 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200700 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
701 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
702 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
703 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
704 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
705 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
706 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
707 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
708 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
709 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
710 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
711 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
712 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
713 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
714 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
715 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
716 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
717 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000718 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200719 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000720 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200721 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000722 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200723 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000724 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200725 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000726 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200727 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000728 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200729 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000730 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200731 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000732 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200733 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000734};
735
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100736static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000737{
738 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
739 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
740 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
741 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
742 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200743 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000744 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
745 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
746 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
747 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
748 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
749 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
750 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
751 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
752 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200753 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000754 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
755 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
756 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200757 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000758 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200759 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000760 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200761 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000762 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200763 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000764 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200765 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000766 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200767 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000768 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200769 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000770 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200771 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000772 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200773 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000774};
775
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000777{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000779 unsigned char buf[64];
780 unsigned char tag_buf[16];
781 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000783
784 for( j = 0; j < 3; j++ )
785 {
786 int key_len = 128 + 64 * j;
787
788 for( i = 0; i < MAX_TESTS; i++ )
789 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100790 mbedtls_gcm_init( &ctx );
791
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200792 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200793 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100794 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200795
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500796 ret = mbedtls_gcm_setkey( &ctx, cipher,
797 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100798 key_len );
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100799 /*
800 * AES-192 is an optional feature that may be unavailable when
801 * there is an alternative underlying implementation i.e. when
802 * MBEDTLS_AES_ALT is defined.
803 */
Ron Eldor9924bdc2018-10-04 10:59:13 +0300804 if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100805 {
806 mbedtls_printf( "skipped\n" );
807 break;
808 }
809 else if( ret != 0 )
810 {
811 goto exit;
812 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500815 pt_len_test_data[i],
816 iv_test_data[iv_index_test_data[i]],
817 iv_len_test_data[i],
818 additional_test_data[add_index_test_data[i]],
819 add_len_test_data[i],
820 pt_test_data[pt_index_test_data[i]],
821 buf, 16, tag_buf );
Steven Cooreman2222d682021-01-11 18:45:22 +0100822#if defined(MBEDTLS_GCM_ALT)
823 /* Allow alternative implementations to only support 12-byte nonces. */
824 if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
825 iv_len_test_data[i] != 12 )
826 {
827 mbedtls_printf( "skipped\n" );
828 break;
829 }
830#endif /* defined(MBEDTLS_GCM_ALT) */
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100831 if( ret != 0 )
832 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000833
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500834 if ( memcmp( buf, ct_test_data[j * 6 + i],
835 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100836 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000837 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100838 ret = 1;
839 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000840 }
841
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200843
Paul Bakker89e80c92012-03-20 13:50:09 +0000844 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200845 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000846
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100847 mbedtls_gcm_init( &ctx );
848
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200849 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100851 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200852
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500853 ret = mbedtls_gcm_setkey( &ctx, cipher,
854 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100855 key_len );
856 if( ret != 0 )
857 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200859 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500860 pt_len_test_data[i],
861 iv_test_data[iv_index_test_data[i]],
862 iv_len_test_data[i],
863 additional_test_data[add_index_test_data[i]],
864 add_len_test_data[i],
865 ct_test_data[j * 6 + i], buf, 16, tag_buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000866
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100867 if( ret != 0 )
868 goto exit;
869
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100870 if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
871 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100872 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000873 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100874 ret = 1;
875 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000876 }
877
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200878 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200879
Paul Bakker89e80c92012-03-20 13:50:09 +0000880 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200882
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100883 mbedtls_gcm_init( &ctx );
884
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200885 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100887 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200888
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500889 ret = mbedtls_gcm_setkey( &ctx, cipher,
890 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100891 key_len );
892 if( ret != 0 )
893 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200894
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200895 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500896 iv_test_data[iv_index_test_data[i]],
897 iv_len_test_data[i],
898 additional_test_data[add_index_test_data[i]],
899 add_len_test_data[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200900 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100901 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200902
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100903 if( pt_len_test_data[i] > 32 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200904 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100905 size_t rest_len = pt_len_test_data[i] - 32;
906 ret = mbedtls_gcm_update( &ctx, 32,
907 pt_test_data[pt_index_test_data[i]],
908 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200909 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100910 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200911
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100912 ret = mbedtls_gcm_update( &ctx, rest_len,
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500913 pt_test_data[pt_index_test_data[i]] + 32,
914 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200915 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100916 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200917 }
918 else
919 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100920 ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i],
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500921 pt_test_data[pt_index_test_data[i]],
922 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200923 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100924 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200925 }
926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100928 if( ret != 0 )
929 goto exit;
930
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500931 if( memcmp( buf, ct_test_data[j * 6 + i],
932 pt_len_test_data[i] ) != 0 ||
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100933 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200934 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100935 ret = 1;
936 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200937 }
938
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200940
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200941 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200942 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200943
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100944 mbedtls_gcm_init( &ctx );
945
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200946 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100948 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200949
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100950 ret = mbedtls_gcm_setkey( &ctx, cipher,
951 key_test_data[key_index_test_data[i]],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100952 key_len );
953 if( ret != 0 )
954 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100957 iv_test_data[iv_index_test_data[i]],
958 iv_len_test_data[i],
959 additional_test_data[add_index_test_data[i]],
960 add_len_test_data[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200961 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100962 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200963
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100964 if( pt_len_test_data[i] > 32 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200965 {
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100966 size_t rest_len = pt_len_test_data[i] - 32;
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500967 ret = mbedtls_gcm_update( &ctx, 32, ct_test_data[j * 6 + 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
Andrzej Kurekee3c4352019-01-10 03:10:02 -0500972 ret = mbedtls_gcm_update( &ctx, rest_len,
973 ct_test_data[j * 6 + i] + 32,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100974 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],
981 ct_test_data[j * 6 + i],
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100982 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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100988 if( ret != 0 )
989 goto exit;
990
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100991 if( memcmp( buf, pt_test_data[pt_index_test_data[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 Bakker89e80c92012-03-20 13:50:09 +00001003 }
1004 }
Paul Bakker169b7f42013-06-25 14:58:00 +02001005
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +02001006 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +00001008
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +01001009 ret = 0;
1010
1011exit:
1012 if( ret != 0 )
1013 {
1014 if( verbose != 0 )
1015 mbedtls_printf( "failed\n" );
1016 mbedtls_gcm_free( &ctx );
1017 }
1018
1019 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +00001020}
1021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +00001023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024#endif /* MBEDTLS_GCM_C */