• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
7  *
8  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
9  *  not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  */
20 /*
21  * Definition of Key Wrapping:
22  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
23  * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
24  * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
25  *
26  * Note: RFC 3394 defines different methodology for intermediate operations for
27  * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
28  */
29 
30 #include "common.h"
31 
32 #if defined(MBEDTLS_NIST_KW_C)
33 
34 #include "mbedtls/nist_kw.h"
35 #include "mbedtls/platform_util.h"
36 #include "mbedtls/error.h"
37 #include "mbedtls/constant_time.h"
38 
39 #include <stdint.h>
40 #include <string.h>
41 
42 #include "mbedtls/platform.h"
43 
44 #if !defined(MBEDTLS_NIST_KW_ALT)
45 
46 #define KW_SEMIBLOCK_LENGTH    8
47 #define MIN_SEMIBLOCKS_COUNT   3
48 
49 /*! The 64-bit default integrity check value (ICV) for KW mode. */
50 static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
51 /*! The 32-bit default integrity check value (ICV) for KWP mode. */
52 static const  unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
53 
54 /*
55  * Initialize context
56  */
mbedtls_nist_kw_init(mbedtls_nist_kw_context * ctx)57 void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
58 {
59     memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
60 }
61 
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)62 int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
63                            mbedtls_cipher_id_t cipher,
64                            const unsigned char *key,
65                            unsigned int keybits,
66                            const int is_wrap)
67 {
68     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
69     const mbedtls_cipher_info_t *cipher_info;
70 
71     cipher_info = mbedtls_cipher_info_from_values(cipher,
72                                                   keybits,
73                                                   MBEDTLS_MODE_ECB);
74     if (cipher_info == NULL) {
75         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
76     }
77 
78     if (cipher_info->block_size != 16) {
79         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
80     }
81 
82     /*
83      * SP 800-38F currently defines AES cipher as the only block cipher allowed:
84      * "For KW and KWP, the underlying block cipher shall be approved, and the
85      *  block size shall be 128 bits. Currently, the AES block cipher, with key
86      *  lengths of 128, 192, or 256 bits, is the only block cipher that fits
87      *  this profile."
88      *  Currently we don't support other 128 bit block ciphers for key wrapping,
89      *  such as Camellia and Aria.
90      */
91     if (cipher != MBEDTLS_CIPHER_ID_AES) {
92         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
93     }
94 
95     mbedtls_cipher_free(&ctx->cipher_ctx);
96 
97     if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
98         return ret;
99     }
100 
101     if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
102                                      is_wrap ? MBEDTLS_ENCRYPT :
103                                      MBEDTLS_DECRYPT)
104          ) != 0) {
105         return ret;
106     }
107 
108     return 0;
109 }
110 
111 /*
112  * Free context
113  */
mbedtls_nist_kw_free(mbedtls_nist_kw_context * ctx)114 void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
115 {
116     mbedtls_cipher_free(&ctx->cipher_ctx);
117     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
118 }
119 
120 /*
121  * Helper function for Xoring the uint64_t "t" with the encrypted A.
122  * Defined in NIST SP 800-38F section 6.1
123  */
calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH],uint64_t t)124 static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
125 {
126     size_t i = 0;
127     for (i = 0; i < sizeof(t); i++) {
128         A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
129     }
130 }
131 
132 /*
133  * KW-AE as defined in SP 800-38F section 6.2
134  * KWP-AE as defined in SP 800-38F section 6.3
135  */
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)136 int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
137                          mbedtls_nist_kw_mode_t mode,
138                          const unsigned char *input, size_t in_len,
139                          unsigned char *output, size_t *out_len, size_t out_size)
140 {
141     int ret = 0;
142     size_t semiblocks = 0;
143     size_t s;
144     size_t olen, padlen = 0;
145     uint64_t t = 0;
146     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
147     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
148 
149     *out_len = 0;
150     /*
151      * Generate the String to work on
152      */
153     if (mode == MBEDTLS_KW_MODE_KW) {
154         if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
155             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
156         }
157 
158         /*
159          * According to SP 800-38F Table 1, the plaintext length for KW
160          * must be between 2 to 2^54-1 semiblocks inclusive.
161          */
162         if (in_len < 16 ||
163 #if SIZE_MAX > 0x1FFFFFFFFFFFFF8
164             in_len > 0x1FFFFFFFFFFFFF8 ||
165 #endif
166             in_len % KW_SEMIBLOCK_LENGTH != 0) {
167             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
168         }
169 
170         memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
171         memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
172     } else {
173         if (in_len % 8 != 0) {
174             padlen = (8 - (in_len % 8));
175         }
176 
177         if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
178             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
179         }
180 
181         /*
182          * According to SP 800-38F Table 1, the plaintext length for KWP
183          * must be between 1 and 2^32-1 octets inclusive.
184          */
185         if (in_len < 1
186 #if SIZE_MAX > 0xFFFFFFFF
187             || in_len > 0xFFFFFFFF
188 #endif
189             ) {
190             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
191         }
192 
193         memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
194         MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
195                               KW_SEMIBLOCK_LENGTH / 2);
196 
197         memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
198         memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
199     }
200     semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
201 
202     s = 6 * (semiblocks - 1);
203 
204     if (mode == MBEDTLS_KW_MODE_KWP
205         && in_len <= KW_SEMIBLOCK_LENGTH) {
206         memcpy(inbuff, output, 16);
207         ret = mbedtls_cipher_update(&ctx->cipher_ctx,
208                                     inbuff, 16, output, &olen);
209         if (ret != 0) {
210             goto cleanup;
211         }
212     } else {
213         unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
214         unsigned char *A = output;
215 
216         /*
217          * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
218          */
219         if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
220             ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
221             goto cleanup;
222         }
223 
224         /* Calculate intermediate values */
225         for (t = 1; t <= s; t++) {
226             memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
227             memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
228 
229             ret = mbedtls_cipher_update(&ctx->cipher_ctx,
230                                         inbuff, 16, outbuff, &olen);
231             if (ret != 0) {
232                 goto cleanup;
233             }
234 
235             memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
236             calc_a_xor_t(A, t);
237 
238             memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
239             R2 += KW_SEMIBLOCK_LENGTH;
240             if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
241                 R2 = output + KW_SEMIBLOCK_LENGTH;
242             }
243         }
244     }
245 
246     *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
247 
248 cleanup:
249 
250     if (ret != 0) {
251         memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
252     }
253     mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
254     mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
255 
256     return ret;
257 }
258 
259 /*
260  * W-1 function as defined in RFC 3394 section 2.2.2
261  * This function assumes the following:
262  * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
263  * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
264  * 3. Minimal number of semiblocks is 3.
265  * 4. A is a buffer to hold the first semiblock of the input buffer.
266  */
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)267 static int unwrap(mbedtls_nist_kw_context *ctx,
268                   const unsigned char *input, size_t semiblocks,
269                   unsigned char A[KW_SEMIBLOCK_LENGTH],
270                   unsigned char *output, size_t *out_len)
271 {
272     int ret = 0;
273     const size_t s = 6 * (semiblocks - 1);
274     size_t olen;
275     uint64_t t = 0;
276     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
277     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
278     unsigned char *R = NULL;
279     *out_len = 0;
280 
281     if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
282         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
283     }
284 
285     memcpy(A, input, KW_SEMIBLOCK_LENGTH);
286     memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
287     R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
288 
289     /* Calculate intermediate values */
290     for (t = s; t >= 1; t--) {
291         calc_a_xor_t(A, t);
292 
293         memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
294         memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
295 
296         ret = mbedtls_cipher_update(&ctx->cipher_ctx,
297                                     inbuff, 16, outbuff, &olen);
298         if (ret != 0) {
299             goto cleanup;
300         }
301 
302         memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
303 
304         /* Set R as LSB64 of outbuff */
305         memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
306 
307         if (R == output) {
308             R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
309         } else {
310             R -= KW_SEMIBLOCK_LENGTH;
311         }
312     }
313 
314     *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
315 
316 cleanup:
317     if (ret != 0) {
318         memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
319     }
320     mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
321     mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
322 
323     return ret;
324 }
325 
326 /*
327  * KW-AD as defined in SP 800-38F section 6.2
328  * KWP-AD as defined in SP 800-38F section 6.3
329  */
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)330 int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
331                            mbedtls_nist_kw_mode_t mode,
332                            const unsigned char *input, size_t in_len,
333                            unsigned char *output, size_t *out_len, size_t out_size)
334 {
335     int ret = 0;
336     size_t i, olen;
337     unsigned char A[KW_SEMIBLOCK_LENGTH];
338     unsigned char diff, bad_padding = 0;
339 
340     *out_len = 0;
341     if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
342         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
343     }
344 
345     if (mode == MBEDTLS_KW_MODE_KW) {
346         /*
347          * According to SP 800-38F Table 1, the ciphertext length for KW
348          * must be between 3 to 2^54 semiblocks inclusive.
349          */
350         if (in_len < 24 ||
351 #if SIZE_MAX > 0x200000000000000
352             in_len > 0x200000000000000 ||
353 #endif
354             in_len % KW_SEMIBLOCK_LENGTH != 0) {
355             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
356         }
357 
358         ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
359                      A, output, out_len);
360         if (ret != 0) {
361             goto cleanup;
362         }
363 
364         /* Check ICV in "constant-time" */
365         diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
366 
367         if (diff != 0) {
368             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
369             goto cleanup;
370         }
371 
372     } else if (mode == MBEDTLS_KW_MODE_KWP) {
373         size_t padlen = 0;
374         uint32_t Plen;
375         /*
376          * According to SP 800-38F Table 1, the ciphertext length for KWP
377          * must be between 2 to 2^29 semiblocks inclusive.
378          */
379         if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
380 #if SIZE_MAX > 0x100000000
381             in_len > 0x100000000 ||
382 #endif
383             in_len % KW_SEMIBLOCK_LENGTH != 0) {
384             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
385         }
386 
387         if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
388             unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
389             ret = mbedtls_cipher_update(&ctx->cipher_ctx,
390                                         input, 16, outbuff, &olen);
391             if (ret != 0) {
392                 goto cleanup;
393             }
394 
395             memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
396             memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
397             mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
398             *out_len = KW_SEMIBLOCK_LENGTH;
399         } else {
400             /* in_len >=  KW_SEMIBLOCK_LENGTH * 3 */
401             ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
402                          A, output, out_len);
403             if (ret != 0) {
404                 goto cleanup;
405             }
406         }
407 
408         /* Check ICV in "constant-time" */
409         diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
410 
411         if (diff != 0) {
412             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
413         }
414 
415         Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
416 
417         /*
418          * Plen is the length of the plaintext, when the input is valid.
419          * If Plen is larger than the plaintext and padding, padlen will be
420          * larger than 8, because of the type wrap around.
421          */
422         padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
423         if (padlen > 7) {
424             padlen &= 7;
425             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
426         }
427 
428         /* Check padding in "constant-time" */
429         for (diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++) {
430             if (i >= KW_SEMIBLOCK_LENGTH - padlen) {
431                 diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
432             } else {
433                 bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
434             }
435         }
436 
437         if (diff != 0) {
438             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
439         }
440 
441         if (ret != 0) {
442             goto cleanup;
443         }
444         memset(output + Plen, 0, padlen);
445         *out_len = Plen;
446     } else {
447         ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
448         goto cleanup;
449     }
450 
451 cleanup:
452     if (ret != 0) {
453         memset(output, 0, *out_len);
454         *out_len = 0;
455     }
456 
457     mbedtls_platform_zeroize(&bad_padding, sizeof(bad_padding));
458     mbedtls_platform_zeroize(&diff, sizeof(diff));
459     mbedtls_platform_zeroize(A, sizeof(A));
460 
461     return ret;
462 }
463 
464 #endif /* !MBEDTLS_NIST_KW_ALT */
465 
466 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
467 
468 #define KW_TESTS 3
469 
470 /*
471  * Test vectors taken from NIST
472  * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
473  */
474 static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
475 
476 static const unsigned char kw_key[KW_TESTS][32] = {
477     { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
478       0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
479     { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
480       0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
481       0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
482     { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
483       0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
484       0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
485       0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
486 };
487 
488 static const unsigned char kw_msg[KW_TESTS][40] = {
489     { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
490       0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
491     { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
492       0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
493       0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
494       0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
495       0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
496     { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
497       0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
498       0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
499 };
500 
501 static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
502 static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
503 static const unsigned char kw_res[KW_TESTS][48] = {
504     { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
505       0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
506       0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
507     { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
508       0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
509       0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
510       0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
511       0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
512       0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
513     { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
514       0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
515       0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
516       0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
517 };
518 
519 static const unsigned char kwp_key[KW_TESTS][32] = {
520     { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
521       0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
522     { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
523       0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
524       0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
525     { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
526       0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
527       0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
528       0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
529 };
530 
531 static const unsigned char kwp_msg[KW_TESTS][31] = {
532     { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
533       0x96 },
534     { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
535       0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
536       0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
537       0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
538     { 0xd1 }
539 };
540 static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
541 
542 static const unsigned char kwp_res[KW_TESTS][48] = {
543     { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
544       0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
545       0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
546     { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
547       0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
548       0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
549       0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
550       0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
551     { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
552       0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4  }
553 };
554 static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
555 
mbedtls_nist_kw_self_test(int verbose)556 int mbedtls_nist_kw_self_test(int verbose)
557 {
558     mbedtls_nist_kw_context ctx;
559     unsigned char out[48];
560     size_t olen;
561     int i;
562     int ret = 0;
563     mbedtls_nist_kw_init(&ctx);
564 
565     for (i = 0; i < KW_TESTS; i++) {
566         if (verbose != 0) {
567             mbedtls_printf("  KW-AES-%u ", (unsigned int) key_len[i] * 8);
568         }
569 
570         ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
571                                      kw_key[i], key_len[i] * 8, 1);
572         if (ret != 0) {
573             if (verbose != 0) {
574                 mbedtls_printf("  KW: setup failed ");
575             }
576 
577             goto end;
578         }
579 
580         ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
581                                    kw_msg_len[i], out, &olen, sizeof(out));
582         if (ret != 0 || kw_out_len[i] != olen ||
583             memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
584             if (verbose != 0) {
585                 mbedtls_printf("failed. ");
586             }
587 
588             ret = 1;
589             goto end;
590         }
591 
592         if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
593                                           kw_key[i], key_len[i] * 8, 0))
594             != 0) {
595             if (verbose != 0) {
596                 mbedtls_printf("  KW: setup failed ");
597             }
598 
599             goto end;
600         }
601 
602         ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
603                                      out, olen, out, &olen, sizeof(out));
604 
605         if (ret != 0 || olen != kw_msg_len[i] ||
606             memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
607             if (verbose != 0) {
608                 mbedtls_printf("failed\n");
609             }
610 
611             ret = 1;
612             goto end;
613         }
614 
615         if (verbose != 0) {
616             mbedtls_printf(" passed\n");
617         }
618     }
619 
620     for (i = 0; i < KW_TESTS; i++) {
621         olen = sizeof(out);
622         if (verbose != 0) {
623             mbedtls_printf("  KWP-AES-%u ", (unsigned int) key_len[i] * 8);
624         }
625 
626         ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
627                                      key_len[i] * 8, 1);
628         if (ret  != 0) {
629             if (verbose != 0) {
630                 mbedtls_printf("  KWP: setup failed ");
631             }
632 
633             goto end;
634         }
635         ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
636                                    kwp_msg_len[i], out, &olen, sizeof(out));
637 
638         if (ret != 0 || kwp_out_len[i] != olen ||
639             memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
640             if (verbose != 0) {
641                 mbedtls_printf("failed. ");
642             }
643 
644             ret = 1;
645             goto end;
646         }
647 
648         if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
649                                           kwp_key[i], key_len[i] * 8, 0))
650             != 0) {
651             if (verbose != 0) {
652                 mbedtls_printf("  KWP: setup failed ");
653             }
654 
655             goto end;
656         }
657 
658         ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
659                                      olen, out, &olen, sizeof(out));
660 
661         if (ret != 0 || olen != kwp_msg_len[i] ||
662             memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
663             if (verbose != 0) {
664                 mbedtls_printf("failed. ");
665             }
666 
667             ret = 1;
668             goto end;
669         }
670 
671         if (verbose != 0) {
672             mbedtls_printf(" passed\n");
673         }
674     }
675 end:
676     mbedtls_nist_kw_free(&ctx);
677 
678     if (verbose != 0) {
679         mbedtls_printf("\n");
680     }
681 
682     return ret;
683 }
684 
685 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
686 
687 #endif /* MBEDTLS_NIST_KW_C */
688