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