gcm.c 29.9 KB
Newer Older
1 2 3
/*
 *  NIST SP800-38D compliant GCM implementation
 *
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
4
 *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
22

23
/*
24 25 26 27 28 29 30
 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
 *
 * See also:
 * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf
 *
 * We use the algorithm described as Shoup's method with 4-bit tables in
 * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory.
31
 */
32

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
33
#if !defined(MBEDTLS_CONFIG_FILE)
34
#include "mbedtls/config.h"
35
#else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
36
#include MBEDTLS_CONFIG_FILE
37
#endif
38

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
39
#if defined(MBEDTLS_GCM_C)
40

41
#include "mbedtls/gcm.h"
42

43 44
#include <string.h>

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
45
#if defined(MBEDTLS_AESNI_C)
46
#include "mbedtls/aesni.h"
47 48
#endif

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
49 50
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_PLATFORM_C)
51
#include "mbedtls/platform.h"
52
#else
53
#include <stdio.h>
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
54 55 56
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
57

58 59 60
/*
 * 32-bit integer manipulation macros (big endian)
 */
61 62
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i)                            \
63
{                                                       \
64 65 66 67
    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
        | ( (uint32_t) (b)[(i) + 3]       );            \
68 69 70
}
#endif

71 72
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i)                            \
73 74 75 76 77 78 79 80
{                                                       \
    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
}
#endif

81
/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
82
static void mbedtls_zeroize( void *v, size_t n ) {
83 84 85
    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}

86 87 88 89 90 91 92 93
/*
 * Initialize a context
 */
void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
{
    memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
}

94 95 96 97 98 99 100 101
/*
 * Precompute small multiples of H, that is set
 *      HH[i] || HL[i] = H times i,
 * where i is seen as a field element as in [MGV], ie high-order bits
 * correspond to low powers of P. The result is stored in the same way, that
 * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
 * corresponds to P^127.
 */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
102
static int gcm_gen_table( mbedtls_gcm_context *ctx )
103
{
104
    int ret, i, j;
105 106 107
    uint64_t hi, lo;
    uint64_t vl, vh;
    unsigned char h[16];
108
    size_t olen = 0;
109

110
    memset( h, 0, 16 );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
111
    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
112
        return( ret );
113

114
    /* pack h as two 64-bits ints, big-endian */
115 116
    GET_UINT32_BE( hi, h,  0  );
    GET_UINT32_BE( lo, h,  4  );
117 118
    vh = (uint64_t) hi << 32 | lo;

119 120
    GET_UINT32_BE( hi, h,  8  );
    GET_UINT32_BE( lo, h,  12 );
121
    vl = (uint64_t) hi << 32 | lo;
122

123
    /* 8 = 1000 corresponds to 1 in GF(2^128) */
124 125 126
    ctx->HL[8] = vl;
    ctx->HH[8] = vh;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
127
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
128
    /* With CLMUL support, we need only h, not the rest of the table */
129
    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
130 131 132 133 134 135 136
        return( 0 );
#endif

    /* 0 corresponds to 0 in GF(2^128) */
    ctx->HH[0] = 0;
    ctx->HL[0] = 0;

137 138
    for( i = 4; i > 0; i >>= 1 )
    {
Paul Bakker's avatar
Paul Bakker committed
139
        uint32_t T = ( vl & 1 ) * 0xe1000000U;
140 141 142 143 144 145 146
        vl  = ( vh << 63 ) | ( vl >> 1 );
        vh  = ( vh >> 1 ) ^ ( (uint64_t) T << 32);

        ctx->HL[i] = vl;
        ctx->HH[i] = vh;
    }

147
    for( i = 2; i <= 8; i *= 2 )
148 149 150 151 152 153 154 155 156 157
    {
        uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
        vh = *HiH;
        vl = *HiL;
        for( j = 1; j < i; j++ )
        {
            HiH[j] = vh ^ ctx->HH[j];
            HiL[j] = vl ^ ctx->HL[j];
        }
    }
158 159

    return( 0 );
160 161
}

162 163 164
int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
                        mbedtls_cipher_id_t cipher,
                        const unsigned char *key,
165
                        unsigned int keybits )
166 167
{
    int ret;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
168
    const mbedtls_cipher_info_t *cipher_info;
169

170
    cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
171
    if( cipher_info == NULL )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
172
        return( MBEDTLS_ERR_GCM_BAD_INPUT );
173

174
    if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
175
        return( MBEDTLS_ERR_GCM_BAD_INPUT );
176

177 178
    mbedtls_cipher_free( &ctx->cipher_ctx );

179
    if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
180 181
        return( ret );

182
    if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
183
                               MBEDTLS_ENCRYPT ) ) != 0 )
184 185 186 187 188 189
    {
        return( ret );
    }

    if( ( ret = gcm_gen_table( ctx ) ) != 0 )
        return( ret );
190 191 192 193

    return( 0 );
}

194 195 196 197 198
/*
 * Shoup's method for multiplication use this table with
 *      last4[x] = x times P^128
 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
 */
199 200 201 202 203 204 205 206
static const uint64_t last4[16] =
{
    0x0000, 0x1c20, 0x3840, 0x2460,
    0x7080, 0x6ca0, 0x48c0, 0x54e0,
    0xe100, 0xfd20, 0xd940, 0xc560,
    0x9180, 0x8da0, 0xa9c0, 0xb5e0
};

207 208 209 210
/*
 * Sets output to x times H using the precomputed tables.
 * x and output are seen as elements of GF(2^128) as in [MGV].
 */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
211
static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
212
                      unsigned char output[16] )
213 214 215 216 217
{
    int i = 0;
    unsigned char lo, hi, rem;
    uint64_t zh, zl;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
218
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
219
    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
220 221 222 223 224 225 226
        unsigned char h[16];

        PUT_UINT32_BE( ctx->HH[8] >> 32, h,  0 );
        PUT_UINT32_BE( ctx->HH[8],       h,  4 );
        PUT_UINT32_BE( ctx->HL[8] >> 32, h,  8 );
        PUT_UINT32_BE( ctx->HL[8],       h, 12 );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
227
        mbedtls_aesni_gcm_mult( output, x, h );
228 229
        return;
    }
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
230
#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
231

232 233 234 235 236 237 238 239 240 241 242 243
    lo = x[15] & 0xf;

    zh = ctx->HH[lo];
    zl = ctx->HL[lo];

    for( i = 15; i >= 0; i-- )
    {
        lo = x[i] & 0xf;
        hi = x[i] >> 4;

        if( i != 15 )
        {
244
            rem = (unsigned char) zl & 0xf;
245 246 247 248 249 250 251 252
            zl = ( zh << 60 ) | ( zl >> 4 );
            zh = ( zh >> 4 );
            zh ^= (uint64_t) last4[rem] << 48;
            zh ^= ctx->HH[lo];
            zl ^= ctx->HL[lo];

        }

253
        rem = (unsigned char) zl & 0xf;
254 255 256 257 258 259 260
        zl = ( zh << 60 ) | ( zl >> 4 );
        zh = ( zh >> 4 );
        zh ^= (uint64_t) last4[rem] << 48;
        zh ^= ctx->HH[hi];
        zl ^= ctx->HL[hi];
    }

261 262 263 264
    PUT_UINT32_BE( zh >> 32, output, 0 );
    PUT_UINT32_BE( zh, output, 4 );
    PUT_UINT32_BE( zl >> 32, output, 8 );
    PUT_UINT32_BE( zl, output, 12 );
265 266
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
267
int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
268 269 270 271 272
                int mode,
                const unsigned char *iv,
                size_t iv_len,
                const unsigned char *add,
                size_t add_len )
273
{
274
    int ret;
275 276 277
    unsigned char work_buf[16];
    size_t i;
    const unsigned char *p;
278
    size_t use_len, olen = 0;
279

280 281 282 283
    /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
    if( ( (uint64_t) iv_len  ) >> 61 != 0 ||
        ( (uint64_t) add_len ) >> 61 != 0 )
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
284
        return( MBEDTLS_ERR_GCM_BAD_INPUT );
285 286
    }

287 288 289
    memset( ctx->y, 0x00, sizeof(ctx->y) );
    memset( ctx->buf, 0x00, sizeof(ctx->buf) );

290
    ctx->mode = mode;
291 292
    ctx->len = 0;
    ctx->add_len = 0;
293 294 295

    if( iv_len == 12 )
    {
296 297
        memcpy( ctx->y, iv, iv_len );
        ctx->y[15] = 1;
298 299 300 301
    }
    else
    {
        memset( work_buf, 0x00, 16 );
302
        PUT_UINT32_BE( iv_len * 8, work_buf, 12 );
303 304 305 306 307 308

        p = iv;
        while( iv_len > 0 )
        {
            use_len = ( iv_len < 16 ) ? iv_len : 16;

309
            for( i = 0; i < use_len; i++ )
310
                ctx->y[i] ^= p[i];
311

312
            gcm_mult( ctx, ctx->y, ctx->y );
313 314 315 316 317

            iv_len -= use_len;
            p += use_len;
        }

318
        for( i = 0; i < 16; i++ )
319
            ctx->y[i] ^= work_buf[i];
320

321
        gcm_mult( ctx, ctx->y, ctx->y );
322 323
    }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
324
    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
325 326 327 328
                             &olen ) ) != 0 )
    {
        return( ret );
    }
329

330
    ctx->add_len = add_len;
331 332 333 334 335
    p = add;
    while( add_len > 0 )
    {
        use_len = ( add_len < 16 ) ? add_len : 16;

336
        for( i = 0; i < use_len; i++ )
337
            ctx->buf[i] ^= p[i];
338

339
        gcm_mult( ctx, ctx->buf, ctx->buf );
340 341 342 343 344

        add_len -= use_len;
        p += use_len;
    }

345 346 347
    return( 0 );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
348
int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
349 350 351 352
                size_t length,
                const unsigned char *input,
                unsigned char *output )
{
353
    int ret;
354 355 356 357
    unsigned char ectr[16];
    size_t i;
    const unsigned char *p;
    unsigned char *out_p = output;
358
    size_t use_len, olen = 0;
359 360

    if( output > input && (size_t) ( output - input ) < length )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
361
        return( MBEDTLS_ERR_GCM_BAD_INPUT );
362

363 364 365
    /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
     * Also check for possible overflow */
    if( ctx->len + length < ctx->len ||
366
        (uint64_t) ctx->len + length > 0x03FFFFE0ull )
367
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
368
        return( MBEDTLS_ERR_GCM_BAD_INPUT );
369 370
    }

371 372
    ctx->len += length;

373 374 375 376 377
    p = input;
    while( length > 0 )
    {
        use_len = ( length < 16 ) ? length : 16;

378
        for( i = 16; i > 12; i-- )
379
            if( ++ctx->y[i - 1] != 0 )
380
                break;
381

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
382
        if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
383 384 385 386
                                   &olen ) ) != 0 )
        {
            return( ret );
        }
387

388
        for( i = 0; i < use_len; i++ )
389
        {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
390
            if( ctx->mode == MBEDTLS_GCM_DECRYPT )
391
                ctx->buf[i] ^= p[i];
392
            out_p[i] = ectr[i] ^ p[i];
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
393
            if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
394
                ctx->buf[i] ^= out_p[i];
395
        }
396

397
        gcm_mult( ctx, ctx->buf, ctx->buf );
398

399 400 401 402 403
        length -= use_len;
        p += use_len;
        out_p += use_len;
    }

404 405 406
    return( 0 );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
407
int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
408 409 410 411 412 413 414 415
                unsigned char *tag,
                size_t tag_len )
{
    unsigned char work_buf[16];
    size_t i;
    uint64_t orig_len = ctx->len * 8;
    uint64_t orig_add_len = ctx->add_len * 8;

416
    if( tag_len > 16 || tag_len < 4 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
417
        return( MBEDTLS_ERR_GCM_BAD_INPUT );
418

419 420
    if( tag_len != 0 )
        memcpy( tag, ctx->base_ectr, tag_len );
421

422 423 424 425
    if( orig_len || orig_add_len )
    {
        memset( work_buf, 0x00, 16 );

Paul Bakker's avatar
Paul Bakker committed
426 427 428 429
        PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0  );
        PUT_UINT32_BE( ( orig_add_len       ), work_buf, 4  );
        PUT_UINT32_BE( ( orig_len     >> 32 ), work_buf, 8  );
        PUT_UINT32_BE( ( orig_len           ), work_buf, 12 );
430

431
        for( i = 0; i < 16; i++ )
432
            ctx->buf[i] ^= work_buf[i];
433

434
        gcm_mult( ctx, ctx->buf, ctx->buf );
435

436
        for( i = 0; i < tag_len; i++ )
437
            tag[i] ^= ctx->buf[i];
438 439 440 441 442
    }

    return( 0 );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
443
int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
444 445 446 447 448 449 450 451 452 453 454 455 456
                       int mode,
                       size_t length,
                       const unsigned char *iv,
                       size_t iv_len,
                       const unsigned char *add,
                       size_t add_len,
                       const unsigned char *input,
                       unsigned char *output,
                       size_t tag_len,
                       unsigned char *tag )
{
    int ret;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
457
    if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
458 459
        return( ret );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
460
    if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
461 462
        return( ret );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
463
    if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
464 465 466 467 468
        return( ret );

    return( 0 );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
469
int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
470 471 472 473 474
                      size_t length,
                      const unsigned char *iv,
                      size_t iv_len,
                      const unsigned char *add,
                      size_t add_len,
475
                      const unsigned char *tag,
476 477 478 479
                      size_t tag_len,
                      const unsigned char *input,
                      unsigned char *output )
{
480
    int ret;
481
    unsigned char check_tag[16];
482 483
    size_t i;
    int diff;
484

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
485
    if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
486 487 488 489 490
                                   iv, iv_len, add, add_len,
                                   input, output, tag_len, check_tag ) ) != 0 )
    {
        return( ret );
    }
491

492 493 494
    /* Check tag in "constant-time" */
    for( diff = 0, i = 0; i < tag_len; i++ )
        diff |= tag[i] ^ check_tag[i];
495

496 497
    if( diff != 0 )
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
498 499
        mbedtls_zeroize( output, length );
        return( MBEDTLS_ERR_GCM_AUTH_FAILED );
500
    }
501

502
    return( 0 );
503 504
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
505
void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
506
{
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
507 508
    mbedtls_cipher_free( &ctx->cipher_ctx );
    mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
509 510
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
511
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
512
/*
513
 * AES-GCM test vectors from:
514 515 516 517 518
 *
 * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
 */
#define MAX_TESTS   6

519
static const int key_index[MAX_TESTS] =
520 521
    { 0, 0, 1, 1, 1, 1 };

522
static const unsigned char key[MAX_TESTS][32] =
523 524 525 526 527 528 529 530
{
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
    { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
      0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
      0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
531
      0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
532 533
};

534
static const size_t iv_len[MAX_TESTS] =
535 536
    { 12, 12, 12, 12, 8, 60 };

537
static const int iv_index[MAX_TESTS] =
538 539
    { 0, 0, 1, 1, 1, 2 };

540
static const unsigned char iv[MAX_TESTS][64] =
541 542 543 544 545 546
{
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00 },
    { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
      0xde, 0xca, 0xf8, 0x88 },
    { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5,
547
      0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa,
548
      0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1,
549
      0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28,
550
      0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39,
551
      0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54,
552
      0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
553
      0xa6, 0x37, 0xb3, 0x9b },
554 555
};

556
static const size_t add_len[MAX_TESTS] =
557 558
    { 0, 0, 0, 20, 20, 20 };

559
static const int add_index[MAX_TESTS] =
560 561
    { 0, 0, 0, 1, 1, 1 };

562
static const unsigned char additional[MAX_TESTS][64] =
563 564 565
{
    { 0x00 },
    { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
566
      0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
567 568 569
      0xab, 0xad, 0xda, 0xd2 },
};

570
static const size_t pt_len[MAX_TESTS] =
571 572
    { 0, 16, 64, 60, 60, 60 };

573
static const int pt_index[MAX_TESTS] =
574 575
    { 0, 0, 1, 1, 1, 1 };

576
static const unsigned char pt[MAX_TESTS][64] =
577 578 579 580 581 582 583 584 585 586 587 588 589
{
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
    { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
      0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
      0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
      0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
      0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
      0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
      0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
      0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
};

590
static const unsigned char ct[MAX_TESTS * 3][64] =
591 592 593 594 595
{
    { 0x00 },
    { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
      0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
    { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
596
      0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
597
      0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
598
      0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
599
      0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
600
      0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
601 602 603
      0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
      0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 },
    { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
604
      0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
605
      0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
606
      0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
607
      0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
608
      0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
609 610 611
      0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
      0x3d, 0x58, 0xe0, 0x91 },
    { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a,
612
      0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55,
613
      0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8,
614
      0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23,
615
      0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2,
616
      0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42,
617 618 619
      0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
      0xc2, 0x3f, 0x45, 0x98 },
    { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6,
620
      0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94,
621
      0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8,
622
      0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7,
623
      0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90,
624
      0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
625 626 627 628
      0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
      0x4c, 0x34, 0xae, 0xe5 },
    { 0x00 },
    { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
629
      0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
630
    { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
631
      0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
632
      0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
633
      0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
634
      0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
635
      0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
636 637 638
      0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
      0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 },
    { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
639
      0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
640
      0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
641 642 643
      0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
      0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
      0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
644
      0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
645
      0xcc, 0xda, 0x27, 0x10 },
646
    { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54,
647
      0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8,
648
      0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f,
649
      0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57,
650
      0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75,
651
      0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9,
652
      0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
653
      0xa0, 0xf0, 0x62, 0xf7 },
654
    { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c,
655
      0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff,
656
      0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef,
657
      0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45,
658
      0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9,
659
      0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3,
660
      0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
661
      0xe9, 0xb7, 0x37, 0x3b },
662
    { 0x00 },
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
    { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
      0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 },
    { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
      0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
      0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
      0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
      0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
      0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
      0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
      0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad },
    { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
      0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
      0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
      0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
      0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
      0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
      0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
      0xbc, 0xc9, 0xf6, 0x62 },
681
    { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32,
682
      0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb,
683
      0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa,
684
      0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0,
685
      0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0,
686
      0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78,
687
      0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
688
      0xf4, 0x7c, 0x9b, 0x1f },
689
    { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1,
690
      0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20,
691
      0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19,
692
      0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4,
693
      0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45,
694
      0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
695
      0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
696
      0x44, 0xae, 0x7e, 0x3f },
697 698
};

699
static const unsigned char tag[MAX_TESTS * 3][16] =
700 701 702 703 704 705
{
    { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
      0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
    { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
      0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
    { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
706
      0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
707 708 709 710 711 712 713 714 715
    { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
      0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
    { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85,
      0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
    { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
      0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
    { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
      0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
    { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
716
      0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
717 718 719
    { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
      0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
    { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
720
      0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
721
    { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24,
722
      0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 },
723
    { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb,
724
      0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 },
725
    { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
726
      0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
727
    { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
728
      0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
729
    { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
730
      0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
731
    { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
732
      0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
733
    { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4,
734
      0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
735
    { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
736
      0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
737 738
};

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
739
int mbedtls_gcm_self_test( int verbose )
740
{
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
741
    mbedtls_gcm_context ctx;
742 743 744
    unsigned char buf[64];
    unsigned char tag_buf[16];
    int i, j, ret;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
745
    mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
746

747 748
    mbedtls_gcm_init( &ctx );

749 750 751 752 753 754
    for( j = 0; j < 3; j++ )
    {
        int key_len = 128 + 64 * j;

        for( i = 0; i < MAX_TESTS; i++ )
        {
755
            if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
756
                mbedtls_printf( "  AES-GCM-%3d #%d (%s): ",
757
                                 key_len, i, "enc" );
758

759
            mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len );
760

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
761
            ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
762 763 764 765 766 767 768 769 770 771
                                     pt_len[i],
                                     iv[iv_index[i]], iv_len[i],
                                     additional[add_index[i]], add_len[i],
                                     pt[pt_index[i]], buf, 16, tag_buf );

            if( ret != 0 ||
                memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
                memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
            {
                if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
772
                    mbedtls_printf( "failed\n" );
773 774 775 776

                return( 1 );
            }

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
777
            mbedtls_gcm_free( &ctx );
778

779
            if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
780
                mbedtls_printf( "passed\n" );
781

782
            if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
783
                mbedtls_printf( "  AES-GCM-%3d #%d (%s): ",
784
                                 key_len, i, "dec" );