blob: a4b4be759da9de2cd8faf01f9ef032ab833ed9ab [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
Ron Eldorcb349ac2018-07-15 09:29:47 +030033#define KW_SEMIBLOCK_LENGTH 8
34#define MIN_SEMIBLOCKS_COUNT 3
35
Ron Eldorcb349ac2018-07-15 09:29:47 +030036/*! The 64-bit default integrity check value (ICV) for KW mode. */
Gilles Peskine449bd832023-01-11 14:50:10 +010037static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
Ron Eldorcb349ac2018-07-15 09:29:47 +030038/*! The 32-bit default integrity check value (ICV) for KWP mode. */
Gilles Peskine449bd832023-01-11 14:50:10 +010039static const unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
Ron Eldorcb349ac2018-07-15 09:29:47 +030040
Ron Eldorcb349ac2018-07-15 09:29:47 +030041/*
42 * Initialize context
43 */
Gilles Peskine449bd832023-01-11 14:50:10 +010044void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
Ron Eldorcb349ac2018-07-15 09:29:47 +030045{
Gilles Peskine449bd832023-01-11 14:50:10 +010046 memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
Ron Eldorcb349ac2018-07-15 09:29:47 +030047}
48
Gilles Peskine449bd832023-01-11 14:50:10 +010049int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
50 mbedtls_cipher_id_t cipher,
51 const unsigned char *key,
52 unsigned int keybits,
53 const int is_wrap)
Ron Eldorcb349ac2018-07-15 09:29:47 +030054{
Janos Follath24eed8d2019-11-22 13:21:35 +000055 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldorcb349ac2018-07-15 09:29:47 +030056 const mbedtls_cipher_info_t *cipher_info;
57
Gilles Peskine449bd832023-01-11 14:50:10 +010058 cipher_info = mbedtls_cipher_info_from_values(cipher,
59 keybits,
60 MBEDTLS_MODE_ECB);
61 if (cipher_info == NULL) {
62 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
63 }
Ron Eldorcb349ac2018-07-15 09:29:47 +030064
Dave Rodgman85a88132023-06-24 11:41:50 +010065 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +010066 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
67 }
Ron Eldorcb349ac2018-07-15 09:29:47 +030068
69 /*
70 * SP 800-38F currently defines AES cipher as the only block cipher allowed:
71 * "For KW and KWP, the underlying block cipher shall be approved, and the
72 * block size shall be 128 bits. Currently, the AES block cipher, with key
73 * lengths of 128, 192, or 256 bits, is the only block cipher that fits
74 * this profile."
75 * Currently we don't support other 128 bit block ciphers for key wrapping,
76 * such as Camellia and Aria.
77 */
Gilles Peskine449bd832023-01-11 14:50:10 +010078 if (cipher != MBEDTLS_CIPHER_ID_AES) {
79 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Ron Eldorcb349ac2018-07-15 09:29:47 +030080 }
81
Gilles Peskine449bd832023-01-11 14:50:10 +010082 mbedtls_cipher_free(&ctx->cipher_ctx);
83
84 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
85 return ret;
86 }
87
88 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
89 is_wrap ? MBEDTLS_ENCRYPT :
90 MBEDTLS_DECRYPT)
91 ) != 0) {
92 return ret;
93 }
94
95 return 0;
Ron Eldorcb349ac2018-07-15 09:29:47 +030096}
97
98/*
99 * Free context
100 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100101void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300102{
Troy-Butler9ac3e232024-03-22 14:46:04 -0400103 if (ctx == NULL) {
104 return;
105 }
106
Gilles Peskine449bd832023-01-11 14:50:10 +0100107 mbedtls_cipher_free(&ctx->cipher_ctx);
108 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300109}
110
111/*
112 * Helper function for Xoring the uint64_t "t" with the encrypted A.
113 * Defined in NIST SP 800-38F section 6.1
114 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100115static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300116{
117 size_t i = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 for (i = 0; i < sizeof(t); i++) {
119 A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300120 }
121}
122
123/*
124 * KW-AE as defined in SP 800-38F section 6.2
125 * KWP-AE as defined in SP 800-38F section 6.3
126 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100127int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
128 mbedtls_nist_kw_mode_t mode,
129 const unsigned char *input, size_t in_len,
130 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300131{
132 int ret = 0;
133 size_t semiblocks = 0;
134 size_t s;
135 size_t olen, padlen = 0;
136 uint64_t t = 0;
137 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
138 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Ron Eldorcb349ac2018-07-15 09:29:47 +0300139
140 *out_len = 0;
141 /*
142 * Generate the String to work on
143 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 if (mode == MBEDTLS_KW_MODE_KW) {
145 if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
146 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300147 }
148
149 /*
150 * According to SP 800-38F Table 1, the plaintext length for KW
151 * must be between 2 to 2^54-1 semiblocks inclusive.
152 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 if (in_len < 16 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300154#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
155 in_len > 0x1FFFFFFFFFFFFF8 ||
156#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 in_len % KW_SEMIBLOCK_LENGTH != 0) {
158 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300159 }
160
Gilles Peskine449bd832023-01-11 14:50:10 +0100161 memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
162 memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
163 } else {
164 if (in_len % 8 != 0) {
165 padlen = (8 - (in_len % 8));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300166 }
167
Gilles Peskine449bd832023-01-11 14:50:10 +0100168 if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
169 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300170 }
171
172 /*
173 * According to SP 800-38F Table 1, the plaintext length for KWP
174 * must be between 1 and 2^32-1 octets inclusive.
175 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 if (in_len < 1
Ron Eldorcb349ac2018-07-15 09:29:47 +0300177#if SIZE_MAX > 0xFFFFFFFF
178 || in_len > 0xFFFFFFFF
179#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 ) {
181 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300182 }
183
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
185 MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
186 KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300187
Gilles Peskine449bd832023-01-11 14:50:10 +0100188 memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
189 memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300190 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300192
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300194
Gilles Peskine449bd832023-01-11 14:50:10 +0100195 if (mode == MBEDTLS_KW_MODE_KWP
196 && in_len <= KW_SEMIBLOCK_LENGTH) {
197 memcpy(inbuff, output, 16);
198 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
199 inbuff, 16, output, &olen);
200 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300201 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 }
203 } else {
Gilles Peskine89ee5992021-06-01 11:22:56 +0200204 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
205 unsigned char *A = output;
206
Ron Eldorcb349ac2018-07-15 09:29:47 +0300207 /*
208 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
209 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300211 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
212 goto cleanup;
213 }
214
215 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 for (t = 1; t <= s; t++) {
217 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
218 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300219
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
221 inbuff, 16, outbuff, &olen);
222 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300223 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300225
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
227 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300228
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300230 R2 += KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300232 R2 = output + KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300234 }
235 }
236
237 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
238
239cleanup:
240
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 if (ret != 0) {
242 memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300243 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
245 mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500246
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300248}
249
250/*
251 * W-1 function as defined in RFC 3394 section 2.2.2
252 * This function assumes the following:
253 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
254 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
255 * 3. Minimal number of semiblocks is 3.
256 * 4. A is a buffer to hold the first semiblock of the input buffer.
257 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100258static int unwrap(mbedtls_nist_kw_context *ctx,
259 const unsigned char *input, size_t semiblocks,
260 unsigned char A[KW_SEMIBLOCK_LENGTH],
261 unsigned char *output, size_t *out_len)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300262{
263 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 const size_t s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300265 size_t olen;
266 uint64_t t = 0;
267 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
268 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine89ee5992021-06-01 11:22:56 +0200269 unsigned char *R = NULL;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300270 *out_len = 0;
271
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
273 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300274 }
275
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 memcpy(A, input, KW_SEMIBLOCK_LENGTH);
277 memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
278 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300279
280 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 for (t = s; t >= 1; t--) {
282 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
285 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300286
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
288 inbuff, 16, outbuff, &olen);
289 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300290 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300292
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300294
295 /* Set R as LSB64 of outbuff */
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300297
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 if (R == output) {
299 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
300 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300301 R -= KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300303 }
304
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300306
307cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 if (ret != 0) {
309 memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
310 }
311 mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
312 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300313
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300315}
316
317/*
318 * KW-AD as defined in SP 800-38F section 6.2
319 * KWP-AD as defined in SP 800-38F section 6.3
320 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100321int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
322 mbedtls_nist_kw_mode_t mode,
323 const unsigned char *input, size_t in_len,
324 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300325{
326 int ret = 0;
Dave Rodgmand337bd92023-09-18 18:22:27 +0100327 size_t olen;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300328 unsigned char A[KW_SEMIBLOCK_LENGTH];
Dave Rodgmand337bd92023-09-18 18:22:27 +0100329 int diff;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300330
331 *out_len = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
333 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300334 }
335
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 if (mode == MBEDTLS_KW_MODE_KW) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300337 /*
338 * According to SP 800-38F Table 1, the ciphertext length for KW
339 * must be between 3 to 2^54 semiblocks inclusive.
340 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 if (in_len < 24 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300342#if SIZE_MAX > 0x200000000000000
343 in_len > 0x200000000000000 ||
344#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 in_len % KW_SEMIBLOCK_LENGTH != 0) {
346 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300347 }
348
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
350 A, output, out_len);
351 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300352 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100353 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300354
355 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300357
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300359 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
360 goto cleanup;
361 }
362
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 } else if (mode == MBEDTLS_KW_MODE_KWP) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300364 size_t padlen = 0;
365 uint32_t Plen;
366 /*
367 * According to SP 800-38F Table 1, the ciphertext length for KWP
368 * must be between 2 to 2^29 semiblocks inclusive.
369 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300371#if SIZE_MAX > 0x100000000
372 in_len > 0x100000000 ||
373#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 in_len % KW_SEMIBLOCK_LENGTH != 0) {
375 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300376 }
377
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300379 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
381 input, 16, outbuff, &olen);
382 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300383 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300385
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
387 memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
388 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300389 *out_len = KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300391 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
393 A, output, out_len);
394 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300395 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300397 }
398
399 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300401
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300403 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
404 }
405
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300407
408 /*
409 * Plen is the length of the plaintext, when the input is valid.
410 * If Plen is larger than the plaintext and padding, padlen will be
411 * larger than 8, because of the type wrap around.
412 */
413 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
Dave Rodgmand03f4832023-09-22 09:52:15 +0100414 ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
415 MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
Dave Rodgman51c15302023-09-19 17:09:13 +0100416 padlen &= 7;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300417
418 /* Check padding in "constant-time" */
Dave Rodgmand337bd92023-09-18 18:22:27 +0100419 const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
420 diff = mbedtls_ct_memcmp_partial(
421 &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
422 KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300425 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
426 }
427
Gilles Peskine449bd832023-01-11 14:50:10 +0100428 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300429 goto cleanup;
430 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 memset(output + Plen, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300432 *out_len = Plen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300434 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
435 goto cleanup;
436 }
437
438cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 if (ret != 0) {
440 memset(output, 0, *out_len);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300441 *out_len = 0;
442 }
443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 mbedtls_platform_zeroize(&diff, sizeof(diff));
445 mbedtls_platform_zeroize(A, sizeof(A));
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500446
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300448}
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 */