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