dolphin/Externals/polarssl/library/gcm.c
Ryan Houdek a48e284317 Update external polarssl to 1.3.8
There were some fixes back on March 13th, 2014 for fixing compiling on MIPS64.
Also some fixes on June 25th, 2014 for SPARC64 fixes.

Probably more things, but those are what I care about.
2014-09-08 02:21:18 -05:00

948 lines
29 KiB
C

/*
* NIST SP800-38D compliant GCM implementation
*
* Copyright (C) 2006-2014, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
*
* See also:
* [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
*
* We use the algorithm described as Shoup's method with 4-bit tables in
* [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
*/
#if !defined(POLARSSL_CONFIG_FILE)
#include "polarssl/config.h"
#else
#include POLARSSL_CONFIG_FILE
#endif
#if defined(POLARSSL_GCM_C)
#include "polarssl/gcm.h"
#if defined(POLARSSL_AESNI_C)
#include "polarssl/aesni.h"
#endif
#if defined(POLARSSL_PLATFORM_C)
#include "polarssl/platform.h"
#else
#define polarssl_printf printf
#endif
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/* Implementation that should never be optimized out by the compiler */
static void polarssl_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
/*
* Precompute small multiples of H, that is set
* HH[i] || HL[i] = H times i,
* where i is seen as a field element as in [MGV], ie high-order bits
* correspond to low powers of P. The result is stored in the same way, that
* is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
* corresponds to P^127.
*/
static int gcm_gen_table( gcm_context *ctx )
{
int ret, i, j;
uint64_t hi, lo;
uint64_t vl, vh;
unsigned char h[16];
size_t olen = 0;
memset( h, 0, 16 );
if( ( ret = cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
return( ret );
/* pack h as two 64-bits ints, big-endian */
GET_UINT32_BE( hi, h, 0 );
GET_UINT32_BE( lo, h, 4 );
vh = (uint64_t) hi << 32 | lo;
GET_UINT32_BE( hi, h, 8 );
GET_UINT32_BE( lo, h, 12 );
vl = (uint64_t) hi << 32 | lo;
/* 8 = 1000 corresponds to 1 in GF(2^128) */
ctx->HL[8] = vl;
ctx->HH[8] = vh;
#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
/* With CLMUL support, we need only h, not the rest of the table */
if( aesni_supports( POLARSSL_AESNI_CLMUL ) )
return( 0 );
#endif
/* 0 corresponds to 0 in GF(2^128) */
ctx->HH[0] = 0;
ctx->HL[0] = 0;
for( i = 4; i > 0; i >>= 1 )
{
uint32_t T = ( vl & 1 ) * 0xe1000000U;
vl = ( vh << 63 ) | ( vl >> 1 );
vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
ctx->HL[i] = vl;
ctx->HH[i] = vh;
}
for( i = 2; i < 16; i <<= 1 )
{
uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
vh = *HiH;
vl = *HiL;
for( j = 1; j < i; j++ )
{
HiH[j] = vh ^ ctx->HH[j];
HiL[j] = vl ^ ctx->HL[j];
}
}
return( 0 );
}
int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
unsigned int keysize )
{
int ret;
const cipher_info_t *cipher_info;
memset( ctx, 0, sizeof(gcm_context) );
cipher_init( &ctx->cipher_ctx );
cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
if( cipher_info == NULL )
return( POLARSSL_ERR_GCM_BAD_INPUT );
if( cipher_info->block_size != 16 )
return( POLARSSL_ERR_GCM_BAD_INPUT );
if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
return( ret );
if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize,
POLARSSL_ENCRYPT ) ) != 0 )
{
return( ret );
}
if( ( ret = gcm_gen_table( ctx ) ) != 0 )
return( ret );
return( 0 );
}
/*
* Shoup's method for multiplication use this table with
* last4[x] = x times P^128
* where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
*/
static const uint64_t last4[16] =
{
0x0000, 0x1c20, 0x3840, 0x2460,
0x7080, 0x6ca0, 0x48c0, 0x54e0,
0xe100, 0xfd20, 0xd940, 0xc560,
0x9180, 0x8da0, 0xa9c0, 0xb5e0
};
/*
* Sets output to x times H using the precomputed tables.
* x and output are seen as elements of GF(2^128) as in [MGV].
*/
static void gcm_mult( gcm_context *ctx, const unsigned char x[16],
unsigned char output[16] )
{
int i = 0;
unsigned char lo, hi, rem;
uint64_t zh, zl;
#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) {
unsigned char h[16];
PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
PUT_UINT32_BE( ctx->HH[8], h, 4 );
PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
PUT_UINT32_BE( ctx->HL[8], h, 12 );
aesni_gcm_mult( output, x, h );
return;
}
#endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */
lo = x[15] & 0xf;
hi = x[15] >> 4;
zh = ctx->HH[lo];
zl = ctx->HL[lo];
for( i = 15; i >= 0; i-- )
{
lo = x[i] & 0xf;
hi = x[i] >> 4;
if( i != 15 )
{
rem = (unsigned char) zl & 0xf;
zl = ( zh << 60 ) | ( zl >> 4 );
zh = ( zh >> 4 );
zh ^= (uint64_t) last4[rem] << 48;
zh ^= ctx->HH[lo];
zl ^= ctx->HL[lo];
}
rem = (unsigned char) zl & 0xf;
zl = ( zh << 60 ) | ( zl >> 4 );
zh = ( zh >> 4 );
zh ^= (uint64_t) last4[rem] << 48;
zh ^= ctx->HH[hi];
zl ^= ctx->HL[hi];
}
PUT_UINT32_BE( zh >> 32, output, 0 );
PUT_UINT32_BE( zh, output, 4 );
PUT_UINT32_BE( zl >> 32, output, 8 );
PUT_UINT32_BE( zl, output, 12 );
}
int gcm_starts( gcm_context *ctx,
int mode,
const unsigned char *iv,
size_t iv_len,
const unsigned char *add,
size_t add_len )
{
int ret;
unsigned char work_buf[16];
size_t i;
const unsigned char *p;
size_t use_len, olen = 0;
/* IV and AD are limited to 2^64 bits, so 2^61 bytes */
if( ( (uint64_t) iv_len ) >> 61 != 0 ||
( (uint64_t) add_len ) >> 61 != 0 )
{
return( POLARSSL_ERR_GCM_BAD_INPUT );
}
memset( ctx->y, 0x00, sizeof(ctx->y) );
memset( ctx->buf, 0x00, sizeof(ctx->buf) );
ctx->mode = mode;
ctx->len = 0;
ctx->add_len = 0;
if( iv_len == 12 )
{
memcpy( ctx->y, iv, iv_len );
ctx->y[15] = 1;
}
else
{
memset( work_buf, 0x00, 16 );
PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
p = iv;
while( iv_len > 0 )
{
use_len = ( iv_len < 16 ) ? iv_len : 16;
for( i = 0; i < use_len; i++ )
ctx->y[i] ^= p[i];
gcm_mult( ctx, ctx->y, ctx->y );
iv_len -= use_len;
p += use_len;
}
for( i = 0; i < 16; i++ )
ctx->y[i] ^= work_buf[i];
gcm_mult( ctx, ctx->y, ctx->y );
}
if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
&olen ) ) != 0 )
{
return( ret );
}
ctx->add_len = add_len;
p = add;
while( add_len > 0 )
{
use_len = ( add_len < 16 ) ? add_len : 16;
for( i = 0; i < use_len; i++ )
ctx->buf[i] ^= p[i];
gcm_mult( ctx, ctx->buf, ctx->buf );
add_len -= use_len;
p += use_len;
}
return( 0 );
}
int gcm_update( gcm_context *ctx,
size_t length,
const unsigned char *input,
unsigned char *output )
{
int ret;
unsigned char ectr[16];
size_t i;
const unsigned char *p;
unsigned char *out_p = output;
size_t use_len, olen = 0;
if( output > input && (size_t) ( output - input ) < length )
return( POLARSSL_ERR_GCM_BAD_INPUT );
/* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
* Also check for possible overflow */
if( ctx->len + length < ctx->len ||
(uint64_t) ctx->len + length > 0x03FFFFE0llu )
{
return( POLARSSL_ERR_GCM_BAD_INPUT );
}
ctx->len += length;
p = input;
while( length > 0 )
{
use_len = ( length < 16 ) ? length : 16;
for( i = 16; i > 12; i-- )
if( ++ctx->y[i - 1] != 0 )
break;
if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
&olen ) ) != 0 )
{
return( ret );
}
for( i = 0; i < use_len; i++ )
{
if( ctx->mode == GCM_DECRYPT )
ctx->buf[i] ^= p[i];
out_p[i] = ectr[i] ^ p[i];
if( ctx->mode == GCM_ENCRYPT )
ctx->buf[i] ^= out_p[i];
}
gcm_mult( ctx, ctx->buf, ctx->buf );
length -= use_len;
p += use_len;
out_p += use_len;
}
return( 0 );
}
int gcm_finish( gcm_context *ctx,
unsigned char *tag,
size_t tag_len )
{
unsigned char work_buf[16];
size_t i;
uint64_t orig_len = ctx->len * 8;
uint64_t orig_add_len = ctx->add_len * 8;
if( tag_len > 16 || tag_len < 4 )
return( POLARSSL_ERR_GCM_BAD_INPUT );
if( tag_len != 0 )
memcpy( tag, ctx->base_ectr, tag_len );
if( orig_len || orig_add_len )
{
memset( work_buf, 0x00, 16 );
PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
for( i = 0; i < 16; i++ )
ctx->buf[i] ^= work_buf[i];
gcm_mult( ctx, ctx->buf, ctx->buf );
for( i = 0; i < tag_len; i++ )
tag[i] ^= ctx->buf[i];
}
return( 0 );
}
int gcm_crypt_and_tag( gcm_context *ctx,
int mode,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *add,
size_t add_len,
const unsigned char *input,
unsigned char *output,
size_t tag_len,
unsigned char *tag )
{
int ret;
if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
return( ret );
if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 )
return( ret );
if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 )
return( ret );
return( 0 );
}
int gcm_auth_decrypt( gcm_context *ctx,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *add,
size_t add_len,
const unsigned char *tag,
size_t tag_len,
const unsigned char *input,
unsigned char *output )
{
int ret;
unsigned char check_tag[16];
size_t i;
int diff;
if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length,
iv, iv_len, add, add_len,
input, output, tag_len, check_tag ) ) != 0 )
{
return( ret );
}
/* Check tag in "constant-time" */
for( diff = 0, i = 0; i < tag_len; i++ )
diff |= tag[i] ^ check_tag[i];
if( diff != 0 )
{
polarssl_zeroize( output, length );
return( POLARSSL_ERR_GCM_AUTH_FAILED );
}
return( 0 );
}
void gcm_free( gcm_context *ctx )
{
cipher_free( &ctx->cipher_ctx );
polarssl_zeroize( ctx, sizeof( gcm_context ) );
}
#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
#include <stdio.h>
/*
* AES-GCM test vectors from:
*
* http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
*/
#define MAX_TESTS 6
int key_index[MAX_TESTS] =
{ 0, 0, 1, 1, 1, 1 };
unsigned char key[MAX_TESTS][32] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
};
size_t iv_len[MAX_TESTS] =
{ 12, 12, 12, 12, 8, 60 };
int iv_index[MAX_TESTS] =
{ 0, 0, 1, 1, 1, 2 };
unsigned char iv[MAX_TESTS][64] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 },
{ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
0xde, 0xca, 0xf8, 0x88 },
{ 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
0xa6, 0x37, 0xb3, 0x9b },
};
size_t add_len[MAX_TESTS] =
{ 0, 0, 0, 20, 20, 20 };
int add_index[MAX_TESTS] =
{ 0, 0, 0, 1, 1, 1 };
unsigned char additional[MAX_TESTS][64] =
{
{ 0x00 },
{ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
0xab, 0xad, 0xda, 0xd2 },
};
size_t pt_len[MAX_TESTS] =
{ 0, 16, 64, 60, 60, 60 };
int pt_index[MAX_TESTS] =
{ 0, 0, 1, 1, 1, 1 };
unsigned char pt[MAX_TESTS][64] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
};
unsigned char ct[MAX_TESTS * 3][64] =
{
{ 0x00 },
{ 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
{ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
{ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91 },
{ 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
0xc2, 0x3f, 0x45, 0x98 },
{ 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
0x4c, 0x34, 0xae, 0xe5 },
{ 0x00 },
{ 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
{ 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
{ 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
0xcc, 0xda, 0x27, 0x10 },
{ 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
0xa0, 0xf0, 0x62, 0xf7 },
{ 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
0xe9, 0xb7, 0x37, 0x3b },
{ 0x00 },
{ 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
{ 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
{ 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
0xbc, 0xc9, 0xf6, 0x62 },
{ 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
0xf4, 0x7c, 0x9b, 0x1f },
{ 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
0x44, 0xae, 0x7e, 0x3f },
};
unsigned char tag[MAX_TESTS * 3][16] =
{
{ 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
{ 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
{ 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
{ 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
{ 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
{ 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
{ 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
{ 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
{ 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
{ 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
{ 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
{ 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
{ 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
{ 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
{ 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
{ 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
{ 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
{ 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
};
int gcm_self_test( int verbose )
{
gcm_context ctx;
unsigned char buf[64];
unsigned char tag_buf[16];
int i, j, ret;
cipher_id_t cipher = POLARSSL_CIPHER_ID_AES;
for( j = 0; j < 3; j++ )
{
int key_len = 128 + 64 * j;
for( i = 0; i < MAX_TESTS; i++ )
{
if( verbose != 0 )
polarssl_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "enc" );
gcm_init( &ctx, cipher, key[key_index[i]], key_len );
ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
pt_len[i],
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i],
pt[pt_index[i]], buf, 16, tag_buf );
if( ret != 0 ||
memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
gcm_free( &ctx );
if( verbose != 0 )
polarssl_printf( "passed\n" );
if( verbose != 0 )
polarssl_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "dec" );
gcm_init( &ctx, cipher, key[key_index[i]], key_len );
ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
pt_len[i],
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i],
ct[j * 6 + i], buf, 16, tag_buf );
if( ret != 0 ||
memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
gcm_free( &ctx );
if( verbose != 0 )
polarssl_printf( "passed\n" );
if( verbose != 0 )
polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "enc" );
gcm_init( &ctx, cipher, key[key_index[i]], key_len );
ret = gcm_starts( &ctx, GCM_ENCRYPT,
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] );
if( ret != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
if( pt_len[i] > 32 )
{
size_t rest_len = pt_len[i] - 32;
ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf );
if( ret != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
buf + 32 );
if( ret != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
}
else
{
ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
if( ret != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
}
ret = gcm_finish( &ctx, tag_buf, 16 );
if( ret != 0 ||
memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
gcm_free( &ctx );
if( verbose != 0 )
polarssl_printf( "passed\n" );
if( verbose != 0 )
polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "dec" );
gcm_init( &ctx, cipher, key[key_index[i]], key_len );
ret = gcm_starts( &ctx, GCM_DECRYPT,
iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] );
if( ret != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
if( pt_len[i] > 32 )
{
size_t rest_len = pt_len[i] - 32;
ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf );
if( ret != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
buf + 32 );
if( ret != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
}
else
{
ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
if( ret != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
}
ret = gcm_finish( &ctx, tag_buf, 16 );
if( ret != 0 ||
memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{
if( verbose != 0 )
polarssl_printf( "failed\n" );
return( 1 );
}
gcm_free( &ctx );
if( verbose != 0 )
polarssl_printf( "passed\n" );
}
}
if( verbose != 0 )
polarssl_printf( "\n" );
return( 0 );
}
#endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
#endif /* POLARSSL_GCM_C */