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