blob: 97e9d889d55369e703dd881331a6625a09ca5284 [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)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +010049#include "mbedtls/aes.h"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000051#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010052#else
Rich Evans00ab4702015-02-06 13:43:58 +000053#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#define mbedtls_printf printf
55#endif /* MBEDTLS_PLATFORM_C */
56#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010057
Paul Bakker89e80c92012-03-20 13:50:09 +000058/*
59 * 32-bit integer manipulation macros (big endian)
60 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000061#ifndef GET_UINT32_BE
62#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000063{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000064 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
65 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
66 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
67 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000068}
69#endif
70
Paul Bakker5c2364c2012-10-01 14:41:15 +000071#ifndef PUT_UINT32_BE
72#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000073{ \
74 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
75 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
76 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
77 (b)[(i) + 3] = (unsigned char) ( (n) ); \
78}
79#endif
80
Paul Bakker34617722014-06-13 17:20:13 +020081/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020083 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
84}
85
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010086/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020087 * Initialize a context
88 */
89void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
90{
91 memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
92}
93
94/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010095 * Precompute small multiples of H, that is set
96 * HH[i] || HL[i] = H times i,
97 * where i is seen as a field element as in [MGV], ie high-order bits
98 * correspond to low powers of P. The result is stored in the same way, that
99 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
100 * corresponds to P^127.
101 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +0000103{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200104 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +0000105 uint64_t hi, lo;
106 uint64_t vl, vh;
107 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200108 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200109
Paul Bakker89e80c92012-03-20 13:50:09 +0000110 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200112 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000113
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100114 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000115 GET_UINT32_BE( hi, h, 0 );
116 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000117 vh = (uint64_t) hi << 32 | lo;
118
Paul Bakker5c2364c2012-10-01 14:41:15 +0000119 GET_UINT32_BE( hi, h, 8 );
120 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000121 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200122
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100123 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000124 ctx->HL[8] = vl;
125 ctx->HH[8] = vh;
126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100128 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100129 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100130 return( 0 );
131#endif
132
133 /* 0 corresponds to 0 in GF(2^128) */
134 ctx->HH[0] = 0;
135 ctx->HL[0] = 0;
136
Paul Bakker89e80c92012-03-20 13:50:09 +0000137 for( i = 4; i > 0; i >>= 1 )
138 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200139 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000140 vl = ( vh << 63 ) | ( vl >> 1 );
141 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
142
143 ctx->HL[i] = vl;
144 ctx->HH[i] = vh;
145 }
146
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000147 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000148 {
149 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
150 vh = *HiH;
151 vl = *HiL;
152 for( j = 1; j < i; j++ )
153 {
154 HiH[j] = vh ^ ctx->HH[j];
155 HiL[j] = vl ^ ctx->HL[j];
156 }
157 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200158
159 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000160}
161
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200162int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
163 mbedtls_cipher_id_t cipher,
164 const unsigned char *key,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200165 unsigned int keybits )
Paul Bakker89e80c92012-03-20 13:50:09 +0000166{
167 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000169
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200170 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200171 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200173
Paul Bakkera0558e02013-09-10 14:25:51 +0200174 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200176
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200177 mbedtls_cipher_free( &ctx->cipher_ctx );
178
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200179 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000180 return( ret );
181
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200182 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200184 {
185 return( ret );
186 }
187
188 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
189 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000190
191 return( 0 );
192}
193
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100194/*
195 * Shoup's method for multiplication use this table with
196 * last4[x] = x times P^128
197 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
198 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000199static const uint64_t last4[16] =
200{
201 0x0000, 0x1c20, 0x3840, 0x2460,
202 0x7080, 0x6ca0, 0x48c0, 0x54e0,
203 0xe100, 0xfd20, 0xd940, 0xc560,
204 0x9180, 0x8da0, 0xa9c0, 0xb5e0
205};
206
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100207/*
208 * Sets output to x times H using the precomputed tables.
209 * x and output are seen as elements of GF(2^128) as in [MGV].
210 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200212 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000213{
214 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000215 unsigned char lo, hi, rem;
216 uint64_t zh, zl;
217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100219 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100220 unsigned char h[16];
221
222 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
223 PUT_UINT32_BE( ctx->HH[8], h, 4 );
224 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
225 PUT_UINT32_BE( ctx->HL[8], h, 12 );
226
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100228 return;
229 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100231
Paul Bakker89e80c92012-03-20 13:50:09 +0000232 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000233
234 zh = ctx->HH[lo];
235 zl = ctx->HL[lo];
236
237 for( i = 15; i >= 0; i-- )
238 {
239 lo = x[i] & 0xf;
240 hi = x[i] >> 4;
241
242 if( i != 15 )
243 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000244 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000245 zl = ( zh << 60 ) | ( zl >> 4 );
246 zh = ( zh >> 4 );
247 zh ^= (uint64_t) last4[rem] << 48;
248 zh ^= ctx->HH[lo];
249 zl ^= ctx->HL[lo];
250
251 }
252
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000253 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000254 zl = ( zh << 60 ) | ( zl >> 4 );
255 zh = ( zh >> 4 );
256 zh ^= (uint64_t) last4[rem] << 48;
257 zh ^= ctx->HH[hi];
258 zl ^= ctx->HL[hi];
259 }
260
Paul Bakker5c2364c2012-10-01 14:41:15 +0000261 PUT_UINT32_BE( zh >> 32, output, 0 );
262 PUT_UINT32_BE( zh, output, 4 );
263 PUT_UINT32_BE( zl >> 32, output, 8 );
264 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000265}
266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200268 int mode,
269 const unsigned char *iv,
270 size_t iv_len,
271 const unsigned char *add,
272 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000273{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200274 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000275 unsigned char work_buf[16];
276 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000277 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200278 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000279
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200280 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
281 if( ( (uint64_t) iv_len ) >> 61 != 0 ||
282 ( (uint64_t) add_len ) >> 61 != 0 )
283 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200285 }
286
Paul Bakker52cf16c2013-07-26 13:55:38 +0200287 memset( ctx->y, 0x00, sizeof(ctx->y) );
288 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
289
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200290 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200291 ctx->len = 0;
292 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000293
294 if( iv_len == 12 )
295 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200296 memcpy( ctx->y, iv, iv_len );
297 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000298 }
299 else
300 {
301 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000302 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000303
304 p = iv;
305 while( iv_len > 0 )
306 {
307 use_len = ( iv_len < 16 ) ? iv_len : 16;
308
Paul Bakker67f9d532012-10-23 11:49:05 +0000309 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200310 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200311
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200312 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000313
314 iv_len -= use_len;
315 p += use_len;
316 }
317
Paul Bakker67f9d532012-10-23 11:49:05 +0000318 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200319 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000320
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200321 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000322 }
323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200325 &olen ) ) != 0 )
326 {
327 return( ret );
328 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000329
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200330 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000331 p = add;
332 while( add_len > 0 )
333 {
334 use_len = ( add_len < 16 ) ? add_len : 16;
335
Paul Bakker67f9d532012-10-23 11:49:05 +0000336 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200337 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200338
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200339 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000340
341 add_len -= use_len;
342 p += use_len;
343 }
344
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200345 return( 0 );
346}
347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200349 size_t length,
350 const unsigned char *input,
351 unsigned char *output )
352{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200353 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200354 unsigned char ectr[16];
355 size_t i;
356 const unsigned char *p;
357 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200358 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200359
360 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200362
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200363 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
364 * Also check for possible overflow */
365 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard1e075622015-12-10 14:46:25 +0100366 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200367 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200369 }
370
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200371 ctx->len += length;
372
Paul Bakker89e80c92012-03-20 13:50:09 +0000373 p = input;
374 while( length > 0 )
375 {
376 use_len = ( length < 16 ) ? length : 16;
377
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100378 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200379 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000380 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200383 &olen ) ) != 0 )
384 {
385 return( ret );
386 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000387
Paul Bakker67f9d532012-10-23 11:49:05 +0000388 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000389 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200391 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000392 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200394 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000395 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200396
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200397 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200398
Paul Bakker89e80c92012-03-20 13:50:09 +0000399 length -= use_len;
400 p += use_len;
401 out_p += use_len;
402 }
403
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200404 return( 0 );
405}
406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200408 unsigned char *tag,
409 size_t tag_len )
410{
411 unsigned char work_buf[16];
412 size_t i;
413 uint64_t orig_len = ctx->len * 8;
414 uint64_t orig_add_len = ctx->add_len * 8;
415
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200416 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200418
Andres AG821da842016-09-26 10:09:30 +0100419 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200420
Paul Bakker89e80c92012-03-20 13:50:09 +0000421 if( orig_len || orig_add_len )
422 {
423 memset( work_buf, 0x00, 16 );
424
Paul Bakker0ecdb232013-04-09 11:36:42 +0200425 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
426 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
427 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
428 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000429
Paul Bakker67f9d532012-10-23 11:49:05 +0000430 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200431 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000432
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200433 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000434
Paul Bakker67f9d532012-10-23 11:49:05 +0000435 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200436 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000437 }
438
439 return( 0 );
440}
441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200443 int mode,
444 size_t length,
445 const unsigned char *iv,
446 size_t iv_len,
447 const unsigned char *add,
448 size_t add_len,
449 const unsigned char *input,
450 unsigned char *output,
451 size_t tag_len,
452 unsigned char *tag )
453{
454 int ret;
455
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200457 return( ret );
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 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_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200463 return( ret );
464
465 return( 0 );
466}
467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000469 size_t length,
470 const unsigned char *iv,
471 size_t iv_len,
472 const unsigned char *add,
473 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200474 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000475 size_t tag_len,
476 const unsigned char *input,
477 unsigned char *output )
478{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100479 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000480 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200481 size_t i;
482 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100485 iv, iv_len, add, add_len,
486 input, output, tag_len, check_tag ) ) != 0 )
487 {
488 return( ret );
489 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000490
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200491 /* Check tag in "constant-time" */
492 for( diff = 0, i = 0; i < tag_len; i++ )
493 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000494
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200495 if( diff != 0 )
496 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 mbedtls_zeroize( output, length );
498 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200499 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000500
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200501 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000502}
503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200505{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506 mbedtls_cipher_free( &ctx->cipher_ctx );
507 mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200508}
509
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000511/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200512 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000513 *
514 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
515 */
516#define MAX_TESTS 6
517
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000518static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000519 { 0, 0, 1, 1, 1, 1 };
520
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000521static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000522{
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
527 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
528 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
529 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200530 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000531};
532
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000533static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000534 { 12, 12, 12, 12, 8, 60 };
535
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000536static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000537 { 0, 0, 1, 1, 1, 2 };
538
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000539static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000540{
541 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542 0x00, 0x00, 0x00, 0x00 },
543 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
544 0xde, 0xca, 0xf8, 0x88 },
545 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200546 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000547 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200548 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000549 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200550 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000551 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200552 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000553};
554
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000555static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000556 { 0, 0, 0, 20, 20, 20 };
557
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000558static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000559 { 0, 0, 0, 1, 1, 1 };
560
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000561static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000562{
563 { 0x00 },
564 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200565 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000566 0xab, 0xad, 0xda, 0xd2 },
567};
568
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000569static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000570 { 0, 16, 64, 60, 60, 60 };
571
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000572static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000573 { 0, 0, 1, 1, 1, 1 };
574
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000575static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000576{
577 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
579 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
580 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
581 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
582 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
583 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
584 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
585 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
586 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
587};
588
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000589static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000590{
591 { 0x00 },
592 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
593 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
594 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200595 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000596 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200597 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000598 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200599 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000600 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
601 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
602 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200603 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000604 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200605 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000606 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200607 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000608 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
609 0x3d, 0x58, 0xe0, 0x91 },
610 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200611 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000612 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200613 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000614 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200615 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000616 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
617 0xc2, 0x3f, 0x45, 0x98 },
618 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200619 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000620 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200621 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000622 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200623 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000624 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
625 0x4c, 0x34, 0xae, 0xe5 },
626 { 0x00 },
627 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200628 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000629 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200630 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000631 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200632 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000633 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200634 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000635 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
636 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
637 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200638 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000639 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200640 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
641 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
642 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000643 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200644 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000645 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200646 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000647 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200648 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000649 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200650 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000651 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200652 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000653 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200654 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000655 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200656 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000657 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200658 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000659 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200660 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000661 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200662 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
663 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
664 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
665 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
666 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
667 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
668 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
669 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
670 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
671 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
672 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
673 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
674 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
675 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
676 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
677 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
678 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
679 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000680 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200681 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000682 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200683 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000684 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200685 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000686 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200687 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000688 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200689 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000690 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200691 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000692 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200693 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000694 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200695 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000696};
697
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000698static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000699{
700 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
701 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
702 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
703 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
704 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200705 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000706 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
707 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
708 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
709 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
710 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
711 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
712 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
713 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
714 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200715 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000716 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
717 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
718 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200719 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000720 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200721 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000722 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200723 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000724 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200725 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000726 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200727 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000728 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200729 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000730 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200731 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000732 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200733 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000734 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200735 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000736};
737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000739{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000741 unsigned char buf[64];
742 unsigned char tag_buf[16];
743 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000745
746 for( j = 0; j < 3; j++ )
747 {
748 int key_len = 128 + 64 * j;
749
750 for( i = 0; i < MAX_TESTS; i++ )
751 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100752 mbedtls_gcm_init( &ctx );
753
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200754 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100756 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200757
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100758 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
759 key_len );
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100760 /*
761 * AES-192 is an optional feature that may be unavailable when
762 * there is an alternative underlying implementation i.e. when
763 * MBEDTLS_AES_ALT is defined.
764 */
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100765 if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
766 {
767 mbedtls_printf( "skipped\n" );
768 break;
769 }
770 else if( ret != 0 )
771 {
772 goto exit;
773 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000774
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100776 pt_len[i],
777 iv[iv_index[i]], iv_len[i],
778 additional[add_index[i]], add_len[i],
779 pt[pt_index[i]], buf, 16, tag_buf );
780 if( ret != 0 )
781 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000782
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100783 if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
784 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000785 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100786 ret = 1;
787 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000788 }
789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200790 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200791
Paul Bakker89e80c92012-03-20 13:50:09 +0000792 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200793 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000794
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100795 mbedtls_gcm_init( &ctx );
796
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200797 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200798 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100799 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200800
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100801 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
802 key_len );
803 if( ret != 0 )
804 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000805
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200806 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100807 pt_len[i],
808 iv[iv_index[i]], iv_len[i],
809 additional[add_index[i]], add_len[i],
810 ct[j * 6 + i], buf, 16, tag_buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000811
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100812 if( ret != 0 )
813 goto exit;
814
815 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakker89e80c92012-03-20 13:50:09 +0000816 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
817 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100818 ret = 1;
819 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000820 }
821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200822 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200823
Paul Bakker89e80c92012-03-20 13:50:09 +0000824 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200826
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100827 mbedtls_gcm_init( &ctx );
828
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200829 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200830 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100831 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200832
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100833 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
834 key_len );
835 if( ret != 0 )
836 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200837
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100839 iv[iv_index[i]], iv_len[i],
840 additional[add_index[i]], add_len[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200841 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100842 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200843
844 if( pt_len[i] > 32 )
845 {
846 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200847 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200848 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100849 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200850
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200852 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200853 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100854 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200855 }
856 else
857 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200859 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100860 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200861 }
862
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200863 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100864 if( ret != 0 )
865 goto exit;
866
867 if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200868 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
869 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100870 ret = 1;
871 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200872 }
873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200875
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200876 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200878
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100879 mbedtls_gcm_init( &ctx );
880
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200881 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100883 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200884
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100885 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
886 key_len );
887 if( ret != 0 )
888 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200891 iv[iv_index[i]], iv_len[i],
892 additional[add_index[i]], add_len[i] );
893 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100894 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200895
896 if( pt_len[i] > 32 )
897 {
898 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200900 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100901 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100904 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200905 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100906 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200907 }
908 else
909 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100910 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
911 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200912 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100913 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200914 }
915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100917 if( ret != 0 )
918 goto exit;
919
920 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200921 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
922 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100923 ret = 1;
924 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200925 }
926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200928
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200929 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200930 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000931 }
932 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200933
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200934 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000936
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100937 ret = 0;
938
939exit:
940 if( ret != 0 )
941 {
942 if( verbose != 0 )
943 mbedtls_printf( "failed\n" );
944 mbedtls_gcm_free( &ctx );
945 }
946
947 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000948}
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 */