1*817466cbSJens Wiklander /* 2*817466cbSJens Wiklander * NIST SP800-38D compliant GCM implementation 3*817466cbSJens Wiklander * 4*817466cbSJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5*817466cbSJens Wiklander * SPDX-License-Identifier: Apache-2.0 6*817466cbSJens Wiklander * 7*817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8*817466cbSJens Wiklander * not use this file except in compliance with the License. 9*817466cbSJens Wiklander * You may obtain a copy of the License at 10*817466cbSJens Wiklander * 11*817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12*817466cbSJens Wiklander * 13*817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14*817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15*817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16*817466cbSJens Wiklander * See the License for the specific language governing permissions and 17*817466cbSJens Wiklander * limitations under the License. 18*817466cbSJens Wiklander * 19*817466cbSJens Wiklander * This file is part of mbed TLS (https://tls.mbed.org) 20*817466cbSJens Wiklander */ 21*817466cbSJens Wiklander 22*817466cbSJens Wiklander /* 23*817466cbSJens Wiklander * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf 24*817466cbSJens Wiklander * 25*817466cbSJens Wiklander * See also: 26*817466cbSJens Wiklander * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf 27*817466cbSJens Wiklander * 28*817466cbSJens Wiklander * We use the algorithm described as Shoup's method with 4-bit tables in 29*817466cbSJens Wiklander * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. 30*817466cbSJens Wiklander */ 31*817466cbSJens Wiklander 32*817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 33*817466cbSJens Wiklander #include "mbedtls/config.h" 34*817466cbSJens Wiklander #else 35*817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 36*817466cbSJens Wiklander #endif 37*817466cbSJens Wiklander 38*817466cbSJens Wiklander #if defined(MBEDTLS_GCM_C) 39*817466cbSJens Wiklander 40*817466cbSJens Wiklander #include "mbedtls/gcm.h" 41*817466cbSJens Wiklander 42*817466cbSJens Wiklander #include <string.h> 43*817466cbSJens Wiklander 44*817466cbSJens Wiklander #if defined(MBEDTLS_AESNI_C) 45*817466cbSJens Wiklander #include "mbedtls/aesni.h" 46*817466cbSJens Wiklander #endif 47*817466cbSJens Wiklander 48*817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 49*817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 50*817466cbSJens Wiklander #include "mbedtls/platform.h" 51*817466cbSJens Wiklander #else 52*817466cbSJens Wiklander #include <stdio.h> 53*817466cbSJens Wiklander #define mbedtls_printf printf 54*817466cbSJens Wiklander #endif /* MBEDTLS_PLATFORM_C */ 55*817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 56*817466cbSJens Wiklander 57*817466cbSJens Wiklander /* 58*817466cbSJens Wiklander * 32-bit integer manipulation macros (big endian) 59*817466cbSJens Wiklander */ 60*817466cbSJens Wiklander #ifndef GET_UINT32_BE 61*817466cbSJens Wiklander #define GET_UINT32_BE(n,b,i) \ 62*817466cbSJens Wiklander { \ 63*817466cbSJens Wiklander (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ 64*817466cbSJens Wiklander | ( (uint32_t) (b)[(i) + 1] << 16 ) \ 65*817466cbSJens Wiklander | ( (uint32_t) (b)[(i) + 2] << 8 ) \ 66*817466cbSJens Wiklander | ( (uint32_t) (b)[(i) + 3] ); \ 67*817466cbSJens Wiklander } 68*817466cbSJens Wiklander #endif 69*817466cbSJens Wiklander 70*817466cbSJens Wiklander #ifndef PUT_UINT32_BE 71*817466cbSJens Wiklander #define PUT_UINT32_BE(n,b,i) \ 72*817466cbSJens Wiklander { \ 73*817466cbSJens Wiklander (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ 74*817466cbSJens Wiklander (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ 75*817466cbSJens Wiklander (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ 76*817466cbSJens Wiklander (b)[(i) + 3] = (unsigned char) ( (n) ); \ 77*817466cbSJens Wiklander } 78*817466cbSJens Wiklander #endif 79*817466cbSJens Wiklander 80*817466cbSJens Wiklander /* Implementation that should never be optimized out by the compiler */ 81*817466cbSJens Wiklander static void mbedtls_zeroize( void *v, size_t n ) { 82*817466cbSJens Wiklander volatile unsigned char *p = v; while( n-- ) *p++ = 0; 83*817466cbSJens Wiklander } 84*817466cbSJens Wiklander 85*817466cbSJens Wiklander /* 86*817466cbSJens Wiklander * Initialize a context 87*817466cbSJens Wiklander */ 88*817466cbSJens Wiklander void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) 89*817466cbSJens Wiklander { 90*817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); 91*817466cbSJens Wiklander } 92*817466cbSJens Wiklander 93*817466cbSJens Wiklander /* 94*817466cbSJens Wiklander * Precompute small multiples of H, that is set 95*817466cbSJens Wiklander * HH[i] || HL[i] = H times i, 96*817466cbSJens Wiklander * where i is seen as a field element as in [MGV], ie high-order bits 97*817466cbSJens Wiklander * correspond to low powers of P. The result is stored in the same way, that 98*817466cbSJens Wiklander * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL 99*817466cbSJens Wiklander * corresponds to P^127. 100*817466cbSJens Wiklander */ 101*817466cbSJens Wiklander static int gcm_gen_table( mbedtls_gcm_context *ctx ) 102*817466cbSJens Wiklander { 103*817466cbSJens Wiklander int ret, i, j; 104*817466cbSJens Wiklander uint64_t hi, lo; 105*817466cbSJens Wiklander uint64_t vl, vh; 106*817466cbSJens Wiklander unsigned char h[16]; 107*817466cbSJens Wiklander size_t olen = 0; 108*817466cbSJens Wiklander 109*817466cbSJens Wiklander memset( h, 0, 16 ); 110*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) 111*817466cbSJens Wiklander return( ret ); 112*817466cbSJens Wiklander 113*817466cbSJens Wiklander /* pack h as two 64-bits ints, big-endian */ 114*817466cbSJens Wiklander GET_UINT32_BE( hi, h, 0 ); 115*817466cbSJens Wiklander GET_UINT32_BE( lo, h, 4 ); 116*817466cbSJens Wiklander vh = (uint64_t) hi << 32 | lo; 117*817466cbSJens Wiklander 118*817466cbSJens Wiklander GET_UINT32_BE( hi, h, 8 ); 119*817466cbSJens Wiklander GET_UINT32_BE( lo, h, 12 ); 120*817466cbSJens Wiklander vl = (uint64_t) hi << 32 | lo; 121*817466cbSJens Wiklander 122*817466cbSJens Wiklander /* 8 = 1000 corresponds to 1 in GF(2^128) */ 123*817466cbSJens Wiklander ctx->HL[8] = vl; 124*817466cbSJens Wiklander ctx->HH[8] = vh; 125*817466cbSJens Wiklander 126*817466cbSJens Wiklander #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) 127*817466cbSJens Wiklander /* With CLMUL support, we need only h, not the rest of the table */ 128*817466cbSJens Wiklander if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) 129*817466cbSJens Wiklander return( 0 ); 130*817466cbSJens Wiklander #endif 131*817466cbSJens Wiklander 132*817466cbSJens Wiklander /* 0 corresponds to 0 in GF(2^128) */ 133*817466cbSJens Wiklander ctx->HH[0] = 0; 134*817466cbSJens Wiklander ctx->HL[0] = 0; 135*817466cbSJens Wiklander 136*817466cbSJens Wiklander for( i = 4; i > 0; i >>= 1 ) 137*817466cbSJens Wiklander { 138*817466cbSJens Wiklander uint32_t T = ( vl & 1 ) * 0xe1000000U; 139*817466cbSJens Wiklander vl = ( vh << 63 ) | ( vl >> 1 ); 140*817466cbSJens Wiklander vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); 141*817466cbSJens Wiklander 142*817466cbSJens Wiklander ctx->HL[i] = vl; 143*817466cbSJens Wiklander ctx->HH[i] = vh; 144*817466cbSJens Wiklander } 145*817466cbSJens Wiklander 146*817466cbSJens Wiklander for( i = 2; i <= 8; i *= 2 ) 147*817466cbSJens Wiklander { 148*817466cbSJens Wiklander uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; 149*817466cbSJens Wiklander vh = *HiH; 150*817466cbSJens Wiklander vl = *HiL; 151*817466cbSJens Wiklander for( j = 1; j < i; j++ ) 152*817466cbSJens Wiklander { 153*817466cbSJens Wiklander HiH[j] = vh ^ ctx->HH[j]; 154*817466cbSJens Wiklander HiL[j] = vl ^ ctx->HL[j]; 155*817466cbSJens Wiklander } 156*817466cbSJens Wiklander } 157*817466cbSJens Wiklander 158*817466cbSJens Wiklander return( 0 ); 159*817466cbSJens Wiklander } 160*817466cbSJens Wiklander 161*817466cbSJens Wiklander int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, 162*817466cbSJens Wiklander mbedtls_cipher_id_t cipher, 163*817466cbSJens Wiklander const unsigned char *key, 164*817466cbSJens Wiklander unsigned int keybits ) 165*817466cbSJens Wiklander { 166*817466cbSJens Wiklander int ret; 167*817466cbSJens Wiklander const mbedtls_cipher_info_t *cipher_info; 168*817466cbSJens Wiklander 169*817466cbSJens Wiklander cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); 170*817466cbSJens Wiklander if( cipher_info == NULL ) 171*817466cbSJens Wiklander return( MBEDTLS_ERR_GCM_BAD_INPUT ); 172*817466cbSJens Wiklander 173*817466cbSJens Wiklander if( cipher_info->block_size != 16 ) 174*817466cbSJens Wiklander return( MBEDTLS_ERR_GCM_BAD_INPUT ); 175*817466cbSJens Wiklander 176*817466cbSJens Wiklander mbedtls_cipher_free( &ctx->cipher_ctx ); 177*817466cbSJens Wiklander 178*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) 179*817466cbSJens Wiklander return( ret ); 180*817466cbSJens Wiklander 181*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, 182*817466cbSJens Wiklander MBEDTLS_ENCRYPT ) ) != 0 ) 183*817466cbSJens Wiklander { 184*817466cbSJens Wiklander return( ret ); 185*817466cbSJens Wiklander } 186*817466cbSJens Wiklander 187*817466cbSJens Wiklander if( ( ret = gcm_gen_table( ctx ) ) != 0 ) 188*817466cbSJens Wiklander return( ret ); 189*817466cbSJens Wiklander 190*817466cbSJens Wiklander return( 0 ); 191*817466cbSJens Wiklander } 192*817466cbSJens Wiklander 193*817466cbSJens Wiklander /* 194*817466cbSJens Wiklander * Shoup's method for multiplication use this table with 195*817466cbSJens Wiklander * last4[x] = x times P^128 196*817466cbSJens Wiklander * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] 197*817466cbSJens Wiklander */ 198*817466cbSJens Wiklander static const uint64_t last4[16] = 199*817466cbSJens Wiklander { 200*817466cbSJens Wiklander 0x0000, 0x1c20, 0x3840, 0x2460, 201*817466cbSJens Wiklander 0x7080, 0x6ca0, 0x48c0, 0x54e0, 202*817466cbSJens Wiklander 0xe100, 0xfd20, 0xd940, 0xc560, 203*817466cbSJens Wiklander 0x9180, 0x8da0, 0xa9c0, 0xb5e0 204*817466cbSJens Wiklander }; 205*817466cbSJens Wiklander 206*817466cbSJens Wiklander /* 207*817466cbSJens Wiklander * Sets output to x times H using the precomputed tables. 208*817466cbSJens Wiklander * x and output are seen as elements of GF(2^128) as in [MGV]. 209*817466cbSJens Wiklander */ 210*817466cbSJens Wiklander static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], 211*817466cbSJens Wiklander unsigned char output[16] ) 212*817466cbSJens Wiklander { 213*817466cbSJens Wiklander int i = 0; 214*817466cbSJens Wiklander unsigned char lo, hi, rem; 215*817466cbSJens Wiklander uint64_t zh, zl; 216*817466cbSJens Wiklander 217*817466cbSJens Wiklander #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) 218*817466cbSJens Wiklander if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { 219*817466cbSJens Wiklander unsigned char h[16]; 220*817466cbSJens Wiklander 221*817466cbSJens Wiklander PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); 222*817466cbSJens Wiklander PUT_UINT32_BE( ctx->HH[8], h, 4 ); 223*817466cbSJens Wiklander PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); 224*817466cbSJens Wiklander PUT_UINT32_BE( ctx->HL[8], h, 12 ); 225*817466cbSJens Wiklander 226*817466cbSJens Wiklander mbedtls_aesni_gcm_mult( output, x, h ); 227*817466cbSJens Wiklander return; 228*817466cbSJens Wiklander } 229*817466cbSJens Wiklander #endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ 230*817466cbSJens Wiklander 231*817466cbSJens Wiklander lo = x[15] & 0xf; 232*817466cbSJens Wiklander 233*817466cbSJens Wiklander zh = ctx->HH[lo]; 234*817466cbSJens Wiklander zl = ctx->HL[lo]; 235*817466cbSJens Wiklander 236*817466cbSJens Wiklander for( i = 15; i >= 0; i-- ) 237*817466cbSJens Wiklander { 238*817466cbSJens Wiklander lo = x[i] & 0xf; 239*817466cbSJens Wiklander hi = x[i] >> 4; 240*817466cbSJens Wiklander 241*817466cbSJens Wiklander if( i != 15 ) 242*817466cbSJens Wiklander { 243*817466cbSJens Wiklander rem = (unsigned char) zl & 0xf; 244*817466cbSJens Wiklander zl = ( zh << 60 ) | ( zl >> 4 ); 245*817466cbSJens Wiklander zh = ( zh >> 4 ); 246*817466cbSJens Wiklander zh ^= (uint64_t) last4[rem] << 48; 247*817466cbSJens Wiklander zh ^= ctx->HH[lo]; 248*817466cbSJens Wiklander zl ^= ctx->HL[lo]; 249*817466cbSJens Wiklander 250*817466cbSJens Wiklander } 251*817466cbSJens Wiklander 252*817466cbSJens Wiklander rem = (unsigned char) zl & 0xf; 253*817466cbSJens Wiklander zl = ( zh << 60 ) | ( zl >> 4 ); 254*817466cbSJens Wiklander zh = ( zh >> 4 ); 255*817466cbSJens Wiklander zh ^= (uint64_t) last4[rem] << 48; 256*817466cbSJens Wiklander zh ^= ctx->HH[hi]; 257*817466cbSJens Wiklander zl ^= ctx->HL[hi]; 258*817466cbSJens Wiklander } 259*817466cbSJens Wiklander 260*817466cbSJens Wiklander PUT_UINT32_BE( zh >> 32, output, 0 ); 261*817466cbSJens Wiklander PUT_UINT32_BE( zh, output, 4 ); 262*817466cbSJens Wiklander PUT_UINT32_BE( zl >> 32, output, 8 ); 263*817466cbSJens Wiklander PUT_UINT32_BE( zl, output, 12 ); 264*817466cbSJens Wiklander } 265*817466cbSJens Wiklander 266*817466cbSJens Wiklander int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, 267*817466cbSJens Wiklander int mode, 268*817466cbSJens Wiklander const unsigned char *iv, 269*817466cbSJens Wiklander size_t iv_len, 270*817466cbSJens Wiklander const unsigned char *add, 271*817466cbSJens Wiklander size_t add_len ) 272*817466cbSJens Wiklander { 273*817466cbSJens Wiklander int ret; 274*817466cbSJens Wiklander unsigned char work_buf[16]; 275*817466cbSJens Wiklander size_t i; 276*817466cbSJens Wiklander const unsigned char *p; 277*817466cbSJens Wiklander size_t use_len, olen = 0; 278*817466cbSJens Wiklander 279*817466cbSJens Wiklander /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ 280*817466cbSJens Wiklander /* IV is not allowed to be zero length */ 281*817466cbSJens Wiklander if( iv_len == 0 || 282*817466cbSJens Wiklander ( (uint64_t) iv_len ) >> 61 != 0 || 283*817466cbSJens Wiklander ( (uint64_t) add_len ) >> 61 != 0 ) 284*817466cbSJens Wiklander { 285*817466cbSJens Wiklander return( MBEDTLS_ERR_GCM_BAD_INPUT ); 286*817466cbSJens Wiklander } 287*817466cbSJens Wiklander 288*817466cbSJens Wiklander memset( ctx->y, 0x00, sizeof(ctx->y) ); 289*817466cbSJens Wiklander memset( ctx->buf, 0x00, sizeof(ctx->buf) ); 290*817466cbSJens Wiklander 291*817466cbSJens Wiklander ctx->mode = mode; 292*817466cbSJens Wiklander ctx->len = 0; 293*817466cbSJens Wiklander ctx->add_len = 0; 294*817466cbSJens Wiklander 295*817466cbSJens Wiklander if( iv_len == 12 ) 296*817466cbSJens Wiklander { 297*817466cbSJens Wiklander memcpy( ctx->y, iv, iv_len ); 298*817466cbSJens Wiklander ctx->y[15] = 1; 299*817466cbSJens Wiklander } 300*817466cbSJens Wiklander else 301*817466cbSJens Wiklander { 302*817466cbSJens Wiklander memset( work_buf, 0x00, 16 ); 303*817466cbSJens Wiklander PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); 304*817466cbSJens Wiklander 305*817466cbSJens Wiklander p = iv; 306*817466cbSJens Wiklander while( iv_len > 0 ) 307*817466cbSJens Wiklander { 308*817466cbSJens Wiklander use_len = ( iv_len < 16 ) ? iv_len : 16; 309*817466cbSJens Wiklander 310*817466cbSJens Wiklander for( i = 0; i < use_len; i++ ) 311*817466cbSJens Wiklander ctx->y[i] ^= p[i]; 312*817466cbSJens Wiklander 313*817466cbSJens Wiklander gcm_mult( ctx, ctx->y, ctx->y ); 314*817466cbSJens Wiklander 315*817466cbSJens Wiklander iv_len -= use_len; 316*817466cbSJens Wiklander p += use_len; 317*817466cbSJens Wiklander } 318*817466cbSJens Wiklander 319*817466cbSJens Wiklander for( i = 0; i < 16; i++ ) 320*817466cbSJens Wiklander ctx->y[i] ^= work_buf[i]; 321*817466cbSJens Wiklander 322*817466cbSJens Wiklander gcm_mult( ctx, ctx->y, ctx->y ); 323*817466cbSJens Wiklander } 324*817466cbSJens Wiklander 325*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, 326*817466cbSJens Wiklander &olen ) ) != 0 ) 327*817466cbSJens Wiklander { 328*817466cbSJens Wiklander return( ret ); 329*817466cbSJens Wiklander } 330*817466cbSJens Wiklander 331*817466cbSJens Wiklander ctx->add_len = add_len; 332*817466cbSJens Wiklander p = add; 333*817466cbSJens Wiklander while( add_len > 0 ) 334*817466cbSJens Wiklander { 335*817466cbSJens Wiklander use_len = ( add_len < 16 ) ? add_len : 16; 336*817466cbSJens Wiklander 337*817466cbSJens Wiklander for( i = 0; i < use_len; i++ ) 338*817466cbSJens Wiklander ctx->buf[i] ^= p[i]; 339*817466cbSJens Wiklander 340*817466cbSJens Wiklander gcm_mult( ctx, ctx->buf, ctx->buf ); 341*817466cbSJens Wiklander 342*817466cbSJens Wiklander add_len -= use_len; 343*817466cbSJens Wiklander p += use_len; 344*817466cbSJens Wiklander } 345*817466cbSJens Wiklander 346*817466cbSJens Wiklander return( 0 ); 347*817466cbSJens Wiklander } 348*817466cbSJens Wiklander 349*817466cbSJens Wiklander int mbedtls_gcm_update( mbedtls_gcm_context *ctx, 350*817466cbSJens Wiklander size_t length, 351*817466cbSJens Wiklander const unsigned char *input, 352*817466cbSJens Wiklander unsigned char *output ) 353*817466cbSJens Wiklander { 354*817466cbSJens Wiklander int ret; 355*817466cbSJens Wiklander unsigned char ectr[16]; 356*817466cbSJens Wiklander size_t i; 357*817466cbSJens Wiklander const unsigned char *p; 358*817466cbSJens Wiklander unsigned char *out_p = output; 359*817466cbSJens Wiklander size_t use_len, olen = 0; 360*817466cbSJens Wiklander 361*817466cbSJens Wiklander if( output > input && (size_t) ( output - input ) < length ) 362*817466cbSJens Wiklander return( MBEDTLS_ERR_GCM_BAD_INPUT ); 363*817466cbSJens Wiklander 364*817466cbSJens Wiklander /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes 365*817466cbSJens Wiklander * Also check for possible overflow */ 366*817466cbSJens Wiklander if( ctx->len + length < ctx->len || 367*817466cbSJens Wiklander (uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) 368*817466cbSJens Wiklander { 369*817466cbSJens Wiklander return( MBEDTLS_ERR_GCM_BAD_INPUT ); 370*817466cbSJens Wiklander } 371*817466cbSJens Wiklander 372*817466cbSJens Wiklander ctx->len += length; 373*817466cbSJens Wiklander 374*817466cbSJens Wiklander p = input; 375*817466cbSJens Wiklander while( length > 0 ) 376*817466cbSJens Wiklander { 377*817466cbSJens Wiklander use_len = ( length < 16 ) ? length : 16; 378*817466cbSJens Wiklander 379*817466cbSJens Wiklander for( i = 16; i > 12; i-- ) 380*817466cbSJens Wiklander if( ++ctx->y[i - 1] != 0 ) 381*817466cbSJens Wiklander break; 382*817466cbSJens Wiklander 383*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, 384*817466cbSJens Wiklander &olen ) ) != 0 ) 385*817466cbSJens Wiklander { 386*817466cbSJens Wiklander return( ret ); 387*817466cbSJens Wiklander } 388*817466cbSJens Wiklander 389*817466cbSJens Wiklander for( i = 0; i < use_len; i++ ) 390*817466cbSJens Wiklander { 391*817466cbSJens Wiklander if( ctx->mode == MBEDTLS_GCM_DECRYPT ) 392*817466cbSJens Wiklander ctx->buf[i] ^= p[i]; 393*817466cbSJens Wiklander out_p[i] = ectr[i] ^ p[i]; 394*817466cbSJens Wiklander if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) 395*817466cbSJens Wiklander ctx->buf[i] ^= out_p[i]; 396*817466cbSJens Wiklander } 397*817466cbSJens Wiklander 398*817466cbSJens Wiklander gcm_mult( ctx, ctx->buf, ctx->buf ); 399*817466cbSJens Wiklander 400*817466cbSJens Wiklander length -= use_len; 401*817466cbSJens Wiklander p += use_len; 402*817466cbSJens Wiklander out_p += use_len; 403*817466cbSJens Wiklander } 404*817466cbSJens Wiklander 405*817466cbSJens Wiklander return( 0 ); 406*817466cbSJens Wiklander } 407*817466cbSJens Wiklander 408*817466cbSJens Wiklander int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, 409*817466cbSJens Wiklander unsigned char *tag, 410*817466cbSJens Wiklander size_t tag_len ) 411*817466cbSJens Wiklander { 412*817466cbSJens Wiklander unsigned char work_buf[16]; 413*817466cbSJens Wiklander size_t i; 414*817466cbSJens Wiklander uint64_t orig_len = ctx->len * 8; 415*817466cbSJens Wiklander uint64_t orig_add_len = ctx->add_len * 8; 416*817466cbSJens Wiklander 417*817466cbSJens Wiklander if( tag_len > 16 || tag_len < 4 ) 418*817466cbSJens Wiklander return( MBEDTLS_ERR_GCM_BAD_INPUT ); 419*817466cbSJens Wiklander 420*817466cbSJens Wiklander memcpy( tag, ctx->base_ectr, tag_len ); 421*817466cbSJens Wiklander 422*817466cbSJens Wiklander if( orig_len || orig_add_len ) 423*817466cbSJens Wiklander { 424*817466cbSJens Wiklander memset( work_buf, 0x00, 16 ); 425*817466cbSJens Wiklander 426*817466cbSJens Wiklander PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); 427*817466cbSJens Wiklander PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); 428*817466cbSJens Wiklander PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); 429*817466cbSJens Wiklander PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); 430*817466cbSJens Wiklander 431*817466cbSJens Wiklander for( i = 0; i < 16; i++ ) 432*817466cbSJens Wiklander ctx->buf[i] ^= work_buf[i]; 433*817466cbSJens Wiklander 434*817466cbSJens Wiklander gcm_mult( ctx, ctx->buf, ctx->buf ); 435*817466cbSJens Wiklander 436*817466cbSJens Wiklander for( i = 0; i < tag_len; i++ ) 437*817466cbSJens Wiklander tag[i] ^= ctx->buf[i]; 438*817466cbSJens Wiklander } 439*817466cbSJens Wiklander 440*817466cbSJens Wiklander return( 0 ); 441*817466cbSJens Wiklander } 442*817466cbSJens Wiklander 443*817466cbSJens Wiklander int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, 444*817466cbSJens Wiklander int mode, 445*817466cbSJens Wiklander size_t length, 446*817466cbSJens Wiklander const unsigned char *iv, 447*817466cbSJens Wiklander size_t iv_len, 448*817466cbSJens Wiklander const unsigned char *add, 449*817466cbSJens Wiklander size_t add_len, 450*817466cbSJens Wiklander const unsigned char *input, 451*817466cbSJens Wiklander unsigned char *output, 452*817466cbSJens Wiklander size_t tag_len, 453*817466cbSJens Wiklander unsigned char *tag ) 454*817466cbSJens Wiklander { 455*817466cbSJens Wiklander int ret; 456*817466cbSJens Wiklander 457*817466cbSJens Wiklander if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) 458*817466cbSJens Wiklander return( ret ); 459*817466cbSJens Wiklander 460*817466cbSJens Wiklander if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) 461*817466cbSJens Wiklander return( ret ); 462*817466cbSJens Wiklander 463*817466cbSJens Wiklander if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) 464*817466cbSJens Wiklander return( ret ); 465*817466cbSJens Wiklander 466*817466cbSJens Wiklander return( 0 ); 467*817466cbSJens Wiklander } 468*817466cbSJens Wiklander 469*817466cbSJens Wiklander int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, 470*817466cbSJens Wiklander size_t length, 471*817466cbSJens Wiklander const unsigned char *iv, 472*817466cbSJens Wiklander size_t iv_len, 473*817466cbSJens Wiklander const unsigned char *add, 474*817466cbSJens Wiklander size_t add_len, 475*817466cbSJens Wiklander const unsigned char *tag, 476*817466cbSJens Wiklander size_t tag_len, 477*817466cbSJens Wiklander const unsigned char *input, 478*817466cbSJens Wiklander unsigned char *output ) 479*817466cbSJens Wiklander { 480*817466cbSJens Wiklander int ret; 481*817466cbSJens Wiklander unsigned char check_tag[16]; 482*817466cbSJens Wiklander size_t i; 483*817466cbSJens Wiklander int diff; 484*817466cbSJens Wiklander 485*817466cbSJens Wiklander if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, 486*817466cbSJens Wiklander iv, iv_len, add, add_len, 487*817466cbSJens Wiklander input, output, tag_len, check_tag ) ) != 0 ) 488*817466cbSJens Wiklander { 489*817466cbSJens Wiklander return( ret ); 490*817466cbSJens Wiklander } 491*817466cbSJens Wiklander 492*817466cbSJens Wiklander /* Check tag in "constant-time" */ 493*817466cbSJens Wiklander for( diff = 0, i = 0; i < tag_len; i++ ) 494*817466cbSJens Wiklander diff |= tag[i] ^ check_tag[i]; 495*817466cbSJens Wiklander 496*817466cbSJens Wiklander if( diff != 0 ) 497*817466cbSJens Wiklander { 498*817466cbSJens Wiklander mbedtls_zeroize( output, length ); 499*817466cbSJens Wiklander return( MBEDTLS_ERR_GCM_AUTH_FAILED ); 500*817466cbSJens Wiklander } 501*817466cbSJens Wiklander 502*817466cbSJens Wiklander return( 0 ); 503*817466cbSJens Wiklander } 504*817466cbSJens Wiklander 505*817466cbSJens Wiklander void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) 506*817466cbSJens Wiklander { 507*817466cbSJens Wiklander mbedtls_cipher_free( &ctx->cipher_ctx ); 508*817466cbSJens Wiklander mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); 509*817466cbSJens Wiklander } 510*817466cbSJens Wiklander 511*817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 512*817466cbSJens Wiklander /* 513*817466cbSJens Wiklander * AES-GCM test vectors from: 514*817466cbSJens Wiklander * 515*817466cbSJens Wiklander * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip 516*817466cbSJens Wiklander */ 517*817466cbSJens Wiklander #define MAX_TESTS 6 518*817466cbSJens Wiklander 519*817466cbSJens Wiklander static const int key_index[MAX_TESTS] = 520*817466cbSJens Wiklander { 0, 0, 1, 1, 1, 1 }; 521*817466cbSJens Wiklander 522*817466cbSJens Wiklander static const unsigned char key[MAX_TESTS][32] = 523*817466cbSJens Wiklander { 524*817466cbSJens Wiklander { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 525*817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 526*817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 527*817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 528*817466cbSJens Wiklander { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 529*817466cbSJens Wiklander 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 530*817466cbSJens Wiklander 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 531*817466cbSJens Wiklander 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, 532*817466cbSJens Wiklander }; 533*817466cbSJens Wiklander 534*817466cbSJens Wiklander static const size_t iv_len[MAX_TESTS] = 535*817466cbSJens Wiklander { 12, 12, 12, 12, 8, 60 }; 536*817466cbSJens Wiklander 537*817466cbSJens Wiklander static const int iv_index[MAX_TESTS] = 538*817466cbSJens Wiklander { 0, 0, 1, 1, 1, 2 }; 539*817466cbSJens Wiklander 540*817466cbSJens Wiklander static const unsigned char iv[MAX_TESTS][64] = 541*817466cbSJens Wiklander { 542*817466cbSJens Wiklander { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 543*817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00 }, 544*817466cbSJens Wiklander { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 545*817466cbSJens Wiklander 0xde, 0xca, 0xf8, 0x88 }, 546*817466cbSJens Wiklander { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 547*817466cbSJens Wiklander 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, 548*817466cbSJens Wiklander 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 549*817466cbSJens Wiklander 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, 550*817466cbSJens Wiklander 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 551*817466cbSJens Wiklander 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 552*817466cbSJens Wiklander 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, 553*817466cbSJens Wiklander 0xa6, 0x37, 0xb3, 0x9b }, 554*817466cbSJens Wiklander }; 555*817466cbSJens Wiklander 556*817466cbSJens Wiklander static const size_t add_len[MAX_TESTS] = 557*817466cbSJens Wiklander { 0, 0, 0, 20, 20, 20 }; 558*817466cbSJens Wiklander 559*817466cbSJens Wiklander static const int add_index[MAX_TESTS] = 560*817466cbSJens Wiklander { 0, 0, 0, 1, 1, 1 }; 561*817466cbSJens Wiklander 562*817466cbSJens Wiklander static const unsigned char additional[MAX_TESTS][64] = 563*817466cbSJens Wiklander { 564*817466cbSJens Wiklander { 0x00 }, 565*817466cbSJens Wiklander { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 566*817466cbSJens Wiklander 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 567*817466cbSJens Wiklander 0xab, 0xad, 0xda, 0xd2 }, 568*817466cbSJens Wiklander }; 569*817466cbSJens Wiklander 570*817466cbSJens Wiklander static const size_t pt_len[MAX_TESTS] = 571*817466cbSJens Wiklander { 0, 16, 64, 60, 60, 60 }; 572*817466cbSJens Wiklander 573*817466cbSJens Wiklander static const int pt_index[MAX_TESTS] = 574*817466cbSJens Wiklander { 0, 0, 1, 1, 1, 1 }; 575*817466cbSJens Wiklander 576*817466cbSJens Wiklander static const unsigned char pt[MAX_TESTS][64] = 577*817466cbSJens Wiklander { 578*817466cbSJens Wiklander { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 579*817466cbSJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 580*817466cbSJens Wiklander { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 581*817466cbSJens Wiklander 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 582*817466cbSJens Wiklander 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 583*817466cbSJens Wiklander 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 584*817466cbSJens Wiklander 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 585*817466cbSJens Wiklander 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 586*817466cbSJens Wiklander 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 587*817466cbSJens Wiklander 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, 588*817466cbSJens Wiklander }; 589*817466cbSJens Wiklander 590*817466cbSJens Wiklander static const unsigned char ct[MAX_TESTS * 3][64] = 591*817466cbSJens Wiklander { 592*817466cbSJens Wiklander { 0x00 }, 593*817466cbSJens Wiklander { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 594*817466cbSJens Wiklander 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, 595*817466cbSJens Wiklander { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 596*817466cbSJens Wiklander 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 597*817466cbSJens Wiklander 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 598*817466cbSJens Wiklander 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 599*817466cbSJens Wiklander 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 600*817466cbSJens Wiklander 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 601*817466cbSJens Wiklander 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 602*817466cbSJens Wiklander 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, 603*817466cbSJens Wiklander { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 604*817466cbSJens Wiklander 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 605*817466cbSJens Wiklander 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 606*817466cbSJens Wiklander 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 607*817466cbSJens Wiklander 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 608*817466cbSJens Wiklander 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 609*817466cbSJens Wiklander 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 610*817466cbSJens Wiklander 0x3d, 0x58, 0xe0, 0x91 }, 611*817466cbSJens Wiklander { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 612*817466cbSJens Wiklander 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, 613*817466cbSJens Wiklander 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 614*817466cbSJens Wiklander 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, 615*817466cbSJens Wiklander 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 616*817466cbSJens Wiklander 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 617*817466cbSJens Wiklander 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, 618*817466cbSJens Wiklander 0xc2, 0x3f, 0x45, 0x98 }, 619*817466cbSJens Wiklander { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 620*817466cbSJens Wiklander 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, 621*817466cbSJens Wiklander 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 622*817466cbSJens Wiklander 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, 623*817466cbSJens Wiklander 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 624*817466cbSJens Wiklander 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 625*817466cbSJens Wiklander 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, 626*817466cbSJens Wiklander 0x4c, 0x34, 0xae, 0xe5 }, 627*817466cbSJens Wiklander { 0x00 }, 628*817466cbSJens Wiklander { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, 629*817466cbSJens Wiklander 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, 630*817466cbSJens Wiklander { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 631*817466cbSJens Wiklander 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 632*817466cbSJens Wiklander 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 633*817466cbSJens Wiklander 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 634*817466cbSJens Wiklander 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 635*817466cbSJens Wiklander 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 636*817466cbSJens Wiklander 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 637*817466cbSJens Wiklander 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, 638*817466cbSJens Wiklander { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 639*817466cbSJens Wiklander 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 640*817466cbSJens Wiklander 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 641*817466cbSJens Wiklander 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 642*817466cbSJens Wiklander 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 643*817466cbSJens Wiklander 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 644*817466cbSJens Wiklander 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 645*817466cbSJens Wiklander 0xcc, 0xda, 0x27, 0x10 }, 646*817466cbSJens Wiklander { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, 647*817466cbSJens Wiklander 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, 648*817466cbSJens Wiklander 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, 649*817466cbSJens Wiklander 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, 650*817466cbSJens Wiklander 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, 651*817466cbSJens Wiklander 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, 652*817466cbSJens Wiklander 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, 653*817466cbSJens Wiklander 0xa0, 0xf0, 0x62, 0xf7 }, 654*817466cbSJens Wiklander { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, 655*817466cbSJens Wiklander 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, 656*817466cbSJens Wiklander 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, 657*817466cbSJens Wiklander 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, 658*817466cbSJens Wiklander 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, 659*817466cbSJens Wiklander 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, 660*817466cbSJens Wiklander 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, 661*817466cbSJens Wiklander 0xe9, 0xb7, 0x37, 0x3b }, 662*817466cbSJens Wiklander { 0x00 }, 663*817466cbSJens Wiklander { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 664*817466cbSJens Wiklander 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, 665*817466cbSJens Wiklander { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 666*817466cbSJens Wiklander 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 667*817466cbSJens Wiklander 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 668*817466cbSJens Wiklander 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 669*817466cbSJens Wiklander 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 670*817466cbSJens Wiklander 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 671*817466cbSJens Wiklander 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 672*817466cbSJens Wiklander 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, 673*817466cbSJens Wiklander { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 674*817466cbSJens Wiklander 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 675*817466cbSJens Wiklander 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 676*817466cbSJens Wiklander 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 677*817466cbSJens Wiklander 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 678*817466cbSJens Wiklander 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 679*817466cbSJens Wiklander 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 680*817466cbSJens Wiklander 0xbc, 0xc9, 0xf6, 0x62 }, 681*817466cbSJens Wiklander { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 682*817466cbSJens Wiklander 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, 683*817466cbSJens Wiklander 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 684*817466cbSJens Wiklander 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, 685*817466cbSJens Wiklander 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 686*817466cbSJens Wiklander 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 687*817466cbSJens Wiklander 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, 688*817466cbSJens Wiklander 0xf4, 0x7c, 0x9b, 0x1f }, 689*817466cbSJens Wiklander { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 690*817466cbSJens Wiklander 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, 691*817466cbSJens Wiklander 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 692*817466cbSJens Wiklander 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, 693*817466cbSJens Wiklander 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 694*817466cbSJens Wiklander 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 695*817466cbSJens Wiklander 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, 696*817466cbSJens Wiklander 0x44, 0xae, 0x7e, 0x3f }, 697*817466cbSJens Wiklander }; 698*817466cbSJens Wiklander 699*817466cbSJens Wiklander static const unsigned char tag[MAX_TESTS * 3][16] = 700*817466cbSJens Wiklander { 701*817466cbSJens Wiklander { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 702*817466cbSJens Wiklander 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, 703*817466cbSJens Wiklander { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 704*817466cbSJens Wiklander 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, 705*817466cbSJens Wiklander { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 706*817466cbSJens Wiklander 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, 707*817466cbSJens Wiklander { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 708*817466cbSJens Wiklander 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, 709*817466cbSJens Wiklander { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 710*817466cbSJens Wiklander 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, 711*817466cbSJens Wiklander { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 712*817466cbSJens Wiklander 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, 713*817466cbSJens Wiklander { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, 714*817466cbSJens Wiklander 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, 715*817466cbSJens Wiklander { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 716*817466cbSJens Wiklander 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, 717*817466cbSJens Wiklander { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, 718*817466cbSJens Wiklander 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, 719*817466cbSJens Wiklander { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, 720*817466cbSJens Wiklander 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, 721*817466cbSJens Wiklander { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, 722*817466cbSJens Wiklander 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, 723*817466cbSJens Wiklander { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 724*817466cbSJens Wiklander 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, 725*817466cbSJens Wiklander { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 726*817466cbSJens Wiklander 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, 727*817466cbSJens Wiklander { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 728*817466cbSJens Wiklander 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, 729*817466cbSJens Wiklander { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 730*817466cbSJens Wiklander 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, 731*817466cbSJens Wiklander { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 732*817466cbSJens Wiklander 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, 733*817466cbSJens Wiklander { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 734*817466cbSJens Wiklander 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, 735*817466cbSJens Wiklander { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 736*817466cbSJens Wiklander 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, 737*817466cbSJens Wiklander }; 738*817466cbSJens Wiklander 739*817466cbSJens Wiklander int mbedtls_gcm_self_test( int verbose ) 740*817466cbSJens Wiklander { 741*817466cbSJens Wiklander mbedtls_gcm_context ctx; 742*817466cbSJens Wiklander unsigned char buf[64]; 743*817466cbSJens Wiklander unsigned char tag_buf[16]; 744*817466cbSJens Wiklander int i, j, ret; 745*817466cbSJens Wiklander mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; 746*817466cbSJens Wiklander 747*817466cbSJens Wiklander mbedtls_gcm_init( &ctx ); 748*817466cbSJens Wiklander 749*817466cbSJens Wiklander for( j = 0; j < 3; j++ ) 750*817466cbSJens Wiklander { 751*817466cbSJens Wiklander int key_len = 128 + 64 * j; 752*817466cbSJens Wiklander 753*817466cbSJens Wiklander for( i = 0; i < MAX_TESTS; i++ ) 754*817466cbSJens Wiklander { 755*817466cbSJens Wiklander if( verbose != 0 ) 756*817466cbSJens Wiklander mbedtls_printf( " AES-GCM-%3d #%d (%s): ", 757*817466cbSJens Wiklander key_len, i, "enc" ); 758*817466cbSJens Wiklander 759*817466cbSJens Wiklander mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); 760*817466cbSJens Wiklander 761*817466cbSJens Wiklander ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, 762*817466cbSJens Wiklander pt_len[i], 763*817466cbSJens Wiklander iv[iv_index[i]], iv_len[i], 764*817466cbSJens Wiklander additional[add_index[i]], add_len[i], 765*817466cbSJens Wiklander pt[pt_index[i]], buf, 16, tag_buf ); 766*817466cbSJens Wiklander 767*817466cbSJens Wiklander if( ret != 0 || 768*817466cbSJens Wiklander memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || 769*817466cbSJens Wiklander memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) 770*817466cbSJens Wiklander { 771*817466cbSJens Wiklander if( verbose != 0 ) 772*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 773*817466cbSJens Wiklander 774*817466cbSJens Wiklander return( 1 ); 775*817466cbSJens Wiklander } 776*817466cbSJens Wiklander 777*817466cbSJens Wiklander mbedtls_gcm_free( &ctx ); 778*817466cbSJens Wiklander 779*817466cbSJens Wiklander if( verbose != 0 ) 780*817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 781*817466cbSJens Wiklander 782*817466cbSJens Wiklander if( verbose != 0 ) 783*817466cbSJens Wiklander mbedtls_printf( " AES-GCM-%3d #%d (%s): ", 784*817466cbSJens Wiklander key_len, i, "dec" ); 785*817466cbSJens Wiklander 786*817466cbSJens Wiklander mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); 787*817466cbSJens Wiklander 788*817466cbSJens Wiklander ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, 789*817466cbSJens Wiklander pt_len[i], 790*817466cbSJens Wiklander iv[iv_index[i]], iv_len[i], 791*817466cbSJens Wiklander additional[add_index[i]], add_len[i], 792*817466cbSJens Wiklander ct[j * 6 + i], buf, 16, tag_buf ); 793*817466cbSJens Wiklander 794*817466cbSJens Wiklander if( ret != 0 || 795*817466cbSJens Wiklander memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || 796*817466cbSJens Wiklander memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) 797*817466cbSJens Wiklander { 798*817466cbSJens Wiklander if( verbose != 0 ) 799*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 800*817466cbSJens Wiklander 801*817466cbSJens Wiklander return( 1 ); 802*817466cbSJens Wiklander } 803*817466cbSJens Wiklander 804*817466cbSJens Wiklander mbedtls_gcm_free( &ctx ); 805*817466cbSJens Wiklander 806*817466cbSJens Wiklander if( verbose != 0 ) 807*817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 808*817466cbSJens Wiklander 809*817466cbSJens Wiklander if( verbose != 0 ) 810*817466cbSJens Wiklander mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", 811*817466cbSJens Wiklander key_len, i, "enc" ); 812*817466cbSJens Wiklander 813*817466cbSJens Wiklander mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); 814*817466cbSJens Wiklander 815*817466cbSJens Wiklander ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, 816*817466cbSJens Wiklander iv[iv_index[i]], iv_len[i], 817*817466cbSJens Wiklander additional[add_index[i]], add_len[i] ); 818*817466cbSJens Wiklander if( ret != 0 ) 819*817466cbSJens Wiklander { 820*817466cbSJens Wiklander if( verbose != 0 ) 821*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 822*817466cbSJens Wiklander 823*817466cbSJens Wiklander return( 1 ); 824*817466cbSJens Wiklander } 825*817466cbSJens Wiklander 826*817466cbSJens Wiklander if( pt_len[i] > 32 ) 827*817466cbSJens Wiklander { 828*817466cbSJens Wiklander size_t rest_len = pt_len[i] - 32; 829*817466cbSJens Wiklander ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); 830*817466cbSJens Wiklander if( ret != 0 ) 831*817466cbSJens Wiklander { 832*817466cbSJens Wiklander if( verbose != 0 ) 833*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 834*817466cbSJens Wiklander 835*817466cbSJens Wiklander return( 1 ); 836*817466cbSJens Wiklander } 837*817466cbSJens Wiklander 838*817466cbSJens Wiklander ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, 839*817466cbSJens Wiklander buf + 32 ); 840*817466cbSJens Wiklander if( ret != 0 ) 841*817466cbSJens Wiklander { 842*817466cbSJens Wiklander if( verbose != 0 ) 843*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 844*817466cbSJens Wiklander 845*817466cbSJens Wiklander return( 1 ); 846*817466cbSJens Wiklander } 847*817466cbSJens Wiklander } 848*817466cbSJens Wiklander else 849*817466cbSJens Wiklander { 850*817466cbSJens Wiklander ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); 851*817466cbSJens Wiklander if( ret != 0 ) 852*817466cbSJens Wiklander { 853*817466cbSJens Wiklander if( verbose != 0 ) 854*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 855*817466cbSJens Wiklander 856*817466cbSJens Wiklander return( 1 ); 857*817466cbSJens Wiklander } 858*817466cbSJens Wiklander } 859*817466cbSJens Wiklander 860*817466cbSJens Wiklander ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); 861*817466cbSJens Wiklander if( ret != 0 || 862*817466cbSJens Wiklander memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || 863*817466cbSJens Wiklander memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) 864*817466cbSJens Wiklander { 865*817466cbSJens Wiklander if( verbose != 0 ) 866*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 867*817466cbSJens Wiklander 868*817466cbSJens Wiklander return( 1 ); 869*817466cbSJens Wiklander } 870*817466cbSJens Wiklander 871*817466cbSJens Wiklander mbedtls_gcm_free( &ctx ); 872*817466cbSJens Wiklander 873*817466cbSJens Wiklander if( verbose != 0 ) 874*817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 875*817466cbSJens Wiklander 876*817466cbSJens Wiklander if( verbose != 0 ) 877*817466cbSJens Wiklander mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", 878*817466cbSJens Wiklander key_len, i, "dec" ); 879*817466cbSJens Wiklander 880*817466cbSJens Wiklander mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); 881*817466cbSJens Wiklander 882*817466cbSJens Wiklander ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, 883*817466cbSJens Wiklander iv[iv_index[i]], iv_len[i], 884*817466cbSJens Wiklander additional[add_index[i]], add_len[i] ); 885*817466cbSJens Wiklander if( ret != 0 ) 886*817466cbSJens Wiklander { 887*817466cbSJens Wiklander if( verbose != 0 ) 888*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 889*817466cbSJens Wiklander 890*817466cbSJens Wiklander return( 1 ); 891*817466cbSJens Wiklander } 892*817466cbSJens Wiklander 893*817466cbSJens Wiklander if( pt_len[i] > 32 ) 894*817466cbSJens Wiklander { 895*817466cbSJens Wiklander size_t rest_len = pt_len[i] - 32; 896*817466cbSJens Wiklander ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); 897*817466cbSJens Wiklander if( ret != 0 ) 898*817466cbSJens Wiklander { 899*817466cbSJens Wiklander if( verbose != 0 ) 900*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 901*817466cbSJens Wiklander 902*817466cbSJens Wiklander return( 1 ); 903*817466cbSJens Wiklander } 904*817466cbSJens Wiklander 905*817466cbSJens Wiklander ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, 906*817466cbSJens Wiklander buf + 32 ); 907*817466cbSJens Wiklander if( ret != 0 ) 908*817466cbSJens Wiklander { 909*817466cbSJens Wiklander if( verbose != 0 ) 910*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 911*817466cbSJens Wiklander 912*817466cbSJens Wiklander return( 1 ); 913*817466cbSJens Wiklander } 914*817466cbSJens Wiklander } 915*817466cbSJens Wiklander else 916*817466cbSJens Wiklander { 917*817466cbSJens Wiklander ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); 918*817466cbSJens Wiklander if( ret != 0 ) 919*817466cbSJens Wiklander { 920*817466cbSJens Wiklander if( verbose != 0 ) 921*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 922*817466cbSJens Wiklander 923*817466cbSJens Wiklander return( 1 ); 924*817466cbSJens Wiklander } 925*817466cbSJens Wiklander } 926*817466cbSJens Wiklander 927*817466cbSJens Wiklander ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); 928*817466cbSJens Wiklander if( ret != 0 || 929*817466cbSJens Wiklander memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || 930*817466cbSJens Wiklander memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) 931*817466cbSJens Wiklander { 932*817466cbSJens Wiklander if( verbose != 0 ) 933*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 934*817466cbSJens Wiklander 935*817466cbSJens Wiklander return( 1 ); 936*817466cbSJens Wiklander } 937*817466cbSJens Wiklander 938*817466cbSJens Wiklander mbedtls_gcm_free( &ctx ); 939*817466cbSJens Wiklander 940*817466cbSJens Wiklander if( verbose != 0 ) 941*817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 942*817466cbSJens Wiklander 943*817466cbSJens Wiklander } 944*817466cbSJens Wiklander } 945*817466cbSJens Wiklander 946*817466cbSJens Wiklander if( verbose != 0 ) 947*817466cbSJens Wiklander mbedtls_printf( "\n" ); 948*817466cbSJens Wiklander 949*817466cbSJens Wiklander return( 0 ); 950*817466cbSJens Wiklander } 951*817466cbSJens Wiklander 952*817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 953*817466cbSJens Wiklander 954*817466cbSJens Wiklander #endif /* MBEDTLS_GCM_C */ 955