blob: d4c68ae71f9bd9c056c29c18a95b6ceef19501cf [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 Bakker43aff2a2013-09-09 00:10:27 +0200160 cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
161 if( cipher_info == NULL )
162 return( POLARSSL_ERR_GCM_BAD_INPUT );
163
Paul Bakkera0558e02013-09-10 14:25:51 +0200164 if( cipher_info->block_size != 16 )
165 return( POLARSSL_ERR_GCM_BAD_INPUT );
166
Paul Bakker43aff2a2013-09-09 00:10:27 +0200167 if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Paul Bakker89e80c92012-03-20 13:50:09 +0000168 return( ret );
169
Paul Bakker43aff2a2013-09-09 00:10:27 +0200170 if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize,
171 POLARSSL_ENCRYPT ) ) != 0 )
172 {
173 return( ret );
174 }
175
176 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
177 return( ret );
Paul Bakker89e80c92012-03-20 13:50:09 +0000178
179 return( 0 );
180}
181
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100182/*
183 * Shoup's method for multiplication use this table with
184 * last4[x] = x times P^128
185 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
186 */
Paul Bakker89e80c92012-03-20 13:50:09 +0000187static const uint64_t last4[16] =
188{
189 0x0000, 0x1c20, 0x3840, 0x2460,
190 0x7080, 0x6ca0, 0x48c0, 0x54e0,
191 0xe100, 0xfd20, 0xd940, 0xc560,
192 0x9180, 0x8da0, 0xa9c0, 0xb5e0
193};
194
Manuel Pégourié-Gonnard9d574822013-12-25 15:41:25 +0100195/*
196 * Sets output to x times H using the precomputed tables.
197 * x and output are seen as elements of GF(2^128) as in [MGV].
198 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200199static void gcm_mult( gcm_context *ctx, const unsigned char x[16],
200 unsigned char output[16] )
Paul Bakker89e80c92012-03-20 13:50:09 +0000201{
202 int i = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000203 unsigned char lo, hi, rem;
204 uint64_t zh, zl;
205
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100206#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
207 if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) {
208 unsigned char h[16];
209
210 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
211 PUT_UINT32_BE( ctx->HH[8], h, 4 );
212 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
213 PUT_UINT32_BE( ctx->HL[8], h, 12 );
214
Manuel Pégourié-Gonnardd4588cf2013-12-30 13:54:23 +0100215 aesni_gcm_mult( output, x, h );
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100216 return;
217 }
Paul Bakker9af723c2014-05-01 13:03:14 +0200218#endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */
Manuel Pégourié-Gonnard80637c72013-12-26 16:09:58 +0100219
Paul Bakker89e80c92012-03-20 13:50:09 +0000220 lo = x[15] & 0xf;
221 hi = x[15] >> 4;
222
223 zh = ctx->HH[lo];
224 zl = ctx->HL[lo];
225
226 for( i = 15; i >= 0; i-- )
227 {
228 lo = x[i] & 0xf;
229 hi = x[i] >> 4;
230
231 if( i != 15 )
232 {
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000233 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000234 zl = ( zh << 60 ) | ( zl >> 4 );
235 zh = ( zh >> 4 );
236 zh ^= (uint64_t) last4[rem] << 48;
237 zh ^= ctx->HH[lo];
238 zl ^= ctx->HL[lo];
239
240 }
241
Paul Bakker4a2bd0d2012-11-02 11:06:08 +0000242 rem = (unsigned char) zl & 0xf;
Paul Bakker89e80c92012-03-20 13:50:09 +0000243 zl = ( zh << 60 ) | ( zl >> 4 );
244 zh = ( zh >> 4 );
245 zh ^= (uint64_t) last4[rem] << 48;
246 zh ^= ctx->HH[hi];
247 zl ^= ctx->HL[hi];
248 }
249
Paul Bakker5c2364c2012-10-01 14:41:15 +0000250 PUT_UINT32_BE( zh >> 32, output, 0 );
251 PUT_UINT32_BE( zh, output, 4 );
252 PUT_UINT32_BE( zl >> 32, output, 8 );
253 PUT_UINT32_BE( zl, output, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000254}
255
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200256int gcm_starts( gcm_context *ctx,
257 int mode,
258 const unsigned char *iv,
259 size_t iv_len,
260 const unsigned char *add,
261 size_t add_len )
Paul Bakker89e80c92012-03-20 13:50:09 +0000262{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200263 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000264 unsigned char work_buf[16];
265 size_t i;
Paul Bakker89e80c92012-03-20 13:50:09 +0000266 const unsigned char *p;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200267 size_t use_len, olen = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000268
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200269 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
270 if( ( (uint64_t) iv_len ) >> 61 != 0 ||
271 ( (uint64_t) add_len ) >> 61 != 0 )
272 {
273 return( POLARSSL_ERR_GCM_BAD_INPUT );
274 }
275
Paul Bakker52cf16c2013-07-26 13:55:38 +0200276 memset( ctx->y, 0x00, sizeof(ctx->y) );
277 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
278
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200279 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200280 ctx->len = 0;
281 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000282
283 if( iv_len == 12 )
284 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200285 memcpy( ctx->y, iv, iv_len );
286 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000287 }
288 else
289 {
290 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000291 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000292
293 p = iv;
294 while( iv_len > 0 )
295 {
296 use_len = ( iv_len < 16 ) ? iv_len : 16;
297
Paul Bakker67f9d532012-10-23 11:49:05 +0000298 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200299 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200300
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200301 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000302
303 iv_len -= use_len;
304 p += use_len;
305 }
306
Paul Bakker67f9d532012-10-23 11:49:05 +0000307 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200308 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000309
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200310 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000311 }
312
Paul Bakker43aff2a2013-09-09 00:10:27 +0200313 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
314 &olen ) ) != 0 )
315 {
316 return( ret );
317 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000318
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200319 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000320 p = add;
321 while( add_len > 0 )
322 {
323 use_len = ( add_len < 16 ) ? add_len : 16;
324
Paul Bakker67f9d532012-10-23 11:49:05 +0000325 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200326 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200327
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200328 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000329
330 add_len -= use_len;
331 p += use_len;
332 }
333
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200334 return( 0 );
335}
336
337int gcm_update( gcm_context *ctx,
338 size_t length,
339 const unsigned char *input,
340 unsigned char *output )
341{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200342 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200343 unsigned char ectr[16];
344 size_t i;
345 const unsigned char *p;
346 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200347 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200348
349 if( output > input && (size_t) ( output - input ) < length )
350 return( POLARSSL_ERR_GCM_BAD_INPUT );
351
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200352 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
353 * Also check for possible overflow */
354 if( ctx->len + length < ctx->len ||
355 (uint64_t) ctx->len + length > 0x03FFFFE0llu )
356 {
357 return( POLARSSL_ERR_GCM_BAD_INPUT );
358 }
359
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200360 ctx->len += length;
361
Paul Bakker89e80c92012-03-20 13:50:09 +0000362 p = input;
363 while( length > 0 )
364 {
365 use_len = ( length < 16 ) ? length : 16;
366
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100367 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200368 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000369 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000370
Paul Bakker43aff2a2013-09-09 00:10:27 +0200371 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
372 &olen ) ) != 0 )
373 {
374 return( ret );
375 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000376
Paul Bakker67f9d532012-10-23 11:49:05 +0000377 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000378 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200379 if( ctx->mode == GCM_DECRYPT )
380 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000381 out_p[i] = ectr[i] ^ p[i];
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200382 if( ctx->mode == GCM_ENCRYPT )
383 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000384 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200385
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200386 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200387
Paul Bakker89e80c92012-03-20 13:50:09 +0000388 length -= use_len;
389 p += use_len;
390 out_p += use_len;
391 }
392
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200393 return( 0 );
394}
395
396int gcm_finish( gcm_context *ctx,
397 unsigned char *tag,
398 size_t tag_len )
399{
400 unsigned char work_buf[16];
401 size_t i;
402 uint64_t orig_len = ctx->len * 8;
403 uint64_t orig_add_len = ctx->add_len * 8;
404
Manuel Pégourié-Gonnardb46e6ad2014-06-18 11:29:30 +0200405 if( tag_len > 16 || tag_len < 4 )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200406 return( POLARSSL_ERR_GCM_BAD_INPUT );
407
Manuel Pégourié-Gonnard9241be72013-08-31 17:31:03 +0200408 if( tag_len != 0 )
409 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200410
Paul Bakker89e80c92012-03-20 13:50:09 +0000411 if( orig_len || orig_add_len )
412 {
413 memset( work_buf, 0x00, 16 );
414
Paul Bakker0ecdb232013-04-09 11:36:42 +0200415 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
416 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
417 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
418 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000419
Paul Bakker67f9d532012-10-23 11:49:05 +0000420 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200421 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000422
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200423 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000424
Paul Bakker67f9d532012-10-23 11:49:05 +0000425 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200426 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000427 }
428
429 return( 0 );
430}
431
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200432int gcm_crypt_and_tag( gcm_context *ctx,
433 int mode,
434 size_t length,
435 const unsigned char *iv,
436 size_t iv_len,
437 const unsigned char *add,
438 size_t add_len,
439 const unsigned char *input,
440 unsigned char *output,
441 size_t tag_len,
442 unsigned char *tag )
443{
444 int ret;
445
446 if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
447 return( ret );
448
449 if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 )
450 return( ret );
451
452 if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 )
453 return( ret );
454
455 return( 0 );
456}
457
Paul Bakker89e80c92012-03-20 13:50:09 +0000458int gcm_auth_decrypt( gcm_context *ctx,
459 size_t length,
460 const unsigned char *iv,
461 size_t iv_len,
462 const unsigned char *add,
463 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200464 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000465 size_t tag_len,
466 const unsigned char *input,
467 unsigned char *output )
468{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100469 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000470 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200471 size_t i;
472 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000473
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100474 if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length,
475 iv, iv_len, add, add_len,
476 input, output, tag_len, check_tag ) ) != 0 )
477 {
478 return( ret );
479 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000480
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200481 /* Check tag in "constant-time" */
482 for( diff = 0, i = 0; i < tag_len; i++ )
483 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000484
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200485 if( diff != 0 )
486 {
Paul Bakker34617722014-06-13 17:20:13 +0200487 polarssl_zeroize( output, length );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200488 return( POLARSSL_ERR_GCM_AUTH_FAILED );
489 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000490
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200491 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000492}
493
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200494void gcm_free( gcm_context *ctx )
495{
496 (void) cipher_free_ctx( &ctx->cipher_ctx );
Paul Bakker34617722014-06-13 17:20:13 +0200497 polarssl_zeroize( ctx, sizeof( gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200498}
499
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200500#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000501
502#include <stdio.h>
503
504/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200505 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000506 *
507 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
508 */
509#define MAX_TESTS 6
510
511int key_index[MAX_TESTS] =
512 { 0, 0, 1, 1, 1, 1 };
513
514unsigned char key[MAX_TESTS][32] =
515{
516 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
521 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
522 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200523 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000524};
525
526size_t iv_len[MAX_TESTS] =
527 { 12, 12, 12, 12, 8, 60 };
528
529int iv_index[MAX_TESTS] =
530 { 0, 0, 1, 1, 1, 2 };
531
532unsigned char iv[MAX_TESTS][64] =
533{
534 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00 },
536 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
537 0xde, 0xca, 0xf8, 0x88 },
538 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200539 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000540 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200541 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000542 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200543 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000544 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200545 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000546};
547
548size_t add_len[MAX_TESTS] =
549 { 0, 0, 0, 20, 20, 20 };
550
551int add_index[MAX_TESTS] =
552 { 0, 0, 0, 1, 1, 1 };
553
554unsigned char additional[MAX_TESTS][64] =
555{
556 { 0x00 },
557 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200558 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000559 0xab, 0xad, 0xda, 0xd2 },
560};
561
562size_t pt_len[MAX_TESTS] =
563 { 0, 16, 64, 60, 60, 60 };
564
565int pt_index[MAX_TESTS] =
566 { 0, 0, 1, 1, 1, 1 };
567
568unsigned char pt[MAX_TESTS][64] =
569{
570 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
572 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
573 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
574 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
575 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
576 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
577 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
578 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
579 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
580};
581
582unsigned char ct[MAX_TESTS * 3][64] =
583{
584 { 0x00 },
585 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
586 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
587 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200588 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000589 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200590 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000591 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200592 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000593 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
594 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
595 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200596 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000597 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200598 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000599 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200600 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000601 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
602 0x3d, 0x58, 0xe0, 0x91 },
603 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200604 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000605 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200606 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000607 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200608 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000609 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
610 0xc2, 0x3f, 0x45, 0x98 },
611 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200612 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000613 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200614 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000615 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200616 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
618 0x4c, 0x34, 0xae, 0xe5 },
619 { 0x00 },
620 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200621 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000622 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200623 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000624 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200625 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000626 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200627 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000628 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
629 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
630 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200631 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000632 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200633 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
634 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
635 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000636 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200637 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000638 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200639 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000640 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200641 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000642 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200643 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000644 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200645 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000646 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200647 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000648 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200649 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000650 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200651 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000652 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200653 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000654 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200655 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
656 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
657 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
658 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
659 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
660 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
661 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
662 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
663 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
664 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
665 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
666 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
667 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
668 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
669 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
670 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
671 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
672 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000673 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200674 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000675 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200676 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000677 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200678 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000679 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200680 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000681 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200682 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000683 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200684 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000685 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200686 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000687 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200688 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000689};
690
691unsigned char tag[MAX_TESTS * 3][16] =
692{
693 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
694 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
695 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
696 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
697 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200698 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000699 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
700 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
701 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
702 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
703 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
704 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
705 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
706 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
707 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200708 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000709 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
710 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
711 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200712 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000713 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200714 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000715 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200716 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000717 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200718 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000719 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200720 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000721 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200722 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000723 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200724 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000725 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200726 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000727 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200728 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000729};
730
731int gcm_self_test( int verbose )
732{
733 gcm_context ctx;
734 unsigned char buf[64];
735 unsigned char tag_buf[16];
736 int i, j, ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200737 cipher_id_t cipher = POLARSSL_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000738
739 for( j = 0; j < 3; j++ )
740 {
741 int key_len = 128 + 64 * j;
742
743 for( i = 0; i < MAX_TESTS; i++ )
744 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200745 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100746 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
747 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200748
Paul Bakker43aff2a2013-09-09 00:10:27 +0200749 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000750
751 ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
752 pt_len[i],
753 iv[iv_index[i]], iv_len[i],
754 additional[add_index[i]], add_len[i],
755 pt[pt_index[i]], buf, 16, tag_buf );
756
757 if( ret != 0 ||
758 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
759 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
760 {
761 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100762 polarssl_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000763
764 return( 1 );
765 }
766
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200767 gcm_free( &ctx );
768
Paul Bakker89e80c92012-03-20 13:50:09 +0000769 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100770 polarssl_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000771
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200772 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100773 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
774 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200775
Paul Bakker43aff2a2013-09-09 00:10:27 +0200776 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000777
778 ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
779 pt_len[i],
780 iv[iv_index[i]], iv_len[i],
781 additional[add_index[i]], add_len[i],
782 ct[j * 6 + i], buf, 16, tag_buf );
783
784 if( ret != 0 ||
785 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
786 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
787 {
788 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100789 polarssl_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000790
791 return( 1 );
792 }
793
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200794 gcm_free( &ctx );
795
Paul Bakker89e80c92012-03-20 13:50:09 +0000796 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100797 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200798
799 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100800 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
801 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200802
Paul Bakker43aff2a2013-09-09 00:10:27 +0200803 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200804
805 ret = gcm_starts( &ctx, GCM_ENCRYPT,
806 iv[iv_index[i]], iv_len[i],
807 additional[add_index[i]], add_len[i] );
808 if( ret != 0 )
809 {
810 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100811 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200812
813 return( 1 );
814 }
815
816 if( pt_len[i] > 32 )
817 {
818 size_t rest_len = pt_len[i] - 32;
819 ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf );
820 if( ret != 0 )
821 {
822 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100823 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200824
825 return( 1 );
826 }
827
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200828 ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
829 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200830 if( ret != 0 )
831 {
832 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100833 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200834
835 return( 1 );
836 }
837 }
838 else
839 {
840 ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
841 if( ret != 0 )
842 {
843 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100844 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200845
846 return( 1 );
847 }
848 }
849
850 ret = gcm_finish( &ctx, tag_buf, 16 );
851 if( ret != 0 ||
852 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
853 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
854 {
855 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100856 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200857
858 return( 1 );
859 }
860
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200861 gcm_free( &ctx );
862
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200863 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100864 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200865
866 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100867 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
868 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200869
Paul Bakker43aff2a2013-09-09 00:10:27 +0200870 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200871
872 ret = gcm_starts( &ctx, GCM_DECRYPT,
873 iv[iv_index[i]], iv_len[i],
874 additional[add_index[i]], add_len[i] );
875 if( ret != 0 )
876 {
877 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100878 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200879
880 return( 1 );
881 }
882
883 if( pt_len[i] > 32 )
884 {
885 size_t rest_len = pt_len[i] - 32;
886 ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf );
887 if( ret != 0 )
888 {
889 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100890 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200891
892 return( 1 );
893 }
894
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200895 ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
896 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200897 if( ret != 0 )
898 {
899 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100900 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200901
902 return( 1 );
903 }
904 }
905 else
906 {
907 ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
908 if( ret != 0 )
909 {
910 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100911 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200912
913 return( 1 );
914 }
915 }
916
917 ret = gcm_finish( &ctx, tag_buf, 16 );
918 if( ret != 0 ||
919 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
920 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
921 {
922 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100923 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200924
925 return( 1 );
926 }
927
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200928 gcm_free( &ctx );
929
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200930 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100931 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200932
Paul Bakker89e80c92012-03-20 13:50:09 +0000933 }
934 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200935
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200936 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100937 polarssl_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000938
939 return( 0 );
940}
941
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200942
943
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200944#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000945
Paul Bakker9af723c2014-05-01 13:03:14 +0200946#endif /* POLARSSL_GCM_C */