blob: 15b5bc0f9d6bbcd7da75ee1ba38fee93ff2b4d74 [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
Ron Eldorcb349ac2018-07-15 09:29:47 +03006 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
Ron Eldorcb349ac2018-07-15 09:29:47 +030019 */
20/*
21 * Definition of Key Wrapping:
22 * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
23 * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
24 * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
25 *
26 * Note: RFC 3394 defines different methodology for intermediate operations for
27 * the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
28 */
29
Gilles Peskinedb09ef62020-06-03 01:43:33 +020030#include "common.h"
Ron Eldorcb349ac2018-07-15 09:29:47 +030031
32#if defined(MBEDTLS_NIST_KW_C)
33
34#include "mbedtls/nist_kw.h"
35#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000036#include "mbedtls/error.h"
Gabor Mezei765862c2021-10-19 12:22:25 +020037#include "mbedtls/constant_time.h"
Dave Rodgmand337bd92023-09-18 18:22:27 +010038#include "constant_time_internal.h"
Ron Eldorcb349ac2018-07-15 09:29:47 +030039
40#include <stdint.h>
41#include <string.h>
42
Ron Eldorcb349ac2018-07-15 09:29:47 +030043#include "mbedtls/platform.h"
Ron Eldorcb349ac2018-07-15 09:29:47 +030044
45#if !defined(MBEDTLS_NIST_KW_ALT)
46
47#define KW_SEMIBLOCK_LENGTH 8
48#define MIN_SEMIBLOCKS_COUNT 3
49
Ron Eldorcb349ac2018-07-15 09:29:47 +030050/*! The 64-bit default integrity check value (ICV) for KW mode. */
Gilles Peskine449bd832023-01-11 14:50:10 +010051static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
Ron Eldorcb349ac2018-07-15 09:29:47 +030052/*! The 32-bit default integrity check value (ICV) for KWP mode. */
Gilles Peskine449bd832023-01-11 14:50:10 +010053static const unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
Ron Eldorcb349ac2018-07-15 09:29:47 +030054
Ron Eldorcb349ac2018-07-15 09:29:47 +030055/*
56 * Initialize context
57 */
Gilles Peskine449bd832023-01-11 14:50:10 +010058void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
Ron Eldorcb349ac2018-07-15 09:29:47 +030059{
Gilles Peskine449bd832023-01-11 14:50:10 +010060 memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
Ron Eldorcb349ac2018-07-15 09:29:47 +030061}
62
Gilles Peskine449bd832023-01-11 14:50:10 +010063int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
64 mbedtls_cipher_id_t cipher,
65 const unsigned char *key,
66 unsigned int keybits,
67 const int is_wrap)
Ron Eldorcb349ac2018-07-15 09:29:47 +030068{
Janos Follath24eed8d2019-11-22 13:21:35 +000069 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldorcb349ac2018-07-15 09:29:47 +030070 const mbedtls_cipher_info_t *cipher_info;
71
Gilles Peskine449bd832023-01-11 14:50:10 +010072 cipher_info = mbedtls_cipher_info_from_values(cipher,
73 keybits,
74 MBEDTLS_MODE_ECB);
75 if (cipher_info == NULL) {
76 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
77 }
Ron Eldorcb349ac2018-07-15 09:29:47 +030078
Dave Rodgman85a88132023-06-24 11:41:50 +010079 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +010080 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
81 }
Ron Eldorcb349ac2018-07-15 09:29:47 +030082
83 /*
84 * SP 800-38F currently defines AES cipher as the only block cipher allowed:
85 * "For KW and KWP, the underlying block cipher shall be approved, and the
86 * block size shall be 128 bits. Currently, the AES block cipher, with key
87 * lengths of 128, 192, or 256 bits, is the only block cipher that fits
88 * this profile."
89 * Currently we don't support other 128 bit block ciphers for key wrapping,
90 * such as Camellia and Aria.
91 */
Gilles Peskine449bd832023-01-11 14:50:10 +010092 if (cipher != MBEDTLS_CIPHER_ID_AES) {
93 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Ron Eldorcb349ac2018-07-15 09:29:47 +030094 }
95
Gilles Peskine449bd832023-01-11 14:50:10 +010096 mbedtls_cipher_free(&ctx->cipher_ctx);
97
98 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
99 return ret;
100 }
101
102 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
103 is_wrap ? MBEDTLS_ENCRYPT :
104 MBEDTLS_DECRYPT)
105 ) != 0) {
106 return ret;
107 }
108
109 return 0;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300110}
111
112/*
113 * Free context
114 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100115void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300116{
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 mbedtls_cipher_free(&ctx->cipher_ctx);
118 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300119}
120
121/*
122 * Helper function for Xoring the uint64_t "t" with the encrypted A.
123 * Defined in NIST SP 800-38F section 6.1
124 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100125static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300126{
127 size_t i = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100128 for (i = 0; i < sizeof(t); i++) {
129 A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300130 }
131}
132
133/*
134 * KW-AE as defined in SP 800-38F section 6.2
135 * KWP-AE as defined in SP 800-38F section 6.3
136 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100137int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
138 mbedtls_nist_kw_mode_t mode,
139 const unsigned char *input, size_t in_len,
140 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300141{
142 int ret = 0;
143 size_t semiblocks = 0;
144 size_t s;
145 size_t olen, padlen = 0;
146 uint64_t t = 0;
147 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
148 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Ron Eldorcb349ac2018-07-15 09:29:47 +0300149
150 *out_len = 0;
151 /*
152 * Generate the String to work on
153 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100154 if (mode == MBEDTLS_KW_MODE_KW) {
155 if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
156 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300157 }
158
159 /*
160 * According to SP 800-38F Table 1, the plaintext length for KW
161 * must be between 2 to 2^54-1 semiblocks inclusive.
162 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 if (in_len < 16 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300164#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
165 in_len > 0x1FFFFFFFFFFFFF8 ||
166#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100167 in_len % KW_SEMIBLOCK_LENGTH != 0) {
168 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300169 }
170
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
172 memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
173 } else {
174 if (in_len % 8 != 0) {
175 padlen = (8 - (in_len % 8));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300176 }
177
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
179 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300180 }
181
182 /*
183 * According to SP 800-38F Table 1, the plaintext length for KWP
184 * must be between 1 and 2^32-1 octets inclusive.
185 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 if (in_len < 1
Ron Eldorcb349ac2018-07-15 09:29:47 +0300187#if SIZE_MAX > 0xFFFFFFFF
188 || in_len > 0xFFFFFFFF
189#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 ) {
191 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300192 }
193
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
195 MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
196 KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300197
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
199 memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300200 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300202
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 if (mode == MBEDTLS_KW_MODE_KWP
206 && in_len <= KW_SEMIBLOCK_LENGTH) {
207 memcpy(inbuff, output, 16);
208 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
209 inbuff, 16, output, &olen);
210 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300211 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 }
213 } else {
Gilles Peskine89ee5992021-06-01 11:22:56 +0200214 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
215 unsigned char *A = output;
216
Ron Eldorcb349ac2018-07-15 09:29:47 +0300217 /*
218 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
219 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300221 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
222 goto cleanup;
223 }
224
225 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 for (t = 1; t <= s; t++) {
227 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
228 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300229
Gilles Peskine449bd832023-01-11 14:50:10 +0100230 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
231 inbuff, 16, outbuff, &olen);
232 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300233 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300235
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
237 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300238
Gilles Peskine449bd832023-01-11 14:50:10 +0100239 memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300240 R2 += KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300242 R2 = output + KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300244 }
245 }
246
247 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
248
249cleanup:
250
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 if (ret != 0) {
252 memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300253 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
255 mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300258}
259
260/*
261 * W-1 function as defined in RFC 3394 section 2.2.2
262 * This function assumes the following:
263 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
264 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
265 * 3. Minimal number of semiblocks is 3.
266 * 4. A is a buffer to hold the first semiblock of the input buffer.
267 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100268static int unwrap(mbedtls_nist_kw_context *ctx,
269 const unsigned char *input, size_t semiblocks,
270 unsigned char A[KW_SEMIBLOCK_LENGTH],
271 unsigned char *output, size_t *out_len)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300272{
273 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 const size_t s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300275 size_t olen;
276 uint64_t t = 0;
277 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
278 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine89ee5992021-06-01 11:22:56 +0200279 unsigned char *R = NULL;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300280 *out_len = 0;
281
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
283 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300284 }
285
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 memcpy(A, input, KW_SEMIBLOCK_LENGTH);
287 memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
288 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300289
290 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 for (t = s; t >= 1; t--) {
292 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300293
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
295 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300296
Gilles Peskine449bd832023-01-11 14:50:10 +0100297 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
298 inbuff, 16, outbuff, &olen);
299 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300300 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300302
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300304
305 /* Set R as LSB64 of outbuff */
Gilles Peskine449bd832023-01-11 14:50:10 +0100306 memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300307
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 if (R == output) {
309 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
310 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300311 R -= KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300313 }
314
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300316
317cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100318 if (ret != 0) {
319 memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
320 }
321 mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
322 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300323
Gilles Peskine449bd832023-01-11 14:50:10 +0100324 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300325}
326
327/*
328 * KW-AD as defined in SP 800-38F section 6.2
329 * KWP-AD as defined in SP 800-38F section 6.3
330 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100331int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
332 mbedtls_nist_kw_mode_t mode,
333 const unsigned char *input, size_t in_len,
334 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300335{
336 int ret = 0;
Dave Rodgmand337bd92023-09-18 18:22:27 +0100337 size_t olen;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300338 unsigned char A[KW_SEMIBLOCK_LENGTH];
Dave Rodgmand337bd92023-09-18 18:22:27 +0100339 int diff;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300340
341 *out_len = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
343 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300344 }
345
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 if (mode == MBEDTLS_KW_MODE_KW) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300347 /*
348 * According to SP 800-38F Table 1, the ciphertext length for KW
349 * must be between 3 to 2^54 semiblocks inclusive.
350 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 if (in_len < 24 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300352#if SIZE_MAX > 0x200000000000000
353 in_len > 0x200000000000000 ||
354#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 in_len % KW_SEMIBLOCK_LENGTH != 0) {
356 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300357 }
358
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
360 A, output, out_len);
361 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300362 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300364
365 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300367
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300369 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
370 goto cleanup;
371 }
372
Gilles Peskine449bd832023-01-11 14:50:10 +0100373 } else if (mode == MBEDTLS_KW_MODE_KWP) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300374 size_t padlen = 0;
375 uint32_t Plen;
376 /*
377 * According to SP 800-38F Table 1, the ciphertext length for KWP
378 * must be between 2 to 2^29 semiblocks inclusive.
379 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300381#if SIZE_MAX > 0x100000000
382 in_len > 0x100000000 ||
383#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 in_len % KW_SEMIBLOCK_LENGTH != 0) {
385 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300386 }
387
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300389 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
391 input, 16, outbuff, &olen);
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
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
397 memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
398 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300399 *out_len = KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300401 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
403 A, output, out_len);
404 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300405 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300407 }
408
409 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300411
Gilles Peskine449bd832023-01-11 14:50:10 +0100412 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300413 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
414 }
415
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300417
418 /*
419 * Plen is the length of the plaintext, when the input is valid.
420 * If Plen is larger than the plaintext and padding, padlen will be
421 * larger than 8, because of the type wrap around.
422 */
423 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 if (padlen > 7) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300425 padlen &= 7;
426 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
427 }
428
429 /* Check padding in "constant-time" */
Dave Rodgmand337bd92023-09-18 18:22:27 +0100430 const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
431 diff = mbedtls_ct_memcmp_partial(
432 &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
433 KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300434
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300436 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
437 }
438
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300440 goto cleanup;
441 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 memset(output + Plen, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300443 *out_len = Plen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300445 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
446 goto cleanup;
447 }
448
449cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 if (ret != 0) {
451 memset(output, 0, *out_len);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300452 *out_len = 0;
453 }
454
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 mbedtls_platform_zeroize(&diff, sizeof(diff));
456 mbedtls_platform_zeroize(A, sizeof(A));
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500457
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300459}
460
461#endif /* !MBEDTLS_NIST_KW_ALT */
462
Ron Eldor9ab746c2018-07-15 09:33:07 +0300463#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
464
Ron Eldor9ab746c2018-07-15 09:33:07 +0300465/*
466 * Test vectors taken from NIST
467 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
468 */
Yanray Wangd896fcb2023-05-11 17:24:41 +0800469static const unsigned int key_len[] = {
470 16,
471#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
472 24,
473 32
474#endif
475};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300476
Yanray Wangd896fcb2023-05-11 17:24:41 +0800477static const unsigned char kw_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300478 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
479 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800480#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300481 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
482 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
483 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
484 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
485 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
486 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
487 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800488#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300489};
490
Yanray Wangd896fcb2023-05-11 17:24:41 +0800491static const unsigned char kw_msg[][40] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300492 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
493 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800494#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300495 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
496 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
497 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
498 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
499 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
500 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
501 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
502 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800503#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300504};
505
Yanray Wangd896fcb2023-05-11 17:24:41 +0800506static const size_t kw_msg_len[] = {
507 16,
508#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
509 40,
510 24
511#endif
512};
513static const size_t kw_out_len[] = {
514 24,
515#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
516 48,
517 32
518#endif
519};
520static const unsigned char kw_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300521 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
522 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
523 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800524#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300525 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
526 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
527 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
528 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
529 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
530 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
531 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
532 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
533 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
534 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800535#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300536};
537
Yanray Wangd896fcb2023-05-11 17:24:41 +0800538static const unsigned char kwp_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300539 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
540 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800541#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300542 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
543 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
544 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
545 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
546 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
547 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
548 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800549#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300550};
551
Yanray Wangd896fcb2023-05-11 17:24:41 +0800552static const unsigned char kwp_msg[][31] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300553 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
554 0x96 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800555#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300556 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
557 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
558 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
559 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
560 { 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800561#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300562};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800563static const size_t kwp_msg_len[] = {
564 9,
565#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
566 31,
567 1
568#endif
569};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300570
Yanray Wangd896fcb2023-05-11 17:24:41 +0800571static const unsigned char kwp_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300572 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
573 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
574 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800575#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300576 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
577 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
578 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
579 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
580 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
581 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
582 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800583#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300584};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800585static const size_t kwp_out_len[] = {
586 24,
587#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
588 40,
589 16
590#endif
591};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300592
Gilles Peskine449bd832023-01-11 14:50:10 +0100593int mbedtls_nist_kw_self_test(int verbose)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300594{
595 mbedtls_nist_kw_context ctx;
596 unsigned char out[48];
597 size_t olen;
598 int i;
599 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100600 mbedtls_nist_kw_init(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300601
Yanray Wangd896fcb2023-05-11 17:24:41 +0800602 /*
603 * KW mode
604 */
605 {
606 static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300607
Yanray Wangd896fcb2023-05-11 17:24:41 +0800608 for (i = 0; i < num_tests; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100609 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800610 mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100611 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300612
Yanray Wangd896fcb2023-05-11 17:24:41 +0800613 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
614 kw_key[i], key_len[i] * 8, 1);
615 if (ret != 0) {
616 if (verbose != 0) {
617 mbedtls_printf(" KW: setup failed ");
618 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300619
Yanray Wangd896fcb2023-05-11 17:24:41 +0800620 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100621 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300622
Yanray Wangd896fcb2023-05-11 17:24:41 +0800623 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
624 kw_msg_len[i], out, &olen, sizeof(out));
625 if (ret != 0 || kw_out_len[i] != olen ||
626 memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
627 if (verbose != 0) {
628 mbedtls_printf("failed. ");
629 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300630
Yanray Wangd896fcb2023-05-11 17:24:41 +0800631 ret = 1;
632 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300634
Yanray Wangd896fcb2023-05-11 17:24:41 +0800635 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
636 kw_key[i], key_len[i] * 8, 0))
637 != 0) {
638 if (verbose != 0) {
639 mbedtls_printf(" KW: setup failed ");
640 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300641
Yanray Wangd896fcb2023-05-11 17:24:41 +0800642 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300644
Yanray Wangd896fcb2023-05-11 17:24:41 +0800645 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
646 out, olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300647
Yanray Wangd896fcb2023-05-11 17:24:41 +0800648 if (ret != 0 || olen != kw_msg_len[i] ||
649 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
650 if (verbose != 0) {
651 mbedtls_printf("failed\n");
652 }
653
654 ret = 1;
655 goto end;
656 }
657
658 if (verbose != 0) {
659 mbedtls_printf(" passed\n");
660 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100661 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300662 }
663
Yanray Wangd896fcb2023-05-11 17:24:41 +0800664 /*
665 * KWP mode
666 */
667 {
668 static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300669
Yanray Wangd896fcb2023-05-11 17:24:41 +0800670 for (i = 0; i < num_tests; i++) {
671 olen = sizeof(out);
Gilles Peskine449bd832023-01-11 14:50:10 +0100672 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800673 mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100674 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300675
Yanray Wangd896fcb2023-05-11 17:24:41 +0800676 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
677 key_len[i] * 8, 1);
678 if (ret != 0) {
679 if (verbose != 0) {
680 mbedtls_printf(" KWP: setup failed ");
681 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300682
Yanray Wangd896fcb2023-05-11 17:24:41 +0800683 goto end;
684 }
685 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
686 kwp_msg_len[i], out, &olen, sizeof(out));
687
688 if (ret != 0 || kwp_out_len[i] != olen ||
689 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
690 if (verbose != 0) {
691 mbedtls_printf("failed. ");
692 }
693
694 ret = 1;
695 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100696 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300697
Yanray Wangd896fcb2023-05-11 17:24:41 +0800698 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
699 kwp_key[i], key_len[i] * 8, 0))
700 != 0) {
701 if (verbose != 0) {
702 mbedtls_printf(" KWP: setup failed ");
703 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300704
Yanray Wangd896fcb2023-05-11 17:24:41 +0800705 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 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
709 olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300710
Yanray Wangd896fcb2023-05-11 17:24:41 +0800711 if (ret != 0 || olen != kwp_msg_len[i] ||
712 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
713 if (verbose != 0) {
714 mbedtls_printf("failed. ");
715 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300716
Yanray Wangd896fcb2023-05-11 17:24:41 +0800717 ret = 1;
718 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100719 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300720
Yanray Wangd896fcb2023-05-11 17:24:41 +0800721 if (verbose != 0) {
722 mbedtls_printf(" passed\n");
723 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100724 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300725 }
726end:
Gilles Peskine449bd832023-01-11 14:50:10 +0100727 mbedtls_nist_kw_free(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300728
Gilles Peskine449bd832023-01-11 14:50:10 +0100729 if (verbose != 0) {
730 mbedtls_printf("\n");
731 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300732
Gilles Peskine449bd832023-01-11 14:50:10 +0100733 return ret;
Ron Eldor9ab746c2018-07-15 09:33:07 +0300734}
735
736#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
737
Ron Eldorcb349ac2018-07-15 09:29:47 +0300738#endif /* MBEDTLS_NIST_KW_C */