xref: /optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c (revision cb03400251f98aed22a2664509e3ed9e183800b0)
13d3b0591SJens Wiklander /*
23d3b0591SJens Wiklander  *  Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes
33d3b0591SJens Wiklander  *  only
43d3b0591SJens Wiklander  *
57901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
6b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
73d3b0591SJens Wiklander  */
83d3b0591SJens Wiklander /*
93d3b0591SJens Wiklander  * Definition of Key Wrapping:
103d3b0591SJens Wiklander  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
113d3b0591SJens Wiklander  * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
123d3b0591SJens Wiklander  * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
133d3b0591SJens Wiklander  *
143d3b0591SJens Wiklander  * Note: RFC 3394 defines different methodology for intermediate operations for
153d3b0591SJens Wiklander  * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
163d3b0591SJens Wiklander  */
173d3b0591SJens Wiklander 
187901324dSJerome Forissier #include "common.h"
193d3b0591SJens Wiklander 
203d3b0591SJens Wiklander #if defined(MBEDTLS_NIST_KW_C)
213d3b0591SJens Wiklander 
223d3b0591SJens Wiklander #include "mbedtls/nist_kw.h"
233d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
2411fa71b9SJerome Forissier #include "mbedtls/error.h"
25039e02dfSJerome Forissier #include "mbedtls/constant_time.h"
26b0563631STom Van Eyck #include "constant_time_internal.h"
273d3b0591SJens Wiklander 
283d3b0591SJens Wiklander #include <stdint.h>
293d3b0591SJens Wiklander #include <string.h>
303d3b0591SJens Wiklander 
313d3b0591SJens Wiklander #include "mbedtls/platform.h"
323d3b0591SJens Wiklander 
333d3b0591SJens Wiklander #if !defined(MBEDTLS_NIST_KW_ALT)
343d3b0591SJens Wiklander 
353d3b0591SJens Wiklander #define KW_SEMIBLOCK_LENGTH    8
363d3b0591SJens Wiklander #define MIN_SEMIBLOCKS_COUNT   3
373d3b0591SJens Wiklander 
383d3b0591SJens Wiklander /*! The 64-bit default integrity check value (ICV) for KW mode. */
393d3b0591SJens Wiklander static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
403d3b0591SJens Wiklander /*! The 32-bit default integrity check value (ICV) for KWP mode. */
413d3b0591SJens Wiklander static const  unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
423d3b0591SJens Wiklander 
433d3b0591SJens Wiklander /*
443d3b0591SJens Wiklander  * Initialize context
453d3b0591SJens Wiklander  */
mbedtls_nist_kw_init(mbedtls_nist_kw_context * ctx)463d3b0591SJens Wiklander void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
473d3b0591SJens Wiklander {
483d3b0591SJens Wiklander     memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
493d3b0591SJens Wiklander }
503d3b0591SJens Wiklander 
mbedtls_nist_kw_setkey(mbedtls_nist_kw_context * ctx,mbedtls_cipher_id_t cipher,const unsigned char * key,unsigned int keybits,const int is_wrap)513d3b0591SJens Wiklander int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
523d3b0591SJens Wiklander                            mbedtls_cipher_id_t cipher,
533d3b0591SJens Wiklander                            const unsigned char *key,
543d3b0591SJens Wiklander                            unsigned int keybits,
553d3b0591SJens Wiklander                            const int is_wrap)
563d3b0591SJens Wiklander {
5711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
583d3b0591SJens Wiklander     const mbedtls_cipher_info_t *cipher_info;
593d3b0591SJens Wiklander 
603d3b0591SJens Wiklander     cipher_info = mbedtls_cipher_info_from_values(cipher,
613d3b0591SJens Wiklander                                                   keybits,
623d3b0591SJens Wiklander                                                   MBEDTLS_MODE_ECB);
6332b31808SJens Wiklander     if (cipher_info == NULL) {
6432b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
6532b31808SJens Wiklander     }
663d3b0591SJens Wiklander 
67b0563631STom Van Eyck     if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
6832b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
6932b31808SJens Wiklander     }
703d3b0591SJens Wiklander 
713d3b0591SJens Wiklander     /*
723d3b0591SJens Wiklander      * SP 800-38F currently defines AES cipher as the only block cipher allowed:
733d3b0591SJens Wiklander      * "For KW and KWP, the underlying block cipher shall be approved, and the
743d3b0591SJens Wiklander      *  block size shall be 128 bits. Currently, the AES block cipher, with key
753d3b0591SJens Wiklander      *  lengths of 128, 192, or 256 bits, is the only block cipher that fits
763d3b0591SJens Wiklander      *  this profile."
773d3b0591SJens Wiklander      *  Currently we don't support other 128 bit block ciphers for key wrapping,
783d3b0591SJens Wiklander      *  such as Camellia and Aria.
793d3b0591SJens Wiklander      */
8032b31808SJens Wiklander     if (cipher != MBEDTLS_CIPHER_ID_AES) {
8132b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
8232b31808SJens Wiklander     }
833d3b0591SJens Wiklander 
843d3b0591SJens Wiklander     mbedtls_cipher_free(&ctx->cipher_ctx);
853d3b0591SJens Wiklander 
8632b31808SJens Wiklander     if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
8732b31808SJens Wiklander         return ret;
8832b31808SJens Wiklander     }
893d3b0591SJens Wiklander 
903d3b0591SJens Wiklander     if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
913d3b0591SJens Wiklander                                      is_wrap ? MBEDTLS_ENCRYPT :
923d3b0591SJens Wiklander                                      MBEDTLS_DECRYPT)
9332b31808SJens Wiklander          ) != 0) {
9432b31808SJens Wiklander         return ret;
953d3b0591SJens Wiklander     }
963d3b0591SJens Wiklander 
9732b31808SJens Wiklander     return 0;
983d3b0591SJens Wiklander }
993d3b0591SJens Wiklander 
1003d3b0591SJens Wiklander /*
1013d3b0591SJens Wiklander  * Free context
1023d3b0591SJens Wiklander  */
mbedtls_nist_kw_free(mbedtls_nist_kw_context * ctx)1033d3b0591SJens Wiklander void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
1043d3b0591SJens Wiklander {
105*cb034002SJerome Forissier     if (ctx == NULL) {
106*cb034002SJerome Forissier         return;
107*cb034002SJerome Forissier     }
108*cb034002SJerome Forissier 
1093d3b0591SJens Wiklander     mbedtls_cipher_free(&ctx->cipher_ctx);
1103d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
1113d3b0591SJens Wiklander }
1123d3b0591SJens Wiklander 
1133d3b0591SJens Wiklander /*
1143d3b0591SJens Wiklander  * Helper function for Xoring the uint64_t "t" with the encrypted A.
1153d3b0591SJens Wiklander  * Defined in NIST SP 800-38F section 6.1
1163d3b0591SJens Wiklander  */
calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH],uint64_t t)1173d3b0591SJens Wiklander static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
1183d3b0591SJens Wiklander {
1193d3b0591SJens Wiklander     size_t i = 0;
12032b31808SJens Wiklander     for (i = 0; i < sizeof(t); i++) {
1213d3b0591SJens Wiklander         A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
1223d3b0591SJens Wiklander     }
1233d3b0591SJens Wiklander }
1243d3b0591SJens Wiklander 
1253d3b0591SJens Wiklander /*
1263d3b0591SJens Wiklander  * KW-AE as defined in SP 800-38F section 6.2
1273d3b0591SJens Wiklander  * KWP-AE as defined in SP 800-38F section 6.3
1283d3b0591SJens Wiklander  */
mbedtls_nist_kw_wrap(mbedtls_nist_kw_context * ctx,mbedtls_nist_kw_mode_t mode,const unsigned char * input,size_t in_len,unsigned char * output,size_t * out_len,size_t out_size)1293d3b0591SJens Wiklander int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
1303d3b0591SJens Wiklander                          mbedtls_nist_kw_mode_t mode,
1313d3b0591SJens Wiklander                          const unsigned char *input, size_t in_len,
1323d3b0591SJens Wiklander                          unsigned char *output, size_t *out_len, size_t out_size)
1333d3b0591SJens Wiklander {
1343d3b0591SJens Wiklander     int ret = 0;
1353d3b0591SJens Wiklander     size_t semiblocks = 0;
1363d3b0591SJens Wiklander     size_t s;
1373d3b0591SJens Wiklander     size_t olen, padlen = 0;
1383d3b0591SJens Wiklander     uint64_t t = 0;
1393d3b0591SJens Wiklander     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
1403d3b0591SJens Wiklander     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
1413d3b0591SJens Wiklander 
1423d3b0591SJens Wiklander     *out_len = 0;
1433d3b0591SJens Wiklander     /*
1443d3b0591SJens Wiklander      * Generate the String to work on
1453d3b0591SJens Wiklander      */
14632b31808SJens Wiklander     if (mode == MBEDTLS_KW_MODE_KW) {
14732b31808SJens Wiklander         if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
14832b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1493d3b0591SJens Wiklander         }
1503d3b0591SJens Wiklander 
1513d3b0591SJens Wiklander         /*
1523d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the plaintext length for KW
1533d3b0591SJens Wiklander          * must be between 2 to 2^54-1 semiblocks inclusive.
1543d3b0591SJens Wiklander          */
1553d3b0591SJens Wiklander         if (in_len < 16 ||
1563d3b0591SJens Wiklander #if SIZE_MAX > 0x1FFFFFFFFFFFFF8
1573d3b0591SJens Wiklander             in_len > 0x1FFFFFFFFFFFFF8 ||
1583d3b0591SJens Wiklander #endif
15932b31808SJens Wiklander             in_len % KW_SEMIBLOCK_LENGTH != 0) {
16032b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1613d3b0591SJens Wiklander         }
1623d3b0591SJens Wiklander 
1633d3b0591SJens Wiklander         memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
1643d3b0591SJens Wiklander         memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
16532b31808SJens Wiklander     } else {
16632b31808SJens Wiklander         if (in_len % 8 != 0) {
1673d3b0591SJens Wiklander             padlen = (8 - (in_len % 8));
1683d3b0591SJens Wiklander         }
1693d3b0591SJens Wiklander 
17032b31808SJens Wiklander         if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
17132b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1723d3b0591SJens Wiklander         }
1733d3b0591SJens Wiklander 
1743d3b0591SJens Wiklander         /*
1753d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the plaintext length for KWP
1763d3b0591SJens Wiklander          * must be between 1 and 2^32-1 octets inclusive.
1773d3b0591SJens Wiklander          */
1783d3b0591SJens Wiklander         if (in_len < 1
1793d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF
1803d3b0591SJens Wiklander             || in_len > 0xFFFFFFFF
1813d3b0591SJens Wiklander #endif
18232b31808SJens Wiklander             ) {
18332b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1843d3b0591SJens Wiklander         }
1853d3b0591SJens Wiklander 
1863d3b0591SJens Wiklander         memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
187039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
1883d3b0591SJens Wiklander                               KW_SEMIBLOCK_LENGTH / 2);
1893d3b0591SJens Wiklander 
1903d3b0591SJens Wiklander         memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
1913d3b0591SJens Wiklander         memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
1923d3b0591SJens Wiklander     }
1933d3b0591SJens Wiklander     semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
1943d3b0591SJens Wiklander 
1953d3b0591SJens Wiklander     s = 6 * (semiblocks - 1);
1963d3b0591SJens Wiklander 
1973d3b0591SJens Wiklander     if (mode == MBEDTLS_KW_MODE_KWP
19832b31808SJens Wiklander         && in_len <= KW_SEMIBLOCK_LENGTH) {
1993d3b0591SJens Wiklander         memcpy(inbuff, output, 16);
2003d3b0591SJens Wiklander         ret = mbedtls_cipher_update(&ctx->cipher_ctx,
2013d3b0591SJens Wiklander                                     inbuff, 16, output, &olen);
20232b31808SJens Wiklander         if (ret != 0) {
2033d3b0591SJens Wiklander             goto cleanup;
2043d3b0591SJens Wiklander         }
20532b31808SJens Wiklander     } else {
2067901324dSJerome Forissier         unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
2077901324dSJerome Forissier         unsigned char *A = output;
2087901324dSJerome Forissier 
2093d3b0591SJens Wiklander         /*
2103d3b0591SJens Wiklander          * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
2113d3b0591SJens Wiklander          */
21232b31808SJens Wiklander         if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
2133d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
2143d3b0591SJens Wiklander             goto cleanup;
2153d3b0591SJens Wiklander         }
2163d3b0591SJens Wiklander 
2173d3b0591SJens Wiklander         /* Calculate intermediate values */
21832b31808SJens Wiklander         for (t = 1; t <= s; t++) {
2193d3b0591SJens Wiklander             memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
2203d3b0591SJens Wiklander             memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
2213d3b0591SJens Wiklander 
2223d3b0591SJens Wiklander             ret = mbedtls_cipher_update(&ctx->cipher_ctx,
2233d3b0591SJens Wiklander                                         inbuff, 16, outbuff, &olen);
22432b31808SJens Wiklander             if (ret != 0) {
2253d3b0591SJens Wiklander                 goto cleanup;
22632b31808SJens Wiklander             }
2273d3b0591SJens Wiklander 
2283d3b0591SJens Wiklander             memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
2293d3b0591SJens Wiklander             calc_a_xor_t(A, t);
2303d3b0591SJens Wiklander 
2313d3b0591SJens Wiklander             memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
2323d3b0591SJens Wiklander             R2 += KW_SEMIBLOCK_LENGTH;
23332b31808SJens Wiklander             if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
2343d3b0591SJens Wiklander                 R2 = output + KW_SEMIBLOCK_LENGTH;
2353d3b0591SJens Wiklander             }
2363d3b0591SJens Wiklander         }
23732b31808SJens Wiklander     }
2383d3b0591SJens Wiklander 
2393d3b0591SJens Wiklander     *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
2403d3b0591SJens Wiklander 
2413d3b0591SJens Wiklander cleanup:
2423d3b0591SJens Wiklander 
24332b31808SJens Wiklander     if (ret != 0) {
2443d3b0591SJens Wiklander         memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
2453d3b0591SJens Wiklander     }
2463d3b0591SJens Wiklander     mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
2473d3b0591SJens Wiklander     mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
2483d3b0591SJens Wiklander 
24932b31808SJens Wiklander     return ret;
2503d3b0591SJens Wiklander }
2513d3b0591SJens Wiklander 
2523d3b0591SJens Wiklander /*
2533d3b0591SJens Wiklander  * W-1 function as defined in RFC 3394 section 2.2.2
2543d3b0591SJens Wiklander  * This function assumes the following:
2553d3b0591SJens Wiklander  * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
2563d3b0591SJens Wiklander  * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
2573d3b0591SJens Wiklander  * 3. Minimal number of semiblocks is 3.
2583d3b0591SJens Wiklander  * 4. A is a buffer to hold the first semiblock of the input buffer.
2593d3b0591SJens Wiklander  */
unwrap(mbedtls_nist_kw_context * ctx,const unsigned char * input,size_t semiblocks,unsigned char A[KW_SEMIBLOCK_LENGTH],unsigned char * output,size_t * out_len)2603d3b0591SJens Wiklander static int unwrap(mbedtls_nist_kw_context *ctx,
2613d3b0591SJens Wiklander                   const unsigned char *input, size_t semiblocks,
2623d3b0591SJens Wiklander                   unsigned char A[KW_SEMIBLOCK_LENGTH],
2633d3b0591SJens Wiklander                   unsigned char *output, size_t *out_len)
2643d3b0591SJens Wiklander {
2653d3b0591SJens Wiklander     int ret = 0;
2663d3b0591SJens Wiklander     const size_t s = 6 * (semiblocks - 1);
2673d3b0591SJens Wiklander     size_t olen;
2683d3b0591SJens Wiklander     uint64_t t = 0;
2693d3b0591SJens Wiklander     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
2703d3b0591SJens Wiklander     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
2717901324dSJerome Forissier     unsigned char *R = NULL;
2723d3b0591SJens Wiklander     *out_len = 0;
2733d3b0591SJens Wiklander 
27432b31808SJens Wiklander     if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
27532b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
2763d3b0591SJens Wiklander     }
2773d3b0591SJens Wiklander 
2783d3b0591SJens Wiklander     memcpy(A, input, KW_SEMIBLOCK_LENGTH);
2793d3b0591SJens Wiklander     memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
2807901324dSJerome Forissier     R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
2813d3b0591SJens Wiklander 
2823d3b0591SJens Wiklander     /* Calculate intermediate values */
28332b31808SJens Wiklander     for (t = s; t >= 1; t--) {
2843d3b0591SJens Wiklander         calc_a_xor_t(A, t);
2853d3b0591SJens Wiklander 
2863d3b0591SJens Wiklander         memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
2873d3b0591SJens Wiklander         memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
2883d3b0591SJens Wiklander 
2893d3b0591SJens Wiklander         ret = mbedtls_cipher_update(&ctx->cipher_ctx,
2903d3b0591SJens Wiklander                                     inbuff, 16, outbuff, &olen);
29132b31808SJens Wiklander         if (ret != 0) {
2923d3b0591SJens Wiklander             goto cleanup;
29332b31808SJens Wiklander         }
2943d3b0591SJens Wiklander 
2953d3b0591SJens Wiklander         memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
2963d3b0591SJens Wiklander 
2973d3b0591SJens Wiklander         /* Set R as LSB64 of outbuff */
2983d3b0591SJens Wiklander         memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
2993d3b0591SJens Wiklander 
30032b31808SJens Wiklander         if (R == output) {
3013d3b0591SJens Wiklander             R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
30232b31808SJens Wiklander         } else {
3033d3b0591SJens Wiklander             R -= KW_SEMIBLOCK_LENGTH;
3043d3b0591SJens Wiklander         }
30532b31808SJens Wiklander     }
3063d3b0591SJens Wiklander 
3073d3b0591SJens Wiklander     *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
3083d3b0591SJens Wiklander 
3093d3b0591SJens Wiklander cleanup:
31032b31808SJens Wiklander     if (ret != 0) {
3113d3b0591SJens Wiklander         memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
31232b31808SJens Wiklander     }
3133d3b0591SJens Wiklander     mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
3143d3b0591SJens Wiklander     mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
3153d3b0591SJens Wiklander 
31632b31808SJens Wiklander     return ret;
3173d3b0591SJens Wiklander }
3183d3b0591SJens Wiklander 
3193d3b0591SJens Wiklander /*
3203d3b0591SJens Wiklander  * KW-AD as defined in SP 800-38F section 6.2
3213d3b0591SJens Wiklander  * KWP-AD as defined in SP 800-38F section 6.3
3223d3b0591SJens Wiklander  */
mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context * ctx,mbedtls_nist_kw_mode_t mode,const unsigned char * input,size_t in_len,unsigned char * output,size_t * out_len,size_t out_size)3233d3b0591SJens Wiklander int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
3243d3b0591SJens Wiklander                            mbedtls_nist_kw_mode_t mode,
3253d3b0591SJens Wiklander                            const unsigned char *input, size_t in_len,
3263d3b0591SJens Wiklander                            unsigned char *output, size_t *out_len, size_t out_size)
3273d3b0591SJens Wiklander {
3283d3b0591SJens Wiklander     int ret = 0;
329b0563631STom Van Eyck     size_t olen;
3303d3b0591SJens Wiklander     unsigned char A[KW_SEMIBLOCK_LENGTH];
331b0563631STom Van Eyck     int diff;
3323d3b0591SJens Wiklander 
3333d3b0591SJens Wiklander     *out_len = 0;
33432b31808SJens Wiklander     if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
33532b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
3363d3b0591SJens Wiklander     }
3373d3b0591SJens Wiklander 
33832b31808SJens Wiklander     if (mode == MBEDTLS_KW_MODE_KW) {
3393d3b0591SJens Wiklander         /*
3403d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the ciphertext length for KW
3413d3b0591SJens Wiklander          * must be between 3 to 2^54 semiblocks inclusive.
3423d3b0591SJens Wiklander          */
3433d3b0591SJens Wiklander         if (in_len < 24 ||
3443d3b0591SJens Wiklander #if SIZE_MAX > 0x200000000000000
3453d3b0591SJens Wiklander             in_len > 0x200000000000000 ||
3463d3b0591SJens Wiklander #endif
34732b31808SJens Wiklander             in_len % KW_SEMIBLOCK_LENGTH != 0) {
34832b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
3493d3b0591SJens Wiklander         }
3503d3b0591SJens Wiklander 
3513d3b0591SJens Wiklander         ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
3523d3b0591SJens Wiklander                      A, output, out_len);
35332b31808SJens Wiklander         if (ret != 0) {
3543d3b0591SJens Wiklander             goto cleanup;
35532b31808SJens Wiklander         }
3563d3b0591SJens Wiklander 
3573d3b0591SJens Wiklander         /* Check ICV in "constant-time" */
358039e02dfSJerome Forissier         diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
3593d3b0591SJens Wiklander 
36032b31808SJens Wiklander         if (diff != 0) {
3613d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
3623d3b0591SJens Wiklander             goto cleanup;
3633d3b0591SJens Wiklander         }
3643d3b0591SJens Wiklander 
36532b31808SJens Wiklander     } else if (mode == MBEDTLS_KW_MODE_KWP) {
3663d3b0591SJens Wiklander         size_t padlen = 0;
3673d3b0591SJens Wiklander         uint32_t Plen;
3683d3b0591SJens Wiklander         /*
3693d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the ciphertext length for KWP
3703d3b0591SJens Wiklander          * must be between 2 to 2^29 semiblocks inclusive.
3713d3b0591SJens Wiklander          */
3723d3b0591SJens Wiklander         if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
3733d3b0591SJens Wiklander #if SIZE_MAX > 0x100000000
3743d3b0591SJens Wiklander             in_len > 0x100000000 ||
3753d3b0591SJens Wiklander #endif
37632b31808SJens Wiklander             in_len % KW_SEMIBLOCK_LENGTH != 0) {
37732b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
3783d3b0591SJens Wiklander         }
3793d3b0591SJens Wiklander 
38032b31808SJens Wiklander         if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
3813d3b0591SJens Wiklander             unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
3823d3b0591SJens Wiklander             ret = mbedtls_cipher_update(&ctx->cipher_ctx,
3833d3b0591SJens Wiklander                                         input, 16, outbuff, &olen);
38432b31808SJens Wiklander             if (ret != 0) {
3853d3b0591SJens Wiklander                 goto cleanup;
38632b31808SJens Wiklander             }
3873d3b0591SJens Wiklander 
3883d3b0591SJens Wiklander             memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
3893d3b0591SJens Wiklander             memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
3903d3b0591SJens Wiklander             mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
3913d3b0591SJens Wiklander             *out_len = KW_SEMIBLOCK_LENGTH;
39232b31808SJens Wiklander         } else {
3933d3b0591SJens Wiklander             /* in_len >=  KW_SEMIBLOCK_LENGTH * 3 */
3943d3b0591SJens Wiklander             ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
3953d3b0591SJens Wiklander                          A, output, out_len);
39632b31808SJens Wiklander             if (ret != 0) {
3973d3b0591SJens Wiklander                 goto cleanup;
3983d3b0591SJens Wiklander             }
39932b31808SJens Wiklander         }
4003d3b0591SJens Wiklander 
4013d3b0591SJens Wiklander         /* Check ICV in "constant-time" */
402039e02dfSJerome Forissier         diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
4033d3b0591SJens Wiklander 
40432b31808SJens Wiklander         if (diff != 0) {
4053d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
4063d3b0591SJens Wiklander         }
4073d3b0591SJens Wiklander 
408039e02dfSJerome Forissier         Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
4093d3b0591SJens Wiklander 
4103d3b0591SJens Wiklander         /*
4113d3b0591SJens Wiklander          * Plen is the length of the plaintext, when the input is valid.
4123d3b0591SJens Wiklander          * If Plen is larger than the plaintext and padding, padlen will be
4133d3b0591SJens Wiklander          * larger than 8, because of the type wrap around.
4143d3b0591SJens Wiklander          */
4153d3b0591SJens Wiklander         padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
416b0563631STom Van Eyck         ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
417b0563631STom Van Eyck                                   MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
4183d3b0591SJens Wiklander         padlen &= 7;
4193d3b0591SJens Wiklander 
4203d3b0591SJens Wiklander         /* Check padding in "constant-time" */
421b0563631STom Van Eyck         const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
422b0563631STom Van Eyck         diff = mbedtls_ct_memcmp_partial(
423b0563631STom Van Eyck             &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
424b0563631STom Van Eyck             KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
4253d3b0591SJens Wiklander 
42632b31808SJens Wiklander         if (diff != 0) {
4273d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
4283d3b0591SJens Wiklander         }
4293d3b0591SJens Wiklander 
43032b31808SJens Wiklander         if (ret != 0) {
4313d3b0591SJens Wiklander             goto cleanup;
4323d3b0591SJens Wiklander         }
4333d3b0591SJens Wiklander         memset(output + Plen, 0, padlen);
4343d3b0591SJens Wiklander         *out_len = Plen;
43532b31808SJens Wiklander     } else {
4363d3b0591SJens Wiklander         ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
4373d3b0591SJens Wiklander         goto cleanup;
4383d3b0591SJens Wiklander     }
4393d3b0591SJens Wiklander 
4403d3b0591SJens Wiklander cleanup:
44132b31808SJens Wiklander     if (ret != 0) {
4423d3b0591SJens Wiklander         memset(output, 0, *out_len);
4433d3b0591SJens Wiklander         *out_len = 0;
4443d3b0591SJens Wiklander     }
4453d3b0591SJens Wiklander 
4463d3b0591SJens Wiklander     mbedtls_platform_zeroize(&diff, sizeof(diff));
4473d3b0591SJens Wiklander     mbedtls_platform_zeroize(A, sizeof(A));
4483d3b0591SJens Wiklander 
44932b31808SJens Wiklander     return ret;
4503d3b0591SJens Wiklander }
4513d3b0591SJens Wiklander 
4523d3b0591SJens Wiklander #endif /* !MBEDTLS_NIST_KW_ALT */
4533d3b0591SJens Wiklander 
4543d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
4553d3b0591SJens Wiklander 
4563d3b0591SJens Wiklander /*
4573d3b0591SJens Wiklander  * Test vectors taken from NIST
4583d3b0591SJens Wiklander  * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
4593d3b0591SJens Wiklander  */
460b0563631STom Van Eyck static const unsigned int key_len[] = {
461b0563631STom Van Eyck     16,
462b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
463b0563631STom Van Eyck     24,
464b0563631STom Van Eyck     32
465b0563631STom Van Eyck #endif
466b0563631STom Van Eyck };
4673d3b0591SJens Wiklander 
468b0563631STom Van Eyck static const unsigned char kw_key[][32] = {
4693d3b0591SJens Wiklander     { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
4703d3b0591SJens Wiklander       0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
471b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
4723d3b0591SJens Wiklander     { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
4733d3b0591SJens Wiklander       0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
4743d3b0591SJens Wiklander       0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
4753d3b0591SJens Wiklander     { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
4763d3b0591SJens Wiklander       0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
4773d3b0591SJens Wiklander       0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
4783d3b0591SJens Wiklander       0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
479b0563631STom Van Eyck #endif
4803d3b0591SJens Wiklander };
4813d3b0591SJens Wiklander 
482b0563631STom Van Eyck static const unsigned char kw_msg[][40] = {
4833d3b0591SJens Wiklander     { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
4843d3b0591SJens Wiklander       0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
485b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
4863d3b0591SJens Wiklander     { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
4873d3b0591SJens Wiklander       0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
4883d3b0591SJens Wiklander       0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
4893d3b0591SJens Wiklander       0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
4903d3b0591SJens Wiklander       0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
4913d3b0591SJens Wiklander     { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
4923d3b0591SJens Wiklander       0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
4933d3b0591SJens Wiklander       0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
494b0563631STom Van Eyck #endif
4953d3b0591SJens Wiklander };
4963d3b0591SJens Wiklander 
497b0563631STom Van Eyck static const size_t kw_msg_len[] = {
498b0563631STom Van Eyck     16,
499b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
500b0563631STom Van Eyck     40,
501b0563631STom Van Eyck     24
502b0563631STom Van Eyck #endif
503b0563631STom Van Eyck };
504b0563631STom Van Eyck static const size_t kw_out_len[] = {
505b0563631STom Van Eyck     24,
506b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
507b0563631STom Van Eyck     48,
508b0563631STom Van Eyck     32
509b0563631STom Van Eyck #endif
510b0563631STom Van Eyck };
511b0563631STom Van Eyck static const unsigned char kw_res[][48] = {
5123d3b0591SJens Wiklander     { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
5133d3b0591SJens Wiklander       0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
5143d3b0591SJens Wiklander       0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
515b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
5163d3b0591SJens Wiklander     { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
5173d3b0591SJens Wiklander       0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
5183d3b0591SJens Wiklander       0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
5193d3b0591SJens Wiklander       0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
5203d3b0591SJens Wiklander       0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
5213d3b0591SJens Wiklander       0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
5223d3b0591SJens Wiklander     { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
5233d3b0591SJens Wiklander       0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
5243d3b0591SJens Wiklander       0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
5253d3b0591SJens Wiklander       0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
526b0563631STom Van Eyck #endif
5273d3b0591SJens Wiklander };
5283d3b0591SJens Wiklander 
529b0563631STom Van Eyck static const unsigned char kwp_key[][32] = {
5303d3b0591SJens Wiklander     { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
5313d3b0591SJens Wiklander       0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
532b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
5333d3b0591SJens Wiklander     { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
5343d3b0591SJens Wiklander       0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
5353d3b0591SJens Wiklander       0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
5363d3b0591SJens Wiklander     { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
5373d3b0591SJens Wiklander       0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
5383d3b0591SJens Wiklander       0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
5393d3b0591SJens Wiklander       0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
540b0563631STom Van Eyck #endif
5413d3b0591SJens Wiklander };
5423d3b0591SJens Wiklander 
543b0563631STom Van Eyck static const unsigned char kwp_msg[][31] = {
5443d3b0591SJens Wiklander     { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
5453d3b0591SJens Wiklander       0x96 },
546b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
5473d3b0591SJens Wiklander     { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
5483d3b0591SJens Wiklander       0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
5493d3b0591SJens Wiklander       0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
5503d3b0591SJens Wiklander       0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
5513d3b0591SJens Wiklander     { 0xd1 }
552b0563631STom Van Eyck #endif
5533d3b0591SJens Wiklander };
554b0563631STom Van Eyck static const size_t kwp_msg_len[] = {
555b0563631STom Van Eyck     9,
556b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
557b0563631STom Van Eyck     31,
558b0563631STom Van Eyck     1
559b0563631STom Van Eyck #endif
560b0563631STom Van Eyck };
5613d3b0591SJens Wiklander 
562b0563631STom Van Eyck static const unsigned char kwp_res[][48] = {
5633d3b0591SJens Wiklander     { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
5643d3b0591SJens Wiklander       0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
5653d3b0591SJens Wiklander       0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
566b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
5673d3b0591SJens Wiklander     { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
5683d3b0591SJens Wiklander       0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
5693d3b0591SJens Wiklander       0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
5703d3b0591SJens Wiklander       0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
5713d3b0591SJens Wiklander       0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
5723d3b0591SJens Wiklander     { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
5733d3b0591SJens Wiklander       0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4  }
574b0563631STom Van Eyck #endif
5753d3b0591SJens Wiklander };
576b0563631STom Van Eyck static const size_t kwp_out_len[] = {
577b0563631STom Van Eyck     24,
578b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
579b0563631STom Van Eyck     40,
580b0563631STom Van Eyck     16
581b0563631STom Van Eyck #endif
582b0563631STom Van Eyck };
5833d3b0591SJens Wiklander 
mbedtls_nist_kw_self_test(int verbose)5843d3b0591SJens Wiklander int mbedtls_nist_kw_self_test(int verbose)
5853d3b0591SJens Wiklander {
5863d3b0591SJens Wiklander     mbedtls_nist_kw_context ctx;
5873d3b0591SJens Wiklander     unsigned char out[48];
5883d3b0591SJens Wiklander     size_t olen;
5893d3b0591SJens Wiklander     int i;
5903d3b0591SJens Wiklander     int ret = 0;
5913d3b0591SJens Wiklander     mbedtls_nist_kw_init(&ctx);
5923d3b0591SJens Wiklander 
593b0563631STom Van Eyck     /*
594b0563631STom Van Eyck      * KW mode
595b0563631STom Van Eyck      */
596b0563631STom Van Eyck     {
597b0563631STom Van Eyck         static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
598b0563631STom Van Eyck 
599b0563631STom Van Eyck         for (i = 0; i < num_tests; i++) {
60032b31808SJens Wiklander             if (verbose != 0) {
6013d3b0591SJens Wiklander                 mbedtls_printf("  KW-AES-%u ", (unsigned int) key_len[i] * 8);
60232b31808SJens Wiklander             }
6033d3b0591SJens Wiklander 
6043d3b0591SJens Wiklander             ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
6053d3b0591SJens Wiklander                                          kw_key[i], key_len[i] * 8, 1);
60632b31808SJens Wiklander             if (ret != 0) {
60732b31808SJens Wiklander                 if (verbose != 0) {
6083d3b0591SJens Wiklander                     mbedtls_printf("  KW: setup failed ");
60932b31808SJens Wiklander                 }
6103d3b0591SJens Wiklander 
6113d3b0591SJens Wiklander                 goto end;
6123d3b0591SJens Wiklander             }
6133d3b0591SJens Wiklander 
6143d3b0591SJens Wiklander             ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
6153d3b0591SJens Wiklander                                        kw_msg_len[i], out, &olen, sizeof(out));
6163d3b0591SJens Wiklander             if (ret != 0 || kw_out_len[i] != olen ||
61732b31808SJens Wiklander                 memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
61832b31808SJens Wiklander                 if (verbose != 0) {
6193d3b0591SJens Wiklander                     mbedtls_printf("failed. ");
62032b31808SJens Wiklander                 }
6213d3b0591SJens Wiklander 
6223d3b0591SJens Wiklander                 ret = 1;
6233d3b0591SJens Wiklander                 goto end;
6243d3b0591SJens Wiklander             }
6253d3b0591SJens Wiklander 
6263d3b0591SJens Wiklander             if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
6273d3b0591SJens Wiklander                                               kw_key[i], key_len[i] * 8, 0))
62832b31808SJens Wiklander                 != 0) {
62932b31808SJens Wiklander                 if (verbose != 0) {
6303d3b0591SJens Wiklander                     mbedtls_printf("  KW: setup failed ");
63132b31808SJens Wiklander                 }
6323d3b0591SJens Wiklander 
6333d3b0591SJens Wiklander                 goto end;
6343d3b0591SJens Wiklander             }
6353d3b0591SJens Wiklander 
6363d3b0591SJens Wiklander             ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
6373d3b0591SJens Wiklander                                          out, olen, out, &olen, sizeof(out));
6383d3b0591SJens Wiklander 
6393d3b0591SJens Wiklander             if (ret != 0 || olen != kw_msg_len[i] ||
64032b31808SJens Wiklander                 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
64132b31808SJens Wiklander                 if (verbose != 0) {
6423d3b0591SJens Wiklander                     mbedtls_printf("failed\n");
64332b31808SJens Wiklander                 }
6443d3b0591SJens Wiklander 
6453d3b0591SJens Wiklander                 ret = 1;
6463d3b0591SJens Wiklander                 goto end;
6473d3b0591SJens Wiklander             }
6483d3b0591SJens Wiklander 
64932b31808SJens Wiklander             if (verbose != 0) {
6503d3b0591SJens Wiklander                 mbedtls_printf(" passed\n");
6513d3b0591SJens Wiklander             }
65232b31808SJens Wiklander         }
653b0563631STom Van Eyck     }
6543d3b0591SJens Wiklander 
655b0563631STom Van Eyck     /*
656b0563631STom Van Eyck      * KWP mode
657b0563631STom Van Eyck      */
658b0563631STom Van Eyck     {
659b0563631STom Van Eyck         static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
660b0563631STom Van Eyck 
661b0563631STom Van Eyck         for (i = 0; i < num_tests; i++) {
6623d3b0591SJens Wiklander             olen = sizeof(out);
66332b31808SJens Wiklander             if (verbose != 0) {
6643d3b0591SJens Wiklander                 mbedtls_printf("  KWP-AES-%u ", (unsigned int) key_len[i] * 8);
66532b31808SJens Wiklander             }
6663d3b0591SJens Wiklander 
6673d3b0591SJens Wiklander             ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
6683d3b0591SJens Wiklander                                          key_len[i] * 8, 1);
66932b31808SJens Wiklander             if (ret  != 0) {
67032b31808SJens Wiklander                 if (verbose != 0) {
6713d3b0591SJens Wiklander                     mbedtls_printf("  KWP: setup failed ");
67232b31808SJens Wiklander                 }
6733d3b0591SJens Wiklander 
6743d3b0591SJens Wiklander                 goto end;
6753d3b0591SJens Wiklander             }
6763d3b0591SJens Wiklander             ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
6773d3b0591SJens Wiklander                                        kwp_msg_len[i], out, &olen, sizeof(out));
6783d3b0591SJens Wiklander 
6793d3b0591SJens Wiklander             if (ret != 0 || kwp_out_len[i] != olen ||
68032b31808SJens Wiklander                 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
68132b31808SJens Wiklander                 if (verbose != 0) {
6823d3b0591SJens Wiklander                     mbedtls_printf("failed. ");
68332b31808SJens Wiklander                 }
6843d3b0591SJens Wiklander 
6853d3b0591SJens Wiklander                 ret = 1;
6863d3b0591SJens Wiklander                 goto end;
6873d3b0591SJens Wiklander             }
6883d3b0591SJens Wiklander 
6893d3b0591SJens Wiklander             if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
6903d3b0591SJens Wiklander                                               kwp_key[i], key_len[i] * 8, 0))
69132b31808SJens Wiklander                 != 0) {
69232b31808SJens Wiklander                 if (verbose != 0) {
6933d3b0591SJens Wiklander                     mbedtls_printf("  KWP: setup failed ");
69432b31808SJens Wiklander                 }
6953d3b0591SJens Wiklander 
6963d3b0591SJens Wiklander                 goto end;
6973d3b0591SJens Wiklander             }
6983d3b0591SJens Wiklander 
6993d3b0591SJens Wiklander             ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
7003d3b0591SJens Wiklander                                          olen, out, &olen, sizeof(out));
7013d3b0591SJens Wiklander 
7023d3b0591SJens Wiklander             if (ret != 0 || olen != kwp_msg_len[i] ||
70332b31808SJens Wiklander                 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
70432b31808SJens Wiklander                 if (verbose != 0) {
7053d3b0591SJens Wiklander                     mbedtls_printf("failed. ");
70632b31808SJens Wiklander                 }
7073d3b0591SJens Wiklander 
7083d3b0591SJens Wiklander                 ret = 1;
7093d3b0591SJens Wiklander                 goto end;
7103d3b0591SJens Wiklander             }
7113d3b0591SJens Wiklander 
71232b31808SJens Wiklander             if (verbose != 0) {
7133d3b0591SJens Wiklander                 mbedtls_printf(" passed\n");
7143d3b0591SJens Wiklander             }
71532b31808SJens Wiklander         }
716b0563631STom Van Eyck     }
7173d3b0591SJens Wiklander end:
7183d3b0591SJens Wiklander     mbedtls_nist_kw_free(&ctx);
7193d3b0591SJens Wiklander 
72032b31808SJens Wiklander     if (verbose != 0) {
7213d3b0591SJens Wiklander         mbedtls_printf("\n");
72232b31808SJens Wiklander     }
7233d3b0591SJens Wiklander 
72432b31808SJens Wiklander     return ret;
7253d3b0591SJens Wiklander }
7263d3b0591SJens Wiklander 
7273d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
7283d3b0591SJens Wiklander 
7293d3b0591SJens Wiklander #endif /* MBEDTLS_NIST_KW_C */
730