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