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 #define KW_SEMIBLOCK_LENGTH 8
36 #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 */
mbedtls_nist_kw_init(mbedtls_nist_kw_context * ctx)46 void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
47 {
48 memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
49 }
50
mbedtls_nist_kw_setkey(mbedtls_nist_kw_context * ctx,mbedtls_cipher_id_t cipher,const unsigned char * key,unsigned int keybits,const int is_wrap)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 {
57 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
58 const mbedtls_cipher_info_t *cipher_info;
59
60 cipher_info = mbedtls_cipher_info_from_values(cipher,
61 keybits,
62 MBEDTLS_MODE_ECB);
63 if (cipher_info == NULL) {
64 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
65 }
66
67 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
68 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
69 }
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 if (cipher != MBEDTLS_CIPHER_ID_AES) {
81 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
82 }
83
84 mbedtls_cipher_free(&ctx->cipher_ctx);
85
86 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
87 return ret;
88 }
89
90 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
91 is_wrap ? MBEDTLS_ENCRYPT :
92 MBEDTLS_DECRYPT)
93 ) != 0) {
94 return ret;
95 }
96
97 return 0;
98 }
99
100 /*
101 * Free context
102 */
mbedtls_nist_kw_free(mbedtls_nist_kw_context * ctx)103 void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
104 {
105 if (ctx == NULL) {
106 return;
107 }
108
109 mbedtls_cipher_free(&ctx->cipher_ctx);
110 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
111 }
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 */
calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH],uint64_t t)117 static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
118 {
119 size_t i = 0;
120 for (i = 0; i < sizeof(t); i++) {
121 A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
122 }
123 }
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 */
mbedtls_nist_kw_wrap(mbedtls_nist_kw_context * ctx,mbedtls_nist_kw_mode_t mode,const unsigned char * input,size_t in_len,unsigned char * output,size_t * out_len,size_t out_size)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 {
134 int ret = 0;
135 size_t semiblocks = 0;
136 size_t s;
137 size_t olen, padlen = 0;
138 uint64_t t = 0;
139 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
140 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
141
142 *out_len = 0;
143 /*
144 * Generate the String to work on
145 */
146 if (mode == MBEDTLS_KW_MODE_KW) {
147 if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
148 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
149 }
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 if (in_len < 16 ||
156 #if SIZE_MAX > 0x1FFFFFFFFFFFFF8
157 in_len > 0x1FFFFFFFFFFFFF8 ||
158 #endif
159 in_len % KW_SEMIBLOCK_LENGTH != 0) {
160 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
161 }
162
163 memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
164 memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
165 } else {
166 if (in_len % 8 != 0) {
167 padlen = (8 - (in_len % 8));
168 }
169
170 if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
171 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
172 }
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 if (in_len < 1
179 #if SIZE_MAX > 0xFFFFFFFF
180 || in_len > 0xFFFFFFFF
181 #endif
182 ) {
183 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
184 }
185
186 memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
187 MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
188 KW_SEMIBLOCK_LENGTH / 2);
189
190 memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
191 memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
192 }
193 semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
194
195 s = 6 * (semiblocks - 1);
196
197 if (mode == MBEDTLS_KW_MODE_KWP
198 && in_len <= KW_SEMIBLOCK_LENGTH) {
199 memcpy(inbuff, output, 16);
200 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
201 inbuff, 16, output, &olen);
202 if (ret != 0) {
203 goto cleanup;
204 }
205 } else {
206 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
207 unsigned char *A = output;
208
209 /*
210 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
211 */
212 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
213 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
214 goto cleanup;
215 }
216
217 /* Calculate intermediate values */
218 for (t = 1; t <= s; t++) {
219 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
220 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
221
222 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
223 inbuff, 16, outbuff, &olen);
224 if (ret != 0) {
225 goto cleanup;
226 }
227
228 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
229 calc_a_xor_t(A, t);
230
231 memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
232 R2 += KW_SEMIBLOCK_LENGTH;
233 if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
234 R2 = output + KW_SEMIBLOCK_LENGTH;
235 }
236 }
237 }
238
239 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
240
241 cleanup:
242
243 if (ret != 0) {
244 memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
245 }
246 mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
247 mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
248
249 return ret;
250 }
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 */
unwrap(mbedtls_nist_kw_context * ctx,const unsigned char * input,size_t semiblocks,unsigned char A[KW_SEMIBLOCK_LENGTH],unsigned char * output,size_t * out_len)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 {
265 int ret = 0;
266 const size_t s = 6 * (semiblocks - 1);
267 size_t olen;
268 uint64_t t = 0;
269 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
270 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
271 unsigned char *R = NULL;
272 *out_len = 0;
273
274 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
275 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
276 }
277
278 memcpy(A, input, KW_SEMIBLOCK_LENGTH);
279 memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
280 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
281
282 /* Calculate intermediate values */
283 for (t = s; t >= 1; t--) {
284 calc_a_xor_t(A, t);
285
286 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
287 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
288
289 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
290 inbuff, 16, outbuff, &olen);
291 if (ret != 0) {
292 goto cleanup;
293 }
294
295 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
296
297 /* Set R as LSB64 of outbuff */
298 memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
299
300 if (R == output) {
301 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
302 } else {
303 R -= KW_SEMIBLOCK_LENGTH;
304 }
305 }
306
307 *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
308
309 cleanup:
310 if (ret != 0) {
311 memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
312 }
313 mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
314 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
315
316 return ret;
317 }
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 */
mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context * ctx,mbedtls_nist_kw_mode_t mode,const unsigned char * input,size_t in_len,unsigned char * output,size_t * out_len,size_t out_size)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 {
328 int ret = 0;
329 size_t olen;
330 unsigned char A[KW_SEMIBLOCK_LENGTH];
331 int diff;
332
333 *out_len = 0;
334 if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
335 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
336 }
337
338 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 if (in_len < 24 ||
344 #if SIZE_MAX > 0x200000000000000
345 in_len > 0x200000000000000 ||
346 #endif
347 in_len % KW_SEMIBLOCK_LENGTH != 0) {
348 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
349 }
350
351 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
352 A, output, out_len);
353 if (ret != 0) {
354 goto cleanup;
355 }
356
357 /* Check ICV in "constant-time" */
358 diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
359
360 if (diff != 0) {
361 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
362 goto cleanup;
363 }
364
365 } else if (mode == MBEDTLS_KW_MODE_KWP) {
366 size_t padlen = 0;
367 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 if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
373 #if SIZE_MAX > 0x100000000
374 in_len > 0x100000000 ||
375 #endif
376 in_len % KW_SEMIBLOCK_LENGTH != 0) {
377 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
378 }
379
380 if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
381 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
382 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
383 input, 16, outbuff, &olen);
384 if (ret != 0) {
385 goto cleanup;
386 }
387
388 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
389 memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
390 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
391 *out_len = KW_SEMIBLOCK_LENGTH;
392 } else {
393 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
394 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
395 A, output, out_len);
396 if (ret != 0) {
397 goto cleanup;
398 }
399 }
400
401 /* Check ICV in "constant-time" */
402 diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
403
404 if (diff != 0) {
405 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
406 }
407
408 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 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
416 ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
417 MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
418 padlen &= 7;
419
420 /* Check padding in "constant-time" */
421 const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
422 diff = mbedtls_ct_memcmp_partial(
423 &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
424 KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
425
426 if (diff != 0) {
427 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
428 }
429
430 if (ret != 0) {
431 goto cleanup;
432 }
433 memset(output + Plen, 0, padlen);
434 *out_len = Plen;
435 } else {
436 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
437 goto cleanup;
438 }
439
440 cleanup:
441 if (ret != 0) {
442 memset(output, 0, *out_len);
443 *out_len = 0;
444 }
445
446 mbedtls_platform_zeroize(&diff, sizeof(diff));
447 mbedtls_platform_zeroize(A, sizeof(A));
448
449 return ret;
450 }
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
mbedtls_nist_kw_self_test(int verbose)584 int mbedtls_nist_kw_self_test(int verbose)
585 {
586 mbedtls_nist_kw_context ctx;
587 unsigned char out[48];
588 size_t olen;
589 int i;
590 int ret = 0;
591 mbedtls_nist_kw_init(&ctx);
592
593 /*
594 * KW mode
595 */
596 {
597 static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
598
599 for (i = 0; i < num_tests; i++) {
600 if (verbose != 0) {
601 mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8);
602 }
603
604 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
605 kw_key[i], key_len[i] * 8, 1);
606 if (ret != 0) {
607 if (verbose != 0) {
608 mbedtls_printf(" KW: setup failed ");
609 }
610
611 goto end;
612 }
613
614 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
615 kw_msg_len[i], out, &olen, sizeof(out));
616 if (ret != 0 || kw_out_len[i] != olen ||
617 memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
618 if (verbose != 0) {
619 mbedtls_printf("failed. ");
620 }
621
622 ret = 1;
623 goto end;
624 }
625
626 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
627 kw_key[i], key_len[i] * 8, 0))
628 != 0) {
629 if (verbose != 0) {
630 mbedtls_printf(" KW: setup failed ");
631 }
632
633 goto end;
634 }
635
636 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
637 out, olen, out, &olen, sizeof(out));
638
639 if (ret != 0 || olen != kw_msg_len[i] ||
640 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
641 if (verbose != 0) {
642 mbedtls_printf("failed\n");
643 }
644
645 ret = 1;
646 goto end;
647 }
648
649 if (verbose != 0) {
650 mbedtls_printf(" passed\n");
651 }
652 }
653 }
654
655 /*
656 * KWP mode
657 */
658 {
659 static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
660
661 for (i = 0; i < num_tests; i++) {
662 olen = sizeof(out);
663 if (verbose != 0) {
664 mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8);
665 }
666
667 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
668 key_len[i] * 8, 1);
669 if (ret != 0) {
670 if (verbose != 0) {
671 mbedtls_printf(" KWP: setup failed ");
672 }
673
674 goto end;
675 }
676 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
677 kwp_msg_len[i], out, &olen, sizeof(out));
678
679 if (ret != 0 || kwp_out_len[i] != olen ||
680 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
681 if (verbose != 0) {
682 mbedtls_printf("failed. ");
683 }
684
685 ret = 1;
686 goto end;
687 }
688
689 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
690 kwp_key[i], key_len[i] * 8, 0))
691 != 0) {
692 if (verbose != 0) {
693 mbedtls_printf(" KWP: setup failed ");
694 }
695
696 goto end;
697 }
698
699 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
700 olen, out, &olen, sizeof(out));
701
702 if (ret != 0 || olen != kwp_msg_len[i] ||
703 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
704 if (verbose != 0) {
705 mbedtls_printf("failed. ");
706 }
707
708 ret = 1;
709 goto end;
710 }
711
712 if (verbose != 0) {
713 mbedtls_printf(" passed\n");
714 }
715 }
716 }
717 end:
718 mbedtls_nist_kw_free(&ctx);
719
720 if (verbose != 0) {
721 mbedtls_printf("\n");
722 }
723
724 return ret;
725 }
726
727 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
728
729 #endif /* MBEDTLS_NIST_KW_C */
730