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