blob: d48f318d3b9e7cffd43aa81f2150765c5bcae95e [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
Paul Bakker7dc4c442014-02-01 22:50:26 +01004 * Copyright (C) 2006-2014, Brainspark B.V.
Paul Bakker89e80c92012-03-20 13:50:09 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010025
Paul Bakker89e80c92012-03-20 13:50:09 +000026/*
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010027 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
28 *
29 * See also:
30 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
31 *
32 * We use the algorithm described as Shoup's method with 4-bit tables in
33 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
Paul Bakker89e80c92012-03-20 13:50:09 +000034 */
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010035
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020036#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker89e80c92012-03-20 13:50:09 +000037#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020038#else
39#include POLARSSL_CONFIG_FILE
40#endif
Paul Bakker89e80c92012-03-20 13:50:09 +000041
42#if defined(POLARSSL_GCM_C)
43
44#include "polarssl/gcm.h"
45
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +010046#if defined(POLARSSL_AESNI_C)
47#include "polarssl/aesni.h"
48#endif
49
Paul Bakker7dc4c442014-02-01 22:50:26 +010050#if defined(POLARSSL_PLATFORM_C)
51#include "polarssl/platform.h"
52#else
53#define polarssl_printf printf
54#endif
55
Paul Bakker89e80c92012-03-20 13:50:09 +000056/*
57 * 32-bit integer manipulation macros (big endian)
58 */
Paul Bakker5c2364c2012-10-01 14:41:15 +000059#ifndef GET_UINT32_BE
60#define GET_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000061{ \
Paul Bakker5c2364c2012-10-01 14:41:15 +000062 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
63 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
64 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
65 | ( (uint32_t) (b)[(i) + 3] ); \
Paul Bakker89e80c92012-03-20 13:50:09 +000066}
67#endif
68
Paul Bakker5c2364c2012-10-01 14:41:15 +000069#ifndef PUT_UINT32_BE
70#define PUT_UINT32_BE(n,b,i) \
Paul Bakker89e80c92012-03-20 13:50:09 +000071{ \
72 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
73 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
74 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
75 (b)[(i) + 3] = (unsigned char) ( (n) ); \
76}
77#endif
78
Paul Bakker34617722014-06-13 17:20:13 +020079/* Implementation that should never be optimized out by the compiler */
80static void polarssl_zeroize( void *v, size_t n ) {
81 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
82}
83
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +010084/*
85 * Precompute small multiples of H, that is set
86 * HH[i] || HL[i] = H times i,
87 * where i is seen as a field element as in [MGV], ie high-order bits
88 * correspond to low powers of P. The result is stored in the same way, that
89 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
90 * corresponds to P^127.
91 */
Paul Bakker43aff2a2013-09-09 00:10:27 +020092static int gcm_gen_table( gcm_context *ctx )
Paul Bakker89e80c92012-03-20 13:50:09 +000093{
Paul Bakker43aff2a2013-09-09 00:10:27 +020094 int ret, i, j;
Paul Bakker89e80c92012-03-20 13:50:09 +000095 uint64_t hi, lo;
96 uint64_t vl, vh;
97 unsigned char h[16];
Paul Bakker43aff2a2013-09-09 00:10:27 +020098 size_t olen = 0;
Paul Bakker169b7f42013-06-25 14:58:00 +020099
Paul Bakker89e80c92012-03-20 13:50:09 +0000100 memset( h, 0, 16 );
Paul Bakker43aff2a2013-09-09 00:10:27 +0200101 if( ( ret = cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
102 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000103
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100104 /* pack h as two 64-bits ints, big-endian */
Paul Bakker5c2364c2012-10-01 14:41:15 +0000105 GET_UINT32_BE( hi, h, 0 );
106 GET_UINT32_BE( lo, h, 4 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000107 vh = (uint64_t) hi << 32 | lo;
108
Paul Bakker5c2364c2012-10-01 14:41:15 +0000109 GET_UINT32_BE( hi, h, 8 );
110 GET_UINT32_BE( lo, h, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000111 vl = (uint64_t) hi << 32 | lo;
Paul Bakker169b7f42013-06-25 14:58:00 +0200112
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100113 /* 8 = 1000 corresponds to 1 in GF(2^128) */
Paul Bakker89e80c92012-03-20 13:50:09 +0000114 ctx->HL[8] = vl;
115 ctx->HH[8] = vh;
116
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100117#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
118 /* With CLMUL support, we need only h, not the rest of the table */
119 if( aesni_supports( POLARSSL_AESNI_CLMUL ) )
120 return( 0 );
121#endif
122
123 /* 0 corresponds to 0 in GF(2^128) */
124 ctx->HH[0] = 0;
125 ctx->HL[0] = 0;
126
Paul Bakker89e80c92012-03-20 13:50:09 +0000127 for( i = 4; i > 0; i >>= 1 )
128 {
Paul Bakker0ecdb232013-04-09 11:36:42 +0200129 uint32_t T = ( vl & 1 ) * 0xe1000000U;
Paul Bakker89e80c92012-03-20 13:50:09 +0000130 vl = ( vh << 63 ) | ( vl >> 1 );
131 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
132
133 ctx->HL[i] = vl;
134 ctx->HH[i] = vh;
135 }
136
Paul Bakker66d5d072014-06-17 16:39:18 +0200137 for( i = 2; i < 16; i <<= 1 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000138 {
139 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
140 vh = *HiH;
141 vl = *HiL;
142 for( j = 1; j < i; j++ )
143 {
144 HiH[j] = vh ^ ctx->HH[j];
145 HiL[j] = vl ^ ctx->HL[j];
146 }
147 }
Paul Bakker43aff2a2013-09-09 00:10:27 +0200148
149 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000150}
151
Paul Bakker43aff2a2013-09-09 00:10:27 +0200152int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
153 unsigned int keysize )
Paul Bakker89e80c92012-03-20 13:50:09 +0000154{
155 int ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200156 const cipher_info_t *cipher_info;
Paul Bakker89e80c92012-03-20 13:50:09 +0000157
158 memset( ctx, 0, sizeof(gcm_context) );
159
Paul Bakker84bbeb52014-07-01 14:53:22 +0200160 cipher_init( &ctx->cipher_ctx );
161
Paul Bakker43aff2a2013-09-09 00:10:27 +0200162 cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
163 if( cipher_info == NULL )
164 return( POLARSSL_ERR_GCM_BAD_INPUT );
165
Paul Bakkera0558e02013-09-10 14:25:51 +0200166 if( cipher_info->block_size != 16 )
167 return( POLARSSL_ERR_GCM_BAD_INPUT );
168
Paul Bakker43aff2a2013-09-09 00:10:27 +0200169 if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000170 return( ret );
171
Paul Bakker43aff2a2013-09-09 00:10:27 +0200172 if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize,
173 POLARSSL_ENCRYPT ) ) != 0 )
174 {
175 return( ret );
176 }
177
178 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
179 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000180
181 return( 0 );
182}
183
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100184/*
185 * Shoup's method for multiplication use this table with
186 * last4[x] = x times P^128
187 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
188 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000189static const uint64_t last4[16] =
190{
191 0x0000, 0x1c20, 0x3840, 0x2460,
192 0x7080, 0x6ca0, 0x48c0, 0x54e0,
193 0xe100, 0xfd20, 0xd940, 0xc560,
194 0x9180, 0x8da0, 0xa9c0, 0xb5e0
195};
196
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100197/*
198 * Sets output to x times H using the precomputed tables.
199 * x and output are seen as elements of GF(2^128) as in [MGV].
200 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200201static void gcm_mult( gcm_context *ctx, const unsigned char x[16],
202 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000203{
204 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000205 unsigned char lo, hi, rem;
206 uint64_t zh, zl;
207
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100208#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
209 if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) {
210 unsigned char h[16];
211
212 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
213 PUT_UINT32_BE( ctx->HH[8], h, 4 );
214 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
215 PUT_UINT32_BE( ctx->HL[8], h, 12 );
216
Manuel Pégourié-Gonnardd4588cf2013-12-30 13:54:23 +0100217 aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100218 return;
219 }
Paul Bakker9af723c2014-05-01 13:03:14 +0200220#endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100221
Paul Bakker89e80c92012-03-20 13:50:09 +0000222 lo = x[15] & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000223
224 zh = ctx->HH[lo];
225 zl = ctx->HL[lo];
226
227 for( i = 15; i >= 0; i-- )
228 {
229 lo = x[i] & 0xf;
230 hi = x[i] >> 4;
231
232 if( i != 15 )
233 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000234 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000235 zl = ( zh << 60 ) | ( zl >> 4 );
236 zh = ( zh >> 4 );
237 zh ^= (uint64_t) last4[rem] << 48;
238 zh ^= ctx->HH[lo];
239 zl ^= ctx->HL[lo];
240
241 }
242
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000243 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000244 zl = ( zh << 60 ) | ( zl >> 4 );
245 zh = ( zh >> 4 );
246 zh ^= (uint64_t) last4[rem] << 48;
247 zh ^= ctx->HH[hi];
248 zl ^= ctx->HL[hi];
249 }
250
Paul Bakker5c2364c2012-10-01 14:41:15 +0000251 PUT_UINT32_BE( zh >> 32, output, 0 );
252 PUT_UINT32_BE( zh, output, 4 );
253 PUT_UINT32_BE( zl >> 32, output, 8 );
254 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000255}
256
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200257int gcm_starts( gcm_context *ctx,
258 int mode,
259 const unsigned char *iv,
260 size_t iv_len,
261 const unsigned char *add,
262 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000263{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200264 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000265 unsigned char work_buf[16];
266 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000267 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200268 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000269
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200270 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
271 if( ( (uint64_t) iv_len ) >> 61 != 0 ||
272 ( (uint64_t) add_len ) >> 61 != 0 )
273 {
274 return( POLARSSL_ERR_GCM_BAD_INPUT );
275 }
276
Paul Bakker52cf16c2013-07-26 13:55:38 +0200277 memset( ctx->y, 0x00, sizeof(ctx->y) );
278 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
279
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200280 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200281 ctx->len = 0;
282 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000283
284 if( iv_len == 12 )
285 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200286 memcpy( ctx->y, iv, iv_len );
287 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000288 }
289 else
290 {
291 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000292 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000293
294 p = iv;
295 while( iv_len > 0 )
296 {
297 use_len = ( iv_len < 16 ) ? iv_len : 16;
298
Paul Bakker67f9d532012-10-23 11:49:05 +0000299 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200300 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200301
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200302 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000303
304 iv_len -= use_len;
305 p += use_len;
306 }
307
Paul Bakker67f9d532012-10-23 11:49:05 +0000308 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200309 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000310
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200311 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000312 }
313
Paul Bakker43aff2a2013-09-09 00:10:27 +0200314 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
315 &olen ) ) != 0 )
316 {
317 return( ret );
318 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000319
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200320 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000321 p = add;
322 while( add_len > 0 )
323 {
324 use_len = ( add_len < 16 ) ? add_len : 16;
325
Paul Bakker67f9d532012-10-23 11:49:05 +0000326 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200327 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200328
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200329 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000330
331 add_len -= use_len;
332 p += use_len;
333 }
334
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200335 return( 0 );
336}
337
338int gcm_update( gcm_context *ctx,
339 size_t length,
340 const unsigned char *input,
341 unsigned char *output )
342{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200343 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200344 unsigned char ectr[16];
345 size_t i;
346 const unsigned char *p;
347 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200348 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200349
350 if( output > input && (size_t) ( output - input ) < length )
351 return( POLARSSL_ERR_GCM_BAD_INPUT );
352
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200353 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
354 * Also check for possible overflow */
355 if( ctx->len + length < ctx->len ||
Manuel Pégourié-Gonnard8d77eee2014-07-21 13:59:12 +0200356 (uint64_t) ctx->len + length > 0x03FFFFE0ull )
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200357 {
358 return( POLARSSL_ERR_GCM_BAD_INPUT );
359 }
360
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200361 ctx->len += length;
362
Paul Bakker89e80c92012-03-20 13:50:09 +0000363 p = input;
364 while( length > 0 )
365 {
366 use_len = ( length < 16 ) ? length : 16;
367
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100368 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200369 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000370 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000371
Paul Bakker43aff2a2013-09-09 00:10:27 +0200372 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
373 &olen ) ) != 0 )
374 {
375 return( ret );
376 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000377
Paul Bakker67f9d532012-10-23 11:49:05 +0000378 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000379 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200380 if( ctx->mode == GCM_DECRYPT )
381 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000382 out_p[i] = ectr[i] ^ p[i];
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200383 if( ctx->mode == GCM_ENCRYPT )
384 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000385 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200386
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200387 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200388
Paul Bakker89e80c92012-03-20 13:50:09 +0000389 length -= use_len;
390 p += use_len;
391 out_p += use_len;
392 }
393
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200394 return( 0 );
395}
396
397int gcm_finish( gcm_context *ctx,
398 unsigned char *tag,
399 size_t tag_len )
400{
401 unsigned char work_buf[16];
402 size_t i;
403 uint64_t orig_len = ctx->len * 8;
404 uint64_t orig_add_len = ctx->add_len * 8;
405
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200406 if( tag_len > 16 || tag_len < 4 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200407 return( POLARSSL_ERR_GCM_BAD_INPUT );
408
Manuel Pégourié-Gonnard9241be72013-08-31 17:31:03 +0200409 if( tag_len != 0 )
410 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200411
Paul Bakker89e80c92012-03-20 13:50:09 +0000412 if( orig_len || orig_add_len )
413 {
414 memset( work_buf, 0x00, 16 );
415
Paul Bakker0ecdb232013-04-09 11:36:42 +0200416 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
417 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
418 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
419 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000420
Paul Bakker67f9d532012-10-23 11:49:05 +0000421 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200422 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000423
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200424 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000425
Paul Bakker67f9d532012-10-23 11:49:05 +0000426 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200427 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000428 }
429
430 return( 0 );
431}
432
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200433int gcm_crypt_and_tag( gcm_context *ctx,
434 int mode,
435 size_t length,
436 const unsigned char *iv,
437 size_t iv_len,
438 const unsigned char *add,
439 size_t add_len,
440 const unsigned char *input,
441 unsigned char *output,
442 size_t tag_len,
443 unsigned char *tag )
444{
445 int ret;
446
447 if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
448 return( ret );
449
450 if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 )
451 return( ret );
452
453 if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 )
454 return( ret );
455
456 return( 0 );
457}
458
Paul Bakker89e80c92012-03-20 13:50:09 +0000459int gcm_auth_decrypt( gcm_context *ctx,
460 size_t length,
461 const unsigned char *iv,
462 size_t iv_len,
463 const unsigned char *add,
464 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200465 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000466 size_t tag_len,
467 const unsigned char *input,
468 unsigned char *output )
469{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100470 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000471 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200472 size_t i;
473 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000474
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100475 if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length,
476 iv, iv_len, add, add_len,
477 input, output, tag_len, check_tag ) ) != 0 )
478 {
479 return( ret );
480 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000481
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200482 /* Check tag in "constant-time" */
483 for( diff = 0, i = 0; i < tag_len; i++ )
484 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000485
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200486 if( diff != 0 )
487 {
Paul Bakker34617722014-06-13 17:20:13 +0200488 polarssl_zeroize( output, length );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200489 return( POLARSSL_ERR_GCM_AUTH_FAILED );
490 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000491
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200492 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000493}
494
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200495void gcm_free( gcm_context *ctx )
496{
Paul Bakker84bbeb52014-07-01 14:53:22 +0200497 cipher_free( &ctx->cipher_ctx );
Paul Bakker34617722014-06-13 17:20:13 +0200498 polarssl_zeroize( ctx, sizeof( gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200499}
500
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200501#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000502
503#include <stdio.h>
504
505/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200506 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000507 *
508 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
509 */
510#define MAX_TESTS 6
511
512int key_index[MAX_TESTS] =
513 { 0, 0, 1, 1, 1, 1 };
514
515unsigned char key[MAX_TESTS][32] =
516{
517 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
521 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
522 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
523 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200524 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000525};
526
527size_t iv_len[MAX_TESTS] =
528 { 12, 12, 12, 12, 8, 60 };
529
530int iv_index[MAX_TESTS] =
531 { 0, 0, 1, 1, 1, 2 };
532
533unsigned char iv[MAX_TESTS][64] =
534{
535 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x00, 0x00, 0x00, 0x00 },
537 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
538 0xde, 0xca, 0xf8, 0x88 },
539 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200540 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000541 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200542 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000543 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200544 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000545 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200546 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000547};
548
549size_t add_len[MAX_TESTS] =
550 { 0, 0, 0, 20, 20, 20 };
551
552int add_index[MAX_TESTS] =
553 { 0, 0, 0, 1, 1, 1 };
554
555unsigned char additional[MAX_TESTS][64] =
556{
557 { 0x00 },
558 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200559 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000560 0xab, 0xad, 0xda, 0xd2 },
561};
562
563size_t pt_len[MAX_TESTS] =
564 { 0, 16, 64, 60, 60, 60 };
565
566int pt_index[MAX_TESTS] =
567 { 0, 0, 1, 1, 1, 1 };
568
569unsigned char pt[MAX_TESTS][64] =
570{
571 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
573 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
574 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
575 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
576 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
577 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
578 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
579 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
580 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
581};
582
583unsigned char ct[MAX_TESTS * 3][64] =
584{
585 { 0x00 },
586 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
587 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
588 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200589 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000590 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200591 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000592 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200593 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000594 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
595 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
596 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200597 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000598 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200599 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000600 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200601 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000602 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
603 0x3d, 0x58, 0xe0, 0x91 },
604 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200605 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000606 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200607 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000608 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200609 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000610 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
611 0xc2, 0x3f, 0x45, 0x98 },
612 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200613 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000614 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200615 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000616 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200617 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000618 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
619 0x4c, 0x34, 0xae, 0xe5 },
620 { 0x00 },
621 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200622 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000623 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200624 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000625 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200626 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000627 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200628 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000629 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
630 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
631 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200632 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000633 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200634 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
635 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
636 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000637 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200638 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000639 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200640 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000641 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200642 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000643 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200644 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000645 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200646 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000647 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200648 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000649 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200650 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000651 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200652 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000653 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200654 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000655 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200656 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
657 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
658 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
659 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
660 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
661 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
662 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
663 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
664 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
665 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
666 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
667 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
668 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
669 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
670 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
671 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
672 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
673 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000674 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200675 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000676 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200677 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000678 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200679 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000680 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200681 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000682 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200683 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000684 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200685 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000686 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200687 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000688 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200689 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000690};
691
692unsigned char tag[MAX_TESTS * 3][16] =
693{
694 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
695 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
696 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
697 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
698 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200699 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000700 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
701 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
702 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
703 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
704 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
705 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
706 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
707 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
708 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200709 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000710 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
711 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
712 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200713 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000714 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200715 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000716 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200717 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000718 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200719 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000720 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200721 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000722 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200723 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000724 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200725 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000726 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200727 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000728 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200729 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000730};
731
732int gcm_self_test( int verbose )
733{
734 gcm_context ctx;
735 unsigned char buf[64];
736 unsigned char tag_buf[16];
737 int i, j, ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200738 cipher_id_t cipher = POLARSSL_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000739
740 for( j = 0; j < 3; j++ )
741 {
742 int key_len = 128 + 64 * j;
743
744 for( i = 0; i < MAX_TESTS; i++ )
745 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200746 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100747 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
748 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200749
Paul Bakker43aff2a2013-09-09 00:10:27 +0200750 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000751
752 ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
753 pt_len[i],
754 iv[iv_index[i]], iv_len[i],
755 additional[add_index[i]], add_len[i],
756 pt[pt_index[i]], buf, 16, tag_buf );
757
758 if( ret != 0 ||
759 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
760 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
761 {
762 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100763 polarssl_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000764
765 return( 1 );
766 }
767
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200768 gcm_free( &ctx );
769
Paul Bakker89e80c92012-03-20 13:50:09 +0000770 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100771 polarssl_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000772
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200773 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100774 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
775 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200776
Paul Bakker43aff2a2013-09-09 00:10:27 +0200777 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000778
779 ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
780 pt_len[i],
781 iv[iv_index[i]], iv_len[i],
782 additional[add_index[i]], add_len[i],
783 ct[j * 6 + i], buf, 16, tag_buf );
784
785 if( ret != 0 ||
786 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
787 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
788 {
789 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100790 polarssl_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000791
792 return( 1 );
793 }
794
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200795 gcm_free( &ctx );
796
Paul Bakker89e80c92012-03-20 13:50:09 +0000797 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100798 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200799
800 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100801 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
802 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200803
Paul Bakker43aff2a2013-09-09 00:10:27 +0200804 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200805
806 ret = gcm_starts( &ctx, GCM_ENCRYPT,
807 iv[iv_index[i]], iv_len[i],
808 additional[add_index[i]], add_len[i] );
809 if( ret != 0 )
810 {
811 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100812 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200813
814 return( 1 );
815 }
816
817 if( pt_len[i] > 32 )
818 {
819 size_t rest_len = pt_len[i] - 32;
820 ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf );
821 if( ret != 0 )
822 {
823 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100824 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200825
826 return( 1 );
827 }
828
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200829 ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
830 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200831 if( ret != 0 )
832 {
833 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100834 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200835
836 return( 1 );
837 }
838 }
839 else
840 {
841 ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
842 if( ret != 0 )
843 {
844 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100845 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200846
847 return( 1 );
848 }
849 }
850
851 ret = gcm_finish( &ctx, tag_buf, 16 );
852 if( ret != 0 ||
853 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
854 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
855 {
856 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100857 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200858
859 return( 1 );
860 }
861
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200862 gcm_free( &ctx );
863
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200864 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100865 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200866
867 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100868 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
869 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200870
Paul Bakker43aff2a2013-09-09 00:10:27 +0200871 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200872
873 ret = gcm_starts( &ctx, GCM_DECRYPT,
874 iv[iv_index[i]], iv_len[i],
875 additional[add_index[i]], add_len[i] );
876 if( ret != 0 )
877 {
878 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100879 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200880
881 return( 1 );
882 }
883
884 if( pt_len[i] > 32 )
885 {
886 size_t rest_len = pt_len[i] - 32;
887 ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf );
888 if( ret != 0 )
889 {
890 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100891 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200892
893 return( 1 );
894 }
895
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200896 ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
897 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200898 if( ret != 0 )
899 {
900 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100901 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200902
903 return( 1 );
904 }
905 }
906 else
907 {
908 ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
909 if( ret != 0 )
910 {
911 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100912 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200913
914 return( 1 );
915 }
916 }
917
918 ret = gcm_finish( &ctx, tag_buf, 16 );
919 if( ret != 0 ||
920 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
921 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
922 {
923 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100924 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200925
926 return( 1 );
927 }
928
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200929 gcm_free( &ctx );
930
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200931 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100932 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200933
Paul Bakker89e80c92012-03-20 13:50:09 +0000934 }
935 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200936
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200937 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100938 polarssl_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000939
940 return( 0 );
941}
942
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200943
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 */