blob: 7b2760a62dacaced7bd497d7c0ddd78c382272eb [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 );
760 if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
761 {
762 mbedtls_printf( "skipped\n" );
763 break;
764 }
765 else if( ret != 0 )
766 {
767 goto exit;
768 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100771 pt_len[i],
772 iv[iv_index[i]], iv_len[i],
773 additional[add_index[i]], add_len[i],
774 pt[pt_index[i]], buf, 16, tag_buf );
775 if( ret != 0 )
776 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000777
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100778 if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
779 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000780 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100781 ret = 1;
782 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000783 }
784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200786
Paul Bakker89e80c92012-03-20 13:50:09 +0000787 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000789
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100790 mbedtls_gcm_init( &ctx );
791
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200792 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200793 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100794 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200795
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100796 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
797 key_len );
798 if( ret != 0 )
799 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000800
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200801 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100802 pt_len[i],
803 iv[iv_index[i]], iv_len[i],
804 additional[add_index[i]], add_len[i],
805 ct[j * 6 + i], buf, 16, tag_buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000806
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100807 if( ret != 0 )
808 goto exit;
809
810 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakker89e80c92012-03-20 13:50:09 +0000811 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
812 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100813 ret = 1;
814 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000815 }
816
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200817 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200818
Paul Bakker89e80c92012-03-20 13:50:09 +0000819 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200821
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100822 mbedtls_gcm_init( &ctx );
823
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200824 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100826 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200827
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100828 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
829 key_len );
830 if( ret != 0 )
831 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200832
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200833 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100834 iv[iv_index[i]], iv_len[i],
835 additional[add_index[i]], add_len[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200836 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100837 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200838
839 if( pt_len[i] > 32 )
840 {
841 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200843 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100844 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200845
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200846 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200847 buf + 32 );
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 }
851 else
852 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200854 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100855 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200856 }
857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100859 if( ret != 0 )
860 goto exit;
861
862 if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200863 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
864 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100865 ret = 1;
866 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200867 }
868
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200870
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200871 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200873
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100874 mbedtls_gcm_init( &ctx );
875
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200876 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100878 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200879
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100880 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
881 key_len );
882 if( ret != 0 )
883 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200884
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200886 iv[iv_index[i]], iv_len[i],
887 additional[add_index[i]], add_len[i] );
888 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100889 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200890
891 if( pt_len[i] > 32 )
892 {
893 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200894 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200895 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100896 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200897
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100899 buf + 32 );
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 }
903 else
904 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100905 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
906 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200907 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100908 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200909 }
910
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200911 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100912 if( ret != 0 )
913 goto exit;
914
915 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200916 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
917 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100918 ret = 1;
919 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200920 }
921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200922 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200923
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200924 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000926 }
927 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200928
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200929 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200930 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000931
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100932 ret = 0;
933
934exit:
935 if( ret != 0 )
936 {
937 if( verbose != 0 )
938 mbedtls_printf( "failed\n" );
939 mbedtls_gcm_free( &ctx );
940 }
941
942 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000943}
944
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000946
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947#endif /* MBEDTLS_GCM_C */