blob: f1210c52c39a28607a13c6d9f8b1f6bd3a7f5a61 [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 */
280 if( ( (uint64_t) iv_len ) >> 61 != 0 ||
281 ( (uint64_t) add_len ) >> 61 != 0 )
282 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200284 }
285
Paul Bakker52cf16c2013-07-26 13:55:38 +0200286 memset( ctx->y, 0x00, sizeof(ctx->y) );
287 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
288
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200289 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200290 ctx->len = 0;
291 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000292
293 if( iv_len == 12 )
294 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200295 memcpy( ctx->y, iv, iv_len );
296 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000297 }
298 else
299 {
300 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000301 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000302
303 p = iv;
304 while( iv_len > 0 )
305 {
306 use_len = ( iv_len < 16 ) ? iv_len : 16;
307
Paul Bakker67f9d532012-10-23 11:49:05 +0000308 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200309 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200310
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200311 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000312
313 iv_len -= use_len;
314 p += use_len;
315 }
316
Paul Bakker67f9d532012-10-23 11:49:05 +0000317 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200318 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000319
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200320 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000321 }
322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200324 &olen ) ) != 0 )
325 {
326 return( ret );
327 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000328
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200329 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000330 p = add;
331 while( add_len > 0 )
332 {
333 use_len = ( add_len < 16 ) ? add_len : 16;
334
Paul Bakker67f9d532012-10-23 11:49:05 +0000335 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200336 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200337
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200338 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000339
340 add_len -= use_len;
341 p += use_len;
342 }
343
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200344 return( 0 );
345}
346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200348 size_t length,
349 const unsigned char *input,
350 unsigned char *output )
351{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200352 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200353 unsigned char ectr[16];
354 size_t i;
355 const unsigned char *p;
356 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200357 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200358
359 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200361
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200362 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
363 * Also check for possible overflow */
364 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard1e075622015-12-10 14:46:25 +0100365 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200366 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200368 }
369
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200370 ctx->len += length;
371
Paul Bakker89e80c92012-03-20 13:50:09 +0000372 p = input;
373 while( length > 0 )
374 {
375 use_len = ( length < 16 ) ? length : 16;
376
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100377 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200378 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000379 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200382 &olen ) ) != 0 )
383 {
384 return( ret );
385 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000386
Paul Bakker67f9d532012-10-23 11:49:05 +0000387 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000388 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200390 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000391 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200393 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000394 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200395
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200396 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200397
Paul Bakker89e80c92012-03-20 13:50:09 +0000398 length -= use_len;
399 p += use_len;
400 out_p += use_len;
401 }
402
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200403 return( 0 );
404}
405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200407 unsigned char *tag,
408 size_t tag_len )
409{
410 unsigned char work_buf[16];
411 size_t i;
412 uint64_t orig_len = ctx->len * 8;
413 uint64_t orig_add_len = ctx->add_len * 8;
414
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200415 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200417
Andres AG821da842016-09-26 10:09:30 +0100418 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200419
Paul Bakker89e80c92012-03-20 13:50:09 +0000420 if( orig_len || orig_add_len )
421 {
422 memset( work_buf, 0x00, 16 );
423
Paul Bakker0ecdb232013-04-09 11:36:42 +0200424 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
425 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
426 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
427 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000428
Paul Bakker67f9d532012-10-23 11:49:05 +0000429 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200430 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000431
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200432 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000433
Paul Bakker67f9d532012-10-23 11:49:05 +0000434 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200435 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000436 }
437
438 return( 0 );
439}
440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200442 int mode,
443 size_t length,
444 const unsigned char *iv,
445 size_t iv_len,
446 const unsigned char *add,
447 size_t add_len,
448 const unsigned char *input,
449 unsigned char *output,
450 size_t tag_len,
451 unsigned char *tag )
452{
453 int ret;
454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200456 return( ret );
457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200459 return( ret );
460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200462 return( ret );
463
464 return( 0 );
465}
466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000468 size_t length,
469 const unsigned char *iv,
470 size_t iv_len,
471 const unsigned char *add,
472 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200473 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000474 size_t tag_len,
475 const unsigned char *input,
476 unsigned char *output )
477{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100478 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000479 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200480 size_t i;
481 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100484 iv, iv_len, add, add_len,
485 input, output, tag_len, check_tag ) ) != 0 )
486 {
487 return( ret );
488 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000489
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200490 /* Check tag in "constant-time" */
491 for( diff = 0, i = 0; i < tag_len; i++ )
492 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000493
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200494 if( diff != 0 )
495 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 mbedtls_zeroize( output, length );
497 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200498 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000499
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200500 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000501}
502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200504{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 mbedtls_cipher_free( &ctx->cipher_ctx );
506 mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200507}
508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000510/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200511 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000512 *
513 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
514 */
515#define MAX_TESTS 6
516
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000517static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000518 { 0, 0, 1, 1, 1, 1 };
519
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000520static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000521{
522 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
523 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
526 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
527 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
528 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200529 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000530};
531
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000532static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000533 { 12, 12, 12, 12, 8, 60 };
534
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000535static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000536 { 0, 0, 1, 1, 1, 2 };
537
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000538static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000539{
540 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
541 0x00, 0x00, 0x00, 0x00 },
542 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
543 0xde, 0xca, 0xf8, 0x88 },
544 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200545 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000546 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200547 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000548 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200549 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000550 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200551 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000552};
553
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000554static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000555 { 0, 0, 0, 20, 20, 20 };
556
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000557static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000558 { 0, 0, 0, 1, 1, 1 };
559
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000560static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000561{
562 { 0x00 },
563 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200564 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000565 0xab, 0xad, 0xda, 0xd2 },
566};
567
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000568static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000569 { 0, 16, 64, 60, 60, 60 };
570
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000571static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000572 { 0, 0, 1, 1, 1, 1 };
573
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000574static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000575{
576 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
578 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
579 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
580 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
581 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
582 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
583 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
584 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
585 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
586};
587
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000588static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000589{
590 { 0x00 },
591 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
592 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
593 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200594 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000595 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200596 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000597 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200598 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000599 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
600 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
601 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200602 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000603 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200604 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000605 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200606 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000607 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
608 0x3d, 0x58, 0xe0, 0x91 },
609 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200610 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200612 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000613 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200614 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000615 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
616 0xc2, 0x3f, 0x45, 0x98 },
617 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200618 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000619 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200620 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000621 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200622 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000623 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
624 0x4c, 0x34, 0xae, 0xe5 },
625 { 0x00 },
626 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200627 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000628 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200629 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000630 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200631 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000632 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200633 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000634 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
635 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
636 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200637 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200639 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
640 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
641 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000642 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200645 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000646 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200647 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000656 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
662 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
663 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
664 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
665 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
666 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
667 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
668 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
669 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
670 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
671 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
672 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
673 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
674 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
675 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
676 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
677 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
678 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000679 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200680 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000681 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200682 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000683 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200684 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200686 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000687 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200688 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000689 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200690 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200694 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000695};
696
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000697static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000698{
699 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
700 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
701 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
702 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
703 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200704 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000705 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
706 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
707 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
708 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
709 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
710 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
711 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
712 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
713 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200714 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000715 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
716 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
717 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200718 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000719 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000735};
736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000738{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000740 unsigned char buf[64];
741 unsigned char tag_buf[16];
742 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000744
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200745 mbedtls_gcm_init( &ctx );
746
Paul Bakker89e80c92012-03-20 13:50:09 +0000747 for( j = 0; j < 3; j++ )
748 {
749 int key_len = 128 + 64 * j;
750
751 for( i = 0; i < MAX_TESTS; i++ )
752 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200753 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200754 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100755 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200756
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200757 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000760 pt_len[i],
761 iv[iv_index[i]], iv_len[i],
762 additional[add_index[i]], add_len[i],
763 pt[pt_index[i]], buf, 16, tag_buf );
764
765 if( ret != 0 ||
766 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
767 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
768 {
769 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000771
772 return( 1 );
773 }
774
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200776
Paul Bakker89e80c92012-03-20 13:50:09 +0000777 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000779
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200780 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100782 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200783
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200784 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000785
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200786 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000787 pt_len[i],
788 iv[iv_index[i]], iv_len[i],
789 additional[add_index[i]], add_len[i],
790 ct[j * 6 + i], buf, 16, tag_buf );
791
792 if( ret != 0 ||
793 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
794 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
795 {
796 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000798
799 return( 1 );
800 }
801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200803
Paul Bakker89e80c92012-03-20 13:50:09 +0000804 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200806
807 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100809 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200810
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200811 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200813 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200814 iv[iv_index[i]], iv_len[i],
815 additional[add_index[i]], add_len[i] );
816 if( ret != 0 )
817 {
818 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200820
821 return( 1 );
822 }
823
824 if( pt_len[i] > 32 )
825 {
826 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200827 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200828 if( ret != 0 )
829 {
830 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200832
833 return( 1 );
834 }
835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200836 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200837 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200838 if( ret != 0 )
839 {
840 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200842
843 return( 1 );
844 }
845 }
846 else
847 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200849 if( ret != 0 )
850 {
851 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200852 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200853
854 return( 1 );
855 }
856 }
857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200859 if( ret != 0 ||
860 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
861 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
862 {
863 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200865
866 return( 1 );
867 }
868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200870
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200871 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200873
874 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100876 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200877
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200878 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200881 iv[iv_index[i]], iv_len[i],
882 additional[add_index[i]], add_len[i] );
883 if( ret != 0 )
884 {
885 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200887
888 return( 1 );
889 }
890
891 if( pt_len[i] > 32 )
892 {
893 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200895 if( ret != 0 )
896 {
897 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200899
900 return( 1 );
901 }
902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200904 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200905 if( ret != 0 )
906 {
907 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200909
910 return( 1 );
911 }
912 }
913 else
914 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200916 if( ret != 0 )
917 {
918 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200920
921 return( 1 );
922 }
923 }
924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200926 if( ret != 0 ||
927 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
928 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
929 {
930 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200932
933 return( 1 );
934 }
935
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200937
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200938 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200940
Paul Bakker89e80c92012-03-20 13:50:09 +0000941 }
942 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200943
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200944 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000946
947 return( 0 );
948}
949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952#endif /* MBEDTLS_GCM_C */