mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

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