blob: e42c6d017b06b9359d3639c82bd42ae2268dbccf [file] [log] [blame]
Paul Bakker89e80c92012-03-20 13:50:09 +00001/*
2 * NIST SP800-38D compliant GCM implementation
3 *
4 * Copyright (C) 2006-2012, Brainspark B.V.
5 *
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 */
25/*
26 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
27 */
28#include "polarssl/config.h"
29
30#if defined(POLARSSL_GCM_C)
31
32#include "polarssl/gcm.h"
33
34/*
35 * 32-bit integer manipulation macros (big endian)
36 */
37#ifndef GET_ULONG_BE
38#define GET_ULONG_BE(n,b,i) \
39{ \
40 (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
41 | ( (unsigned long) (b)[(i) + 1] << 16 ) \
42 | ( (unsigned long) (b)[(i) + 2] << 8 ) \
43 | ( (unsigned long) (b)[(i) + 3] ); \
44}
45#endif
46
47#ifndef PUT_ULONG_BE
48#define PUT_ULONG_BE(n,b,i) \
49{ \
50 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
51 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
52 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
53 (b)[(i) + 3] = (unsigned char) ( (n) ); \
54}
55#endif
56
57static void gcm_gen_table( gcm_context *ctx )
58{
59 int i, j;
60 uint64_t hi, lo;
61 uint64_t vl, vh;
62 unsigned char h[16];
63
64 memset( h, 0, 16 );
65 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, h, h );
66
67 ctx->HH[0] = 0;
68 ctx->HL[0] = 0;
69
70 GET_ULONG_BE( hi, h, 0 );
71 GET_ULONG_BE( lo, h, 4 );
72 vh = (uint64_t) hi << 32 | lo;
73
74 GET_ULONG_BE( hi, h, 8 );
75 GET_ULONG_BE( lo, h, 12 );
76 vl = (uint64_t) hi << 32 | lo;
77
78 ctx->HL[8] = vl;
79 ctx->HH[8] = vh;
80
81 for( i = 4; i > 0; i >>= 1 )
82 {
83 uint32_t T = ( vl & 1 ) ? 0xe1000000U : 0;
84 vl = ( vh << 63 ) | ( vl >> 1 );
85 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
86
87 ctx->HL[i] = vl;
88 ctx->HH[i] = vh;
89 }
90
91 for (i = 2; i < 16; i <<= 1 )
92 {
93 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
94 vh = *HiH;
95 vl = *HiL;
96 for( j = 1; j < i; j++ )
97 {
98 HiH[j] = vh ^ ctx->HH[j];
99 HiL[j] = vl ^ ctx->HL[j];
100 }
101 }
102
103}
104
105int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize )
106{
107 int ret;
108
109 memset( ctx, 0, sizeof(gcm_context) );
110
111 if( ( ret = aes_setkey_enc( &ctx->aes_ctx, key, keysize ) ) != 0 )
112 return( ret );
113
114 gcm_gen_table( ctx );
115
116 return( 0 );
117}
118
119static const uint64_t last4[16] =
120{
121 0x0000, 0x1c20, 0x3840, 0x2460,
122 0x7080, 0x6ca0, 0x48c0, 0x54e0,
123 0xe100, 0xfd20, 0xd940, 0xc560,
124 0x9180, 0x8da0, 0xa9c0, 0xb5e0
125};
126
127void gcm_mult( gcm_context *ctx, const unsigned char x[16], unsigned char output[16] )
128{
129 int i = 0;
130 unsigned char z[16];
131 unsigned char v[16];
132 unsigned char lo, hi, rem;
133 uint64_t zh, zl;
134
135 memset( z, 0x00, 16 );
136 memcpy( v, x, 16 );
137
138 lo = x[15] & 0xf;
139 hi = x[15] >> 4;
140
141 zh = ctx->HH[lo];
142 zl = ctx->HL[lo];
143
144 for( i = 15; i >= 0; i-- )
145 {
146 lo = x[i] & 0xf;
147 hi = x[i] >> 4;
148
149 if( i != 15 )
150 {
151 rem = zl & 0xf;
152 zl = ( zh << 60 ) | ( zl >> 4 );
153 zh = ( zh >> 4 );
154 zh ^= (uint64_t) last4[rem] << 48;
155 zh ^= ctx->HH[lo];
156 zl ^= ctx->HL[lo];
157
158 }
159
160 rem = zl & 0xf;
161 zl = ( zh << 60 ) | ( zl >> 4 );
162 zh = ( zh >> 4 );
163 zh ^= (uint64_t) last4[rem] << 48;
164 zh ^= ctx->HH[hi];
165 zl ^= ctx->HL[hi];
166 }
167
168 PUT_ULONG_BE( zh >> 32, output, 0 );
169 PUT_ULONG_BE( zh, output, 4 );
170 PUT_ULONG_BE( zl >> 32, output, 8 );
171 PUT_ULONG_BE( zl, output, 12 );
172}
173
174int gcm_crypt_and_tag( gcm_context *ctx,
175 int mode,
176 size_t length,
177 const unsigned char *iv,
178 size_t iv_len,
179 const unsigned char *add,
180 size_t add_len,
181 const unsigned char *input,
182 unsigned char *output,
183 size_t tag_len,
184 unsigned char *tag )
185{
186 unsigned char h[16];
187 unsigned char y[16];
188 unsigned char ectr[16];
189 unsigned char buf[16];
190 unsigned char ghash[16];
191 unsigned char work_buf[16];
192 size_t i;
193 unsigned char cb;
194 const unsigned char *p;
195 unsigned char *out_p = output;
196 size_t use_len;
197 size_t orig_len = length * 8;
198 size_t orig_add_len = add_len * 8;
199 unsigned char **xor_p;
200
201 memset( h, 0x00, 16 );
202 memset( y, 0x00, 16 );
203 memset( work_buf, 0x00, 16 );
204 memset( ghash, 0x00, 16 );
205 memset( tag, 0x00, tag_len );
206 memset( buf, 0x00, 16 );
207
208 if( mode == GCM_ENCRYPT )
209 xor_p = (unsigned char **) &out_p;
210 else
211 xor_p = (unsigned char **) &p;
212
213 if( iv_len == 12 )
214 {
215 memcpy( y, iv, iv_len );
216 y[15] = 1;
217 }
218 else
219 {
220 memset( work_buf, 0x00, 16 );
221 PUT_ULONG_BE( iv_len * 8, work_buf, 12 );
222
223 p = iv;
224 while( iv_len > 0 )
225 {
226 use_len = ( iv_len < 16 ) ? iv_len : 16;
227
228 if( use_len == 16 )
229 {
230 ((uint64_t *) y)[0] ^= ((uint64_t *) p)[0];
231 ((uint64_t *) y)[1] ^= ((uint64_t *) p)[1];
232 }
233 else
234 for( i = 0; i < use_len; i++ )
235 y[i] ^= p[i];
236
237 gcm_mult( ctx, y, y );
238
239 iv_len -= use_len;
240 p += use_len;
241 }
242
243 ((uint64_t *) y)[0] ^= ((uint64_t *) work_buf)[0];
244 ((uint64_t *) y)[1] ^= ((uint64_t *) work_buf)[1];
245
246 gcm_mult( ctx, y, y );
247 }
248
249 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
250 memcpy( tag, ectr, tag_len );
251
252 p = add;
253 while( add_len > 0 )
254 {
255 use_len = ( add_len < 16 ) ? add_len : 16;
256
257 if( use_len == 16 )
258 {
259 ((uint64_t *) buf)[0] ^= ((uint64_t *) p)[0];
260 ((uint64_t *) buf)[1] ^= ((uint64_t *) p)[1];
261 }
262 else
263 for( i = 0; i < use_len; i++ )
264 buf[i] ^= p[i];
265
266 gcm_mult( ctx, buf, buf );
267
268 add_len -= use_len;
269 p += use_len;
270 }
271
272 p = input;
273 while( length > 0 )
274 {
275 use_len = ( length < 16 ) ? length : 16;
276
277 i = 15;
278 do {
279 y[i]++;
280 cb = y[i] == 0;
281 } while( i-- && cb );
282
283 aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
284
285 if( use_len == 16 )
286 {
287 ((uint64_t *) out_p)[0] = ((uint64_t *) ectr)[0] ^
288 ((uint64_t *) p)[0];
289 ((uint64_t *) out_p)[1] = ((uint64_t *) ectr)[1] ^
290 ((uint64_t *) p)[1];
291 }
292 else
293 for( i = 0; i < use_len; i++ )
294 out_p[i] = ectr[i] ^ p[i];
295
296 if( use_len == 16 )
297 {
298 ((uint64_t *) buf)[0] ^= ((uint64_t *) (*xor_p))[0];
299 ((uint64_t *) buf)[1] ^= ((uint64_t *) (*xor_p))[1];
300 }
301 else
302 for( i = 0; i < use_len; i++ )
303 buf[i] ^= (*xor_p)[i];
304
305 gcm_mult( ctx, buf, buf );
306
307 length -= use_len;
308 p += use_len;
309 out_p += use_len;
310 }
311
312 if( orig_len || orig_add_len )
313 {
314 memset( work_buf, 0x00, 16 );
315
316 PUT_ULONG_BE( orig_add_len , work_buf, 4 );
317 PUT_ULONG_BE( orig_len , work_buf, 12 );
318
319 ((uint64_t *) buf)[0] ^= ((uint64_t *) work_buf)[0];
320 ((uint64_t *) buf)[1] ^= ((uint64_t *) work_buf)[1];
321
322 gcm_mult( ctx, buf, buf );
323
324 if( tag_len == 16 )
325 {
326 ((uint64_t *) tag)[0] ^= ((uint64_t *) buf)[0];
327 ((uint64_t *) tag)[1] ^= ((uint64_t *) buf)[1];
328 }
329 else
330 for( i = 0; i < tag_len; i++ )
331 tag[i] ^= buf[i];
332 }
333
334 return( 0 );
335}
336
337int gcm_auth_decrypt( gcm_context *ctx,
338 size_t length,
339 const unsigned char *iv,
340 size_t iv_len,
341 const unsigned char *add,
342 size_t add_len,
343 const unsigned char *tag,
344 size_t tag_len,
345 const unsigned char *input,
346 unsigned char *output )
347{
348 unsigned char check_tag[16];
349
350 gcm_crypt_and_tag( ctx, GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag );
351
352 if( memcmp( check_tag, tag, tag_len ) == 0 )
353 return( 0 );
354
355 memset( output, 0, length );
356
357 return( POLARSSL_ERR_GCM_AUTH_FAILED );
358}
359
360#if defined(POLARSSL_SELF_TEST)
361
362#include <stdio.h>
363
364/*
365 * GCM test vectors from:
366 *
367 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
368 */
369#define MAX_TESTS 6
370
371int key_index[MAX_TESTS] =
372 { 0, 0, 1, 1, 1, 1 };
373
374unsigned char key[MAX_TESTS][32] =
375{
376 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
380 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
381 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
382 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
383 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
384};
385
386size_t iv_len[MAX_TESTS] =
387 { 12, 12, 12, 12, 8, 60 };
388
389int iv_index[MAX_TESTS] =
390 { 0, 0, 1, 1, 1, 2 };
391
392unsigned char iv[MAX_TESTS][64] =
393{
394 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00 },
396 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
397 0xde, 0xca, 0xf8, 0x88 },
398 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
399 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
400 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
401 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
402 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
403 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
404 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
405 0xa6, 0x37, 0xb3, 0x9b },
406};
407
408size_t add_len[MAX_TESTS] =
409 { 0, 0, 0, 20, 20, 20 };
410
411int add_index[MAX_TESTS] =
412 { 0, 0, 0, 1, 1, 1 };
413
414unsigned char additional[MAX_TESTS][64] =
415{
416 { 0x00 },
417 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
418 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
419 0xab, 0xad, 0xda, 0xd2 },
420};
421
422size_t pt_len[MAX_TESTS] =
423 { 0, 16, 64, 60, 60, 60 };
424
425int pt_index[MAX_TESTS] =
426 { 0, 0, 1, 1, 1, 1 };
427
428unsigned char pt[MAX_TESTS][64] =
429{
430 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
432 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
433 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
434 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
435 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
436 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
437 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
438 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
439 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
440};
441
442unsigned char ct[MAX_TESTS * 3][64] =
443{
444 { 0x00 },
445 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
446 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
447 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
448 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
449 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
450 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
451 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
452 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
453 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
454 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
455 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
456 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
457 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
458 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
459 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
460 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
461 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
462 0x3d, 0x58, 0xe0, 0x91 },
463 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
464 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
465 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
466 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
467 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
468 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
469 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
470 0xc2, 0x3f, 0x45, 0x98 },
471 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
472 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
473 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
474 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
475 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
476 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
477 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
478 0x4c, 0x34, 0xae, 0xe5 },
479 { 0x00 },
480 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
481 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
482 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
483 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
484 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
485 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
486 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
487 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
488 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
489 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
490 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
491 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
492 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
493 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
494 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
495 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
496 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
497 0xcc, 0xda, 0x27, 0x10 },
498 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
499 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
500 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
501 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
502 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
503 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
504 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
505 0xa0, 0xf0, 0x62, 0xf7 },
506 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
507 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
508 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
509 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
510 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
511 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
512 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
513 0xe9, 0xb7, 0x37, 0x3b },
514 { 0x00 },
515 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
516 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
517 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
518 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
519 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
520 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
521 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
522 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
523 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
524 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
525 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
526 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
527 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
528 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
529 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
530 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
531 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
532 0xbc, 0xc9, 0xf6, 0x62 },
533 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
534 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
535 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
536 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
537 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
538 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
539 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
540 0xf4, 0x7c, 0x9b, 0x1f },
541 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
542 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
543 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
544 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
545 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
546 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
547 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
548 0x44, 0xae, 0x7e, 0x3f },
549};
550
551unsigned char tag[MAX_TESTS * 3][16] =
552{
553 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
554 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
555 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
556 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
557 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
558 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
559 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
560 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
561 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
562 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
563 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
564 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
565 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
566 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
567 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
568 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
569 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
570 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
571 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
572 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
573 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
574 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
575 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
576 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
577 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
578 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
579 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
580 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
581 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
582 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
583 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
584 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
585 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
586 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
587 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
588 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
589};
590
591int gcm_self_test( int verbose )
592{
593 gcm_context ctx;
594 unsigned char buf[64];
595 unsigned char tag_buf[16];
596 int i, j, ret;
597
598 for( j = 0; j < 3; j++ )
599 {
600 int key_len = 128 + 64 * j;
601
602 for( i = 0; i < MAX_TESTS; i++ )
603 {
604 printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "enc" );
605 gcm_init( &ctx, key[key_index[i]], key_len );
606
607 ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
608 pt_len[i],
609 iv[iv_index[i]], iv_len[i],
610 additional[add_index[i]], add_len[i],
611 pt[pt_index[i]], buf, 16, tag_buf );
612
613 if( ret != 0 ||
614 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
615 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
616 {
617 if( verbose != 0 )
618 printf( "failed\n" );
619
620 return( 1 );
621 }
622
623 if( verbose != 0 )
624 printf( "passed\n" );
625
626 printf( " AES-GCM-%3d #%d (%s): ", key_len, i, "dec" );
627 gcm_init( &ctx, key[key_index[i]], key_len );
628
629 ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
630 pt_len[i],
631 iv[iv_index[i]], iv_len[i],
632 additional[add_index[i]], add_len[i],
633 ct[j * 6 + i], buf, 16, tag_buf );
634
635 if( ret != 0 ||
636 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
637 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
638 {
639 if( verbose != 0 )
640 printf( "failed\n" );
641
642 return( 1 );
643 }
644
645 if( verbose != 0 )
646 printf( "passed\n" );
647 }
648 }
649
650 printf( "\n" );
651
652 return( 0 );
653}
654
655#endif
656
657#endif