blob: 58cb4f2838790065b697ad632ea67251b2f15f89 [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 memset( ctx, 0, sizeof(mbedtls_gcm_context) );
Paul Bakker89e80c92012-03-20 13:50:09 +0000171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 mbedtls_cipher_init( &ctx->cipher_ctx );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 cipher_info = mbedtls_cipher_info_from_values( cipher, keysize, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200175 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200177
Paul Bakkera0558e02013-09-10 14:25:51 +0200178 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 if( ( ret = mbedtls_cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000182 return( ret );
183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keysize,
185 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200186 {
187 return( ret );
188 }
189
190 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
191 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000192
193 return( 0 );
194}
195
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100196/*
197 * Shoup's method for multiplication use this table with
198 * last4[x] = x times P^128
199 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
200 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000201static const uint64_t last4[16] =
202{
203 0x0000, 0x1c20, 0x3840, 0x2460,
204 0x7080, 0x6ca0, 0x48c0, 0x54e0,
205 0xe100, 0xfd20, 0xd940, 0xc560,
206 0x9180, 0x8da0, 0xa9c0, 0xb5e0
207};
208
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100209/*
210 * Sets output to x times H using the precomputed tables.
211 * x and output are seen as elements of GF(2^128) as in [MGV].
212 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200214 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000215{
216 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000217 unsigned char lo, hi, rem;
218 uint64_t zh, zl;
219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
221 if( mbedtls_aesni_supports( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100222 unsigned char h[16];
223
224 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
225 PUT_UINT32_BE( ctx->HH[8], h, 4 );
226 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
227 PUT_UINT32_BE( ctx->HL[8], h, 12 );
228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100230 return;
231 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100233
Paul Bakker89e80c92012-03-20 13:50:09 +0000234 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000235
236 zh = ctx->HH[lo];
237 zl = ctx->HL[lo];
238
239 for( i = 15; i >= 0; i-- )
240 {
241 lo = x[i] & 0xf;
242 hi = x[i] >> 4;
243
244 if( i != 15 )
245 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000246 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000247 zl = ( zh << 60 ) | ( zl >> 4 );
248 zh = ( zh >> 4 );
249 zh ^= (uint64_t) last4[rem] << 48;
250 zh ^= ctx->HH[lo];
251 zl ^= ctx->HL[lo];
252
253 }
254
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000255 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000256 zl = ( zh << 60 ) | ( zl >> 4 );
257 zh = ( zh >> 4 );
258 zh ^= (uint64_t) last4[rem] << 48;
259 zh ^= ctx->HH[hi];
260 zl ^= ctx->HL[hi];
261 }
262
Paul Bakker5c2364c2012-10-01 14:41:15 +0000263 PUT_UINT32_BE( zh >> 32, output, 0 );
264 PUT_UINT32_BE( zh, output, 4 );
265 PUT_UINT32_BE( zl >> 32, output, 8 );
266 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000267}
268
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200270 int mode,
271 const unsigned char *iv,
272 size_t iv_len,
273 const unsigned char *add,
274 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000275{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200276 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000277 unsigned char work_buf[16];
278 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000279 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200280 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000281
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200282 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
283 if( ( (uint64_t) iv_len ) >> 61 != 0 ||
284 ( (uint64_t) add_len ) >> 61 != 0 )
285 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200286 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200287 }
288
Paul Bakker52cf16c2013-07-26 13:55:38 +0200289 memset( ctx->y, 0x00, sizeof(ctx->y) );
290 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
291
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200292 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200293 ctx->len = 0;
294 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000295
296 if( iv_len == 12 )
297 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200298 memcpy( ctx->y, iv, iv_len );
299 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000300 }
301 else
302 {
303 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000304 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000305
306 p = iv;
307 while( iv_len > 0 )
308 {
309 use_len = ( iv_len < 16 ) ? iv_len : 16;
310
Paul Bakker67f9d532012-10-23 11:49:05 +0000311 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200312 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200313
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200314 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000315
316 iv_len -= use_len;
317 p += use_len;
318 }
319
Paul Bakker67f9d532012-10-23 11:49:05 +0000320 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200321 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000322
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200323 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000324 }
325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200327 &olen ) ) != 0 )
328 {
329 return( ret );
330 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000331
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200332 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000333 p = add;
334 while( add_len > 0 )
335 {
336 use_len = ( add_len < 16 ) ? add_len : 16;
337
Paul Bakker67f9d532012-10-23 11:49:05 +0000338 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200339 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200340
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200341 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000342
343 add_len -= use_len;
344 p += use_len;
345 }
346
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200347 return( 0 );
348}
349
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200351 size_t length,
352 const unsigned char *input,
353 unsigned char *output )
354{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200355 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200356 unsigned char ectr[16];
357 size_t i;
358 const unsigned char *p;
359 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200360 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200361
362 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200364
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200365 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
366 * Also check for possible overflow */
367 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard8d77eee2014-07-21 13:59:12 +0200368 (uint64_t) ctx->len + length > 0x03FFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200369 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200371 }
372
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200373 ctx->len += length;
374
Paul Bakker89e80c92012-03-20 13:50:09 +0000375 p = input;
376 while( length > 0 )
377 {
378 use_len = ( length < 16 ) ? length : 16;
379
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100380 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200381 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000382 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200385 &olen ) ) != 0 )
386 {
387 return( ret );
388 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000389
Paul Bakker67f9d532012-10-23 11:49:05 +0000390 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000391 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200393 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000394 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200396 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000397 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200398
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200399 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200400
Paul Bakker89e80c92012-03-20 13:50:09 +0000401 length -= use_len;
402 p += use_len;
403 out_p += use_len;
404 }
405
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200406 return( 0 );
407}
408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200410 unsigned char *tag,
411 size_t tag_len )
412{
413 unsigned char work_buf[16];
414 size_t i;
415 uint64_t orig_len = ctx->len * 8;
416 uint64_t orig_add_len = ctx->add_len * 8;
417
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200418 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200420
Manuel Pégourié-Gonnard9241be72013-08-31 17:31:03 +0200421 if( tag_len != 0 )
422 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200423
Paul Bakker89e80c92012-03-20 13:50:09 +0000424 if( orig_len || orig_add_len )
425 {
426 memset( work_buf, 0x00, 16 );
427
Paul Bakker0ecdb232013-04-09 11:36:42 +0200428 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
429 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
430 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
431 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000432
Paul Bakker67f9d532012-10-23 11:49:05 +0000433 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200434 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000435
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200436 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000437
Paul Bakker67f9d532012-10-23 11:49:05 +0000438 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200439 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000440 }
441
442 return( 0 );
443}
444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200446 int mode,
447 size_t length,
448 const unsigned char *iv,
449 size_t iv_len,
450 const unsigned char *add,
451 size_t add_len,
452 const unsigned char *input,
453 unsigned char *output,
454 size_t tag_len,
455 unsigned char *tag )
456{
457 int ret;
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200460 return( ret );
461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200463 return( ret );
464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200466 return( ret );
467
468 return( 0 );
469}
470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000472 size_t length,
473 const unsigned char *iv,
474 size_t iv_len,
475 const unsigned char *add,
476 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200477 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000478 size_t tag_len,
479 const unsigned char *input,
480 unsigned char *output )
481{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100482 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000483 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200484 size_t i;
485 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100488 iv, iv_len, add, add_len,
489 input, output, tag_len, check_tag ) ) != 0 )
490 {
491 return( ret );
492 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000493
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200494 /* Check tag in "constant-time" */
495 for( diff = 0, i = 0; i < tag_len; i++ )
496 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000497
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200498 if( diff != 0 )
499 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500 mbedtls_zeroize( output, length );
501 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200502 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000503
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200504 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000505}
506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200508{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 mbedtls_cipher_free( &ctx->cipher_ctx );
510 mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200511}
512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000514/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200515 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000516 *
517 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
518 */
519#define MAX_TESTS 6
520
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000521static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000522 { 0, 0, 1, 1, 1, 1 };
523
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000524static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000525{
526 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
530 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
531 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
532 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200533 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000534};
535
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000536static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000537 { 12, 12, 12, 12, 8, 60 };
538
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000539static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000540 { 0, 0, 1, 1, 1, 2 };
541
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000542static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000543{
544 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00 },
546 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
547 0xde, 0xca, 0xf8, 0x88 },
548 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200549 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000550 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200551 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000552 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200553 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000554 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200555 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000556};
557
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000558static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000559 { 0, 0, 0, 20, 20, 20 };
560
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000561static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000562 { 0, 0, 0, 1, 1, 1 };
563
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000564static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000565{
566 { 0x00 },
567 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200568 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000569 0xab, 0xad, 0xda, 0xd2 },
570};
571
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000572static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000573 { 0, 16, 64, 60, 60, 60 };
574
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000575static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000576 { 0, 0, 1, 1, 1, 1 };
577
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000578static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000579{
580 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
582 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
583 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
584 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
585 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
586 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
587 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
588 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
589 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
590};
591
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000592static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000593{
594 { 0x00 },
595 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
596 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
597 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200598 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000599 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200600 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000601 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200602 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000603 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
604 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
605 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200606 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000607 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200608 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000609 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200610 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
612 0x3d, 0x58, 0xe0, 0x91 },
613 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200614 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000615 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200616 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200618 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000619 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
620 0xc2, 0x3f, 0x45, 0x98 },
621 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200622 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000623 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200624 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000625 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200626 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000627 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
628 0x4c, 0x34, 0xae, 0xe5 },
629 { 0x00 },
630 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200631 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000632 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200633 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000634 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200635 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000636 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200637 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
639 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
640 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200641 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000642 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
644 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
645 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000646 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200647 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000656 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200663 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000664 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200665 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
666 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
667 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
668 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
669 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
670 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
671 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
672 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
673 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
674 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
675 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
676 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
677 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
678 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
679 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
680 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
681 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
682 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000683 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200684 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200686 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000687 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200688 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000689 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200690 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200694 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000695 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200696 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000697 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200698 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000699};
700
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000701static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000702{
703 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
704 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
705 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
706 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
707 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200708 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000709 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
710 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
711 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
712 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
713 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
714 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
715 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
716 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
717 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200718 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000719 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
720 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
721 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000735 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200736 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000737 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200738 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000739};
740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000742{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000744 unsigned char buf[64];
745 unsigned char tag_buf[16];
746 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000748
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200749 mbedtls_gcm_init( &ctx );
750
Paul Bakker89e80c92012-03-20 13:50:09 +0000751 for( j = 0; j < 3; j++ )
752 {
753 int key_len = 128 + 64 * j;
754
755 for( i = 0; i < MAX_TESTS; i++ )
756 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200757 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200758 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100759 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200760
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200761 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000764 pt_len[i],
765 iv[iv_index[i]], iv_len[i],
766 additional[add_index[i]], add_len[i],
767 pt[pt_index[i]], buf, 16, tag_buf );
768
769 if( ret != 0 ||
770 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
771 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
772 {
773 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000775
776 return( 1 );
777 }
778
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200779 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200780
Paul Bakker89e80c92012-03-20 13:50:09 +0000781 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000783
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200784 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100786 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200787
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200788 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200790 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000791 pt_len[i],
792 iv[iv_index[i]], iv_len[i],
793 additional[add_index[i]], add_len[i],
794 ct[j * 6 + i], buf, 16, tag_buf );
795
796 if( ret != 0 ||
797 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
798 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
799 {
800 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200801 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000802
803 return( 1 );
804 }
805
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200806 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200807
Paul Bakker89e80c92012-03-20 13:50:09 +0000808 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200809 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200810
811 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200812 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100813 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200814
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200815 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200816
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200817 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200818 iv[iv_index[i]], iv_len[i],
819 additional[add_index[i]], add_len[i] );
820 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
828 if( pt_len[i] > 32 )
829 {
830 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200832 if( ret != 0 )
833 {
834 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200835 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200836
837 return( 1 );
838 }
839
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200841 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200842 if( ret != 0 )
843 {
844 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200845 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200846
847 return( 1 );
848 }
849 }
850 else
851 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200852 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200853 if( ret != 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 }
861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200862 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200863 if( ret != 0 ||
864 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
865 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
866 {
867 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200869
870 return( 1 );
871 }
872
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200873 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200874
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200875 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200877
878 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200879 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100880 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200881
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200882 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200883
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200884 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200885 iv[iv_index[i]], iv_len[i],
886 additional[add_index[i]], add_len[i] );
887 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
895 if( pt_len[i] > 32 )
896 {
897 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200899 if( ret != 0 )
900 {
901 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200903
904 return( 1 );
905 }
906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200908 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200909 if( ret != 0 )
910 {
911 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200912 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200913
914 return( 1 );
915 }
916 }
917 else
918 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200920 if( ret != 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 }
928
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200930 if( ret != 0 ||
931 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
932 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
933 {
934 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200936
937 return( 1 );
938 }
939
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200941
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200942 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200944
Paul Bakker89e80c92012-03-20 13:50:09 +0000945 }
946 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200947
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200948 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000950
951 return( 0 );
952}
953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956#endif /* MBEDTLS_GCM_C */