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