ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

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