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