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