blob: fccb092bdd01836b99cc84d1e789f2e50ce95339 [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker89e80c92012-03-20 13:50:09 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker89e80c92012-03-20 13:50:09 +000020 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010021
Paul Bakker89e80c92012-03-20 13:50:09 +000022/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010023 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
24 *
25 * See also:
26 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
27 *
28 * We use the algorithm described as Shoup's method with 4-bit tables in
29 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000030 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000033#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020034#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020036#endif
Paul Bakker89e80c92012-03-20 13:50:09 +000037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/gcm.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000041
Rich Evans00ab4702015-02-06 13:43:58 +000042#include <string.h>
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_AESNI_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010046#endif
47
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
49#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000050#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010051#else
Rich Evans00ab4702015-02-06 13:43:58 +000052#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053#define mbedtls_printf printf
54#endif /* MBEDTLS_PLATFORM_C */
55#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010056
Paul Bakker89e80c92012-03-20 13:50:09 +000057/*
58 * 32-bit integer manipulation macros (big endian)
59 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000060#ifndef GET_UINT32_BE
61#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000062{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000063 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
64 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
65 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
66 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000067}
68#endif
69
Paul Bakker5c2364c2012-10-01 14:41:15 +000070#ifndef PUT_UINT32_BE
71#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000072{ \
73 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
74 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
75 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
76 (b)[(i) + 3] = (unsigned char) ( (n) ); \
77}
78#endif
79
Paul Bakker34617722014-06-13 17:20:13 +020080/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020082 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
83}
84
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010085/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020086 * Initialize a context
87 */
88void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
89{
90 memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
91}
92
93/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010094 * Precompute small multiples of H, that is set
95 * HH[i] || HL[i] = H times i,
96 * where i is seen as a field element as in [MGV], ie high-order bits
97 * correspond to low powers of P. The result is stored in the same way, that
98 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
99 * corresponds to P^127.
100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +0000102{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200103 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +0000104 uint64_t hi, lo;
105 uint64_t vl, vh;
106 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200107 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200108
Paul Bakker89e80c92012-03-20 13:50:09 +0000109 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200111 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000112
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100113 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000114 GET_UINT32_BE( hi, h, 0 );
115 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000116 vh = (uint64_t) hi << 32 | lo;
117
Paul Bakker5c2364c2012-10-01 14:41:15 +0000118 GET_UINT32_BE( hi, h, 8 );
119 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000120 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200121
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100122 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000123 ctx->HL[8] = vl;
124 ctx->HH[8] = vh;
125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100127 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100128 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100129 return( 0 );
130#endif
131
132 /* 0 corresponds to 0 in GF(2^128) */
133 ctx->HH[0] = 0;
134 ctx->HL[0] = 0;
135
Paul Bakker89e80c92012-03-20 13:50:09 +0000136 for( i = 4; i > 0; i >>= 1 )
137 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200138 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000139 vl = ( vh << 63 ) | ( vl >> 1 );
140 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
141
142 ctx->HL[i] = vl;
143 ctx->HH[i] = vh;
144 }
145
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000146 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000147 {
148 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
149 vh = *HiH;
150 vl = *HiL;
151 for( j = 1; j < i; j++ )
152 {
153 HiH[j] = vh ^ ctx->HH[j];
154 HiL[j] = vl ^ ctx->HL[j];
155 }
156 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200157
158 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000159}
160
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200161int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
162 mbedtls_cipher_id_t cipher,
163 const unsigned char *key,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200164 unsigned int keybits )
Paul Bakker89e80c92012-03-20 13:50:09 +0000165{
166 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200167 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000168
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200169 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200170 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200172
Paul Bakkera0558e02013-09-10 14:25:51 +0200173 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200175
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200176 mbedtls_cipher_free( &ctx->cipher_ctx );
177
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200178 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000179 return( ret );
180
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200181 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200183 {
184 return( ret );
185 }
186
187 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
188 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000189
190 return( 0 );
191}
192
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100193/*
194 * Shoup's method for multiplication use this table with
195 * last4[x] = x times P^128
196 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
197 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000198static const uint64_t last4[16] =
199{
200 0x0000, 0x1c20, 0x3840, 0x2460,
201 0x7080, 0x6ca0, 0x48c0, 0x54e0,
202 0xe100, 0xfd20, 0xd940, 0xc560,
203 0x9180, 0x8da0, 0xa9c0, 0xb5e0
204};
205
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100206/*
207 * Sets output to x times H using the precomputed tables.
208 * x and output are seen as elements of GF(2^128) as in [MGV].
209 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200211 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000212{
213 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000214 unsigned char lo, hi, rem;
215 uint64_t zh, zl;
216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100218 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100219 unsigned char h[16];
220
221 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
222 PUT_UINT32_BE( ctx->HH[8], h, 4 );
223 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
224 PUT_UINT32_BE( ctx->HL[8], h, 12 );
225
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100227 return;
228 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100230
Paul Bakker89e80c92012-03-20 13:50:09 +0000231 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000232
233 zh = ctx->HH[lo];
234 zl = ctx->HL[lo];
235
236 for( i = 15; i >= 0; i-- )
237 {
238 lo = x[i] & 0xf;
239 hi = x[i] >> 4;
240
241 if( i != 15 )
242 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000243 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000244 zl = ( zh << 60 ) | ( zl >> 4 );
245 zh = ( zh >> 4 );
246 zh ^= (uint64_t) last4[rem] << 48;
247 zh ^= ctx->HH[lo];
248 zl ^= ctx->HL[lo];
249
250 }
251
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000252 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000253 zl = ( zh << 60 ) | ( zl >> 4 );
254 zh = ( zh >> 4 );
255 zh ^= (uint64_t) last4[rem] << 48;
256 zh ^= ctx->HH[hi];
257 zl ^= ctx->HL[hi];
258 }
259
Paul Bakker5c2364c2012-10-01 14:41:15 +0000260 PUT_UINT32_BE( zh >> 32, output, 0 );
261 PUT_UINT32_BE( zh, output, 4 );
262 PUT_UINT32_BE( zl >> 32, output, 8 );
263 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000264}
265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200266int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200267 int mode,
268 const unsigned char *iv,
269 size_t iv_len,
270 const unsigned char *add,
271 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000272{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200273 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000274 unsigned char work_buf[16];
275 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000276 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200277 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000278
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200279 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5ff277e2017-07-20 00:30:44 +0200280 /* IV is not allowed to be zero length */
281 if( iv_len == 0 ||
282 ( (uint64_t) iv_len ) >> 61 != 0 ||
283 ( (uint64_t) add_len ) >> 61 != 0 )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200284 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200286 }
287
Paul Bakker52cf16c2013-07-26 13:55:38 +0200288 memset( ctx->y, 0x00, sizeof(ctx->y) );
289 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
290
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200291 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200292 ctx->len = 0;
293 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000294
295 if( iv_len == 12 )
296 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200297 memcpy( ctx->y, iv, iv_len );
298 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000299 }
300 else
301 {
302 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000303 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000304
305 p = iv;
306 while( iv_len > 0 )
307 {
308 use_len = ( iv_len < 16 ) ? iv_len : 16;
309
Paul Bakker67f9d532012-10-23 11:49:05 +0000310 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200311 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200312
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200313 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000314
315 iv_len -= use_len;
316 p += use_len;
317 }
318
Paul Bakker67f9d532012-10-23 11:49:05 +0000319 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200320 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000321
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200322 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000323 }
324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200325 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200326 &olen ) ) != 0 )
327 {
328 return( ret );
329 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000330
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200331 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000332 p = add;
333 while( add_len > 0 )
334 {
335 use_len = ( add_len < 16 ) ? add_len : 16;
336
Paul Bakker67f9d532012-10-23 11:49:05 +0000337 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200338 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200339
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200340 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000341
342 add_len -= use_len;
343 p += use_len;
344 }
345
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200346 return( 0 );
347}
348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200350 size_t length,
351 const unsigned char *input,
352 unsigned char *output )
353{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200354 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200355 unsigned char ectr[16];
356 size_t i;
357 const unsigned char *p;
358 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200359 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200360
361 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200363
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200364 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
365 * Also check for possible overflow */
366 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard9055c1a2015-12-10 14:46:25 +0100367 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200368 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200370 }
371
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200372 ctx->len += length;
373
Paul Bakker89e80c92012-03-20 13:50:09 +0000374 p = input;
375 while( length > 0 )
376 {
377 use_len = ( length < 16 ) ? length : 16;
378
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100379 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200380 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000381 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200384 &olen ) ) != 0 )
385 {
386 return( ret );
387 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000388
Paul Bakker67f9d532012-10-23 11:49:05 +0000389 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000390 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200392 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000393 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200395 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000396 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200397
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200398 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200399
Paul Bakker89e80c92012-03-20 13:50:09 +0000400 length -= use_len;
401 p += use_len;
402 out_p += use_len;
403 }
404
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200405 return( 0 );
406}
407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200409 unsigned char *tag,
410 size_t tag_len )
411{
412 unsigned char work_buf[16];
413 size_t i;
414 uint64_t orig_len = ctx->len * 8;
415 uint64_t orig_add_len = ctx->add_len * 8;
416
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200417 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200419
Andres AG6c052082016-09-26 10:09:30 +0100420 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 */