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