blob: 9a9de2d2b477eb7836e3cda940bc7664234f9846 [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
Bence Szépkúti4e9f7122020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakker89e80c92012-03-20 13:50:09 +000024 *
Bence Szépkúti4e9f7122020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
45 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000046 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker89e80c92012-03-20 13:50:09 +000047 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010048
Paul Bakker89e80c92012-03-20 13:50:09 +000049/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010050 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
51 *
52 * See also:
53 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
54 *
55 * We use the algorithm described as Shoup's method with 4-bit tables in
56 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000057 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000060#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020061#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020063#endif
Paul Bakker89e80c92012-03-20 13:50:09 +000064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065#if defined(MBEDTLS_GCM_C)
Paul Bakker89e80c92012-03-20 13:50:09 +000066
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000067#include "mbedtls/gcm.h"
Paul Bakker89e80c92012-03-20 13:50:09 +000068
Rich Evans00ab4702015-02-06 13:43:58 +000069#include <string.h>
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#if defined(MBEDTLS_AESNI_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000072#include "mbedtls/aesni.h"
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010073#endif
74
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +010076#include "mbedtls/aes.h"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000078#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010079#else
Rich Evans00ab4702015-02-06 13:43:58 +000080#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081#define mbedtls_printf printf
82#endif /* MBEDTLS_PLATFORM_C */
83#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010084
Jaeden Amero15263302017-09-21 12:53:48 +010085#if !defined(MBEDTLS_GCM_ALT)
86
Paul Bakker89e80c92012-03-20 13:50:09 +000087/*
88 * 32-bit integer manipulation macros (big endian)
89 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000090#ifndef GET_UINT32_BE
91#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000092{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000093 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
94 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
95 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
96 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000097}
98#endif
99
Paul Bakker5c2364c2012-10-01 14:41:15 +0000100#ifndef PUT_UINT32_BE
101#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +0000102{ \
103 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
104 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
105 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
106 (b)[(i) + 3] = (unsigned char) ( (n) ); \
107}
108#endif
109
Paul Bakker34617722014-06-13 17:20:13 +0200110/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +0200112 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
113}
114
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100115/*
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200116 * Initialize a context
117 */
118void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
119{
120 memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
121}
122
123/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100124 * Precompute small multiples of H, that is set
125 * HH[i] || HL[i] = H times i,
126 * where i is seen as a field element as in [MGV], ie high-order bits
127 * correspond to low powers of P. The result is stored in the same way, that
128 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
129 * corresponds to P^127.
130 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131static int gcm_gen_table( mbedtls_gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +0000132{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200133 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +0000134 uint64_t hi, lo;
135 uint64_t vl, vh;
136 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200137 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200138
Paul Bakker89e80c92012-03-20 13:50:09 +0000139 memset( h, 0, 16 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200141 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000142
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100143 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000144 GET_UINT32_BE( hi, h, 0 );
145 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000146 vh = (uint64_t) hi << 32 | lo;
147
Paul Bakker5c2364c2012-10-01 14:41:15 +0000148 GET_UINT32_BE( hi, h, 8 );
149 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000150 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200151
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100152 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000153 ctx->HL[8] = vl;
154 ctx->HH[8] = vh;
155
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100157 /* With CLMUL support, we need only h, not the rest of the table */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100158 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100159 return( 0 );
160#endif
161
162 /* 0 corresponds to 0 in GF(2^128) */
163 ctx->HH[0] = 0;
164 ctx->HL[0] = 0;
165
Paul Bakker89e80c92012-03-20 13:50:09 +0000166 for( i = 4; i > 0; i >>= 1 )
167 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200168 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000169 vl = ( vh << 63 ) | ( vl >> 1 );
170 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
171
172 ctx->HL[i] = vl;
173 ctx->HH[i] = vh;
174 }
175
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000176 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000177 {
178 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
179 vh = *HiH;
180 vl = *HiL;
181 for( j = 1; j < i; j++ )
182 {
183 HiH[j] = vh ^ ctx->HH[j];
184 HiL[j] = vl ^ ctx->HL[j];
185 }
186 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200187
188 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000189}
190
Manuel Pégourié-Gonnardc34e8dd2015-04-28 21:42:17 +0200191int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
192 mbedtls_cipher_id_t cipher,
193 const unsigned char *key,
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200194 unsigned int keybits )
Paul Bakker89e80c92012-03-20 13:50:09 +0000195{
196 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 const mbedtls_cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000198
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200199 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200200 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200202
Paul Bakkera0558e02013-09-10 14:25:51 +0200203 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkera0558e02013-09-10 14:25:51 +0200205
Manuel Pégourié-Gonnard43b08572015-05-27 17:23:30 +0200206 mbedtls_cipher_free( &ctx->cipher_ctx );
207
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +0200208 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000209 return( ret );
210
Manuel Pégourié-Gonnardb8186a52015-06-18 14:58:58 +0200211 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 MBEDTLS_ENCRYPT ) ) != 0 )
Paul Bakker43aff2a2013-09-09 00:10:27 +0200213 {
214 return( ret );
215 }
216
217 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
218 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000219
220 return( 0 );
221}
222
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100223/*
224 * Shoup's method for multiplication use this table with
225 * last4[x] = x times P^128
226 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
227 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000228static const uint64_t last4[16] =
229{
230 0x0000, 0x1c20, 0x3840, 0x2460,
231 0x7080, 0x6ca0, 0x48c0, 0x54e0,
232 0xe100, 0xfd20, 0xd940, 0xc560,
233 0x9180, 0x8da0, 0xa9c0, 0xb5e0
234};
235
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100236/*
237 * Sets output to x times H using the precomputed tables.
238 * x and output are seen as elements of GF(2^128) as in [MGV].
239 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200241 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000242{
243 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000244 unsigned char lo, hi, rem;
245 uint64_t zh, zl;
246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100248 if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100249 unsigned char h[16];
250
251 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
252 PUT_UINT32_BE( ctx->HH[8], h, 4 );
253 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
254 PUT_UINT32_BE( ctx->HL[8], h, 12 );
255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 mbedtls_aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100257 return;
258 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100260
Paul Bakker89e80c92012-03-20 13:50:09 +0000261 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000262
263 zh = ctx->HH[lo];
264 zl = ctx->HL[lo];
265
266 for( i = 15; i >= 0; i-- )
267 {
268 lo = x[i] & 0xf;
269 hi = x[i] >> 4;
270
271 if( i != 15 )
272 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000273 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000274 zl = ( zh << 60 ) | ( zl >> 4 );
275 zh = ( zh >> 4 );
276 zh ^= (uint64_t) last4[rem] << 48;
277 zh ^= ctx->HH[lo];
278 zl ^= ctx->HL[lo];
279
280 }
281
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000282 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000283 zl = ( zh << 60 ) | ( zl >> 4 );
284 zh = ( zh >> 4 );
285 zh ^= (uint64_t) last4[rem] << 48;
286 zh ^= ctx->HH[hi];
287 zl ^= ctx->HL[hi];
288 }
289
Paul Bakker5c2364c2012-10-01 14:41:15 +0000290 PUT_UINT32_BE( zh >> 32, output, 0 );
291 PUT_UINT32_BE( zh, output, 4 );
292 PUT_UINT32_BE( zl >> 32, output, 8 );
293 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000294}
295
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200297 int mode,
298 const unsigned char *iv,
299 size_t iv_len,
300 const unsigned char *add,
301 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000302{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200303 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000304 unsigned char work_buf[16];
305 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000306 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200307 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000308
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200309 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor5a21fd62016-12-16 16:15:56 +0200310 /* IV is not allowed to be zero length */
311 if( iv_len == 0 ||
312 ( (uint64_t) iv_len ) >> 61 != 0 ||
313 ( (uint64_t) add_len ) >> 61 != 0 )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200314 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200316 }
317
Paul Bakker52cf16c2013-07-26 13:55:38 +0200318 memset( ctx->y, 0x00, sizeof(ctx->y) );
319 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
320
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200321 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200322 ctx->len = 0;
323 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000324
325 if( iv_len == 12 )
326 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200327 memcpy( ctx->y, iv, iv_len );
328 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000329 }
330 else
331 {
332 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000333 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000334
335 p = iv;
336 while( iv_len > 0 )
337 {
338 use_len = ( iv_len < 16 ) ? iv_len : 16;
339
Paul Bakker67f9d532012-10-23 11:49:05 +0000340 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200341 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200342
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200343 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000344
345 iv_len -= use_len;
346 p += use_len;
347 }
348
Paul Bakker67f9d532012-10-23 11:49:05 +0000349 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200350 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000351
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200352 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000353 }
354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200356 &olen ) ) != 0 )
357 {
358 return( ret );
359 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000360
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200361 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000362 p = add;
363 while( add_len > 0 )
364 {
365 use_len = ( add_len < 16 ) ? add_len : 16;
366
Paul Bakker67f9d532012-10-23 11:49:05 +0000367 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200368 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200369
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200370 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000371
372 add_len -= use_len;
373 p += use_len;
374 }
375
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200376 return( 0 );
377}
378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200380 size_t length,
381 const unsigned char *input,
382 unsigned char *output )
383{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200384 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200385 unsigned char ectr[16];
386 size_t i;
387 const unsigned char *p;
388 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200389 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200390
391 if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200393
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200394 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
395 * Also check for possible overflow */
396 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard1e075622015-12-10 14:46:25 +0100397 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200398 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200400 }
401
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200402 ctx->len += length;
403
Paul Bakker89e80c92012-03-20 13:50:09 +0000404 p = input;
405 while( length > 0 )
406 {
407 use_len = ( length < 16 ) ? length : 16;
408
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100409 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200410 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000411 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
Paul Bakker43aff2a2013-09-09 00:10:27 +0200414 &olen ) ) != 0 )
415 {
416 return( ret );
417 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000418
Paul Bakker67f9d532012-10-23 11:49:05 +0000419 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000420 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 if( ctx->mode == MBEDTLS_GCM_DECRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200422 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000423 out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200425 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000426 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200427
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200428 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200429
Paul Bakker89e80c92012-03-20 13:50:09 +0000430 length -= use_len;
431 p += use_len;
432 out_p += use_len;
433 }
434
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200435 return( 0 );
436}
437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200439 unsigned char *tag,
440 size_t tag_len )
441{
442 unsigned char work_buf[16];
443 size_t i;
444 uint64_t orig_len = ctx->len * 8;
445 uint64_t orig_add_len = ctx->add_len * 8;
446
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200447 if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448 return( MBEDTLS_ERR_GCM_BAD_INPUT );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200449
Andres AG821da842016-09-26 10:09:30 +0100450 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200451
Paul Bakker89e80c92012-03-20 13:50:09 +0000452 if( orig_len || orig_add_len )
453 {
454 memset( work_buf, 0x00, 16 );
455
Paul Bakker0ecdb232013-04-09 11:36:42 +0200456 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
457 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
458 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
459 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000460
Paul Bakker67f9d532012-10-23 11:49:05 +0000461 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200462 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000463
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200464 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000465
Paul Bakker67f9d532012-10-23 11:49:05 +0000466 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200467 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000468 }
469
470 return( 0 );
471}
472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200474 int mode,
475 size_t length,
476 const unsigned char *iv,
477 size_t iv_len,
478 const unsigned char *add,
479 size_t add_len,
480 const unsigned char *input,
481 unsigned char *output,
482 size_t tag_len,
483 unsigned char *tag )
484{
485 int ret;
486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200488 return( ret );
489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200491 return( ret );
492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200494 return( ret );
495
496 return( 0 );
497}
498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
Paul Bakker89e80c92012-03-20 13:50:09 +0000500 size_t length,
501 const unsigned char *iv,
502 size_t iv_len,
503 const unsigned char *add,
504 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200505 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000506 size_t tag_len,
507 const unsigned char *input,
508 unsigned char *output )
509{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100510 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000511 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200512 size_t i;
513 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100516 iv, iv_len, add, add_len,
517 input, output, tag_len, check_tag ) ) != 0 )
518 {
519 return( ret );
520 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000521
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200522 /* Check tag in "constant-time" */
523 for( diff = 0, i = 0; i < tag_len; i++ )
524 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000525
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200526 if( diff != 0 )
527 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528 mbedtls_zeroize( output, length );
529 return( MBEDTLS_ERR_GCM_AUTH_FAILED );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200530 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000531
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200532 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000533}
534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200536{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 mbedtls_cipher_free( &ctx->cipher_ctx );
538 mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200539}
540
Jaeden Amero15263302017-09-21 12:53:48 +0100541#endif /* !MBEDTLS_GCM_ALT */
542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000544/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200545 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000546 *
547 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
548 */
549#define MAX_TESTS 6
550
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000551static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000552 { 0, 0, 1, 1, 1, 1 };
553
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000554static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000555{
556 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
557 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
558 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
559 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
560 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
561 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
562 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200563 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000564};
565
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000566static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000567 { 12, 12, 12, 12, 8, 60 };
568
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000569static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000570 { 0, 0, 1, 1, 1, 2 };
571
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000572static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000573{
574 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00 },
576 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
577 0xde, 0xca, 0xf8, 0x88 },
578 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200579 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000580 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200581 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000582 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200583 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000584 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200585 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000586};
587
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000588static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000589 { 0, 0, 0, 20, 20, 20 };
590
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000591static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000592 { 0, 0, 0, 1, 1, 1 };
593
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000594static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000595{
596 { 0x00 },
597 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200598 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000599 0xab, 0xad, 0xda, 0xd2 },
600};
601
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000602static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000603 { 0, 16, 64, 60, 60, 60 };
604
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000605static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000606 { 0, 0, 1, 1, 1, 1 };
607
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000608static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000609{
610 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
612 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
613 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
614 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
615 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
616 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
617 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
618 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
619 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
620};
621
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000622static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000623{
624 { 0x00 },
625 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
626 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
627 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200628 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000629 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200630 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000631 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200632 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000633 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
634 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
635 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200636 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000637 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200638 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000639 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200640 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000641 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
642 0x3d, 0x58, 0xe0, 0x91 },
643 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200644 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000645 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200646 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000647 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200648 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000649 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
650 0xc2, 0x3f, 0x45, 0x98 },
651 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200652 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000653 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200654 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000655 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200656 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000657 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
658 0x4c, 0x34, 0xae, 0xe5 },
659 { 0x00 },
660 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200663 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000664 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200665 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000666 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200667 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000668 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
669 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
670 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200671 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000672 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200673 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
674 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
675 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000676 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200677 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000678 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200679 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000680 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200681 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000682 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200683 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000684 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200685 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000686 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200687 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000688 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200689 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000690 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200691 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000692 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200693 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000694 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200695 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
696 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
697 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
698 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
699 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
700 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
701 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
702 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
703 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
704 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
705 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
706 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
707 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
708 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
709 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
710 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
711 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
712 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000713 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200714 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000715 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200716 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000717 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200718 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000719 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729};
730
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000731static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000732{
733 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
734 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
735 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
736 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
737 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200738 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000739 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
740 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
741 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
742 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
743 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
744 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
745 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
746 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
747 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200748 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000749 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
750 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
751 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200752 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000753 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200754 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000755 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200756 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000757 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200758 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000759 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200760 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000761 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200762 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000763 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200764 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000765 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200766 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000767 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200768 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000769};
770
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200771int mbedtls_gcm_self_test( int verbose )
Paul Bakker89e80c92012-03-20 13:50:09 +0000772{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 mbedtls_gcm_context ctx;
Paul Bakker89e80c92012-03-20 13:50:09 +0000774 unsigned char buf[64];
775 unsigned char tag_buf[16];
776 int i, j, ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777 mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000778
779 for( j = 0; j < 3; j++ )
780 {
781 int key_len = 128 + 64 * j;
782
783 for( i = 0; i < MAX_TESTS; i++ )
784 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100785 mbedtls_gcm_init( &ctx );
786
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200787 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100789 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200790
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100791 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
792 key_len );
Andres Amaya Garciad3e7e7d2017-06-15 16:17:46 +0100793 /*
794 * AES-192 is an optional feature that may be unavailable when
795 * there is an alternative underlying implementation i.e. when
796 * MBEDTLS_AES_ALT is defined.
797 */
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100798 if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
799 {
800 mbedtls_printf( "skipped\n" );
801 break;
802 }
803 else if( ret != 0 )
804 {
805 goto exit;
806 }
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_ENCRYPT,
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 pt[pt_index[i]], buf, 16, tag_buf );
813 if( ret != 0 )
814 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000815
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100816 if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
817 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000818 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100819 ret = 1;
820 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000821 }
822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200824
Paul Bakker89e80c92012-03-20 13:50:09 +0000825 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200826 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000827
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100828 mbedtls_gcm_init( &ctx );
829
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200830 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100832 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200833
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100834 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
835 key_len );
836 if( ret != 0 )
837 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000838
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200839 ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100840 pt_len[i],
841 iv[iv_index[i]], iv_len[i],
842 additional[add_index[i]], add_len[i],
843 ct[j * 6 + i], buf, 16, tag_buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000844
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100845 if( ret != 0 )
846 goto exit;
847
848 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakker89e80c92012-03-20 13:50:09 +0000849 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
850 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100851 ret = 1;
852 goto exit;
Paul Bakker89e80c92012-03-20 13:50:09 +0000853 }
854
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200855 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200856
Paul Bakker89e80c92012-03-20 13:50:09 +0000857 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200859
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100860 mbedtls_gcm_init( &ctx );
861
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200862 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200863 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100864 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200865
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100866 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
867 key_len );
868 if( ret != 0 )
869 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100872 iv[iv_index[i]], iv_len[i],
873 additional[add_index[i]], add_len[i] );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200874 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100875 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200876
877 if( pt_len[i] > 32 )
878 {
879 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200881 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100882 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200883
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200884 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200885 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200886 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100887 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200888 }
889 else
890 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200892 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100893 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200894 }
895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100897 if( ret != 0 )
898 goto exit;
899
900 if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200901 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
902 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100903 ret = 1;
904 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200905 }
906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200908
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200909 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 mbedtls_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200911
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100912 mbedtls_gcm_init( &ctx );
913
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200914 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915 mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100916 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200917
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100918 ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
919 key_len );
920 if( ret != 0 )
921 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200924 iv[iv_index[i]], iv_len[i],
925 additional[add_index[i]], add_len[i] );
926 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100927 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200928
929 if( pt_len[i] > 32 )
930 {
931 size_t rest_len = pt_len[i] - 32;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200933 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100934 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200935
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100937 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200938 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100939 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200940 }
941 else
942 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100943 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
944 buf );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200945 if( ret != 0 )
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100946 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200947 }
948
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949 ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100950 if( ret != 0 )
951 goto exit;
952
953 if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200954 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
955 {
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100956 ret = 1;
957 goto exit;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200958 }
959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960 mbedtls_gcm_free( &ctx );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200961
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200962 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200963 mbedtls_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000964 }
965 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200966
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200967 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 mbedtls_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000969
Andres Amaya Garcia2a078da2017-06-15 11:30:51 +0100970 ret = 0;
971
972exit:
973 if( ret != 0 )
974 {
975 if( verbose != 0 )
976 mbedtls_printf( "failed\n" );
977 mbedtls_gcm_free( &ctx );
978 }
979
980 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000981}
982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985#endif /* MBEDTLS_GCM_C */