blob: 4e40fbf90fb2c3d1c155317becd177285cfa5696 [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
Paul Bakker52cf16c2013-07-26 13:55:38 +0200269 memset( ctx->y, 0x00, sizeof(ctx->y) );
270 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
271
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200272 ctx->mode = mode;
Paul Bakker52cf16c2013-07-26 13:55:38 +0200273 ctx->len = 0;
274 ctx->add_len = 0;
Paul Bakker89e80c92012-03-20 13:50:09 +0000275
276 if( iv_len == 12 )
277 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200278 memcpy( ctx->y, iv, iv_len );
279 ctx->y[15] = 1;
Paul Bakker89e80c92012-03-20 13:50:09 +0000280 }
281 else
282 {
283 memset( work_buf, 0x00, 16 );
Paul Bakker5c2364c2012-10-01 14:41:15 +0000284 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000285
286 p = iv;
287 while( iv_len > 0 )
288 {
289 use_len = ( iv_len < 16 ) ? iv_len : 16;
290
Paul Bakker67f9d532012-10-23 11:49:05 +0000291 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200292 ctx->y[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200293
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200294 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000295
296 iv_len -= use_len;
297 p += use_len;
298 }
299
Paul Bakker67f9d532012-10-23 11:49:05 +0000300 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200301 ctx->y[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000302
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200303 gcm_mult( ctx, ctx->y, ctx->y );
Paul Bakker89e80c92012-03-20 13:50:09 +0000304 }
305
Paul Bakker43aff2a2013-09-09 00:10:27 +0200306 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
307 &olen ) ) != 0 )
308 {
309 return( ret );
310 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000311
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200312 ctx->add_len = add_len;
Paul Bakker89e80c92012-03-20 13:50:09 +0000313 p = add;
314 while( add_len > 0 )
315 {
316 use_len = ( add_len < 16 ) ? add_len : 16;
317
Paul Bakker67f9d532012-10-23 11:49:05 +0000318 for( i = 0; i < use_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200319 ctx->buf[i] ^= p[i];
Paul Bakker169b7f42013-06-25 14:58:00 +0200320
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200321 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000322
323 add_len -= use_len;
324 p += use_len;
325 }
326
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200327 return( 0 );
328}
329
330int gcm_update( gcm_context *ctx,
331 size_t length,
332 const unsigned char *input,
333 unsigned char *output )
334{
Paul Bakker43aff2a2013-09-09 00:10:27 +0200335 int ret;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200336 unsigned char ectr[16];
337 size_t i;
338 const unsigned char *p;
339 unsigned char *out_p = output;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200340 size_t use_len, olen = 0;
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200341
342 if( output > input && (size_t) ( output - input ) < length )
343 return( POLARSSL_ERR_GCM_BAD_INPUT );
344
345 ctx->len += length;
346
Paul Bakker89e80c92012-03-20 13:50:09 +0000347 p = input;
348 while( length > 0 )
349 {
350 use_len = ( length < 16 ) ? length : 16;
351
Paul Bakker3d2dc0f2013-02-27 14:52:37 +0100352 for( i = 16; i > 12; i-- )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200353 if( ++ctx->y[i - 1] != 0 )
Paul Bakkerfc5183c2012-04-18 14:17:01 +0000354 break;
Paul Bakker89e80c92012-03-20 13:50:09 +0000355
Paul Bakker43aff2a2013-09-09 00:10:27 +0200356 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
357 &olen ) ) != 0 )
358 {
359 return( ret );
360 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000361
Paul Bakker67f9d532012-10-23 11:49:05 +0000362 for( i = 0; i < use_len; i++ )
Paul Bakker89e80c92012-03-20 13:50:09 +0000363 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200364 if( ctx->mode == GCM_DECRYPT )
365 ctx->buf[i] ^= p[i];
Paul Bakker67f9d532012-10-23 11:49:05 +0000366 out_p[i] = ectr[i] ^ p[i];
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200367 if( ctx->mode == GCM_ENCRYPT )
368 ctx->buf[i] ^= out_p[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000369 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200370
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200371 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker169b7f42013-06-25 14:58:00 +0200372
Paul Bakker89e80c92012-03-20 13:50:09 +0000373 length -= use_len;
374 p += use_len;
375 out_p += use_len;
376 }
377
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200378 return( 0 );
379}
380
381int gcm_finish( gcm_context *ctx,
382 unsigned char *tag,
383 size_t tag_len )
384{
385 unsigned char work_buf[16];
386 size_t i;
387 uint64_t orig_len = ctx->len * 8;
388 uint64_t orig_add_len = ctx->add_len * 8;
389
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200390 if( tag_len > 16 )
391 return( POLARSSL_ERR_GCM_BAD_INPUT );
392
Manuel Pégourié-Gonnard9241be72013-08-31 17:31:03 +0200393 if( tag_len != 0 )
394 memcpy( tag, ctx->base_ectr, tag_len );
Manuel Pégourié-Gonnard07f8fa52013-08-30 18:34:08 +0200395
Paul Bakker89e80c92012-03-20 13:50:09 +0000396 if( orig_len || orig_add_len )
397 {
398 memset( work_buf, 0x00, 16 );
399
Paul Bakker0ecdb232013-04-09 11:36:42 +0200400 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
401 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
402 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
403 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000404
Paul Bakker67f9d532012-10-23 11:49:05 +0000405 for( i = 0; i < 16; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200406 ctx->buf[i] ^= work_buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000407
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200408 gcm_mult( ctx, ctx->buf, ctx->buf );
Paul Bakker89e80c92012-03-20 13:50:09 +0000409
Paul Bakker67f9d532012-10-23 11:49:05 +0000410 for( i = 0; i < tag_len; i++ )
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200411 tag[i] ^= ctx->buf[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000412 }
413
414 return( 0 );
415}
416
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200417int gcm_crypt_and_tag( gcm_context *ctx,
418 int mode,
419 size_t length,
420 const unsigned char *iv,
421 size_t iv_len,
422 const unsigned char *add,
423 size_t add_len,
424 const unsigned char *input,
425 unsigned char *output,
426 size_t tag_len,
427 unsigned char *tag )
428{
429 int ret;
430
431 if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
432 return( ret );
433
434 if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 )
435 return( ret );
436
437 if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 )
438 return( ret );
439
440 return( 0 );
441}
442
Paul Bakker89e80c92012-03-20 13:50:09 +0000443int gcm_auth_decrypt( gcm_context *ctx,
444 size_t length,
445 const unsigned char *iv,
446 size_t iv_len,
447 const unsigned char *add,
448 size_t add_len,
Paul Bakker169b7f42013-06-25 14:58:00 +0200449 const unsigned char *tag,
Paul Bakker89e80c92012-03-20 13:50:09 +0000450 size_t tag_len,
451 const unsigned char *input,
452 unsigned char *output )
453{
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100454 int ret;
Paul Bakker89e80c92012-03-20 13:50:09 +0000455 unsigned char check_tag[16];
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200456 size_t i;
457 int diff;
Paul Bakker89e80c92012-03-20 13:50:09 +0000458
Manuel Pégourié-Gonnard073f0fa2014-01-18 18:49:32 +0100459 if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length,
460 iv, iv_len, add, add_len,
461 input, output, tag_len, check_tag ) ) != 0 )
462 {
463 return( ret );
464 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000465
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200466 /* Check tag in "constant-time" */
467 for( diff = 0, i = 0; i < tag_len; i++ )
468 diff |= tag[i] ^ check_tag[i];
Paul Bakker89e80c92012-03-20 13:50:09 +0000469
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200470 if( diff != 0 )
471 {
Paul Bakker34617722014-06-13 17:20:13 +0200472 polarssl_zeroize( output, length );
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200473 return( POLARSSL_ERR_GCM_AUTH_FAILED );
474 }
Paul Bakker89e80c92012-03-20 13:50:09 +0000475
Manuel Pégourié-Gonnard20d6a172013-08-31 16:37:46 +0200476 return( 0 );
Paul Bakker89e80c92012-03-20 13:50:09 +0000477}
478
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200479void gcm_free( gcm_context *ctx )
480{
481 (void) cipher_free_ctx( &ctx->cipher_ctx );
Paul Bakker34617722014-06-13 17:20:13 +0200482 polarssl_zeroize( ctx, sizeof( gcm_context ) );
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200483}
484
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200485#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
Paul Bakker89e80c92012-03-20 13:50:09 +0000486
487#include <stdio.h>
488
489/*
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200490 * AES-GCM test vectors from:
Paul Bakker89e80c92012-03-20 13:50:09 +0000491 *
492 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
493 */
494#define MAX_TESTS 6
495
496int key_index[MAX_TESTS] =
497 { 0, 0, 1, 1, 1, 1 };
498
499unsigned char key[MAX_TESTS][32] =
500{
501 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
505 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
506 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
507 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200508 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000509};
510
511size_t iv_len[MAX_TESTS] =
512 { 12, 12, 12, 12, 8, 60 };
513
514int iv_index[MAX_TESTS] =
515 { 0, 0, 1, 1, 1, 2 };
516
517unsigned char iv[MAX_TESTS][64] =
518{
519 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
520 0x00, 0x00, 0x00, 0x00 },
521 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
522 0xde, 0xca, 0xf8, 0x88 },
523 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
Paul Bakker169b7f42013-06-25 14:58:00 +0200524 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
Paul Bakker89e80c92012-03-20 13:50:09 +0000525 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200526 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
Paul Bakker89e80c92012-03-20 13:50:09 +0000527 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
Paul Bakker169b7f42013-06-25 14:58:00 +0200528 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
Paul Bakker89e80c92012-03-20 13:50:09 +0000529 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
Paul Bakker169b7f42013-06-25 14:58:00 +0200530 0xa6, 0x37, 0xb3, 0x9b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000531};
532
533size_t add_len[MAX_TESTS] =
534 { 0, 0, 0, 20, 20, 20 };
535
536int add_index[MAX_TESTS] =
537 { 0, 0, 0, 1, 1, 1 };
538
539unsigned char additional[MAX_TESTS][64] =
540{
541 { 0x00 },
542 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200543 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
Paul Bakker89e80c92012-03-20 13:50:09 +0000544 0xab, 0xad, 0xda, 0xd2 },
545};
546
547size_t pt_len[MAX_TESTS] =
548 { 0, 16, 64, 60, 60, 60 };
549
550int pt_index[MAX_TESTS] =
551 { 0, 0, 1, 1, 1, 1 };
552
553unsigned char pt[MAX_TESTS][64] =
554{
555 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
557 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
558 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
559 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
560 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
561 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
562 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
563 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
564 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
565};
566
567unsigned char ct[MAX_TESTS * 3][64] =
568{
569 { 0x00 },
570 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
571 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
572 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200573 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000574 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200575 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000576 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200577 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000578 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
579 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
580 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200581 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000582 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200583 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
Paul Bakker89e80c92012-03-20 13:50:09 +0000584 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200585 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
Paul Bakker89e80c92012-03-20 13:50:09 +0000586 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
587 0x3d, 0x58, 0xe0, 0x91 },
588 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
Paul Bakker169b7f42013-06-25 14:58:00 +0200589 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
Paul Bakker89e80c92012-03-20 13:50:09 +0000590 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200591 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
Paul Bakker89e80c92012-03-20 13:50:09 +0000592 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
Paul Bakker169b7f42013-06-25 14:58:00 +0200593 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
Paul Bakker89e80c92012-03-20 13:50:09 +0000594 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
595 0xc2, 0x3f, 0x45, 0x98 },
596 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200597 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
Paul Bakker89e80c92012-03-20 13:50:09 +0000598 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
Paul Bakker169b7f42013-06-25 14:58:00 +0200599 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
Paul Bakker89e80c92012-03-20 13:50:09 +0000600 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
Paul Bakker169b7f42013-06-25 14:58:00 +0200601 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
Paul Bakker89e80c92012-03-20 13:50:09 +0000602 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
603 0x4c, 0x34, 0xae, 0xe5 },
604 { 0x00 },
605 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200606 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000607 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200608 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000609 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200610 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
Paul Bakker89e80c92012-03-20 13:50:09 +0000611 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
Paul Bakker169b7f42013-06-25 14:58:00 +0200612 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000613 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
614 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
615 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
Paul Bakker169b7f42013-06-25 14:58:00 +0200616 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000617 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
Paul Bakker169b7f42013-06-25 14:58:00 +0200618 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
619 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
620 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
Paul Bakker89e80c92012-03-20 13:50:09 +0000621 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200622 0xcc, 0xda, 0x27, 0x10 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000623 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
Paul Bakker169b7f42013-06-25 14:58:00 +0200624 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
Paul Bakker89e80c92012-03-20 13:50:09 +0000625 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200626 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
Paul Bakker89e80c92012-03-20 13:50:09 +0000627 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
Paul Bakker169b7f42013-06-25 14:58:00 +0200628 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
Paul Bakker89e80c92012-03-20 13:50:09 +0000629 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200630 0xa0, 0xf0, 0x62, 0xf7 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000631 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
Paul Bakker169b7f42013-06-25 14:58:00 +0200632 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
Paul Bakker89e80c92012-03-20 13:50:09 +0000633 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
Paul Bakker169b7f42013-06-25 14:58:00 +0200634 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
Paul Bakker89e80c92012-03-20 13:50:09 +0000635 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200636 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
Paul Bakker89e80c92012-03-20 13:50:09 +0000637 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
Paul Bakker169b7f42013-06-25 14:58:00 +0200638 0xe9, 0xb7, 0x37, 0x3b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000639 { 0x00 },
Paul Bakker169b7f42013-06-25 14:58:00 +0200640 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
641 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
642 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
643 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
644 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
645 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
646 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
647 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
648 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
649 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
650 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
651 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
652 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
653 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
654 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
655 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
656 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
657 0xbc, 0xc9, 0xf6, 0x62 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000658 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
Paul Bakker169b7f42013-06-25 14:58:00 +0200659 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
Paul Bakker89e80c92012-03-20 13:50:09 +0000660 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
Paul Bakker169b7f42013-06-25 14:58:00 +0200661 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
Paul Bakker89e80c92012-03-20 13:50:09 +0000662 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200663 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
Paul Bakker89e80c92012-03-20 13:50:09 +0000664 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
Paul Bakker169b7f42013-06-25 14:58:00 +0200665 0xf4, 0x7c, 0x9b, 0x1f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000666 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
Paul Bakker169b7f42013-06-25 14:58:00 +0200667 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
Paul Bakker89e80c92012-03-20 13:50:09 +0000668 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
Paul Bakker169b7f42013-06-25 14:58:00 +0200669 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
Paul Bakker89e80c92012-03-20 13:50:09 +0000670 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
Paul Bakker169b7f42013-06-25 14:58:00 +0200671 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
Paul Bakker89e80c92012-03-20 13:50:09 +0000672 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
Paul Bakker169b7f42013-06-25 14:58:00 +0200673 0x44, 0xae, 0x7e, 0x3f },
Paul Bakker89e80c92012-03-20 13:50:09 +0000674};
675
676unsigned char tag[MAX_TESTS * 3][16] =
677{
678 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
679 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
680 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
681 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
682 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
Paul Bakker169b7f42013-06-25 14:58:00 +0200683 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000684 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
685 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
686 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
687 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
688 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
689 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
690 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
691 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
692 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
Paul Bakker169b7f42013-06-25 14:58:00 +0200693 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
Paul Bakker89e80c92012-03-20 13:50:09 +0000694 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
695 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
696 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
Paul Bakker169b7f42013-06-25 14:58:00 +0200697 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000698 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
Paul Bakker169b7f42013-06-25 14:58:00 +0200699 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000700 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
Paul Bakker169b7f42013-06-25 14:58:00 +0200701 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000702 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
Paul Bakker169b7f42013-06-25 14:58:00 +0200703 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000704 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200705 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000706 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
Paul Bakker169b7f42013-06-25 14:58:00 +0200707 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
Paul Bakker89e80c92012-03-20 13:50:09 +0000708 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
Paul Bakker169b7f42013-06-25 14:58:00 +0200709 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
Paul Bakker89e80c92012-03-20 13:50:09 +0000710 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
Paul Bakker169b7f42013-06-25 14:58:00 +0200711 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
Paul Bakker89e80c92012-03-20 13:50:09 +0000712 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
Paul Bakker169b7f42013-06-25 14:58:00 +0200713 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
Paul Bakker89e80c92012-03-20 13:50:09 +0000714};
715
716int gcm_self_test( int verbose )
717{
718 gcm_context ctx;
719 unsigned char buf[64];
720 unsigned char tag_buf[16];
721 int i, j, ret;
Paul Bakker43aff2a2013-09-09 00:10:27 +0200722 cipher_id_t cipher = POLARSSL_CIPHER_ID_AES;
Paul Bakker89e80c92012-03-20 13:50:09 +0000723
724 for( j = 0; j < 3; j++ )
725 {
726 int key_len = 128 + 64 * j;
727
728 for( i = 0; i < MAX_TESTS; i++ )
729 {
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200730 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100731 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
732 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200733
Paul Bakker43aff2a2013-09-09 00:10:27 +0200734 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000735
736 ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
737 pt_len[i],
738 iv[iv_index[i]], iv_len[i],
739 additional[add_index[i]], add_len[i],
740 pt[pt_index[i]], buf, 16, tag_buf );
741
742 if( ret != 0 ||
743 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
744 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
745 {
746 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100747 polarssl_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000748
749 return( 1 );
750 }
751
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200752 gcm_free( &ctx );
753
Paul Bakker89e80c92012-03-20 13:50:09 +0000754 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100755 polarssl_printf( "passed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000756
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200757 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100758 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
759 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200760
Paul Bakker43aff2a2013-09-09 00:10:27 +0200761 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakker89e80c92012-03-20 13:50:09 +0000762
763 ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
764 pt_len[i],
765 iv[iv_index[i]], iv_len[i],
766 additional[add_index[i]], add_len[i],
767 ct[j * 6 + i], buf, 16, tag_buf );
768
769 if( ret != 0 ||
770 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
771 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
772 {
773 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100774 polarssl_printf( "failed\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000775
776 return( 1 );
777 }
778
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200779 gcm_free( &ctx );
780
Paul Bakker89e80c92012-03-20 13:50:09 +0000781 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100782 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200783
784 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100785 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
786 key_len, i, "enc" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200787
Paul Bakker43aff2a2013-09-09 00:10:27 +0200788 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200789
790 ret = gcm_starts( &ctx, GCM_ENCRYPT,
791 iv[iv_index[i]], iv_len[i],
792 additional[add_index[i]], add_len[i] );
793 if( ret != 0 )
794 {
795 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100796 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200797
798 return( 1 );
799 }
800
801 if( pt_len[i] > 32 )
802 {
803 size_t rest_len = pt_len[i] - 32;
804 ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf );
805 if( ret != 0 )
806 {
807 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100808 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200809
810 return( 1 );
811 }
812
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200813 ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
814 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200815 if( ret != 0 )
816 {
817 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100818 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200819
820 return( 1 );
821 }
822 }
823 else
824 {
825 ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
826 if( ret != 0 )
827 {
828 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100829 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200830
831 return( 1 );
832 }
833 }
834
835 ret = gcm_finish( &ctx, tag_buf, 16 );
836 if( ret != 0 ||
837 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
838 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
839 {
840 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100841 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200842
843 return( 1 );
844 }
845
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200846 gcm_free( &ctx );
847
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200848 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100849 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200850
851 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100852 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
853 key_len, i, "dec" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200854
Paul Bakker43aff2a2013-09-09 00:10:27 +0200855 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200856
857 ret = gcm_starts( &ctx, GCM_DECRYPT,
858 iv[iv_index[i]], iv_len[i],
859 additional[add_index[i]], add_len[i] );
860 if( ret != 0 )
861 {
862 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100863 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200864
865 return( 1 );
866 }
867
868 if( pt_len[i] > 32 )
869 {
870 size_t rest_len = pt_len[i] - 32;
871 ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf );
872 if( ret != 0 )
873 {
874 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100875 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200876
877 return( 1 );
878 }
879
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200880 ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
881 buf + 32 );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200882 if( ret != 0 )
883 {
884 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100885 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200886
887 return( 1 );
888 }
889 }
890 else
891 {
892 ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
893 if( ret != 0 )
894 {
895 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100896 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200897
898 return( 1 );
899 }
900 }
901
902 ret = gcm_finish( &ctx, tag_buf, 16 );
903 if( ret != 0 ||
904 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
905 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
906 {
907 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100908 polarssl_printf( "failed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200909
910 return( 1 );
911 }
912
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200913 gcm_free( &ctx );
914
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200915 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100916 polarssl_printf( "passed\n" );
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200917
Paul Bakker89e80c92012-03-20 13:50:09 +0000918 }
919 }
Paul Bakker169b7f42013-06-25 14:58:00 +0200920
Paul Bakkerb9d3cfa2013-06-26 15:07:16 +0200921 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100922 polarssl_printf( "\n" );
Paul Bakker89e80c92012-03-20 13:50:09 +0000923
924 return( 0 );
925}
926
Manuel Pégourié-Gonnard4fe92002013-09-13 13:45:58 +0200927
928
Manuel Pégourié-Gonnarddae70932013-10-24 15:06:33 +0200929#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
Paul Bakker89e80c92012-03-20 13:50:09 +0000930
Paul Bakker9af723c2014-05-01 13:03:14 +0200931#endif /* POLARSSL_GCM_C */