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