blob: 79d433a17501108c25cf2b563f6bcbeeb4159d83 [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakker89e80c92012-03-20 13:50:09 +00005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker89e80c92012-03-20 13:50:09 +00007 *
Paul Bakker89e80c92012-03-20 13:50:09 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010022
Paul Bakker89e80c92012-03-20 13:50:09 +000023/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010024 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
25 *
26 * See also:
27 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
28 *
29 * We use the algorithm described as Shoup's method with 4-bit tables in
30 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000031 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020033#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020035#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020036#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020037#endif
Paul Bakker89e80c92012-03-20 13:50:09 +000038
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020039#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000040
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000041#include "mbedtls/gcm.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000042
Rich Evans00ab4702015-02-06 13:43:58 +000043#include <string.h>
44
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_AESNI_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010047#endif
48
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
50#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
Paul Bakker89e80c92012-03-20 13:50:09 +000058/*
59 * 32-bit integer manipulation macros (big endian)
60 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000061#ifndef GET_UINT32_BE
62#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000063{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000064 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
65 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
66 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
67 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000068}
69#endif
70
Paul Bakker5c2364c2012-10-01 14:41:15 +000071#ifndef PUT_UINT32_BE
72#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000073{ \
74 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
75 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
76 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
77 (b)[(i) + 3] = (unsigned char) ( (n) ); \
78}
79#endif
80
Paul Bakker34617722014-06-13 17:20:13 +020081/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020083 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
84}
85
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010086/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020087 * Initialize a context
88 */
89void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
90{
91 memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
92}
93
94/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010095 * Precompute small multiples of H, that is set
96 * HH[i] || HL[i] = H times i,
97 * where i is seen as a field element as in [MGV], ie high-order bits
98 * correspond to low powers of P. The result is stored in the same way, that
99 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
100 * corresponds to P^127.
101 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +0000103{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200104 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +0000105 uint64_t hi, lo;
106 uint64_t vl, vh;
107 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200108 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200109
Paul Bakker89e80c92012-03-20 13:50:09 +0000110 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200112 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000113
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100114 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000115 GET_UINT32_BE( hi, h, 0 );
116 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000117 vh = (uint64_t) hi << 32 | lo;
118
Paul Bakker5c2364c2012-10-01 14:41:15 +0000119 GET_UINT32_BE( hi, h, 8 );
120 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000121 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200122
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100123 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000124 ctx->HL[8] = vl;
125 ctx->HH[8] = vh;
126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100128 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129 if( mbedtls_aesni_supports( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100130 return( 0 );
131#endif
132
133 /* 0 corresponds to 0 in GF(2^128) */
134 ctx->HH[0] = 0;
135 ctx->HL[0] = 0;
136
Paul Bakker89e80c92012-03-20 13:50:09 +0000137 for( i = 4; i > 0; i >>= 1 )
138 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200139 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000140 vl = ( vh << 63 ) | ( vl >> 1 );
141 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
142
143 ctx->HL[i] = vl;
144 ctx->HH[i] = vh;
145 }
146
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000147 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000148 {
149 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
150 vh = *HiH;
151 vl = *HiL;
152 for( j = 1; j < i; j++ )
153 {
154 HiH[j] = vh ^ ctx->HH[j];
155 HiL[j] = vl ^ ctx->HL[j];
156 }
157 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200158
159 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000160}
161
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200162int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
163 mbedtls_cipher_id_t cipher,
164 const unsigned char *key,
165 unsigned int keysize )
Paul Bakker89e80c92012-03-20 13:50:09 +0000166{
167 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 cipher_info = mbedtls_cipher_info_from_values( cipher, keysize, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200171 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200173
Paul Bakkera0558e02013-09-10 14:25:51 +0200174 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200176
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200177 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000178 return( ret );
179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keysize,
181 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200182 {
183 return( ret );
184 }
185
186 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
187 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000188
189 return( 0 );
190}
191
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100192/*
193 * Shoup's method for multiplication use this table with
194 * last4[x] = x times P^128
195 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
196 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000197static const uint64_t last4[16] =
198{
199 0x0000, 0x1c20, 0x3840, 0x2460,
200 0x7080, 0x6ca0, 0x48c0, 0x54e0,
201 0xe100, 0xfd20, 0xd940, 0xc560,
202 0x9180, 0x8da0, 0xa9c0, 0xb5e0
203};
204
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100205/*
206 * Sets output to x times H using the precomputed tables.
207 * x and output are seen as elements of GF(2^128) as in [MGV].
208 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200210 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000211{
212 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000213 unsigned char lo, hi, rem;
214 uint64_t zh, zl;
215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
217 if( mbedtls_aesni_supports( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100218 unsigned char h[16];
219
220 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
221 PUT_UINT32_BE( ctx->HH[8], h, 4 );
222 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
223 PUT_UINT32_BE( ctx->HL[8], h, 12 );
224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100226 return;
227 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100229
Paul Bakker89e80c92012-03-20 13:50:09 +0000230 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000231
232 zh = ctx->HH[lo];
233 zl = ctx->HL[lo];
234
235 for( i = 15; i >= 0; i-- )
236 {
237 lo = x[i] & 0xf;
238 hi = x[i] >> 4;
239
240 if( i != 15 )
241 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000242 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000243 zl = ( zh << 60 ) | ( zl >> 4 );
244 zh = ( zh >> 4 );
245 zh ^= (uint64_t) last4[rem] << 48;
246 zh ^= ctx->HH[lo];
247 zl ^= ctx->HL[lo];
248
249 }
250
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000251 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000252 zl = ( zh << 60 ) | ( zl >> 4 );
253 zh = ( zh >> 4 );
254 zh ^= (uint64_t) last4[rem] << 48;
255 zh ^= ctx->HH[hi];
256 zl ^= ctx->HL[hi];
257 }
258
Paul Bakker5c2364c2012-10-01 14:41:15 +0000259 PUT_UINT32_BE( zh >> 32, output, 0 );
260 PUT_UINT32_BE( zh, output, 4 );
261 PUT_UINT32_BE( zl >> 32, output, 8 );
262 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000263}
264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200266 int mode,
267 const unsigned char *iv,
268 size_t iv_len,
269 const unsigned char *add,
270 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000271{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200272 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000273 unsigned char work_buf[16];
274 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000275 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200276 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000277
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200278 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
279 if( ( (uint64_t) iv_len ) >> 61 != 0 ||
280 ( (uint64_t) add_len ) >> 61 != 0 )
281 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200283 }
284
Paul Bakker52cf16c2013-07-26 13:55:38 +0200285 memset( ctx->y, 0x00, sizeof(ctx->y) );
286 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
287
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200288 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200289 ctx->len = 0;
290 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000291
292 if( iv_len == 12 )
293 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200294 memcpy( ctx->y, iv, iv_len );
295 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000296 }
297 else
298 {
299 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000300 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000301
302 p = iv;
303 while( iv_len > 0 )
304 {
305 use_len = ( iv_len < 16 ) ? iv_len : 16;
306
Paul Bakker67f9d532012-10-23 11:49:05 +0000307 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200308 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200309
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200310 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000311
312 iv_len -= use_len;
313 p += use_len;
314 }
315
Paul Bakker67f9d532012-10-23 11:49:05 +0000316 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200317 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000318
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200319 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000320 }
321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200323 &olen ) ) != 0 )
324 {
325 return( ret );
326 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000327
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200328 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000329 p = add;
330 while( add_len > 0 )
331 {
332 use_len = ( add_len < 16 ) ? add_len : 16;
333
Paul Bakker67f9d532012-10-23 11:49:05 +0000334 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200335 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200336
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200337 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000338
339 add_len -= use_len;
340 p += use_len;
341 }
342
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200343 return( 0 );
344}
345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200347 size_t length,
348 const unsigned char *input,
349 unsigned char *output )
350{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200351 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200352 unsigned char ectr[16];
353 size_t i;
354 const unsigned char *p;
355 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200356 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200357
358 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200360
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200361 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
362 * Also check for possible overflow */
363 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard8d77eee2014-07-21 13:59:12 +0200364 (uint64_t) ctx->len + length > 0x03FFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200365 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200367 }
368
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200369 ctx->len += length;
370
Paul Bakker89e80c92012-03-20 13:50:09 +0000371 p = input;
372 while( length > 0 )
373 {
374 use_len = ( length < 16 ) ? length : 16;
375
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100376 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200377 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000378 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000379
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200381 &olen ) ) != 0 )
382 {
383 return( ret );
384 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000385
Paul Bakker67f9d532012-10-23 11:49:05 +0000386 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000387 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200389 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000390 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200392 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000393 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200394
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200395 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200396
Paul Bakker89e80c92012-03-20 13:50:09 +0000397 length -= use_len;
398 p += use_len;
399 out_p += use_len;
400 }
401
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200402 return( 0 );
403}
404
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200406 unsigned char *tag,
407 size_t tag_len )
408{
409 unsigned char work_buf[16];
410 size_t i;
411 uint64_t orig_len = ctx->len * 8;
412 uint64_t orig_add_len = ctx->add_len * 8;
413
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200414 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200416
Manuel Pégourié-Gonnard9241be72013-08-31 17:31:03 +0200417 if( tag_len != 0 )
418 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200419
Paul Bakker89e80c92012-03-20 13:50:09 +0000420 if( orig_len || orig_add_len )
421 {
422 memset( work_buf, 0x00, 16 );
423
Paul Bakker0ecdb232013-04-09 11:36:42 +0200424 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
425 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
426 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
427 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000428
Paul Bakker67f9d532012-10-23 11:49:05 +0000429 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200430 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000431
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200432 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000433
Paul Bakker67f9d532012-10-23 11:49:05 +0000434 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200435 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000436 }
437
438 return( 0 );
439}
440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200442 int mode,
443 size_t length,
444 const unsigned char *iv,
445 size_t iv_len,
446 const unsigned char *add,
447 size_t add_len,
448 const unsigned char *input,
449 unsigned char *output,
450 size_t tag_len,
451 unsigned char *tag )
452{
453 int ret;
454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200456 return( ret );
457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200459 return( ret );
460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200462 return( ret );
463
464 return( 0 );
465}
466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000468 size_t length,
469 const unsigned char *iv,
470 size_t iv_len,
471 const unsigned char *add,
472 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200473 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000474 size_t tag_len,
475 const unsigned char *input,
476 unsigned char *output )
477{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100478 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000479 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200480 size_t i;
481 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100484 iv, iv_len, add, add_len,
485 input, output, tag_len, check_tag ) ) != 0 )
486 {
487 return( ret );
488 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000489
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200490 /* Check tag in "constant-time" */
491 for( diff = 0, i = 0; i < tag_len; i++ )
492 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000493
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200494 if( diff != 0 )
495 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 mbedtls_zeroize( output, length );
497 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200498 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000499
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200500 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000501}
502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200504{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 mbedtls_cipher_free( &ctx->cipher_ctx );
506 mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200507}
508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000510/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200511 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000512 *
513 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
514 */
515#define MAX_TESTS 6
516
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000517static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000518 { 0, 0, 1, 1, 1, 1 };
519
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000520static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000521{
522 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
526 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
527 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
528 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200529 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000530};
531
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000532static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000533 { 12, 12, 12, 12, 8, 60 };
534
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000535static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000536 { 0, 0, 1, 1, 1, 2 };
537
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000538static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000539{
540 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00 },
542 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
543 0xde, 0xca, 0xf8, 0x88 },
544 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200545 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000546 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200547 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000548 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200549 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000550 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200551 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000552};
553
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000554static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000555 { 0, 0, 0, 20, 20, 20 };
556
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000557static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000558 { 0, 0, 0, 1, 1, 1 };
559
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000560static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000561{
562 { 0x00 },
563 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200564 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000565 0xab, 0xad, 0xda, 0xd2 },
566};
567
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000568static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000569 { 0, 16, 64, 60, 60, 60 };
570
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000571static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000572 { 0, 0, 1, 1, 1, 1 };
573
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000574static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000575{
576 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
578 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
579 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
580 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
581 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
582 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
583 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
584 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
585 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
586};
587
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000588static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000589{
590 { 0x00 },
591 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
592 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
593 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200594 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000595 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200596 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000597 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200598 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000599 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
600 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
601 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200602 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000603 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200604 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000605 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200606 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000607 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
608 0x3d, 0x58, 0xe0, 0x91 },
609 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200610 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200612 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000613 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200614 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000615 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
616 0xc2, 0x3f, 0x45, 0x98 },
617 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200618 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000619 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200620 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000621 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200622 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000623 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
624 0x4c, 0x34, 0xae, 0xe5 },
625 { 0x00 },
626 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200627 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000628 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200629 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000630 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200631 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000632 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200633 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000634 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
635 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
636 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200637 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200639 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
640 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
641 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000642 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200645 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000646 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200647 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000656 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
662 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
663 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
664 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
665 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
666 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
667 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
668 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
669 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
670 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
671 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
672 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
673 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
674 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
675 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
676 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
677 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
678 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000679 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200680 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000681 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200682 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000683 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200684 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200686 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000687 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200688 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000689 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200690 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200694 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000695};
696
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000697static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000698{
699 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
700 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
701 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
702 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
703 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200704 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000705 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
706 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
707 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
708 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
709 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
710 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
711 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
712 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
713 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200714 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000715 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
716 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
717 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200718 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000719 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000735};
736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000738{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000740 unsigned char buf[64];
741 unsigned char tag_buf[16];
742 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000744
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200745 mbedtls_gcm_init( &ctx );
746
Paul Bakker89e80c92012-03-20 13:50:09 +0000747 for( j = 0; j < 3; j++ )
748 {
749 int key_len = 128 + 64 * j;
750
751 for( i = 0; i < MAX_TESTS; i++ )
752 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200753 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200754 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100755 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200756
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200757 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000760 pt_len[i],
761 iv[iv_index[i]], iv_len[i],
762 additional[add_index[i]], add_len[i],
763 pt[pt_index[i]], buf, 16, tag_buf );
764
765 if( ret != 0 ||
766 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
767 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
768 {
769 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000771
772 return( 1 );
773 }
774
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200776
Paul Bakker89e80c92012-03-20 13:50:09 +0000777 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000779
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200780 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100782 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200783
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200784 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000785
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200786 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000787 pt_len[i],
788 iv[iv_index[i]], iv_len[i],
789 additional[add_index[i]], add_len[i],
790 ct[j * 6 + i], buf, 16, tag_buf );
791
792 if( ret != 0 ||
793 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
794 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
795 {
796 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000798
799 return( 1 );
800 }
801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200803
Paul Bakker89e80c92012-03-20 13:50:09 +0000804 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200806
807 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100809 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200810
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200811 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200813 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200814 iv[iv_index[i]], iv_len[i],
815 additional[add_index[i]], add_len[i] );
816 if( ret != 0 )
817 {
818 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200820
821 return( 1 );
822 }
823
824 if( pt_len[i] > 32 )
825 {
826 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200827 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200828 if( ret != 0 )
829 {
830 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200832
833 return( 1 );
834 }
835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200836 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200837 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200838 if( ret != 0 )
839 {
840 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200842
843 return( 1 );
844 }
845 }
846 else
847 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200849 if( ret != 0 )
850 {
851 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200852 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200853
854 return( 1 );
855 }
856 }
857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200859 if( ret != 0 ||
860 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
861 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
862 {
863 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200865
866 return( 1 );
867 }
868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200870
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200871 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200873
874 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100876 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200877
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200878 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200881 iv[iv_index[i]], iv_len[i],
882 additional[add_index[i]], add_len[i] );
883 if( ret != 0 )
884 {
885 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200887
888 return( 1 );
889 }
890
891 if( pt_len[i] > 32 )
892 {
893 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200895 if( ret != 0 )
896 {
897 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200899
900 return( 1 );
901 }
902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200904 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200905 if( ret != 0 )
906 {
907 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200909
910 return( 1 );
911 }
912 }
913 else
914 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200916 if( ret != 0 )
917 {
918 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200920
921 return( 1 );
922 }
923 }
924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200926 if( ret != 0 ||
927 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
928 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
929 {
930 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200932
933 return( 1 );
934 }
935
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200937
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200938 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200940
Paul Bakker89e80c92012-03-20 13:50:09 +0000941 }
942 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200943
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200944 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000946
947 return( 0 );
948}
949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952#endif /* MBEDTLS_GCM_C */