Rtos API example

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