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 (cipher_info->block_size != 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 i, olen;
326 unsigned char A[KW_SEMIBLOCK_LENGTH];
327 unsigned char 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 = -(int) mbedtls_ct_uint_if(padlen & ~7, -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret);
413 padlen &= 7;
414
415 /* Check padding in "constant-time" */
416 for (diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++) {
417 size_t mask = mbedtls_ct_size_mask_ge(i, KW_SEMIBLOCK_LENGTH - padlen);
418 diff |= (unsigned char) (mask & output[*out_len - KW_SEMIBLOCK_LENGTH + i]);
419 }
420
421 if (diff != 0) {
422 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
423 }
424
425 if (ret != 0) {
426 goto cleanup;
427 }
428 memset(output + Plen, 0, padlen);
429 *out_len = Plen;
430 } else {
431 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
432 goto cleanup;
433 }
434
435 cleanup:
436 if (ret != 0) {
437 memset(output, 0, *out_len);
438 *out_len = 0;
439 }
440
441 mbedtls_platform_zeroize(&diff, sizeof(diff));
442 mbedtls_platform_zeroize(A, sizeof(A));
443
444 return ret;
445 }
446
447 #endif /* !MBEDTLS_NIST_KW_ALT */
448
449 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
450
451 #define KW_TESTS 3
452
453 /*
454 * Test vectors taken from NIST
455 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
456 */
457 static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
458
459 static const unsigned char kw_key[KW_TESTS][32] = {
460 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
461 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
462 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
463 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
464 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
465 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
466 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
467 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
468 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
469 };
470
471 static const unsigned char kw_msg[KW_TESTS][40] = {
472 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
473 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
474 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
475 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
476 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
477 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
478 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
479 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
480 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
481 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
482 };
483
484 static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
485 static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
486 static const unsigned char kw_res[KW_TESTS][48] = {
487 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
488 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
489 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
490 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
491 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
492 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
493 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
494 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
495 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
496 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
497 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
498 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
499 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
500 };
501
502 static const unsigned char kwp_key[KW_TESTS][32] = {
503 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
504 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
505 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
506 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
507 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
508 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
509 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
510 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
511 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
512 };
513
514 static const unsigned char kwp_msg[KW_TESTS][31] = {
515 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
516 0x96 },
517 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
518 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
519 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
520 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
521 { 0xd1 }
522 };
523 static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
524
525 static const unsigned char kwp_res[KW_TESTS][48] = {
526 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
527 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
528 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
529 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
530 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
531 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
532 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
533 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
534 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
535 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
536 };
537 static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
538
mbedtls_nist_kw_self_test(int verbose)539 int mbedtls_nist_kw_self_test(int verbose)
540 {
541 mbedtls_nist_kw_context ctx;
542 unsigned char out[48];
543 size_t olen;
544 int i;
545 int ret = 0;
546 mbedtls_nist_kw_init(&ctx);
547
548 for (i = 0; i < KW_TESTS; i++) {
549 if (verbose != 0) {
550 mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8);
551 }
552
553 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
554 kw_key[i], key_len[i] * 8, 1);
555 if (ret != 0) {
556 if (verbose != 0) {
557 mbedtls_printf(" KW: setup failed ");
558 }
559
560 goto end;
561 }
562
563 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
564 kw_msg_len[i], out, &olen, sizeof(out));
565 if (ret != 0 || kw_out_len[i] != olen ||
566 memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
567 if (verbose != 0) {
568 mbedtls_printf("failed. ");
569 }
570
571 ret = 1;
572 goto end;
573 }
574
575 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
576 kw_key[i], key_len[i] * 8, 0))
577 != 0) {
578 if (verbose != 0) {
579 mbedtls_printf(" KW: setup failed ");
580 }
581
582 goto end;
583 }
584
585 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
586 out, olen, out, &olen, sizeof(out));
587
588 if (ret != 0 || olen != kw_msg_len[i] ||
589 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
590 if (verbose != 0) {
591 mbedtls_printf("failed\n");
592 }
593
594 ret = 1;
595 goto end;
596 }
597
598 if (verbose != 0) {
599 mbedtls_printf(" passed\n");
600 }
601 }
602
603 for (i = 0; i < KW_TESTS; i++) {
604 olen = sizeof(out);
605 if (verbose != 0) {
606 mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8);
607 }
608
609 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
610 key_len[i] * 8, 1);
611 if (ret != 0) {
612 if (verbose != 0) {
613 mbedtls_printf(" KWP: setup failed ");
614 }
615
616 goto end;
617 }
618 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
619 kwp_msg_len[i], out, &olen, sizeof(out));
620
621 if (ret != 0 || kwp_out_len[i] != olen ||
622 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
623 if (verbose != 0) {
624 mbedtls_printf("failed. ");
625 }
626
627 ret = 1;
628 goto end;
629 }
630
631 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
632 kwp_key[i], key_len[i] * 8, 0))
633 != 0) {
634 if (verbose != 0) {
635 mbedtls_printf(" KWP: setup failed ");
636 }
637
638 goto end;
639 }
640
641 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
642 olen, out, &olen, sizeof(out));
643
644 if (ret != 0 || olen != kwp_msg_len[i] ||
645 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
646 if (verbose != 0) {
647 mbedtls_printf("failed. ");
648 }
649
650 ret = 1;
651 goto end;
652 }
653
654 if (verbose != 0) {
655 mbedtls_printf(" passed\n");
656 }
657 }
658 end:
659 mbedtls_nist_kw_free(&ctx);
660
661 if (verbose != 0) {
662 mbedtls_printf("\n");
663 }
664
665 return ret;
666 }
667
668 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
669
670 #endif /* MBEDTLS_NIST_KW_C */
671