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