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