blob: 294a86d3d47d21d14053594ec36b8973d1034b5e [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
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é-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker89e80c92012-03-20 13:50:09 +000020 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010021
Paul Bakker89e80c92012-03-20 13:50:09 +000022/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010023 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
24 *
25 * See also:
26 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
27 *
28 * We use the algorithm described as Shoup's method with 4-bit tables in
29 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000030 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000033#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020034#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020036#endif
Paul Bakker89e80c92012-03-20 13:50:09 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/gcm.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000041
Rich Evans00ab4702015-02-06 13:43:58 +000042#include <string.h>
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_AESNI_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010046#endif
47
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +010049#include "mbedtls/aes.h"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000051#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010052#else
Rich Evans00ab4702015-02-06 13:43:58 +000053#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#define mbedtls_printf printf
55#endif /* MBEDTLS_PLATFORM_C */
56#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010057
Jaeden Amero15263302017-09-21 12:53:48 +010058#if !defined(MBEDTLS_GCM_ALT)
59
Paul Bakker89e80c92012-03-20 13:50:09 +000060/*
61 * 32-bit integer manipulation macros (big endian)
62 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000063#ifndef GET_UINT32_BE
64#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000065{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000066 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
67 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
68 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
69 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000070}
71#endif
72
Paul Bakker5c2364c2012-10-01 14:41:15 +000073#ifndef PUT_UINT32_BE
74#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000075{ \
76 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
77 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
78 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
79 (b)[(i) + 3] = (unsigned char) ( (n) ); \
80}
81#endif
82
Paul Bakker34617722014-06-13 17:20:13 +020083/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020085 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
86}
87
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010088/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020089 * Initialize a context
90 */
91void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
92{
93 memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
94}
95
96/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010097 * Precompute small multiples of H, that is set
98 * HH[i] || HL[i] = H times i,
99 * where i is seen as a field element as in [MGV], ie high-order bits
100 * correspond to low powers of P. The result is stored in the same way, that
101 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
102 * corresponds to P^127.
103 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +0000105{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200106 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +0000107 uint64_t hi, lo;
108 uint64_t vl, vh;
109 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200110 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200111
Paul Bakker89e80c92012-03-20 13:50:09 +0000112 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200114 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000115
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100116 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000117 GET_UINT32_BE( hi, h, 0 );
118 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000119 vh = (uint64_t) hi << 32 | lo;
120
Paul Bakker5c2364c2012-10-01 14:41:15 +0000121 GET_UINT32_BE( hi, h, 8 );
122 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000123 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200124
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100125 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000126 ctx->HL[8] = vl;
127 ctx->HH[8] = vh;
128
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100130 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100131 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100132 return( 0 );
133#endif
134
135 /* 0 corresponds to 0 in GF(2^128) */
136 ctx->HH[0] = 0;
137 ctx->HL[0] = 0;
138
Paul Bakker89e80c92012-03-20 13:50:09 +0000139 for( i = 4; i > 0; i >>= 1 )
140 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200141 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000142 vl = ( vh << 63 ) | ( vl >> 1 );
143 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
144
145 ctx->HL[i] = vl;
146 ctx->HH[i] = vh;
147 }
148
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000149 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000150 {
151 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
152 vh = *HiH;
153 vl = *HiL;
154 for( j = 1; j < i; j++ )
155 {
156 HiH[j] = vh ^ ctx->HH[j];
157 HiL[j] = vl ^ ctx->HL[j];
158 }
159 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200160
161 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000162}
163
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200164int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
165 mbedtls_cipher_id_t cipher,
166 const unsigned char *key,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200167 unsigned int keybits )
Paul Bakker89e80c92012-03-20 13:50:09 +0000168{
169 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000171
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200172 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200173 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200175
Paul Bakkera0558e02013-09-10 14:25:51 +0200176 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200178
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200179 mbedtls_cipher_free( &ctx->cipher_ctx );
180
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200181 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000182 return( ret );
183
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200184 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200186 {
187 return( ret );
188 }
189
190 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
191 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000192
193 return( 0 );
194}
195
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100196/*
197 * Shoup's method for multiplication use this table with
198 * last4[x] = x times P^128
199 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
200 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000201static const uint64_t last4[16] =
202{
203 0x0000, 0x1c20, 0x3840, 0x2460,
204 0x7080, 0x6ca0, 0x48c0, 0x54e0,
205 0xe100, 0xfd20, 0xd940, 0xc560,
206 0x9180, 0x8da0, 0xa9c0, 0xb5e0
207};
208
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100209/*
210 * Sets output to x times H using the precomputed tables.
211 * x and output are seen as elements of GF(2^128) as in [MGV].
212 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200214 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000215{
216 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000217 unsigned char lo, hi, rem;
218 uint64_t zh, zl;
219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100221 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100222 unsigned char h[16];
223
224 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
225 PUT_UINT32_BE( ctx->HH[8], h, 4 );
226 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
227 PUT_UINT32_BE( ctx->HL[8], h, 12 );
228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100230 return;
231 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100233
Paul Bakker89e80c92012-03-20 13:50:09 +0000234 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000235
236 zh = ctx->HH[lo];
237 zl = ctx->HL[lo];
238
239 for( i = 15; i >= 0; i-- )
240 {
241 lo = x[i] & 0xf;
242 hi = x[i] >> 4;
243
244 if( i != 15 )
245 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000246 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000247 zl = ( zh << 60 ) | ( zl >> 4 );
248 zh = ( zh >> 4 );
249 zh ^= (uint64_t) last4[rem] << 48;
250 zh ^= ctx->HH[lo];
251 zl ^= ctx->HL[lo];
252
253 }
254
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000255 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000256 zl = ( zh << 60 ) | ( zl >> 4 );
257 zh = ( zh >> 4 );
258 zh ^= (uint64_t) last4[rem] << 48;
259 zh ^= ctx->HH[hi];
260 zl ^= ctx->HL[hi];
261 }
262
Paul Bakker5c2364c2012-10-01 14:41:15 +0000263 PUT_UINT32_BE( zh >> 32, output, 0 );
264 PUT_UINT32_BE( zh, output, 4 );
265 PUT_UINT32_BE( zl >> 32, output, 8 );
266 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000267}
268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200270 int mode,
271 const unsigned char *iv,
272 size_t iv_len,
273 const unsigned char *add,
274 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000275{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200276 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000277 unsigned char work_buf[16];
278 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000279 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200280 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000281
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200282 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200283 /* IV is not allowed to be zero length */
284 if( iv_len == 0 ||
285 ( (uint64_t) iv_len ) >> 61 != 0 ||
286 ( (uint64_t) add_len ) >> 61 != 0 )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200287 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200289 }
290
Paul Bakker52cf16c2013-07-26 13:55:38 +0200291 memset( ctx->y, 0x00, sizeof(ctx->y) );
292 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
293
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200294 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200295 ctx->len = 0;
296 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000297
298 if( iv_len == 12 )
299 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200300 memcpy( ctx->y, iv, iv_len );
301 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000302 }
303 else
304 {
305 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000306 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000307
308 p = iv;
309 while( iv_len > 0 )
310 {
311 use_len = ( iv_len < 16 ) ? iv_len : 16;
312
Paul Bakker67f9d532012-10-23 11:49:05 +0000313 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200314 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200315
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200316 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000317
318 iv_len -= use_len;
319 p += use_len;
320 }
321
Paul Bakker67f9d532012-10-23 11:49:05 +0000322 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200323 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000324
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200325 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000326 }
327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200329 &olen ) ) != 0 )
330 {
331 return( ret );
332 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000333
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200334 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000335 p = add;
336 while( add_len > 0 )
337 {
338 use_len = ( add_len < 16 ) ? add_len : 16;
339
Paul Bakker67f9d532012-10-23 11:49:05 +0000340 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200341 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200342
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200343 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000344
345 add_len -= use_len;
346 p += use_len;
347 }
348
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200349 return( 0 );
350}
351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200353 size_t length,
354 const unsigned char *input,
355 unsigned char *output )
356{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200357 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200358 unsigned char ectr[16];
359 size_t i;
360 const unsigned char *p;
361 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200362 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200363
364 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200366
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200367 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
368 * Also check for possible overflow */
369 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard1e075622015-12-10 14:46:25 +0100370 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200371 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200373 }
374
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200375 ctx->len += length;
376
Paul Bakker89e80c92012-03-20 13:50:09 +0000377 p = input;
378 while( length > 0 )
379 {
380 use_len = ( length < 16 ) ? length : 16;
381
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100382 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200383 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000384 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000385
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200387 &olen ) ) != 0 )
388 {
389 return( ret );
390 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000391
Paul Bakker67f9d532012-10-23 11:49:05 +0000392 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000393 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200395 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000396 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200398 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000399 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200400
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200401 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200402
Paul Bakker89e80c92012-03-20 13:50:09 +0000403 length -= use_len;
404 p += use_len;
405 out_p += use_len;
406 }
407
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200408 return( 0 );
409}
410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200412 unsigned char *tag,
413 size_t tag_len )
414{
415 unsigned char work_buf[16];
416 size_t i;
417 uint64_t orig_len = ctx->len * 8;
418 uint64_t orig_add_len = ctx->add_len * 8;
419
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200420 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200422
Andres AG821da842016-09-26 10:09:30 +0100423 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200424
Paul Bakker89e80c92012-03-20 13:50:09 +0000425 if( orig_len || orig_add_len )
426 {
427 memset( work_buf, 0x00, 16 );
428
Paul Bakker0ecdb232013-04-09 11:36:42 +0200429 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
430 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
431 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
432 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000433
Paul Bakker67f9d532012-10-23 11:49:05 +0000434 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200435 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000436
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200437 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000438
Paul Bakker67f9d532012-10-23 11:49:05 +0000439 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200440 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000441 }
442
443 return( 0 );
444}
445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200447 int mode,
448 size_t length,
449 const unsigned char *iv,
450 size_t iv_len,
451 const unsigned char *add,
452 size_t add_len,
453 const unsigned char *input,
454 unsigned char *output,
455 size_t tag_len,
456 unsigned char *tag )
457{
458 int ret;
459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200461 return( ret );
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200464 return( ret );
465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200467 return( ret );
468
469 return( 0 );
470}
471
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000473 size_t length,
474 const unsigned char *iv,
475 size_t iv_len,
476 const unsigned char *add,
477 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200478 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000479 size_t tag_len,
480 const unsigned char *input,
481 unsigned char *output )
482{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100483 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000484 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200485 size_t i;
486 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000487
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100489 iv, iv_len, add, add_len,
490 input, output, tag_len, check_tag ) ) != 0 )
491 {
492 return( ret );
493 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000494
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200495 /* Check tag in "constant-time" */
496 for( diff = 0, i = 0; i < tag_len; i++ )
497 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000498
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200499 if( diff != 0 )
500 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 mbedtls_zeroize( output, length );
502 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200503 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000504
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200505 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000506}
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200509{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 mbedtls_cipher_free( &ctx->cipher_ctx );
511 mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200512}
513
Jaeden Amero15263302017-09-21 12:53:48 +0100514#endif /* !MBEDTLS_GCM_ALT */
515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000517/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200518 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000519 *
520 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
521 */
522#define MAX_TESTS 6
523
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000524static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000525 { 0, 0, 1, 1, 1, 1 };
526
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000527static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000528{
529 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
533 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
534 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
535 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200536 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000537};
538
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000539static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000540 { 12, 12, 12, 12, 8, 60 };
541
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000542static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000543 { 0, 0, 1, 1, 1, 2 };
544
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000545static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000546{
547 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548 0x00, 0x00, 0x00, 0x00 },
549 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
550 0xde, 0xca, 0xf8, 0x88 },
551 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200552 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000553 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200554 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000555 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200556 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000557 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200558 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000559};
560
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000561static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000562 { 0, 0, 0, 20, 20, 20 };
563
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000564static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000565 { 0, 0, 0, 1, 1, 1 };
566
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000567static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000568{
569 { 0x00 },
570 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200571 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000572 0xab, 0xad, 0xda, 0xd2 },
573};
574
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000575static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000576 { 0, 16, 64, 60, 60, 60 };
577
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000578static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000579 { 0, 0, 1, 1, 1, 1 };
580
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000581static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000582{
583 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
585 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
586 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
587 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
588 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
589 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
590 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
591 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
592 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
593};
594
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000595static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000596{
597 { 0x00 },
598 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
599 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
600 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200601 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000602 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200603 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000604 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200605 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000606 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
607 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
608 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200609 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000610 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200611 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000612 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200613 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000614 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
615 0x3d, 0x58, 0xe0, 0x91 },
616 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200617 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000618 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200619 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000620 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200621 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000622 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
623 0xc2, 0x3f, 0x45, 0x98 },
624 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200625 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000626 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200627 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000628 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200629 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000630 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
631 0x4c, 0x34, 0xae, 0xe5 },
632 { 0x00 },
633 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200634 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000635 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200636 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000637 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200638 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000639 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200640 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000641 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
642 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
643 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200644 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000645 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200646 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
647 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
648 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000649 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200650 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000651 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200652 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000653 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200654 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000655 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200656 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000657 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200658 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000659 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200660 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000661 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200662 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000663 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200664 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000665 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200666 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000667 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200668 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
669 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
670 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
671 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
672 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
673 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
674 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
675 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
676 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
677 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
678 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
679 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
680 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
681 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
682 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
683 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
684 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
685 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000686 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200687 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000688 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200689 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000690 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200691 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000692 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200693 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000694 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200695 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000696 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200697 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000698 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200699 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000700 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200701 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000702};
703
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000704static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000705{
706 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
707 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
708 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
709 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
710 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200711 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000712 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
713 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
714 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
715 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
716 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
717 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
718 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
719 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
720 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200721 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000722 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
723 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
724 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200725 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000726 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200727 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000728 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200729 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000730 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200731 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000732 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200733 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000734 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200735 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000736 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200737 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000738 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200739 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000740 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200741 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000742};
743
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000745{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000747 unsigned char buf[64];
748 unsigned char tag_buf[16];
749 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000751
752 for( j = 0; j < 3; j++ )
753 {
754 int key_len = 128 + 64 * j;
755
756 for( i = 0; i < MAX_TESTS; i++ )
757 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100758 mbedtls_gcm_init( &ctx );
759
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200760 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100762 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200763
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100764 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
765 key_len );
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100766 /*
767 * AES-192 is an optional feature that may be unavailable when
768 * there is an alternative underlying implementation i.e. when
769 * MBEDTLS_AES_ALT is defined.
770 */
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100771 if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
772 {
773 mbedtls_printf( "skipped\n" );
774 break;
775 }
776 else if( ret != 0 )
777 {
778 goto exit;
779 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000780
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100782 pt_len[i],
783 iv[iv_index[i]], iv_len[i],
784 additional[add_index[i]], add_len[i],
785 pt[pt_index[i]], buf, 16, tag_buf );
786 if( ret != 0 )
787 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000788
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100789 if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
790 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000791 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100792 ret = 1;
793 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000794 }
795
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200797
Paul Bakker89e80c92012-03-20 13:50:09 +0000798 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200799 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000800
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100801 mbedtls_gcm_init( &ctx );
802
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200803 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100805 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200806
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100807 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
808 key_len );
809 if( ret != 0 )
810 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000811
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200812 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100813 pt_len[i],
814 iv[iv_index[i]], iv_len[i],
815 additional[add_index[i]], add_len[i],
816 ct[j * 6 + i], buf, 16, tag_buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000817
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100818 if( ret != 0 )
819 goto exit;
820
821 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakker89e80c92012-03-20 13:50:09 +0000822 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
823 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100824 ret = 1;
825 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000826 }
827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200829
Paul Bakker89e80c92012-03-20 13:50:09 +0000830 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200832
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100833 mbedtls_gcm_init( &ctx );
834
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200835 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200836 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100837 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200838
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100839 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
840 key_len );
841 if( ret != 0 )
842 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200844 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100845 iv[iv_index[i]], iv_len[i],
846 additional[add_index[i]], add_len[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200847 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100848 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200849
850 if( pt_len[i] > 32 )
851 {
852 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200854 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100855 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200858 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200859 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100860 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200861 }
862 else
863 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200865 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100866 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200867 }
868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100870 if( ret != 0 )
871 goto exit;
872
873 if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200874 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
875 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100876 ret = 1;
877 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200878 }
879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200881
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200882 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200883 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200884
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100885 mbedtls_gcm_init( &ctx );
886
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200887 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100889 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200890
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100891 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
892 key_len );
893 if( ret != 0 )
894 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200897 iv[iv_index[i]], iv_len[i],
898 additional[add_index[i]], add_len[i] );
899 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100900 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200901
902 if( pt_len[i] > 32 )
903 {
904 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200906 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100907 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200908
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200909 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100910 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200911 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100912 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200913 }
914 else
915 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100916 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
917 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200918 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100919 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200920 }
921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200922 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100923 if( ret != 0 )
924 goto exit;
925
926 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200927 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
928 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100929 ret = 1;
930 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200931 }
932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200934
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200935 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000937 }
938 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200939
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200940 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000942
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100943 ret = 0;
944
945exit:
946 if( ret != 0 )
947 {
948 if( verbose != 0 )
949 mbedtls_printf( "failed\n" );
950 mbedtls_gcm_free( &ctx );
951 }
952
953 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000954}
955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958#endif /* MBEDTLS_GCM_C */