Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
nist_kw.c
00001 /* 00002 * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes 00003 * only 00004 * 00005 * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved 00006 * SPDX-License-Identifier: Apache-2.0 00007 * 00008 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00009 * not use this file except in compliance with the License. 00010 * You may obtain a copy of the License at 00011 * 00012 * http://www.apache.org/licenses/LICENSE-2.0 00013 * 00014 * Unless required by applicable law or agreed to in writing, software 00015 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00016 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00017 * See the License for the specific language governing permissions and 00018 * limitations under the License. 00019 * 00020 * This file is part of Mbed TLS (https://tls.mbed.org) 00021 */ 00022 /* 00023 * Definition of Key Wrapping: 00024 * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf 00025 * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" 00026 * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" 00027 * 00028 * Note: RFC 3394 defines different methodology for intermediate operations for 00029 * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. 00030 */ 00031 00032 #if !defined(MBEDTLS_CONFIG_FILE) 00033 #include "mbedtls/config.h" 00034 #else 00035 #include MBEDTLS_CONFIG_FILE 00036 #endif 00037 00038 #if defined(MBEDTLS_NIST_KW_C) 00039 00040 #include "mbedtls/nist_kw.h" 00041 #include "mbedtls/platform_util.h" 00042 00043 #include <stdint.h> 00044 #include <string.h> 00045 00046 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 00047 #if defined(MBEDTLS_PLATFORM_C) 00048 #include "mbedtls/platform.h" 00049 #else 00050 #include <stdio.h> 00051 #define mbedtls_printf printf 00052 #endif /* MBEDTLS_PLATFORM_C */ 00053 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 00054 00055 #if !defined(MBEDTLS_NIST_KW_ALT) 00056 00057 #define KW_SEMIBLOCK_LENGTH 8 00058 #define MIN_SEMIBLOCKS_COUNT 3 00059 00060 /* constant-time buffer comparison */ 00061 static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n ) 00062 { 00063 size_t i; 00064 volatile const unsigned char *A = (volatile const unsigned char *) a; 00065 volatile const unsigned char *B = (volatile const unsigned char *) b; 00066 volatile unsigned char diff = 0; 00067 00068 for( i = 0; i < n; i++ ) 00069 { 00070 /* Read volatile data in order before computing diff. 00071 * This avoids IAR compiler warning: 00072 * 'the order of volatile accesses is undefined ..' */ 00073 unsigned char x = A[i], y = B[i]; 00074 diff |= x ^ y; 00075 } 00076 00077 return( diff ); 00078 } 00079 00080 /*! The 64-bit default integrity check value (ICV) for KW mode. */ 00081 static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; 00082 /*! The 32-bit default integrity check value (ICV) for KWP mode. */ 00083 static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; 00084 00085 #ifndef GET_UINT32_BE 00086 #define GET_UINT32_BE(n,b,i) \ 00087 do { \ 00088 (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ 00089 | ( (uint32_t) (b)[(i) + 1] << 16 ) \ 00090 | ( (uint32_t) (b)[(i) + 2] << 8 ) \ 00091 | ( (uint32_t) (b)[(i) + 3] ); \ 00092 } while( 0 ) 00093 #endif 00094 00095 #ifndef PUT_UINT32_BE 00096 #define PUT_UINT32_BE(n,b,i) \ 00097 do { \ 00098 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ 00099 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ 00100 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ 00101 (b)[(i) + 3] = (unsigned char) ( (n) ); \ 00102 } while( 0 ) 00103 #endif 00104 00105 /* 00106 * Initialize context 00107 */ 00108 void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) 00109 { 00110 memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); 00111 } 00112 00113 int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, 00114 mbedtls_cipher_id_t cipher, 00115 const unsigned char *key, 00116 unsigned int keybits, 00117 const int is_wrap ) 00118 { 00119 int ret; 00120 const mbedtls_cipher_info_t *cipher_info; 00121 00122 cipher_info = mbedtls_cipher_info_from_values( cipher, 00123 keybits, 00124 MBEDTLS_MODE_ECB ); 00125 if( cipher_info == NULL ) 00126 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00127 00128 if( cipher_info->block_size != 16 ) 00129 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00130 00131 /* 00132 * SP 800-38F currently defines AES cipher as the only block cipher allowed: 00133 * "For KW and KWP, the underlying block cipher shall be approved, and the 00134 * block size shall be 128 bits. Currently, the AES block cipher, with key 00135 * lengths of 128, 192, or 256 bits, is the only block cipher that fits 00136 * this profile." 00137 * Currently we don't support other 128 bit block ciphers for key wrapping, 00138 * such as Camellia and Aria. 00139 */ 00140 if( cipher != MBEDTLS_CIPHER_ID_AES ) 00141 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 00142 00143 mbedtls_cipher_free( &ctx->cipher_ctx ); 00144 00145 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx , cipher_info ) ) != 0 ) 00146 return( ret ); 00147 00148 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx , key, keybits, 00149 is_wrap ? MBEDTLS_ENCRYPT : 00150 MBEDTLS_DECRYPT ) 00151 ) != 0 ) 00152 { 00153 return( ret ); 00154 } 00155 00156 return( 0 ); 00157 } 00158 00159 /* 00160 * Free context 00161 */ 00162 void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) 00163 { 00164 mbedtls_cipher_free( &ctx->cipher_ctx ); 00165 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); 00166 } 00167 00168 /* 00169 * Helper function for Xoring the uint64_t "t" with the encrypted A. 00170 * Defined in NIST SP 800-38F section 6.1 00171 */ 00172 static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) 00173 { 00174 size_t i = 0; 00175 for( i = 0; i < sizeof( t ); i++ ) 00176 { 00177 A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; 00178 } 00179 } 00180 00181 /* 00182 * KW-AE as defined in SP 800-38F section 6.2 00183 * KWP-AE as defined in SP 800-38F section 6.3 00184 */ 00185 int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, 00186 mbedtls_nist_kw_mode_t mode, 00187 const unsigned char *input, size_t in_len, 00188 unsigned char *output, size_t *out_len, size_t out_size ) 00189 { 00190 int ret = 0; 00191 size_t semiblocks = 0; 00192 size_t s; 00193 size_t olen, padlen = 0; 00194 uint64_t t = 0; 00195 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; 00196 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; 00197 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; 00198 unsigned char *A = output; 00199 00200 *out_len = 0; 00201 /* 00202 * Generate the String to work on 00203 */ 00204 if( mode == MBEDTLS_KW_MODE_KW ) 00205 { 00206 if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) 00207 { 00208 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00209 } 00210 00211 /* 00212 * According to SP 800-38F Table 1, the plaintext length for KW 00213 * must be between 2 to 2^54-1 semiblocks inclusive. 00214 */ 00215 if( in_len < 16 || 00216 #if SIZE_MAX > 0x1FFFFFFFFFFFFF8 00217 in_len > 0x1FFFFFFFFFFFFF8 || 00218 #endif 00219 in_len % KW_SEMIBLOCK_LENGTH != 0 ) 00220 { 00221 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00222 } 00223 00224 memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); 00225 memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); 00226 } 00227 else 00228 { 00229 if( in_len % 8 != 0 ) 00230 { 00231 padlen = ( 8 - ( in_len % 8 ) ); 00232 } 00233 00234 if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) 00235 { 00236 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00237 } 00238 00239 /* 00240 * According to SP 800-38F Table 1, the plaintext length for KWP 00241 * must be between 1 and 2^32-1 octets inclusive. 00242 */ 00243 if( in_len < 1 00244 #if SIZE_MAX > 0xFFFFFFFF 00245 || in_len > 0xFFFFFFFF 00246 #endif 00247 ) 00248 { 00249 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00250 } 00251 00252 memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); 00253 PUT_UINT32_BE( ( in_len & 0xffffffff ), output, 00254 KW_SEMIBLOCK_LENGTH / 2 ); 00255 00256 memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); 00257 memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); 00258 } 00259 semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; 00260 00261 s = 6 * ( semiblocks - 1 ); 00262 00263 if( mode == MBEDTLS_KW_MODE_KWP 00264 && in_len <= KW_SEMIBLOCK_LENGTH ) 00265 { 00266 memcpy( inbuff, output, 16 ); 00267 ret = mbedtls_cipher_update( &ctx->cipher_ctx , 00268 inbuff, 16, output, &olen ); 00269 if( ret != 0 ) 00270 goto cleanup; 00271 } 00272 else 00273 { 00274 /* 00275 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 00276 */ 00277 if( semiblocks < MIN_SEMIBLOCKS_COUNT ) 00278 { 00279 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 00280 goto cleanup; 00281 } 00282 00283 /* Calculate intermediate values */ 00284 for( t = 1; t <= s; t++ ) 00285 { 00286 memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); 00287 memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); 00288 00289 ret = mbedtls_cipher_update( &ctx->cipher_ctx , 00290 inbuff, 16, outbuff, &olen ); 00291 if( ret != 0 ) 00292 goto cleanup; 00293 00294 memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); 00295 calc_a_xor_t( A, t ); 00296 00297 memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); 00298 R2 += KW_SEMIBLOCK_LENGTH; 00299 if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) 00300 R2 = output + KW_SEMIBLOCK_LENGTH; 00301 } 00302 } 00303 00304 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; 00305 00306 cleanup: 00307 00308 if( ret != 0) 00309 { 00310 memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); 00311 } 00312 mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); 00313 mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); 00314 mbedtls_cipher_finish( &ctx->cipher_ctx , NULL, &olen ); 00315 return( ret ); 00316 } 00317 00318 /* 00319 * W-1 function as defined in RFC 3394 section 2.2.2 00320 * This function assumes the following: 00321 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. 00322 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. 00323 * 3. Minimal number of semiblocks is 3. 00324 * 4. A is a buffer to hold the first semiblock of the input buffer. 00325 */ 00326 static int unwrap( mbedtls_nist_kw_context *ctx, 00327 const unsigned char *input, size_t semiblocks, 00328 unsigned char A[KW_SEMIBLOCK_LENGTH], 00329 unsigned char *output, size_t* out_len ) 00330 { 00331 int ret = 0; 00332 const size_t s = 6 * ( semiblocks - 1 ); 00333 size_t olen; 00334 uint64_t t = 0; 00335 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; 00336 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; 00337 unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; 00338 *out_len = 0; 00339 00340 if( semiblocks < MIN_SEMIBLOCKS_COUNT ) 00341 { 00342 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00343 } 00344 00345 memcpy( A, input, KW_SEMIBLOCK_LENGTH ); 00346 memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); 00347 00348 /* Calculate intermediate values */ 00349 for( t = s; t >= 1; t-- ) 00350 { 00351 calc_a_xor_t( A, t ); 00352 00353 memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); 00354 memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); 00355 00356 ret = mbedtls_cipher_update( &ctx->cipher_ctx , 00357 inbuff, 16, outbuff, &olen ); 00358 if( ret != 0 ) 00359 goto cleanup; 00360 00361 memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); 00362 00363 /* Set R as LSB64 of outbuff */ 00364 memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); 00365 00366 if( R == output ) 00367 R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; 00368 else 00369 R -= KW_SEMIBLOCK_LENGTH; 00370 } 00371 00372 *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; 00373 00374 cleanup: 00375 if( ret != 0) 00376 memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); 00377 mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); 00378 mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); 00379 00380 return( ret ); 00381 } 00382 00383 /* 00384 * KW-AD as defined in SP 800-38F section 6.2 00385 * KWP-AD as defined in SP 800-38F section 6.3 00386 */ 00387 int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, 00388 mbedtls_nist_kw_mode_t mode, 00389 const unsigned char *input, size_t in_len, 00390 unsigned char *output, size_t *out_len, size_t out_size ) 00391 { 00392 int ret = 0; 00393 size_t i, olen; 00394 unsigned char A[KW_SEMIBLOCK_LENGTH]; 00395 unsigned char diff, bad_padding = 0; 00396 00397 *out_len = 0; 00398 if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) 00399 { 00400 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00401 } 00402 00403 if( mode == MBEDTLS_KW_MODE_KW ) 00404 { 00405 /* 00406 * According to SP 800-38F Table 1, the ciphertext length for KW 00407 * must be between 3 to 2^54 semiblocks inclusive. 00408 */ 00409 if( in_len < 24 || 00410 #if SIZE_MAX > 0x200000000000000 00411 in_len > 0x200000000000000 || 00412 #endif 00413 in_len % KW_SEMIBLOCK_LENGTH != 0 ) 00414 { 00415 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00416 } 00417 00418 ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, 00419 A, output, out_len ); 00420 if( ret != 0 ) 00421 goto cleanup; 00422 00423 /* Check ICV in "constant-time" */ 00424 diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); 00425 00426 if( diff != 0 ) 00427 { 00428 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 00429 goto cleanup; 00430 } 00431 00432 } 00433 else if( mode == MBEDTLS_KW_MODE_KWP ) 00434 { 00435 size_t padlen = 0; 00436 uint32_t Plen; 00437 /* 00438 * According to SP 800-38F Table 1, the ciphertext length for KWP 00439 * must be between 2 to 2^29 semiblocks inclusive. 00440 */ 00441 if( in_len < KW_SEMIBLOCK_LENGTH * 2 || 00442 #if SIZE_MAX > 0x100000000 00443 in_len > 0x100000000 || 00444 #endif 00445 in_len % KW_SEMIBLOCK_LENGTH != 0 ) 00446 { 00447 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 00448 } 00449 00450 if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) 00451 { 00452 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; 00453 ret = mbedtls_cipher_update( &ctx->cipher_ctx , 00454 input, 16, outbuff, &olen ); 00455 if( ret != 0 ) 00456 goto cleanup; 00457 00458 memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); 00459 memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); 00460 mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); 00461 *out_len = KW_SEMIBLOCK_LENGTH; 00462 } 00463 else 00464 { 00465 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ 00466 ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, 00467 A, output, out_len ); 00468 if( ret != 0 ) 00469 goto cleanup; 00470 } 00471 00472 /* Check ICV in "constant-time" */ 00473 diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); 00474 00475 if( diff != 0 ) 00476 { 00477 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 00478 } 00479 00480 GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 ); 00481 00482 /* 00483 * Plen is the length of the plaintext, when the input is valid. 00484 * If Plen is larger than the plaintext and padding, padlen will be 00485 * larger than 8, because of the type wrap around. 00486 */ 00487 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; 00488 if ( padlen > 7 ) 00489 { 00490 padlen &= 7; 00491 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 00492 } 00493 00494 /* Check padding in "constant-time" */ 00495 for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) 00496 { 00497 if( i >= KW_SEMIBLOCK_LENGTH - padlen ) 00498 diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; 00499 else 00500 bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; 00501 } 00502 00503 if( diff != 0 ) 00504 { 00505 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 00506 } 00507 00508 if( ret != 0 ) 00509 { 00510 goto cleanup; 00511 } 00512 memset( output + Plen, 0, padlen ); 00513 *out_len = Plen; 00514 } 00515 else 00516 { 00517 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 00518 goto cleanup; 00519 } 00520 00521 cleanup: 00522 if( ret != 0 ) 00523 { 00524 memset( output, 0, *out_len ); 00525 *out_len = 0; 00526 } 00527 00528 mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); 00529 mbedtls_platform_zeroize( &diff, sizeof( diff ) ); 00530 mbedtls_platform_zeroize( A, sizeof( A ) ); 00531 mbedtls_cipher_finish( &ctx->cipher_ctx , NULL, &olen ); 00532 return( ret ); 00533 } 00534 00535 #endif /* !MBEDTLS_NIST_KW_ALT */ 00536 00537 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 00538 00539 #define KW_TESTS 3 00540 00541 /* 00542 * Test vectors taken from NIST 00543 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW 00544 */ 00545 static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; 00546 00547 static const unsigned char kw_key[KW_TESTS][32] = { 00548 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, 00549 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, 00550 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, 00551 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, 00552 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, 00553 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, 00554 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, 00555 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, 00556 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } 00557 }; 00558 00559 static const unsigned char kw_msg[KW_TESTS][40] = { 00560 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, 00561 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, 00562 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, 00563 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, 00564 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, 00565 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, 00566 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, 00567 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, 00568 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, 00569 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } 00570 }; 00571 00572 static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; 00573 static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; 00574 static const unsigned char kw_res[KW_TESTS][48] = { 00575 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, 00576 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, 00577 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, 00578 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, 00579 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, 00580 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, 00581 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, 00582 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, 00583 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, 00584 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, 00585 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, 00586 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, 00587 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } 00588 }; 00589 00590 static const unsigned char kwp_key[KW_TESTS][32] = { 00591 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, 00592 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, 00593 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, 00594 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, 00595 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, 00596 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, 00597 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, 00598 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, 00599 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } 00600 }; 00601 00602 static const unsigned char kwp_msg[KW_TESTS][31] = { 00603 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, 00604 0x96 }, 00605 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, 00606 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, 00607 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, 00608 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, 00609 { 0xd1 } 00610 }; 00611 static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; 00612 00613 static const unsigned char kwp_res[KW_TESTS][48] = { 00614 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, 00615 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, 00616 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, 00617 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, 00618 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, 00619 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, 00620 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, 00621 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, 00622 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, 00623 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } 00624 }; 00625 static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; 00626 00627 int mbedtls_nist_kw_self_test( int verbose ) 00628 { 00629 mbedtls_nist_kw_context ctx; 00630 unsigned char out[48]; 00631 size_t olen; 00632 int i; 00633 int ret = 0; 00634 mbedtls_nist_kw_init( &ctx ); 00635 00636 for( i = 0; i < KW_TESTS; i++ ) 00637 { 00638 if( verbose != 0 ) 00639 mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); 00640 00641 ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, 00642 kw_key[i], key_len[i] * 8, 1 ); 00643 if( ret != 0 ) 00644 { 00645 if( verbose != 0 ) 00646 mbedtls_printf( " KW: setup failed " ); 00647 00648 goto end; 00649 } 00650 00651 ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], 00652 kw_msg_len[i], out, &olen, sizeof( out ) ); 00653 if( ret != 0 || kw_out_len[i] != olen || 00654 memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) 00655 { 00656 if( verbose != 0 ) 00657 mbedtls_printf( "failed. "); 00658 00659 ret = 1; 00660 goto end; 00661 } 00662 00663 if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, 00664 kw_key[i], key_len[i] * 8, 0 ) ) 00665 != 0 ) 00666 { 00667 if( verbose != 0 ) 00668 mbedtls_printf( " KW: setup failed "); 00669 00670 goto end; 00671 } 00672 00673 ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, 00674 out, olen, out, &olen, sizeof( out ) ); 00675 00676 if( ret != 0 || olen != kw_msg_len[i] || 00677 memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) 00678 { 00679 if( verbose != 0 ) 00680 mbedtls_printf( "failed\n" ); 00681 00682 ret = 1; 00683 goto end; 00684 } 00685 00686 if( verbose != 0 ) 00687 mbedtls_printf( " passed\n" ); 00688 } 00689 00690 for( i = 0; i < KW_TESTS; i++ ) 00691 { 00692 olen = sizeof( out ); 00693 if( verbose != 0 ) 00694 mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); 00695 00696 ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], 00697 key_len[i] * 8, 1 ); 00698 if( ret != 0 ) 00699 { 00700 if( verbose != 0 ) 00701 mbedtls_printf( " KWP: setup failed " ); 00702 00703 goto end; 00704 } 00705 ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], 00706 kwp_msg_len[i], out, &olen, sizeof( out ) ); 00707 00708 if( ret != 0 || kwp_out_len[i] != olen || 00709 memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) 00710 { 00711 if( verbose != 0 ) 00712 mbedtls_printf( "failed. "); 00713 00714 ret = 1; 00715 goto end; 00716 } 00717 00718 if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, 00719 kwp_key[i], key_len[i] * 8, 0 ) ) 00720 != 0 ) 00721 { 00722 if( verbose != 0 ) 00723 mbedtls_printf( " KWP: setup failed "); 00724 00725 goto end; 00726 } 00727 00728 ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, 00729 olen, out, &olen, sizeof( out ) ); 00730 00731 if( ret != 0 || olen != kwp_msg_len[i] || 00732 memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) 00733 { 00734 if( verbose != 0 ) 00735 mbedtls_printf( "failed. "); 00736 00737 ret = 1; 00738 goto end; 00739 } 00740 00741 if( verbose != 0 ) 00742 mbedtls_printf( " passed\n" ); 00743 } 00744 end: 00745 mbedtls_nist_kw_free( &ctx ); 00746 00747 if( verbose != 0 ) 00748 mbedtls_printf( "\n" ); 00749 00750 return( ret ); 00751 } 00752 00753 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 00754 00755 #endif /* MBEDTLS_NIST_KW_C */
Generated on Tue Aug 9 2022 00:37:16 by
1.7.2