xref: /optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c (revision b0563631928755fe864b97785160fb3088e9efdc)
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
6*b0563631STom 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"
26*b0563631STom 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  */
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 
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 
67*b0563631STom 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  */
1033d3b0591SJens Wiklander void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
1043d3b0591SJens Wiklander {
1053d3b0591SJens Wiklander     mbedtls_cipher_free(&ctx->cipher_ctx);
1063d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
1073d3b0591SJens Wiklander }
1083d3b0591SJens Wiklander 
1093d3b0591SJens Wiklander /*
1103d3b0591SJens Wiklander  * Helper function for Xoring the uint64_t "t" with the encrypted A.
1113d3b0591SJens Wiklander  * Defined in NIST SP 800-38F section 6.1
1123d3b0591SJens Wiklander  */
1133d3b0591SJens Wiklander static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
1143d3b0591SJens Wiklander {
1153d3b0591SJens Wiklander     size_t i = 0;
11632b31808SJens Wiklander     for (i = 0; i < sizeof(t); i++) {
1173d3b0591SJens Wiklander         A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
1183d3b0591SJens Wiklander     }
1193d3b0591SJens Wiklander }
1203d3b0591SJens Wiklander 
1213d3b0591SJens Wiklander /*
1223d3b0591SJens Wiklander  * KW-AE as defined in SP 800-38F section 6.2
1233d3b0591SJens Wiklander  * KWP-AE as defined in SP 800-38F section 6.3
1243d3b0591SJens Wiklander  */
1253d3b0591SJens Wiklander int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
1263d3b0591SJens Wiklander                          mbedtls_nist_kw_mode_t mode,
1273d3b0591SJens Wiklander                          const unsigned char *input, size_t in_len,
1283d3b0591SJens Wiklander                          unsigned char *output, size_t *out_len, size_t out_size)
1293d3b0591SJens Wiklander {
1303d3b0591SJens Wiklander     int ret = 0;
1313d3b0591SJens Wiklander     size_t semiblocks = 0;
1323d3b0591SJens Wiklander     size_t s;
1333d3b0591SJens Wiklander     size_t olen, padlen = 0;
1343d3b0591SJens Wiklander     uint64_t t = 0;
1353d3b0591SJens Wiklander     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
1363d3b0591SJens Wiklander     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
1373d3b0591SJens Wiklander 
1383d3b0591SJens Wiklander     *out_len = 0;
1393d3b0591SJens Wiklander     /*
1403d3b0591SJens Wiklander      * Generate the String to work on
1413d3b0591SJens Wiklander      */
14232b31808SJens Wiklander     if (mode == MBEDTLS_KW_MODE_KW) {
14332b31808SJens Wiklander         if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
14432b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1453d3b0591SJens Wiklander         }
1463d3b0591SJens Wiklander 
1473d3b0591SJens Wiklander         /*
1483d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the plaintext length for KW
1493d3b0591SJens Wiklander          * must be between 2 to 2^54-1 semiblocks inclusive.
1503d3b0591SJens Wiklander          */
1513d3b0591SJens Wiklander         if (in_len < 16 ||
1523d3b0591SJens Wiklander #if SIZE_MAX > 0x1FFFFFFFFFFFFF8
1533d3b0591SJens Wiklander             in_len > 0x1FFFFFFFFFFFFF8 ||
1543d3b0591SJens Wiklander #endif
15532b31808SJens Wiklander             in_len % KW_SEMIBLOCK_LENGTH != 0) {
15632b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1573d3b0591SJens Wiklander         }
1583d3b0591SJens Wiklander 
1593d3b0591SJens Wiklander         memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
1603d3b0591SJens Wiklander         memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
16132b31808SJens Wiklander     } else {
16232b31808SJens Wiklander         if (in_len % 8 != 0) {
1633d3b0591SJens Wiklander             padlen = (8 - (in_len % 8));
1643d3b0591SJens Wiklander         }
1653d3b0591SJens Wiklander 
16632b31808SJens Wiklander         if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
16732b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1683d3b0591SJens Wiklander         }
1693d3b0591SJens Wiklander 
1703d3b0591SJens Wiklander         /*
1713d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the plaintext length for KWP
1723d3b0591SJens Wiklander          * must be between 1 and 2^32-1 octets inclusive.
1733d3b0591SJens Wiklander          */
1743d3b0591SJens Wiklander         if (in_len < 1
1753d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF
1763d3b0591SJens Wiklander             || in_len > 0xFFFFFFFF
1773d3b0591SJens Wiklander #endif
17832b31808SJens Wiklander             ) {
17932b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1803d3b0591SJens Wiklander         }
1813d3b0591SJens Wiklander 
1823d3b0591SJens Wiklander         memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
183039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
1843d3b0591SJens Wiklander                               KW_SEMIBLOCK_LENGTH / 2);
1853d3b0591SJens Wiklander 
1863d3b0591SJens Wiklander         memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
1873d3b0591SJens Wiklander         memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
1883d3b0591SJens Wiklander     }
1893d3b0591SJens Wiklander     semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
1903d3b0591SJens Wiklander 
1913d3b0591SJens Wiklander     s = 6 * (semiblocks - 1);
1923d3b0591SJens Wiklander 
1933d3b0591SJens Wiklander     if (mode == MBEDTLS_KW_MODE_KWP
19432b31808SJens Wiklander         && in_len <= KW_SEMIBLOCK_LENGTH) {
1953d3b0591SJens Wiklander         memcpy(inbuff, output, 16);
1963d3b0591SJens Wiklander         ret = mbedtls_cipher_update(&ctx->cipher_ctx,
1973d3b0591SJens Wiklander                                     inbuff, 16, output, &olen);
19832b31808SJens Wiklander         if (ret != 0) {
1993d3b0591SJens Wiklander             goto cleanup;
2003d3b0591SJens Wiklander         }
20132b31808SJens Wiklander     } else {
2027901324dSJerome Forissier         unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
2037901324dSJerome Forissier         unsigned char *A = output;
2047901324dSJerome Forissier 
2053d3b0591SJens Wiklander         /*
2063d3b0591SJens Wiklander          * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
2073d3b0591SJens Wiklander          */
20832b31808SJens Wiklander         if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
2093d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
2103d3b0591SJens Wiklander             goto cleanup;
2113d3b0591SJens Wiklander         }
2123d3b0591SJens Wiklander 
2133d3b0591SJens Wiklander         /* Calculate intermediate values */
21432b31808SJens Wiklander         for (t = 1; t <= s; t++) {
2153d3b0591SJens Wiklander             memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
2163d3b0591SJens Wiklander             memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
2173d3b0591SJens Wiklander 
2183d3b0591SJens Wiklander             ret = mbedtls_cipher_update(&ctx->cipher_ctx,
2193d3b0591SJens Wiklander                                         inbuff, 16, outbuff, &olen);
22032b31808SJens Wiklander             if (ret != 0) {
2213d3b0591SJens Wiklander                 goto cleanup;
22232b31808SJens Wiklander             }
2233d3b0591SJens Wiklander 
2243d3b0591SJens Wiklander             memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
2253d3b0591SJens Wiklander             calc_a_xor_t(A, t);
2263d3b0591SJens Wiklander 
2273d3b0591SJens Wiklander             memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
2283d3b0591SJens Wiklander             R2 += KW_SEMIBLOCK_LENGTH;
22932b31808SJens Wiklander             if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
2303d3b0591SJens Wiklander                 R2 = output + KW_SEMIBLOCK_LENGTH;
2313d3b0591SJens Wiklander             }
2323d3b0591SJens Wiklander         }
23332b31808SJens Wiklander     }
2343d3b0591SJens Wiklander 
2353d3b0591SJens Wiklander     *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
2363d3b0591SJens Wiklander 
2373d3b0591SJens Wiklander cleanup:
2383d3b0591SJens Wiklander 
23932b31808SJens Wiklander     if (ret != 0) {
2403d3b0591SJens Wiklander         memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
2413d3b0591SJens Wiklander     }
2423d3b0591SJens Wiklander     mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
2433d3b0591SJens Wiklander     mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
2443d3b0591SJens Wiklander 
24532b31808SJens Wiklander     return ret;
2463d3b0591SJens Wiklander }
2473d3b0591SJens Wiklander 
2483d3b0591SJens Wiklander /*
2493d3b0591SJens Wiklander  * W-1 function as defined in RFC 3394 section 2.2.2
2503d3b0591SJens Wiklander  * This function assumes the following:
2513d3b0591SJens Wiklander  * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
2523d3b0591SJens Wiklander  * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
2533d3b0591SJens Wiklander  * 3. Minimal number of semiblocks is 3.
2543d3b0591SJens Wiklander  * 4. A is a buffer to hold the first semiblock of the input buffer.
2553d3b0591SJens Wiklander  */
2563d3b0591SJens Wiklander static int unwrap(mbedtls_nist_kw_context *ctx,
2573d3b0591SJens Wiklander                   const unsigned char *input, size_t semiblocks,
2583d3b0591SJens Wiklander                   unsigned char A[KW_SEMIBLOCK_LENGTH],
2593d3b0591SJens Wiklander                   unsigned char *output, size_t *out_len)
2603d3b0591SJens Wiklander {
2613d3b0591SJens Wiklander     int ret = 0;
2623d3b0591SJens Wiklander     const size_t s = 6 * (semiblocks - 1);
2633d3b0591SJens Wiklander     size_t olen;
2643d3b0591SJens Wiklander     uint64_t t = 0;
2653d3b0591SJens Wiklander     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
2663d3b0591SJens Wiklander     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
2677901324dSJerome Forissier     unsigned char *R = NULL;
2683d3b0591SJens Wiklander     *out_len = 0;
2693d3b0591SJens Wiklander 
27032b31808SJens Wiklander     if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
27132b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
2723d3b0591SJens Wiklander     }
2733d3b0591SJens Wiklander 
2743d3b0591SJens Wiklander     memcpy(A, input, KW_SEMIBLOCK_LENGTH);
2753d3b0591SJens Wiklander     memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
2767901324dSJerome Forissier     R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
2773d3b0591SJens Wiklander 
2783d3b0591SJens Wiklander     /* Calculate intermediate values */
27932b31808SJens Wiklander     for (t = s; t >= 1; t--) {
2803d3b0591SJens Wiklander         calc_a_xor_t(A, t);
2813d3b0591SJens Wiklander 
2823d3b0591SJens Wiklander         memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
2833d3b0591SJens Wiklander         memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
2843d3b0591SJens Wiklander 
2853d3b0591SJens Wiklander         ret = mbedtls_cipher_update(&ctx->cipher_ctx,
2863d3b0591SJens Wiklander                                     inbuff, 16, outbuff, &olen);
28732b31808SJens Wiklander         if (ret != 0) {
2883d3b0591SJens Wiklander             goto cleanup;
28932b31808SJens Wiklander         }
2903d3b0591SJens Wiklander 
2913d3b0591SJens Wiklander         memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
2923d3b0591SJens Wiklander 
2933d3b0591SJens Wiklander         /* Set R as LSB64 of outbuff */
2943d3b0591SJens Wiklander         memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
2953d3b0591SJens Wiklander 
29632b31808SJens Wiklander         if (R == output) {
2973d3b0591SJens Wiklander             R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
29832b31808SJens Wiklander         } else {
2993d3b0591SJens Wiklander             R -= KW_SEMIBLOCK_LENGTH;
3003d3b0591SJens Wiklander         }
30132b31808SJens Wiklander     }
3023d3b0591SJens Wiklander 
3033d3b0591SJens Wiklander     *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
3043d3b0591SJens Wiklander 
3053d3b0591SJens Wiklander cleanup:
30632b31808SJens Wiklander     if (ret != 0) {
3073d3b0591SJens Wiklander         memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
30832b31808SJens Wiklander     }
3093d3b0591SJens Wiklander     mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
3103d3b0591SJens Wiklander     mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
3113d3b0591SJens Wiklander 
31232b31808SJens Wiklander     return ret;
3133d3b0591SJens Wiklander }
3143d3b0591SJens Wiklander 
3153d3b0591SJens Wiklander /*
3163d3b0591SJens Wiklander  * KW-AD as defined in SP 800-38F section 6.2
3173d3b0591SJens Wiklander  * KWP-AD as defined in SP 800-38F section 6.3
3183d3b0591SJens Wiklander  */
3193d3b0591SJens Wiklander int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
3203d3b0591SJens Wiklander                            mbedtls_nist_kw_mode_t mode,
3213d3b0591SJens Wiklander                            const unsigned char *input, size_t in_len,
3223d3b0591SJens Wiklander                            unsigned char *output, size_t *out_len, size_t out_size)
3233d3b0591SJens Wiklander {
3243d3b0591SJens Wiklander     int ret = 0;
325*b0563631STom Van Eyck     size_t olen;
3263d3b0591SJens Wiklander     unsigned char A[KW_SEMIBLOCK_LENGTH];
327*b0563631STom Van Eyck     int diff;
3283d3b0591SJens Wiklander 
3293d3b0591SJens Wiklander     *out_len = 0;
33032b31808SJens Wiklander     if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
33132b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
3323d3b0591SJens Wiklander     }
3333d3b0591SJens Wiklander 
33432b31808SJens Wiklander     if (mode == MBEDTLS_KW_MODE_KW) {
3353d3b0591SJens Wiklander         /*
3363d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the ciphertext length for KW
3373d3b0591SJens Wiklander          * must be between 3 to 2^54 semiblocks inclusive.
3383d3b0591SJens Wiklander          */
3393d3b0591SJens Wiklander         if (in_len < 24 ||
3403d3b0591SJens Wiklander #if SIZE_MAX > 0x200000000000000
3413d3b0591SJens Wiklander             in_len > 0x200000000000000 ||
3423d3b0591SJens Wiklander #endif
34332b31808SJens Wiklander             in_len % KW_SEMIBLOCK_LENGTH != 0) {
34432b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
3453d3b0591SJens Wiklander         }
3463d3b0591SJens Wiklander 
3473d3b0591SJens Wiklander         ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
3483d3b0591SJens Wiklander                      A, output, out_len);
34932b31808SJens Wiklander         if (ret != 0) {
3503d3b0591SJens Wiklander             goto cleanup;
35132b31808SJens Wiklander         }
3523d3b0591SJens Wiklander 
3533d3b0591SJens Wiklander         /* Check ICV in "constant-time" */
354039e02dfSJerome Forissier         diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
3553d3b0591SJens Wiklander 
35632b31808SJens Wiklander         if (diff != 0) {
3573d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
3583d3b0591SJens Wiklander             goto cleanup;
3593d3b0591SJens Wiklander         }
3603d3b0591SJens Wiklander 
36132b31808SJens Wiklander     } else if (mode == MBEDTLS_KW_MODE_KWP) {
3623d3b0591SJens Wiklander         size_t padlen = 0;
3633d3b0591SJens Wiklander         uint32_t Plen;
3643d3b0591SJens Wiklander         /*
3653d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the ciphertext length for KWP
3663d3b0591SJens Wiklander          * must be between 2 to 2^29 semiblocks inclusive.
3673d3b0591SJens Wiklander          */
3683d3b0591SJens Wiklander         if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
3693d3b0591SJens Wiklander #if SIZE_MAX > 0x100000000
3703d3b0591SJens Wiklander             in_len > 0x100000000 ||
3713d3b0591SJens Wiklander #endif
37232b31808SJens Wiklander             in_len % KW_SEMIBLOCK_LENGTH != 0) {
37332b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
3743d3b0591SJens Wiklander         }
3753d3b0591SJens Wiklander 
37632b31808SJens Wiklander         if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
3773d3b0591SJens Wiklander             unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
3783d3b0591SJens Wiklander             ret = mbedtls_cipher_update(&ctx->cipher_ctx,
3793d3b0591SJens Wiklander                                         input, 16, outbuff, &olen);
38032b31808SJens Wiklander             if (ret != 0) {
3813d3b0591SJens Wiklander                 goto cleanup;
38232b31808SJens Wiklander             }
3833d3b0591SJens Wiklander 
3843d3b0591SJens Wiklander             memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
3853d3b0591SJens Wiklander             memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
3863d3b0591SJens Wiklander             mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
3873d3b0591SJens Wiklander             *out_len = KW_SEMIBLOCK_LENGTH;
38832b31808SJens Wiklander         } else {
3893d3b0591SJens Wiklander             /* in_len >=  KW_SEMIBLOCK_LENGTH * 3 */
3903d3b0591SJens Wiklander             ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
3913d3b0591SJens Wiklander                          A, output, out_len);
39232b31808SJens Wiklander             if (ret != 0) {
3933d3b0591SJens Wiklander                 goto cleanup;
3943d3b0591SJens Wiklander             }
39532b31808SJens Wiklander         }
3963d3b0591SJens Wiklander 
3973d3b0591SJens Wiklander         /* Check ICV in "constant-time" */
398039e02dfSJerome Forissier         diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
3993d3b0591SJens Wiklander 
40032b31808SJens Wiklander         if (diff != 0) {
4013d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
4023d3b0591SJens Wiklander         }
4033d3b0591SJens Wiklander 
404039e02dfSJerome Forissier         Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
4053d3b0591SJens Wiklander 
4063d3b0591SJens Wiklander         /*
4073d3b0591SJens Wiklander          * Plen is the length of the plaintext, when the input is valid.
4083d3b0591SJens Wiklander          * If Plen is larger than the plaintext and padding, padlen will be
4093d3b0591SJens Wiklander          * larger than 8, because of the type wrap around.
4103d3b0591SJens Wiklander          */
4113d3b0591SJens Wiklander         padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
412*b0563631STom Van Eyck         ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
413*b0563631STom Van Eyck                                   MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
4143d3b0591SJens Wiklander         padlen &= 7;
4153d3b0591SJens Wiklander 
4163d3b0591SJens Wiklander         /* Check padding in "constant-time" */
417*b0563631STom Van Eyck         const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
418*b0563631STom Van Eyck         diff = mbedtls_ct_memcmp_partial(
419*b0563631STom Van Eyck             &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
420*b0563631STom Van Eyck             KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
4213d3b0591SJens Wiklander 
42232b31808SJens Wiklander         if (diff != 0) {
4233d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
4243d3b0591SJens Wiklander         }
4253d3b0591SJens Wiklander 
42632b31808SJens Wiklander         if (ret != 0) {
4273d3b0591SJens Wiklander             goto cleanup;
4283d3b0591SJens Wiklander         }
4293d3b0591SJens Wiklander         memset(output + Plen, 0, padlen);
4303d3b0591SJens Wiklander         *out_len = Plen;
43132b31808SJens Wiklander     } else {
4323d3b0591SJens Wiklander         ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
4333d3b0591SJens Wiklander         goto cleanup;
4343d3b0591SJens Wiklander     }
4353d3b0591SJens Wiklander 
4363d3b0591SJens Wiklander cleanup:
43732b31808SJens Wiklander     if (ret != 0) {
4383d3b0591SJens Wiklander         memset(output, 0, *out_len);
4393d3b0591SJens Wiklander         *out_len = 0;
4403d3b0591SJens Wiklander     }
4413d3b0591SJens Wiklander 
4423d3b0591SJens Wiklander     mbedtls_platform_zeroize(&diff, sizeof(diff));
4433d3b0591SJens Wiklander     mbedtls_platform_zeroize(A, sizeof(A));
4443d3b0591SJens Wiklander 
44532b31808SJens Wiklander     return ret;
4463d3b0591SJens Wiklander }
4473d3b0591SJens Wiklander 
4483d3b0591SJens Wiklander #endif /* !MBEDTLS_NIST_KW_ALT */
4493d3b0591SJens Wiklander 
4503d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
4513d3b0591SJens Wiklander 
4523d3b0591SJens Wiklander /*
4533d3b0591SJens Wiklander  * Test vectors taken from NIST
4543d3b0591SJens Wiklander  * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
4553d3b0591SJens Wiklander  */
456*b0563631STom Van Eyck static const unsigned int key_len[] = {
457*b0563631STom Van Eyck     16,
458*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
459*b0563631STom Van Eyck     24,
460*b0563631STom Van Eyck     32
461*b0563631STom Van Eyck #endif
462*b0563631STom Van Eyck };
4633d3b0591SJens Wiklander 
464*b0563631STom Van Eyck static const unsigned char kw_key[][32] = {
4653d3b0591SJens Wiklander     { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
4663d3b0591SJens Wiklander       0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
467*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
4683d3b0591SJens Wiklander     { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
4693d3b0591SJens Wiklander       0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
4703d3b0591SJens Wiklander       0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
4713d3b0591SJens Wiklander     { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
4723d3b0591SJens Wiklander       0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
4733d3b0591SJens Wiklander       0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
4743d3b0591SJens Wiklander       0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
475*b0563631STom Van Eyck #endif
4763d3b0591SJens Wiklander };
4773d3b0591SJens Wiklander 
478*b0563631STom Van Eyck static const unsigned char kw_msg[][40] = {
4793d3b0591SJens Wiklander     { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
4803d3b0591SJens Wiklander       0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
481*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
4823d3b0591SJens Wiklander     { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
4833d3b0591SJens Wiklander       0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
4843d3b0591SJens Wiklander       0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
4853d3b0591SJens Wiklander       0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
4863d3b0591SJens Wiklander       0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
4873d3b0591SJens Wiklander     { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
4883d3b0591SJens Wiklander       0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
4893d3b0591SJens Wiklander       0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
490*b0563631STom Van Eyck #endif
4913d3b0591SJens Wiklander };
4923d3b0591SJens Wiklander 
493*b0563631STom Van Eyck static const size_t kw_msg_len[] = {
494*b0563631STom Van Eyck     16,
495*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
496*b0563631STom Van Eyck     40,
497*b0563631STom Van Eyck     24
498*b0563631STom Van Eyck #endif
499*b0563631STom Van Eyck };
500*b0563631STom Van Eyck static const size_t kw_out_len[] = {
501*b0563631STom Van Eyck     24,
502*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
503*b0563631STom Van Eyck     48,
504*b0563631STom Van Eyck     32
505*b0563631STom Van Eyck #endif
506*b0563631STom Van Eyck };
507*b0563631STom Van Eyck static const unsigned char kw_res[][48] = {
5083d3b0591SJens Wiklander     { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
5093d3b0591SJens Wiklander       0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
5103d3b0591SJens Wiklander       0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
511*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
5123d3b0591SJens Wiklander     { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
5133d3b0591SJens Wiklander       0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
5143d3b0591SJens Wiklander       0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
5153d3b0591SJens Wiklander       0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
5163d3b0591SJens Wiklander       0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
5173d3b0591SJens Wiklander       0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
5183d3b0591SJens Wiklander     { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
5193d3b0591SJens Wiklander       0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
5203d3b0591SJens Wiklander       0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
5213d3b0591SJens Wiklander       0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
522*b0563631STom Van Eyck #endif
5233d3b0591SJens Wiklander };
5243d3b0591SJens Wiklander 
525*b0563631STom Van Eyck static const unsigned char kwp_key[][32] = {
5263d3b0591SJens Wiklander     { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
5273d3b0591SJens Wiklander       0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
528*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
5293d3b0591SJens Wiklander     { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
5303d3b0591SJens Wiklander       0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
5313d3b0591SJens Wiklander       0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
5323d3b0591SJens Wiklander     { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
5333d3b0591SJens Wiklander       0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
5343d3b0591SJens Wiklander       0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
5353d3b0591SJens Wiklander       0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
536*b0563631STom Van Eyck #endif
5373d3b0591SJens Wiklander };
5383d3b0591SJens Wiklander 
539*b0563631STom Van Eyck static const unsigned char kwp_msg[][31] = {
5403d3b0591SJens Wiklander     { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
5413d3b0591SJens Wiklander       0x96 },
542*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
5433d3b0591SJens Wiklander     { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
5443d3b0591SJens Wiklander       0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
5453d3b0591SJens Wiklander       0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
5463d3b0591SJens Wiklander       0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
5473d3b0591SJens Wiklander     { 0xd1 }
548*b0563631STom Van Eyck #endif
5493d3b0591SJens Wiklander };
550*b0563631STom Van Eyck static const size_t kwp_msg_len[] = {
551*b0563631STom Van Eyck     9,
552*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
553*b0563631STom Van Eyck     31,
554*b0563631STom Van Eyck     1
555*b0563631STom Van Eyck #endif
556*b0563631STom Van Eyck };
5573d3b0591SJens Wiklander 
558*b0563631STom Van Eyck static const unsigned char kwp_res[][48] = {
5593d3b0591SJens Wiklander     { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
5603d3b0591SJens Wiklander       0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
5613d3b0591SJens Wiklander       0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
562*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
5633d3b0591SJens Wiklander     { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
5643d3b0591SJens Wiklander       0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
5653d3b0591SJens Wiklander       0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
5663d3b0591SJens Wiklander       0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
5673d3b0591SJens Wiklander       0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
5683d3b0591SJens Wiklander     { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
5693d3b0591SJens Wiklander       0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4  }
570*b0563631STom Van Eyck #endif
5713d3b0591SJens Wiklander };
572*b0563631STom Van Eyck static const size_t kwp_out_len[] = {
573*b0563631STom Van Eyck     24,
574*b0563631STom Van Eyck #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
575*b0563631STom Van Eyck     40,
576*b0563631STom Van Eyck     16
577*b0563631STom Van Eyck #endif
578*b0563631STom Van Eyck };
5793d3b0591SJens Wiklander 
5803d3b0591SJens Wiklander int mbedtls_nist_kw_self_test(int verbose)
5813d3b0591SJens Wiklander {
5823d3b0591SJens Wiklander     mbedtls_nist_kw_context ctx;
5833d3b0591SJens Wiklander     unsigned char out[48];
5843d3b0591SJens Wiklander     size_t olen;
5853d3b0591SJens Wiklander     int i;
5863d3b0591SJens Wiklander     int ret = 0;
5873d3b0591SJens Wiklander     mbedtls_nist_kw_init(&ctx);
5883d3b0591SJens Wiklander 
589*b0563631STom Van Eyck     /*
590*b0563631STom Van Eyck      * KW mode
591*b0563631STom Van Eyck      */
592*b0563631STom Van Eyck     {
593*b0563631STom Van Eyck         static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
594*b0563631STom Van Eyck 
595*b0563631STom Van Eyck         for (i = 0; i < num_tests; i++) {
59632b31808SJens Wiklander             if (verbose != 0) {
5973d3b0591SJens Wiklander                 mbedtls_printf("  KW-AES-%u ", (unsigned int) key_len[i] * 8);
59832b31808SJens Wiklander             }
5993d3b0591SJens Wiklander 
6003d3b0591SJens Wiklander             ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
6013d3b0591SJens Wiklander                                          kw_key[i], key_len[i] * 8, 1);
60232b31808SJens Wiklander             if (ret != 0) {
60332b31808SJens Wiklander                 if (verbose != 0) {
6043d3b0591SJens Wiklander                     mbedtls_printf("  KW: setup failed ");
60532b31808SJens Wiklander                 }
6063d3b0591SJens Wiklander 
6073d3b0591SJens Wiklander                 goto end;
6083d3b0591SJens Wiklander             }
6093d3b0591SJens Wiklander 
6103d3b0591SJens Wiklander             ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
6113d3b0591SJens Wiklander                                        kw_msg_len[i], out, &olen, sizeof(out));
6123d3b0591SJens Wiklander             if (ret != 0 || kw_out_len[i] != olen ||
61332b31808SJens Wiklander                 memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
61432b31808SJens Wiklander                 if (verbose != 0) {
6153d3b0591SJens Wiklander                     mbedtls_printf("failed. ");
61632b31808SJens Wiklander                 }
6173d3b0591SJens Wiklander 
6183d3b0591SJens Wiklander                 ret = 1;
6193d3b0591SJens Wiklander                 goto end;
6203d3b0591SJens Wiklander             }
6213d3b0591SJens Wiklander 
6223d3b0591SJens Wiklander             if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
6233d3b0591SJens Wiklander                                               kw_key[i], key_len[i] * 8, 0))
62432b31808SJens Wiklander                 != 0) {
62532b31808SJens Wiklander                 if (verbose != 0) {
6263d3b0591SJens Wiklander                     mbedtls_printf("  KW: setup failed ");
62732b31808SJens Wiklander                 }
6283d3b0591SJens Wiklander 
6293d3b0591SJens Wiklander                 goto end;
6303d3b0591SJens Wiklander             }
6313d3b0591SJens Wiklander 
6323d3b0591SJens Wiklander             ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
6333d3b0591SJens Wiklander                                          out, olen, out, &olen, sizeof(out));
6343d3b0591SJens Wiklander 
6353d3b0591SJens Wiklander             if (ret != 0 || olen != kw_msg_len[i] ||
63632b31808SJens Wiklander                 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
63732b31808SJens Wiklander                 if (verbose != 0) {
6383d3b0591SJens Wiklander                     mbedtls_printf("failed\n");
63932b31808SJens Wiklander                 }
6403d3b0591SJens Wiklander 
6413d3b0591SJens Wiklander                 ret = 1;
6423d3b0591SJens Wiklander                 goto end;
6433d3b0591SJens Wiklander             }
6443d3b0591SJens Wiklander 
64532b31808SJens Wiklander             if (verbose != 0) {
6463d3b0591SJens Wiklander                 mbedtls_printf(" passed\n");
6473d3b0591SJens Wiklander             }
64832b31808SJens Wiklander         }
649*b0563631STom Van Eyck     }
6503d3b0591SJens Wiklander 
651*b0563631STom Van Eyck     /*
652*b0563631STom Van Eyck      * KWP mode
653*b0563631STom Van Eyck      */
654*b0563631STom Van Eyck     {
655*b0563631STom Van Eyck         static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
656*b0563631STom Van Eyck 
657*b0563631STom Van Eyck         for (i = 0; i < num_tests; i++) {
6583d3b0591SJens Wiklander             olen = sizeof(out);
65932b31808SJens Wiklander             if (verbose != 0) {
6603d3b0591SJens Wiklander                 mbedtls_printf("  KWP-AES-%u ", (unsigned int) key_len[i] * 8);
66132b31808SJens Wiklander             }
6623d3b0591SJens Wiklander 
6633d3b0591SJens Wiklander             ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
6643d3b0591SJens Wiklander                                          key_len[i] * 8, 1);
66532b31808SJens Wiklander             if (ret  != 0) {
66632b31808SJens Wiklander                 if (verbose != 0) {
6673d3b0591SJens Wiklander                     mbedtls_printf("  KWP: setup failed ");
66832b31808SJens Wiklander                 }
6693d3b0591SJens Wiklander 
6703d3b0591SJens Wiklander                 goto end;
6713d3b0591SJens Wiklander             }
6723d3b0591SJens Wiklander             ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
6733d3b0591SJens Wiklander                                        kwp_msg_len[i], out, &olen, sizeof(out));
6743d3b0591SJens Wiklander 
6753d3b0591SJens Wiklander             if (ret != 0 || kwp_out_len[i] != olen ||
67632b31808SJens Wiklander                 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
67732b31808SJens Wiklander                 if (verbose != 0) {
6783d3b0591SJens Wiklander                     mbedtls_printf("failed. ");
67932b31808SJens Wiklander                 }
6803d3b0591SJens Wiklander 
6813d3b0591SJens Wiklander                 ret = 1;
6823d3b0591SJens Wiklander                 goto end;
6833d3b0591SJens Wiklander             }
6843d3b0591SJens Wiklander 
6853d3b0591SJens Wiklander             if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
6863d3b0591SJens Wiklander                                               kwp_key[i], key_len[i] * 8, 0))
68732b31808SJens Wiklander                 != 0) {
68832b31808SJens Wiklander                 if (verbose != 0) {
6893d3b0591SJens Wiklander                     mbedtls_printf("  KWP: setup failed ");
69032b31808SJens Wiklander                 }
6913d3b0591SJens Wiklander 
6923d3b0591SJens Wiklander                 goto end;
6933d3b0591SJens Wiklander             }
6943d3b0591SJens Wiklander 
6953d3b0591SJens Wiklander             ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
6963d3b0591SJens Wiklander                                          olen, out, &olen, sizeof(out));
6973d3b0591SJens Wiklander 
6983d3b0591SJens Wiklander             if (ret != 0 || olen != kwp_msg_len[i] ||
69932b31808SJens Wiklander                 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
70032b31808SJens Wiklander                 if (verbose != 0) {
7013d3b0591SJens Wiklander                     mbedtls_printf("failed. ");
70232b31808SJens Wiklander                 }
7033d3b0591SJens Wiklander 
7043d3b0591SJens Wiklander                 ret = 1;
7053d3b0591SJens Wiklander                 goto end;
7063d3b0591SJens Wiklander             }
7073d3b0591SJens Wiklander 
70832b31808SJens Wiklander             if (verbose != 0) {
7093d3b0591SJens Wiklander                 mbedtls_printf(" passed\n");
7103d3b0591SJens Wiklander             }
71132b31808SJens Wiklander         }
712*b0563631STom Van Eyck     }
7133d3b0591SJens Wiklander end:
7143d3b0591SJens Wiklander     mbedtls_nist_kw_free(&ctx);
7153d3b0591SJens Wiklander 
71632b31808SJens Wiklander     if (verbose != 0) {
7173d3b0591SJens Wiklander         mbedtls_printf("\n");
71832b31808SJens Wiklander     }
7193d3b0591SJens Wiklander 
72032b31808SJens Wiklander     return ret;
7213d3b0591SJens Wiklander }
7223d3b0591SJens Wiklander 
7233d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
7243d3b0591SJens Wiklander 
7253d3b0591SJens Wiklander #endif /* MBEDTLS_NIST_KW_C */
726