blob: fe7cf720e6142d81fbd87a1bf3064529e3edc5c2 [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/*
87 * Precompute small multiples of H, that is set
88 * HH[i] || HL[i] = H times i,
89 * where i is seen as a field element as in [MGV], ie high-order bits
90 * correspond to low powers of P. The result is stored in the same way, that
91 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
92 * corresponds to P^127.
93 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +000095{
Paul Bakker43aff2a2013-09-09 00:10:27 +020096 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000097 uint64_t hi, lo;
98 uint64_t vl, vh;
99 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200100 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200101
Paul Bakker89e80c92012-03-20 13:50:09 +0000102 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200104 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000105
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100106 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000107 GET_UINT32_BE( hi, h, 0 );
108 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000109 vh = (uint64_t) hi << 32 | lo;
110
Paul Bakker5c2364c2012-10-01 14:41:15 +0000111 GET_UINT32_BE( hi, h, 8 );
112 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000113 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200114
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100115 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000116 ctx->HL[8] = vl;
117 ctx->HH[8] = vh;
118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100120 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 if( mbedtls_aesni_supports( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100122 return( 0 );
123#endif
124
125 /* 0 corresponds to 0 in GF(2^128) */
126 ctx->HH[0] = 0;
127 ctx->HL[0] = 0;
128
Paul Bakker89e80c92012-03-20 13:50:09 +0000129 for( i = 4; i > 0; i >>= 1 )
130 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200131 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000132 vl = ( vh << 63 ) | ( vl >> 1 );
133 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
134
135 ctx->HL[i] = vl;
136 ctx->HH[i] = vh;
137 }
138
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000139 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000140 {
141 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
142 vh = *HiH;
143 vl = *HiL;
144 for( j = 1; j < i; j++ )
145 {
146 HiH[j] = vh ^ ctx->HH[j];
147 HiL[j] = vl ^ ctx->HL[j];
148 }
149 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200150
151 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000152}
153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154int mbedtls_gcm_init( mbedtls_gcm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200155 unsigned int keysize )
Paul Bakker89e80c92012-03-20 13:50:09 +0000156{
157 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 memset( ctx, 0, sizeof(mbedtls_gcm_context) );
Paul Bakker89e80c92012-03-20 13:50:09 +0000161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 mbedtls_cipher_init( &ctx->cipher_ctx );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 cipher_info = mbedtls_cipher_info_from_values( cipher, keysize, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200165 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200166 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200167
Paul Bakkera0558e02013-09-10 14:25:51 +0200168 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 if( ( ret = mbedtls_cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000172 return( ret );
173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keysize,
175 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200176 {
177 return( ret );
178 }
179
180 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
181 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000182
183 return( 0 );
184}
185
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100186/*
187 * Shoup's method for multiplication use this table with
188 * last4[x] = x times P^128
189 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
190 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000191static const uint64_t last4[16] =
192{
193 0x0000, 0x1c20, 0x3840, 0x2460,
194 0x7080, 0x6ca0, 0x48c0, 0x54e0,
195 0xe100, 0xfd20, 0xd940, 0xc560,
196 0x9180, 0x8da0, 0xa9c0, 0xb5e0
197};
198
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100199/*
200 * Sets output to x times H using the precomputed tables.
201 * x and output are seen as elements of GF(2^128) as in [MGV].
202 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200204 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000205{
206 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000207 unsigned char lo, hi, rem;
208 uint64_t zh, zl;
209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
211 if( mbedtls_aesni_supports( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100212 unsigned char h[16];
213
214 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
215 PUT_UINT32_BE( ctx->HH[8], h, 4 );
216 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
217 PUT_UINT32_BE( ctx->HL[8], h, 12 );
218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100220 return;
221 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100223
Paul Bakker89e80c92012-03-20 13:50:09 +0000224 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000225
226 zh = ctx->HH[lo];
227 zl = ctx->HL[lo];
228
229 for( i = 15; i >= 0; i-- )
230 {
231 lo = x[i] & 0xf;
232 hi = x[i] >> 4;
233
234 if( i != 15 )
235 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000236 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000237 zl = ( zh << 60 ) | ( zl >> 4 );
238 zh = ( zh >> 4 );
239 zh ^= (uint64_t) last4[rem] << 48;
240 zh ^= ctx->HH[lo];
241 zl ^= ctx->HL[lo];
242
243 }
244
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000245 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000246 zl = ( zh << 60 ) | ( zl >> 4 );
247 zh = ( zh >> 4 );
248 zh ^= (uint64_t) last4[rem] << 48;
249 zh ^= ctx->HH[hi];
250 zl ^= ctx->HL[hi];
251 }
252
Paul Bakker5c2364c2012-10-01 14:41:15 +0000253 PUT_UINT32_BE( zh >> 32, output, 0 );
254 PUT_UINT32_BE( zh, output, 4 );
255 PUT_UINT32_BE( zl >> 32, output, 8 );
256 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000257}
258
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200260 int mode,
261 const unsigned char *iv,
262 size_t iv_len,
263 const unsigned char *add,
264 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000265{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200266 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000267 unsigned char work_buf[16];
268 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000269 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200270 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000271
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200272 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
273 if( ( (uint64_t) iv_len ) >> 61 != 0 ||
274 ( (uint64_t) add_len ) >> 61 != 0 )
275 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200277 }
278
Paul Bakker52cf16c2013-07-26 13:55:38 +0200279 memset( ctx->y, 0x00, sizeof(ctx->y) );
280 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
281
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200282 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200283 ctx->len = 0;
284 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000285
286 if( iv_len == 12 )
287 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200288 memcpy( ctx->y, iv, iv_len );
289 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000290 }
291 else
292 {
293 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000294 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000295
296 p = iv;
297 while( iv_len > 0 )
298 {
299 use_len = ( iv_len < 16 ) ? iv_len : 16;
300
Paul Bakker67f9d532012-10-23 11:49:05 +0000301 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200302 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200303
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200304 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000305
306 iv_len -= use_len;
307 p += use_len;
308 }
309
Paul Bakker67f9d532012-10-23 11:49:05 +0000310 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200311 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000312
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200313 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000314 }
315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200317 &olen ) ) != 0 )
318 {
319 return( ret );
320 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000321
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200322 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000323 p = add;
324 while( add_len > 0 )
325 {
326 use_len = ( add_len < 16 ) ? add_len : 16;
327
Paul Bakker67f9d532012-10-23 11:49:05 +0000328 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200329 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200330
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200331 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000332
333 add_len -= use_len;
334 p += use_len;
335 }
336
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200337 return( 0 );
338}
339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200341 size_t length,
342 const unsigned char *input,
343 unsigned char *output )
344{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200345 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200346 unsigned char ectr[16];
347 size_t i;
348 const unsigned char *p;
349 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200350 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200351
352 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200354
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200355 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
356 * Also check for possible overflow */
357 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard8d77eee2014-07-21 13:59:12 +0200358 (uint64_t) ctx->len + length > 0x03FFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200359 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200361 }
362
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200363 ctx->len += length;
364
Paul Bakker89e80c92012-03-20 13:50:09 +0000365 p = input;
366 while( length > 0 )
367 {
368 use_len = ( length < 16 ) ? length : 16;
369
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100370 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200371 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000372 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200375 &olen ) ) != 0 )
376 {
377 return( ret );
378 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000379
Paul Bakker67f9d532012-10-23 11:49:05 +0000380 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200383 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000384 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200386 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000387 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200388
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200389 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200390
Paul Bakker89e80c92012-03-20 13:50:09 +0000391 length -= use_len;
392 p += use_len;
393 out_p += use_len;
394 }
395
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200396 return( 0 );
397}
398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200400 unsigned char *tag,
401 size_t tag_len )
402{
403 unsigned char work_buf[16];
404 size_t i;
405 uint64_t orig_len = ctx->len * 8;
406 uint64_t orig_add_len = ctx->add_len * 8;
407
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200408 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200410
Manuel Pégourié-Gonnard9241be72013-08-31 17:31:03 +0200411 if( tag_len != 0 )
412 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200413
Paul Bakker89e80c92012-03-20 13:50:09 +0000414 if( orig_len || orig_add_len )
415 {
416 memset( work_buf, 0x00, 16 );
417
Paul Bakker0ecdb232013-04-09 11:36:42 +0200418 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
419 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
420 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
421 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000422
Paul Bakker67f9d532012-10-23 11:49:05 +0000423 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200424 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000425
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200426 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000427
Paul Bakker67f9d532012-10-23 11:49:05 +0000428 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200429 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000430 }
431
432 return( 0 );
433}
434
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200436 int mode,
437 size_t length,
438 const unsigned char *iv,
439 size_t iv_len,
440 const unsigned char *add,
441 size_t add_len,
442 const unsigned char *input,
443 unsigned char *output,
444 size_t tag_len,
445 unsigned char *tag )
446{
447 int ret;
448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200450 return( ret );
451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200453 return( ret );
454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200456 return( ret );
457
458 return( 0 );
459}
460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000462 size_t length,
463 const unsigned char *iv,
464 size_t iv_len,
465 const unsigned char *add,
466 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200467 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000468 size_t tag_len,
469 const unsigned char *input,
470 unsigned char *output )
471{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100472 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000473 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200474 size_t i;
475 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100478 iv, iv_len, add, add_len,
479 input, output, tag_len, check_tag ) ) != 0 )
480 {
481 return( ret );
482 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000483
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200484 /* Check tag in "constant-time" */
485 for( diff = 0, i = 0; i < tag_len; i++ )
486 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000487
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200488 if( diff != 0 )
489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 mbedtls_zeroize( output, length );
491 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200492 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000493
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200494 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000495}
496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200498{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_cipher_free( &ctx->cipher_ctx );
500 mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200501}
502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000504/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200505 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000506 *
507 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
508 */
509#define MAX_TESTS 6
510
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000511static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000512 { 0, 0, 1, 1, 1, 1 };
513
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000514static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000515{
516 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
520 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
521 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
522 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200523 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000524};
525
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000526static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000527 { 12, 12, 12, 12, 8, 60 };
528
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000529static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000530 { 0, 0, 1, 1, 1, 2 };
531
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000532static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000533{
534 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00 },
536 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
537 0xde, 0xca, 0xf8, 0x88 },
538 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200539 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000540 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200541 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000542 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200543 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000544 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200545 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000546};
547
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000548static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000549 { 0, 0, 0, 20, 20, 20 };
550
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000551static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000552 { 0, 0, 0, 1, 1, 1 };
553
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000554static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000555{
556 { 0x00 },
557 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200558 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000559 0xab, 0xad, 0xda, 0xd2 },
560};
561
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000562static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000563 { 0, 16, 64, 60, 60, 60 };
564
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000565static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000566 { 0, 0, 1, 1, 1, 1 };
567
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000568static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000569{
570 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
572 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
573 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
574 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
575 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
576 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
577 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
578 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
579 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
580};
581
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000582static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000583{
584 { 0x00 },
585 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
586 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
587 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200588 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000589 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200590 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000591 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200592 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000593 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
594 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
595 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200596 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000597 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200598 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000599 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200600 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000601 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
602 0x3d, 0x58, 0xe0, 0x91 },
603 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200604 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000605 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200606 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000607 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200608 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000609 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
610 0xc2, 0x3f, 0x45, 0x98 },
611 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200612 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000613 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200614 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000615 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200616 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
618 0x4c, 0x34, 0xae, 0xe5 },
619 { 0x00 },
620 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200621 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000622 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200623 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000624 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200625 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000626 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200627 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000628 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
629 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
630 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200631 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000632 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200633 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
634 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
635 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000636 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200637 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200639 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000640 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200641 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000642 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200645 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000646 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200647 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
656 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
657 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
658 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
659 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
660 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
661 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
662 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
663 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
664 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
665 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
666 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
667 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
668 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
669 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
670 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
671 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
672 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000673 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200674 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000675 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200676 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000677 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200678 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000679 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200680 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000681 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200682 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000683 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200684 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200686 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000687 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200688 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000689};
690
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000691static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000692{
693 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
694 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
695 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
696 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
697 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200698 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000699 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
700 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
701 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
702 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
703 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
704 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
705 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
706 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
707 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200708 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000709 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
710 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
711 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200712 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000713 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200714 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000715 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200716 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000717 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200718 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000719 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729};
730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000732{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200733 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000734 unsigned char buf[64];
735 unsigned char tag_buf[16];
736 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000738
739 for( j = 0; j < 3; j++ )
740 {
741 int key_len = 128 + 64 * j;
742
743 for( i = 0; i < MAX_TESTS; i++ )
744 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200745 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100747 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200748
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 mbedtls_gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000752 pt_len[i],
753 iv[iv_index[i]], iv_len[i],
754 additional[add_index[i]], add_len[i],
755 pt[pt_index[i]], buf, 16, tag_buf );
756
757 if( ret != 0 ||
758 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
759 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
760 {
761 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200762 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000763
764 return( 1 );
765 }
766
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200767 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200768
Paul Bakker89e80c92012-03-20 13:50:09 +0000769 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000771
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200772 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100774 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200775
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776 mbedtls_gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000777
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000779 pt_len[i],
780 iv[iv_index[i]], iv_len[i],
781 additional[add_index[i]], add_len[i],
782 ct[j * 6 + i], buf, 16, tag_buf );
783
784 if( ret != 0 ||
785 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
786 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
787 {
788 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200789 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000790
791 return( 1 );
792 }
793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200794 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200795
Paul Bakker89e80c92012-03-20 13:50:09 +0000796 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200798
799 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200800 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100801 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200802
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803 mbedtls_gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200806 iv[iv_index[i]], iv_len[i],
807 additional[add_index[i]], add_len[i] );
808 if( ret != 0 )
809 {
810 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200812
813 return( 1 );
814 }
815
816 if( pt_len[i] > 32 )
817 {
818 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200820 if( ret != 0 )
821 {
822 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200824
825 return( 1 );
826 }
827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200829 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200830 if( ret != 0 )
831 {
832 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200834
835 return( 1 );
836 }
837 }
838 else
839 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200841 if( ret != 0 )
842 {
843 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200844 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200845
846 return( 1 );
847 }
848 }
849
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200851 if( ret != 0 ||
852 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
853 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
854 {
855 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200856 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200857
858 return( 1 );
859 }
860
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200862
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200863 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200865
866 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100868 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870 mbedtls_gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200873 iv[iv_index[i]], iv_len[i],
874 additional[add_index[i]], add_len[i] );
875 if( ret != 0 )
876 {
877 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200878 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200879
880 return( 1 );
881 }
882
883 if( pt_len[i] > 32 )
884 {
885 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200887 if( ret != 0 )
888 {
889 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200891
892 return( 1 );
893 }
894
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200895 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200896 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200897 if( ret != 0 )
898 {
899 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200900 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200901
902 return( 1 );
903 }
904 }
905 else
906 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200908 if( ret != 0 )
909 {
910 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200911 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200912
913 return( 1 );
914 }
915 }
916
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200917 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200918 if( ret != 0 ||
919 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
920 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
921 {
922 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200924
925 return( 1 );
926 }
927
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200929
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200930 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200932
Paul Bakker89e80c92012-03-20 13:50:09 +0000933 }
934 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200935
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200936 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000938
939 return( 0 );
940}
941
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200942#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000943
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944#endif /* MBEDTLS_GCM_C */