Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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