2 * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes
\r
5 * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved
\r
6 * SPDX-License-Identifier: Apache-2.0
\r
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
\r
9 * not use this file except in compliance with the License.
\r
10 * You may obtain a copy of the License at
\r
12 * http://www.apache.org/licenses/LICENSE-2.0
\r
14 * Unless required by applicable law or agreed to in writing, software
\r
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
\r
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
17 * See the License for the specific language governing permissions and
\r
18 * limitations under the License.
\r
20 * This file is part of Mbed TLS (https://tls.mbed.org)
\r
23 * Definition of Key Wrapping:
\r
24 * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
\r
25 * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
\r
26 * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
\r
28 * Note: RFC 3394 defines different methodology for intermediate operations for
\r
29 * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
\r
32 #if !defined(MBEDTLS_CONFIG_FILE)
\r
33 #include "mbedtls/config.h"
\r
35 #include MBEDTLS_CONFIG_FILE
\r
38 #if defined(MBEDTLS_NIST_KW_C)
\r
40 #include "mbedtls/nist_kw.h"
\r
41 #include "mbedtls/platform_util.h"
\r
46 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
\r
47 #if defined(MBEDTLS_PLATFORM_C)
\r
48 #include "mbedtls/platform.h"
\r
51 #define mbedtls_printf printf
\r
52 #endif /* MBEDTLS_PLATFORM_C */
\r
53 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
\r
55 #if !defined(MBEDTLS_NIST_KW_ALT)
\r
57 #define KW_SEMIBLOCK_LENGTH 8
\r
58 #define MIN_SEMIBLOCKS_COUNT 3
\r
60 /* constant-time buffer comparison */
\r
61 static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n )
\r
64 volatile const unsigned char *A = (volatile const unsigned char *) a;
\r
65 volatile const unsigned char *B = (volatile const unsigned char *) b;
\r
66 volatile unsigned char diff = 0;
\r
68 for( i = 0; i < n; i++ )
\r
70 /* Read volatile data in order before computing diff.
\r
71 * This avoids IAR compiler warning:
\r
72 * 'the order of volatile accesses is undefined ..' */
\r
73 unsigned char x = A[i], y = B[i];
\r
80 /*! The 64-bit default integrity check value (ICV) for KW mode. */
\r
81 static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
\r
82 /*! The 32-bit default integrity check value (ICV) for KWP mode. */
\r
83 static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6};
\r
85 #ifndef GET_UINT32_BE
\r
86 #define GET_UINT32_BE(n,b,i) \
\r
88 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
\r
89 | ( (uint32_t) (b)[(i) + 1] << 16 ) \
\r
90 | ( (uint32_t) (b)[(i) + 2] << 8 ) \
\r
91 | ( (uint32_t) (b)[(i) + 3] ); \
\r
95 #ifndef PUT_UINT32_BE
\r
96 #define PUT_UINT32_BE(n,b,i) \
\r
98 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
\r
99 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
\r
100 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
\r
101 (b)[(i) + 3] = (unsigned char) ( (n) ); \
\r
106 * Initialize context
\r
108 void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx )
\r
110 memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) );
\r
113 int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
\r
114 mbedtls_cipher_id_t cipher,
\r
115 const unsigned char *key,
\r
116 unsigned int keybits,
\r
117 const int is_wrap )
\r
120 const mbedtls_cipher_info_t *cipher_info;
\r
122 cipher_info = mbedtls_cipher_info_from_values( cipher,
\r
124 MBEDTLS_MODE_ECB );
\r
125 if( cipher_info == NULL )
\r
126 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
128 if( cipher_info->block_size != 16 )
\r
129 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
132 * SP 800-38F currently defines AES cipher as the only block cipher allowed:
\r
133 * "For KW and KWP, the underlying block cipher shall be approved, and the
\r
134 * block size shall be 128 bits. Currently, the AES block cipher, with key
\r
135 * lengths of 128, 192, or 256 bits, is the only block cipher that fits
\r
137 * Currently we don't support other 128 bit block ciphers for key wrapping,
\r
138 * such as Camellia and Aria.
\r
140 if( cipher != MBEDTLS_CIPHER_ID_AES )
\r
141 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
\r
143 mbedtls_cipher_free( &ctx->cipher_ctx );
\r
145 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
\r
148 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
\r
149 is_wrap ? MBEDTLS_ENCRYPT :
\r
162 void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx )
\r
164 mbedtls_cipher_free( &ctx->cipher_ctx );
\r
165 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) );
\r
169 * Helper function for Xoring the uint64_t "t" with the encrypted A.
\r
170 * Defined in NIST SP 800-38F section 6.1
\r
172 static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t )
\r
175 for( i = 0; i < sizeof( t ); i++ )
\r
177 A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff;
\r
182 * KW-AE as defined in SP 800-38F section 6.2
\r
183 * KWP-AE as defined in SP 800-38F section 6.3
\r
185 int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx,
\r
186 mbedtls_nist_kw_mode_t mode,
\r
187 const unsigned char *input, size_t in_len,
\r
188 unsigned char *output, size_t *out_len, size_t out_size )
\r
191 size_t semiblocks = 0;
\r
193 size_t olen, padlen = 0;
\r
195 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
\r
196 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
\r
197 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
\r
198 unsigned char *A = output;
\r
202 * Generate the String to work on
\r
204 if( mode == MBEDTLS_KW_MODE_KW )
\r
206 if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
\r
208 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
212 * According to SP 800-38F Table 1, the plaintext length for KW
\r
213 * must be between 2 to 2^54-1 semiblocks inclusive.
\r
216 #if SIZE_MAX > 0x1FFFFFFFFFFFFF8
\r
217 in_len > 0x1FFFFFFFFFFFFF8 ||
\r
219 in_len % KW_SEMIBLOCK_LENGTH != 0 )
\r
221 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
224 memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
\r
225 memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
\r
229 if( in_len % 8 != 0 )
\r
231 padlen = ( 8 - ( in_len % 8 ) );
\r
234 if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen )
\r
236 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
240 * According to SP 800-38F Table 1, the plaintext length for KWP
\r
241 * must be between 1 and 2^32-1 octets inclusive.
\r
244 #if SIZE_MAX > 0xFFFFFFFF
\r
245 || in_len > 0xFFFFFFFF
\r
249 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
252 memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
\r
253 PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
\r
254 KW_SEMIBLOCK_LENGTH / 2 );
\r
256 memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
\r
257 memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen );
\r
259 semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1;
\r
261 s = 6 * ( semiblocks - 1 );
\r
263 if( mode == MBEDTLS_KW_MODE_KWP
\r
264 && in_len <= KW_SEMIBLOCK_LENGTH )
\r
266 memcpy( inbuff, output, 16 );
\r
267 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
\r
268 inbuff, 16, output, &olen );
\r
275 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
\r
277 if( semiblocks < MIN_SEMIBLOCKS_COUNT )
\r
279 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
\r
283 /* Calculate intermediate values */
\r
284 for( t = 1; t <= s; t++ )
\r
286 memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
\r
287 memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH );
\r
289 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
\r
290 inbuff, 16, outbuff, &olen );
\r
294 memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
\r
295 calc_a_xor_t( A, t );
\r
297 memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
\r
298 R2 += KW_SEMIBLOCK_LENGTH;
\r
299 if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) )
\r
300 R2 = output + KW_SEMIBLOCK_LENGTH;
\r
304 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
\r
310 memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH );
\r
312 mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
\r
313 mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
\r
319 * W-1 function as defined in RFC 3394 section 2.2.2
\r
320 * This function assumes the following:
\r
321 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
\r
322 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
\r
323 * 3. Minimal number of semiblocks is 3.
\r
324 * 4. A is a buffer to hold the first semiblock of the input buffer.
\r
326 static int unwrap( mbedtls_nist_kw_context *ctx,
\r
327 const unsigned char *input, size_t semiblocks,
\r
328 unsigned char A[KW_SEMIBLOCK_LENGTH],
\r
329 unsigned char *output, size_t* out_len )
\r
332 const size_t s = 6 * ( semiblocks - 1 );
\r
335 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
\r
336 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
\r
337 unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
\r
340 if( semiblocks < MIN_SEMIBLOCKS_COUNT )
\r
342 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
345 memcpy( A, input, KW_SEMIBLOCK_LENGTH );
\r
346 memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
\r
348 /* Calculate intermediate values */
\r
349 for( t = s; t >= 1; t-- )
\r
351 calc_a_xor_t( A, t );
\r
353 memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
\r
354 memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH );
\r
356 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
\r
357 inbuff, 16, outbuff, &olen );
\r
361 memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
\r
363 /* Set R as LSB64 of outbuff */
\r
364 memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
\r
367 R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
\r
369 R -= KW_SEMIBLOCK_LENGTH;
\r
372 *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH;
\r
376 memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
\r
377 mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) );
\r
378 mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
\r
384 * KW-AD as defined in SP 800-38F section 6.2
\r
385 * KWP-AD as defined in SP 800-38F section 6.3
\r
387 int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx,
\r
388 mbedtls_nist_kw_mode_t mode,
\r
389 const unsigned char *input, size_t in_len,
\r
390 unsigned char *output, size_t *out_len, size_t out_size )
\r
394 unsigned char A[KW_SEMIBLOCK_LENGTH];
\r
395 unsigned char diff, bad_padding = 0;
\r
398 if( out_size < in_len - KW_SEMIBLOCK_LENGTH )
\r
400 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
403 if( mode == MBEDTLS_KW_MODE_KW )
\r
406 * According to SP 800-38F Table 1, the ciphertext length for KW
\r
407 * must be between 3 to 2^54 semiblocks inclusive.
\r
410 #if SIZE_MAX > 0x200000000000000
\r
411 in_len > 0x200000000000000 ||
\r
413 in_len % KW_SEMIBLOCK_LENGTH != 0 )
\r
415 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
418 ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
\r
419 A, output, out_len );
\r
423 /* Check ICV in "constant-time" */
\r
424 diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
\r
428 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
\r
433 else if( mode == MBEDTLS_KW_MODE_KWP )
\r
438 * According to SP 800-38F Table 1, the ciphertext length for KWP
\r
439 * must be between 2 to 2^29 semiblocks inclusive.
\r
441 if( in_len < KW_SEMIBLOCK_LENGTH * 2 ||
\r
442 #if SIZE_MAX > 0x100000000
\r
443 in_len > 0x100000000 ||
\r
445 in_len % KW_SEMIBLOCK_LENGTH != 0 )
\r
447 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
\r
450 if( in_len == KW_SEMIBLOCK_LENGTH * 2 )
\r
452 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
\r
453 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
\r
454 input, 16, outbuff, &olen );
\r
458 memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
\r
459 memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
\r
460 mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
\r
461 *out_len = KW_SEMIBLOCK_LENGTH;
\r
465 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
\r
466 ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
\r
467 A, output, out_len );
\r
472 /* Check ICV in "constant-time" */
\r
473 diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
\r
477 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
\r
480 GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 );
\r
483 * Plen is the length of the plaintext, when the input is valid.
\r
484 * If Plen is larger than the plaintext and padding, padlen will be
\r
485 * larger than 8, because of the type wrap around.
\r
487 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
\r
491 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
\r
494 /* Check padding in "constant-time" */
\r
495 for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ )
\r
497 if( i >= KW_SEMIBLOCK_LENGTH - padlen )
\r
498 diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
\r
500 bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
\r
505 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
\r
512 memset( output + Plen, 0, padlen );
\r
517 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
\r
524 memset( output, 0, *out_len );
\r
528 mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
\r
529 mbedtls_platform_zeroize( &diff, sizeof( diff ) );
\r
530 mbedtls_platform_zeroize( A, sizeof( A ) );
\r
535 #endif /* !MBEDTLS_NIST_KW_ALT */
\r
537 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
\r
542 * Test vectors taken from NIST
\r
543 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
\r
545 static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
\r
547 static const unsigned char kw_key[KW_TESTS][32] = {
\r
548 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
\r
549 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
\r
550 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
\r
551 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
\r
552 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
\r
553 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
\r
554 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
\r
555 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
\r
556 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
\r
559 static const unsigned char kw_msg[KW_TESTS][40] = {
\r
560 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
\r
561 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
\r
562 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
\r
563 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
\r
564 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
\r
565 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
\r
566 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
\r
567 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
\r
568 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
\r
569 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
\r
572 static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
\r
573 static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
\r
574 static const unsigned char kw_res[KW_TESTS][48] = {
\r
575 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
\r
576 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
\r
577 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
\r
578 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
\r
579 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
\r
580 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
\r
581 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
\r
582 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
\r
583 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
\r
584 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
\r
585 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
\r
586 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
\r
587 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
\r
590 static const unsigned char kwp_key[KW_TESTS][32] = {
\r
591 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
\r
592 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
\r
593 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
\r
594 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
\r
595 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
\r
596 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
\r
597 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
\r
598 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
\r
599 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
\r
602 static const unsigned char kwp_msg[KW_TESTS][31] = {
\r
603 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
\r
605 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
\r
606 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
\r
607 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
\r
608 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
\r
611 static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
\r
613 static const unsigned char kwp_res[KW_TESTS][48] = {
\r
614 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
\r
615 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
\r
616 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
\r
617 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
\r
618 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
\r
619 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
\r
620 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
\r
621 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
\r
622 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
\r
623 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
\r
625 static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
\r
627 int mbedtls_nist_kw_self_test( int verbose )
\r
629 mbedtls_nist_kw_context ctx;
\r
630 unsigned char out[48];
\r
634 mbedtls_nist_kw_init( &ctx );
\r
636 for( i = 0; i < KW_TESTS; i++ )
\r
639 mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 );
\r
641 ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
\r
642 kw_key[i], key_len[i] * 8, 1 );
\r
646 mbedtls_printf( " KW: setup failed " );
\r
651 ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
\r
652 kw_msg_len[i], out, &olen, sizeof( out ) );
\r
653 if( ret != 0 || kw_out_len[i] != olen ||
\r
654 memcmp( out, kw_res[i], kw_out_len[i] ) != 0 )
\r
657 mbedtls_printf( "failed. ");
\r
663 if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
\r
664 kw_key[i], key_len[i] * 8, 0 ) )
\r
668 mbedtls_printf( " KW: setup failed ");
\r
673 ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW,
\r
674 out, olen, out, &olen, sizeof( out ) );
\r
676 if( ret != 0 || olen != kw_msg_len[i] ||
\r
677 memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 )
\r
680 mbedtls_printf( "failed\n" );
\r
687 mbedtls_printf( " passed\n" );
\r
690 for( i = 0; i < KW_TESTS; i++ )
\r
692 olen = sizeof( out );
\r
694 mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 );
\r
696 ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
\r
697 key_len[i] * 8, 1 );
\r
701 mbedtls_printf( " KWP: setup failed " );
\r
705 ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
\r
706 kwp_msg_len[i], out, &olen, sizeof( out ) );
\r
708 if( ret != 0 || kwp_out_len[i] != olen ||
\r
709 memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 )
\r
712 mbedtls_printf( "failed. ");
\r
718 if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
\r
719 kwp_key[i], key_len[i] * 8, 0 ) )
\r
723 mbedtls_printf( " KWP: setup failed ");
\r
728 ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out,
\r
729 olen, out, &olen, sizeof( out ) );
\r
731 if( ret != 0 || olen != kwp_msg_len[i] ||
\r
732 memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 )
\r
735 mbedtls_printf( "failed. ");
\r
742 mbedtls_printf( " passed\n" );
\r
745 mbedtls_nist_kw_free( &ctx );
\r
748 mbedtls_printf( "\n" );
\r
753 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
\r
755 #endif /* MBEDTLS_NIST_KW_C */
\r