blob: 2b49fa66c7a636b684f86c7b143b28f7d934ae11 [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
Jaeden Amero15263302017-09-21 12:53:48 +010057#if !defined(MBEDTLS_GCM_ALT)
58
Paul Bakker89e80c92012-03-20 13:50:09 +000059/*
60 * 32-bit integer manipulation macros (big endian)
61 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000062#ifndef GET_UINT32_BE
63#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000064{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000065 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
66 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
67 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
68 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000069}
70#endif
71
Paul Bakker5c2364c2012-10-01 14:41:15 +000072#ifndef PUT_UINT32_BE
73#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000074{ \
75 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
76 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
77 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
78 (b)[(i) + 3] = (unsigned char) ( (n) ); \
79}
80#endif
81
Paul Bakker34617722014-06-13 17:20:13 +020082/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020084 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
85}
86
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010087/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020088 * Initialize a context
89 */
90void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
91{
92 memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
93}
94
95/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010096 * Precompute small multiples of H, that is set
97 * HH[i] || HL[i] = H times i,
98 * where i is seen as a field element as in [MGV], ie high-order bits
99 * correspond to low powers of P. The result is stored in the same way, that
100 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
101 * corresponds to P^127.
102 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +0000104{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200105 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +0000106 uint64_t hi, lo;
107 uint64_t vl, vh;
108 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200109 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200110
Paul Bakker89e80c92012-03-20 13:50:09 +0000111 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200113 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000114
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100115 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000116 GET_UINT32_BE( hi, h, 0 );
117 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000118 vh = (uint64_t) hi << 32 | lo;
119
Paul Bakker5c2364c2012-10-01 14:41:15 +0000120 GET_UINT32_BE( hi, h, 8 );
121 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000122 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200123
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100124 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000125 ctx->HL[8] = vl;
126 ctx->HH[8] = vh;
127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100129 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100130 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100131 return( 0 );
132#endif
133
134 /* 0 corresponds to 0 in GF(2^128) */
135 ctx->HH[0] = 0;
136 ctx->HL[0] = 0;
137
Paul Bakker89e80c92012-03-20 13:50:09 +0000138 for( i = 4; i > 0; i >>= 1 )
139 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200140 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000141 vl = ( vh << 63 ) | ( vl >> 1 );
142 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
143
144 ctx->HL[i] = vl;
145 ctx->HH[i] = vh;
146 }
147
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000148 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000149 {
150 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
151 vh = *HiH;
152 vl = *HiL;
153 for( j = 1; j < i; j++ )
154 {
155 HiH[j] = vh ^ ctx->HH[j];
156 HiL[j] = vl ^ ctx->HL[j];
157 }
158 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200159
160 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000161}
162
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200163int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
164 mbedtls_cipher_id_t cipher,
165 const unsigned char *key,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200166 unsigned int keybits )
Paul Bakker89e80c92012-03-20 13:50:09 +0000167{
168 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000170
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200171 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200172 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200174
Paul Bakkera0558e02013-09-10 14:25:51 +0200175 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200176 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200177
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200178 mbedtls_cipher_free( &ctx->cipher_ctx );
179
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200180 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000181 return( ret );
182
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200183 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200185 {
186 return( ret );
187 }
188
189 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
190 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000191
192 return( 0 );
193}
194
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100195/*
196 * Shoup's method for multiplication use this table with
197 * last4[x] = x times P^128
198 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
199 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000200static const uint64_t last4[16] =
201{
202 0x0000, 0x1c20, 0x3840, 0x2460,
203 0x7080, 0x6ca0, 0x48c0, 0x54e0,
204 0xe100, 0xfd20, 0xd940, 0xc560,
205 0x9180, 0x8da0, 0xa9c0, 0xb5e0
206};
207
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100208/*
209 * Sets output to x times H using the precomputed tables.
210 * x and output are seen as elements of GF(2^128) as in [MGV].
211 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200213 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000214{
215 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000216 unsigned char lo, hi, rem;
217 uint64_t zh, zl;
218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200219#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100220 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100221 unsigned char h[16];
222
223 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
224 PUT_UINT32_BE( ctx->HH[8], h, 4 );
225 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
226 PUT_UINT32_BE( ctx->HL[8], h, 12 );
227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100229 return;
230 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100232
Paul Bakker89e80c92012-03-20 13:50:09 +0000233 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000234
235 zh = ctx->HH[lo];
236 zl = ctx->HL[lo];
237
238 for( i = 15; i >= 0; i-- )
239 {
240 lo = x[i] & 0xf;
241 hi = x[i] >> 4;
242
243 if( i != 15 )
244 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000245 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000246 zl = ( zh << 60 ) | ( zl >> 4 );
247 zh = ( zh >> 4 );
248 zh ^= (uint64_t) last4[rem] << 48;
249 zh ^= ctx->HH[lo];
250 zl ^= ctx->HL[lo];
251
252 }
253
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000254 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000255 zl = ( zh << 60 ) | ( zl >> 4 );
256 zh = ( zh >> 4 );
257 zh ^= (uint64_t) last4[rem] << 48;
258 zh ^= ctx->HH[hi];
259 zl ^= ctx->HL[hi];
260 }
261
Paul Bakker5c2364c2012-10-01 14:41:15 +0000262 PUT_UINT32_BE( zh >> 32, output, 0 );
263 PUT_UINT32_BE( zh, output, 4 );
264 PUT_UINT32_BE( zl >> 32, output, 8 );
265 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000266}
267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200269 int mode,
270 const unsigned char *iv,
271 size_t iv_len,
272 const unsigned char *add,
273 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000274{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200275 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000276 unsigned char work_buf[16];
277 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000278 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200279 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000280
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200281 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200282 /* IV is not allowed to be zero length */
283 if( iv_len == 0 ||
284 ( (uint64_t) iv_len ) >> 61 != 0 ||
285 ( (uint64_t) add_len ) >> 61 != 0 )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200286 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200288 }
289
Paul Bakker52cf16c2013-07-26 13:55:38 +0200290 memset( ctx->y, 0x00, sizeof(ctx->y) );
291 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
292
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200293 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200294 ctx->len = 0;
295 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000296
297 if( iv_len == 12 )
298 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200299 memcpy( ctx->y, iv, iv_len );
300 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000301 }
302 else
303 {
304 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000305 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000306
307 p = iv;
308 while( iv_len > 0 )
309 {
310 use_len = ( iv_len < 16 ) ? iv_len : 16;
311
Paul Bakker67f9d532012-10-23 11:49:05 +0000312 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200313 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200314
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200315 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000316
317 iv_len -= use_len;
318 p += use_len;
319 }
320
Paul Bakker67f9d532012-10-23 11:49:05 +0000321 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200322 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000323
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200324 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000325 }
326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200328 &olen ) ) != 0 )
329 {
330 return( ret );
331 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000332
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200333 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000334 p = add;
335 while( add_len > 0 )
336 {
337 use_len = ( add_len < 16 ) ? add_len : 16;
338
Paul Bakker67f9d532012-10-23 11:49:05 +0000339 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200340 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200341
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200342 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000343
344 add_len -= use_len;
345 p += use_len;
346 }
347
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200348 return( 0 );
349}
350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200352 size_t length,
353 const unsigned char *input,
354 unsigned char *output )
355{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200356 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200357 unsigned char ectr[16];
358 size_t i;
359 const unsigned char *p;
360 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200361 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200362
363 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200364 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200365
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200366 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
367 * Also check for possible overflow */
368 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard1e075622015-12-10 14:46:25 +0100369 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200370 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200372 }
373
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200374 ctx->len += length;
375
Paul Bakker89e80c92012-03-20 13:50:09 +0000376 p = input;
377 while( length > 0 )
378 {
379 use_len = ( length < 16 ) ? length : 16;
380
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100381 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200382 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000383 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200386 &olen ) ) != 0 )
387 {
388 return( ret );
389 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000390
Paul Bakker67f9d532012-10-23 11:49:05 +0000391 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000392 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200394 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000395 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200397 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000398 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200399
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200400 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200401
Paul Bakker89e80c92012-03-20 13:50:09 +0000402 length -= use_len;
403 p += use_len;
404 out_p += use_len;
405 }
406
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200407 return( 0 );
408}
409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200411 unsigned char *tag,
412 size_t tag_len )
413{
414 unsigned char work_buf[16];
415 size_t i;
416 uint64_t orig_len = ctx->len * 8;
417 uint64_t orig_add_len = ctx->add_len * 8;
418
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200419 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200421
Andres AG821da842016-09-26 10:09:30 +0100422 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200423
Paul Bakker89e80c92012-03-20 13:50:09 +0000424 if( orig_len || orig_add_len )
425 {
426 memset( work_buf, 0x00, 16 );
427
Paul Bakker0ecdb232013-04-09 11:36:42 +0200428 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
429 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
430 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
431 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000432
Paul Bakker67f9d532012-10-23 11:49:05 +0000433 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200434 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000435
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200436 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000437
Paul Bakker67f9d532012-10-23 11:49:05 +0000438 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200439 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000440 }
441
442 return( 0 );
443}
444
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200446 int mode,
447 size_t length,
448 const unsigned char *iv,
449 size_t iv_len,
450 const unsigned char *add,
451 size_t add_len,
452 const unsigned char *input,
453 unsigned char *output,
454 size_t tag_len,
455 unsigned char *tag )
456{
457 int ret;
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200460 return( ret );
461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200463 return( ret );
464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200466 return( ret );
467
468 return( 0 );
469}
470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000472 size_t length,
473 const unsigned char *iv,
474 size_t iv_len,
475 const unsigned char *add,
476 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200477 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000478 size_t tag_len,
479 const unsigned char *input,
480 unsigned char *output )
481{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100482 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000483 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200484 size_t i;
485 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100488 iv, iv_len, add, add_len,
489 input, output, tag_len, check_tag ) ) != 0 )
490 {
491 return( ret );
492 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000493
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200494 /* Check tag in "constant-time" */
495 for( diff = 0, i = 0; i < tag_len; i++ )
496 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000497
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200498 if( diff != 0 )
499 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500 mbedtls_zeroize( output, length );
501 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200502 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000503
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200504 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000505}
506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200508{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 mbedtls_cipher_free( &ctx->cipher_ctx );
510 mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200511}
512
Jaeden Amero15263302017-09-21 12:53:48 +0100513#endif /* !MBEDTLS_GCM_ALT */
514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000516/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200517 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000518 *
519 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
520 */
521#define MAX_TESTS 6
522
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000523static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000524 { 0, 0, 1, 1, 1, 1 };
525
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000526static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000527{
528 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
532 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
533 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
534 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200535 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000536};
537
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000538static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000539 { 12, 12, 12, 12, 8, 60 };
540
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000541static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000542 { 0, 0, 1, 1, 1, 2 };
543
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000544static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000545{
546 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00 },
548 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
549 0xde, 0xca, 0xf8, 0x88 },
550 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200551 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000552 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200553 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000554 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200555 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000556 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200557 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000558};
559
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000560static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000561 { 0, 0, 0, 20, 20, 20 };
562
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000563static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000564 { 0, 0, 0, 1, 1, 1 };
565
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000566static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000567{
568 { 0x00 },
569 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200570 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000571 0xab, 0xad, 0xda, 0xd2 },
572};
573
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000574static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000575 { 0, 16, 64, 60, 60, 60 };
576
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000577static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000578 { 0, 0, 1, 1, 1, 1 };
579
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000580static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000581{
582 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
584 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
585 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
586 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
587 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
588 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
589 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
590 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
591 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
592};
593
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000594static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000595{
596 { 0x00 },
597 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
598 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
599 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200600 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000601 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200602 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000603 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200604 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000605 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
606 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
607 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200608 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000609 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200610 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200612 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000613 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
614 0x3d, 0x58, 0xe0, 0x91 },
615 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200616 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200618 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000619 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200620 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000621 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
622 0xc2, 0x3f, 0x45, 0x98 },
623 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200624 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000625 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200626 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000627 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200628 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000629 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
630 0x4c, 0x34, 0xae, 0xe5 },
631 { 0x00 },
632 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200633 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000634 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200635 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000636 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200637 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200639 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000640 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
641 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
642 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200645 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
646 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
647 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000656 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200657 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200663 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000664 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200665 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000666 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200667 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
668 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
669 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
670 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
671 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
672 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
673 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
674 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
675 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
676 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
677 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
678 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
679 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
680 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
681 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
682 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
683 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
684 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200686 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000687 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200688 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000689 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200690 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000691 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200692 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000693 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200694 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000695 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200696 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000697 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200698 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000699 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200700 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000701};
702
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000703static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000704{
705 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
706 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
707 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
708 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
709 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200710 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000711 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
712 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
713 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
714 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
715 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
716 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
717 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
718 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
719 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
722 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
723 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200730 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000731 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200732 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000733 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200734 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000735 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200736 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000737 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200738 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000739 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200740 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000741};
742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000744{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000746 unsigned char buf[64];
747 unsigned char tag_buf[16];
748 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000750
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200751 mbedtls_gcm_init( &ctx );
752
Paul Bakker89e80c92012-03-20 13:50:09 +0000753 for( j = 0; j < 3; j++ )
754 {
755 int key_len = 128 + 64 * j;
756
757 for( i = 0; i < MAX_TESTS; i++ )
758 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200759 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100761 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200762
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200763 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000766 pt_len[i],
767 iv[iv_index[i]], iv_len[i],
768 additional[add_index[i]], add_len[i],
769 pt[pt_index[i]], buf, 16, tag_buf );
770
771 if( ret != 0 ||
772 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
773 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
774 {
775 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200776 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000777
778 return( 1 );
779 }
780
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200782
Paul Bakker89e80c92012-03-20 13:50:09 +0000783 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200784 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000785
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200786 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100788 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200789
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200790 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200792 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakker89e80c92012-03-20 13:50:09 +0000793 pt_len[i],
794 iv[iv_index[i]], iv_len[i],
795 additional[add_index[i]], add_len[i],
796 ct[j * 6 + i], buf, 16, tag_buf );
797
798 if( ret != 0 ||
799 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
800 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
801 {
802 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200803 mbedtls_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000804
805 return( 1 );
806 }
807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200809
Paul Bakker89e80c92012-03-20 13:50:09 +0000810 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200812
813 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100815 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200816
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200817 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200818
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200820 iv[iv_index[i]], iv_len[i],
821 additional[add_index[i]], add_len[i] );
822 if( ret != 0 )
823 {
824 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200826
827 return( 1 );
828 }
829
830 if( pt_len[i] > 32 )
831 {
832 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200834 if( ret != 0 )
835 {
836 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200838
839 return( 1 );
840 }
841
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200843 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200844 if( ret != 0 )
845 {
846 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200847 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200848
849 return( 1 );
850 }
851 }
852 else
853 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200855 if( ret != 0 )
856 {
857 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200859
860 return( 1 );
861 }
862 }
863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200865 if( ret != 0 ||
866 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
867 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
868 {
869 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200871
872 return( 1 );
873 }
874
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200876
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200877 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200878 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200879
880 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100882 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200883
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200884 mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200885
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200887 iv[iv_index[i]], iv_len[i],
888 additional[add_index[i]], add_len[i] );
889 if( ret != 0 )
890 {
891 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200893
894 return( 1 );
895 }
896
897 if( pt_len[i] > 32 )
898 {
899 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200900 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200901 if( ret != 0 )
902 {
903 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200904 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200905
906 return( 1 );
907 }
908
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200909 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200910 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200911 if( ret != 0 )
912 {
913 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200915
916 return( 1 );
917 }
918 }
919 else
920 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200922 if( ret != 0 )
923 {
924 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200926
927 return( 1 );
928 }
929 }
930
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200932 if( ret != 0 ||
933 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
934 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
935 {
936 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937 mbedtls_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200938
939 return( 1 );
940 }
941
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200942 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200943
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200944 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200946
Paul Bakker89e80c92012-03-20 13:50:09 +0000947 }
948 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200949
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200950 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200951 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000952
953 return( 0 );
954}
955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000957
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958#endif /* MBEDTLS_GCM_C */