Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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