13d3b0591SJens Wiklander /* 23d3b0591SJens Wiklander * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes 33d3b0591SJens Wiklander * only 43d3b0591SJens Wiklander * 5*7901324dSJerome Forissier * Copyright The Mbed TLS Contributors 6*7901324dSJerome Forissier * SPDX-License-Identifier: Apache-2.0 73d3b0591SJens Wiklander * 83d3b0591SJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 93d3b0591SJens Wiklander * not use this file except in compliance with the License. 103d3b0591SJens Wiklander * You may obtain a copy of the License at 113d3b0591SJens Wiklander * 123d3b0591SJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 133d3b0591SJens Wiklander * 143d3b0591SJens Wiklander * Unless required by applicable law or agreed to in writing, software 153d3b0591SJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 163d3b0591SJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 173d3b0591SJens Wiklander * See the License for the specific language governing permissions and 183d3b0591SJens Wiklander * limitations under the License. 193d3b0591SJens Wiklander */ 203d3b0591SJens Wiklander /* 213d3b0591SJens Wiklander * Definition of Key Wrapping: 223d3b0591SJens Wiklander * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf 233d3b0591SJens Wiklander * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" 243d3b0591SJens Wiklander * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" 253d3b0591SJens Wiklander * 263d3b0591SJens Wiklander * Note: RFC 3394 defines different methodology for intermediate operations for 273d3b0591SJens Wiklander * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. 283d3b0591SJens Wiklander */ 293d3b0591SJens Wiklander 30*7901324dSJerome Forissier #include "common.h" 313d3b0591SJens Wiklander 323d3b0591SJens Wiklander #if defined(MBEDTLS_NIST_KW_C) 333d3b0591SJens Wiklander 343d3b0591SJens Wiklander #include "mbedtls/nist_kw.h" 353d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 3611fa71b9SJerome Forissier #include "mbedtls/error.h" 373d3b0591SJens Wiklander 383d3b0591SJens Wiklander #include <stdint.h> 393d3b0591SJens Wiklander #include <string.h> 403d3b0591SJens Wiklander 413d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 423d3b0591SJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 433d3b0591SJens Wiklander #include "mbedtls/platform.h" 443d3b0591SJens Wiklander #else 453d3b0591SJens Wiklander #include <stdio.h> 463d3b0591SJens Wiklander #define mbedtls_printf printf 473d3b0591SJens Wiklander #endif /* MBEDTLS_PLATFORM_C */ 483d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 493d3b0591SJens Wiklander 503d3b0591SJens Wiklander #if !defined(MBEDTLS_NIST_KW_ALT) 513d3b0591SJens Wiklander 523d3b0591SJens Wiklander #define KW_SEMIBLOCK_LENGTH 8 533d3b0591SJens Wiklander #define MIN_SEMIBLOCKS_COUNT 3 543d3b0591SJens Wiklander 553d3b0591SJens Wiklander /* constant-time buffer comparison */ 563d3b0591SJens Wiklander static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n ) 573d3b0591SJens Wiklander { 583d3b0591SJens Wiklander size_t i; 593d3b0591SJens Wiklander volatile const unsigned char *A = (volatile const unsigned char *) a; 603d3b0591SJens Wiklander volatile const unsigned char *B = (volatile const unsigned char *) b; 613d3b0591SJens Wiklander volatile unsigned char diff = 0; 623d3b0591SJens Wiklander 633d3b0591SJens Wiklander for( i = 0; i < n; i++ ) 643d3b0591SJens Wiklander { 653d3b0591SJens Wiklander /* Read volatile data in order before computing diff. 663d3b0591SJens Wiklander * This avoids IAR compiler warning: 673d3b0591SJens Wiklander * 'the order of volatile accesses is undefined ..' */ 683d3b0591SJens Wiklander unsigned char x = A[i], y = B[i]; 693d3b0591SJens Wiklander diff |= x ^ y; 703d3b0591SJens Wiklander } 713d3b0591SJens Wiklander 723d3b0591SJens Wiklander return( diff ); 733d3b0591SJens Wiklander } 743d3b0591SJens Wiklander 753d3b0591SJens Wiklander /*! The 64-bit default integrity check value (ICV) for KW mode. */ 763d3b0591SJens Wiklander static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; 773d3b0591SJens Wiklander /*! The 32-bit default integrity check value (ICV) for KWP mode. */ 783d3b0591SJens Wiklander static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; 793d3b0591SJens Wiklander 803d3b0591SJens Wiklander #ifndef GET_UINT32_BE 813d3b0591SJens Wiklander #define GET_UINT32_BE(n,b,i) \ 823d3b0591SJens Wiklander do { \ 833d3b0591SJens Wiklander (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ 843d3b0591SJens Wiklander | ( (uint32_t) (b)[(i) + 1] << 16 ) \ 853d3b0591SJens Wiklander | ( (uint32_t) (b)[(i) + 2] << 8 ) \ 863d3b0591SJens Wiklander | ( (uint32_t) (b)[(i) + 3] ); \ 873d3b0591SJens Wiklander } while( 0 ) 883d3b0591SJens Wiklander #endif 893d3b0591SJens Wiklander 903d3b0591SJens Wiklander #ifndef PUT_UINT32_BE 913d3b0591SJens Wiklander #define PUT_UINT32_BE(n,b,i) \ 923d3b0591SJens Wiklander do { \ 933d3b0591SJens Wiklander (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ 943d3b0591SJens Wiklander (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ 953d3b0591SJens Wiklander (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ 963d3b0591SJens Wiklander (b)[(i) + 3] = (unsigned char) ( (n) ); \ 973d3b0591SJens Wiklander } while( 0 ) 983d3b0591SJens Wiklander #endif 993d3b0591SJens Wiklander 1003d3b0591SJens Wiklander /* 1013d3b0591SJens Wiklander * Initialize context 1023d3b0591SJens Wiklander */ 1033d3b0591SJens Wiklander void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) 1043d3b0591SJens Wiklander { 1053d3b0591SJens Wiklander memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); 1063d3b0591SJens Wiklander } 1073d3b0591SJens Wiklander 1083d3b0591SJens Wiklander int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, 1093d3b0591SJens Wiklander mbedtls_cipher_id_t cipher, 1103d3b0591SJens Wiklander const unsigned char *key, 1113d3b0591SJens Wiklander unsigned int keybits, 1123d3b0591SJens Wiklander const int is_wrap ) 1133d3b0591SJens Wiklander { 11411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 1153d3b0591SJens Wiklander const mbedtls_cipher_info_t *cipher_info; 1163d3b0591SJens Wiklander 1173d3b0591SJens Wiklander cipher_info = mbedtls_cipher_info_from_values( cipher, 1183d3b0591SJens Wiklander keybits, 1193d3b0591SJens Wiklander MBEDTLS_MODE_ECB ); 1203d3b0591SJens Wiklander if( cipher_info == NULL ) 1213d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1223d3b0591SJens Wiklander 1233d3b0591SJens Wiklander if( cipher_info->block_size != 16 ) 1243d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 1253d3b0591SJens Wiklander 1263d3b0591SJens Wiklander /* 1273d3b0591SJens Wiklander * SP 800-38F currently defines AES cipher as the only block cipher allowed: 1283d3b0591SJens Wiklander * "For KW and KWP, the underlying block cipher shall be approved, and the 1293d3b0591SJens Wiklander * block size shall be 128 bits. Currently, the AES block cipher, with key 1303d3b0591SJens Wiklander * lengths of 128, 192, or 256 bits, is the only block cipher that fits 1313d3b0591SJens Wiklander * this profile." 1323d3b0591SJens Wiklander * Currently we don't support other 128 bit block ciphers for key wrapping, 1333d3b0591SJens Wiklander * such as Camellia and Aria. 1343d3b0591SJens Wiklander */ 1353d3b0591SJens Wiklander if( cipher != MBEDTLS_CIPHER_ID_AES ) 1363d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 1373d3b0591SJens Wiklander 1383d3b0591SJens Wiklander mbedtls_cipher_free( &ctx->cipher_ctx ); 1393d3b0591SJens Wiklander 1403d3b0591SJens Wiklander if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) 1413d3b0591SJens Wiklander return( ret ); 1423d3b0591SJens Wiklander 1433d3b0591SJens Wiklander if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, 1443d3b0591SJens Wiklander is_wrap ? MBEDTLS_ENCRYPT : 1453d3b0591SJens Wiklander MBEDTLS_DECRYPT ) 1463d3b0591SJens Wiklander ) != 0 ) 1473d3b0591SJens Wiklander { 1483d3b0591SJens Wiklander return( ret ); 1493d3b0591SJens Wiklander } 1503d3b0591SJens Wiklander 1513d3b0591SJens Wiklander return( 0 ); 1523d3b0591SJens Wiklander } 1533d3b0591SJens Wiklander 1543d3b0591SJens Wiklander /* 1553d3b0591SJens Wiklander * Free context 1563d3b0591SJens Wiklander */ 1573d3b0591SJens Wiklander void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) 1583d3b0591SJens Wiklander { 1593d3b0591SJens Wiklander mbedtls_cipher_free( &ctx->cipher_ctx ); 1603d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); 1613d3b0591SJens Wiklander } 1623d3b0591SJens Wiklander 1633d3b0591SJens Wiklander /* 1643d3b0591SJens Wiklander * Helper function for Xoring the uint64_t "t" with the encrypted A. 1653d3b0591SJens Wiklander * Defined in NIST SP 800-38F section 6.1 1663d3b0591SJens Wiklander */ 1673d3b0591SJens Wiklander static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) 1683d3b0591SJens Wiklander { 1693d3b0591SJens Wiklander size_t i = 0; 1703d3b0591SJens Wiklander for( i = 0; i < sizeof( t ); i++ ) 1713d3b0591SJens Wiklander { 1723d3b0591SJens Wiklander A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; 1733d3b0591SJens Wiklander } 1743d3b0591SJens Wiklander } 1753d3b0591SJens Wiklander 1763d3b0591SJens Wiklander /* 1773d3b0591SJens Wiklander * KW-AE as defined in SP 800-38F section 6.2 1783d3b0591SJens Wiklander * KWP-AE as defined in SP 800-38F section 6.3 1793d3b0591SJens Wiklander */ 1803d3b0591SJens Wiklander int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, 1813d3b0591SJens Wiklander mbedtls_nist_kw_mode_t mode, 1823d3b0591SJens Wiklander const unsigned char *input, size_t in_len, 1833d3b0591SJens Wiklander unsigned char *output, size_t *out_len, size_t out_size ) 1843d3b0591SJens Wiklander { 1853d3b0591SJens Wiklander int ret = 0; 1863d3b0591SJens Wiklander size_t semiblocks = 0; 1873d3b0591SJens Wiklander size_t s; 1883d3b0591SJens Wiklander size_t olen, padlen = 0; 1893d3b0591SJens Wiklander uint64_t t = 0; 1903d3b0591SJens Wiklander unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; 1913d3b0591SJens Wiklander unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; 1923d3b0591SJens Wiklander 1933d3b0591SJens Wiklander *out_len = 0; 1943d3b0591SJens Wiklander /* 1953d3b0591SJens Wiklander * Generate the String to work on 1963d3b0591SJens Wiklander */ 1973d3b0591SJens Wiklander if( mode == MBEDTLS_KW_MODE_KW ) 1983d3b0591SJens Wiklander { 1993d3b0591SJens Wiklander if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) 2003d3b0591SJens Wiklander { 2013d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 2023d3b0591SJens Wiklander } 2033d3b0591SJens Wiklander 2043d3b0591SJens Wiklander /* 2053d3b0591SJens Wiklander * According to SP 800-38F Table 1, the plaintext length for KW 2063d3b0591SJens Wiklander * must be between 2 to 2^54-1 semiblocks inclusive. 2073d3b0591SJens Wiklander */ 2083d3b0591SJens Wiklander if( in_len < 16 || 2093d3b0591SJens Wiklander #if SIZE_MAX > 0x1FFFFFFFFFFFFF8 2103d3b0591SJens Wiklander in_len > 0x1FFFFFFFFFFFFF8 || 2113d3b0591SJens Wiklander #endif 2123d3b0591SJens Wiklander in_len % KW_SEMIBLOCK_LENGTH != 0 ) 2133d3b0591SJens Wiklander { 2143d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 2153d3b0591SJens Wiklander } 2163d3b0591SJens Wiklander 2173d3b0591SJens Wiklander memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); 2183d3b0591SJens Wiklander memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); 2193d3b0591SJens Wiklander } 2203d3b0591SJens Wiklander else 2213d3b0591SJens Wiklander { 2223d3b0591SJens Wiklander if( in_len % 8 != 0 ) 2233d3b0591SJens Wiklander { 2243d3b0591SJens Wiklander padlen = ( 8 - ( in_len % 8 ) ); 2253d3b0591SJens Wiklander } 2263d3b0591SJens Wiklander 2273d3b0591SJens Wiklander if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) 2283d3b0591SJens Wiklander { 2293d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 2303d3b0591SJens Wiklander } 2313d3b0591SJens Wiklander 2323d3b0591SJens Wiklander /* 2333d3b0591SJens Wiklander * According to SP 800-38F Table 1, the plaintext length for KWP 2343d3b0591SJens Wiklander * must be between 1 and 2^32-1 octets inclusive. 2353d3b0591SJens Wiklander */ 2363d3b0591SJens Wiklander if( in_len < 1 2373d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF 2383d3b0591SJens Wiklander || in_len > 0xFFFFFFFF 2393d3b0591SJens Wiklander #endif 2403d3b0591SJens Wiklander ) 2413d3b0591SJens Wiklander { 2423d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 2433d3b0591SJens Wiklander } 2443d3b0591SJens Wiklander 2453d3b0591SJens Wiklander memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); 2463d3b0591SJens Wiklander PUT_UINT32_BE( ( in_len & 0xffffffff ), output, 2473d3b0591SJens Wiklander KW_SEMIBLOCK_LENGTH / 2 ); 2483d3b0591SJens Wiklander 2493d3b0591SJens Wiklander memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); 2503d3b0591SJens Wiklander memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); 2513d3b0591SJens Wiklander } 2523d3b0591SJens Wiklander semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; 2533d3b0591SJens Wiklander 2543d3b0591SJens Wiklander s = 6 * ( semiblocks - 1 ); 2553d3b0591SJens Wiklander 2563d3b0591SJens Wiklander if( mode == MBEDTLS_KW_MODE_KWP 2573d3b0591SJens Wiklander && in_len <= KW_SEMIBLOCK_LENGTH ) 2583d3b0591SJens Wiklander { 2593d3b0591SJens Wiklander memcpy( inbuff, output, 16 ); 2603d3b0591SJens Wiklander ret = mbedtls_cipher_update( &ctx->cipher_ctx, 2613d3b0591SJens Wiklander inbuff, 16, output, &olen ); 2623d3b0591SJens Wiklander if( ret != 0 ) 2633d3b0591SJens Wiklander goto cleanup; 2643d3b0591SJens Wiklander } 2653d3b0591SJens Wiklander else 2663d3b0591SJens Wiklander { 267*7901324dSJerome Forissier unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; 268*7901324dSJerome Forissier unsigned char *A = output; 269*7901324dSJerome Forissier 2703d3b0591SJens Wiklander /* 2713d3b0591SJens Wiklander * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 2723d3b0591SJens Wiklander */ 2733d3b0591SJens Wiklander if( semiblocks < MIN_SEMIBLOCKS_COUNT ) 2743d3b0591SJens Wiklander { 2753d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; 2763d3b0591SJens Wiklander goto cleanup; 2773d3b0591SJens Wiklander } 2783d3b0591SJens Wiklander 2793d3b0591SJens Wiklander /* Calculate intermediate values */ 2803d3b0591SJens Wiklander for( t = 1; t <= s; t++ ) 2813d3b0591SJens Wiklander { 2823d3b0591SJens Wiklander memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); 2833d3b0591SJens Wiklander memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); 2843d3b0591SJens Wiklander 2853d3b0591SJens Wiklander ret = mbedtls_cipher_update( &ctx->cipher_ctx, 2863d3b0591SJens Wiklander inbuff, 16, outbuff, &olen ); 2873d3b0591SJens Wiklander if( ret != 0 ) 2883d3b0591SJens Wiklander goto cleanup; 2893d3b0591SJens Wiklander 2903d3b0591SJens Wiklander memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); 2913d3b0591SJens Wiklander calc_a_xor_t( A, t ); 2923d3b0591SJens Wiklander 2933d3b0591SJens Wiklander memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); 2943d3b0591SJens Wiklander R2 += KW_SEMIBLOCK_LENGTH; 2953d3b0591SJens Wiklander if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) 2963d3b0591SJens Wiklander R2 = output + KW_SEMIBLOCK_LENGTH; 2973d3b0591SJens Wiklander } 2983d3b0591SJens Wiklander } 2993d3b0591SJens Wiklander 3003d3b0591SJens Wiklander *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; 3013d3b0591SJens Wiklander 3023d3b0591SJens Wiklander cleanup: 3033d3b0591SJens Wiklander 3043d3b0591SJens Wiklander if( ret != 0) 3053d3b0591SJens Wiklander { 3063d3b0591SJens Wiklander memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); 3073d3b0591SJens Wiklander } 3083d3b0591SJens Wiklander mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); 3093d3b0591SJens Wiklander mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); 3103d3b0591SJens Wiklander 3113d3b0591SJens Wiklander return( ret ); 3123d3b0591SJens Wiklander } 3133d3b0591SJens Wiklander 3143d3b0591SJens Wiklander /* 3153d3b0591SJens Wiklander * W-1 function as defined in RFC 3394 section 2.2.2 3163d3b0591SJens Wiklander * This function assumes the following: 3173d3b0591SJens Wiklander * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. 3183d3b0591SJens Wiklander * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. 3193d3b0591SJens Wiklander * 3. Minimal number of semiblocks is 3. 3203d3b0591SJens Wiklander * 4. A is a buffer to hold the first semiblock of the input buffer. 3213d3b0591SJens Wiklander */ 3223d3b0591SJens Wiklander static int unwrap( mbedtls_nist_kw_context *ctx, 3233d3b0591SJens Wiklander const unsigned char *input, size_t semiblocks, 3243d3b0591SJens Wiklander unsigned char A[KW_SEMIBLOCK_LENGTH], 3253d3b0591SJens Wiklander unsigned char *output, size_t* out_len ) 3263d3b0591SJens Wiklander { 3273d3b0591SJens Wiklander int ret = 0; 3283d3b0591SJens Wiklander const size_t s = 6 * ( semiblocks - 1 ); 3293d3b0591SJens Wiklander size_t olen; 3303d3b0591SJens Wiklander uint64_t t = 0; 3313d3b0591SJens Wiklander unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; 3323d3b0591SJens Wiklander unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; 333*7901324dSJerome Forissier unsigned char *R = NULL; 3343d3b0591SJens Wiklander *out_len = 0; 3353d3b0591SJens Wiklander 3363d3b0591SJens Wiklander if( semiblocks < MIN_SEMIBLOCKS_COUNT ) 3373d3b0591SJens Wiklander { 3383d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 3393d3b0591SJens Wiklander } 3403d3b0591SJens Wiklander 3413d3b0591SJens Wiklander memcpy( A, input, KW_SEMIBLOCK_LENGTH ); 3423d3b0591SJens Wiklander memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); 343*7901324dSJerome Forissier R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; 3443d3b0591SJens Wiklander 3453d3b0591SJens Wiklander /* Calculate intermediate values */ 3463d3b0591SJens Wiklander for( t = s; t >= 1; t-- ) 3473d3b0591SJens Wiklander { 3483d3b0591SJens Wiklander calc_a_xor_t( A, t ); 3493d3b0591SJens Wiklander 3503d3b0591SJens Wiklander memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); 3513d3b0591SJens Wiklander memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); 3523d3b0591SJens Wiklander 3533d3b0591SJens Wiklander ret = mbedtls_cipher_update( &ctx->cipher_ctx, 3543d3b0591SJens Wiklander inbuff, 16, outbuff, &olen ); 3553d3b0591SJens Wiklander if( ret != 0 ) 3563d3b0591SJens Wiklander goto cleanup; 3573d3b0591SJens Wiklander 3583d3b0591SJens Wiklander memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); 3593d3b0591SJens Wiklander 3603d3b0591SJens Wiklander /* Set R as LSB64 of outbuff */ 3613d3b0591SJens Wiklander memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); 3623d3b0591SJens Wiklander 3633d3b0591SJens Wiklander if( R == output ) 3643d3b0591SJens Wiklander R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; 3653d3b0591SJens Wiklander else 3663d3b0591SJens Wiklander R -= KW_SEMIBLOCK_LENGTH; 3673d3b0591SJens Wiklander } 3683d3b0591SJens Wiklander 3693d3b0591SJens Wiklander *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; 3703d3b0591SJens Wiklander 3713d3b0591SJens Wiklander cleanup: 3723d3b0591SJens Wiklander if( ret != 0) 3733d3b0591SJens Wiklander memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); 3743d3b0591SJens Wiklander mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); 3753d3b0591SJens Wiklander mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); 3763d3b0591SJens Wiklander 3773d3b0591SJens Wiklander return( ret ); 3783d3b0591SJens Wiklander } 3793d3b0591SJens Wiklander 3803d3b0591SJens Wiklander /* 3813d3b0591SJens Wiklander * KW-AD as defined in SP 800-38F section 6.2 3823d3b0591SJens Wiklander * KWP-AD as defined in SP 800-38F section 6.3 3833d3b0591SJens Wiklander */ 3843d3b0591SJens Wiklander int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, 3853d3b0591SJens Wiklander mbedtls_nist_kw_mode_t mode, 3863d3b0591SJens Wiklander const unsigned char *input, size_t in_len, 3873d3b0591SJens Wiklander unsigned char *output, size_t *out_len, size_t out_size ) 3883d3b0591SJens Wiklander { 3893d3b0591SJens Wiklander int ret = 0; 3903d3b0591SJens Wiklander size_t i, olen; 3913d3b0591SJens Wiklander unsigned char A[KW_SEMIBLOCK_LENGTH]; 3923d3b0591SJens Wiklander unsigned char diff, bad_padding = 0; 3933d3b0591SJens Wiklander 3943d3b0591SJens Wiklander *out_len = 0; 3953d3b0591SJens Wiklander if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) 3963d3b0591SJens Wiklander { 3973d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 3983d3b0591SJens Wiklander } 3993d3b0591SJens Wiklander 4003d3b0591SJens Wiklander if( mode == MBEDTLS_KW_MODE_KW ) 4013d3b0591SJens Wiklander { 4023d3b0591SJens Wiklander /* 4033d3b0591SJens Wiklander * According to SP 800-38F Table 1, the ciphertext length for KW 4043d3b0591SJens Wiklander * must be between 3 to 2^54 semiblocks inclusive. 4053d3b0591SJens Wiklander */ 4063d3b0591SJens Wiklander if( in_len < 24 || 4073d3b0591SJens Wiklander #if SIZE_MAX > 0x200000000000000 4083d3b0591SJens Wiklander in_len > 0x200000000000000 || 4093d3b0591SJens Wiklander #endif 4103d3b0591SJens Wiklander in_len % KW_SEMIBLOCK_LENGTH != 0 ) 4113d3b0591SJens Wiklander { 4123d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 4133d3b0591SJens Wiklander } 4143d3b0591SJens Wiklander 4153d3b0591SJens Wiklander ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, 4163d3b0591SJens Wiklander A, output, out_len ); 4173d3b0591SJens Wiklander if( ret != 0 ) 4183d3b0591SJens Wiklander goto cleanup; 4193d3b0591SJens Wiklander 4203d3b0591SJens Wiklander /* Check ICV in "constant-time" */ 4213d3b0591SJens Wiklander diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); 4223d3b0591SJens Wiklander 4233d3b0591SJens Wiklander if( diff != 0 ) 4243d3b0591SJens Wiklander { 4253d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 4263d3b0591SJens Wiklander goto cleanup; 4273d3b0591SJens Wiklander } 4283d3b0591SJens Wiklander 4293d3b0591SJens Wiklander } 4303d3b0591SJens Wiklander else if( mode == MBEDTLS_KW_MODE_KWP ) 4313d3b0591SJens Wiklander { 4323d3b0591SJens Wiklander size_t padlen = 0; 4333d3b0591SJens Wiklander uint32_t Plen; 4343d3b0591SJens Wiklander /* 4353d3b0591SJens Wiklander * According to SP 800-38F Table 1, the ciphertext length for KWP 4363d3b0591SJens Wiklander * must be between 2 to 2^29 semiblocks inclusive. 4373d3b0591SJens Wiklander */ 4383d3b0591SJens Wiklander if( in_len < KW_SEMIBLOCK_LENGTH * 2 || 4393d3b0591SJens Wiklander #if SIZE_MAX > 0x100000000 4403d3b0591SJens Wiklander in_len > 0x100000000 || 4413d3b0591SJens Wiklander #endif 4423d3b0591SJens Wiklander in_len % KW_SEMIBLOCK_LENGTH != 0 ) 4433d3b0591SJens Wiklander { 4443d3b0591SJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 4453d3b0591SJens Wiklander } 4463d3b0591SJens Wiklander 4473d3b0591SJens Wiklander if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) 4483d3b0591SJens Wiklander { 4493d3b0591SJens Wiklander unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; 4503d3b0591SJens Wiklander ret = mbedtls_cipher_update( &ctx->cipher_ctx, 4513d3b0591SJens Wiklander input, 16, outbuff, &olen ); 4523d3b0591SJens Wiklander if( ret != 0 ) 4533d3b0591SJens Wiklander goto cleanup; 4543d3b0591SJens Wiklander 4553d3b0591SJens Wiklander memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); 4563d3b0591SJens Wiklander memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); 4573d3b0591SJens Wiklander mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); 4583d3b0591SJens Wiklander *out_len = KW_SEMIBLOCK_LENGTH; 4593d3b0591SJens Wiklander } 4603d3b0591SJens Wiklander else 4613d3b0591SJens Wiklander { 4623d3b0591SJens Wiklander /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ 4633d3b0591SJens Wiklander ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, 4643d3b0591SJens Wiklander A, output, out_len ); 4653d3b0591SJens Wiklander if( ret != 0 ) 4663d3b0591SJens Wiklander goto cleanup; 4673d3b0591SJens Wiklander } 4683d3b0591SJens Wiklander 4693d3b0591SJens Wiklander /* Check ICV in "constant-time" */ 4703d3b0591SJens Wiklander diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); 4713d3b0591SJens Wiklander 4723d3b0591SJens Wiklander if( diff != 0 ) 4733d3b0591SJens Wiklander { 4743d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 4753d3b0591SJens Wiklander } 4763d3b0591SJens Wiklander 4773d3b0591SJens Wiklander GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 ); 4783d3b0591SJens Wiklander 4793d3b0591SJens Wiklander /* 4803d3b0591SJens Wiklander * Plen is the length of the plaintext, when the input is valid. 4813d3b0591SJens Wiklander * If Plen is larger than the plaintext and padding, padlen will be 4823d3b0591SJens Wiklander * larger than 8, because of the type wrap around. 4833d3b0591SJens Wiklander */ 4843d3b0591SJens Wiklander padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; 4853d3b0591SJens Wiklander if ( padlen > 7 ) 4863d3b0591SJens Wiklander { 4873d3b0591SJens Wiklander padlen &= 7; 4883d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 4893d3b0591SJens Wiklander } 4903d3b0591SJens Wiklander 4913d3b0591SJens Wiklander /* Check padding in "constant-time" */ 4923d3b0591SJens Wiklander for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) 4933d3b0591SJens Wiklander { 4943d3b0591SJens Wiklander if( i >= KW_SEMIBLOCK_LENGTH - padlen ) 4953d3b0591SJens Wiklander diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; 4963d3b0591SJens Wiklander else 4973d3b0591SJens Wiklander bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; 4983d3b0591SJens Wiklander } 4993d3b0591SJens Wiklander 5003d3b0591SJens Wiklander if( diff != 0 ) 5013d3b0591SJens Wiklander { 5023d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; 5033d3b0591SJens Wiklander } 5043d3b0591SJens Wiklander 5053d3b0591SJens Wiklander if( ret != 0 ) 5063d3b0591SJens Wiklander { 5073d3b0591SJens Wiklander goto cleanup; 5083d3b0591SJens Wiklander } 5093d3b0591SJens Wiklander memset( output + Plen, 0, padlen ); 5103d3b0591SJens Wiklander *out_len = Plen; 5113d3b0591SJens Wiklander } 5123d3b0591SJens Wiklander else 5133d3b0591SJens Wiklander { 5143d3b0591SJens Wiklander ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 5153d3b0591SJens Wiklander goto cleanup; 5163d3b0591SJens Wiklander } 5173d3b0591SJens Wiklander 5183d3b0591SJens Wiklander cleanup: 5193d3b0591SJens Wiklander if( ret != 0 ) 5203d3b0591SJens Wiklander { 5213d3b0591SJens Wiklander memset( output, 0, *out_len ); 5223d3b0591SJens Wiklander *out_len = 0; 5233d3b0591SJens Wiklander } 5243d3b0591SJens Wiklander 5253d3b0591SJens Wiklander mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); 5263d3b0591SJens Wiklander mbedtls_platform_zeroize( &diff, sizeof( diff ) ); 5273d3b0591SJens Wiklander mbedtls_platform_zeroize( A, sizeof( A ) ); 5283d3b0591SJens Wiklander 5293d3b0591SJens Wiklander return( ret ); 5303d3b0591SJens Wiklander } 5313d3b0591SJens Wiklander 5323d3b0591SJens Wiklander #endif /* !MBEDTLS_NIST_KW_ALT */ 5333d3b0591SJens Wiklander 5343d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) 5353d3b0591SJens Wiklander 5363d3b0591SJens Wiklander #define KW_TESTS 3 5373d3b0591SJens Wiklander 5383d3b0591SJens Wiklander /* 5393d3b0591SJens Wiklander * Test vectors taken from NIST 5403d3b0591SJens Wiklander * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW 5413d3b0591SJens Wiklander */ 5423d3b0591SJens Wiklander static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; 5433d3b0591SJens Wiklander 5443d3b0591SJens Wiklander static const unsigned char kw_key[KW_TESTS][32] = { 5453d3b0591SJens Wiklander { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, 5463d3b0591SJens Wiklander 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, 5473d3b0591SJens Wiklander { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, 5483d3b0591SJens Wiklander 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, 5493d3b0591SJens Wiklander 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, 5503d3b0591SJens Wiklander { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, 5513d3b0591SJens Wiklander 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, 5523d3b0591SJens Wiklander 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, 5533d3b0591SJens Wiklander 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } 5543d3b0591SJens Wiklander }; 5553d3b0591SJens Wiklander 5563d3b0591SJens Wiklander static const unsigned char kw_msg[KW_TESTS][40] = { 5573d3b0591SJens Wiklander { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, 5583d3b0591SJens Wiklander 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, 5593d3b0591SJens Wiklander { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, 5603d3b0591SJens Wiklander 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, 5613d3b0591SJens Wiklander 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, 5623d3b0591SJens Wiklander 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, 5633d3b0591SJens Wiklander 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, 5643d3b0591SJens Wiklander { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, 5653d3b0591SJens Wiklander 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, 5663d3b0591SJens Wiklander 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } 5673d3b0591SJens Wiklander }; 5683d3b0591SJens Wiklander 5693d3b0591SJens Wiklander static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; 5703d3b0591SJens Wiklander static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; 5713d3b0591SJens Wiklander static const unsigned char kw_res[KW_TESTS][48] = { 5723d3b0591SJens Wiklander { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, 5733d3b0591SJens Wiklander 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, 5743d3b0591SJens Wiklander 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, 5753d3b0591SJens Wiklander { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, 5763d3b0591SJens Wiklander 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, 5773d3b0591SJens Wiklander 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, 5783d3b0591SJens Wiklander 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, 5793d3b0591SJens Wiklander 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, 5803d3b0591SJens Wiklander 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, 5813d3b0591SJens Wiklander { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, 5823d3b0591SJens Wiklander 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, 5833d3b0591SJens Wiklander 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, 5843d3b0591SJens Wiklander 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } 5853d3b0591SJens Wiklander }; 5863d3b0591SJens Wiklander 5873d3b0591SJens Wiklander static const unsigned char kwp_key[KW_TESTS][32] = { 5883d3b0591SJens Wiklander { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, 5893d3b0591SJens Wiklander 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, 5903d3b0591SJens Wiklander { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, 5913d3b0591SJens Wiklander 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, 5923d3b0591SJens Wiklander 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, 5933d3b0591SJens Wiklander { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, 5943d3b0591SJens Wiklander 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, 5953d3b0591SJens Wiklander 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, 5963d3b0591SJens Wiklander 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } 5973d3b0591SJens Wiklander }; 5983d3b0591SJens Wiklander 5993d3b0591SJens Wiklander static const unsigned char kwp_msg[KW_TESTS][31] = { 6003d3b0591SJens Wiklander { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, 6013d3b0591SJens Wiklander 0x96 }, 6023d3b0591SJens Wiklander { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, 6033d3b0591SJens Wiklander 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, 6043d3b0591SJens Wiklander 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, 6053d3b0591SJens Wiklander 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, 6063d3b0591SJens Wiklander { 0xd1 } 6073d3b0591SJens Wiklander }; 6083d3b0591SJens Wiklander static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; 6093d3b0591SJens Wiklander 6103d3b0591SJens Wiklander static const unsigned char kwp_res[KW_TESTS][48] = { 6113d3b0591SJens Wiklander { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, 6123d3b0591SJens Wiklander 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, 6133d3b0591SJens Wiklander 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, 6143d3b0591SJens Wiklander { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, 6153d3b0591SJens Wiklander 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, 6163d3b0591SJens Wiklander 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, 6173d3b0591SJens Wiklander 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, 6183d3b0591SJens Wiklander 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, 6193d3b0591SJens Wiklander { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, 6203d3b0591SJens Wiklander 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } 6213d3b0591SJens Wiklander }; 6223d3b0591SJens Wiklander static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; 6233d3b0591SJens Wiklander 6243d3b0591SJens Wiklander int mbedtls_nist_kw_self_test( int verbose ) 6253d3b0591SJens Wiklander { 6263d3b0591SJens Wiklander mbedtls_nist_kw_context ctx; 6273d3b0591SJens Wiklander unsigned char out[48]; 6283d3b0591SJens Wiklander size_t olen; 6293d3b0591SJens Wiklander int i; 6303d3b0591SJens Wiklander int ret = 0; 6313d3b0591SJens Wiklander mbedtls_nist_kw_init( &ctx ); 6323d3b0591SJens Wiklander 6333d3b0591SJens Wiklander for( i = 0; i < KW_TESTS; i++ ) 6343d3b0591SJens Wiklander { 6353d3b0591SJens Wiklander if( verbose != 0 ) 6363d3b0591SJens Wiklander mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); 6373d3b0591SJens Wiklander 6383d3b0591SJens Wiklander ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, 6393d3b0591SJens Wiklander kw_key[i], key_len[i] * 8, 1 ); 6403d3b0591SJens Wiklander if( ret != 0 ) 6413d3b0591SJens Wiklander { 6423d3b0591SJens Wiklander if( verbose != 0 ) 6433d3b0591SJens Wiklander mbedtls_printf( " KW: setup failed " ); 6443d3b0591SJens Wiklander 6453d3b0591SJens Wiklander goto end; 6463d3b0591SJens Wiklander } 6473d3b0591SJens Wiklander 6483d3b0591SJens Wiklander ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], 6493d3b0591SJens Wiklander kw_msg_len[i], out, &olen, sizeof( out ) ); 6503d3b0591SJens Wiklander if( ret != 0 || kw_out_len[i] != olen || 6513d3b0591SJens Wiklander memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) 6523d3b0591SJens Wiklander { 6533d3b0591SJens Wiklander if( verbose != 0 ) 6543d3b0591SJens Wiklander mbedtls_printf( "failed. "); 6553d3b0591SJens Wiklander 6563d3b0591SJens Wiklander ret = 1; 6573d3b0591SJens Wiklander goto end; 6583d3b0591SJens Wiklander } 6593d3b0591SJens Wiklander 6603d3b0591SJens Wiklander if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, 6613d3b0591SJens Wiklander kw_key[i], key_len[i] * 8, 0 ) ) 6623d3b0591SJens Wiklander != 0 ) 6633d3b0591SJens Wiklander { 6643d3b0591SJens Wiklander if( verbose != 0 ) 6653d3b0591SJens Wiklander mbedtls_printf( " KW: setup failed "); 6663d3b0591SJens Wiklander 6673d3b0591SJens Wiklander goto end; 6683d3b0591SJens Wiklander } 6693d3b0591SJens Wiklander 6703d3b0591SJens Wiklander ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, 6713d3b0591SJens Wiklander out, olen, out, &olen, sizeof( out ) ); 6723d3b0591SJens Wiklander 6733d3b0591SJens Wiklander if( ret != 0 || olen != kw_msg_len[i] || 6743d3b0591SJens Wiklander memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) 6753d3b0591SJens Wiklander { 6763d3b0591SJens Wiklander if( verbose != 0 ) 6773d3b0591SJens Wiklander mbedtls_printf( "failed\n" ); 6783d3b0591SJens Wiklander 6793d3b0591SJens Wiklander ret = 1; 6803d3b0591SJens Wiklander goto end; 6813d3b0591SJens Wiklander } 6823d3b0591SJens Wiklander 6833d3b0591SJens Wiklander if( verbose != 0 ) 6843d3b0591SJens Wiklander mbedtls_printf( " passed\n" ); 6853d3b0591SJens Wiklander } 6863d3b0591SJens Wiklander 6873d3b0591SJens Wiklander for( i = 0; i < KW_TESTS; i++ ) 6883d3b0591SJens Wiklander { 6893d3b0591SJens Wiklander olen = sizeof( out ); 6903d3b0591SJens Wiklander if( verbose != 0 ) 6913d3b0591SJens Wiklander mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); 6923d3b0591SJens Wiklander 6933d3b0591SJens Wiklander ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], 6943d3b0591SJens Wiklander key_len[i] * 8, 1 ); 6953d3b0591SJens Wiklander if( ret != 0 ) 6963d3b0591SJens Wiklander { 6973d3b0591SJens Wiklander if( verbose != 0 ) 6983d3b0591SJens Wiklander mbedtls_printf( " KWP: setup failed " ); 6993d3b0591SJens Wiklander 7003d3b0591SJens Wiklander goto end; 7013d3b0591SJens Wiklander } 7023d3b0591SJens Wiklander ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], 7033d3b0591SJens Wiklander kwp_msg_len[i], out, &olen, sizeof( out ) ); 7043d3b0591SJens Wiklander 7053d3b0591SJens Wiklander if( ret != 0 || kwp_out_len[i] != olen || 7063d3b0591SJens Wiklander memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) 7073d3b0591SJens Wiklander { 7083d3b0591SJens Wiklander if( verbose != 0 ) 7093d3b0591SJens Wiklander mbedtls_printf( "failed. "); 7103d3b0591SJens Wiklander 7113d3b0591SJens Wiklander ret = 1; 7123d3b0591SJens Wiklander goto end; 7133d3b0591SJens Wiklander } 7143d3b0591SJens Wiklander 7153d3b0591SJens Wiklander if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, 7163d3b0591SJens Wiklander kwp_key[i], key_len[i] * 8, 0 ) ) 7173d3b0591SJens Wiklander != 0 ) 7183d3b0591SJens Wiklander { 7193d3b0591SJens Wiklander if( verbose != 0 ) 7203d3b0591SJens Wiklander mbedtls_printf( " KWP: setup failed "); 7213d3b0591SJens Wiklander 7223d3b0591SJens Wiklander goto end; 7233d3b0591SJens Wiklander } 7243d3b0591SJens Wiklander 7253d3b0591SJens Wiklander ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, 7263d3b0591SJens Wiklander olen, out, &olen, sizeof( out ) ); 7273d3b0591SJens Wiklander 7283d3b0591SJens Wiklander if( ret != 0 || olen != kwp_msg_len[i] || 7293d3b0591SJens Wiklander memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) 7303d3b0591SJens Wiklander { 7313d3b0591SJens Wiklander if( verbose != 0 ) 7323d3b0591SJens Wiklander mbedtls_printf( "failed. "); 7333d3b0591SJens Wiklander 7343d3b0591SJens Wiklander ret = 1; 7353d3b0591SJens Wiklander goto end; 7363d3b0591SJens Wiklander } 7373d3b0591SJens Wiklander 7383d3b0591SJens Wiklander if( verbose != 0 ) 7393d3b0591SJens Wiklander mbedtls_printf( " passed\n" ); 7403d3b0591SJens Wiklander } 7413d3b0591SJens Wiklander end: 7423d3b0591SJens Wiklander mbedtls_nist_kw_free( &ctx ); 7433d3b0591SJens Wiklander 7443d3b0591SJens Wiklander if( verbose != 0 ) 7453d3b0591SJens Wiklander mbedtls_printf( "\n" ); 7463d3b0591SJens Wiklander 7473d3b0591SJens Wiklander return( ret ); 7483d3b0591SJens Wiklander } 7493d3b0591SJens Wiklander 7503d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ 7513d3b0591SJens Wiklander 7523d3b0591SJens Wiklander #endif /* MBEDTLS_NIST_KW_C */ 753