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