xref: /optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
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
67901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
73d3b0591SJens Wiklander  *
83d3b0591SJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
93d3b0591SJens Wiklander  *  not use this file except in compliance with the License.
103d3b0591SJens Wiklander  *  You may obtain a copy of the License at
113d3b0591SJens Wiklander  *
123d3b0591SJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
133d3b0591SJens Wiklander  *
143d3b0591SJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
153d3b0591SJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
163d3b0591SJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
173d3b0591SJens Wiklander  *  See the License for the specific language governing permissions and
183d3b0591SJens Wiklander  *  limitations under the License.
193d3b0591SJens Wiklander  */
203d3b0591SJens Wiklander /*
213d3b0591SJens Wiklander  * Definition of Key Wrapping:
223d3b0591SJens Wiklander  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
233d3b0591SJens Wiklander  * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
243d3b0591SJens Wiklander  * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
253d3b0591SJens Wiklander  *
263d3b0591SJens Wiklander  * Note: RFC 3394 defines different methodology for intermediate operations for
273d3b0591SJens Wiklander  * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
283d3b0591SJens Wiklander  */
293d3b0591SJens Wiklander 
307901324dSJerome Forissier #include "common.h"
313d3b0591SJens Wiklander 
323d3b0591SJens Wiklander #if defined(MBEDTLS_NIST_KW_C)
333d3b0591SJens Wiklander 
343d3b0591SJens Wiklander #include "mbedtls/nist_kw.h"
353d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
3611fa71b9SJerome Forissier #include "mbedtls/error.h"
37039e02dfSJerome Forissier #include "mbedtls/constant_time.h"
383d3b0591SJens Wiklander 
393d3b0591SJens Wiklander #include <stdint.h>
403d3b0591SJens Wiklander #include <string.h>
413d3b0591SJens Wiklander 
423d3b0591SJens Wiklander #include "mbedtls/platform.h"
433d3b0591SJens Wiklander 
443d3b0591SJens Wiklander #if !defined(MBEDTLS_NIST_KW_ALT)
453d3b0591SJens Wiklander 
463d3b0591SJens Wiklander #define KW_SEMIBLOCK_LENGTH    8
473d3b0591SJens Wiklander #define MIN_SEMIBLOCKS_COUNT   3
483d3b0591SJens Wiklander 
493d3b0591SJens Wiklander /*! The 64-bit default integrity check value (ICV) for KW mode. */
503d3b0591SJens Wiklander static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
513d3b0591SJens Wiklander /*! The 32-bit default integrity check value (ICV) for KWP mode. */
523d3b0591SJens Wiklander static const  unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
533d3b0591SJens Wiklander 
543d3b0591SJens Wiklander /*
553d3b0591SJens Wiklander  * Initialize context
563d3b0591SJens Wiklander  */
573d3b0591SJens Wiklander void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
583d3b0591SJens Wiklander {
593d3b0591SJens Wiklander     memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
603d3b0591SJens Wiklander }
613d3b0591SJens Wiklander 
623d3b0591SJens Wiklander int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
633d3b0591SJens Wiklander                            mbedtls_cipher_id_t cipher,
643d3b0591SJens Wiklander                            const unsigned char *key,
653d3b0591SJens Wiklander                            unsigned int keybits,
663d3b0591SJens Wiklander                            const int is_wrap)
673d3b0591SJens Wiklander {
6811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
693d3b0591SJens Wiklander     const mbedtls_cipher_info_t *cipher_info;
703d3b0591SJens Wiklander 
713d3b0591SJens Wiklander     cipher_info = mbedtls_cipher_info_from_values(cipher,
723d3b0591SJens Wiklander                                                   keybits,
733d3b0591SJens Wiklander                                                   MBEDTLS_MODE_ECB);
74*32b31808SJens Wiklander     if (cipher_info == NULL) {
75*32b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
76*32b31808SJens Wiklander     }
773d3b0591SJens Wiklander 
78*32b31808SJens Wiklander     if (cipher_info->block_size != 16) {
79*32b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
80*32b31808SJens Wiklander     }
813d3b0591SJens Wiklander 
823d3b0591SJens Wiklander     /*
833d3b0591SJens Wiklander      * SP 800-38F currently defines AES cipher as the only block cipher allowed:
843d3b0591SJens Wiklander      * "For KW and KWP, the underlying block cipher shall be approved, and the
853d3b0591SJens Wiklander      *  block size shall be 128 bits. Currently, the AES block cipher, with key
863d3b0591SJens Wiklander      *  lengths of 128, 192, or 256 bits, is the only block cipher that fits
873d3b0591SJens Wiklander      *  this profile."
883d3b0591SJens Wiklander      *  Currently we don't support other 128 bit block ciphers for key wrapping,
893d3b0591SJens Wiklander      *  such as Camellia and Aria.
903d3b0591SJens Wiklander      */
91*32b31808SJens Wiklander     if (cipher != MBEDTLS_CIPHER_ID_AES) {
92*32b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
93*32b31808SJens Wiklander     }
943d3b0591SJens Wiklander 
953d3b0591SJens Wiklander     mbedtls_cipher_free(&ctx->cipher_ctx);
963d3b0591SJens Wiklander 
97*32b31808SJens Wiklander     if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
98*32b31808SJens Wiklander         return ret;
99*32b31808SJens Wiklander     }
1003d3b0591SJens Wiklander 
1013d3b0591SJens Wiklander     if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
1023d3b0591SJens Wiklander                                      is_wrap ? MBEDTLS_ENCRYPT :
1033d3b0591SJens Wiklander                                      MBEDTLS_DECRYPT)
104*32b31808SJens Wiklander          ) != 0) {
105*32b31808SJens Wiklander         return ret;
1063d3b0591SJens Wiklander     }
1073d3b0591SJens Wiklander 
108*32b31808SJens Wiklander     return 0;
1093d3b0591SJens Wiklander }
1103d3b0591SJens Wiklander 
1113d3b0591SJens Wiklander /*
1123d3b0591SJens Wiklander  * Free context
1133d3b0591SJens Wiklander  */
1143d3b0591SJens Wiklander void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
1153d3b0591SJens Wiklander {
1163d3b0591SJens Wiklander     mbedtls_cipher_free(&ctx->cipher_ctx);
1173d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
1183d3b0591SJens Wiklander }
1193d3b0591SJens Wiklander 
1203d3b0591SJens Wiklander /*
1213d3b0591SJens Wiklander  * Helper function for Xoring the uint64_t "t" with the encrypted A.
1223d3b0591SJens Wiklander  * Defined in NIST SP 800-38F section 6.1
1233d3b0591SJens Wiklander  */
1243d3b0591SJens Wiklander static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
1253d3b0591SJens Wiklander {
1263d3b0591SJens Wiklander     size_t i = 0;
127*32b31808SJens Wiklander     for (i = 0; i < sizeof(t); i++) {
1283d3b0591SJens Wiklander         A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
1293d3b0591SJens Wiklander     }
1303d3b0591SJens Wiklander }
1313d3b0591SJens Wiklander 
1323d3b0591SJens Wiklander /*
1333d3b0591SJens Wiklander  * KW-AE as defined in SP 800-38F section 6.2
1343d3b0591SJens Wiklander  * KWP-AE as defined in SP 800-38F section 6.3
1353d3b0591SJens Wiklander  */
1363d3b0591SJens Wiklander int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
1373d3b0591SJens Wiklander                          mbedtls_nist_kw_mode_t mode,
1383d3b0591SJens Wiklander                          const unsigned char *input, size_t in_len,
1393d3b0591SJens Wiklander                          unsigned char *output, size_t *out_len, size_t out_size)
1403d3b0591SJens Wiklander {
1413d3b0591SJens Wiklander     int ret = 0;
1423d3b0591SJens Wiklander     size_t semiblocks = 0;
1433d3b0591SJens Wiklander     size_t s;
1443d3b0591SJens Wiklander     size_t olen, padlen = 0;
1453d3b0591SJens Wiklander     uint64_t t = 0;
1463d3b0591SJens Wiklander     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
1473d3b0591SJens Wiklander     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
1483d3b0591SJens Wiklander 
1493d3b0591SJens Wiklander     *out_len = 0;
1503d3b0591SJens Wiklander     /*
1513d3b0591SJens Wiklander      * Generate the String to work on
1523d3b0591SJens Wiklander      */
153*32b31808SJens Wiklander     if (mode == MBEDTLS_KW_MODE_KW) {
154*32b31808SJens Wiklander         if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
155*32b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1563d3b0591SJens Wiklander         }
1573d3b0591SJens Wiklander 
1583d3b0591SJens Wiklander         /*
1593d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the plaintext length for KW
1603d3b0591SJens Wiklander          * must be between 2 to 2^54-1 semiblocks inclusive.
1613d3b0591SJens Wiklander          */
1623d3b0591SJens Wiklander         if (in_len < 16 ||
1633d3b0591SJens Wiklander #if SIZE_MAX > 0x1FFFFFFFFFFFFF8
1643d3b0591SJens Wiklander             in_len > 0x1FFFFFFFFFFFFF8 ||
1653d3b0591SJens Wiklander #endif
166*32b31808SJens Wiklander             in_len % KW_SEMIBLOCK_LENGTH != 0) {
167*32b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1683d3b0591SJens Wiklander         }
1693d3b0591SJens Wiklander 
1703d3b0591SJens Wiklander         memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
1713d3b0591SJens Wiklander         memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
172*32b31808SJens Wiklander     } else {
173*32b31808SJens Wiklander         if (in_len % 8 != 0) {
1743d3b0591SJens Wiklander             padlen = (8 - (in_len % 8));
1753d3b0591SJens Wiklander         }
1763d3b0591SJens Wiklander 
177*32b31808SJens Wiklander         if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
178*32b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1793d3b0591SJens Wiklander         }
1803d3b0591SJens Wiklander 
1813d3b0591SJens Wiklander         /*
1823d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the plaintext length for KWP
1833d3b0591SJens Wiklander          * must be between 1 and 2^32-1 octets inclusive.
1843d3b0591SJens Wiklander          */
1853d3b0591SJens Wiklander         if (in_len < 1
1863d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF
1873d3b0591SJens Wiklander             || in_len > 0xFFFFFFFF
1883d3b0591SJens Wiklander #endif
189*32b31808SJens Wiklander             ) {
190*32b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
1913d3b0591SJens Wiklander         }
1923d3b0591SJens Wiklander 
1933d3b0591SJens Wiklander         memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
194039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
1953d3b0591SJens Wiklander                               KW_SEMIBLOCK_LENGTH / 2);
1963d3b0591SJens Wiklander 
1973d3b0591SJens Wiklander         memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
1983d3b0591SJens Wiklander         memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
1993d3b0591SJens Wiklander     }
2003d3b0591SJens Wiklander     semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
2013d3b0591SJens Wiklander 
2023d3b0591SJens Wiklander     s = 6 * (semiblocks - 1);
2033d3b0591SJens Wiklander 
2043d3b0591SJens Wiklander     if (mode == MBEDTLS_KW_MODE_KWP
205*32b31808SJens Wiklander         && in_len <= KW_SEMIBLOCK_LENGTH) {
2063d3b0591SJens Wiklander         memcpy(inbuff, output, 16);
2073d3b0591SJens Wiklander         ret = mbedtls_cipher_update(&ctx->cipher_ctx,
2083d3b0591SJens Wiklander                                     inbuff, 16, output, &olen);
209*32b31808SJens Wiklander         if (ret != 0) {
2103d3b0591SJens Wiklander             goto cleanup;
2113d3b0591SJens Wiklander         }
212*32b31808SJens Wiklander     } else {
2137901324dSJerome Forissier         unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
2147901324dSJerome Forissier         unsigned char *A = output;
2157901324dSJerome Forissier 
2163d3b0591SJens Wiklander         /*
2173d3b0591SJens Wiklander          * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
2183d3b0591SJens Wiklander          */
219*32b31808SJens Wiklander         if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
2203d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
2213d3b0591SJens Wiklander             goto cleanup;
2223d3b0591SJens Wiklander         }
2233d3b0591SJens Wiklander 
2243d3b0591SJens Wiklander         /* Calculate intermediate values */
225*32b31808SJens Wiklander         for (t = 1; t <= s; t++) {
2263d3b0591SJens Wiklander             memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
2273d3b0591SJens Wiklander             memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
2283d3b0591SJens Wiklander 
2293d3b0591SJens Wiklander             ret = mbedtls_cipher_update(&ctx->cipher_ctx,
2303d3b0591SJens Wiklander                                         inbuff, 16, outbuff, &olen);
231*32b31808SJens Wiklander             if (ret != 0) {
2323d3b0591SJens Wiklander                 goto cleanup;
233*32b31808SJens Wiklander             }
2343d3b0591SJens Wiklander 
2353d3b0591SJens Wiklander             memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
2363d3b0591SJens Wiklander             calc_a_xor_t(A, t);
2373d3b0591SJens Wiklander 
2383d3b0591SJens Wiklander             memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
2393d3b0591SJens Wiklander             R2 += KW_SEMIBLOCK_LENGTH;
240*32b31808SJens Wiklander             if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
2413d3b0591SJens Wiklander                 R2 = output + KW_SEMIBLOCK_LENGTH;
2423d3b0591SJens Wiklander             }
2433d3b0591SJens Wiklander         }
244*32b31808SJens Wiklander     }
2453d3b0591SJens Wiklander 
2463d3b0591SJens Wiklander     *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
2473d3b0591SJens Wiklander 
2483d3b0591SJens Wiklander cleanup:
2493d3b0591SJens Wiklander 
250*32b31808SJens Wiklander     if (ret != 0) {
2513d3b0591SJens Wiklander         memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
2523d3b0591SJens Wiklander     }
2533d3b0591SJens Wiklander     mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
2543d3b0591SJens Wiklander     mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
2553d3b0591SJens Wiklander 
256*32b31808SJens Wiklander     return ret;
2573d3b0591SJens Wiklander }
2583d3b0591SJens Wiklander 
2593d3b0591SJens Wiklander /*
2603d3b0591SJens Wiklander  * W-1 function as defined in RFC 3394 section 2.2.2
2613d3b0591SJens Wiklander  * This function assumes the following:
2623d3b0591SJens Wiklander  * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
2633d3b0591SJens Wiklander  * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
2643d3b0591SJens Wiklander  * 3. Minimal number of semiblocks is 3.
2653d3b0591SJens Wiklander  * 4. A is a buffer to hold the first semiblock of the input buffer.
2663d3b0591SJens Wiklander  */
2673d3b0591SJens Wiklander static int unwrap(mbedtls_nist_kw_context *ctx,
2683d3b0591SJens Wiklander                   const unsigned char *input, size_t semiblocks,
2693d3b0591SJens Wiklander                   unsigned char A[KW_SEMIBLOCK_LENGTH],
2703d3b0591SJens Wiklander                   unsigned char *output, size_t *out_len)
2713d3b0591SJens Wiklander {
2723d3b0591SJens Wiklander     int ret = 0;
2733d3b0591SJens Wiklander     const size_t s = 6 * (semiblocks - 1);
2743d3b0591SJens Wiklander     size_t olen;
2753d3b0591SJens Wiklander     uint64_t t = 0;
2763d3b0591SJens Wiklander     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
2773d3b0591SJens Wiklander     unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
2787901324dSJerome Forissier     unsigned char *R = NULL;
2793d3b0591SJens Wiklander     *out_len = 0;
2803d3b0591SJens Wiklander 
281*32b31808SJens Wiklander     if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
282*32b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
2833d3b0591SJens Wiklander     }
2843d3b0591SJens Wiklander 
2853d3b0591SJens Wiklander     memcpy(A, input, KW_SEMIBLOCK_LENGTH);
2863d3b0591SJens Wiklander     memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
2877901324dSJerome Forissier     R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
2883d3b0591SJens Wiklander 
2893d3b0591SJens Wiklander     /* Calculate intermediate values */
290*32b31808SJens Wiklander     for (t = s; t >= 1; t--) {
2913d3b0591SJens Wiklander         calc_a_xor_t(A, t);
2923d3b0591SJens Wiklander 
2933d3b0591SJens Wiklander         memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
2943d3b0591SJens Wiklander         memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
2953d3b0591SJens Wiklander 
2963d3b0591SJens Wiklander         ret = mbedtls_cipher_update(&ctx->cipher_ctx,
2973d3b0591SJens Wiklander                                     inbuff, 16, outbuff, &olen);
298*32b31808SJens Wiklander         if (ret != 0) {
2993d3b0591SJens Wiklander             goto cleanup;
300*32b31808SJens Wiklander         }
3013d3b0591SJens Wiklander 
3023d3b0591SJens Wiklander         memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
3033d3b0591SJens Wiklander 
3043d3b0591SJens Wiklander         /* Set R as LSB64 of outbuff */
3053d3b0591SJens Wiklander         memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
3063d3b0591SJens Wiklander 
307*32b31808SJens Wiklander         if (R == output) {
3083d3b0591SJens Wiklander             R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
309*32b31808SJens Wiklander         } else {
3103d3b0591SJens Wiklander             R -= KW_SEMIBLOCK_LENGTH;
3113d3b0591SJens Wiklander         }
312*32b31808SJens Wiklander     }
3133d3b0591SJens Wiklander 
3143d3b0591SJens Wiklander     *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
3153d3b0591SJens Wiklander 
3163d3b0591SJens Wiklander cleanup:
317*32b31808SJens Wiklander     if (ret != 0) {
3183d3b0591SJens Wiklander         memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
319*32b31808SJens Wiklander     }
3203d3b0591SJens Wiklander     mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
3213d3b0591SJens Wiklander     mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
3223d3b0591SJens Wiklander 
323*32b31808SJens Wiklander     return ret;
3243d3b0591SJens Wiklander }
3253d3b0591SJens Wiklander 
3263d3b0591SJens Wiklander /*
3273d3b0591SJens Wiklander  * KW-AD as defined in SP 800-38F section 6.2
3283d3b0591SJens Wiklander  * KWP-AD as defined in SP 800-38F section 6.3
3293d3b0591SJens Wiklander  */
3303d3b0591SJens Wiklander int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
3313d3b0591SJens Wiklander                            mbedtls_nist_kw_mode_t mode,
3323d3b0591SJens Wiklander                            const unsigned char *input, size_t in_len,
3333d3b0591SJens Wiklander                            unsigned char *output, size_t *out_len, size_t out_size)
3343d3b0591SJens Wiklander {
3353d3b0591SJens Wiklander     int ret = 0;
3363d3b0591SJens Wiklander     size_t i, olen;
3373d3b0591SJens Wiklander     unsigned char A[KW_SEMIBLOCK_LENGTH];
3383d3b0591SJens Wiklander     unsigned char diff, bad_padding = 0;
3393d3b0591SJens Wiklander 
3403d3b0591SJens Wiklander     *out_len = 0;
341*32b31808SJens Wiklander     if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
342*32b31808SJens Wiklander         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
3433d3b0591SJens Wiklander     }
3443d3b0591SJens Wiklander 
345*32b31808SJens Wiklander     if (mode == MBEDTLS_KW_MODE_KW) {
3463d3b0591SJens Wiklander         /*
3473d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the ciphertext length for KW
3483d3b0591SJens Wiklander          * must be between 3 to 2^54 semiblocks inclusive.
3493d3b0591SJens Wiklander          */
3503d3b0591SJens Wiklander         if (in_len < 24 ||
3513d3b0591SJens Wiklander #if SIZE_MAX > 0x200000000000000
3523d3b0591SJens Wiklander             in_len > 0x200000000000000 ||
3533d3b0591SJens Wiklander #endif
354*32b31808SJens Wiklander             in_len % KW_SEMIBLOCK_LENGTH != 0) {
355*32b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
3563d3b0591SJens Wiklander         }
3573d3b0591SJens Wiklander 
3583d3b0591SJens Wiklander         ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
3593d3b0591SJens Wiklander                      A, output, out_len);
360*32b31808SJens Wiklander         if (ret != 0) {
3613d3b0591SJens Wiklander             goto cleanup;
362*32b31808SJens Wiklander         }
3633d3b0591SJens Wiklander 
3643d3b0591SJens Wiklander         /* Check ICV in "constant-time" */
365039e02dfSJerome Forissier         diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
3663d3b0591SJens Wiklander 
367*32b31808SJens Wiklander         if (diff != 0) {
3683d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
3693d3b0591SJens Wiklander             goto cleanup;
3703d3b0591SJens Wiklander         }
3713d3b0591SJens Wiklander 
372*32b31808SJens Wiklander     } else if (mode == MBEDTLS_KW_MODE_KWP) {
3733d3b0591SJens Wiklander         size_t padlen = 0;
3743d3b0591SJens Wiklander         uint32_t Plen;
3753d3b0591SJens Wiklander         /*
3763d3b0591SJens Wiklander          * According to SP 800-38F Table 1, the ciphertext length for KWP
3773d3b0591SJens Wiklander          * must be between 2 to 2^29 semiblocks inclusive.
3783d3b0591SJens Wiklander          */
3793d3b0591SJens Wiklander         if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
3803d3b0591SJens Wiklander #if SIZE_MAX > 0x100000000
3813d3b0591SJens Wiklander             in_len > 0x100000000 ||
3823d3b0591SJens Wiklander #endif
383*32b31808SJens Wiklander             in_len % KW_SEMIBLOCK_LENGTH != 0) {
384*32b31808SJens Wiklander             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
3853d3b0591SJens Wiklander         }
3863d3b0591SJens Wiklander 
387*32b31808SJens Wiklander         if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
3883d3b0591SJens Wiklander             unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
3893d3b0591SJens Wiklander             ret = mbedtls_cipher_update(&ctx->cipher_ctx,
3903d3b0591SJens Wiklander                                         input, 16, outbuff, &olen);
391*32b31808SJens Wiklander             if (ret != 0) {
3923d3b0591SJens Wiklander                 goto cleanup;
393*32b31808SJens Wiklander             }
3943d3b0591SJens Wiklander 
3953d3b0591SJens Wiklander             memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
3963d3b0591SJens Wiklander             memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
3973d3b0591SJens Wiklander             mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
3983d3b0591SJens Wiklander             *out_len = KW_SEMIBLOCK_LENGTH;
399*32b31808SJens Wiklander         } else {
4003d3b0591SJens Wiklander             /* in_len >=  KW_SEMIBLOCK_LENGTH * 3 */
4013d3b0591SJens Wiklander             ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
4023d3b0591SJens Wiklander                          A, output, out_len);
403*32b31808SJens Wiklander             if (ret != 0) {
4043d3b0591SJens Wiklander                 goto cleanup;
4053d3b0591SJens Wiklander             }
406*32b31808SJens Wiklander         }
4073d3b0591SJens Wiklander 
4083d3b0591SJens Wiklander         /* Check ICV in "constant-time" */
409039e02dfSJerome Forissier         diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
4103d3b0591SJens Wiklander 
411*32b31808SJens Wiklander         if (diff != 0) {
4123d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
4133d3b0591SJens Wiklander         }
4143d3b0591SJens Wiklander 
415039e02dfSJerome Forissier         Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
4163d3b0591SJens Wiklander 
4173d3b0591SJens Wiklander         /*
4183d3b0591SJens Wiklander          * Plen is the length of the plaintext, when the input is valid.
4193d3b0591SJens Wiklander          * If Plen is larger than the plaintext and padding, padlen will be
4203d3b0591SJens Wiklander          * larger than 8, because of the type wrap around.
4213d3b0591SJens Wiklander          */
4223d3b0591SJens Wiklander         padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
423*32b31808SJens Wiklander         if (padlen > 7) {
4243d3b0591SJens Wiklander             padlen &= 7;
4253d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
4263d3b0591SJens Wiklander         }
4273d3b0591SJens Wiklander 
4283d3b0591SJens Wiklander         /* Check padding in "constant-time" */
429*32b31808SJens Wiklander         for (diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++) {
430*32b31808SJens Wiklander             if (i >= KW_SEMIBLOCK_LENGTH - padlen) {
4313d3b0591SJens Wiklander                 diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
432*32b31808SJens Wiklander             } else {
4333d3b0591SJens Wiklander                 bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
4343d3b0591SJens Wiklander             }
435*32b31808SJens Wiklander         }
4363d3b0591SJens Wiklander 
437*32b31808SJens Wiklander         if (diff != 0) {
4383d3b0591SJens Wiklander             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
4393d3b0591SJens Wiklander         }
4403d3b0591SJens Wiklander 
441*32b31808SJens Wiklander         if (ret != 0) {
4423d3b0591SJens Wiklander             goto cleanup;
4433d3b0591SJens Wiklander         }
4443d3b0591SJens Wiklander         memset(output + Plen, 0, padlen);
4453d3b0591SJens Wiklander         *out_len = Plen;
446*32b31808SJens Wiklander     } else {
4473d3b0591SJens Wiklander         ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
4483d3b0591SJens Wiklander         goto cleanup;
4493d3b0591SJens Wiklander     }
4503d3b0591SJens Wiklander 
4513d3b0591SJens Wiklander cleanup:
452*32b31808SJens Wiklander     if (ret != 0) {
4533d3b0591SJens Wiklander         memset(output, 0, *out_len);
4543d3b0591SJens Wiklander         *out_len = 0;
4553d3b0591SJens Wiklander     }
4563d3b0591SJens Wiklander 
4573d3b0591SJens Wiklander     mbedtls_platform_zeroize(&bad_padding, sizeof(bad_padding));
4583d3b0591SJens Wiklander     mbedtls_platform_zeroize(&diff, sizeof(diff));
4593d3b0591SJens Wiklander     mbedtls_platform_zeroize(A, sizeof(A));
4603d3b0591SJens Wiklander 
461*32b31808SJens Wiklander     return ret;
4623d3b0591SJens Wiklander }
4633d3b0591SJens Wiklander 
4643d3b0591SJens Wiklander #endif /* !MBEDTLS_NIST_KW_ALT */
4653d3b0591SJens Wiklander 
4663d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
4673d3b0591SJens Wiklander 
4683d3b0591SJens Wiklander #define KW_TESTS 3
4693d3b0591SJens Wiklander 
4703d3b0591SJens Wiklander /*
4713d3b0591SJens Wiklander  * Test vectors taken from NIST
4723d3b0591SJens Wiklander  * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
4733d3b0591SJens Wiklander  */
4743d3b0591SJens Wiklander static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
4753d3b0591SJens Wiklander 
4763d3b0591SJens Wiklander static const unsigned char kw_key[KW_TESTS][32] = {
4773d3b0591SJens Wiklander     { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
4783d3b0591SJens Wiklander       0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
4793d3b0591SJens Wiklander     { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
4803d3b0591SJens Wiklander       0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
4813d3b0591SJens Wiklander       0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
4823d3b0591SJens Wiklander     { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
4833d3b0591SJens Wiklander       0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
4843d3b0591SJens Wiklander       0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
4853d3b0591SJens Wiklander       0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
4863d3b0591SJens Wiklander };
4873d3b0591SJens Wiklander 
4883d3b0591SJens Wiklander static const unsigned char kw_msg[KW_TESTS][40] = {
4893d3b0591SJens Wiklander     { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
4903d3b0591SJens Wiklander       0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
4913d3b0591SJens Wiklander     { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
4923d3b0591SJens Wiklander       0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
4933d3b0591SJens Wiklander       0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
4943d3b0591SJens Wiklander       0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
4953d3b0591SJens Wiklander       0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
4963d3b0591SJens Wiklander     { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
4973d3b0591SJens Wiklander       0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
4983d3b0591SJens Wiklander       0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
4993d3b0591SJens Wiklander };
5003d3b0591SJens Wiklander 
5013d3b0591SJens Wiklander static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
5023d3b0591SJens Wiklander static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
5033d3b0591SJens Wiklander static const unsigned char kw_res[KW_TESTS][48] = {
5043d3b0591SJens Wiklander     { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
5053d3b0591SJens Wiklander       0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
5063d3b0591SJens Wiklander       0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
5073d3b0591SJens Wiklander     { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
5083d3b0591SJens Wiklander       0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
5093d3b0591SJens Wiklander       0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
5103d3b0591SJens Wiklander       0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
5113d3b0591SJens Wiklander       0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
5123d3b0591SJens Wiklander       0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
5133d3b0591SJens Wiklander     { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
5143d3b0591SJens Wiklander       0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
5153d3b0591SJens Wiklander       0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
5163d3b0591SJens Wiklander       0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
5173d3b0591SJens Wiklander };
5183d3b0591SJens Wiklander 
5193d3b0591SJens Wiklander static const unsigned char kwp_key[KW_TESTS][32] = {
5203d3b0591SJens Wiklander     { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
5213d3b0591SJens Wiklander       0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
5223d3b0591SJens Wiklander     { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
5233d3b0591SJens Wiklander       0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
5243d3b0591SJens Wiklander       0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
5253d3b0591SJens Wiklander     { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
5263d3b0591SJens Wiklander       0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
5273d3b0591SJens Wiklander       0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
5283d3b0591SJens Wiklander       0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
5293d3b0591SJens Wiklander };
5303d3b0591SJens Wiklander 
5313d3b0591SJens Wiklander static const unsigned char kwp_msg[KW_TESTS][31] = {
5323d3b0591SJens Wiklander     { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
5333d3b0591SJens Wiklander       0x96 },
5343d3b0591SJens Wiklander     { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
5353d3b0591SJens Wiklander       0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
5363d3b0591SJens Wiklander       0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
5373d3b0591SJens Wiklander       0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
5383d3b0591SJens Wiklander     { 0xd1 }
5393d3b0591SJens Wiklander };
5403d3b0591SJens Wiklander static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
5413d3b0591SJens Wiklander 
5423d3b0591SJens Wiklander static const unsigned char kwp_res[KW_TESTS][48] = {
5433d3b0591SJens Wiklander     { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
5443d3b0591SJens Wiklander       0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
5453d3b0591SJens Wiklander       0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
5463d3b0591SJens Wiklander     { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
5473d3b0591SJens Wiklander       0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
5483d3b0591SJens Wiklander       0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
5493d3b0591SJens Wiklander       0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
5503d3b0591SJens Wiklander       0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
5513d3b0591SJens Wiklander     { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
5523d3b0591SJens Wiklander       0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4  }
5533d3b0591SJens Wiklander };
5543d3b0591SJens Wiklander static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
5553d3b0591SJens Wiklander 
5563d3b0591SJens Wiklander int mbedtls_nist_kw_self_test(int verbose)
5573d3b0591SJens Wiklander {
5583d3b0591SJens Wiklander     mbedtls_nist_kw_context ctx;
5593d3b0591SJens Wiklander     unsigned char out[48];
5603d3b0591SJens Wiklander     size_t olen;
5613d3b0591SJens Wiklander     int i;
5623d3b0591SJens Wiklander     int ret = 0;
5633d3b0591SJens Wiklander     mbedtls_nist_kw_init(&ctx);
5643d3b0591SJens Wiklander 
565*32b31808SJens Wiklander     for (i = 0; i < KW_TESTS; i++) {
566*32b31808SJens Wiklander         if (verbose != 0) {
5673d3b0591SJens Wiklander             mbedtls_printf("  KW-AES-%u ", (unsigned int) key_len[i] * 8);
568*32b31808SJens Wiklander         }
5693d3b0591SJens Wiklander 
5703d3b0591SJens Wiklander         ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
5713d3b0591SJens Wiklander                                      kw_key[i], key_len[i] * 8, 1);
572*32b31808SJens Wiklander         if (ret != 0) {
573*32b31808SJens Wiklander             if (verbose != 0) {
5743d3b0591SJens Wiklander                 mbedtls_printf("  KW: setup failed ");
575*32b31808SJens Wiklander             }
5763d3b0591SJens Wiklander 
5773d3b0591SJens Wiklander             goto end;
5783d3b0591SJens Wiklander         }
5793d3b0591SJens Wiklander 
5803d3b0591SJens Wiklander         ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
5813d3b0591SJens Wiklander                                    kw_msg_len[i], out, &olen, sizeof(out));
5823d3b0591SJens Wiklander         if (ret != 0 || kw_out_len[i] != olen ||
583*32b31808SJens Wiklander             memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
584*32b31808SJens Wiklander             if (verbose != 0) {
5853d3b0591SJens Wiklander                 mbedtls_printf("failed. ");
586*32b31808SJens Wiklander             }
5873d3b0591SJens Wiklander 
5883d3b0591SJens Wiklander             ret = 1;
5893d3b0591SJens Wiklander             goto end;
5903d3b0591SJens Wiklander         }
5913d3b0591SJens Wiklander 
5923d3b0591SJens Wiklander         if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
5933d3b0591SJens Wiklander                                           kw_key[i], key_len[i] * 8, 0))
594*32b31808SJens Wiklander             != 0) {
595*32b31808SJens Wiklander             if (verbose != 0) {
5963d3b0591SJens Wiklander                 mbedtls_printf("  KW: setup failed ");
597*32b31808SJens Wiklander             }
5983d3b0591SJens Wiklander 
5993d3b0591SJens Wiklander             goto end;
6003d3b0591SJens Wiklander         }
6013d3b0591SJens Wiklander 
6023d3b0591SJens Wiklander         ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
6033d3b0591SJens Wiklander                                      out, olen, out, &olen, sizeof(out));
6043d3b0591SJens Wiklander 
6053d3b0591SJens Wiklander         if (ret != 0 || olen != kw_msg_len[i] ||
606*32b31808SJens Wiklander             memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
607*32b31808SJens Wiklander             if (verbose != 0) {
6083d3b0591SJens Wiklander                 mbedtls_printf("failed\n");
609*32b31808SJens Wiklander             }
6103d3b0591SJens Wiklander 
6113d3b0591SJens Wiklander             ret = 1;
6123d3b0591SJens Wiklander             goto end;
6133d3b0591SJens Wiklander         }
6143d3b0591SJens Wiklander 
615*32b31808SJens Wiklander         if (verbose != 0) {
6163d3b0591SJens Wiklander             mbedtls_printf(" passed\n");
6173d3b0591SJens Wiklander         }
618*32b31808SJens Wiklander     }
6193d3b0591SJens Wiklander 
620*32b31808SJens Wiklander     for (i = 0; i < KW_TESTS; i++) {
6213d3b0591SJens Wiklander         olen = sizeof(out);
622*32b31808SJens Wiklander         if (verbose != 0) {
6233d3b0591SJens Wiklander             mbedtls_printf("  KWP-AES-%u ", (unsigned int) key_len[i] * 8);
624*32b31808SJens Wiklander         }
6253d3b0591SJens Wiklander 
6263d3b0591SJens Wiklander         ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
6273d3b0591SJens Wiklander                                      key_len[i] * 8, 1);
628*32b31808SJens Wiklander         if (ret  != 0) {
629*32b31808SJens Wiklander             if (verbose != 0) {
6303d3b0591SJens Wiklander                 mbedtls_printf("  KWP: setup failed ");
631*32b31808SJens Wiklander             }
6323d3b0591SJens Wiklander 
6333d3b0591SJens Wiklander             goto end;
6343d3b0591SJens Wiklander         }
6353d3b0591SJens Wiklander         ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
6363d3b0591SJens Wiklander                                    kwp_msg_len[i], out, &olen, sizeof(out));
6373d3b0591SJens Wiklander 
6383d3b0591SJens Wiklander         if (ret != 0 || kwp_out_len[i] != olen ||
639*32b31808SJens Wiklander             memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
640*32b31808SJens Wiklander             if (verbose != 0) {
6413d3b0591SJens Wiklander                 mbedtls_printf("failed. ");
642*32b31808SJens Wiklander             }
6433d3b0591SJens Wiklander 
6443d3b0591SJens Wiklander             ret = 1;
6453d3b0591SJens Wiklander             goto end;
6463d3b0591SJens Wiklander         }
6473d3b0591SJens Wiklander 
6483d3b0591SJens Wiklander         if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
6493d3b0591SJens Wiklander                                           kwp_key[i], key_len[i] * 8, 0))
650*32b31808SJens Wiklander             != 0) {
651*32b31808SJens Wiklander             if (verbose != 0) {
6523d3b0591SJens Wiklander                 mbedtls_printf("  KWP: setup failed ");
653*32b31808SJens Wiklander             }
6543d3b0591SJens Wiklander 
6553d3b0591SJens Wiklander             goto end;
6563d3b0591SJens Wiklander         }
6573d3b0591SJens Wiklander 
6583d3b0591SJens Wiklander         ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
6593d3b0591SJens Wiklander                                      olen, out, &olen, sizeof(out));
6603d3b0591SJens Wiklander 
6613d3b0591SJens Wiklander         if (ret != 0 || olen != kwp_msg_len[i] ||
662*32b31808SJens Wiklander             memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
663*32b31808SJens Wiklander             if (verbose != 0) {
6643d3b0591SJens Wiklander                 mbedtls_printf("failed. ");
665*32b31808SJens Wiklander             }
6663d3b0591SJens Wiklander 
6673d3b0591SJens Wiklander             ret = 1;
6683d3b0591SJens Wiklander             goto end;
6693d3b0591SJens Wiklander         }
6703d3b0591SJens Wiklander 
671*32b31808SJens Wiklander         if (verbose != 0) {
6723d3b0591SJens Wiklander             mbedtls_printf(" passed\n");
6733d3b0591SJens Wiklander         }
674*32b31808SJens Wiklander     }
6753d3b0591SJens Wiklander end:
6763d3b0591SJens Wiklander     mbedtls_nist_kw_free(&ctx);
6773d3b0591SJens Wiklander 
678*32b31808SJens Wiklander     if (verbose != 0) {
6793d3b0591SJens Wiklander         mbedtls_printf("\n");
680*32b31808SJens Wiklander     }
6813d3b0591SJens Wiklander 
682*32b31808SJens Wiklander     return ret;
6833d3b0591SJens Wiklander }
6843d3b0591SJens Wiklander 
6853d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
6863d3b0591SJens Wiklander 
6873d3b0591SJens Wiklander #endif /* MBEDTLS_NIST_KW_C */
688