blob: fbd7221a4636644c19f849abd08b829ccd90299e [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"
Ron Eldorcb349ac2018-07-15 09:29:47 +030038
39#include <stdint.h>
40#include <string.h>
41
Ron Eldorcb349ac2018-07-15 09:29:47 +030042#include "mbedtls/platform.h"
Ron Eldorcb349ac2018-07-15 09:29:47 +030043
44#if !defined(MBEDTLS_NIST_KW_ALT)
45
46#define KW_SEMIBLOCK_LENGTH 8
47#define MIN_SEMIBLOCKS_COUNT 3
48
Ron Eldorcb349ac2018-07-15 09:29:47 +030049/*! The 64-bit default integrity check value (ICV) for KW mode. */
Gilles Peskine449bd832023-01-11 14:50:10 +010050static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
Ron Eldorcb349ac2018-07-15 09:29:47 +030051/*! The 32-bit default integrity check value (ICV) for KWP mode. */
Gilles Peskine449bd832023-01-11 14:50:10 +010052static const unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
Ron Eldorcb349ac2018-07-15 09:29:47 +030053
Ron Eldorcb349ac2018-07-15 09:29:47 +030054/*
55 * Initialize context
56 */
Gilles Peskine449bd832023-01-11 14:50:10 +010057void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
Ron Eldorcb349ac2018-07-15 09:29:47 +030058{
Gilles Peskine449bd832023-01-11 14:50:10 +010059 memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
Ron Eldorcb349ac2018-07-15 09:29:47 +030060}
61
Gilles Peskine449bd832023-01-11 14:50:10 +010062int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
63 mbedtls_cipher_id_t cipher,
64 const unsigned char *key,
65 unsigned int keybits,
66 const int is_wrap)
Ron Eldorcb349ac2018-07-15 09:29:47 +030067{
Janos Follath24eed8d2019-11-22 13:21:35 +000068 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldorcb349ac2018-07-15 09:29:47 +030069 const mbedtls_cipher_info_t *cipher_info;
70
Gilles Peskine449bd832023-01-11 14:50:10 +010071 cipher_info = mbedtls_cipher_info_from_values(cipher,
72 keybits,
73 MBEDTLS_MODE_ECB);
74 if (cipher_info == NULL) {
75 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
76 }
Ron Eldorcb349ac2018-07-15 09:29:47 +030077
Dave Rodgman85a88132023-06-24 11:41:50 +010078 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
Gilles Peskine449bd832023-01-11 14:50:10 +010079 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
80 }
Ron Eldorcb349ac2018-07-15 09:29:47 +030081
82 /*
83 * SP 800-38F currently defines AES cipher as the only block cipher allowed:
84 * "For KW and KWP, the underlying block cipher shall be approved, and the
85 * block size shall be 128 bits. Currently, the AES block cipher, with key
86 * lengths of 128, 192, or 256 bits, is the only block cipher that fits
87 * this profile."
88 * Currently we don't support other 128 bit block ciphers for key wrapping,
89 * such as Camellia and Aria.
90 */
Gilles Peskine449bd832023-01-11 14:50:10 +010091 if (cipher != MBEDTLS_CIPHER_ID_AES) {
92 return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Ron Eldorcb349ac2018-07-15 09:29:47 +030093 }
94
Gilles Peskine449bd832023-01-11 14:50:10 +010095 mbedtls_cipher_free(&ctx->cipher_ctx);
96
97 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
98 return ret;
99 }
100
101 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
102 is_wrap ? MBEDTLS_ENCRYPT :
103 MBEDTLS_DECRYPT)
104 ) != 0) {
105 return ret;
106 }
107
108 return 0;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300109}
110
111/*
112 * Free context
113 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100114void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300115{
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 mbedtls_cipher_free(&ctx->cipher_ctx);
117 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300118}
119
120/*
121 * Helper function for Xoring the uint64_t "t" with the encrypted A.
122 * Defined in NIST SP 800-38F section 6.1
123 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100124static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300125{
126 size_t i = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 for (i = 0; i < sizeof(t); i++) {
128 A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300129 }
130}
131
132/*
133 * KW-AE as defined in SP 800-38F section 6.2
134 * KWP-AE as defined in SP 800-38F section 6.3
135 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100136int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
137 mbedtls_nist_kw_mode_t mode,
138 const unsigned char *input, size_t in_len,
139 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300140{
141 int ret = 0;
142 size_t semiblocks = 0;
143 size_t s;
144 size_t olen, padlen = 0;
145 uint64_t t = 0;
146 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
147 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Ron Eldorcb349ac2018-07-15 09:29:47 +0300148
149 *out_len = 0;
150 /*
151 * Generate the String to work on
152 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 if (mode == MBEDTLS_KW_MODE_KW) {
154 if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
155 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300156 }
157
158 /*
159 * According to SP 800-38F Table 1, the plaintext length for KW
160 * must be between 2 to 2^54-1 semiblocks inclusive.
161 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100162 if (in_len < 16 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300163#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
164 in_len > 0x1FFFFFFFFFFFFF8 ||
165#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 in_len % KW_SEMIBLOCK_LENGTH != 0) {
167 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300168 }
169
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
171 memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
172 } else {
173 if (in_len % 8 != 0) {
174 padlen = (8 - (in_len % 8));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300175 }
176
Gilles Peskine449bd832023-01-11 14:50:10 +0100177 if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
178 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300179 }
180
181 /*
182 * According to SP 800-38F Table 1, the plaintext length for KWP
183 * must be between 1 and 2^32-1 octets inclusive.
184 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 if (in_len < 1
Ron Eldorcb349ac2018-07-15 09:29:47 +0300186#if SIZE_MAX > 0xFFFFFFFF
187 || in_len > 0xFFFFFFFF
188#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 ) {
190 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300191 }
192
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
194 MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
195 KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300196
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
198 memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300199 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300201
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300203
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 if (mode == MBEDTLS_KW_MODE_KWP
205 && in_len <= KW_SEMIBLOCK_LENGTH) {
206 memcpy(inbuff, output, 16);
207 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
208 inbuff, 16, output, &olen);
209 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300210 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 }
212 } else {
Gilles Peskine89ee5992021-06-01 11:22:56 +0200213 unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
214 unsigned char *A = output;
215
Ron Eldorcb349ac2018-07-15 09:29:47 +0300216 /*
217 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
218 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300220 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
221 goto cleanup;
222 }
223
224 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100225 for (t = 1; t <= s; t++) {
226 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
227 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300228
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
230 inbuff, 16, outbuff, &olen);
231 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300232 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300234
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
236 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300237
Gilles Peskine449bd832023-01-11 14:50:10 +0100238 memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300239 R2 += KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300241 R2 = output + KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300243 }
244 }
245
246 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
247
248cleanup:
249
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 if (ret != 0) {
251 memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300252 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
254 mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500255
Gilles Peskine449bd832023-01-11 14:50:10 +0100256 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300257}
258
259/*
260 * W-1 function as defined in RFC 3394 section 2.2.2
261 * This function assumes the following:
262 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
263 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
264 * 3. Minimal number of semiblocks is 3.
265 * 4. A is a buffer to hold the first semiblock of the input buffer.
266 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100267static int unwrap(mbedtls_nist_kw_context *ctx,
268 const unsigned char *input, size_t semiblocks,
269 unsigned char A[KW_SEMIBLOCK_LENGTH],
270 unsigned char *output, size_t *out_len)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300271{
272 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 const size_t s = 6 * (semiblocks - 1);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300274 size_t olen;
275 uint64_t t = 0;
276 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
277 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine89ee5992021-06-01 11:22:56 +0200278 unsigned char *R = NULL;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300279 *out_len = 0;
280
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
282 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300283 }
284
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 memcpy(A, input, KW_SEMIBLOCK_LENGTH);
286 memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
287 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300288
289 /* Calculate intermediate values */
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 for (t = s; t >= 1; t--) {
291 calc_a_xor_t(A, t);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300292
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
294 memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
297 inbuff, 16, outbuff, &olen);
298 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300299 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300301
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300303
304 /* Set R as LSB64 of outbuff */
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300306
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 if (R == output) {
308 R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
309 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300310 R -= KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300312 }
313
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300315
316cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100317 if (ret != 0) {
318 memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
319 }
320 mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
321 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300322
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300324}
325
326/*
327 * KW-AD as defined in SP 800-38F section 6.2
328 * KWP-AD as defined in SP 800-38F section 6.3
329 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100330int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
331 mbedtls_nist_kw_mode_t mode,
332 const unsigned char *input, size_t in_len,
333 unsigned char *output, size_t *out_len, size_t out_size)
Ron Eldorcb349ac2018-07-15 09:29:47 +0300334{
335 int ret = 0;
336 size_t i, olen;
337 unsigned char A[KW_SEMIBLOCK_LENGTH];
338 unsigned char diff, bad_padding = 0;
339
340 *out_len = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
342 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300343 }
344
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 if (mode == MBEDTLS_KW_MODE_KW) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300346 /*
347 * According to SP 800-38F Table 1, the ciphertext length for KW
348 * must be between 3 to 2^54 semiblocks inclusive.
349 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 if (in_len < 24 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300351#if SIZE_MAX > 0x200000000000000
352 in_len > 0x200000000000000 ||
353#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 in_len % KW_SEMIBLOCK_LENGTH != 0) {
355 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300356 }
357
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
359 A, output, out_len);
360 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300361 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300363
364 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300366
Gilles Peskine449bd832023-01-11 14:50:10 +0100367 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300368 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
369 goto cleanup;
370 }
371
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 } else if (mode == MBEDTLS_KW_MODE_KWP) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300373 size_t padlen = 0;
374 uint32_t Plen;
375 /*
376 * According to SP 800-38F Table 1, the ciphertext length for KWP
377 * must be between 2 to 2^29 semiblocks inclusive.
378 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
Ron Eldorcb349ac2018-07-15 09:29:47 +0300380#if SIZE_MAX > 0x100000000
381 in_len > 0x100000000 ||
382#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 in_len % KW_SEMIBLOCK_LENGTH != 0) {
384 return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300385 }
386
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300388 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 ret = mbedtls_cipher_update(&ctx->cipher_ctx,
390 input, 16, outbuff, &olen);
391 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300392 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300394
Gilles Peskine449bd832023-01-11 14:50:10 +0100395 memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
396 memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
397 mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
Ron Eldorcb349ac2018-07-15 09:29:47 +0300398 *out_len = KW_SEMIBLOCK_LENGTH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300400 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
402 A, output, out_len);
403 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300404 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300406 }
407
408 /* Check ICV in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300412 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
413 }
414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300416
417 /*
418 * Plen is the length of the plaintext, when the input is valid.
419 * If Plen is larger than the plaintext and padding, padlen will be
420 * larger than 8, because of the type wrap around.
421 */
422 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 if (padlen > 7) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300424 padlen &= 7;
425 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
426 }
427
428 /* Check padding in "constant-time" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 for (diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++) {
430 if (i >= KW_SEMIBLOCK_LENGTH - padlen) {
431 diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
432 } else {
433 bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
434 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300435 }
436
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300438 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
439 }
440
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300442 goto cleanup;
443 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 memset(output + Plen, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300445 *out_len = Plen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300447 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
448 goto cleanup;
449 }
450
451cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 if (ret != 0) {
453 memset(output, 0, *out_len);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300454 *out_len = 0;
455 }
456
Gilles Peskine449bd832023-01-11 14:50:10 +0100457 mbedtls_platform_zeroize(&bad_padding, sizeof(bad_padding));
458 mbedtls_platform_zeroize(&diff, sizeof(diff));
459 mbedtls_platform_zeroize(A, sizeof(A));
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500460
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300462}
463
464#endif /* !MBEDTLS_NIST_KW_ALT */
465
Ron Eldor9ab746c2018-07-15 09:33:07 +0300466#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
467
Ron Eldor9ab746c2018-07-15 09:33:07 +0300468/*
469 * Test vectors taken from NIST
470 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
471 */
Yanray Wangd896fcb2023-05-11 17:24:41 +0800472static const unsigned int key_len[] = {
473 16,
474#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
475 24,
476 32
477#endif
478};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300479
Yanray Wangd896fcb2023-05-11 17:24:41 +0800480static const unsigned char kw_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300481 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
482 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800483#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300484 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
485 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
486 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
487 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
488 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
489 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
490 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800491#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300492};
493
Yanray Wangd896fcb2023-05-11 17:24:41 +0800494static const unsigned char kw_msg[][40] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300495 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
496 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800497#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300498 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
499 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
500 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
501 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
502 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
503 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
504 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
505 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800506#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300507};
508
Yanray Wangd896fcb2023-05-11 17:24:41 +0800509static const size_t kw_msg_len[] = {
510 16,
511#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
512 40,
513 24
514#endif
515};
516static const size_t kw_out_len[] = {
517 24,
518#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
519 48,
520 32
521#endif
522};
523static const unsigned char kw_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300524 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
525 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
526 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800527#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300528 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
529 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
530 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
531 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
532 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
533 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
534 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
535 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
536 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
537 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800538#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300539};
540
Yanray Wangd896fcb2023-05-11 17:24:41 +0800541static const unsigned char kwp_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300542 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
543 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800544#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300545 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
546 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
547 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
548 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
549 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
550 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
551 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800552#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300553};
554
Yanray Wangd896fcb2023-05-11 17:24:41 +0800555static const unsigned char kwp_msg[][31] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300556 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
557 0x96 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800558#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300559 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
560 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
561 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
562 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
563 { 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800564#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300565};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800566static const size_t kwp_msg_len[] = {
567 9,
568#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
569 31,
570 1
571#endif
572};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300573
Yanray Wangd896fcb2023-05-11 17:24:41 +0800574static const unsigned char kwp_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300575 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
576 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
577 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800578#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300579 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
580 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
581 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
582 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
583 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
584 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
585 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800586#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300587};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800588static const size_t kwp_out_len[] = {
589 24,
590#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
591 40,
592 16
593#endif
594};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300595
Gilles Peskine449bd832023-01-11 14:50:10 +0100596int mbedtls_nist_kw_self_test(int verbose)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300597{
598 mbedtls_nist_kw_context ctx;
599 unsigned char out[48];
600 size_t olen;
601 int i;
602 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100603 mbedtls_nist_kw_init(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300604
Yanray Wangd896fcb2023-05-11 17:24:41 +0800605 /*
606 * KW mode
607 */
608 {
609 static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300610
Yanray Wangd896fcb2023-05-11 17:24:41 +0800611 for (i = 0; i < num_tests; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800613 mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300615
Yanray Wangd896fcb2023-05-11 17:24:41 +0800616 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
617 kw_key[i], key_len[i] * 8, 1);
618 if (ret != 0) {
619 if (verbose != 0) {
620 mbedtls_printf(" KW: setup failed ");
621 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300622
Yanray Wangd896fcb2023-05-11 17:24:41 +0800623 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 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
627 kw_msg_len[i], out, &olen, sizeof(out));
628 if (ret != 0 || kw_out_len[i] != olen ||
629 memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
630 if (verbose != 0) {
631 mbedtls_printf("failed. ");
632 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300633
Yanray Wangd896fcb2023-05-11 17:24:41 +0800634 ret = 1;
635 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100636 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300637
Yanray Wangd896fcb2023-05-11 17:24:41 +0800638 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
639 kw_key[i], key_len[i] * 8, 0))
640 != 0) {
641 if (verbose != 0) {
642 mbedtls_printf(" KW: setup failed ");
643 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300644
Yanray Wangd896fcb2023-05-11 17:24:41 +0800645 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300647
Yanray Wangd896fcb2023-05-11 17:24:41 +0800648 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
649 out, olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300650
Yanray Wangd896fcb2023-05-11 17:24:41 +0800651 if (ret != 0 || olen != kw_msg_len[i] ||
652 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
653 if (verbose != 0) {
654 mbedtls_printf("failed\n");
655 }
656
657 ret = 1;
658 goto end;
659 }
660
661 if (verbose != 0) {
662 mbedtls_printf(" passed\n");
663 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100664 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300665 }
666
Yanray Wangd896fcb2023-05-11 17:24:41 +0800667 /*
668 * KWP mode
669 */
670 {
671 static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300672
Yanray Wangd896fcb2023-05-11 17:24:41 +0800673 for (i = 0; i < num_tests; i++) {
674 olen = sizeof(out);
Gilles Peskine449bd832023-01-11 14:50:10 +0100675 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800676 mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300678
Yanray Wangd896fcb2023-05-11 17:24:41 +0800679 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
680 key_len[i] * 8, 1);
681 if (ret != 0) {
682 if (verbose != 0) {
683 mbedtls_printf(" KWP: setup failed ");
684 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300685
Yanray Wangd896fcb2023-05-11 17:24:41 +0800686 goto end;
687 }
688 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
689 kwp_msg_len[i], out, &olen, sizeof(out));
690
691 if (ret != 0 || kwp_out_len[i] != olen ||
692 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
693 if (verbose != 0) {
694 mbedtls_printf("failed. ");
695 }
696
697 ret = 1;
698 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100699 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300700
Yanray Wangd896fcb2023-05-11 17:24:41 +0800701 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
702 kwp_key[i], key_len[i] * 8, 0))
703 != 0) {
704 if (verbose != 0) {
705 mbedtls_printf(" KWP: setup failed ");
706 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300707
Yanray Wangd896fcb2023-05-11 17:24:41 +0800708 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100709 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300710
Yanray Wangd896fcb2023-05-11 17:24:41 +0800711 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
712 olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300713
Yanray Wangd896fcb2023-05-11 17:24:41 +0800714 if (ret != 0 || olen != kwp_msg_len[i] ||
715 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
716 if (verbose != 0) {
717 mbedtls_printf("failed. ");
718 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300719
Yanray Wangd896fcb2023-05-11 17:24:41 +0800720 ret = 1;
721 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100722 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300723
Yanray Wangd896fcb2023-05-11 17:24:41 +0800724 if (verbose != 0) {
725 mbedtls_printf(" passed\n");
726 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100727 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300728 }
729end:
Gilles Peskine449bd832023-01-11 14:50:10 +0100730 mbedtls_nist_kw_free(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300731
Gilles Peskine449bd832023-01-11 14:50:10 +0100732 if (verbose != 0) {
733 mbedtls_printf("\n");
734 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300735
Gilles Peskine449bd832023-01-11 14:50:10 +0100736 return ret;
Ron Eldor9ab746c2018-07-15 09:33:07 +0300737}
738
739#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
740
Ron Eldorcb349ac2018-07-15 09:29:47 +0300741#endif /* MBEDTLS_NIST_KW_C */