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