blob: d5b2e27fb049e5ea06561ed9bdf623e4a22567e4 [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;
Dave Rodgman7ad37e42023-09-21 21:53:31 +0100424 ret = -(int) mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7),
425 -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret);
Dave Rodgman51c15302023-09-19 17:09:13 +0100426 padlen &= 7;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300427
428 /* Check padding in "constant-time" */
Dave Rodgmand337bd92023-09-18 18:22:27 +0100429 const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
430 diff = mbedtls_ct_memcmp_partial(
431 &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
432 KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300433
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 if (diff != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300435 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
436 }
437
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 if (ret != 0) {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300439 goto cleanup;
440 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 memset(output + Plen, 0, padlen);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300442 *out_len = Plen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100443 } else {
Ron Eldorcb349ac2018-07-15 09:29:47 +0300444 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
445 goto cleanup;
446 }
447
448cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 if (ret != 0) {
450 memset(output, 0, *out_len);
Ron Eldorcb349ac2018-07-15 09:29:47 +0300451 *out_len = 0;
452 }
453
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 mbedtls_platform_zeroize(&diff, sizeof(diff));
455 mbedtls_platform_zeroize(A, sizeof(A));
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500456
Gilles Peskine449bd832023-01-11 14:50:10 +0100457 return ret;
Ron Eldorcb349ac2018-07-15 09:29:47 +0300458}
459
460#endif /* !MBEDTLS_NIST_KW_ALT */
461
Ron Eldor9ab746c2018-07-15 09:33:07 +0300462#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
463
Ron Eldor9ab746c2018-07-15 09:33:07 +0300464/*
465 * Test vectors taken from NIST
466 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
467 */
Yanray Wangd896fcb2023-05-11 17:24:41 +0800468static const unsigned int key_len[] = {
469 16,
470#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
471 24,
472 32
473#endif
474};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300475
Yanray Wangd896fcb2023-05-11 17:24:41 +0800476static const unsigned char kw_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300477 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
478 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800479#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300480 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
481 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
482 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
483 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
484 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
485 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
486 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800487#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300488};
489
Yanray Wangd896fcb2023-05-11 17:24:41 +0800490static const unsigned char kw_msg[][40] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300491 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
492 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800493#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300494 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
495 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
496 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
497 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
498 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
499 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
500 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
501 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800502#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300503};
504
Yanray Wangd896fcb2023-05-11 17:24:41 +0800505static const size_t kw_msg_len[] = {
506 16,
507#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
508 40,
509 24
510#endif
511};
512static const size_t kw_out_len[] = {
513 24,
514#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
515 48,
516 32
517#endif
518};
519static const unsigned char kw_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300520 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
521 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
522 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800523#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300524 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
525 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
526 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
527 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
528 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
529 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
530 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
531 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
532 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
533 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800534#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300535};
536
Yanray Wangd896fcb2023-05-11 17:24:41 +0800537static const unsigned char kwp_key[][32] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300538 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
539 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800540#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300541 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
542 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
543 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
544 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
545 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
546 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
547 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800548#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300549};
550
Yanray Wangd896fcb2023-05-11 17:24:41 +0800551static const unsigned char kwp_msg[][31] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300552 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
553 0x96 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800554#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300555 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
556 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
557 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
558 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
559 { 0xd1 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800560#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300561};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800562static const size_t kwp_msg_len[] = {
563 9,
564#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
565 31,
566 1
567#endif
568};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300569
Yanray Wangd896fcb2023-05-11 17:24:41 +0800570static const unsigned char kwp_res[][48] = {
Ron Eldor9ab746c2018-07-15 09:33:07 +0300571 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
572 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
573 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
Yanray Wangd896fcb2023-05-11 17:24:41 +0800574#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300575 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
576 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
577 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
578 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
579 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
580 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
581 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
Yanray Wangd896fcb2023-05-11 17:24:41 +0800582#endif
Ron Eldor9ab746c2018-07-15 09:33:07 +0300583};
Yanray Wangd896fcb2023-05-11 17:24:41 +0800584static const size_t kwp_out_len[] = {
585 24,
586#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
587 40,
588 16
589#endif
590};
Ron Eldor9ab746c2018-07-15 09:33:07 +0300591
Gilles Peskine449bd832023-01-11 14:50:10 +0100592int mbedtls_nist_kw_self_test(int verbose)
Ron Eldor9ab746c2018-07-15 09:33:07 +0300593{
594 mbedtls_nist_kw_context ctx;
595 unsigned char out[48];
596 size_t olen;
597 int i;
598 int ret = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100599 mbedtls_nist_kw_init(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300600
Yanray Wangd896fcb2023-05-11 17:24:41 +0800601 /*
602 * KW mode
603 */
604 {
605 static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300606
Yanray Wangd896fcb2023-05-11 17:24:41 +0800607 for (i = 0; i < num_tests; i++) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800609 mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100610 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300611
Yanray Wangd896fcb2023-05-11 17:24:41 +0800612 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
613 kw_key[i], key_len[i] * 8, 1);
614 if (ret != 0) {
615 if (verbose != 0) {
616 mbedtls_printf(" KW: setup failed ");
617 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300618
Yanray Wangd896fcb2023-05-11 17:24:41 +0800619 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100620 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300621
Yanray Wangd896fcb2023-05-11 17:24:41 +0800622 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
623 kw_msg_len[i], out, &olen, sizeof(out));
624 if (ret != 0 || kw_out_len[i] != olen ||
625 memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
626 if (verbose != 0) {
627 mbedtls_printf("failed. ");
628 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300629
Yanray Wangd896fcb2023-05-11 17:24:41 +0800630 ret = 1;
631 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100632 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300633
Yanray Wangd896fcb2023-05-11 17:24:41 +0800634 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
635 kw_key[i], key_len[i] * 8, 0))
636 != 0) {
637 if (verbose != 0) {
638 mbedtls_printf(" KW: setup failed ");
639 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300640
Yanray Wangd896fcb2023-05-11 17:24:41 +0800641 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100642 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300643
Yanray Wangd896fcb2023-05-11 17:24:41 +0800644 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
645 out, olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300646
Yanray Wangd896fcb2023-05-11 17:24:41 +0800647 if (ret != 0 || olen != kw_msg_len[i] ||
648 memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
649 if (verbose != 0) {
650 mbedtls_printf("failed\n");
651 }
652
653 ret = 1;
654 goto end;
655 }
656
657 if (verbose != 0) {
658 mbedtls_printf(" passed\n");
659 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100660 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300661 }
662
Yanray Wangd896fcb2023-05-11 17:24:41 +0800663 /*
664 * KWP mode
665 */
666 {
667 static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300668
Yanray Wangd896fcb2023-05-11 17:24:41 +0800669 for (i = 0; i < num_tests; i++) {
670 olen = sizeof(out);
Gilles Peskine449bd832023-01-11 14:50:10 +0100671 if (verbose != 0) {
Yanray Wangd896fcb2023-05-11 17:24:41 +0800672 mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8);
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300674
Yanray Wangd896fcb2023-05-11 17:24:41 +0800675 ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
676 key_len[i] * 8, 1);
677 if (ret != 0) {
678 if (verbose != 0) {
679 mbedtls_printf(" KWP: setup failed ");
680 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300681
Yanray Wangd896fcb2023-05-11 17:24:41 +0800682 goto end;
683 }
684 ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
685 kwp_msg_len[i], out, &olen, sizeof(out));
686
687 if (ret != 0 || kwp_out_len[i] != olen ||
688 memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
689 if (verbose != 0) {
690 mbedtls_printf("failed. ");
691 }
692
693 ret = 1;
694 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100695 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300696
Yanray Wangd896fcb2023-05-11 17:24:41 +0800697 if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
698 kwp_key[i], key_len[i] * 8, 0))
699 != 0) {
700 if (verbose != 0) {
701 mbedtls_printf(" KWP: setup failed ");
702 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300703
Yanray Wangd896fcb2023-05-11 17:24:41 +0800704 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100705 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300706
Yanray Wangd896fcb2023-05-11 17:24:41 +0800707 ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
708 olen, out, &olen, sizeof(out));
Ron Eldor9ab746c2018-07-15 09:33:07 +0300709
Yanray Wangd896fcb2023-05-11 17:24:41 +0800710 if (ret != 0 || olen != kwp_msg_len[i] ||
711 memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
712 if (verbose != 0) {
713 mbedtls_printf("failed. ");
714 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300715
Yanray Wangd896fcb2023-05-11 17:24:41 +0800716 ret = 1;
717 goto end;
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300719
Yanray Wangd896fcb2023-05-11 17:24:41 +0800720 if (verbose != 0) {
721 mbedtls_printf(" passed\n");
722 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100723 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300724 }
725end:
Gilles Peskine449bd832023-01-11 14:50:10 +0100726 mbedtls_nist_kw_free(&ctx);
Ron Eldor9ab746c2018-07-15 09:33:07 +0300727
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 if (verbose != 0) {
729 mbedtls_printf("\n");
730 }
Ron Eldor9ab746c2018-07-15 09:33:07 +0300731
Gilles Peskine449bd832023-01-11 14:50:10 +0100732 return ret;
Ron Eldor9ab746c2018-07-15 09:33:07 +0300733}
734
735#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
736
Ron Eldorcb349ac2018-07-15 09:29:47 +0300737#endif /* MBEDTLS_NIST_KW_C */