takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers nist_kw.c Source File

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 */