blob: 57b027933dd22f55ce52bd355d8d2e092bb83360 [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"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050041#include "mbedtls/platform_util.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000042
Rich Evans00ab4702015-02-06 13:43:58 +000043#include <string.h>
44
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_AESNI_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010047#endif
48
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +010050#include "mbedtls/aes.h"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#define mbedtls_printf printf
56#endif /* MBEDTLS_PLATFORM_C */
57#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010058
Jaeden Amero15263302017-09-21 12:53:48 +010059#if !defined(MBEDTLS_GCM_ALT)
60
Paul Bakker89e80c92012-03-20 13:50:09 +000061/*
62 * 32-bit integer manipulation macros (big endian)
63 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000064#ifndef GET_UINT32_BE
65#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000066{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000067 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
68 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
69 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
70 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000071}
72#endif
73
Paul Bakker5c2364c2012-10-01 14:41:15 +000074#ifndef PUT_UINT32_BE
75#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000076{ \
77 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
78 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
79 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
80 (b)[(i) + 3] = (unsigned char) ( (n) ); \
81}
82#endif
83
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010084/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +020085 * Initialize a context
86 */
87void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
88{
89 memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
90}
91
92/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010093 * Precompute small multiples of H, that is set
94 * HH[i] || HL[i] = H times i,
95 * where i is seen as a field element as in [MGV], ie high-order bits
96 * correspond to low powers of P. The result is stored in the same way, that
97 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
98 * corresponds to P^127.
99 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +0000101{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200102 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +0000103 uint64_t hi, lo;
104 uint64_t vl, vh;
105 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200106 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200107
Paul Bakker89e80c92012-03-20 13:50:09 +0000108 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200110 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000111
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100112 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000113 GET_UINT32_BE( hi, h, 0 );
114 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000115 vh = (uint64_t) hi << 32 | lo;
116
Paul Bakker5c2364c2012-10-01 14:41:15 +0000117 GET_UINT32_BE( hi, h, 8 );
118 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000119 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200120
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100121 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000122 ctx->HL[8] = vl;
123 ctx->HH[8] = vh;
124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100126 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100127 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100128 return( 0 );
129#endif
130
131 /* 0 corresponds to 0 in GF(2^128) */
132 ctx->HH[0] = 0;
133 ctx->HL[0] = 0;
134
Paul Bakker89e80c92012-03-20 13:50:09 +0000135 for( i = 4; i > 0; i >>= 1 )
136 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200137 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000138 vl = ( vh << 63 ) | ( vl >> 1 );
139 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
140
141 ctx->HL[i] = vl;
142 ctx->HH[i] = vh;
143 }
144
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000145 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000146 {
147 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
148 vh = *HiH;
149 vl = *HiL;
150 for( j = 1; j < i; j++ )
151 {
152 HiH[j] = vh ^ ctx->HH[j];
153 HiL[j] = vl ^ ctx->HL[j];
154 }
155 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200156
157 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000158}
159
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200160int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
161 mbedtls_cipher_id_t cipher,
162 const unsigned char *key,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200163 unsigned int keybits )
Paul Bakker89e80c92012-03-20 13:50:09 +0000164{
165 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200166 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000167
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200168 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200169 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200171
Paul Bakkera0558e02013-09-10 14:25:51 +0200172 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200174
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200175 mbedtls_cipher_free( &ctx->cipher_ctx );
176
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200177 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000178 return( ret );
179
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200180 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200182 {
183 return( ret );
184 }
185
186 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
187 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000188
189 return( 0 );
190}
191
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100192/*
193 * Shoup's method for multiplication use this table with
194 * last4[x] = x times P^128
195 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
196 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000197static const uint64_t last4[16] =
198{
199 0x0000, 0x1c20, 0x3840, 0x2460,
200 0x7080, 0x6ca0, 0x48c0, 0x54e0,
201 0xe100, 0xfd20, 0xd940, 0xc560,
202 0x9180, 0x8da0, 0xa9c0, 0xb5e0
203};
204
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100205/*
206 * Sets output to x times H using the precomputed tables.
207 * x and output are seen as elements of GF(2^128) as in [MGV].
208 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200210 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000211{
212 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000213 unsigned char lo, hi, rem;
214 uint64_t zh, zl;
215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200216#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100217 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100218 unsigned char h[16];
219
220 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
221 PUT_UINT32_BE( ctx->HH[8], h, 4 );
222 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
223 PUT_UINT32_BE( ctx->HL[8], h, 12 );
224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100226 return;
227 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100229
Paul Bakker89e80c92012-03-20 13:50:09 +0000230 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000231
232 zh = ctx->HH[lo];
233 zl = ctx->HL[lo];
234
235 for( i = 15; i >= 0; i-- )
236 {
237 lo = x[i] & 0xf;
238 hi = x[i] >> 4;
239
240 if( i != 15 )
241 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000242 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000243 zl = ( zh << 60 ) | ( zl >> 4 );
244 zh = ( zh >> 4 );
245 zh ^= (uint64_t) last4[rem] << 48;
246 zh ^= ctx->HH[lo];
247 zl ^= ctx->HL[lo];
248
249 }
250
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000251 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000252 zl = ( zh << 60 ) | ( zl >> 4 );
253 zh = ( zh >> 4 );
254 zh ^= (uint64_t) last4[rem] << 48;
255 zh ^= ctx->HH[hi];
256 zl ^= ctx->HL[hi];
257 }
258
Paul Bakker5c2364c2012-10-01 14:41:15 +0000259 PUT_UINT32_BE( zh >> 32, output, 0 );
260 PUT_UINT32_BE( zh, output, 4 );
261 PUT_UINT32_BE( zl >> 32, output, 8 );
262 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000263}
264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200266 int mode,
267 const unsigned char *iv,
268 size_t iv_len,
269 const unsigned char *add,
270 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000271{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200272 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000273 unsigned char work_buf[16];
274 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000275 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200276 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000277
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200278 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200279 /* IV is not allowed to be zero length */
280 if( iv_len == 0 ||
281 ( (uint64_t) iv_len ) >> 61 != 0 ||
282 ( (uint64_t) add_len ) >> 61 != 0 )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200283 {
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 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500497 mbedtls_platform_zeroize( output, length );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 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 );
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500507 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200508}
509
Jaeden Amero15263302017-09-21 12:53:48 +0100510#endif /* !MBEDTLS_GCM_ALT */
511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000513/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200514 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000515 *
516 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
517 */
518#define MAX_TESTS 6
519
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000520static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000521 { 0, 0, 1, 1, 1, 1 };
522
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000523static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000524{
525 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
529 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
530 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
531 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200532 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000533};
534
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000535static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000536 { 12, 12, 12, 12, 8, 60 };
537
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000538static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000539 { 0, 0, 1, 1, 1, 2 };
540
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000541static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000542{
543 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00 },
545 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
546 0xde, 0xca, 0xf8, 0x88 },
547 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200548 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000549 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200550 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000551 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200552 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000553 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200554 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000555};
556
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000557static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000558 { 0, 0, 0, 20, 20, 20 };
559
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000560static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000561 { 0, 0, 0, 1, 1, 1 };
562
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000563static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000564{
565 { 0x00 },
566 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200567 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000568 0xab, 0xad, 0xda, 0xd2 },
569};
570
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000571static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000572 { 0, 16, 64, 60, 60, 60 };
573
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000574static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000575 { 0, 0, 1, 1, 1, 1 };
576
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000577static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000578{
579 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
581 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
582 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
583 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
584 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
585 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
586 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
587 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
588 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
589};
590
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000591static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000592{
593 { 0x00 },
594 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
595 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
596 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200597 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000598 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200599 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000600 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200601 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000602 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
603 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
604 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200605 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000606 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200607 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000608 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200609 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000610 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
611 0x3d, 0x58, 0xe0, 0x91 },
612 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200613 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000614 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200615 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000616 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200617 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000618 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
619 0xc2, 0x3f, 0x45, 0x98 },
620 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200621 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000622 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200623 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000624 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200625 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000626 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
627 0x4c, 0x34, 0xae, 0xe5 },
628 { 0x00 },
629 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200630 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000631 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200632 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000633 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200634 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000635 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200636 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000637 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
638 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
639 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200640 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000641 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200642 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
643 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
644 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000645 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200646 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000647 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200648 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000649 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200650 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000651 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200652 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000653 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200654 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000655 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200656 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000657 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200658 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000659 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200660 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000661 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200662 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000663 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200664 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
665 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
666 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
667 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
668 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
669 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
670 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
671 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
672 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
673 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
674 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
675 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
676 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
677 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
678 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
679 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
680 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
681 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000682 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200683 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000684 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200685 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000686 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200687 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000688 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200689 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000690 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200691 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000692 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200693 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000694 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200695 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000696 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200697 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000698};
699
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000700static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000701{
702 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
703 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
704 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
705 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
706 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200707 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000708 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
709 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
710 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
711 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
712 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
713 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
714 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
715 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
716 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200717 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000718 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
719 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
720 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200721 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000722 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200723 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000724 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200725 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000726 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200727 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000728 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200729 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000730 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200731 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000732 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200733 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000734 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200735 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000736 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200737 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000738};
739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000741{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000743 unsigned char buf[64];
744 unsigned char tag_buf[16];
745 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000747
748 for( j = 0; j < 3; j++ )
749 {
750 int key_len = 128 + 64 * j;
751
752 for( i = 0; i < MAX_TESTS; i++ )
753 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100754 mbedtls_gcm_init( &ctx );
755
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200756 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100758 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200759
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100760 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
761 key_len );
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100762 /*
763 * AES-192 is an optional feature that may be unavailable when
764 * there is an alternative underlying implementation i.e. when
765 * MBEDTLS_AES_ALT is defined.
766 */
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100767 if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
768 {
769 mbedtls_printf( "skipped\n" );
770 break;
771 }
772 else if( ret != 0 )
773 {
774 goto exit;
775 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000776
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100778 pt_len[i],
779 iv[iv_index[i]], iv_len[i],
780 additional[add_index[i]], add_len[i],
781 pt[pt_index[i]], buf, 16, tag_buf );
782 if( ret != 0 )
783 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000784
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100785 if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
786 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000787 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100788 ret = 1;
789 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000790 }
791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200792 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200793
Paul Bakker89e80c92012-03-20 13:50:09 +0000794 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200795 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000796
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100797 mbedtls_gcm_init( &ctx );
798
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200799 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200800 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100801 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200802
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100803 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
804 key_len );
805 if( ret != 0 )
806 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200808 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100809 pt_len[i],
810 iv[iv_index[i]], iv_len[i],
811 additional[add_index[i]], add_len[i],
812 ct[j * 6 + i], buf, 16, tag_buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000813
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100814 if( ret != 0 )
815 goto exit;
816
817 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakker89e80c92012-03-20 13:50:09 +0000818 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
819 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100820 ret = 1;
821 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000822 }
823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200824 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200825
Paul Bakker89e80c92012-03-20 13:50:09 +0000826 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200827 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200828
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100829 mbedtls_gcm_init( &ctx );
830
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200831 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100833 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200834
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100835 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
836 key_len );
837 if( ret != 0 )
838 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200839
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100841 iv[iv_index[i]], iv_len[i],
842 additional[add_index[i]], add_len[i] );
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
846 if( pt_len[i] > 32 )
847 {
848 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200850 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100851 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200852
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200854 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200855 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100856 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200857 }
858 else
859 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200860 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200861 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100862 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200863 }
864
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200865 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100866 if( ret != 0 )
867 goto exit;
868
869 if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200870 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
871 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100872 ret = 1;
873 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200874 }
875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200876 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200877
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200878 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200879 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200880
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100881 mbedtls_gcm_init( &ctx );
882
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200883 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200884 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100885 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200886
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100887 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
888 key_len );
889 if( ret != 0 )
890 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200891
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200893 iv[iv_index[i]], iv_len[i],
894 additional[add_index[i]], add_len[i] );
895 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100896 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200897
898 if( pt_len[i] > 32 )
899 {
900 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200901 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200902 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100903 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200904
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100906 buf + 32 );
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 else
911 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100912 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
913 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200914 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100915 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200916 }
917
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200918 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100919 if( ret != 0 )
920 goto exit;
921
922 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200923 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
924 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100925 ret = 1;
926 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200927 }
928
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200930
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200931 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000933 }
934 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200935
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200936 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000938
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100939 ret = 0;
940
941exit:
942 if( ret != 0 )
943 {
944 if( verbose != 0 )
945 mbedtls_printf( "failed\n" );
946 mbedtls_gcm_free( &ctx );
947 }
948
949 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000950}
951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954#endif /* MBEDTLS_GCM_C */