quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

nist_kw.c (22862B)


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