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     unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
193     unsigned char *A = output;
194 
195     *out_len = 0;
196     /*
197      * Generate the String to work on
198      */
199     if( mode == MBEDTLS_KW_MODE_KW )
200     {
201         if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
202         {
203             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
204         }
205 
206         /*
207          * According to SP 800-38F Table 1, the plaintext length for KW
208          * must be between 2 to 2^54-1 semiblocks inclusive.
209          */
210         if( in_len < 16 ||
211 #if SIZE_MAX > 0x1FFFFFFFFFFFFF8
212             in_len > 0x1FFFFFFFFFFFFF8 ||
213 #endif
214             in_len % KW_SEMIBLOCK_LENGTH != 0 )
215         {
216             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
217         }
218 
219         memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
220         memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
221     }
222     else
223     {
224         if( in_len % 8 != 0 )
225         {
226             padlen = ( 8 - ( in_len % 8 ) );
227         }
228 
229         if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen )
230         {
231             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
232         }
233 
234         /*
235          * According to SP 800-38F Table 1, the plaintext length for KWP
236          * must be between 1 and 2^32-1 octets inclusive.
237          */
238         if( in_len < 1
239 #if SIZE_MAX > 0xFFFFFFFF
240             || in_len > 0xFFFFFFFF
241 #endif
242           )
243         {
244             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
245         }
246 
247         memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
248         PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
249                        KW_SEMIBLOCK_LENGTH / 2 );
250 
251         memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
252         memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen );
253     }
254     semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1;
255 
256     s = 6 * ( semiblocks - 1 );
257 
258     if( mode == MBEDTLS_KW_MODE_KWP
259         && in_len <= KW_SEMIBLOCK_LENGTH )
260     {
261         memcpy( inbuff, output, 16 );
262         ret = mbedtls_cipher_update( &ctx->cipher_ctx,
263                                      inbuff, 16, output, &olen );
264         if( ret != 0 )
265             goto cleanup;
266     }
267     else
268     {
269         /*
270          * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
271          */
272         if( semiblocks < MIN_SEMIBLOCKS_COUNT )
273         {
274             ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
275             goto cleanup;
276         }
277 
278         /* Calculate intermediate values */
279         for( t = 1; t <= s; t++ )
280         {
281             memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
282             memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH );
283 
284             ret = mbedtls_cipher_update( &ctx->cipher_ctx,
285                                          inbuff, 16, outbuff, &olen );
286             if( ret != 0 )
287                 goto cleanup;
288 
289             memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
290             calc_a_xor_t( A, t );
291 
292             memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
293             R2 += KW_SEMIBLOCK_LENGTH;
294             if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) )
295                 R2 = output + KW_SEMIBLOCK_LENGTH;
296         }
297     }
298 
299     *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
300 
301 cleanup:
302 
303     if( ret != 0)
304     {
305         memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH );
306     }
307     mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
308     mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
309 
310     return( ret );
311 }
312 
313 /*
314  * W-1 function as defined in RFC 3394 section 2.2.2
315  * This function assumes the following:
316  * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
317  * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
318  * 3. Minimal number of semiblocks is 3.
319  * 4. A is a buffer to hold the first semiblock of the input buffer.
320  */
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)321 static int unwrap( mbedtls_nist_kw_context *ctx,
322                    const unsigned char *input, size_t semiblocks,
323                    unsigned char A[KW_SEMIBLOCK_LENGTH],
324                    unsigned char *output, size_t* out_len )
325 {
326     int ret = 0;
327     const size_t s = 6 * ( semiblocks - 1 );
328     size_t olen;
329     uint64_t t = 0;
330     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
331     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
332     unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
333     *out_len = 0;
334 
335     if( semiblocks < MIN_SEMIBLOCKS_COUNT )
336     {
337         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
338     }
339 
340     memcpy( A, input, KW_SEMIBLOCK_LENGTH );
341     memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
342 
343     /* Calculate intermediate values */
344     for( t = s; t >= 1; t-- )
345     {
346         calc_a_xor_t( A, t );
347 
348         memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
349         memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH );
350 
351         ret = mbedtls_cipher_update( &ctx->cipher_ctx,
352                                      inbuff, 16, outbuff, &olen );
353         if( ret != 0 )
354             goto cleanup;
355 
356         memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
357 
358         /* Set R as LSB64 of outbuff */
359         memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
360 
361         if( R == output )
362             R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
363         else
364             R -= KW_SEMIBLOCK_LENGTH;
365     }
366 
367     *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH;
368 
369 cleanup:
370     if( ret != 0)
371         memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
372     mbedtls_platform_zeroize( inbuff, sizeof( inbuff )  );
373     mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
374 
375     return( ret );
376 }
377 
378 /*
379  * KW-AD as defined in SP 800-38F section 6.2
380  * KWP-AD as defined in SP 800-38F section 6.3
381  */
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)382 int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx,
383                             mbedtls_nist_kw_mode_t mode,
384                             const unsigned char *input, size_t in_len,
385                             unsigned char *output, size_t *out_len, size_t out_size )
386 {
387     int ret = 0;
388     size_t i, olen;
389     unsigned char A[KW_SEMIBLOCK_LENGTH];
390     unsigned char diff, bad_padding = 0;
391 
392     *out_len = 0;
393     if( out_size < in_len - KW_SEMIBLOCK_LENGTH )
394     {
395         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
396     }
397 
398     if( mode == MBEDTLS_KW_MODE_KW )
399     {
400         /*
401          * According to SP 800-38F Table 1, the ciphertext length for KW
402          * must be between 3 to 2^54 semiblocks inclusive.
403          */
404         if( in_len < 24 ||
405 #if SIZE_MAX > 0x200000000000000
406             in_len > 0x200000000000000 ||
407 #endif
408             in_len % KW_SEMIBLOCK_LENGTH != 0 )
409         {
410             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
411         }
412 
413         ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
414                       A, output, out_len );
415         if( ret != 0 )
416             goto cleanup;
417 
418         /* Check ICV in "constant-time" */
419         diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
420 
421         if( diff != 0 )
422         {
423             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
424             goto cleanup;
425         }
426 
427     }
428     else if( mode == MBEDTLS_KW_MODE_KWP )
429     {
430         size_t padlen = 0;
431         uint32_t Plen;
432         /*
433          * According to SP 800-38F Table 1, the ciphertext length for KWP
434          * must be between 2 to 2^29 semiblocks inclusive.
435          */
436         if( in_len < KW_SEMIBLOCK_LENGTH * 2 ||
437 #if SIZE_MAX > 0x100000000
438             in_len > 0x100000000 ||
439 #endif
440             in_len % KW_SEMIBLOCK_LENGTH != 0 )
441         {
442             return(  MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
443         }
444 
445         if( in_len == KW_SEMIBLOCK_LENGTH * 2 )
446         {
447             unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
448             ret = mbedtls_cipher_update( &ctx->cipher_ctx,
449                                          input, 16, outbuff, &olen );
450             if( ret != 0 )
451                 goto cleanup;
452 
453             memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
454             memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
455             mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
456             *out_len = KW_SEMIBLOCK_LENGTH;
457         }
458         else
459         {
460             /* in_len >=  KW_SEMIBLOCK_LENGTH * 3 */
461             ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
462                           A, output, out_len );
463             if( ret != 0 )
464                 goto cleanup;
465         }
466 
467         /* Check ICV in "constant-time" */
468         diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
469 
470         if( diff != 0 )
471         {
472             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
473         }
474 
475         GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 );
476 
477         /*
478          * Plen is the length of the plaintext, when the input is valid.
479          * If Plen is larger than the plaintext and padding, padlen will be
480          * larger than 8, because of the type wrap around.
481          */
482         padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
483         if ( padlen > 7 )
484         {
485             padlen &= 7;
486             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
487         }
488 
489         /* Check padding in "constant-time" */
490         for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ )
491         {
492              if( i >= KW_SEMIBLOCK_LENGTH - padlen )
493                  diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
494              else
495                  bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
496         }
497 
498         if( diff != 0 )
499         {
500             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
501         }
502 
503         if( ret != 0 )
504         {
505             goto cleanup;
506         }
507         memset( output + Plen, 0, padlen );
508         *out_len = Plen;
509     }
510     else
511     {
512         ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
513         goto cleanup;
514     }
515 
516 cleanup:
517     if( ret != 0 )
518     {
519         memset( output, 0, *out_len );
520         *out_len = 0;
521     }
522 
523     mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
524     mbedtls_platform_zeroize( &diff, sizeof( diff ) );
525     mbedtls_platform_zeroize( A, sizeof( A ) );
526 
527     return( ret );
528 }
529 
530 #endif /* !MBEDTLS_NIST_KW_ALT */
531 
532 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
533 
534 #define KW_TESTS 3
535 
536 /*
537  * Test vectors taken from NIST
538  * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
539  */
540 static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
541 
542 static const unsigned char kw_key[KW_TESTS][32] = {
543     { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
544       0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
545     { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
546       0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
547       0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
548     { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
549       0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
550       0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
551       0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
552 };
553 
554 static const unsigned char kw_msg[KW_TESTS][40] = {
555     { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
556       0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
557     { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
558       0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
559       0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
560       0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
561       0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
562     { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
563       0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
564       0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
565 };
566 
567 static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
568 static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
569 static const unsigned char kw_res[KW_TESTS][48] = {
570     { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
571       0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
572       0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
573     { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
574       0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
575       0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
576       0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
577       0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
578       0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
579     { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
580       0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
581       0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
582       0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
583 };
584 
585 static const unsigned char kwp_key[KW_TESTS][32] = {
586     { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
587       0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
588     { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
589       0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
590       0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
591     { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
592       0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
593       0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
594       0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
595 };
596 
597 static const unsigned char kwp_msg[KW_TESTS][31] = {
598     { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
599       0x96 },
600     { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
601       0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
602       0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
603       0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
604     { 0xd1 }
605 };
606 static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
607 
608 static const unsigned char kwp_res[KW_TESTS][48] = {
609     { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
610       0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
611       0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
612     { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
613       0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
614       0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
615       0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
616       0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
617     { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
618       0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4  }
619 };
620 static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
621 
mbedtls_nist_kw_self_test(int verbose)622 int mbedtls_nist_kw_self_test( int verbose )
623 {
624     mbedtls_nist_kw_context ctx;
625     unsigned char out[48];
626     size_t olen;
627     int i;
628     int ret = 0;
629     mbedtls_nist_kw_init( &ctx );
630 
631     for( i = 0; i < KW_TESTS; i++ )
632     {
633         if( verbose != 0 )
634             mbedtls_printf( "  KW-AES-%u ", (unsigned int) key_len[i] * 8 );
635 
636         ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
637                                       kw_key[i], key_len[i] * 8, 1 );
638         if( ret != 0 )
639         {
640             if( verbose != 0 )
641                 mbedtls_printf( "  KW: setup failed " );
642 
643             goto end;
644         }
645 
646         ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
647                                     kw_msg_len[i], out, &olen, sizeof( out ) );
648         if( ret != 0 || kw_out_len[i] != olen ||
649             memcmp( out, kw_res[i], kw_out_len[i] ) != 0 )
650         {
651             if( verbose != 0 )
652                 mbedtls_printf( "failed. ");
653 
654             ret = 1;
655             goto end;
656         }
657 
658         if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
659                                             kw_key[i], key_len[i] * 8, 0 ) )
660               != 0 )
661         {
662             if( verbose != 0 )
663                 mbedtls_printf( "  KW: setup failed ");
664 
665             goto end;
666         }
667 
668         ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW,
669                                       out, olen, out, &olen, sizeof( out ) );
670 
671         if( ret != 0 || olen != kw_msg_len[i] ||
672             memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 )
673         {
674             if( verbose != 0 )
675                 mbedtls_printf( "failed\n" );
676 
677             ret = 1;
678             goto end;
679         }
680 
681         if( verbose != 0 )
682             mbedtls_printf( " passed\n" );
683     }
684 
685     for( i = 0; i < KW_TESTS; i++ )
686     {
687         olen = sizeof( out );
688         if( verbose != 0 )
689             mbedtls_printf( "  KWP-AES-%u ", (unsigned int) key_len[i] * 8 );
690 
691         ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
692                                       key_len[i] * 8, 1 );
693         if( ret  != 0 )
694         {
695             if( verbose != 0 )
696                 mbedtls_printf( "  KWP: setup failed " );
697 
698             goto end;
699         }
700         ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
701                                     kwp_msg_len[i], out, &olen, sizeof( out ) );
702 
703         if( ret != 0 || kwp_out_len[i] != olen ||
704             memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 )
705         {
706             if( verbose != 0 )
707                 mbedtls_printf( "failed. ");
708 
709             ret = 1;
710             goto end;
711         }
712 
713         if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
714                                             kwp_key[i], key_len[i] * 8, 0 ) )
715               != 0 )
716         {
717             if( verbose != 0 )
718                 mbedtls_printf( "  KWP: setup failed ");
719 
720             goto end;
721         }
722 
723         ret = mbedtls_nist_kw_unwrap(  &ctx, MBEDTLS_KW_MODE_KWP, out,
724                                        olen, out, &olen, sizeof( out ) );
725 
726         if( ret != 0 || olen != kwp_msg_len[i] ||
727             memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 )
728         {
729             if( verbose != 0 )
730                 mbedtls_printf( "failed. ");
731 
732             ret = 1;
733             goto end;
734         }
735 
736         if( verbose != 0 )
737             mbedtls_printf( " passed\n" );
738     }
739 end:
740     mbedtls_nist_kw_free( &ctx );
741 
742     if( verbose != 0 )
743         mbedtls_printf( "\n" );
744 
745     return( ret );
746 }
747 
748 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
749 
750 #endif /* MBEDTLS_NIST_KW_C */
751