Coverage Report

Created: 2025-07-01 06:54

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