Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

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