blob: f84511ad014126615ea290748396bbced9cc333c [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é-Gonnardc730ed32015-06-02 10:38:50 +0100129 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100130 return( 0 );
131#endif
132
133 /* 0 corresponds to 0 in GF(2^128) */
134 ctx->HH[0] = 0;
135 ctx->HL[0] = 0;
136
Paul Bakker89e80c92012-03-20 13:50:09 +0000137 for( i = 4; i > 0; i >>= 1 )
138 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200139 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000140 vl = ( vh << 63 ) | ( vl >> 1 );
141 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
142
143 ctx->HL[i] = vl;
144 ctx->HH[i] = vh;
145 }
146
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000147 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000148 {
149 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
150 vh = *HiH;
151 vl = *HiL;
152 for( j = 1; j < i; j++ )
153 {
154 HiH[j] = vh ^ ctx->HH[j];
155 HiL[j] = vl ^ ctx->HL[j];
156 }
157 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200158
159 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000160}
161
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200162int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
163 mbedtls_cipher_id_t cipher,
164 const unsigned char *key,
165 unsigned int keysize )
Paul Bakker89e80c92012-03-20 13:50:09 +0000166{
167 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 cipher_info = mbedtls_cipher_info_from_values( cipher, keysize, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200171 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200173
Paul Bakkera0558e02013-09-10 14:25:51 +0200174 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200176
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200177 mbedtls_cipher_free( &ctx->cipher_ctx );
178
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200179 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000180 return( ret );
181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keysize,
183 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200184 {
185 return( ret );
186 }
187
188 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
189 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000190
191 return( 0 );
192}
193
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100194/*
195 * Shoup's method for multiplication use this table with
196 * last4[x] = x times P^128
197 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
198 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000199static const uint64_t last4[16] =
200{
201 0x0000, 0x1c20, 0x3840, 0x2460,
202 0x7080, 0x6ca0, 0x48c0, 0x54e0,
203 0xe100, 0xfd20, 0xd940, 0xc560,
204 0x9180, 0x8da0, 0xa9c0, 0xb5e0
205};
206
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100207/*
208 * Sets output to x times H using the precomputed tables.
209 * x and output are seen as elements of GF(2^128) as in [MGV].
210 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200212 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000213{
214 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000215 unsigned char lo, hi, rem;
216 uint64_t zh, zl;
217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100219 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100220 unsigned char h[16];
221
222 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
223 PUT_UINT32_BE( ctx->HH[8], h, 4 );
224 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
225 PUT_UINT32_BE( ctx->HL[8], h, 12 );
226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100228 return;
229 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100231
Paul Bakker89e80c92012-03-20 13:50:09 +0000232 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000233
234 zh = ctx->HH[lo];
235 zl = ctx->HL[lo];
236
237 for( i = 15; i >= 0; i-- )
238 {
239 lo = x[i] & 0xf;
240 hi = x[i] >> 4;
241
242 if( i != 15 )
243 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000244 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000245 zl = ( zh << 60 ) | ( zl >> 4 );
246 zh = ( zh >> 4 );
247 zh ^= (uint64_t) last4[rem] << 48;
248 zh ^= ctx->HH[lo];
249 zl ^= ctx->HL[lo];
250
251 }
252
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000253 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000254 zl = ( zh << 60 ) | ( zl >> 4 );
255 zh = ( zh >> 4 );
256 zh ^= (uint64_t) last4[rem] << 48;
257 zh ^= ctx->HH[hi];
258 zl ^= ctx->HL[hi];
259 }
260
Paul Bakker5c2364c2012-10-01 14:41:15 +0000261 PUT_UINT32_BE( zh >> 32, output, 0 );
262 PUT_UINT32_BE( zh, output, 4 );
263 PUT_UINT32_BE( zl >> 32, output, 8 );
264 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000265}
266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200268 int mode,
269 const unsigned char *iv,
270 size_t iv_len,
271 const unsigned char *add,
272 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000273{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200274 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000275 unsigned char work_buf[16];
276 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000277 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200278 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000279
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200280 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
281 if( ( (uint64_t) iv_len ) >> 61 != 0 ||
282 ( (uint64_t) add_len ) >> 61 != 0 )
283 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200285 }
286
Paul Bakker52cf16c2013-07-26 13:55:38 +0200287 memset( ctx->y, 0x00, sizeof(ctx->y) );
288 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
289
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200290 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200291 ctx->len = 0;
292 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000293
294 if( iv_len == 12 )
295 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200296 memcpy( ctx->y, iv, iv_len );
297 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000298 }
299 else
300 {
301 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000302 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000303
304 p = iv;
305 while( iv_len > 0 )
306 {
307 use_len = ( iv_len < 16 ) ? iv_len : 16;
308
Paul Bakker67f9d532012-10-23 11:49:05 +0000309 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200310 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200311
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200312 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000313
314 iv_len -= use_len;
315 p += use_len;
316 }
317
Paul Bakker67f9d532012-10-23 11:49:05 +0000318 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200319 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000320
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200321 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000322 }
323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200325 &olen ) ) != 0 )
326 {
327 return( ret );
328 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000329
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200330 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000331 p = add;
332 while( add_len > 0 )
333 {
334 use_len = ( add_len < 16 ) ? add_len : 16;
335
Paul Bakker67f9d532012-10-23 11:49:05 +0000336 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200337 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200338
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200339 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000340
341 add_len -= use_len;
342 p += use_len;
343 }
344
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200345 return( 0 );
346}
347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200349 size_t length,
350 const unsigned char *input,
351 unsigned char *output )
352{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200353 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200354 unsigned char ectr[16];
355 size_t i;
356 const unsigned char *p;
357 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200358 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200359
360 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200362
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200363 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
364 * Also check for possible overflow */
365 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard8d77eee2014-07-21 13:59:12 +0200366 (uint64_t) ctx->len + length > 0x03FFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200367 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200369 }
370
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200371 ctx->len += length;
372
Paul Bakker89e80c92012-03-20 13:50:09 +0000373 p = input;
374 while( length > 0 )
375 {
376 use_len = ( length < 16 ) ? length : 16;
377
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100378 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200379 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000380 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200383 &olen ) ) != 0 )
384 {
385 return( ret );
386 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000387
Paul Bakker67f9d532012-10-23 11:49:05 +0000388 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000389 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200391 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000392 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200394 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000395 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200396
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200397 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200398
Paul Bakker89e80c92012-03-20 13:50:09 +0000399 length -= use_len;
400 p += use_len;
401 out_p += use_len;
402 }
403
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200404 return( 0 );
405}
406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200408 unsigned char *tag,
409 size_t tag_len )
410{
411 unsigned char work_buf[16];
412 size_t i;
413 uint64_t orig_len = ctx->len * 8;
414 uint64_t orig_add_len = ctx->add_len * 8;
415
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200416 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200418
Manuel Pégourié-Gonnard9241be72013-08-31 17:31:03 +0200419 if( tag_len != 0 )
420 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200421
Paul Bakker89e80c92012-03-20 13:50:09 +0000422 if( orig_len || orig_add_len )
423 {
424 memset( work_buf, 0x00, 16 );
425
Paul Bakker0ecdb232013-04-09 11:36:42 +0200426 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
427 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
428 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
429 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000430
Paul Bakker67f9d532012-10-23 11:49:05 +0000431 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200432 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000433
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200434 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000435
Paul Bakker67f9d532012-10-23 11:49:05 +0000436 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200437 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000438 }
439
440 return( 0 );
441}
442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200444 int mode,
445 size_t length,
446 const unsigned char *iv,
447 size_t iv_len,
448 const unsigned char *add,
449 size_t add_len,
450 const unsigned char *input,
451 unsigned char *output,
452 size_t tag_len,
453 unsigned char *tag )
454{
455 int ret;
456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200458 return( ret );
459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200461 return( ret );
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200464 return( ret );
465
466 return( 0 );
467}
468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000470 size_t length,
471 const unsigned char *iv,
472 size_t iv_len,
473 const unsigned char *add,
474 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200475 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000476 size_t tag_len,
477 const unsigned char *input,
478 unsigned char *output )
479{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100480 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000481 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200482 size_t i;
483 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100486 iv, iv_len, add, add_len,
487 input, output, tag_len, check_tag ) ) != 0 )
488 {
489 return( ret );
490 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000491
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200492 /* Check tag in "constant-time" */
493 for( diff = 0, i = 0; i < tag_len; i++ )
494 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000495
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200496 if( diff != 0 )
497 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 mbedtls_zeroize( output, length );
499 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200500 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000501
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200502 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000503}
504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200506{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 mbedtls_cipher_free( &ctx->cipher_ctx );
508 mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200509}
510
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000512/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200513 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000514 *
515 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
516 */
517#define MAX_TESTS 6
518
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000519static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000520 { 0, 0, 1, 1, 1, 1 };
521
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000522static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000523{
524 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
528 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
529 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
530 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200531 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000532};
533
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000534static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000535 { 12, 12, 12, 12, 8, 60 };
536
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000537static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000538 { 0, 0, 1, 1, 1, 2 };
539
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000540static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000541{
542 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x00, 0x00, 0x00 },
544 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
545 0xde, 0xca, 0xf8, 0x88 },
546 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200547 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000548 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200549 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000550 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200551 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000552 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200553 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000554};
555
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000556static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000557 { 0, 0, 0, 20, 20, 20 };
558
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000559static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000560 { 0, 0, 0, 1, 1, 1 };
561
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000562static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000563{
564 { 0x00 },
565 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200566 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000567 0xab, 0xad, 0xda, 0xd2 },
568};
569
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000570static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000571 { 0, 16, 64, 60, 60, 60 };
572
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000573static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000574 { 0, 0, 1, 1, 1, 1 };
575
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000576static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000577{
578 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
580 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
581 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
582 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
583 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
584 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
585 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
586 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
587 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
588};
589
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000590static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000591{
592 { 0x00 },
593 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
594 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
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, 0x47, 0x3f, 0x59, 0x85 },
603 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200604 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000605 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200606 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000607 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200608 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000609 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
610 0x3d, 0x58, 0xe0, 0x91 },
611 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200612 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000613 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200614 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000615 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200616 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
618 0xc2, 0x3f, 0x45, 0x98 },
619 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200620 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000621 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200622 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000623 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200624 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000625 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
626 0x4c, 0x34, 0xae, 0xe5 },
627 { 0x00 },
628 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200629 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000630 { 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,
Paul Bakker89e80c92012-03-20 13:50:09 +0000634 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200635 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000636 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
637 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
638 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200639 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000640 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200641 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
642 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
643 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200645 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000646 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200647 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000656 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200663 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
664 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
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, 0x89, 0x80, 0x15, 0xad },
673 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
674 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
675 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
676 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
677 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
678 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
679 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
680 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000681 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200682 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000683 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200684 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200686 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000687 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200688 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000689 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200690 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200694 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000695 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200696 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000697};
698
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000699static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000700{
701 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
702 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
703 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
704 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
705 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200706 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000707 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
708 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
709 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
710 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
711 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
712 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
713 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
714 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
715 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200716 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000717 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
718 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
719 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000735 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200736 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000737};
738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000740{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000742 unsigned char buf[64];
743 unsigned char tag_buf[16];
744 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000746
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200747 mbedtls_gcm_init( &ctx );
748
Paul Bakker89e80c92012-03-20 13:50:09 +0000749 for( j = 0; j < 3; j++ )
750 {
751 int key_len = 128 + 64 * j;
752
753 for( i = 0; i < MAX_TESTS; i++ )
754 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200755 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100757 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200758
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200759 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000760
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000762 pt_len[i],
763 iv[iv_index[i]], iv_len[i],
764 additional[add_index[i]], add_len[i],
765 pt[pt_index[i]], buf, 16, tag_buf );
766
767 if( ret != 0 ||
768 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
769 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
770 {
771 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200772 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000773
774 return( 1 );
775 }
776
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200778
Paul Bakker89e80c92012-03-20 13:50:09 +0000779 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200780 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000781
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200782 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200783 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100784 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200785
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200786 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000787
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000789 pt_len[i],
790 iv[iv_index[i]], iv_len[i],
791 additional[add_index[i]], add_len[i],
792 ct[j * 6 + i], buf, 16, tag_buf );
793
794 if( ret != 0 ||
795 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
796 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
797 {
798 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200799 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000800
801 return( 1 );
802 }
803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200805
Paul Bakker89e80c92012-03-20 13:50:09 +0000806 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200808
809 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200810 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100811 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200812
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200813 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200814
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200815 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200816 iv[iv_index[i]], iv_len[i],
817 additional[add_index[i]], add_len[i] );
818 if( ret != 0 )
819 {
820 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200821 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200822
823 return( 1 );
824 }
825
826 if( pt_len[i] > 32 )
827 {
828 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200839 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200840 if( ret != 0 )
841 {
842 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200843 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200844
845 return( 1 );
846 }
847 }
848 else
849 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200851 if( ret != 0 )
852 {
853 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200855
856 return( 1 );
857 }
858 }
859
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200861 if( ret != 0 ||
862 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
863 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
864 {
865 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200867
868 return( 1 );
869 }
870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200872
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200873 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200875
876 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100878 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200879
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200880 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200883 iv[iv_index[i]], iv_len[i],
884 additional[add_index[i]], add_len[i] );
885 if( ret != 0 )
886 {
887 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200889
890 return( 1 );
891 }
892
893 if( pt_len[i] > 32 )
894 {
895 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200906 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200907 if( ret != 0 )
908 {
909 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200911
912 return( 1 );
913 }
914 }
915 else
916 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200917 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200918 if( ret != 0 )
919 {
920 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200922
923 return( 1 );
924 }
925 }
926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200928 if( ret != 0 ||
929 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
930 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
931 {
932 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200934
935 return( 1 );
936 }
937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200938 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200939
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200940 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200942
Paul Bakker89e80c92012-03-20 13:50:09 +0000943 }
944 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200945
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200946 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000948
949 return( 0 );
950}
951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954#endif /* MBEDTLS_GCM_C */