mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * NIST SP800-38D compliant GCM implementation
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22
ansond 0:137634ff4186 23 /*
ansond 0:137634ff4186 24 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
ansond 0:137634ff4186 25 *
ansond 0:137634ff4186 26 * See also:
ansond 0:137634ff4186 27 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
ansond 0:137634ff4186 28 *
ansond 0:137634ff4186 29 * We use the algorithm described as Shoup's method with 4-bit tables in
ansond 0:137634ff4186 30 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
ansond 0:137634ff4186 31 */
ansond 0:137634ff4186 32
ansond 0:137634ff4186 33 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 34 #include "polarssl/config.h"
ansond 0:137634ff4186 35 #else
ansond 0:137634ff4186 36 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 37 #endif
ansond 0:137634ff4186 38
ansond 0:137634ff4186 39 #if defined(POLARSSL_GCM_C)
ansond 0:137634ff4186 40
ansond 0:137634ff4186 41 #include "polarssl/gcm.h"
ansond 0:137634ff4186 42
ansond 0:137634ff4186 43 #include <string.h>
ansond 0:137634ff4186 44
ansond 0:137634ff4186 45 #if defined(POLARSSL_AESNI_C)
ansond 0:137634ff4186 46 #include "polarssl/aesni.h"
ansond 0:137634ff4186 47 #endif
ansond 0:137634ff4186 48
ansond 0:137634ff4186 49 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
ansond 0:137634ff4186 50 #if defined(POLARSSL_PLATFORM_C)
ansond 0:137634ff4186 51 #include "polarssl/platform.h"
ansond 0:137634ff4186 52 #else
ansond 0:137634ff4186 53 #include <stdio.h>
ansond 0:137634ff4186 54 #define polarssl_printf printf
ansond 0:137634ff4186 55 #endif /* POLARSSL_PLATFORM_C */
ansond 0:137634ff4186 56 #endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
ansond 0:137634ff4186 57
ansond 0:137634ff4186 58 /*
ansond 0:137634ff4186 59 * 32-bit integer manipulation macros (big endian)
ansond 0:137634ff4186 60 */
ansond 0:137634ff4186 61 #ifndef GET_UINT32_BE
ansond 0:137634ff4186 62 #define GET_UINT32_BE(n,b,i) \
ansond 0:137634ff4186 63 { \
ansond 0:137634ff4186 64 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
ansond 0:137634ff4186 65 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
ansond 0:137634ff4186 66 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
ansond 0:137634ff4186 67 | ( (uint32_t) (b)[(i) + 3] ); \
ansond 0:137634ff4186 68 }
ansond 0:137634ff4186 69 #endif
ansond 0:137634ff4186 70
ansond 0:137634ff4186 71 #ifndef PUT_UINT32_BE
ansond 0:137634ff4186 72 #define PUT_UINT32_BE(n,b,i) \
ansond 0:137634ff4186 73 { \
ansond 0:137634ff4186 74 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
ansond 0:137634ff4186 75 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
ansond 0:137634ff4186 76 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
ansond 0:137634ff4186 77 (b)[(i) + 3] = (unsigned char) ( (n) ); \
ansond 0:137634ff4186 78 }
ansond 0:137634ff4186 79 #endif
ansond 0:137634ff4186 80
ansond 0:137634ff4186 81 /* Implementation that should never be optimized out by the compiler */
ansond 0:137634ff4186 82 static void polarssl_zeroize( void *v, size_t n ) {
ansond 0:137634ff4186 83 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
ansond 0:137634ff4186 84 }
ansond 0:137634ff4186 85
ansond 0:137634ff4186 86 /*
ansond 0:137634ff4186 87 * Precompute small multiples of H, that is set
ansond 0:137634ff4186 88 * HH[i] || HL[i] = H times i,
ansond 0:137634ff4186 89 * where i is seen as a field element as in [MGV], ie high-order bits
ansond 0:137634ff4186 90 * correspond to low powers of P. The result is stored in the same way, that
ansond 0:137634ff4186 91 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
ansond 0:137634ff4186 92 * corresponds to P^127.
ansond 0:137634ff4186 93 */
ansond 0:137634ff4186 94 static int gcm_gen_table( gcm_context *ctx )
ansond 0:137634ff4186 95 {
ansond 0:137634ff4186 96 int ret, i, j;
ansond 0:137634ff4186 97 uint64_t hi, lo;
ansond 0:137634ff4186 98 uint64_t vl, vh;
ansond 0:137634ff4186 99 unsigned char h[16];
ansond 0:137634ff4186 100 size_t olen = 0;
ansond 0:137634ff4186 101
ansond 0:137634ff4186 102 memset( h, 0, 16 );
ansond 0:137634ff4186 103 if( ( ret = cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
ansond 0:137634ff4186 104 return( ret );
ansond 0:137634ff4186 105
ansond 0:137634ff4186 106 /* pack h as two 64-bits ints, big-endian */
ansond 0:137634ff4186 107 GET_UINT32_BE( hi, h, 0 );
ansond 0:137634ff4186 108 GET_UINT32_BE( lo, h, 4 );
ansond 0:137634ff4186 109 vh = (uint64_t) hi << 32 | lo;
ansond 0:137634ff4186 110
ansond 0:137634ff4186 111 GET_UINT32_BE( hi, h, 8 );
ansond 0:137634ff4186 112 GET_UINT32_BE( lo, h, 12 );
ansond 0:137634ff4186 113 vl = (uint64_t) hi << 32 | lo;
ansond 0:137634ff4186 114
ansond 0:137634ff4186 115 /* 8 = 1000 corresponds to 1 in GF(2^128) */
ansond 0:137634ff4186 116 ctx->HL[8] = vl;
ansond 0:137634ff4186 117 ctx->HH[8] = vh;
ansond 0:137634ff4186 118
ansond 0:137634ff4186 119 #if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
ansond 0:137634ff4186 120 /* With CLMUL support, we need only h, not the rest of the table */
ansond 0:137634ff4186 121 if( aesni_supports( POLARSSL_AESNI_CLMUL ) )
ansond 0:137634ff4186 122 return( 0 );
ansond 0:137634ff4186 123 #endif
ansond 0:137634ff4186 124
ansond 0:137634ff4186 125 /* 0 corresponds to 0 in GF(2^128) */
ansond 0:137634ff4186 126 ctx->HH[0] = 0;
ansond 0:137634ff4186 127 ctx->HL[0] = 0;
ansond 0:137634ff4186 128
ansond 0:137634ff4186 129 for( i = 4; i > 0; i >>= 1 )
ansond 0:137634ff4186 130 {
ansond 0:137634ff4186 131 uint32_t T = ( vl & 1 ) * 0xe1000000U;
ansond 0:137634ff4186 132 vl = ( vh << 63 ) | ( vl >> 1 );
ansond 0:137634ff4186 133 vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
ansond 0:137634ff4186 134
ansond 0:137634ff4186 135 ctx->HL[i] = vl;
ansond 0:137634ff4186 136 ctx->HH[i] = vh;
ansond 0:137634ff4186 137 }
ansond 0:137634ff4186 138
ansond 0:137634ff4186 139 for( i = 2; i <= 8; i *= 2 )
ansond 0:137634ff4186 140 {
ansond 0:137634ff4186 141 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
ansond 0:137634ff4186 142 vh = *HiH;
ansond 0:137634ff4186 143 vl = *HiL;
ansond 0:137634ff4186 144 for( j = 1; j < i; j++ )
ansond 0:137634ff4186 145 {
ansond 0:137634ff4186 146 HiH[j] = vh ^ ctx->HH[j];
ansond 0:137634ff4186 147 HiL[j] = vl ^ ctx->HL[j];
ansond 0:137634ff4186 148 }
ansond 0:137634ff4186 149 }
ansond 0:137634ff4186 150
ansond 0:137634ff4186 151 return( 0 );
ansond 0:137634ff4186 152 }
ansond 0:137634ff4186 153
ansond 0:137634ff4186 154 int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
ansond 0:137634ff4186 155 unsigned int keysize )
ansond 0:137634ff4186 156 {
ansond 0:137634ff4186 157 int ret;
ansond 0:137634ff4186 158 const cipher_info_t *cipher_info;
ansond 0:137634ff4186 159
ansond 0:137634ff4186 160 memset( ctx, 0, sizeof(gcm_context) );
ansond 0:137634ff4186 161
ansond 0:137634ff4186 162 cipher_init( &ctx->cipher_ctx );
ansond 0:137634ff4186 163
ansond 0:137634ff4186 164 cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
ansond 0:137634ff4186 165 if( cipher_info == NULL )
ansond 0:137634ff4186 166 return( POLARSSL_ERR_GCM_BAD_INPUT );
ansond 0:137634ff4186 167
ansond 0:137634ff4186 168 if( cipher_info->block_size != 16 )
ansond 0:137634ff4186 169 return( POLARSSL_ERR_GCM_BAD_INPUT );
ansond 0:137634ff4186 170
ansond 0:137634ff4186 171 cipher_free( &ctx->cipher_ctx );
ansond 0:137634ff4186 172
ansond 0:137634ff4186 173 if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
ansond 0:137634ff4186 174 return( ret );
ansond 0:137634ff4186 175
ansond 0:137634ff4186 176 if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize,
ansond 0:137634ff4186 177 POLARSSL_ENCRYPT ) ) != 0 )
ansond 0:137634ff4186 178 {
ansond 0:137634ff4186 179 return( ret );
ansond 0:137634ff4186 180 }
ansond 0:137634ff4186 181
ansond 0:137634ff4186 182 if( ( ret = gcm_gen_table( ctx ) ) != 0 )
ansond 0:137634ff4186 183 return( ret );
ansond 0:137634ff4186 184
ansond 0:137634ff4186 185 return( 0 );
ansond 0:137634ff4186 186 }
ansond 0:137634ff4186 187
ansond 0:137634ff4186 188 /*
ansond 0:137634ff4186 189 * Shoup's method for multiplication use this table with
ansond 0:137634ff4186 190 * last4[x] = x times P^128
ansond 0:137634ff4186 191 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
ansond 0:137634ff4186 192 */
ansond 0:137634ff4186 193 static const uint64_t last4[16] =
ansond 0:137634ff4186 194 {
ansond 0:137634ff4186 195 0x0000, 0x1c20, 0x3840, 0x2460,
ansond 0:137634ff4186 196 0x7080, 0x6ca0, 0x48c0, 0x54e0,
ansond 0:137634ff4186 197 0xe100, 0xfd20, 0xd940, 0xc560,
ansond 0:137634ff4186 198 0x9180, 0x8da0, 0xa9c0, 0xb5e0
ansond 0:137634ff4186 199 };
ansond 0:137634ff4186 200
ansond 0:137634ff4186 201 /*
ansond 0:137634ff4186 202 * Sets output to x times H using the precomputed tables.
ansond 0:137634ff4186 203 * x and output are seen as elements of GF(2^128) as in [MGV].
ansond 0:137634ff4186 204 */
ansond 0:137634ff4186 205 static void gcm_mult( gcm_context *ctx, const unsigned char x[16],
ansond 0:137634ff4186 206 unsigned char output[16] )
ansond 0:137634ff4186 207 {
ansond 0:137634ff4186 208 int i = 0;
ansond 0:137634ff4186 209 unsigned char lo, hi, rem;
ansond 0:137634ff4186 210 uint64_t zh, zl;
ansond 0:137634ff4186 211
ansond 0:137634ff4186 212 #if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
ansond 0:137634ff4186 213 if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) {
ansond 0:137634ff4186 214 unsigned char h[16];
ansond 0:137634ff4186 215
ansond 0:137634ff4186 216 PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 );
ansond 0:137634ff4186 217 PUT_UINT32_BE( ctx->HH[8], h, 4 );
ansond 0:137634ff4186 218 PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 );
ansond 0:137634ff4186 219 PUT_UINT32_BE( ctx->HL[8], h, 12 );
ansond 0:137634ff4186 220
ansond 0:137634ff4186 221 aesni_gcm_mult( output, x, h );
ansond 0:137634ff4186 222 return;
ansond 0:137634ff4186 223 }
ansond 0:137634ff4186 224 #endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */
ansond 0:137634ff4186 225
ansond 0:137634ff4186 226 lo = x[15] & 0xf;
ansond 0:137634ff4186 227
ansond 0:137634ff4186 228 zh = ctx->HH[lo];
ansond 0:137634ff4186 229 zl = ctx->HL[lo];
ansond 0:137634ff4186 230
ansond 0:137634ff4186 231 for( i = 15; i >= 0; i-- )
ansond 0:137634ff4186 232 {
ansond 0:137634ff4186 233 lo = x[i] & 0xf;
ansond 0:137634ff4186 234 hi = x[i] >> 4;
ansond 0:137634ff4186 235
ansond 0:137634ff4186 236 if( i != 15 )
ansond 0:137634ff4186 237 {
ansond 0:137634ff4186 238 rem = (unsigned char) zl & 0xf;
ansond 0:137634ff4186 239 zl = ( zh << 60 ) | ( zl >> 4 );
ansond 0:137634ff4186 240 zh = ( zh >> 4 );
ansond 0:137634ff4186 241 zh ^= (uint64_t) last4[rem] << 48;
ansond 0:137634ff4186 242 zh ^= ctx->HH[lo];
ansond 0:137634ff4186 243 zl ^= ctx->HL[lo];
ansond 0:137634ff4186 244
ansond 0:137634ff4186 245 }
ansond 0:137634ff4186 246
ansond 0:137634ff4186 247 rem = (unsigned char) zl & 0xf;
ansond 0:137634ff4186 248 zl = ( zh << 60 ) | ( zl >> 4 );
ansond 0:137634ff4186 249 zh = ( zh >> 4 );
ansond 0:137634ff4186 250 zh ^= (uint64_t) last4[rem] << 48;
ansond 0:137634ff4186 251 zh ^= ctx->HH[hi];
ansond 0:137634ff4186 252 zl ^= ctx->HL[hi];
ansond 0:137634ff4186 253 }
ansond 0:137634ff4186 254
ansond 0:137634ff4186 255 PUT_UINT32_BE( zh >> 32, output, 0 );
ansond 0:137634ff4186 256 PUT_UINT32_BE( zh, output, 4 );
ansond 0:137634ff4186 257 PUT_UINT32_BE( zl >> 32, output, 8 );
ansond 0:137634ff4186 258 PUT_UINT32_BE( zl, output, 12 );
ansond 0:137634ff4186 259 }
ansond 0:137634ff4186 260
ansond 0:137634ff4186 261 int gcm_starts( gcm_context *ctx,
ansond 0:137634ff4186 262 int mode,
ansond 0:137634ff4186 263 const unsigned char *iv,
ansond 0:137634ff4186 264 size_t iv_len,
ansond 0:137634ff4186 265 const unsigned char *add,
ansond 0:137634ff4186 266 size_t add_len )
ansond 0:137634ff4186 267 {
ansond 0:137634ff4186 268 int ret;
ansond 0:137634ff4186 269 unsigned char work_buf[16];
ansond 0:137634ff4186 270 size_t i;
ansond 0:137634ff4186 271 const unsigned char *p;
ansond 0:137634ff4186 272 size_t use_len, olen = 0;
ansond 0:137634ff4186 273
ansond 0:137634ff4186 274 /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
ansond 0:137634ff4186 275 if( ( (uint64_t) iv_len ) >> 61 != 0 ||
ansond 0:137634ff4186 276 ( (uint64_t) add_len ) >> 61 != 0 )
ansond 0:137634ff4186 277 {
ansond 0:137634ff4186 278 return( POLARSSL_ERR_GCM_BAD_INPUT );
ansond 0:137634ff4186 279 }
ansond 0:137634ff4186 280
ansond 0:137634ff4186 281 memset( ctx->y, 0x00, sizeof(ctx->y) );
ansond 0:137634ff4186 282 memset( ctx->buf, 0x00, sizeof(ctx->buf) );
ansond 0:137634ff4186 283
ansond 0:137634ff4186 284 ctx->mode = mode;
ansond 0:137634ff4186 285 ctx->len = 0;
ansond 0:137634ff4186 286 ctx->add_len = 0;
ansond 0:137634ff4186 287
ansond 0:137634ff4186 288 if( iv_len == 12 )
ansond 0:137634ff4186 289 {
ansond 0:137634ff4186 290 memcpy( ctx->y, iv, iv_len );
ansond 0:137634ff4186 291 ctx->y[15] = 1;
ansond 0:137634ff4186 292 }
ansond 0:137634ff4186 293 else
ansond 0:137634ff4186 294 {
ansond 0:137634ff4186 295 memset( work_buf, 0x00, 16 );
ansond 0:137634ff4186 296 PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
ansond 0:137634ff4186 297
ansond 0:137634ff4186 298 p = iv;
ansond 0:137634ff4186 299 while( iv_len > 0 )
ansond 0:137634ff4186 300 {
ansond 0:137634ff4186 301 use_len = ( iv_len < 16 ) ? iv_len : 16;
ansond 0:137634ff4186 302
ansond 0:137634ff4186 303 for( i = 0; i < use_len; i++ )
ansond 0:137634ff4186 304 ctx->y[i] ^= p[i];
ansond 0:137634ff4186 305
ansond 0:137634ff4186 306 gcm_mult( ctx, ctx->y, ctx->y );
ansond 0:137634ff4186 307
ansond 0:137634ff4186 308 iv_len -= use_len;
ansond 0:137634ff4186 309 p += use_len;
ansond 0:137634ff4186 310 }
ansond 0:137634ff4186 311
ansond 0:137634ff4186 312 for( i = 0; i < 16; i++ )
ansond 0:137634ff4186 313 ctx->y[i] ^= work_buf[i];
ansond 0:137634ff4186 314
ansond 0:137634ff4186 315 gcm_mult( ctx, ctx->y, ctx->y );
ansond 0:137634ff4186 316 }
ansond 0:137634ff4186 317
ansond 0:137634ff4186 318 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
ansond 0:137634ff4186 319 &olen ) ) != 0 )
ansond 0:137634ff4186 320 {
ansond 0:137634ff4186 321 return( ret );
ansond 0:137634ff4186 322 }
ansond 0:137634ff4186 323
ansond 0:137634ff4186 324 ctx->add_len = add_len;
ansond 0:137634ff4186 325 p = add;
ansond 0:137634ff4186 326 while( add_len > 0 )
ansond 0:137634ff4186 327 {
ansond 0:137634ff4186 328 use_len = ( add_len < 16 ) ? add_len : 16;
ansond 0:137634ff4186 329
ansond 0:137634ff4186 330 for( i = 0; i < use_len; i++ )
ansond 0:137634ff4186 331 ctx->buf[i] ^= p[i];
ansond 0:137634ff4186 332
ansond 0:137634ff4186 333 gcm_mult( ctx, ctx->buf, ctx->buf );
ansond 0:137634ff4186 334
ansond 0:137634ff4186 335 add_len -= use_len;
ansond 0:137634ff4186 336 p += use_len;
ansond 0:137634ff4186 337 }
ansond 0:137634ff4186 338
ansond 0:137634ff4186 339 return( 0 );
ansond 0:137634ff4186 340 }
ansond 0:137634ff4186 341
ansond 0:137634ff4186 342 int gcm_update( gcm_context *ctx,
ansond 0:137634ff4186 343 size_t length,
ansond 0:137634ff4186 344 const unsigned char *input,
ansond 0:137634ff4186 345 unsigned char *output )
ansond 0:137634ff4186 346 {
ansond 0:137634ff4186 347 int ret;
ansond 0:137634ff4186 348 unsigned char ectr[16];
ansond 0:137634ff4186 349 size_t i;
ansond 0:137634ff4186 350 const unsigned char *p;
ansond 0:137634ff4186 351 unsigned char *out_p = output;
ansond 0:137634ff4186 352 size_t use_len, olen = 0;
ansond 0:137634ff4186 353
ansond 0:137634ff4186 354 if( output > input && (size_t) ( output - input ) < length )
ansond 0:137634ff4186 355 return( POLARSSL_ERR_GCM_BAD_INPUT );
ansond 0:137634ff4186 356
ansond 0:137634ff4186 357 /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
ansond 0:137634ff4186 358 * Also check for possible overflow */
ansond 0:137634ff4186 359 if( ctx->len + length < ctx->len ||
ansond 0:137634ff4186 360 (uint64_t) ctx->len + length > 0x03FFFFE0ull )
ansond 0:137634ff4186 361 {
ansond 0:137634ff4186 362 return( POLARSSL_ERR_GCM_BAD_INPUT );
ansond 0:137634ff4186 363 }
ansond 0:137634ff4186 364
ansond 0:137634ff4186 365 ctx->len += length;
ansond 0:137634ff4186 366
ansond 0:137634ff4186 367 p = input;
ansond 0:137634ff4186 368 while( length > 0 )
ansond 0:137634ff4186 369 {
ansond 0:137634ff4186 370 use_len = ( length < 16 ) ? length : 16;
ansond 0:137634ff4186 371
ansond 0:137634ff4186 372 for( i = 16; i > 12; i-- )
ansond 0:137634ff4186 373 if( ++ctx->y[i - 1] != 0 )
ansond 0:137634ff4186 374 break;
ansond 0:137634ff4186 375
ansond 0:137634ff4186 376 if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
ansond 0:137634ff4186 377 &olen ) ) != 0 )
ansond 0:137634ff4186 378 {
ansond 0:137634ff4186 379 return( ret );
ansond 0:137634ff4186 380 }
ansond 0:137634ff4186 381
ansond 0:137634ff4186 382 for( i = 0; i < use_len; i++ )
ansond 0:137634ff4186 383 {
ansond 0:137634ff4186 384 if( ctx->mode == GCM_DECRYPT )
ansond 0:137634ff4186 385 ctx->buf[i] ^= p[i];
ansond 0:137634ff4186 386 out_p[i] = ectr[i] ^ p[i];
ansond 0:137634ff4186 387 if( ctx->mode == GCM_ENCRYPT )
ansond 0:137634ff4186 388 ctx->buf[i] ^= out_p[i];
ansond 0:137634ff4186 389 }
ansond 0:137634ff4186 390
ansond 0:137634ff4186 391 gcm_mult( ctx, ctx->buf, ctx->buf );
ansond 0:137634ff4186 392
ansond 0:137634ff4186 393 length -= use_len;
ansond 0:137634ff4186 394 p += use_len;
ansond 0:137634ff4186 395 out_p += use_len;
ansond 0:137634ff4186 396 }
ansond 0:137634ff4186 397
ansond 0:137634ff4186 398 return( 0 );
ansond 0:137634ff4186 399 }
ansond 0:137634ff4186 400
ansond 0:137634ff4186 401 int gcm_finish( gcm_context *ctx,
ansond 0:137634ff4186 402 unsigned char *tag,
ansond 0:137634ff4186 403 size_t tag_len )
ansond 0:137634ff4186 404 {
ansond 0:137634ff4186 405 unsigned char work_buf[16];
ansond 0:137634ff4186 406 size_t i;
ansond 0:137634ff4186 407 uint64_t orig_len = ctx->len * 8;
ansond 0:137634ff4186 408 uint64_t orig_add_len = ctx->add_len * 8;
ansond 0:137634ff4186 409
ansond 0:137634ff4186 410 if( tag_len > 16 || tag_len < 4 )
ansond 0:137634ff4186 411 return( POLARSSL_ERR_GCM_BAD_INPUT );
ansond 0:137634ff4186 412
ansond 0:137634ff4186 413 if( tag_len != 0 )
ansond 0:137634ff4186 414 memcpy( tag, ctx->base_ectr, tag_len );
ansond 0:137634ff4186 415
ansond 0:137634ff4186 416 if( orig_len || orig_add_len )
ansond 0:137634ff4186 417 {
ansond 0:137634ff4186 418 memset( work_buf, 0x00, 16 );
ansond 0:137634ff4186 419
ansond 0:137634ff4186 420 PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
ansond 0:137634ff4186 421 PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
ansond 0:137634ff4186 422 PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
ansond 0:137634ff4186 423 PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
ansond 0:137634ff4186 424
ansond 0:137634ff4186 425 for( i = 0; i < 16; i++ )
ansond 0:137634ff4186 426 ctx->buf[i] ^= work_buf[i];
ansond 0:137634ff4186 427
ansond 0:137634ff4186 428 gcm_mult( ctx, ctx->buf, ctx->buf );
ansond 0:137634ff4186 429
ansond 0:137634ff4186 430 for( i = 0; i < tag_len; i++ )
ansond 0:137634ff4186 431 tag[i] ^= ctx->buf[i];
ansond 0:137634ff4186 432 }
ansond 0:137634ff4186 433
ansond 0:137634ff4186 434 return( 0 );
ansond 0:137634ff4186 435 }
ansond 0:137634ff4186 436
ansond 0:137634ff4186 437 int gcm_crypt_and_tag( gcm_context *ctx,
ansond 0:137634ff4186 438 int mode,
ansond 0:137634ff4186 439 size_t length,
ansond 0:137634ff4186 440 const unsigned char *iv,
ansond 0:137634ff4186 441 size_t iv_len,
ansond 0:137634ff4186 442 const unsigned char *add,
ansond 0:137634ff4186 443 size_t add_len,
ansond 0:137634ff4186 444 const unsigned char *input,
ansond 0:137634ff4186 445 unsigned char *output,
ansond 0:137634ff4186 446 size_t tag_len,
ansond 0:137634ff4186 447 unsigned char *tag )
ansond 0:137634ff4186 448 {
ansond 0:137634ff4186 449 int ret;
ansond 0:137634ff4186 450
ansond 0:137634ff4186 451 if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
ansond 0:137634ff4186 452 return( ret );
ansond 0:137634ff4186 453
ansond 0:137634ff4186 454 if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 )
ansond 0:137634ff4186 455 return( ret );
ansond 0:137634ff4186 456
ansond 0:137634ff4186 457 if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 )
ansond 0:137634ff4186 458 return( ret );
ansond 0:137634ff4186 459
ansond 0:137634ff4186 460 return( 0 );
ansond 0:137634ff4186 461 }
ansond 0:137634ff4186 462
ansond 0:137634ff4186 463 int gcm_auth_decrypt( gcm_context *ctx,
ansond 0:137634ff4186 464 size_t length,
ansond 0:137634ff4186 465 const unsigned char *iv,
ansond 0:137634ff4186 466 size_t iv_len,
ansond 0:137634ff4186 467 const unsigned char *add,
ansond 0:137634ff4186 468 size_t add_len,
ansond 0:137634ff4186 469 const unsigned char *tag,
ansond 0:137634ff4186 470 size_t tag_len,
ansond 0:137634ff4186 471 const unsigned char *input,
ansond 0:137634ff4186 472 unsigned char *output )
ansond 0:137634ff4186 473 {
ansond 0:137634ff4186 474 int ret;
ansond 0:137634ff4186 475 unsigned char check_tag[16];
ansond 0:137634ff4186 476 size_t i;
ansond 0:137634ff4186 477 int diff;
ansond 0:137634ff4186 478
ansond 0:137634ff4186 479 if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length,
ansond 0:137634ff4186 480 iv, iv_len, add, add_len,
ansond 0:137634ff4186 481 input, output, tag_len, check_tag ) ) != 0 )
ansond 0:137634ff4186 482 {
ansond 0:137634ff4186 483 return( ret );
ansond 0:137634ff4186 484 }
ansond 0:137634ff4186 485
ansond 0:137634ff4186 486 /* Check tag in "constant-time" */
ansond 0:137634ff4186 487 for( diff = 0, i = 0; i < tag_len; i++ )
ansond 0:137634ff4186 488 diff |= tag[i] ^ check_tag[i];
ansond 0:137634ff4186 489
ansond 0:137634ff4186 490 if( diff != 0 )
ansond 0:137634ff4186 491 {
ansond 0:137634ff4186 492 polarssl_zeroize( output, length );
ansond 0:137634ff4186 493 return( POLARSSL_ERR_GCM_AUTH_FAILED );
ansond 0:137634ff4186 494 }
ansond 0:137634ff4186 495
ansond 0:137634ff4186 496 return( 0 );
ansond 0:137634ff4186 497 }
ansond 0:137634ff4186 498
ansond 0:137634ff4186 499 void gcm_free( gcm_context *ctx )
ansond 0:137634ff4186 500 {
ansond 0:137634ff4186 501 cipher_free( &ctx->cipher_ctx );
ansond 0:137634ff4186 502 polarssl_zeroize( ctx, sizeof( gcm_context ) );
ansond 0:137634ff4186 503 }
ansond 0:137634ff4186 504
ansond 0:137634ff4186 505 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
ansond 0:137634ff4186 506 /*
ansond 0:137634ff4186 507 * AES-GCM test vectors from:
ansond 0:137634ff4186 508 *
ansond 0:137634ff4186 509 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
ansond 0:137634ff4186 510 */
ansond 0:137634ff4186 511 #define MAX_TESTS 6
ansond 0:137634ff4186 512
ansond 0:137634ff4186 513 static const int key_index[MAX_TESTS] =
ansond 0:137634ff4186 514 { 0, 0, 1, 1, 1, 1 };
ansond 0:137634ff4186 515
ansond 0:137634ff4186 516 static const unsigned char key[MAX_TESTS][32] =
ansond 0:137634ff4186 517 {
ansond 0:137634ff4186 518 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
ansond 0:137634ff4186 519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
ansond 0:137634ff4186 520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
ansond 0:137634ff4186 521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
ansond 0:137634ff4186 522 { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
ansond 0:137634ff4186 523 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
ansond 0:137634ff4186 524 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
ansond 0:137634ff4186 525 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
ansond 0:137634ff4186 526 };
ansond 0:137634ff4186 527
ansond 0:137634ff4186 528 static const size_t iv_len[MAX_TESTS] =
ansond 0:137634ff4186 529 { 12, 12, 12, 12, 8, 60 };
ansond 0:137634ff4186 530
ansond 0:137634ff4186 531 static const int iv_index[MAX_TESTS] =
ansond 0:137634ff4186 532 { 0, 0, 1, 1, 1, 2 };
ansond 0:137634ff4186 533
ansond 0:137634ff4186 534 static const unsigned char iv[MAX_TESTS][64] =
ansond 0:137634ff4186 535 {
ansond 0:137634ff4186 536 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
ansond 0:137634ff4186 537 0x00, 0x00, 0x00, 0x00 },
ansond 0:137634ff4186 538 { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
ansond 0:137634ff4186 539 0xde, 0xca, 0xf8, 0x88 },
ansond 0:137634ff4186 540 { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
ansond 0:137634ff4186 541 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
ansond 0:137634ff4186 542 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
ansond 0:137634ff4186 543 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
ansond 0:137634ff4186 544 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
ansond 0:137634ff4186 545 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
ansond 0:137634ff4186 546 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
ansond 0:137634ff4186 547 0xa6, 0x37, 0xb3, 0x9b },
ansond 0:137634ff4186 548 };
ansond 0:137634ff4186 549
ansond 0:137634ff4186 550 static const size_t add_len[MAX_TESTS] =
ansond 0:137634ff4186 551 { 0, 0, 0, 20, 20, 20 };
ansond 0:137634ff4186 552
ansond 0:137634ff4186 553 static const int add_index[MAX_TESTS] =
ansond 0:137634ff4186 554 { 0, 0, 0, 1, 1, 1 };
ansond 0:137634ff4186 555
ansond 0:137634ff4186 556 static const unsigned char additional[MAX_TESTS][64] =
ansond 0:137634ff4186 557 {
ansond 0:137634ff4186 558 { 0x00 },
ansond 0:137634ff4186 559 { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
ansond 0:137634ff4186 560 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
ansond 0:137634ff4186 561 0xab, 0xad, 0xda, 0xd2 },
ansond 0:137634ff4186 562 };
ansond 0:137634ff4186 563
ansond 0:137634ff4186 564 static const size_t pt_len[MAX_TESTS] =
ansond 0:137634ff4186 565 { 0, 16, 64, 60, 60, 60 };
ansond 0:137634ff4186 566
ansond 0:137634ff4186 567 static const int pt_index[MAX_TESTS] =
ansond 0:137634ff4186 568 { 0, 0, 1, 1, 1, 1 };
ansond 0:137634ff4186 569
ansond 0:137634ff4186 570 static const unsigned char pt[MAX_TESTS][64] =
ansond 0:137634ff4186 571 {
ansond 0:137634ff4186 572 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
ansond 0:137634ff4186 573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
ansond 0:137634ff4186 574 { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
ansond 0:137634ff4186 575 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
ansond 0:137634ff4186 576 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
ansond 0:137634ff4186 577 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
ansond 0:137634ff4186 578 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
ansond 0:137634ff4186 579 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
ansond 0:137634ff4186 580 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
ansond 0:137634ff4186 581 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
ansond 0:137634ff4186 582 };
ansond 0:137634ff4186 583
ansond 0:137634ff4186 584 static const unsigned char ct[MAX_TESTS * 3][64] =
ansond 0:137634ff4186 585 {
ansond 0:137634ff4186 586 { 0x00 },
ansond 0:137634ff4186 587 { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
ansond 0:137634ff4186 588 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
ansond 0:137634ff4186 589 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
ansond 0:137634ff4186 590 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
ansond 0:137634ff4186 591 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
ansond 0:137634ff4186 592 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
ansond 0:137634ff4186 593 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
ansond 0:137634ff4186 594 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
ansond 0:137634ff4186 595 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
ansond 0:137634ff4186 596 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
ansond 0:137634ff4186 597 { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
ansond 0:137634ff4186 598 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
ansond 0:137634ff4186 599 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
ansond 0:137634ff4186 600 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
ansond 0:137634ff4186 601 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
ansond 0:137634ff4186 602 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
ansond 0:137634ff4186 603 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
ansond 0:137634ff4186 604 0x3d, 0x58, 0xe0, 0x91 },
ansond 0:137634ff4186 605 { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
ansond 0:137634ff4186 606 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
ansond 0:137634ff4186 607 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
ansond 0:137634ff4186 608 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
ansond 0:137634ff4186 609 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
ansond 0:137634ff4186 610 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
ansond 0:137634ff4186 611 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
ansond 0:137634ff4186 612 0xc2, 0x3f, 0x45, 0x98 },
ansond 0:137634ff4186 613 { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
ansond 0:137634ff4186 614 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
ansond 0:137634ff4186 615 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
ansond 0:137634ff4186 616 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
ansond 0:137634ff4186 617 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
ansond 0:137634ff4186 618 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
ansond 0:137634ff4186 619 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
ansond 0:137634ff4186 620 0x4c, 0x34, 0xae, 0xe5 },
ansond 0:137634ff4186 621 { 0x00 },
ansond 0:137634ff4186 622 { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
ansond 0:137634ff4186 623 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
ansond 0:137634ff4186 624 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
ansond 0:137634ff4186 625 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
ansond 0:137634ff4186 626 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
ansond 0:137634ff4186 627 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
ansond 0:137634ff4186 628 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
ansond 0:137634ff4186 629 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
ansond 0:137634ff4186 630 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
ansond 0:137634ff4186 631 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
ansond 0:137634ff4186 632 { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
ansond 0:137634ff4186 633 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
ansond 0:137634ff4186 634 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
ansond 0:137634ff4186 635 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
ansond 0:137634ff4186 636 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
ansond 0:137634ff4186 637 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
ansond 0:137634ff4186 638 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
ansond 0:137634ff4186 639 0xcc, 0xda, 0x27, 0x10 },
ansond 0:137634ff4186 640 { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
ansond 0:137634ff4186 641 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
ansond 0:137634ff4186 642 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
ansond 0:137634ff4186 643 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
ansond 0:137634ff4186 644 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
ansond 0:137634ff4186 645 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
ansond 0:137634ff4186 646 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
ansond 0:137634ff4186 647 0xa0, 0xf0, 0x62, 0xf7 },
ansond 0:137634ff4186 648 { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
ansond 0:137634ff4186 649 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
ansond 0:137634ff4186 650 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
ansond 0:137634ff4186 651 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
ansond 0:137634ff4186 652 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
ansond 0:137634ff4186 653 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
ansond 0:137634ff4186 654 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
ansond 0:137634ff4186 655 0xe9, 0xb7, 0x37, 0x3b },
ansond 0:137634ff4186 656 { 0x00 },
ansond 0:137634ff4186 657 { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
ansond 0:137634ff4186 658 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
ansond 0:137634ff4186 659 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
ansond 0:137634ff4186 660 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
ansond 0:137634ff4186 661 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
ansond 0:137634ff4186 662 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
ansond 0:137634ff4186 663 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
ansond 0:137634ff4186 664 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
ansond 0:137634ff4186 665 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
ansond 0:137634ff4186 666 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
ansond 0:137634ff4186 667 { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
ansond 0:137634ff4186 668 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
ansond 0:137634ff4186 669 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
ansond 0:137634ff4186 670 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
ansond 0:137634ff4186 671 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
ansond 0:137634ff4186 672 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
ansond 0:137634ff4186 673 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
ansond 0:137634ff4186 674 0xbc, 0xc9, 0xf6, 0x62 },
ansond 0:137634ff4186 675 { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
ansond 0:137634ff4186 676 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
ansond 0:137634ff4186 677 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
ansond 0:137634ff4186 678 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
ansond 0:137634ff4186 679 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
ansond 0:137634ff4186 680 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
ansond 0:137634ff4186 681 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
ansond 0:137634ff4186 682 0xf4, 0x7c, 0x9b, 0x1f },
ansond 0:137634ff4186 683 { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
ansond 0:137634ff4186 684 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
ansond 0:137634ff4186 685 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
ansond 0:137634ff4186 686 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
ansond 0:137634ff4186 687 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
ansond 0:137634ff4186 688 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
ansond 0:137634ff4186 689 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
ansond 0:137634ff4186 690 0x44, 0xae, 0x7e, 0x3f },
ansond 0:137634ff4186 691 };
ansond 0:137634ff4186 692
ansond 0:137634ff4186 693 static const unsigned char tag[MAX_TESTS * 3][16] =
ansond 0:137634ff4186 694 {
ansond 0:137634ff4186 695 { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
ansond 0:137634ff4186 696 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
ansond 0:137634ff4186 697 { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
ansond 0:137634ff4186 698 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
ansond 0:137634ff4186 699 { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
ansond 0:137634ff4186 700 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
ansond 0:137634ff4186 701 { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
ansond 0:137634ff4186 702 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
ansond 0:137634ff4186 703 { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
ansond 0:137634ff4186 704 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
ansond 0:137634ff4186 705 { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
ansond 0:137634ff4186 706 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
ansond 0:137634ff4186 707 { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
ansond 0:137634ff4186 708 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
ansond 0:137634ff4186 709 { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
ansond 0:137634ff4186 710 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
ansond 0:137634ff4186 711 { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
ansond 0:137634ff4186 712 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
ansond 0:137634ff4186 713 { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
ansond 0:137634ff4186 714 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
ansond 0:137634ff4186 715 { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
ansond 0:137634ff4186 716 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
ansond 0:137634ff4186 717 { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
ansond 0:137634ff4186 718 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
ansond 0:137634ff4186 719 { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
ansond 0:137634ff4186 720 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
ansond 0:137634ff4186 721 { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
ansond 0:137634ff4186 722 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
ansond 0:137634ff4186 723 { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
ansond 0:137634ff4186 724 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
ansond 0:137634ff4186 725 { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
ansond 0:137634ff4186 726 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
ansond 0:137634ff4186 727 { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
ansond 0:137634ff4186 728 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
ansond 0:137634ff4186 729 { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
ansond 0:137634ff4186 730 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
ansond 0:137634ff4186 731 };
ansond 0:137634ff4186 732
ansond 0:137634ff4186 733 int gcm_self_test( int verbose )
ansond 0:137634ff4186 734 {
ansond 0:137634ff4186 735 gcm_context ctx;
ansond 0:137634ff4186 736 unsigned char buf[64];
ansond 0:137634ff4186 737 unsigned char tag_buf[16];
ansond 0:137634ff4186 738 int i, j, ret;
ansond 0:137634ff4186 739 cipher_id_t cipher = POLARSSL_CIPHER_ID_AES;
ansond 0:137634ff4186 740
ansond 0:137634ff4186 741 for( j = 0; j < 3; j++ )
ansond 0:137634ff4186 742 {
ansond 0:137634ff4186 743 int key_len = 128 + 64 * j;
ansond 0:137634ff4186 744
ansond 0:137634ff4186 745 for( i = 0; i < MAX_TESTS; i++ )
ansond 0:137634ff4186 746 {
ansond 0:137634ff4186 747 if( verbose != 0 )
ansond 0:137634ff4186 748 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
ansond 0:137634ff4186 749 key_len, i, "enc" );
ansond 0:137634ff4186 750
ansond 0:137634ff4186 751 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
ansond 0:137634ff4186 752
ansond 0:137634ff4186 753 ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
ansond 0:137634ff4186 754 pt_len[i],
ansond 0:137634ff4186 755 iv[iv_index[i]], iv_len[i],
ansond 0:137634ff4186 756 additional[add_index[i]], add_len[i],
ansond 0:137634ff4186 757 pt[pt_index[i]], buf, 16, tag_buf );
ansond 0:137634ff4186 758
ansond 0:137634ff4186 759 if( ret != 0 ||
ansond 0:137634ff4186 760 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
ansond 0:137634ff4186 761 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
ansond 0:137634ff4186 762 {
ansond 0:137634ff4186 763 if( verbose != 0 )
ansond 0:137634ff4186 764 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 765
ansond 0:137634ff4186 766 return( 1 );
ansond 0:137634ff4186 767 }
ansond 0:137634ff4186 768
ansond 0:137634ff4186 769 gcm_free( &ctx );
ansond 0:137634ff4186 770
ansond 0:137634ff4186 771 if( verbose != 0 )
ansond 0:137634ff4186 772 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 773
ansond 0:137634ff4186 774 if( verbose != 0 )
ansond 0:137634ff4186 775 polarssl_printf( " AES-GCM-%3d #%d (%s): ",
ansond 0:137634ff4186 776 key_len, i, "dec" );
ansond 0:137634ff4186 777
ansond 0:137634ff4186 778 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
ansond 0:137634ff4186 779
ansond 0:137634ff4186 780 ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
ansond 0:137634ff4186 781 pt_len[i],
ansond 0:137634ff4186 782 iv[iv_index[i]], iv_len[i],
ansond 0:137634ff4186 783 additional[add_index[i]], add_len[i],
ansond 0:137634ff4186 784 ct[j * 6 + i], buf, 16, tag_buf );
ansond 0:137634ff4186 785
ansond 0:137634ff4186 786 if( ret != 0 ||
ansond 0:137634ff4186 787 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
ansond 0:137634ff4186 788 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
ansond 0:137634ff4186 789 {
ansond 0:137634ff4186 790 if( verbose != 0 )
ansond 0:137634ff4186 791 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 792
ansond 0:137634ff4186 793 return( 1 );
ansond 0:137634ff4186 794 }
ansond 0:137634ff4186 795
ansond 0:137634ff4186 796 gcm_free( &ctx );
ansond 0:137634ff4186 797
ansond 0:137634ff4186 798 if( verbose != 0 )
ansond 0:137634ff4186 799 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 800
ansond 0:137634ff4186 801 if( verbose != 0 )
ansond 0:137634ff4186 802 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
ansond 0:137634ff4186 803 key_len, i, "enc" );
ansond 0:137634ff4186 804
ansond 0:137634ff4186 805 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
ansond 0:137634ff4186 806
ansond 0:137634ff4186 807 ret = gcm_starts( &ctx, GCM_ENCRYPT,
ansond 0:137634ff4186 808 iv[iv_index[i]], iv_len[i],
ansond 0:137634ff4186 809 additional[add_index[i]], add_len[i] );
ansond 0:137634ff4186 810 if( ret != 0 )
ansond 0:137634ff4186 811 {
ansond 0:137634ff4186 812 if( verbose != 0 )
ansond 0:137634ff4186 813 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 814
ansond 0:137634ff4186 815 return( 1 );
ansond 0:137634ff4186 816 }
ansond 0:137634ff4186 817
ansond 0:137634ff4186 818 if( pt_len[i] > 32 )
ansond 0:137634ff4186 819 {
ansond 0:137634ff4186 820 size_t rest_len = pt_len[i] - 32;
ansond 0:137634ff4186 821 ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf );
ansond 0:137634ff4186 822 if( ret != 0 )
ansond 0:137634ff4186 823 {
ansond 0:137634ff4186 824 if( verbose != 0 )
ansond 0:137634ff4186 825 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 826
ansond 0:137634ff4186 827 return( 1 );
ansond 0:137634ff4186 828 }
ansond 0:137634ff4186 829
ansond 0:137634ff4186 830 ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
ansond 0:137634ff4186 831 buf + 32 );
ansond 0:137634ff4186 832 if( ret != 0 )
ansond 0:137634ff4186 833 {
ansond 0:137634ff4186 834 if( verbose != 0 )
ansond 0:137634ff4186 835 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 836
ansond 0:137634ff4186 837 return( 1 );
ansond 0:137634ff4186 838 }
ansond 0:137634ff4186 839 }
ansond 0:137634ff4186 840 else
ansond 0:137634ff4186 841 {
ansond 0:137634ff4186 842 ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
ansond 0:137634ff4186 843 if( ret != 0 )
ansond 0:137634ff4186 844 {
ansond 0:137634ff4186 845 if( verbose != 0 )
ansond 0:137634ff4186 846 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 847
ansond 0:137634ff4186 848 return( 1 );
ansond 0:137634ff4186 849 }
ansond 0:137634ff4186 850 }
ansond 0:137634ff4186 851
ansond 0:137634ff4186 852 ret = gcm_finish( &ctx, tag_buf, 16 );
ansond 0:137634ff4186 853 if( ret != 0 ||
ansond 0:137634ff4186 854 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
ansond 0:137634ff4186 855 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
ansond 0:137634ff4186 856 {
ansond 0:137634ff4186 857 if( verbose != 0 )
ansond 0:137634ff4186 858 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 859
ansond 0:137634ff4186 860 return( 1 );
ansond 0:137634ff4186 861 }
ansond 0:137634ff4186 862
ansond 0:137634ff4186 863 gcm_free( &ctx );
ansond 0:137634ff4186 864
ansond 0:137634ff4186 865 if( verbose != 0 )
ansond 0:137634ff4186 866 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 867
ansond 0:137634ff4186 868 if( verbose != 0 )
ansond 0:137634ff4186 869 polarssl_printf( " AES-GCM-%3d #%d split (%s): ",
ansond 0:137634ff4186 870 key_len, i, "dec" );
ansond 0:137634ff4186 871
ansond 0:137634ff4186 872 gcm_init( &ctx, cipher, key[key_index[i]], key_len );
ansond 0:137634ff4186 873
ansond 0:137634ff4186 874 ret = gcm_starts( &ctx, GCM_DECRYPT,
ansond 0:137634ff4186 875 iv[iv_index[i]], iv_len[i],
ansond 0:137634ff4186 876 additional[add_index[i]], add_len[i] );
ansond 0:137634ff4186 877 if( ret != 0 )
ansond 0:137634ff4186 878 {
ansond 0:137634ff4186 879 if( verbose != 0 )
ansond 0:137634ff4186 880 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 881
ansond 0:137634ff4186 882 return( 1 );
ansond 0:137634ff4186 883 }
ansond 0:137634ff4186 884
ansond 0:137634ff4186 885 if( pt_len[i] > 32 )
ansond 0:137634ff4186 886 {
ansond 0:137634ff4186 887 size_t rest_len = pt_len[i] - 32;
ansond 0:137634ff4186 888 ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf );
ansond 0:137634ff4186 889 if( ret != 0 )
ansond 0:137634ff4186 890 {
ansond 0:137634ff4186 891 if( verbose != 0 )
ansond 0:137634ff4186 892 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 893
ansond 0:137634ff4186 894 return( 1 );
ansond 0:137634ff4186 895 }
ansond 0:137634ff4186 896
ansond 0:137634ff4186 897 ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
ansond 0:137634ff4186 898 buf + 32 );
ansond 0:137634ff4186 899 if( ret != 0 )
ansond 0:137634ff4186 900 {
ansond 0:137634ff4186 901 if( verbose != 0 )
ansond 0:137634ff4186 902 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 903
ansond 0:137634ff4186 904 return( 1 );
ansond 0:137634ff4186 905 }
ansond 0:137634ff4186 906 }
ansond 0:137634ff4186 907 else
ansond 0:137634ff4186 908 {
ansond 0:137634ff4186 909 ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
ansond 0:137634ff4186 910 if( ret != 0 )
ansond 0:137634ff4186 911 {
ansond 0:137634ff4186 912 if( verbose != 0 )
ansond 0:137634ff4186 913 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 914
ansond 0:137634ff4186 915 return( 1 );
ansond 0:137634ff4186 916 }
ansond 0:137634ff4186 917 }
ansond 0:137634ff4186 918
ansond 0:137634ff4186 919 ret = gcm_finish( &ctx, tag_buf, 16 );
ansond 0:137634ff4186 920 if( ret != 0 ||
ansond 0:137634ff4186 921 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
ansond 0:137634ff4186 922 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
ansond 0:137634ff4186 923 {
ansond 0:137634ff4186 924 if( verbose != 0 )
ansond 0:137634ff4186 925 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 926
ansond 0:137634ff4186 927 return( 1 );
ansond 0:137634ff4186 928 }
ansond 0:137634ff4186 929
ansond 0:137634ff4186 930 gcm_free( &ctx );
ansond 0:137634ff4186 931
ansond 0:137634ff4186 932 if( verbose != 0 )
ansond 0:137634ff4186 933 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 934
ansond 0:137634ff4186 935 }
ansond 0:137634ff4186 936 }
ansond 0:137634ff4186 937
ansond 0:137634ff4186 938 if( verbose != 0 )
ansond 0:137634ff4186 939 polarssl_printf( "\n" );
ansond 0:137634ff4186 940
ansond 0:137634ff4186 941 return( 0 );
ansond 0:137634ff4186 942 }
ansond 0:137634ff4186 943
ansond 0:137634ff4186 944 #endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
ansond 0:137634ff4186 945
ansond 0:137634ff4186 946 #endif /* POLARSSL_GCM_C */
ansond 0:137634ff4186 947