Coverage Report

Created: 2024-11-21 07:03

/src/mbedtls/library/nist_kw.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes
3
 *  only
4
 *
5
 *  Copyright The Mbed TLS Contributors
6
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
7
 */
8
/*
9
 * Definition of Key Wrapping:
10
 * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
11
 * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
12
 * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
13
 *
14
 * Note: RFC 3394 defines different methodology for intermediate operations for
15
 * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
16
 */
17
18
#include "common.h"
19
20
#if defined(MBEDTLS_NIST_KW_C)
21
22
#include "mbedtls/nist_kw.h"
23
#include "mbedtls/platform_util.h"
24
#include "mbedtls/error.h"
25
#include "mbedtls/constant_time.h"
26
#include "constant_time_internal.h"
27
28
#include <stdint.h>
29
#include <string.h>
30
31
#include "mbedtls/platform.h"
32
33
#if !defined(MBEDTLS_NIST_KW_ALT)
34
35
0
#define KW_SEMIBLOCK_LENGTH    8
36
0
#define MIN_SEMIBLOCKS_COUNT   3
37
38
/*! The 64-bit default integrity check value (ICV) for KW mode. */
39
static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
40
/*! The 32-bit default integrity check value (ICV) for KWP mode. */
41
static const  unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
42
43
/*
44
 * Initialize context
45
 */
46
void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
47
20
{
48
20
    memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
49
20
}
50
51
int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
52
                           mbedtls_cipher_id_t cipher,
53
                           const unsigned char *key,
54
                           unsigned int keybits,
55
                           const int is_wrap)
56
13
{
57
13
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
58
13
    const mbedtls_cipher_info_t *cipher_info;
59
60
13
    cipher_info = mbedtls_cipher_info_from_values(cipher,
61
13
                                                  keybits,
62
13
                                                  MBEDTLS_MODE_ECB);
63
13
    if (cipher_info == NULL) {
64
0
        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
65
0
    }
66
67
13
    if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
68
0
        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
69
0
    }
70
71
    /*
72
     * SP 800-38F currently defines AES cipher as the only block cipher allowed:
73
     * "For KW and KWP, the underlying block cipher shall be approved, and the
74
     *  block size shall be 128 bits. Currently, the AES block cipher, with key
75
     *  lengths of 128, 192, or 256 bits, is the only block cipher that fits
76
     *  this profile."
77
     *  Currently we don't support other 128 bit block ciphers for key wrapping,
78
     *  such as Camellia and Aria.
79
     */
80
13
    if (cipher != MBEDTLS_CIPHER_ID_AES) {
81
0
        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
82
0
    }
83
84
13
    mbedtls_cipher_free(&ctx->cipher_ctx);
85
86
13
    if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
87
0
        return ret;
88
0
    }
89
90
13
    if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
91
13
                                     is_wrap ? MBEDTLS_ENCRYPT :
92
13
                                     MBEDTLS_DECRYPT)
93
13
         ) != 0) {
94
0
        return ret;
95
0
    }
96
97
13
    return 0;
98
13
}
99
100
/*
101
 * Free context
102
 */
103
void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
104
20
{
105
20
    if (ctx == NULL) {
106
0
        return;
107
0
    }
108
109
20
    mbedtls_cipher_free(&ctx->cipher_ctx);
110
20
    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
111
20
}
112
113
/*
114
 * Helper function for Xoring the uint64_t "t" with the encrypted A.
115
 * Defined in NIST SP 800-38F section 6.1
116
 */
117
static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
118
0
{
119
0
    size_t i = 0;
120
0
    for (i = 0; i < sizeof(t); i++) {
121
0
        A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
122
0
    }
123
0
}
124
125
/*
126
 * KW-AE as defined in SP 800-38F section 6.2
127
 * KWP-AE as defined in SP 800-38F section 6.3
128
 */
129
int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
130
                         mbedtls_nist_kw_mode_t mode,
131
                         const unsigned char *input, size_t in_len,
132
                         unsigned char *output, size_t *out_len, size_t out_size)
133
0
{
134
0
    int ret = 0;
135
0
    size_t semiblocks = 0;
136
0
    size_t s;
137
0
    size_t olen, padlen = 0;
138
0
    uint64_t t = 0;
139
0
    unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
140
0
    unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
141
142
0
    *out_len = 0;
143
    /*
144
     * Generate the String to work on
145
     */
146
0
    if (mode == MBEDTLS_KW_MODE_KW) {
147
0
        if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
148
0
            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
149
0
        }
150
151
        /*
152
         * According to SP 800-38F Table 1, the plaintext length for KW
153
         * must be between 2 to 2^54-1 semiblocks inclusive.
154
         */
155
0
        if (in_len < 16 ||
156
0
#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
157
0
            in_len > 0x1FFFFFFFFFFFFF8 ||
158
0
#endif
159
0
            in_len % KW_SEMIBLOCK_LENGTH != 0) {
160
0
            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
161
0
        }
162
163
0
        memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
164
0
        memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
165
0
    } else {
166
0
        if (in_len % 8 != 0) {
167
0
            padlen = (8 - (in_len % 8));
168
0
        }
169
170
0
        if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
171
0
            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
172
0
        }
173
174
        /*
175
         * According to SP 800-38F Table 1, the plaintext length for KWP
176
         * must be between 1 and 2^32-1 octets inclusive.
177
         */
178
0
        if (in_len < 1
179
0
#if SIZE_MAX > 0xFFFFFFFF
180
0
            || in_len > 0xFFFFFFFF
181
0
#endif
182
0
            ) {
183
0
            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
184
0
        }
185
186
0
        memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
187
0
        MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
188
0
                              KW_SEMIBLOCK_LENGTH / 2);
189
190
0
        memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
191
0
        memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
192
0
    }
193
0
    semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
194
195
0
    s = 6 * (semiblocks - 1);
196
197
0
    if (mode == MBEDTLS_KW_MODE_KWP
198
0
        && in_len <= KW_SEMIBLOCK_LENGTH) {
199
0
        memcpy(inbuff, output, 16);
200
0
        ret = mbedtls_cipher_update(&ctx->cipher_ctx,
201
0
                                    inbuff, 16, output, &olen);
202
0
        if (ret != 0) {
203
0
            goto cleanup;
204
0
        }
205
0
    } else {
206
0
        unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
207
0
        unsigned char *A = output;
208
209
        /*
210
         * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
211
         */
212
0
        if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
213
0
            ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
214
0
            goto cleanup;
215
0
        }
216
217
        /* Calculate intermediate values */
218
0
        for (t = 1; t <= s; t++) {
219
0
            memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
220
0
            memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
221
222
0
            ret = mbedtls_cipher_update(&ctx->cipher_ctx,
223
0
                                        inbuff, 16, outbuff, &olen);
224
0
            if (ret != 0) {
225
0
                goto cleanup;
226
0
            }
227
228
0
            memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
229
0
            calc_a_xor_t(A, t);
230
231
0
            memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
232
0
            R2 += KW_SEMIBLOCK_LENGTH;
233
0
            if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
234
0
                R2 = output + KW_SEMIBLOCK_LENGTH;
235
0
            }
236
0
        }
237
0
    }
238
239
0
    *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
240
241
0
cleanup:
242
243
0
    if (ret != 0) {
244
0
        memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
245
0
    }
246
0
    mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
247
0
    mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
248
249
0
    return ret;
250
0
}
251
252
/*
253
 * W-1 function as defined in RFC 3394 section 2.2.2
254
 * This function assumes the following:
255
 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
256
 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
257
 * 3. Minimal number of semiblocks is 3.
258
 * 4. A is a buffer to hold the first semiblock of the input buffer.
259
 */
260
static int unwrap(mbedtls_nist_kw_context *ctx,
261
                  const unsigned char *input, size_t semiblocks,
262
                  unsigned char A[KW_SEMIBLOCK_LENGTH],
263
                  unsigned char *output, size_t *out_len)
264
0
{
265
0
    int ret = 0;
266
0
    const size_t s = 6 * (semiblocks - 1);
267
0
    size_t olen;
268
0
    uint64_t t = 0;
269
0
    unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
270
0
    unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
271
0
    unsigned char *R = NULL;
272
0
    *out_len = 0;
273
274
0
    if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
275
0
        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
276
0
    }
277
278
0
    memcpy(A, input, KW_SEMIBLOCK_LENGTH);
279
0
    memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
280
0
    R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
281
282
    /* Calculate intermediate values */
283
0
    for (t = s; t >= 1; t--) {
284
0
        calc_a_xor_t(A, t);
285
286
0
        memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
287
0
        memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
288
289
0
        ret = mbedtls_cipher_update(&ctx->cipher_ctx,
290
0
                                    inbuff, 16, outbuff, &olen);
291
0
        if (ret != 0) {
292
0
            goto cleanup;
293
0
        }
294
295
0
        memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
296
297
        /* Set R as LSB64 of outbuff */
298
0
        memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
299
300
0
        if (R == output) {
301
0
            R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
302
0
        } else {
303
0
            R -= KW_SEMIBLOCK_LENGTH;
304
0
        }
305
0
    }
306
307
0
    *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
308
309
0
cleanup:
310
0
    if (ret != 0) {
311
0
        memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
312
0
    }
313
0
    mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
314
0
    mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
315
316
0
    return ret;
317
0
}
318
319
/*
320
 * KW-AD as defined in SP 800-38F section 6.2
321
 * KWP-AD as defined in SP 800-38F section 6.3
322
 */
323
int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
324
                           mbedtls_nist_kw_mode_t mode,
325
                           const unsigned char *input, size_t in_len,
326
                           unsigned char *output, size_t *out_len, size_t out_size)
327
0
{
328
0
    int ret = 0;
329
0
    size_t olen;
330
0
    unsigned char A[KW_SEMIBLOCK_LENGTH];
331
0
    int diff;
332
333
0
    *out_len = 0;
334
0
    if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
335
0
        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
336
0
    }
337
338
0
    if (mode == MBEDTLS_KW_MODE_KW) {
339
        /*
340
         * According to SP 800-38F Table 1, the ciphertext length for KW
341
         * must be between 3 to 2^54 semiblocks inclusive.
342
         */
343
0
        if (in_len < 24 ||
344
0
#if SIZE_MAX > 0x200000000000000
345
0
            in_len > 0x200000000000000 ||
346
0
#endif
347
0
            in_len % KW_SEMIBLOCK_LENGTH != 0) {
348
0
            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
349
0
        }
350
351
0
        ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
352
0
                     A, output, out_len);
353
0
        if (ret != 0) {
354
0
            goto cleanup;
355
0
        }
356
357
        /* Check ICV in "constant-time" */
358
0
        diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
359
360
0
        if (diff != 0) {
361
0
            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
362
0
            goto cleanup;
363
0
        }
364
365
0
    } else if (mode == MBEDTLS_KW_MODE_KWP) {
366
0
        size_t padlen = 0;
367
0
        uint32_t Plen;
368
        /*
369
         * According to SP 800-38F Table 1, the ciphertext length for KWP
370
         * must be between 2 to 2^29 semiblocks inclusive.
371
         */
372
0
        if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
373
0
#if SIZE_MAX > 0x100000000
374
0
            in_len > 0x100000000 ||
375
0
#endif
376
0
            in_len % KW_SEMIBLOCK_LENGTH != 0) {
377
0
            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
378
0
        }
379
380
0
        if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
381
0
            unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
382
0
            ret = mbedtls_cipher_update(&ctx->cipher_ctx,
383
0
                                        input, 16, outbuff, &olen);
384
0
            if (ret != 0) {
385
0
                goto cleanup;
386
0
            }
387
388
0
            memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
389
0
            memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
390
0
            mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
391
0
            *out_len = KW_SEMIBLOCK_LENGTH;
392
0
        } else {
393
            /* in_len >=  KW_SEMIBLOCK_LENGTH * 3 */
394
0
            ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
395
0
                         A, output, out_len);
396
0
            if (ret != 0) {
397
0
                goto cleanup;
398
0
            }
399
0
        }
400
401
        /* Check ICV in "constant-time" */
402
0
        diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
403
404
0
        if (diff != 0) {
405
0
            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
406
0
        }
407
408
0
        Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
409
410
        /*
411
         * Plen is the length of the plaintext, when the input is valid.
412
         * If Plen is larger than the plaintext and padding, padlen will be
413
         * larger than 8, because of the type wrap around.
414
         */
415
0
        padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
416
0
        ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
417
0
                                  MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
418
0
        padlen &= 7;
419
420
        /* Check padding in "constant-time" */
421
0
        const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
422
0
        diff = mbedtls_ct_memcmp_partial(
423
0
            &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
424
0
            KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
425
426
0
        if (diff != 0) {
427
0
            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
428
0
        }
429
430
0
        if (ret != 0) {
431
0
            goto cleanup;
432
0
        }
433
0
        memset(output + Plen, 0, padlen);
434
0
        *out_len = Plen;
435
0
    } else {
436
0
        ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
437
0
        goto cleanup;
438
0
    }
439
440
0
cleanup:
441
0
    if (ret != 0) {
442
0
        memset(output, 0, *out_len);
443
0
        *out_len = 0;
444
0
    }
445
446
0
    mbedtls_platform_zeroize(&diff, sizeof(diff));
447
0
    mbedtls_platform_zeroize(A, sizeof(A));
448
449
0
    return ret;
450
0
}
451
452
#endif /* !MBEDTLS_NIST_KW_ALT */
453
454
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
455
456
/*
457
 * Test vectors taken from NIST
458
 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
459
 */
460
static const unsigned int key_len[] = {
461
    16,
462
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
463
    24,
464
    32
465
#endif
466
};
467
468
static const unsigned char kw_key[][32] = {
469
    { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
470
      0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
471
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
472
    { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
473
      0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
474
      0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
475
    { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
476
      0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
477
      0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
478
      0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
479
#endif
480
};
481
482
static const unsigned char kw_msg[][40] = {
483
    { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
484
      0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
485
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
486
    { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
487
      0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
488
      0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
489
      0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
490
      0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
491
    { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
492
      0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
493
      0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
494
#endif
495
};
496
497
static const size_t kw_msg_len[] = {
498
    16,
499
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
500
    40,
501
    24
502
#endif
503
};
504
static const size_t kw_out_len[] = {
505
    24,
506
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
507
    48,
508
    32
509
#endif
510
};
511
static const unsigned char kw_res[][48] = {
512
    { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
513
      0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
514
      0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
515
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
516
    { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
517
      0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
518
      0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
519
      0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
520
      0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
521
      0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
522
    { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
523
      0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
524
      0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
525
      0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
526
#endif
527
};
528
529
static const unsigned char kwp_key[][32] = {
530
    { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
531
      0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
532
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
533
    { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
534
      0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
535
      0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
536
    { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
537
      0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
538
      0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
539
      0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
540
#endif
541
};
542
543
static const unsigned char kwp_msg[][31] = {
544
    { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
545
      0x96 },
546
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
547
    { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
548
      0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
549
      0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
550
      0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
551
    { 0xd1 }
552
#endif
553
};
554
static const size_t kwp_msg_len[] = {
555
    9,
556
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
557
    31,
558
    1
559
#endif
560
};
561
562
static const unsigned char kwp_res[][48] = {
563
    { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
564
      0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
565
      0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
566
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
567
    { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
568
      0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
569
      0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
570
      0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
571
      0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
572
    { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
573
      0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4  }
574
#endif
575
};
576
static const size_t kwp_out_len[] = {
577
    24,
578
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
579
    40,
580
    16
581
#endif
582
};
583
584
int mbedtls_nist_kw_self_test(int verbose)
585
0
{
586
0
    mbedtls_nist_kw_context ctx;
587
0
    unsigned char out[48];
588
0
    size_t olen;
589
0
    int i;
590
0
    int ret = 0;
591
0
    mbedtls_nist_kw_init(&ctx);
592
593
    /*
594
     * KW mode
595
     */
596
0
    {
597
0
        static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
598
599
0
        for (i = 0; i < num_tests; i++) {
600
0
            if (verbose != 0) {
601
0
                mbedtls_printf("  KW-AES-%u ", (unsigned int) key_len[i] * 8);
602
0
            }
603
604
0
            ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
605
0
                                         kw_key[i], key_len[i] * 8, 1);
606
0
            if (ret != 0) {
607
0
                if (verbose != 0) {
608
0
                    mbedtls_printf("  KW: setup failed ");
609
0
                }
610
611
0
                goto end;
612
0
            }
613
614
0
            ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
615
0
                                       kw_msg_len[i], out, &olen, sizeof(out));
616
0
            if (ret != 0 || kw_out_len[i] != olen ||
617
0
                memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
618
0
                if (verbose != 0) {
619
0
                    mbedtls_printf("failed. ");
620
0
                }
621
622
0
                ret = 1;
623
0
                goto end;
624
0
            }
625
626
0
            if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
627
0
                                              kw_key[i], key_len[i] * 8, 0))
628
0
                != 0) {
629
0
                if (verbose != 0) {
630
0
                    mbedtls_printf("  KW: setup failed ");
631
0
                }
632
633
0
                goto end;
634
0
            }
635
636
0
            ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
637
0
                                         out, olen, out, &olen, sizeof(out));
638
639
0
            if (ret != 0 || olen != kw_msg_len[i] ||
640
0
                memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
641
0
                if (verbose != 0) {
642
0
                    mbedtls_printf("failed\n");
643
0
                }
644
645
0
                ret = 1;
646
0
                goto end;
647
0
            }
648
649
0
            if (verbose != 0) {
650
0
                mbedtls_printf(" passed\n");
651
0
            }
652
0
        }
653
0
    }
654
655
    /*
656
     * KWP mode
657
     */
658
0
    {
659
0
        static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
660
661
0
        for (i = 0; i < num_tests; i++) {
662
0
            olen = sizeof(out);
663
0
            if (verbose != 0) {
664
0
                mbedtls_printf("  KWP-AES-%u ", (unsigned int) key_len[i] * 8);
665
0
            }
666
667
0
            ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
668
0
                                         key_len[i] * 8, 1);
669
0
            if (ret  != 0) {
670
0
                if (verbose != 0) {
671
0
                    mbedtls_printf("  KWP: setup failed ");
672
0
                }
673
674
0
                goto end;
675
0
            }
676
0
            ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
677
0
                                       kwp_msg_len[i], out, &olen, sizeof(out));
678
679
0
            if (ret != 0 || kwp_out_len[i] != olen ||
680
0
                memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
681
0
                if (verbose != 0) {
682
0
                    mbedtls_printf("failed. ");
683
0
                }
684
685
0
                ret = 1;
686
0
                goto end;
687
0
            }
688
689
0
            if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
690
0
                                              kwp_key[i], key_len[i] * 8, 0))
691
0
                != 0) {
692
0
                if (verbose != 0) {
693
0
                    mbedtls_printf("  KWP: setup failed ");
694
0
                }
695
696
0
                goto end;
697
0
            }
698
699
0
            ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
700
0
                                         olen, out, &olen, sizeof(out));
701
702
0
            if (ret != 0 || olen != kwp_msg_len[i] ||
703
0
                memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
704
0
                if (verbose != 0) {
705
0
                    mbedtls_printf("failed. ");
706
0
                }
707
708
0
                ret = 1;
709
0
                goto end;
710
0
            }
711
712
0
            if (verbose != 0) {
713
0
                mbedtls_printf(" passed\n");
714
0
            }
715
0
        }
716
0
    }
717
0
end:
718
0
    mbedtls_nist_kw_free(&ctx);
719
720
0
    if (verbose != 0) {
721
0
        mbedtls_printf("\n");
722
0
    }
723
724
0
    return ret;
725
0
}
726
727
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
728
729
#endif /* MBEDTLS_NIST_KW_C */