blob: 57ecc06324eb9bd0d0733b21c601af7e2aa8a107 [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakker89e80c92012-03-20 13:50:09 +00005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker89e80c92012-03-20 13:50:09 +00007 *
Paul Bakker89e80c92012-03-20 13:50:09 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010022
Paul Bakker89e80c92012-03-20 13:50:09 +000023/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010024 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
25 *
26 * See also:
27 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
28 *
29 * We use the algorithm described as Shoup's method with 4-bit tables in
30 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000031 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010032
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker89e80c92012-03-20 13:50:09 +000034#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020035#else
36#include POLARSSL_CONFIG_FILE
37#endif
Paul Bakker89e80c92012-03-20 13:50:09 +000038
39#if defined(POLARSSL_GCM_C)
40
41#include "polarssl/gcm.h"
42
Rich Evans00ab4702015-02-06 13:43:58 +000043#include <string.h>
44
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010045#if defined(POLARSSL_AESNI_C)
46#include "polarssl/aesni.h"
47#endif
48
Rich Evans00ab4702015-02-06 13:43:58 +000049#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
Paul Bakker7dc4c442014-02-01 22:50:26 +010050#if defined(POLARSSL_PLATFORM_C)
51#include "polarssl/platform.h"
52#else
Rich Evans00ab4702015-02-06 13:43:58 +000053#include <stdio.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010054#define polarssl_printf printf
Rich Evans00ab4702015-02-06 13:43:58 +000055#endif /* POLARSSL_PLATFORM_C */
56#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010057
Paul Bakker89e80c92012-03-20 13:50:09 +000058/*
59 * 32-bit integer manipulation macros (big endian)
60 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000061#ifndef GET_UINT32_BE
62#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000063{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000064 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
65 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
66 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
67 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000068}
69#endif
70
Paul Bakker5c2364c2012-10-01 14:41:15 +000071#ifndef PUT_UINT32_BE
72#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000073{ \
74 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
75 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
76 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
77 (b)[(i) + 3] = (unsigned char) ( (n) ); \
78}
79#endif
80
Paul Bakker34617722014-06-13 17:20:13 +020081/* Implementation that should never be optimized out by the compiler */
82static void polarssl_zeroize( void *v, size_t n ) {
83 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
84}
85
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010086/*
87 * Precompute small multiples of H, that is set
88 * HH[i] || HL[i] = H times i,
89 * where i is seen as a field element as in [MGV], ie high-order bits
90 * correspond to low powers of P. The result is stored in the same way, that
91 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
92 * corresponds to P^127.
93 */
Paul Bakker43aff2a2013-09-09 00:10:27 +020094static int gcm_gen_table( gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +000095{
Paul Bakker43aff2a2013-09-09 00:10:27 +020096 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000097 uint64_t hi, lo;
98 uint64_t vl, vh;
99 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +0200100 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +0200101
Paul Bakker89e80c92012-03-20 13:50:09 +0000102 memset( h, 0, 16 );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200103 if( ( ret = cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
104 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000105
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100106 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000107 GET_UINT32_BE( hi, h, 0 );
108 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000109 vh = (uint64_t) hi << 32 | lo;
110
Paul Bakker5c2364c2012-10-01 14:41:15 +0000111 GET_UINT32_BE( hi, h, 8 );
112 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000113 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200114
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100115 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000116 ctx->HL[8] = vl;
117 ctx->HH[8] = vh;
118
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100119#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
120 /* With CLMUL support, we need only h, not the rest of the table */
121 if( aesni_supports( POLARSSL_AESNI_CLMUL ) )
122 return( 0 );
123#endif
124
125 /* 0 corresponds to 0 in GF(2^128) */
126 ctx->HH[0] = 0;
127 ctx->HL[0] = 0;
128
Paul Bakker89e80c92012-03-20 13:50:09 +0000129 for( i = 4; i > 0; i >>= 1 )
130 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200131 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000132 vl = ( vh << 63 ) | ( vl >> 1 );
133 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
134
135 ctx->HL[i] = vl;
136 ctx->HH[i] = vh;
137 }
138
Manuel Pégourié-Gonnard85fadb72015-02-14 14:57:25 +0000139 for( i = 2; i <= 8; i *= 2 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000140 {
141 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
142 vh = *HiH;
143 vl = *HiL;
144 for( j = 1; j < i; j++ )
145 {
146 HiH[j] = vh ^ ctx->HH[j];
147 HiL[j] = vl ^ ctx->HL[j];
148 }
149 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200150
151 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000152}
153
Paul Bakker43aff2a2013-09-09 00:10:27 +0200154int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
155 unsigned int keysize )
Paul Bakker89e80c92012-03-20 13:50:09 +0000156{
157 int ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200158 const cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000159
160 memset( ctx, 0, sizeof(gcm_context) );
161
Paul Bakker84bbeb52014-07-01 14:53:22 +0200162 cipher_init( &ctx->cipher_ctx );
163
Paul Bakker43aff2a2013-09-09 00:10:27 +0200164 cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
165 if( cipher_info == NULL )
166 return( POLARSSL_ERR_GCM_BAD_INPUT );
167
Paul Bakkera0558e02013-09-10 14:25:51 +0200168 if( cipher_info->block_size != 16 )
169 return( POLARSSL_ERR_GCM_BAD_INPUT );
170
Manuel Pégourié-Gonnard61977612015-05-27 17:38:50 +0200171 cipher_free( &ctx->cipher_ctx );
172
Paul Bakker43aff2a2013-09-09 00:10:27 +0200173 if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000174 return( ret );
175
Paul Bakker43aff2a2013-09-09 00:10:27 +0200176 if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize,
177 POLARSSL_ENCRYPT ) ) != 0 )
178 {
179 return( ret );
180 }
181
182 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
183 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000184
185 return( 0 );
186}
187
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100188/*
189 * Shoup's method for multiplication use this table with
190 * last4[x] = x times P^128
191 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
192 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000193static const uint64_t last4[16] =
194{
195 0x0000, 0x1c20, 0x3840, 0x2460,
196 0x7080, 0x6ca0, 0x48c0, 0x54e0,
197 0xe100, 0xfd20, 0xd940, 0xc560,
198 0x9180, 0x8da0, 0xa9c0, 0xb5e0
199};
200
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100201/*
202 * Sets output to x times H using the precomputed tables.
203 * x and output are seen as elements of GF(2^128) as in [MGV].
204 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200205static void gcm_mult( gcm_context *ctx, const unsigned char x[16],
206 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000207{
208 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000209 unsigned char lo, hi, rem;
210 uint64_t zh, zl;
211
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100212#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
213 if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) {
214 unsigned char h[16];
215
216 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
217 PUT_UINT32_BE( ctx->HH[8], h, 4 );
218 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
219 PUT_UINT32_BE( ctx->HL[8], h, 12 );
220
Manuel Pégourié-Gonnardd4588cf2013-12-30 13:54:23 +0100221 aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100222 return;
223 }
Paul Bakker9af723c2014-05-01 13:03:14 +0200224#endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100225
Paul Bakker89e80c92012-03-20 13:50:09 +0000226 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000227
228 zh = ctx->HH[lo];
229 zl = ctx->HL[lo];
230
231 for( i = 15; i >= 0; i-- )
232 {
233 lo = x[i] & 0xf;
234 hi = x[i] >> 4;
235
236 if( i != 15 )
237 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000238 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000239 zl = ( zh << 60 ) | ( zl >> 4 );
240 zh = ( zh >> 4 );
241 zh ^= (uint64_t) last4[rem] << 48;
242 zh ^= ctx->HH[lo];
243 zl ^= ctx->HL[lo];
244
245 }
246
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000247 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000248 zl = ( zh << 60 ) | ( zl >> 4 );
249 zh = ( zh >> 4 );
250 zh ^= (uint64_t) last4[rem] << 48;
251 zh ^= ctx->HH[hi];
252 zl ^= ctx->HL[hi];
253 }
254
Paul Bakker5c2364c2012-10-01 14:41:15 +0000255 PUT_UINT32_BE( zh >> 32, output, 0 );
256 PUT_UINT32_BE( zh, output, 4 );
257 PUT_UINT32_BE( zl >> 32, output, 8 );
258 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000259}
260
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200261int gcm_starts( gcm_context *ctx,
262 int mode,
263 const unsigned char *iv,
264 size_t iv_len,
265 const unsigned char *add,
266 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000267{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200268 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000269 unsigned char work_buf[16];
270 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000271 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200272 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000273
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200274 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
Ron Eldor4f1e64e2016-12-16 16:15:56 +0200275 /* IV is not allowed to be zero length */
276 if( iv_len == 0 ||
277 ( (uint64_t) iv_len ) >> 61 != 0 ||
278 ( (uint64_t) add_len ) >> 61 != 0 )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200279 {
280 return( POLARSSL_ERR_GCM_BAD_INPUT );
281 }
282
Paul Bakker52cf16c2013-07-26 13:55:38 +0200283 memset( ctx->y, 0x00, sizeof(ctx->y) );
284 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
285
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200286 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200287 ctx->len = 0;
288 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000289
290 if( iv_len == 12 )
291 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200292 memcpy( ctx->y, iv, iv_len );
293 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000294 }
295 else
296 {
297 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000298 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000299
300 p = iv;
301 while( iv_len > 0 )
302 {
303 use_len = ( iv_len < 16 ) ? iv_len : 16;
304
Paul Bakker67f9d532012-10-23 11:49:05 +0000305 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200306 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200307
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200308 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000309
310 iv_len -= use_len;
311 p += use_len;
312 }
313
Paul Bakker67f9d532012-10-23 11:49:05 +0000314 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200315 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000316
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200317 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000318 }
319
Paul Bakker43aff2a2013-09-09 00:10:27 +0200320 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
321 &olen ) ) != 0 )
322 {
323 return( ret );
324 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000325
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200326 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000327 p = add;
328 while( add_len > 0 )
329 {
330 use_len = ( add_len < 16 ) ? add_len : 16;
331
Paul Bakker67f9d532012-10-23 11:49:05 +0000332 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200333 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200334
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200335 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000336
337 add_len -= use_len;
338 p += use_len;
339 }
340
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200341 return( 0 );
342}
343
344int gcm_update( gcm_context *ctx,
345 size_t length,
346 const unsigned char *input,
347 unsigned char *output )
348{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200349 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200350 unsigned char ectr[16];
351 size_t i;
352 const unsigned char *p;
353 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200354 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200355
356 if( output > input && (size_t) ( output - input ) < length )
357 return( POLARSSL_ERR_GCM_BAD_INPUT );
358
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200359 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
360 * Also check for possible overflow */
361 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnardc0501442015-12-10 14:46:25 +0100362 (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200363 {
364 return( POLARSSL_ERR_GCM_BAD_INPUT );
365 }
366
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200367 ctx->len += length;
368
Paul Bakker89e80c92012-03-20 13:50:09 +0000369 p = input;
370 while( length > 0 )
371 {
372 use_len = ( length < 16 ) ? length : 16;
373
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100374 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200375 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000376 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000377
Paul Bakker43aff2a2013-09-09 00:10:27 +0200378 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
379 &olen ) ) != 0 )
380 {
381 return( ret );
382 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000383
Paul Bakker67f9d532012-10-23 11:49:05 +0000384 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000385 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200386 if( ctx->mode == GCM_DECRYPT )
387 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000388 out_p[i] = ectr[i] ^ p[i];
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200389 if( ctx->mode == GCM_ENCRYPT )
390 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000391 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200392
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200393 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200394
Paul Bakker89e80c92012-03-20 13:50:09 +0000395 length -= use_len;
396 p += use_len;
397 out_p += use_len;
398 }
399
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200400 return( 0 );
401}
402
403int gcm_finish( gcm_context *ctx,
404 unsigned char *tag,
405 size_t tag_len )
406{
407 unsigned char work_buf[16];
408 size_t i;
409 uint64_t orig_len = ctx->len * 8;
410 uint64_t orig_add_len = ctx->add_len * 8;
411
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200412 if( tag_len > 16 || tag_len < 4 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200413 return( POLARSSL_ERR_GCM_BAD_INPUT );
414
Andres AG6ad5d942016-09-26 10:09:30 +0100415 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200416
Paul Bakker89e80c92012-03-20 13:50:09 +0000417 if( orig_len || orig_add_len )
418 {
419 memset( work_buf, 0x00, 16 );
420
Paul Bakker0ecdb232013-04-09 11:36:42 +0200421 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
422 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
423 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
424 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000425
Paul Bakker67f9d532012-10-23 11:49:05 +0000426 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200427 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000428
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200429 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000430
Paul Bakker67f9d532012-10-23 11:49:05 +0000431 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200432 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000433 }
434
435 return( 0 );
436}
437
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200438int gcm_crypt_and_tag( gcm_context *ctx,
439 int mode,
440 size_t length,
441 const unsigned char *iv,
442 size_t iv_len,
443 const unsigned char *add,
444 size_t add_len,
445 const unsigned char *input,
446 unsigned char *output,
447 size_t tag_len,
448 unsigned char *tag )
449{
450 int ret;
451
452 if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
453 return( ret );
454
455 if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 )
456 return( ret );
457
458 if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 )
459 return( ret );
460
461 return( 0 );
462}
463
Paul Bakker89e80c92012-03-20 13:50:09 +0000464int gcm_auth_decrypt( gcm_context *ctx,
465 size_t length,
466 const unsigned char *iv,
467 size_t iv_len,
468 const unsigned char *add,
469 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200470 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000471 size_t tag_len,
472 const unsigned char *input,
473 unsigned char *output )
474{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100475 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000476 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200477 size_t i;
478 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000479
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100480 if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length,
481 iv, iv_len, add, add_len,
482 input, output, tag_len, check_tag ) ) != 0 )
483 {
484 return( ret );
485 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000486
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200487 /* Check tag in "constant-time" */
488 for( diff = 0, i = 0; i < tag_len; i++ )
489 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000490
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200491 if( diff != 0 )
492 {
Paul Bakker34617722014-06-13 17:20:13 +0200493 polarssl_zeroize( output, length );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200494 return( POLARSSL_ERR_GCM_AUTH_FAILED );
495 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000496
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200497 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000498}
499
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200500void gcm_free( gcm_context *ctx )
501{
Paul Bakker84bbeb52014-07-01 14:53:22 +0200502 cipher_free( &ctx->cipher_ctx );
Paul Bakker34617722014-06-13 17:20:13 +0200503 polarssl_zeroize( ctx, sizeof( gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200504}
505
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200506#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000507/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200508 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000509 *
510 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
511 */
512#define MAX_TESTS 6
513
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000514static const int key_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000515 { 0, 0, 1, 1, 1, 1 };
516
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000517static const unsigned char key[MAX_TESTS][32] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000518{
519 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
523 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
524 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
525 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200526 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000527};
528
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000529static const size_t iv_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000530 { 12, 12, 12, 12, 8, 60 };
531
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000532static const int iv_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000533 { 0, 0, 1, 1, 1, 2 };
534
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000535static const unsigned char iv[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000536{
537 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
538 0x00, 0x00, 0x00, 0x00 },
539 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
540 0xde, 0xca, 0xf8, 0x88 },
541 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200542 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000543 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200544 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000545 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200546 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000547 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200548 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000549};
550
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000551static const size_t add_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000552 { 0, 0, 0, 20, 20, 20 };
553
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000554static const int add_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000555 { 0, 0, 0, 1, 1, 1 };
556
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000557static const unsigned char additional[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000558{
559 { 0x00 },
560 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200561 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000562 0xab, 0xad, 0xda, 0xd2 },
563};
564
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000565static const size_t pt_len[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000566 { 0, 16, 64, 60, 60, 60 };
567
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000568static const int pt_index[MAX_TESTS] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000569 { 0, 0, 1, 1, 1, 1 };
570
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000571static const unsigned char pt[MAX_TESTS][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000572{
573 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
575 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
576 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
577 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
578 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
579 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
580 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
581 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
582 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
583};
584
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000585static const unsigned char ct[MAX_TESTS * 3][64] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000586{
587 { 0x00 },
588 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
589 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
590 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200591 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000592 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200593 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000594 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200595 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000596 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
597 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
598 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200599 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000600 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200601 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000602 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200603 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000604 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
605 0x3d, 0x58, 0xe0, 0x91 },
606 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200607 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000608 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200609 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000610 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200611 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000612 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
613 0xc2, 0x3f, 0x45, 0x98 },
614 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200615 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000616 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200617 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000618 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200619 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000620 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
621 0x4c, 0x34, 0xae, 0xe5 },
622 { 0x00 },
623 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200624 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000625 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200626 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000627 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200628 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000629 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200630 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000631 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
632 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
633 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200634 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000635 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200636 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
637 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
638 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000639 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200640 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000641 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200642 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000643 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200644 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000645 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200646 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000647 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200648 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000649 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200650 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000651 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200652 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000653 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200654 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000655 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200656 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000657 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200658 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
659 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
660 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
661 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
662 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
663 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
664 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
665 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
666 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
667 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
668 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
669 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
670 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
671 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
672 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
673 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
674 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
675 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000676 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200677 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000678 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200679 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000680 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200681 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000682 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200683 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000684 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200685 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000686 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200687 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000688 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200689 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000690 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200691 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000692};
693
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000694static const unsigned char tag[MAX_TESTS * 3][16] =
Paul Bakker89e80c92012-03-20 13:50:09 +0000695{
696 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
697 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
698 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
699 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
700 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200701 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000702 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
703 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
704 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
705 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
706 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
707 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
708 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
709 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
710 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200711 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000712 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
713 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
714 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200715 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000716 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200717 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000718 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200719 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000720 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200721 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000722 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200723 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000724 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200725 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000726 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200727 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000728 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200729 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000730 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200731 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000732};
733
734int gcm_self_test( int verbose )
735{
736 gcm_context ctx;
737 unsigned char buf[64];
738 unsigned char tag_buf[16];
739 int i, j, ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200740 cipher_id_t cipher = POLARSSL_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000741
742 for( j = 0; j < 3; j++ )
743 {
744 int key_len = 128 + 64 * j;
745
746 for( i = 0; i < MAX_TESTS; i++ )
747 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200748 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100749 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
750 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200751
Paul Bakker43aff2a2013-09-09 00:10:27 +0200752 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000753
754 ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
755 pt_len[i],
756 iv[iv_index[i]], iv_len[i],
757 additional[add_index[i]], add_len[i],
758 pt[pt_index[i]], buf, 16, tag_buf );
759
760 if( ret != 0 ||
761 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
762 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
763 {
764 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100765 polarssl_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000766
767 return( 1 );
768 }
769
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200770 gcm_free( &ctx );
771
Paul Bakker89e80c92012-03-20 13:50:09 +0000772 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100773 polarssl_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000774
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200775 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100776 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
777 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200778
Paul Bakker43aff2a2013-09-09 00:10:27 +0200779 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000780
781 ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
782 pt_len[i],
783 iv[iv_index[i]], iv_len[i],
784 additional[add_index[i]], add_len[i],
785 ct[j * 6 + i], buf, 16, tag_buf );
786
787 if( ret != 0 ||
788 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
789 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
790 {
791 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100792 polarssl_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000793
794 return( 1 );
795 }
796
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200797 gcm_free( &ctx );
798
Paul Bakker89e80c92012-03-20 13:50:09 +0000799 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100800 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200801
802 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100803 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
804 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200805
Paul Bakker43aff2a2013-09-09 00:10:27 +0200806 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200807
808 ret = gcm_starts( &ctx, GCM_ENCRYPT,
809 iv[iv_index[i]], iv_len[i],
810 additional[add_index[i]], add_len[i] );
811 if( ret != 0 )
812 {
813 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100814 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200815
816 return( 1 );
817 }
818
819 if( pt_len[i] > 32 )
820 {
821 size_t rest_len = pt_len[i] - 32;
822 ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf );
823 if( ret != 0 )
824 {
825 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100826 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200827
828 return( 1 );
829 }
830
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200831 ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
832 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200833 if( ret != 0 )
834 {
835 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100836 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200837
838 return( 1 );
839 }
840 }
841 else
842 {
843 ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
844 if( ret != 0 )
845 {
846 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100847 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200848
849 return( 1 );
850 }
851 }
852
853 ret = gcm_finish( &ctx, tag_buf, 16 );
854 if( ret != 0 ||
855 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
856 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
857 {
858 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100859 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200860
861 return( 1 );
862 }
863
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200864 gcm_free( &ctx );
865
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200866 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100867 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200868
869 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100870 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
871 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200872
Paul Bakker43aff2a2013-09-09 00:10:27 +0200873 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200874
875 ret = gcm_starts( &ctx, GCM_DECRYPT,
876 iv[iv_index[i]], iv_len[i],
877 additional[add_index[i]], add_len[i] );
878 if( ret != 0 )
879 {
880 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100881 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200882
883 return( 1 );
884 }
885
886 if( pt_len[i] > 32 )
887 {
888 size_t rest_len = pt_len[i] - 32;
889 ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf );
890 if( ret != 0 )
891 {
892 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100893 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200894
895 return( 1 );
896 }
897
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200898 ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
899 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200900 if( ret != 0 )
901 {
902 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100903 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200904
905 return( 1 );
906 }
907 }
908 else
909 {
910 ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
911 if( ret != 0 )
912 {
913 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100914 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200915
916 return( 1 );
917 }
918 }
919
920 ret = gcm_finish( &ctx, tag_buf, 16 );
921 if( ret != 0 ||
922 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
923 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
924 {
925 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100926 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200927
928 return( 1 );
929 }
930
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200931 gcm_free( &ctx );
932
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200933 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100934 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200935
Paul Bakker89e80c92012-03-20 13:50:09 +0000936 }
937 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200938
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200939 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100940 polarssl_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000941
942 return( 0 );
943}
944
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200945#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000946
Paul Bakker9af723c2014-05-01 13:03:14 +0200947#endif /* POLARSSL_GCM_C */