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 */
mbedtls_nist_kw_safer_memcmp(const void * a,const void * b,size_t n)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 */
mbedtls_nist_kw_init(mbedtls_nist_kw_context * ctx)133 void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx )
134 {
135 memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) );
136 }
137
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)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 */
mbedtls_nist_kw_free(mbedtls_nist_kw_context * ctx)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 */
calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH],uint64_t t)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 */
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)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 */
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)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 */
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)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
mbedtls_nist_kw_self_test(int verbose)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