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