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 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
193 unsigned char *A = output;
194
195 *out_len = 0;
196 /*
197 * Generate the String to work on
198 */
199 if( mode == MBEDTLS_KW_MODE_KW )
200 {
201 if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
202 {
203 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
204 }
205
206 /*
207 * According to SP 800-38F Table 1, the plaintext length for KW
208 * must be between 2 to 2^54-1 semiblocks inclusive.
209 */
210 if( in_len < 16 ||
211 #if SIZE_MAX > 0x1FFFFFFFFFFFFF8
212 in_len > 0x1FFFFFFFFFFFFF8 ||
213 #endif
214 in_len % KW_SEMIBLOCK_LENGTH != 0 )
215 {
216 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
217 }
218
219 memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
220 memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
221 }
222 else
223 {
224 if( in_len % 8 != 0 )
225 {
226 padlen = ( 8 - ( in_len % 8 ) );
227 }
228
229 if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen )
230 {
231 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
232 }
233
234 /*
235 * According to SP 800-38F Table 1, the plaintext length for KWP
236 * must be between 1 and 2^32-1 octets inclusive.
237 */
238 if( in_len < 1
239 #if SIZE_MAX > 0xFFFFFFFF
240 || in_len > 0xFFFFFFFF
241 #endif
242 )
243 {
244 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
245 }
246
247 memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
248 PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
249 KW_SEMIBLOCK_LENGTH / 2 );
250
251 memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
252 memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen );
253 }
254 semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1;
255
256 s = 6 * ( semiblocks - 1 );
257
258 if( mode == MBEDTLS_KW_MODE_KWP
259 && in_len <= KW_SEMIBLOCK_LENGTH )
260 {
261 memcpy( inbuff, output, 16 );
262 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
263 inbuff, 16, output, &olen );
264 if( ret != 0 )
265 goto cleanup;
266 }
267 else
268 {
269 /*
270 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
271 */
272 if( semiblocks < MIN_SEMIBLOCKS_COUNT )
273 {
274 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
275 goto cleanup;
276 }
277
278 /* Calculate intermediate values */
279 for( t = 1; t <= s; t++ )
280 {
281 memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
282 memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH );
283
284 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
285 inbuff, 16, outbuff, &olen );
286 if( ret != 0 )
287 goto cleanup;
288
289 memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
290 calc_a_xor_t( A, t );
291
292 memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
293 R2 += KW_SEMIBLOCK_LENGTH;
294 if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) )
295 R2 = output + KW_SEMIBLOCK_LENGTH;
296 }
297 }
298
299 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
300
301 cleanup:
302
303 if( ret != 0)
304 {
305 memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH );
306 }
307 mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
308 mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
309
310 return( ret );
311 }
312
313 /*
314 * W-1 function as defined in RFC 3394 section 2.2.2
315 * This function assumes the following:
316 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
317 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
318 * 3. Minimal number of semiblocks is 3.
319 * 4. A is a buffer to hold the first semiblock of the input buffer.
320 */
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)321 static int unwrap( mbedtls_nist_kw_context *ctx,
322 const unsigned char *input, size_t semiblocks,
323 unsigned char A[KW_SEMIBLOCK_LENGTH],
324 unsigned char *output, size_t* out_len )
325 {
326 int ret = 0;
327 const size_t s = 6 * ( semiblocks - 1 );
328 size_t olen;
329 uint64_t t = 0;
330 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
331 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
332 unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
333 *out_len = 0;
334
335 if( semiblocks < MIN_SEMIBLOCKS_COUNT )
336 {
337 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
338 }
339
340 memcpy( A, input, KW_SEMIBLOCK_LENGTH );
341 memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
342
343 /* Calculate intermediate values */
344 for( t = s; t >= 1; t-- )
345 {
346 calc_a_xor_t( A, t );
347
348 memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
349 memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH );
350
351 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
352 inbuff, 16, outbuff, &olen );
353 if( ret != 0 )
354 goto cleanup;
355
356 memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
357
358 /* Set R as LSB64 of outbuff */
359 memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
360
361 if( R == output )
362 R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
363 else
364 R -= KW_SEMIBLOCK_LENGTH;
365 }
366
367 *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH;
368
369 cleanup:
370 if( ret != 0)
371 memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
372 mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) );
373 mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
374
375 return( ret );
376 }
377
378 /*
379 * KW-AD as defined in SP 800-38F section 6.2
380 * KWP-AD as defined in SP 800-38F section 6.3
381 */
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)382 int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx,
383 mbedtls_nist_kw_mode_t mode,
384 const unsigned char *input, size_t in_len,
385 unsigned char *output, size_t *out_len, size_t out_size )
386 {
387 int ret = 0;
388 size_t i, olen;
389 unsigned char A[KW_SEMIBLOCK_LENGTH];
390 unsigned char diff, bad_padding = 0;
391
392 *out_len = 0;
393 if( out_size < in_len - KW_SEMIBLOCK_LENGTH )
394 {
395 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
396 }
397
398 if( mode == MBEDTLS_KW_MODE_KW )
399 {
400 /*
401 * According to SP 800-38F Table 1, the ciphertext length for KW
402 * must be between 3 to 2^54 semiblocks inclusive.
403 */
404 if( in_len < 24 ||
405 #if SIZE_MAX > 0x200000000000000
406 in_len > 0x200000000000000 ||
407 #endif
408 in_len % KW_SEMIBLOCK_LENGTH != 0 )
409 {
410 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
411 }
412
413 ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
414 A, output, out_len );
415 if( ret != 0 )
416 goto cleanup;
417
418 /* Check ICV in "constant-time" */
419 diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
420
421 if( diff != 0 )
422 {
423 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
424 goto cleanup;
425 }
426
427 }
428 else if( mode == MBEDTLS_KW_MODE_KWP )
429 {
430 size_t padlen = 0;
431 uint32_t Plen;
432 /*
433 * According to SP 800-38F Table 1, the ciphertext length for KWP
434 * must be between 2 to 2^29 semiblocks inclusive.
435 */
436 if( in_len < KW_SEMIBLOCK_LENGTH * 2 ||
437 #if SIZE_MAX > 0x100000000
438 in_len > 0x100000000 ||
439 #endif
440 in_len % KW_SEMIBLOCK_LENGTH != 0 )
441 {
442 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
443 }
444
445 if( in_len == KW_SEMIBLOCK_LENGTH * 2 )
446 {
447 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
448 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
449 input, 16, outbuff, &olen );
450 if( ret != 0 )
451 goto cleanup;
452
453 memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
454 memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
455 mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
456 *out_len = KW_SEMIBLOCK_LENGTH;
457 }
458 else
459 {
460 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
461 ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
462 A, output, out_len );
463 if( ret != 0 )
464 goto cleanup;
465 }
466
467 /* Check ICV in "constant-time" */
468 diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
469
470 if( diff != 0 )
471 {
472 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
473 }
474
475 GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 );
476
477 /*
478 * Plen is the length of the plaintext, when the input is valid.
479 * If Plen is larger than the plaintext and padding, padlen will be
480 * larger than 8, because of the type wrap around.
481 */
482 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
483 if ( padlen > 7 )
484 {
485 padlen &= 7;
486 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
487 }
488
489 /* Check padding in "constant-time" */
490 for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ )
491 {
492 if( i >= KW_SEMIBLOCK_LENGTH - padlen )
493 diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
494 else
495 bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
496 }
497
498 if( diff != 0 )
499 {
500 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
501 }
502
503 if( ret != 0 )
504 {
505 goto cleanup;
506 }
507 memset( output + Plen, 0, padlen );
508 *out_len = Plen;
509 }
510 else
511 {
512 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
513 goto cleanup;
514 }
515
516 cleanup:
517 if( ret != 0 )
518 {
519 memset( output, 0, *out_len );
520 *out_len = 0;
521 }
522
523 mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
524 mbedtls_platform_zeroize( &diff, sizeof( diff ) );
525 mbedtls_platform_zeroize( A, sizeof( A ) );
526
527 return( ret );
528 }
529
530 #endif /* !MBEDTLS_NIST_KW_ALT */
531
532 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
533
534 #define KW_TESTS 3
535
536 /*
537 * Test vectors taken from NIST
538 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
539 */
540 static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
541
542 static const unsigned char kw_key[KW_TESTS][32] = {
543 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
544 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
545 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
546 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
547 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
548 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
549 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
550 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
551 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
552 };
553
554 static const unsigned char kw_msg[KW_TESTS][40] = {
555 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
556 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
557 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
558 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
559 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
560 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
561 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
562 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
563 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
564 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
565 };
566
567 static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
568 static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
569 static const unsigned char kw_res[KW_TESTS][48] = {
570 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
571 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
572 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
573 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
574 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
575 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
576 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
577 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
578 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
579 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
580 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
581 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
582 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
583 };
584
585 static const unsigned char kwp_key[KW_TESTS][32] = {
586 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
587 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
588 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
589 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
590 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
591 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
592 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
593 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
594 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
595 };
596
597 static const unsigned char kwp_msg[KW_TESTS][31] = {
598 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
599 0x96 },
600 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
601 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
602 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
603 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
604 { 0xd1 }
605 };
606 static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
607
608 static const unsigned char kwp_res[KW_TESTS][48] = {
609 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
610 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
611 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
612 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
613 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
614 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
615 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
616 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
617 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
618 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
619 };
620 static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
621
mbedtls_nist_kw_self_test(int verbose)622 int mbedtls_nist_kw_self_test( int verbose )
623 {
624 mbedtls_nist_kw_context ctx;
625 unsigned char out[48];
626 size_t olen;
627 int i;
628 int ret = 0;
629 mbedtls_nist_kw_init( &ctx );
630
631 for( i = 0; i < KW_TESTS; i++ )
632 {
633 if( verbose != 0 )
634 mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 );
635
636 ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
637 kw_key[i], key_len[i] * 8, 1 );
638 if( ret != 0 )
639 {
640 if( verbose != 0 )
641 mbedtls_printf( " KW: setup failed " );
642
643 goto end;
644 }
645
646 ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
647 kw_msg_len[i], out, &olen, sizeof( out ) );
648 if( ret != 0 || kw_out_len[i] != olen ||
649 memcmp( out, kw_res[i], kw_out_len[i] ) != 0 )
650 {
651 if( verbose != 0 )
652 mbedtls_printf( "failed. ");
653
654 ret = 1;
655 goto end;
656 }
657
658 if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
659 kw_key[i], key_len[i] * 8, 0 ) )
660 != 0 )
661 {
662 if( verbose != 0 )
663 mbedtls_printf( " KW: setup failed ");
664
665 goto end;
666 }
667
668 ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW,
669 out, olen, out, &olen, sizeof( out ) );
670
671 if( ret != 0 || olen != kw_msg_len[i] ||
672 memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 )
673 {
674 if( verbose != 0 )
675 mbedtls_printf( "failed\n" );
676
677 ret = 1;
678 goto end;
679 }
680
681 if( verbose != 0 )
682 mbedtls_printf( " passed\n" );
683 }
684
685 for( i = 0; i < KW_TESTS; i++ )
686 {
687 olen = sizeof( out );
688 if( verbose != 0 )
689 mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 );
690
691 ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
692 key_len[i] * 8, 1 );
693 if( ret != 0 )
694 {
695 if( verbose != 0 )
696 mbedtls_printf( " KWP: setup failed " );
697
698 goto end;
699 }
700 ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
701 kwp_msg_len[i], out, &olen, sizeof( out ) );
702
703 if( ret != 0 || kwp_out_len[i] != olen ||
704 memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 )
705 {
706 if( verbose != 0 )
707 mbedtls_printf( "failed. ");
708
709 ret = 1;
710 goto end;
711 }
712
713 if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
714 kwp_key[i], key_len[i] * 8, 0 ) )
715 != 0 )
716 {
717 if( verbose != 0 )
718 mbedtls_printf( " KWP: setup failed ");
719
720 goto end;
721 }
722
723 ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out,
724 olen, out, &olen, sizeof( out ) );
725
726 if( ret != 0 || olen != kwp_msg_len[i] ||
727 memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 )
728 {
729 if( verbose != 0 )
730 mbedtls_printf( "failed. ");
731
732 ret = 1;
733 goto end;
734 }
735
736 if( verbose != 0 )
737 mbedtls_printf( " passed\n" );
738 }
739 end:
740 mbedtls_nist_kw_free( &ctx );
741
742 if( verbose != 0 )
743 mbedtls_printf( "\n" );
744
745 return( ret );
746 }
747
748 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
749
750 #endif /* MBEDTLS_NIST_KW_C */
751