blob: f15425b8bd63363172d00558c5b396a2f892d098 [file] [log] [blame]
Ron Eldorcb349ac2018-07-15 09:29:47 +03001/*
2 * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes
3 * only
4 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02005 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00006 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Ron Eldorcb349ac2018-07-15 09:29:47 +03007 */
8/*
9 * Definition of Key Wrapping:
10 * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
11 * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
12 * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
13 *
14 * Note: RFC 3394 defines different methodology for intermediate operations for
15 * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
16 */
17
Gilles Peskinedb09ef62020-06-03 01:43:33 +020018#include "common.h"
Ron Eldorcb349ac2018-07-15 09:29:47 +030019
20#if defined(MBEDTLS_NIST_KW_C)
21
22#include "mbedtls/nist_kw.h"
23#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000024#include "mbedtls/error.h"
Gabor Mezei765862c2021-10-19 12:22:25 +020025#include "mbedtls/constant_time.h"
Dave Rodgmand337bd92023-09-18 18:22:27 +010026#include "constant_time_internal.h"
Ron Eldorcb349ac2018-07-15 09:29:47 +030027
28#include <stdint.h>
29#include <string.h>
30
Ron Eldorcb349ac2018-07-15 09:29:47 +030031#include "mbedtls/platform.h"
Ron Eldorcb349ac2018-07-15 09:29:47 +030032
33#if !defined(MBEDTLS_NIST_KW_ALT)
34
35#define KW_SEMIBLOCK_LENGTH 8
36#define MIN_SEMIBLOCKS_COUNT 3
37
Ron Eldorcb349ac2018-07-15 09:29:47 +030038/*! The 64-bit default integrity check value (ICV) for KW mode. */
Gilles Peskine449bd832023-01-11 14:50:10 +010039static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
Ron Eldorcb349ac2018-07-15 09:29:47 +030040/*! The 32-bit default integrity check value (ICV) for KWP mode. */
Gilles Peskine449bd832023-01-11 14:50:10 +010041static const unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
Ron Eldorcb349ac2018-07-15 09:29:47 +030042
Ron Eldorcb349ac2018-07-15 09:29:47 +030043/*
44 * Initialize context
45 */
Gilles Peskine449bd832023-01-11 14:50:10 +010046void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
Ron Eldorcb349ac2018-07-15 09:29:47 +030047{
Gilles Peskine449bd832023-01-11 14:50:10 +010048 memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
Ron Eldorcb349ac2018-07-15 09:29:47 +030049}
50
Gilles Peskine449bd832023-01-11 14:50:10 +010051int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
52 mbedtls_cipher_id_t cipher,
53 const unsigned char *key,
54 unsigned int keybits,
55 const int is_wrap)
Ron Eldorcb349ac2018-07-15 09:29:47 +030056{
Janos Follath24eed8d2019-11-22 13:21:35 +000057 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldorcb349ac2018-07-15 09:29:47 +030058 const mbedtls_cipher_info_t *cipher_info;
59
Gilles Peskine449bd832023-01-11 14:50:10 +010060 cipher_info = mbedtls_cipher_info_from_values(cipher,
61 keybits,
62 MBEDTLS_MODE_ECB);
63 if (cipher_info == NULL) {
64 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
65 }
Ron Eldorcb349ac2018-07-15 09:29:47 +030066
Dave Rodgman85a88132023-06-24 11:41:50 +010067 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +010068 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
69 }
Ron Eldorcb349ac2018-07-15 09:29:47 +030070
71 /*
72 * SP 800-38F currently defines AES cipher as the only block cipher allowed:
73 * "For KW and KWP, the underlying block cipher shall be approved, and the
74 * block size shall be 128 bits. Currently, the AES block cipher, with key
75 * lengths of 128, 192, or 256 bits, is the only block cipher that fits
76 * this profile."
77 * Currently we don't support other 128 bit block ciphers for key wrapping,
78 * such as Camellia and Aria.
79 */
Gilles Peskine449bd832023-01-11 14:50:10 +010080 if (cipher != MBEDTLS_CIPHER_ID_AES) {
81 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Ron Eldorcb349ac2018-07-15 09:29:47 +030082 }
83
Gilles Peskine449bd832023-01-11 14:50:10 +010084 mbedtls_cipher_free(&ctx->cipher_ctx);
85
86 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
87 return ret;
88 }
89
90 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
91 is_wrap ? MBEDTLS_ENCRYPT :
92 MBEDTLS_DECRYPT)
93 ) != 0) {
94 return ret;
95 }
96
97 return 0;
Ron Eldorcb349ac2018-07-15 09:29:47 +030098}
99
100/*
101 * Free context
102 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100103void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300104{
Gilles Peskine449bd832023-01-11 14:50:10 +0100105 mbedtls_cipher_free(&ctx->cipher_ctx);
106 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300107}
108
109/*
110 * Helper function for Xoring the uint64_t "t" with the encrypted A.
111 * Defined in NIST SP 800-38F section 6.1
112 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100113static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300114{
115 size_t i = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 for (i = 0; i < sizeof(t); i++) {
117 A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300118 }
119}
120
121/*
122 * KW-AE as defined in SP 800-38F section 6.2
123 * KWP-AE as defined in SP 800-38F section 6.3
124 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100125int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
126 mbedtls_nist_kw_mode_t mode,
127 const unsigned char *input, size_t in_len,
128 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300129{
130 int ret = 0;
131 size_t semiblocks = 0;
132 size_t s;
133 size_t olen, padlen = 0;
134 uint64_t t = 0;
135 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
136 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Ron Eldorcb349ac2018-07-15 09:29:47 +0300137
138 *out_len = 0;
139 /*
140 * Generate the String to work on
141 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 if (mode == MBEDTLS_KW_MODE_KW) {
143 if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
144 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300145 }
146
147 /*
148 * According to SP 800-38F Table 1, the plaintext length for KW
149 * must be between 2 to 2^54-1 semiblocks inclusive.
150 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100151 if (in_len < 16 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300152#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
153 in_len > 0x1FFFFFFFFFFFFF8 ||
154#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100155 in_len % KW_SEMIBLOCK_LENGTH != 0) {
156 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300157 }
158
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
160 memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
161 } else {
162 if (in_len % 8 != 0) {
163 padlen = (8 - (in_len % 8));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300164 }
165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
167 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300168 }
169
170 /*
171 * According to SP 800-38F Table 1, the plaintext length for KWP
172 * must be between 1 and 2^32-1 octets inclusive.
173 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 if (in_len < 1
Ron Eldorcb349ac2018-07-15 09:29:47 +0300175#if SIZE_MAX > 0xFFFFFFFF
176 || in_len > 0xFFFFFFFF
177#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 ) {
179 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300180 }
181
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
183 MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
184 KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300185
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
187 memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300188 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300190
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300192
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 if (mode == MBEDTLS_KW_MODE_KWP
194 && in_len <= KW_SEMIBLOCK_LENGTH) {
195 memcpy(inbuff, output, 16);
196 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
197 inbuff, 16, output, &olen);
198 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300199 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 }
201 } else {
Gilles Peskine89ee5992021-06-01 11:22:56 +0200202 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
203 unsigned char *A = output;
204
Ron Eldorcb349ac2018-07-15 09:29:47 +0300205 /*
206 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
207 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300209 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
210 goto cleanup;
211 }
212
213 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 for (t = 1; t <= s; t++) {
215 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
216 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300217
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
219 inbuff, 16, outbuff, &olen);
220 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300221 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300223
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
225 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300226
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300228 R2 += KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300230 R2 = output + KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300232 }
233 }
234
235 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
236
237cleanup:
238
Gilles Peskine449bd832023-01-11 14:50:10 +0100239 if (ret != 0) {
240 memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300241 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
243 mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500244
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300246}
247
248/*
249 * W-1 function as defined in RFC 3394 section 2.2.2
250 * This function assumes the following:
251 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
252 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
253 * 3. Minimal number of semiblocks is 3.
254 * 4. A is a buffer to hold the first semiblock of the input buffer.
255 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100256static int unwrap(mbedtls_nist_kw_context *ctx,
257 const unsigned char *input, size_t semiblocks,
258 unsigned char A[KW_SEMIBLOCK_LENGTH],
259 unsigned char *output, size_t *out_len)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300260{
261 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100262 const size_t s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300263 size_t olen;
264 uint64_t t = 0;
265 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
266 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine89ee5992021-06-01 11:22:56 +0200267 unsigned char *R = NULL;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300268 *out_len = 0;
269
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
271 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300272 }
273
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 memcpy(A, input, KW_SEMIBLOCK_LENGTH);
275 memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
276 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300277
278 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 for (t = s; t >= 1; t--) {
280 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300281
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
283 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300284
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
286 inbuff, 16, outbuff, &olen);
287 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300288 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300292
293 /* Set R as LSB64 of outbuff */
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 if (R == output) {
297 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
298 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300299 R -= KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300301 }
302
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300304
305cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100306 if (ret != 0) {
307 memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
308 }
309 mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
310 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300311
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300313}
314
315/*
316 * KW-AD as defined in SP 800-38F section 6.2
317 * KWP-AD as defined in SP 800-38F section 6.3
318 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100319int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
320 mbedtls_nist_kw_mode_t mode,
321 const unsigned char *input, size_t in_len,
322 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300323{
324 int ret = 0;
Dave Rodgmand337bd92023-09-18 18:22:27 +0100325 size_t olen;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300326 unsigned char A[KW_SEMIBLOCK_LENGTH];
Dave Rodgmand337bd92023-09-18 18:22:27 +0100327 int diff;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300328
329 *out_len = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
331 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300332 }
333
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 if (mode == MBEDTLS_KW_MODE_KW) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300335 /*
336 * According to SP 800-38F Table 1, the ciphertext length for KW
337 * must be between 3 to 2^54 semiblocks inclusive.
338 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 if (in_len < 24 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300340#if SIZE_MAX > 0x200000000000000
341 in_len > 0x200000000000000 ||
342#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 in_len % KW_SEMIBLOCK_LENGTH != 0) {
344 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300345 }
346
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
348 A, output, out_len);
349 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300350 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300352
353 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300355
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300357 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
358 goto cleanup;
359 }
360
Gilles Peskine449bd832023-01-11 14:50:10 +0100361 } else if (mode == MBEDTLS_KW_MODE_KWP) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300362 size_t padlen = 0;
363 uint32_t Plen;
364 /*
365 * According to SP 800-38F Table 1, the ciphertext length for KWP
366 * must be between 2 to 2^29 semiblocks inclusive.
367 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300369#if SIZE_MAX > 0x100000000
370 in_len > 0x100000000 ||
371#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 in_len % KW_SEMIBLOCK_LENGTH != 0) {
373 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300374 }
375
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300377 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
379 input, 16, outbuff, &olen);
380 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300381 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300383
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
385 memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
386 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300387 *out_len = KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300389 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
391 A, output, out_len);
392 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300393 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300395 }
396
397 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100398 diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300399
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300401 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
402 }
403
Gilles Peskine449bd832023-01-11 14:50:10 +0100404 Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300405
406 /*
407 * Plen is the length of the plaintext, when the input is valid.
408 * If Plen is larger than the plaintext and padding, padlen will be
409 * larger than 8, because of the type wrap around.
410 */
411 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
Dave Rodgmand03f4832023-09-22 09:52:15 +0100412 ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
413 MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
Dave Rodgman51c15302023-09-19 17:09:13 +0100414 padlen &= 7;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300415
416 /* Check padding in "constant-time" */
Dave Rodgmand337bd92023-09-18 18:22:27 +0100417 const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
418 diff = mbedtls_ct_memcmp_partial(
419 &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
420 KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300421
Gilles Peskine449bd832023-01-11 14:50:10 +0100422 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300423 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
424 }
425
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300427 goto cleanup;
428 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 memset(output + Plen, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300430 *out_len = Plen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300432 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
433 goto cleanup;
434 }
435
436cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 if (ret != 0) {
438 memset(output, 0, *out_len);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300439 *out_len = 0;
440 }
441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 mbedtls_platform_zeroize(&diff, sizeof(diff));
443 mbedtls_platform_zeroize(A, sizeof(A));
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300446}
447
448#endif /* !MBEDTLS_NIST_KW_ALT */
449
Ron Eldor9ab746c2018-07-15 09:33:07 +0300450#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
451
Ron Eldor9ab746c2018-07-15 09:33:07 +0300452/*
453 * Test vectors taken from NIST
454 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
455 */
Yanray Wangd896fcb2023-05-11 17:24:41 +0800456static const unsigned int key_len[] = {
457 16,
458#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
459 24,
460 32
461#endif
462};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300463
Yanray Wangd896fcb2023-05-11 17:24:41 +0800464static const unsigned char kw_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300465 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
466 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800467#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300468 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
469 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
470 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
471 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
472 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
473 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
474 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800475#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300476};
477
Yanray Wangd896fcb2023-05-11 17:24:41 +0800478static const unsigned char kw_msg[][40] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300479 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
480 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800481#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300482 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
483 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
484 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
485 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
486 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
487 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
488 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
489 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800490#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300491};
492
Yanray Wangd896fcb2023-05-11 17:24:41 +0800493static const size_t kw_msg_len[] = {
494 16,
495#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
496 40,
497 24
498#endif
499};
500static const size_t kw_out_len[] = {
501 24,
502#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
503 48,
504 32
505#endif
506};
507static const unsigned char kw_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300508 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
509 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
510 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800511#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300512 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
513 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
514 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
515 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
516 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
517 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
518 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
519 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
520 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
521 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800522#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300523};
524
Yanray Wangd896fcb2023-05-11 17:24:41 +0800525static const unsigned char kwp_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300526 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
527 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800528#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300529 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
530 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
531 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
532 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
533 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
534 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
535 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800536#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300537};
538
Yanray Wangd896fcb2023-05-11 17:24:41 +0800539static const unsigned char kwp_msg[][31] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300540 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
541 0x96 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800542#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300543 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
544 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
545 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
546 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
547 { 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800548#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300549};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800550static const size_t kwp_msg_len[] = {
551 9,
552#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
553 31,
554 1
555#endif
556};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300557
Yanray Wangd896fcb2023-05-11 17:24:41 +0800558static const unsigned char kwp_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300559 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
560 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
561 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800562#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300563 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
564 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
565 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
566 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
567 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
568 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
569 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800570#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300571};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800572static const size_t kwp_out_len[] = {
573 24,
574#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
575 40,
576 16
577#endif
578};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300579
Gilles Peskine449bd832023-01-11 14:50:10 +0100580int mbedtls_nist_kw_self_test(int verbose)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300581{
582 mbedtls_nist_kw_context ctx;
583 unsigned char out[48];
584 size_t olen;
585 int i;
586 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100587 mbedtls_nist_kw_init(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300588
Yanray Wangd896fcb2023-05-11 17:24:41 +0800589 /*
590 * KW mode
591 */
592 {
593 static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300594
Yanray Wangd896fcb2023-05-11 17:24:41 +0800595 for (i = 0; i < num_tests; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100596 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800597 mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100598 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300599
Yanray Wangd896fcb2023-05-11 17:24:41 +0800600 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
601 kw_key[i], key_len[i] * 8, 1);
602 if (ret != 0) {
603 if (verbose != 0) {
604 mbedtls_printf(" KW: setup failed ");
605 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300606
Yanray Wangd896fcb2023-05-11 17:24:41 +0800607 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300609
Yanray Wangd896fcb2023-05-11 17:24:41 +0800610 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
611 kw_msg_len[i], out, &olen, sizeof(out));
612 if (ret != 0 || kw_out_len[i] != olen ||
613 memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
614 if (verbose != 0) {
615 mbedtls_printf("failed. ");
616 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300617
Yanray Wangd896fcb2023-05-11 17:24:41 +0800618 ret = 1;
619 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100620 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300621
Yanray Wangd896fcb2023-05-11 17:24:41 +0800622 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
623 kw_key[i], key_len[i] * 8, 0))
624 != 0) {
625 if (verbose != 0) {
626 mbedtls_printf(" KW: setup failed ");
627 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300628
Yanray Wangd896fcb2023-05-11 17:24:41 +0800629 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100630 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300631
Yanray Wangd896fcb2023-05-11 17:24:41 +0800632 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
633 out, olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300634
Yanray Wangd896fcb2023-05-11 17:24:41 +0800635 if (ret != 0 || olen != kw_msg_len[i] ||
636 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
637 if (verbose != 0) {
638 mbedtls_printf("failed\n");
639 }
640
641 ret = 1;
642 goto end;
643 }
644
645 if (verbose != 0) {
646 mbedtls_printf(" passed\n");
647 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100648 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300649 }
650
Yanray Wangd896fcb2023-05-11 17:24:41 +0800651 /*
652 * KWP mode
653 */
654 {
655 static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300656
Yanray Wangd896fcb2023-05-11 17:24:41 +0800657 for (i = 0; i < num_tests; i++) {
658 olen = sizeof(out);
Gilles Peskine449bd832023-01-11 14:50:10 +0100659 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800660 mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100661 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300662
Yanray Wangd896fcb2023-05-11 17:24:41 +0800663 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
664 key_len[i] * 8, 1);
665 if (ret != 0) {
666 if (verbose != 0) {
667 mbedtls_printf(" KWP: setup failed ");
668 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300669
Yanray Wangd896fcb2023-05-11 17:24:41 +0800670 goto end;
671 }
672 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
673 kwp_msg_len[i], out, &olen, sizeof(out));
674
675 if (ret != 0 || kwp_out_len[i] != olen ||
676 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
677 if (verbose != 0) {
678 mbedtls_printf("failed. ");
679 }
680
681 ret = 1;
682 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100683 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300684
Yanray Wangd896fcb2023-05-11 17:24:41 +0800685 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
686 kwp_key[i], key_len[i] * 8, 0))
687 != 0) {
688 if (verbose != 0) {
689 mbedtls_printf(" KWP: setup failed ");
690 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300691
Yanray Wangd896fcb2023-05-11 17:24:41 +0800692 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100693 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300694
Yanray Wangd896fcb2023-05-11 17:24:41 +0800695 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
696 olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300697
Yanray Wangd896fcb2023-05-11 17:24:41 +0800698 if (ret != 0 || olen != kwp_msg_len[i] ||
699 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
700 if (verbose != 0) {
701 mbedtls_printf("failed. ");
702 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300703
Yanray Wangd896fcb2023-05-11 17:24:41 +0800704 ret = 1;
705 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100706 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300707
Yanray Wangd896fcb2023-05-11 17:24:41 +0800708 if (verbose != 0) {
709 mbedtls_printf(" passed\n");
710 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100711 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300712 }
713end:
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 mbedtls_nist_kw_free(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300715
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 if (verbose != 0) {
717 mbedtls_printf("\n");
718 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300719
Gilles Peskine449bd832023-01-11 14:50:10 +0100720 return ret;
Ron Eldor9ab746c2018-07-15 09:33:07 +0300721}
722
723#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
724
Ron Eldorcb349ac2018-07-15 09:29:47 +0300725#endif /* MBEDTLS_NIST_KW_C */