RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

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