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