blob: 8faafe43f1a030184d21dc33197952b3956dc33f [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{
Troy-Butler9ac3e232024-03-22 14:46:04 -0400105 if (ctx == NULL) {
106 return;
107 }
108
Gilles Peskine449bd832023-01-11 14:50:10 +0100109 mbedtls_cipher_free(&ctx->cipher_ctx);
110 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300111}
112
113/*
114 * Helper function for Xoring the uint64_t "t" with the encrypted A.
115 * Defined in NIST SP 800-38F section 6.1
116 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100117static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300118{
119 size_t i = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 for (i = 0; i < sizeof(t); i++) {
121 A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300122 }
123}
124
125/*
126 * KW-AE as defined in SP 800-38F section 6.2
127 * KWP-AE as defined in SP 800-38F section 6.3
128 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100129int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
130 mbedtls_nist_kw_mode_t mode,
131 const unsigned char *input, size_t in_len,
132 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300133{
134 int ret = 0;
135 size_t semiblocks = 0;
136 size_t s;
137 size_t olen, padlen = 0;
138 uint64_t t = 0;
139 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
140 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Ron Eldorcb349ac2018-07-15 09:29:47 +0300141
142 *out_len = 0;
143 /*
144 * Generate the String to work on
145 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 if (mode == MBEDTLS_KW_MODE_KW) {
147 if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
148 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300149 }
150
151 /*
152 * According to SP 800-38F Table 1, the plaintext length for KW
153 * must be between 2 to 2^54-1 semiblocks inclusive.
154 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100155 if (in_len < 16 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300156#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
157 in_len > 0x1FFFFFFFFFFFFF8 ||
158#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 in_len % KW_SEMIBLOCK_LENGTH != 0) {
160 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300161 }
162
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
164 memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
165 } else {
166 if (in_len % 8 != 0) {
167 padlen = (8 - (in_len % 8));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300168 }
169
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
171 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300172 }
173
174 /*
175 * According to SP 800-38F Table 1, the plaintext length for KWP
176 * must be between 1 and 2^32-1 octets inclusive.
177 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 if (in_len < 1
Ron Eldorcb349ac2018-07-15 09:29:47 +0300179#if SIZE_MAX > 0xFFFFFFFF
180 || in_len > 0xFFFFFFFF
181#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 ) {
183 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300184 }
185
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
187 MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
188 KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300189
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
191 memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300192 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300194
Gilles Peskine449bd832023-01-11 14:50:10 +0100195 s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300196
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 if (mode == MBEDTLS_KW_MODE_KWP
198 && in_len <= KW_SEMIBLOCK_LENGTH) {
199 memcpy(inbuff, output, 16);
200 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
201 inbuff, 16, output, &olen);
202 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300203 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 }
205 } else {
Gilles Peskine89ee5992021-06-01 11:22:56 +0200206 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
207 unsigned char *A = output;
208
Ron Eldorcb349ac2018-07-15 09:29:47 +0300209 /*
210 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
211 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300213 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
214 goto cleanup;
215 }
216
217 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 for (t = 1; t <= s; t++) {
219 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
220 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
223 inbuff, 16, outbuff, &olen);
224 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300225 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300227
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
229 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300230
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300232 R2 += KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300234 R2 = output + KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300236 }
237 }
238
239 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
240
241cleanup:
242
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 if (ret != 0) {
244 memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300245 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
247 mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300250}
251
252/*
253 * W-1 function as defined in RFC 3394 section 2.2.2
254 * This function assumes the following:
255 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
256 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
257 * 3. Minimal number of semiblocks is 3.
258 * 4. A is a buffer to hold the first semiblock of the input buffer.
259 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100260static int unwrap(mbedtls_nist_kw_context *ctx,
261 const unsigned char *input, size_t semiblocks,
262 unsigned char A[KW_SEMIBLOCK_LENGTH],
263 unsigned char *output, size_t *out_len)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300264{
265 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 const size_t s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300267 size_t olen;
268 uint64_t t = 0;
269 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
270 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine89ee5992021-06-01 11:22:56 +0200271 unsigned char *R = NULL;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300272 *out_len = 0;
273
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
275 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300276 }
277
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 memcpy(A, input, KW_SEMIBLOCK_LENGTH);
279 memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
280 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300281
282 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 for (t = s; t >= 1; t--) {
284 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300285
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
287 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300288
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
290 inbuff, 16, outbuff, &olen);
291 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300292 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300296
297 /* Set R as LSB64 of outbuff */
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300299
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 if (R == output) {
301 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
302 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300303 R -= KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300305 }
306
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300308
309cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 if (ret != 0) {
311 memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
312 }
313 mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
314 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300315
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300317}
318
319/*
320 * KW-AD as defined in SP 800-38F section 6.2
321 * KWP-AD as defined in SP 800-38F section 6.3
322 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100323int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
324 mbedtls_nist_kw_mode_t mode,
325 const unsigned char *input, size_t in_len,
326 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300327{
328 int ret = 0;
Dave Rodgmand337bd92023-09-18 18:22:27 +0100329 size_t olen;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300330 unsigned char A[KW_SEMIBLOCK_LENGTH];
Dave Rodgmand337bd92023-09-18 18:22:27 +0100331 int diff;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300332
333 *out_len = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
335 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300336 }
337
Gilles Peskine449bd832023-01-11 14:50:10 +0100338 if (mode == MBEDTLS_KW_MODE_KW) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300339 /*
340 * According to SP 800-38F Table 1, the ciphertext length for KW
341 * must be between 3 to 2^54 semiblocks inclusive.
342 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 if (in_len < 24 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300344#if SIZE_MAX > 0x200000000000000
345 in_len > 0x200000000000000 ||
346#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 in_len % KW_SEMIBLOCK_LENGTH != 0) {
348 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300349 }
350
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
352 A, output, out_len);
353 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300354 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300356
357 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300359
Gilles Peskine449bd832023-01-11 14:50:10 +0100360 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300361 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
362 goto cleanup;
363 }
364
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 } else if (mode == MBEDTLS_KW_MODE_KWP) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300366 size_t padlen = 0;
367 uint32_t Plen;
368 /*
369 * According to SP 800-38F Table 1, the ciphertext length for KWP
370 * must be between 2 to 2^29 semiblocks inclusive.
371 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300373#if SIZE_MAX > 0x100000000
374 in_len > 0x100000000 ||
375#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 in_len % KW_SEMIBLOCK_LENGTH != 0) {
377 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300378 }
379
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300381 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
383 input, 16, outbuff, &olen);
384 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300385 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300387
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
389 memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
390 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300391 *out_len = KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300393 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
395 A, output, out_len);
396 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300397 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100398 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300399 }
400
401 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300403
Gilles Peskine449bd832023-01-11 14:50:10 +0100404 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300405 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
406 }
407
Gilles Peskine449bd832023-01-11 14:50:10 +0100408 Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300409
410 /*
411 * Plen is the length of the plaintext, when the input is valid.
412 * If Plen is larger than the plaintext and padding, padlen will be
413 * larger than 8, because of the type wrap around.
414 */
415 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
Dave Rodgmand03f4832023-09-22 09:52:15 +0100416 ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
417 MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
Dave Rodgman51c15302023-09-19 17:09:13 +0100418 padlen &= 7;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300419
420 /* Check padding in "constant-time" */
Dave Rodgmand337bd92023-09-18 18:22:27 +0100421 const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
422 diff = mbedtls_ct_memcmp_partial(
423 &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
424 KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300425
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300427 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
428 }
429
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300431 goto cleanup;
432 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 memset(output + Plen, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300434 *out_len = Plen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300436 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
437 goto cleanup;
438 }
439
440cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 if (ret != 0) {
442 memset(output, 0, *out_len);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300443 *out_len = 0;
444 }
445
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 mbedtls_platform_zeroize(&diff, sizeof(diff));
447 mbedtls_platform_zeroize(A, sizeof(A));
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500448
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300450}
451
452#endif /* !MBEDTLS_NIST_KW_ALT */
453
Ron Eldor9ab746c2018-07-15 09:33:07 +0300454#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
455
Ron Eldor9ab746c2018-07-15 09:33:07 +0300456/*
457 * Test vectors taken from NIST
458 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
459 */
Yanray Wangd896fcb2023-05-11 17:24:41 +0800460static const unsigned int key_len[] = {
461 16,
462#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
463 24,
464 32
465#endif
466};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300467
Yanray Wangd896fcb2023-05-11 17:24:41 +0800468static const unsigned char kw_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300469 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
470 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800471#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300472 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
473 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
474 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
475 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
476 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
477 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
478 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800479#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300480};
481
Yanray Wangd896fcb2023-05-11 17:24:41 +0800482static const unsigned char kw_msg[][40] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300483 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
484 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800485#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300486 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
487 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
488 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
489 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
490 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
491 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
492 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
493 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800494#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300495};
496
Yanray Wangd896fcb2023-05-11 17:24:41 +0800497static const size_t kw_msg_len[] = {
498 16,
499#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
500 40,
501 24
502#endif
503};
504static const size_t kw_out_len[] = {
505 24,
506#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
507 48,
508 32
509#endif
510};
511static const unsigned char kw_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300512 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
513 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
514 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800515#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300516 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
517 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
518 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
519 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
520 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
521 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
522 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
523 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
524 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
525 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800526#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300527};
528
Yanray Wangd896fcb2023-05-11 17:24:41 +0800529static const unsigned char kwp_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300530 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
531 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800532#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300533 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
534 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
535 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
536 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
537 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
538 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
539 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800540#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300541};
542
Yanray Wangd896fcb2023-05-11 17:24:41 +0800543static const unsigned char kwp_msg[][31] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300544 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
545 0x96 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800546#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300547 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
548 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
549 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
550 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
551 { 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800552#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300553};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800554static const size_t kwp_msg_len[] = {
555 9,
556#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
557 31,
558 1
559#endif
560};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300561
Yanray Wangd896fcb2023-05-11 17:24:41 +0800562static const unsigned char kwp_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300563 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
564 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
565 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800566#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300567 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
568 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
569 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
570 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
571 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
572 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
573 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800574#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300575};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800576static const size_t kwp_out_len[] = {
577 24,
578#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
579 40,
580 16
581#endif
582};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300583
Gilles Peskine449bd832023-01-11 14:50:10 +0100584int mbedtls_nist_kw_self_test(int verbose)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300585{
586 mbedtls_nist_kw_context ctx;
587 unsigned char out[48];
588 size_t olen;
589 int i;
590 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100591 mbedtls_nist_kw_init(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300592
Yanray Wangd896fcb2023-05-11 17:24:41 +0800593 /*
594 * KW mode
595 */
596 {
597 static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300598
Yanray Wangd896fcb2023-05-11 17:24:41 +0800599 for (i = 0; i < num_tests; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100600 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800601 mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300603
Yanray Wangd896fcb2023-05-11 17:24:41 +0800604 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
605 kw_key[i], key_len[i] * 8, 1);
606 if (ret != 0) {
607 if (verbose != 0) {
608 mbedtls_printf(" KW: setup failed ");
609 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300610
Yanray Wangd896fcb2023-05-11 17:24:41 +0800611 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300613
Yanray Wangd896fcb2023-05-11 17:24:41 +0800614 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
615 kw_msg_len[i], out, &olen, sizeof(out));
616 if (ret != 0 || kw_out_len[i] != olen ||
617 memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
618 if (verbose != 0) {
619 mbedtls_printf("failed. ");
620 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300621
Yanray Wangd896fcb2023-05-11 17:24:41 +0800622 ret = 1;
623 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100624 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300625
Yanray Wangd896fcb2023-05-11 17:24:41 +0800626 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
627 kw_key[i], key_len[i] * 8, 0))
628 != 0) {
629 if (verbose != 0) {
630 mbedtls_printf(" KW: setup failed ");
631 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300632
Yanray Wangd896fcb2023-05-11 17:24:41 +0800633 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100634 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300635
Yanray Wangd896fcb2023-05-11 17:24:41 +0800636 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
637 out, olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300638
Yanray Wangd896fcb2023-05-11 17:24:41 +0800639 if (ret != 0 || olen != kw_msg_len[i] ||
640 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
641 if (verbose != 0) {
642 mbedtls_printf("failed\n");
643 }
644
645 ret = 1;
646 goto end;
647 }
648
649 if (verbose != 0) {
650 mbedtls_printf(" passed\n");
651 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100652 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300653 }
654
Yanray Wangd896fcb2023-05-11 17:24:41 +0800655 /*
656 * KWP mode
657 */
658 {
659 static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300660
Yanray Wangd896fcb2023-05-11 17:24:41 +0800661 for (i = 0; i < num_tests; i++) {
662 olen = sizeof(out);
Gilles Peskine449bd832023-01-11 14:50:10 +0100663 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800664 mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100665 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300666
Yanray Wangd896fcb2023-05-11 17:24:41 +0800667 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
668 key_len[i] * 8, 1);
669 if (ret != 0) {
670 if (verbose != 0) {
671 mbedtls_printf(" KWP: setup failed ");
672 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300673
Yanray Wangd896fcb2023-05-11 17:24:41 +0800674 goto end;
675 }
676 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
677 kwp_msg_len[i], out, &olen, sizeof(out));
678
679 if (ret != 0 || kwp_out_len[i] != olen ||
680 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
681 if (verbose != 0) {
682 mbedtls_printf("failed. ");
683 }
684
685 ret = 1;
686 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100687 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300688
Yanray Wangd896fcb2023-05-11 17:24:41 +0800689 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
690 kwp_key[i], key_len[i] * 8, 0))
691 != 0) {
692 if (verbose != 0) {
693 mbedtls_printf(" KWP: setup failed ");
694 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300695
Yanray Wangd896fcb2023-05-11 17:24:41 +0800696 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300698
Yanray Wangd896fcb2023-05-11 17:24:41 +0800699 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
700 olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300701
Yanray Wangd896fcb2023-05-11 17:24:41 +0800702 if (ret != 0 || olen != kwp_msg_len[i] ||
703 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
704 if (verbose != 0) {
705 mbedtls_printf("failed. ");
706 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300707
Yanray Wangd896fcb2023-05-11 17:24:41 +0800708 ret = 1;
709 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100710 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300711
Yanray Wangd896fcb2023-05-11 17:24:41 +0800712 if (verbose != 0) {
713 mbedtls_printf(" passed\n");
714 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100715 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300716 }
717end:
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 mbedtls_nist_kw_free(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300719
Gilles Peskine449bd832023-01-11 14:50:10 +0100720 if (verbose != 0) {
721 mbedtls_printf("\n");
722 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300723
Gilles Peskine449bd832023-01-11 14:50:10 +0100724 return ret;
Ron Eldor9ab746c2018-07-15 09:33:07 +0300725}
726
727#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
728
Ron Eldorcb349ac2018-07-15 09:29:47 +0300729#endif /* MBEDTLS_NIST_KW_C */