Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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