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