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