Example program to test AES-GCM functionality. Used for a workshop

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gcm.c Source File

gcm.c

00001 /*
00002  *  NIST SP800-38D compliant GCM implementation
00003  *
00004  *  Copyright (C) 2006-2014, Brainspark B.V.
00005  *
00006  *  This file is part of PolarSSL (http://www.polarssl.org)
00007  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
00008  *
00009  *  All rights reserved.
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License along
00022  *  with this program; if not, write to the Free Software Foundation, Inc.,
00023  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00024  */
00025 
00026 /*
00027  * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
00028  *
00029  * See also:
00030  * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
00031  *
00032  * We use the algorithm described as Shoup's method with 4-bit tables in
00033  * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
00034  */
00035 
00036 #if !defined(POLARSSL_CONFIG_FILE)
00037 #include "polarssl/config.h"
00038 #else
00039 #include POLARSSL_CONFIG_FILE
00040 #endif
00041 
00042 #if defined(POLARSSL_GCM_C)
00043 
00044 #include "polarssl/gcm.h"
00045 
00046 #if defined(POLARSSL_AESNI_C)
00047 #include "polarssl/aesni.h"
00048 #endif
00049 
00050 #if defined(POLARSSL_PLATFORM_C)
00051 #include "polarssl/platform.h"
00052 #else
00053 #define polarssl_printf printf
00054 #endif
00055 
00056 /*
00057  * 32-bit integer manipulation macros (big endian)
00058  */
00059 #ifndef GET_UINT32_BE
00060 #define GET_UINT32_BE(n,b,i)                            \
00061 {                                                       \
00062     (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
00063         | ( (uint32_t) (b)[(i) + 1] << 16 )             \
00064         | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
00065         | ( (uint32_t) (b)[(i) + 3]       );            \
00066 }
00067 #endif
00068 
00069 #ifndef PUT_UINT32_BE
00070 #define PUT_UINT32_BE(n,b,i)                            \
00071 {                                                       \
00072     (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
00073     (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
00074     (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
00075     (b)[(i) + 3] = (unsigned char) ( (n)       );       \
00076 }
00077 #endif
00078 
00079 /*
00080  * Precompute small multiples of H, that is set
00081  *      HH[i] || HL[i] = H times i,
00082  * where i is seen as a field element as in [MGV], ie high-order bits
00083  * correspond to low powers of P. The result is stored in the same way, that
00084  * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
00085  * corresponds to P^127.
00086  */
00087 static int gcm_gen_table( gcm_context *ctx )
00088 {
00089     int ret, i, j;
00090     uint64_t hi, lo;
00091     uint64_t vl, vh;
00092     unsigned char h[16];
00093     size_t olen = 0;
00094 
00095     memset( h, 0, 16 );
00096     if( ( ret = cipher_update( &ctx->cipher_ctx , h, 16, h, &olen ) ) != 0 )
00097         return( ret );
00098 
00099     /* pack h as two 64-bits ints, big-endian */
00100     GET_UINT32_BE( hi, h,  0  );
00101     GET_UINT32_BE( lo, h,  4  );
00102     vh = (uint64_t) hi << 32 | lo;
00103 
00104     GET_UINT32_BE( hi, h,  8  );
00105     GET_UINT32_BE( lo, h,  12 );
00106     vl = (uint64_t) hi << 32 | lo;
00107 
00108     /* 8 = 1000 corresponds to 1 in GF(2^128) */
00109     ctx->HL [8] = vl;
00110     ctx->HH [8] = vh;
00111 
00112 #if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
00113     /* With CLMUL support, we need only h, not the rest of the table */
00114     if( aesni_supports( POLARSSL_AESNI_CLMUL ) )
00115         return( 0 );
00116 #endif
00117 
00118     /* 0 corresponds to 0 in GF(2^128) */
00119     ctx->HH [0] = 0;
00120     ctx->HL [0] = 0;
00121 
00122     for( i = 4; i > 0; i >>= 1 )
00123     {
00124         uint32_t T = ( vl & 1 ) * 0xe1000000U;
00125         vl  = ( vh << 63 ) | ( vl >> 1 );
00126         vh  = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
00127 
00128         ctx->HL [i] = vl;
00129         ctx->HH [i] = vh;
00130     }
00131 
00132     for (i = 2; i < 16; i <<= 1 )
00133     {
00134         uint64_t *HiL = ctx->HL  + i, *HiH = ctx->HH  + i;
00135         vh = *HiH;
00136         vl = *HiL;
00137         for( j = 1; j < i; j++ )
00138         {
00139             HiH[j] = vh ^ ctx->HH [j];
00140             HiL[j] = vl ^ ctx->HL [j];
00141         }
00142     }
00143 
00144     return( 0 );
00145 }
00146 
00147 int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
00148               unsigned int keysize )
00149 {
00150     int ret;
00151     const cipher_info_t *cipher_info;
00152 
00153     memset( ctx, 0, sizeof(gcm_context) );
00154 
00155     cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
00156     if( cipher_info == NULL )
00157         return( POLARSSL_ERR_GCM_BAD_INPUT );
00158 
00159     if( cipher_info->block_size != 16 )
00160         return( POLARSSL_ERR_GCM_BAD_INPUT );
00161 
00162     if( ( ret = cipher_init_ctx( &ctx->cipher_ctx , cipher_info ) ) != 0 )
00163         return( ret );
00164 
00165     if( ( ret = cipher_setkey( &ctx->cipher_ctx , key, keysize,
00166                                POLARSSL_ENCRYPT ) ) != 0 )
00167     {
00168         return( ret );
00169     }
00170 
00171     if( ( ret = gcm_gen_table( ctx ) ) != 0 )
00172         return( ret );
00173 
00174     return( 0 );
00175 }
00176 
00177 /*
00178  * Shoup's method for multiplication use this table with
00179  *      last4[x] = x times P^128
00180  * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
00181  */
00182 static const uint64_t last4[16] =
00183 {
00184     0x0000, 0x1c20, 0x3840, 0x2460,
00185     0x7080, 0x6ca0, 0x48c0, 0x54e0,
00186     0xe100, 0xfd20, 0xd940, 0xc560,
00187     0x9180, 0x8da0, 0xa9c0, 0xb5e0
00188 };
00189 
00190 /*
00191  * Sets output to x times H using the precomputed tables.
00192  * x and output are seen as elements of GF(2^128) as in [MGV].
00193  */
00194 static void gcm_mult( gcm_context *ctx, const unsigned char x[16],
00195                       unsigned char output[16] )
00196 {
00197     int i = 0;
00198     unsigned char z[16];
00199     unsigned char lo, hi, rem;
00200     uint64_t zh, zl;
00201 
00202 #if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64)
00203     if( aesni_supports( POLARSSL_AESNI_CLMUL ) ) {
00204         unsigned char h[16];
00205 
00206         PUT_UINT32_BE( ctx->HH [8] >> 32, h,  0 );
00207         PUT_UINT32_BE( ctx->HH [8],       h,  4 );
00208         PUT_UINT32_BE( ctx->HL [8] >> 32, h,  8 );
00209         PUT_UINT32_BE( ctx->HL [8],       h, 12 );
00210 
00211         aesni_gcm_mult( output, x, h );
00212         return;
00213     }
00214 #endif /* POLARSSL_AESNI_C && POLARSSL_HAVE_X86_64 */
00215 
00216     memset( z, 0x00, 16 );
00217 
00218     lo = x[15] & 0xf;
00219     hi = x[15] >> 4;
00220 
00221     zh = ctx->HH [lo];
00222     zl = ctx->HL [lo];
00223 
00224     for( i = 15; i >= 0; i-- )
00225     {
00226         lo = x[i] & 0xf;
00227         hi = x[i] >> 4;
00228 
00229         if( i != 15 )
00230         {
00231             rem = (unsigned char) zl & 0xf;
00232             zl = ( zh << 60 ) | ( zl >> 4 );
00233             zh = ( zh >> 4 );
00234             zh ^= (uint64_t) last4[rem] << 48;
00235             zh ^= ctx->HH [lo];
00236             zl ^= ctx->HL [lo];
00237 
00238         }
00239 
00240         rem = (unsigned char) zl & 0xf;
00241         zl = ( zh << 60 ) | ( zl >> 4 );
00242         zh = ( zh >> 4 );
00243         zh ^= (uint64_t) last4[rem] << 48;
00244         zh ^= ctx->HH [hi];
00245         zl ^= ctx->HL [hi];
00246     }
00247 
00248     PUT_UINT32_BE( zh >> 32, output, 0 );
00249     PUT_UINT32_BE( zh, output, 4 );
00250     PUT_UINT32_BE( zl >> 32, output, 8 );
00251     PUT_UINT32_BE( zl, output, 12 );
00252 }
00253 
00254 int gcm_starts( gcm_context *ctx,
00255                 int mode,
00256                 const unsigned char *iv,
00257                 size_t iv_len,
00258                 const unsigned char *add,
00259                 size_t add_len )
00260 {
00261     int ret;
00262     unsigned char work_buf[16];
00263     size_t i;
00264     const unsigned char *p;
00265     size_t use_len, olen = 0;
00266 
00267     memset( ctx->y , 0x00, sizeof(ctx->y ) );
00268     memset( ctx->buf , 0x00, sizeof(ctx->buf ) );
00269 
00270     ctx->mode  = mode;
00271     ctx->len  = 0;
00272     ctx->add_len  = 0;
00273 
00274     if( iv_len == 12 )
00275     {
00276         memcpy( ctx->y , iv, iv_len );
00277         ctx->y [15] = 1;
00278     }
00279     else
00280     {
00281         memset( work_buf, 0x00, 16 );
00282         PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
00283 
00284         p = iv;
00285         while( iv_len > 0 )
00286         {
00287             use_len = ( iv_len < 16 ) ? iv_len : 16;
00288 
00289             for( i = 0; i < use_len; i++ )
00290                 ctx->y [i] ^= p[i];
00291 
00292             gcm_mult( ctx, ctx->y , ctx->y  );
00293 
00294             iv_len -= use_len;
00295             p += use_len;
00296         }
00297 
00298         for( i = 0; i < 16; i++ )
00299             ctx->y [i] ^= work_buf[i];
00300 
00301         gcm_mult( ctx, ctx->y , ctx->y  );
00302     }
00303 
00304     if( ( ret = cipher_update( &ctx->cipher_ctx , ctx->y , 16, ctx->base_ectr ,
00305                              &olen ) ) != 0 )
00306     {
00307         return( ret );
00308     }
00309 
00310     ctx->add_len  = add_len;
00311     p = add;
00312     while( add_len > 0 )
00313     {
00314         use_len = ( add_len < 16 ) ? add_len : 16;
00315 
00316         for( i = 0; i < use_len; i++ )
00317             ctx->buf [i] ^= p[i];
00318 
00319         gcm_mult( ctx, ctx->buf , ctx->buf  );
00320 
00321         add_len -= use_len;
00322         p += use_len;
00323     }
00324 
00325     return( 0 );
00326 }
00327 
00328 int gcm_update( gcm_context *ctx,
00329                 size_t length,
00330                 const unsigned char *input,
00331                 unsigned char *output )
00332 {
00333     int ret;
00334     unsigned char ectr[16];
00335     size_t i;
00336     const unsigned char *p;
00337     unsigned char *out_p = output;
00338     size_t use_len, olen = 0;
00339 
00340     if( output > input && (size_t) ( output - input ) < length )
00341         return( POLARSSL_ERR_GCM_BAD_INPUT );
00342 
00343     ctx->len  += length;
00344 
00345     p = input;
00346     while( length > 0 )
00347     {
00348         use_len = ( length < 16 ) ? length : 16;
00349 
00350         for( i = 16; i > 12; i-- )
00351             if( ++ctx->y [i - 1] != 0 )
00352                 break;
00353 
00354         if( ( ret = cipher_update( &ctx->cipher_ctx , ctx->y , 16, ectr,
00355                                    &olen ) ) != 0 )
00356         {
00357             return( ret );
00358         }
00359 
00360         for( i = 0; i < use_len; i++ )
00361         {
00362             if( ctx->mode  == GCM_DECRYPT )
00363                 ctx->buf [i] ^= p[i];
00364             out_p[i] = ectr[i] ^ p[i];
00365             if( ctx->mode  == GCM_ENCRYPT )
00366                 ctx->buf [i] ^= out_p[i];
00367         }
00368 
00369         gcm_mult( ctx, ctx->buf , ctx->buf  );
00370 
00371         length -= use_len;
00372         p += use_len;
00373         out_p += use_len;
00374     }
00375 
00376     return( 0 );
00377 }
00378 
00379 int gcm_finish( gcm_context *ctx,
00380                 unsigned char *tag,
00381                 size_t tag_len )
00382 {
00383     unsigned char work_buf[16];
00384     size_t i;
00385     uint64_t orig_len = ctx->len  * 8;
00386     uint64_t orig_add_len = ctx->add_len  * 8;
00387 
00388     if( tag_len > 16 )
00389         return( POLARSSL_ERR_GCM_BAD_INPUT );
00390 
00391     if( tag_len != 0 )
00392         memcpy( tag, ctx->base_ectr , tag_len );
00393 
00394     if( orig_len || orig_add_len )
00395     {
00396         memset( work_buf, 0x00, 16 );
00397 
00398         PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0  );
00399         PUT_UINT32_BE( ( orig_add_len       ), work_buf, 4  );
00400         PUT_UINT32_BE( ( orig_len     >> 32 ), work_buf, 8  );
00401         PUT_UINT32_BE( ( orig_len           ), work_buf, 12 );
00402 
00403         for( i = 0; i < 16; i++ )
00404             ctx->buf [i] ^= work_buf[i];
00405 
00406         gcm_mult( ctx, ctx->buf , ctx->buf  );
00407 
00408         for( i = 0; i < tag_len; i++ )
00409             tag[i] ^= ctx->buf [i];
00410     }
00411 
00412     return( 0 );
00413 }
00414 
00415 int gcm_crypt_and_tag( gcm_context *ctx,
00416                        int mode,
00417                        size_t length,
00418                        const unsigned char *iv,
00419                        size_t iv_len,
00420                        const unsigned char *add,
00421                        size_t add_len,
00422                        const unsigned char *input,
00423                        unsigned char *output,
00424                        size_t tag_len,
00425                        unsigned char *tag )
00426 {
00427     int ret;
00428 
00429     if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
00430         return( ret );
00431 
00432     if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 )
00433         return( ret );
00434 
00435     if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 )
00436         return( ret );
00437 
00438     return( 0 );
00439 }
00440 
00441 int gcm_auth_decrypt( gcm_context *ctx,
00442                       size_t length,
00443                       const unsigned char *iv,
00444                       size_t iv_len,
00445                       const unsigned char *add,
00446                       size_t add_len,
00447                       const unsigned char *tag,
00448                       size_t tag_len,
00449                       const unsigned char *input,
00450                       unsigned char *output )
00451 {
00452     int ret;
00453     unsigned char check_tag[16];
00454     size_t i;
00455     int diff;
00456 
00457     if( ( ret = gcm_crypt_and_tag( ctx, GCM_DECRYPT, length,
00458                                    iv, iv_len, add, add_len,
00459                                    input, output, tag_len, check_tag ) ) != 0 )
00460     {
00461         return( ret );
00462     }
00463 
00464     /* Check tag in "constant-time" */
00465     for( diff = 0, i = 0; i < tag_len; i++ )
00466         diff |= tag[i] ^ check_tag[i];
00467 
00468     if( diff != 0 )
00469     {
00470         memset( output, 0, length );
00471         return( POLARSSL_ERR_GCM_AUTH_FAILED );
00472     }
00473 
00474     return( 0 );
00475 }
00476 
00477 void gcm_free( gcm_context *ctx )
00478 {
00479     (void) cipher_free_ctx( &ctx->cipher_ctx  );
00480     memset( ctx, 0, sizeof( gcm_context ) );
00481 }
00482 
00483 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
00484 
00485 #include <stdio.h>
00486 
00487 /*
00488  * AES-GCM test vectors from:
00489  *
00490  * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
00491  */
00492 #define MAX_TESTS   6
00493 
00494 int key_index[MAX_TESTS] =
00495     { 0, 0, 1, 1, 1, 1 };
00496 
00497 unsigned char key[MAX_TESTS][32] =
00498 {
00499     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00500       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00501       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00502       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
00503     { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
00504       0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
00505       0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
00506       0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
00507 };
00508 
00509 size_t iv_len[MAX_TESTS] =
00510     { 12, 12, 12, 12, 8, 60 };
00511 
00512 int iv_index[MAX_TESTS] =
00513     { 0, 0, 1, 1, 1, 2 };
00514 
00515 unsigned char iv[MAX_TESTS][64] =
00516 {
00517     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00518       0x00, 0x00, 0x00, 0x00 },
00519     { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
00520       0xde, 0xca, 0xf8, 0x88 },
00521     { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
00522       0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
00523       0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
00524       0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
00525       0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
00526       0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
00527       0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
00528       0xa6, 0x37, 0xb3, 0x9b },
00529 };
00530 
00531 size_t add_len[MAX_TESTS] =
00532     { 0, 0, 0, 20, 20, 20 };
00533 
00534 int add_index[MAX_TESTS] =
00535     { 0, 0, 0, 1, 1, 1 };
00536 
00537 unsigned char additional[MAX_TESTS][64] =
00538 {
00539     { 0x00 },
00540     { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
00541       0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
00542       0xab, 0xad, 0xda, 0xd2 },
00543 };
00544 
00545 size_t pt_len[MAX_TESTS] =
00546     { 0, 16, 64, 60, 60, 60 };
00547 
00548 int pt_index[MAX_TESTS] =
00549     { 0, 0, 1, 1, 1, 1 };
00550 
00551 unsigned char pt[MAX_TESTS][64] =
00552 {
00553     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00554       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
00555     { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
00556       0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
00557       0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
00558       0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
00559       0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
00560       0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
00561       0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
00562       0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
00563 };
00564 
00565 unsigned char ct[MAX_TESTS * 3][64] =
00566 {
00567     { 0x00 },
00568     { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
00569       0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
00570     { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
00571       0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
00572       0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
00573       0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
00574       0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
00575       0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
00576       0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
00577       0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
00578     { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
00579       0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
00580       0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
00581       0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
00582       0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
00583       0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
00584       0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
00585       0x3d, 0x58, 0xe0, 0x91 },
00586     { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
00587       0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
00588       0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
00589       0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
00590       0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
00591       0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
00592       0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
00593       0xc2, 0x3f, 0x45, 0x98 },
00594     { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
00595       0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
00596       0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
00597       0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
00598       0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
00599       0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
00600       0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
00601       0x4c, 0x34, 0xae, 0xe5 },
00602     { 0x00 },
00603     { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
00604       0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
00605     { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
00606       0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
00607       0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
00608       0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
00609       0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
00610       0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
00611       0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
00612       0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
00613     { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
00614       0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
00615       0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
00616       0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
00617       0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
00618       0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
00619       0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
00620       0xcc, 0xda, 0x27, 0x10 },
00621     { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
00622       0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
00623       0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
00624       0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
00625       0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
00626       0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
00627       0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
00628       0xa0, 0xf0, 0x62, 0xf7 },
00629     { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
00630       0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
00631       0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
00632       0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
00633       0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
00634       0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
00635       0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
00636       0xe9, 0xb7, 0x37, 0x3b },
00637     { 0x00 },
00638     { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
00639       0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
00640     { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
00641       0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
00642       0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
00643       0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
00644       0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
00645       0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
00646       0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
00647       0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
00648     { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
00649       0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
00650       0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
00651       0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
00652       0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
00653       0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
00654       0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
00655       0xbc, 0xc9, 0xf6, 0x62 },
00656     { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
00657       0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
00658       0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
00659       0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
00660       0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
00661       0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
00662       0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
00663       0xf4, 0x7c, 0x9b, 0x1f },
00664     { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
00665       0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
00666       0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
00667       0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
00668       0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
00669       0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
00670       0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
00671       0x44, 0xae, 0x7e, 0x3f },
00672 };
00673 
00674 unsigned char tag[MAX_TESTS * 3][16] =
00675 {
00676     { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
00677       0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
00678     { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
00679       0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
00680     { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
00681       0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
00682     { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
00683       0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
00684     { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
00685       0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
00686     { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
00687       0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
00688     { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
00689       0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
00690     { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
00691       0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
00692     { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
00693       0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
00694     { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
00695       0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
00696     { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
00697       0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
00698     { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
00699       0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
00700     { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
00701       0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
00702     { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
00703       0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
00704     { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
00705       0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
00706     { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
00707       0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
00708     { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
00709       0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
00710     { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
00711       0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
00712 };
00713 
00714 int gcm_self_test( int verbose )
00715 {
00716     gcm_context ctx;
00717     unsigned char buf[64];
00718     unsigned char tag_buf[16];
00719     int i, j, ret;
00720     cipher_id_t cipher = POLARSSL_CIPHER_ID_AES;
00721 
00722     for( j = 0; j < 3; j++ )
00723     {
00724         int key_len = 128 + 64 * j;
00725 
00726         for( i = 0; i < MAX_TESTS; i++ )
00727         {
00728             if( verbose != 0 )
00729                 polarssl_printf( "  AES-GCM-%3d #%d (%s): ",
00730                                  key_len, i, "enc" );
00731 
00732             gcm_init( &ctx, cipher, key[key_index[i]], key_len );
00733 
00734             ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
00735                                      pt_len[i],
00736                                      iv[iv_index[i]], iv_len[i],
00737                                      additional[add_index[i]], add_len[i],
00738                                      pt[pt_index[i]], buf, 16, tag_buf );
00739 
00740             if( ret != 0 ||
00741                 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
00742                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
00743             {
00744                 if( verbose != 0 )
00745                     polarssl_printf( "failed\n" );
00746 
00747                 return( 1 );
00748             }
00749 
00750             gcm_free( &ctx );
00751 
00752             if( verbose != 0 )
00753                 polarssl_printf( "passed\n" );
00754 
00755             if( verbose != 0 )
00756                 polarssl_printf( "  AES-GCM-%3d #%d (%s): ",
00757                                  key_len, i, "dec" );
00758 
00759             gcm_init( &ctx, cipher, key[key_index[i]], key_len );
00760 
00761             ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
00762                                      pt_len[i],
00763                                      iv[iv_index[i]], iv_len[i],
00764                                      additional[add_index[i]], add_len[i],
00765                                      ct[j * 6 + i], buf, 16, tag_buf );
00766 
00767             if( ret != 0 ||
00768                 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
00769                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
00770             {
00771                 if( verbose != 0 )
00772                     polarssl_printf( "failed\n" );
00773 
00774                 return( 1 );
00775             }
00776 
00777             gcm_free( &ctx );
00778 
00779             if( verbose != 0 )
00780                 polarssl_printf( "passed\n" );
00781 
00782             if( verbose != 0 )
00783                 polarssl_printf( "  AES-GCM-%3d #%d split (%s): ",
00784                                  key_len, i, "enc" );
00785 
00786             gcm_init( &ctx, cipher, key[key_index[i]], key_len );
00787 
00788             ret = gcm_starts( &ctx, GCM_ENCRYPT,
00789                               iv[iv_index[i]], iv_len[i],
00790                               additional[add_index[i]], add_len[i] );
00791             if( ret != 0 )
00792             {
00793                 if( verbose != 0 )
00794                     polarssl_printf( "failed\n" );
00795 
00796                 return( 1 );
00797             }
00798 
00799             if( pt_len[i] > 32 )
00800             {
00801                 size_t rest_len = pt_len[i] - 32;
00802                 ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf );
00803                 if( ret != 0 )
00804                 {
00805                     if( verbose != 0 )
00806                         polarssl_printf( "failed\n" );
00807 
00808                     return( 1 );
00809                 }
00810 
00811                 ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
00812                                   buf + 32 );
00813                 if( ret != 0 )
00814                 {
00815                     if( verbose != 0 )
00816                         polarssl_printf( "failed\n" );
00817 
00818                     return( 1 );
00819                 }
00820             }
00821             else
00822             {
00823                 ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
00824                 if( ret != 0 )
00825                 {
00826                     if( verbose != 0 )
00827                         polarssl_printf( "failed\n" );
00828 
00829                     return( 1 );
00830                 }
00831             }
00832 
00833             ret = gcm_finish( &ctx, tag_buf, 16 );
00834             if( ret != 0 ||
00835                 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
00836                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
00837             {
00838                 if( verbose != 0 )
00839                     polarssl_printf( "failed\n" );
00840 
00841                 return( 1 );
00842             }
00843 
00844             gcm_free( &ctx );
00845 
00846             if( verbose != 0 )
00847                 polarssl_printf( "passed\n" );
00848 
00849             if( verbose != 0 )
00850                 polarssl_printf( "  AES-GCM-%3d #%d split (%s): ",
00851                                  key_len, i, "dec" );
00852 
00853             gcm_init( &ctx, cipher, key[key_index[i]], key_len );
00854 
00855             ret = gcm_starts( &ctx, GCM_DECRYPT,
00856                               iv[iv_index[i]], iv_len[i],
00857                               additional[add_index[i]], add_len[i] );
00858             if( ret != 0 )
00859             {
00860                 if( verbose != 0 )
00861                     polarssl_printf( "failed\n" );
00862 
00863                 return( 1 );
00864             }
00865 
00866             if( pt_len[i] > 32 )
00867             {
00868                 size_t rest_len = pt_len[i] - 32;
00869                 ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf );
00870                 if( ret != 0 )
00871                 {
00872                     if( verbose != 0 )
00873                         polarssl_printf( "failed\n" );
00874 
00875                     return( 1 );
00876                 }
00877 
00878                 ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
00879                                   buf + 32 );
00880                 if( ret != 0 )
00881                 {
00882                     if( verbose != 0 )
00883                         polarssl_printf( "failed\n" );
00884 
00885                     return( 1 );
00886                 }
00887             }
00888             else
00889             {
00890                 ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
00891                 if( ret != 0 )
00892                 {
00893                     if( verbose != 0 )
00894                         polarssl_printf( "failed\n" );
00895 
00896                     return( 1 );
00897                 }
00898             }
00899 
00900             ret = gcm_finish( &ctx, tag_buf, 16 );
00901             if( ret != 0 ||
00902                 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
00903                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
00904             {
00905                 if( verbose != 0 )
00906                     polarssl_printf( "failed\n" );
00907 
00908                 return( 1 );
00909             }
00910 
00911             gcm_free( &ctx );
00912 
00913             if( verbose != 0 )
00914                 polarssl_printf( "passed\n" );
00915 
00916         }
00917     }
00918 
00919     if( verbose != 0 )
00920         polarssl_printf( "\n" );
00921 
00922     return( 0 );
00923 }
00924 
00925 
00926 
00927 #endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
00928 
00929 #endif /* POLARSSL_GCM_C */
00930 
00931