mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

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     if( ( (uint64_t) iv_len  ) >> 61 != 0 ||
00281         ( (uint64_t) add_len ) >> 61 != 0 )
00282     {
00283         return( MBEDTLS_ERR_GCM_BAD_INPUT );
00284     }
00285 
00286     memset( ctx->y , 0x00, sizeof(ctx->y ) );
00287     memset( ctx->buf , 0x00, sizeof(ctx->buf ) );
00288 
00289     ctx->mode  = mode;
00290     ctx->len  = 0;
00291     ctx->add_len  = 0;
00292 
00293     if( iv_len == 12 )
00294     {
00295         memcpy( ctx->y , iv, iv_len );
00296         ctx->y [15] = 1;
00297     }
00298     else
00299     {
00300         memset( work_buf, 0x00, 16 );
00301         PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
00302 
00303         p = iv;
00304         while( iv_len > 0 )
00305         {
00306             use_len = ( iv_len < 16 ) ? iv_len : 16;
00307 
00308             for( i = 0; i < use_len; i++ )
00309                 ctx->y [i] ^= p[i];
00310 
00311             gcm_mult( ctx, ctx->y , ctx->y  );
00312 
00313             iv_len -= use_len;
00314             p += use_len;
00315         }
00316 
00317         for( i = 0; i < 16; i++ )
00318             ctx->y [i] ^= work_buf[i];
00319 
00320         gcm_mult( ctx, ctx->y , ctx->y  );
00321     }
00322 
00323     if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx , ctx->y , 16, ctx->base_ectr ,
00324                              &olen ) ) != 0 )
00325     {
00326         return( ret );
00327     }
00328 
00329     ctx->add_len  = add_len;
00330     p = add;
00331     while( add_len > 0 )
00332     {
00333         use_len = ( add_len < 16 ) ? add_len : 16;
00334 
00335         for( i = 0; i < use_len; i++ )
00336             ctx->buf [i] ^= p[i];
00337 
00338         gcm_mult( ctx, ctx->buf , ctx->buf  );
00339 
00340         add_len -= use_len;
00341         p += use_len;
00342     }
00343 
00344     return( 0 );
00345 }
00346 
00347 int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
00348                 size_t length,
00349                 const unsigned char *input,
00350                 unsigned char *output )
00351 {
00352     int ret;
00353     unsigned char ectr[16];
00354     size_t i;
00355     const unsigned char *p;
00356     unsigned char *out_p = output;
00357     size_t use_len, olen = 0;
00358 
00359     if( output > input && (size_t) ( output - input ) < length )
00360         return( MBEDTLS_ERR_GCM_BAD_INPUT );
00361 
00362     /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
00363      * Also check for possible overflow */
00364     if( ctx->len  + length < ctx->len ||
00365         (uint64_t) ctx->len  + length > 0x03FFFFE0ull )
00366     {
00367         return( MBEDTLS_ERR_GCM_BAD_INPUT );
00368     }
00369 
00370     ctx->len  += length;
00371 
00372     p = input;
00373     while( length > 0 )
00374     {
00375         use_len = ( length < 16 ) ? length : 16;
00376 
00377         for( i = 16; i > 12; i-- )
00378             if( ++ctx->y [i - 1] != 0 )
00379                 break;
00380 
00381         if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx , ctx->y , 16, ectr,
00382                                    &olen ) ) != 0 )
00383         {
00384             return( ret );
00385         }
00386 
00387         for( i = 0; i < use_len; i++ )
00388         {
00389             if( ctx->mode  == MBEDTLS_GCM_DECRYPT )
00390                 ctx->buf [i] ^= p[i];
00391             out_p[i] = ectr[i] ^ p[i];
00392             if( ctx->mode  == MBEDTLS_GCM_ENCRYPT )
00393                 ctx->buf [i] ^= out_p[i];
00394         }
00395 
00396         gcm_mult( ctx, ctx->buf , ctx->buf  );
00397 
00398         length -= use_len;
00399         p += use_len;
00400         out_p += use_len;
00401     }
00402 
00403     return( 0 );
00404 }
00405 
00406 int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
00407                 unsigned char *tag,
00408                 size_t tag_len )
00409 {
00410     unsigned char work_buf[16];
00411     size_t i;
00412     uint64_t orig_len = ctx->len  * 8;
00413     uint64_t orig_add_len = ctx->add_len  * 8;
00414 
00415     if( tag_len > 16 || tag_len < 4 )
00416         return( MBEDTLS_ERR_GCM_BAD_INPUT );
00417 
00418     if( tag_len != 0 )
00419         memcpy( tag, ctx->base_ectr , tag_len );
00420 
00421     if( orig_len || orig_add_len )
00422     {
00423         memset( work_buf, 0x00, 16 );
00424 
00425         PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0  );
00426         PUT_UINT32_BE( ( orig_add_len       ), work_buf, 4  );
00427         PUT_UINT32_BE( ( orig_len     >> 32 ), work_buf, 8  );
00428         PUT_UINT32_BE( ( orig_len           ), work_buf, 12 );
00429 
00430         for( i = 0; i < 16; i++ )
00431             ctx->buf [i] ^= work_buf[i];
00432 
00433         gcm_mult( ctx, ctx->buf , ctx->buf  );
00434 
00435         for( i = 0; i < tag_len; i++ )
00436             tag[i] ^= ctx->buf [i];
00437     }
00438 
00439     return( 0 );
00440 }
00441 
00442 int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
00443                        int mode,
00444                        size_t length,
00445                        const unsigned char *iv,
00446                        size_t iv_len,
00447                        const unsigned char *add,
00448                        size_t add_len,
00449                        const unsigned char *input,
00450                        unsigned char *output,
00451                        size_t tag_len,
00452                        unsigned char *tag )
00453 {
00454     int ret;
00455 
00456     if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
00457         return( ret );
00458 
00459     if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
00460         return( ret );
00461 
00462     if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
00463         return( ret );
00464 
00465     return( 0 );
00466 }
00467 
00468 int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
00469                       size_t length,
00470                       const unsigned char *iv,
00471                       size_t iv_len,
00472                       const unsigned char *add,
00473                       size_t add_len,
00474                       const unsigned char *tag,
00475                       size_t tag_len,
00476                       const unsigned char *input,
00477                       unsigned char *output )
00478 {
00479     int ret;
00480     unsigned char check_tag[16];
00481     size_t i;
00482     int diff;
00483 
00484     if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
00485                                    iv, iv_len, add, add_len,
00486                                    input, output, tag_len, check_tag ) ) != 0 )
00487     {
00488         return( ret );
00489     }
00490 
00491     /* Check tag in "constant-time" */
00492     for( diff = 0, i = 0; i < tag_len; i++ )
00493         diff |= tag[i] ^ check_tag[i];
00494 
00495     if( diff != 0 )
00496     {
00497         mbedtls_zeroize( output, length );
00498         return( MBEDTLS_ERR_GCM_AUTH_FAILED );
00499     }
00500 
00501     return( 0 );
00502 }
00503 
00504 void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
00505 {
00506     mbedtls_cipher_free( &ctx->cipher_ctx  );
00507     mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
00508 }
00509 
00510 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
00511 /*
00512  * AES-GCM test vectors from:
00513  *
00514  * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
00515  */
00516 #define MAX_TESTS   6
00517 
00518 static const int key_index[MAX_TESTS] =
00519     { 0, 0, 1, 1, 1, 1 };
00520 
00521 static const unsigned char key[MAX_TESTS][32] =
00522 {
00523     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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     { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
00528       0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
00529       0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
00530       0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
00531 };
00532 
00533 static const size_t iv_len[MAX_TESTS] =
00534     { 12, 12, 12, 12, 8, 60 };
00535 
00536 static const int iv_index[MAX_TESTS] =
00537     { 0, 0, 1, 1, 1, 2 };
00538 
00539 static const unsigned char iv[MAX_TESTS][64] =
00540 {
00541     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00542       0x00, 0x00, 0x00, 0x00 },
00543     { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
00544       0xde, 0xca, 0xf8, 0x88 },
00545     { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
00546       0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
00547       0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
00548       0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
00549       0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
00550       0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
00551       0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
00552       0xa6, 0x37, 0xb3, 0x9b },
00553 };
00554 
00555 static const size_t add_len[MAX_TESTS] =
00556     { 0, 0, 0, 20, 20, 20 };
00557 
00558 static const int add_index[MAX_TESTS] =
00559     { 0, 0, 0, 1, 1, 1 };
00560 
00561 static const unsigned char additional[MAX_TESTS][64] =
00562 {
00563     { 0x00 },
00564     { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
00565       0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
00566       0xab, 0xad, 0xda, 0xd2 },
00567 };
00568 
00569 static const size_t pt_len[MAX_TESTS] =
00570     { 0, 16, 64, 60, 60, 60 };
00571 
00572 static const int pt_index[MAX_TESTS] =
00573     { 0, 0, 1, 1, 1, 1 };
00574 
00575 static const unsigned char pt[MAX_TESTS][64] =
00576 {
00577     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00578       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
00579     { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
00580       0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
00581       0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
00582       0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
00583       0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
00584       0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
00585       0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
00586       0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
00587 };
00588 
00589 static const unsigned char ct[MAX_TESTS * 3][64] =
00590 {
00591     { 0x00 },
00592     { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
00593       0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
00594     { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
00595       0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
00596       0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
00597       0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
00598       0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
00599       0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
00600       0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
00601       0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
00602     { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
00603       0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
00604       0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
00605       0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
00606       0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
00607       0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
00608       0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
00609       0x3d, 0x58, 0xe0, 0x91 },
00610     { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
00611       0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
00612       0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
00613       0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
00614       0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
00615       0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
00616       0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
00617       0xc2, 0x3f, 0x45, 0x98 },
00618     { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
00619       0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
00620       0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
00621       0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
00622       0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
00623       0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
00624       0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
00625       0x4c, 0x34, 0xae, 0xe5 },
00626     { 0x00 },
00627     { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
00628       0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
00629     { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
00630       0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
00631       0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
00632       0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
00633       0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
00634       0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
00635       0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
00636       0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
00637     { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
00638       0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
00639       0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
00640       0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
00641       0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
00642       0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
00643       0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
00644       0xcc, 0xda, 0x27, 0x10 },
00645     { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
00646       0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
00647       0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
00648       0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
00649       0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
00650       0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
00651       0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
00652       0xa0, 0xf0, 0x62, 0xf7 },
00653     { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
00654       0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
00655       0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
00656       0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
00657       0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
00658       0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
00659       0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
00660       0xe9, 0xb7, 0x37, 0x3b },
00661     { 0x00 },
00662     { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
00663       0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
00664     { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
00665       0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
00666       0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
00667       0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
00668       0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
00669       0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
00670       0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
00671       0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
00672     { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
00673       0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
00674       0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
00675       0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
00676       0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
00677       0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
00678       0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
00679       0xbc, 0xc9, 0xf6, 0x62 },
00680     { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
00681       0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
00682       0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
00683       0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
00684       0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
00685       0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
00686       0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
00687       0xf4, 0x7c, 0x9b, 0x1f },
00688     { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
00689       0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
00690       0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
00691       0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
00692       0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
00693       0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
00694       0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
00695       0x44, 0xae, 0x7e, 0x3f },
00696 };
00697 
00698 static const unsigned char tag[MAX_TESTS * 3][16] =
00699 {
00700     { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
00701       0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
00702     { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
00703       0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
00704     { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
00705       0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
00706     { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
00707       0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
00708     { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
00709       0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
00710     { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
00711       0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
00712     { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
00713       0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
00714     { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
00715       0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
00716     { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
00717       0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
00718     { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
00719       0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
00720     { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
00721       0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
00722     { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
00723       0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
00724     { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
00725       0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
00726     { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
00727       0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
00728     { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
00729       0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
00730     { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
00731       0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
00732     { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
00733       0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
00734     { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
00735       0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
00736 };
00737 
00738 int mbedtls_gcm_self_test( int verbose )
00739 {
00740     mbedtls_gcm_context ctx;
00741     unsigned char buf[64];
00742     unsigned char tag_buf[16];
00743     int i, j, ret;
00744     mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
00745 
00746     mbedtls_gcm_init( &ctx );
00747 
00748     for( j = 0; j < 3; j++ )
00749     {
00750         int key_len = 128 + 64 * j;
00751 
00752         for( i = 0; i < MAX_TESTS; i++ )
00753         {
00754             if( verbose != 0 )
00755                 mbedtls_printf( "  AES-GCM-%3d #%d (%s): ",
00756                                  key_len, i, "enc" );
00757 
00758             mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
00759 
00760             ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
00761                                      pt_len[i],
00762                                      iv[iv_index[i]], iv_len[i],
00763                                      additional[add_index[i]], add_len[i],
00764                                      pt[pt_index[i]], buf, 16, tag_buf );
00765 
00766             if( ret != 0 ||
00767                 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
00768                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
00769             {
00770                 if( verbose != 0 )
00771                     mbedtls_printf( "failed\n" );
00772 
00773                 return( 1 );
00774             }
00775 
00776             mbedtls_gcm_free( &ctx );
00777 
00778             if( verbose != 0 )
00779                 mbedtls_printf( "passed\n" );
00780 
00781             if( verbose != 0 )
00782                 mbedtls_printf( "  AES-GCM-%3d #%d (%s): ",
00783                                  key_len, i, "dec" );
00784 
00785             mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
00786 
00787             ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
00788                                      pt_len[i],
00789                                      iv[iv_index[i]], iv_len[i],
00790                                      additional[add_index[i]], add_len[i],
00791                                      ct[j * 6 + i], buf, 16, tag_buf );
00792 
00793             if( ret != 0 ||
00794                 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
00795                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
00796             {
00797                 if( verbose != 0 )
00798                     mbedtls_printf( "failed\n" );
00799 
00800                 return( 1 );
00801             }
00802 
00803             mbedtls_gcm_free( &ctx );
00804 
00805             if( verbose != 0 )
00806                 mbedtls_printf( "passed\n" );
00807 
00808             if( verbose != 0 )
00809                 mbedtls_printf( "  AES-GCM-%3d #%d split (%s): ",
00810                                  key_len, i, "enc" );
00811 
00812             mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
00813 
00814             ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
00815                               iv[iv_index[i]], iv_len[i],
00816                               additional[add_index[i]], add_len[i] );
00817             if( ret != 0 )
00818             {
00819                 if( verbose != 0 )
00820                     mbedtls_printf( "failed\n" );
00821 
00822                 return( 1 );
00823             }
00824 
00825             if( pt_len[i] > 32 )
00826             {
00827                 size_t rest_len = pt_len[i] - 32;
00828                 ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
00829                 if( ret != 0 )
00830                 {
00831                     if( verbose != 0 )
00832                         mbedtls_printf( "failed\n" );
00833 
00834                     return( 1 );
00835                 }
00836 
00837                 ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
00838                                   buf + 32 );
00839                 if( ret != 0 )
00840                 {
00841                     if( verbose != 0 )
00842                         mbedtls_printf( "failed\n" );
00843 
00844                     return( 1 );
00845                 }
00846             }
00847             else
00848             {
00849                 ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
00850                 if( ret != 0 )
00851                 {
00852                     if( verbose != 0 )
00853                         mbedtls_printf( "failed\n" );
00854 
00855                     return( 1 );
00856                 }
00857             }
00858 
00859             ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
00860             if( ret != 0 ||
00861                 memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
00862                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
00863             {
00864                 if( verbose != 0 )
00865                     mbedtls_printf( "failed\n" );
00866 
00867                 return( 1 );
00868             }
00869 
00870             mbedtls_gcm_free( &ctx );
00871 
00872             if( verbose != 0 )
00873                 mbedtls_printf( "passed\n" );
00874 
00875             if( verbose != 0 )
00876                 mbedtls_printf( "  AES-GCM-%3d #%d split (%s): ",
00877                                  key_len, i, "dec" );
00878 
00879             mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
00880 
00881             ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
00882                               iv[iv_index[i]], iv_len[i],
00883                               additional[add_index[i]], add_len[i] );
00884             if( ret != 0 )
00885             {
00886                 if( verbose != 0 )
00887                     mbedtls_printf( "failed\n" );
00888 
00889                 return( 1 );
00890             }
00891 
00892             if( pt_len[i] > 32 )
00893             {
00894                 size_t rest_len = pt_len[i] - 32;
00895                 ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
00896                 if( ret != 0 )
00897                 {
00898                     if( verbose != 0 )
00899                         mbedtls_printf( "failed\n" );
00900 
00901                     return( 1 );
00902                 }
00903 
00904                 ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
00905                                   buf + 32 );
00906                 if( ret != 0 )
00907                 {
00908                     if( verbose != 0 )
00909                         mbedtls_printf( "failed\n" );
00910 
00911                     return( 1 );
00912                 }
00913             }
00914             else
00915             {
00916                 ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
00917                 if( ret != 0 )
00918                 {
00919                     if( verbose != 0 )
00920                         mbedtls_printf( "failed\n" );
00921 
00922                     return( 1 );
00923                 }
00924             }
00925 
00926             ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
00927             if( ret != 0 ||
00928                 memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
00929                 memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
00930             {
00931                 if( verbose != 0 )
00932                     mbedtls_printf( "failed\n" );
00933 
00934                 return( 1 );
00935             }
00936 
00937             mbedtls_gcm_free( &ctx );
00938 
00939             if( verbose != 0 )
00940                 mbedtls_printf( "passed\n" );
00941 
00942         }
00943     }
00944 
00945     if( verbose != 0 )
00946         mbedtls_printf( "\n" );
00947 
00948     return( 0 );
00949 }
00950 
00951 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
00952 
00953 #endif /* MBEDTLS_GCM_C */