/src/mbedtls/library/nist_kw.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes |
3 | | * only |
4 | | * |
5 | | * Copyright The Mbed TLS Contributors |
6 | | * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later |
7 | | */ |
8 | | /* |
9 | | * Definition of Key Wrapping: |
10 | | * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf |
11 | | * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" |
12 | | * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" |
13 | | * |
14 | | * Note: RFC 3394 defines different methodology for intermediate operations for |
15 | | * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. |
16 | | */ |
17 | | |
18 | | #include "common.h" |
19 | | |
20 | | #if defined(MBEDTLS_NIST_KW_C) |
21 | | |
22 | | #include "mbedtls/nist_kw.h" |
23 | | #include "mbedtls/platform_util.h" |
24 | | #include "mbedtls/error.h" |
25 | | #include "mbedtls/constant_time.h" |
26 | | #include "constant_time_internal.h" |
27 | | |
28 | | #include <stdint.h> |
29 | | #include <string.h> |
30 | | |
31 | | #include "mbedtls/platform.h" |
32 | | |
33 | | #if !defined(MBEDTLS_NIST_KW_ALT) |
34 | | |
35 | 0 | #define KW_SEMIBLOCK_LENGTH 8 |
36 | 0 | #define MIN_SEMIBLOCKS_COUNT 3 |
37 | | |
38 | | /*! The 64-bit default integrity check value (ICV) for KW mode. */ |
39 | | static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; |
40 | | /*! The 32-bit default integrity check value (ICV) for KWP mode. */ |
41 | | static const unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 }; |
42 | | |
43 | | /* |
44 | | * Initialize context |
45 | | */ |
46 | | void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx) |
47 | 20 | { |
48 | 20 | memset(ctx, 0, sizeof(mbedtls_nist_kw_context)); |
49 | 20 | } |
50 | | |
51 | | int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx, |
52 | | mbedtls_cipher_id_t cipher, |
53 | | const unsigned char *key, |
54 | | unsigned int keybits, |
55 | | const int is_wrap) |
56 | 13 | { |
57 | 13 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
58 | 13 | const mbedtls_cipher_info_t *cipher_info; |
59 | | |
60 | 13 | cipher_info = mbedtls_cipher_info_from_values(cipher, |
61 | 13 | keybits, |
62 | 13 | MBEDTLS_MODE_ECB); |
63 | 13 | if (cipher_info == NULL) { |
64 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
65 | 0 | } |
66 | | |
67 | 13 | if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { |
68 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
69 | 0 | } |
70 | | |
71 | | /* |
72 | | * SP 800-38F currently defines AES cipher as the only block cipher allowed: |
73 | | * "For KW and KWP, the underlying block cipher shall be approved, and the |
74 | | * block size shall be 128 bits. Currently, the AES block cipher, with key |
75 | | * lengths of 128, 192, or 256 bits, is the only block cipher that fits |
76 | | * this profile." |
77 | | * Currently we don't support other 128 bit block ciphers for key wrapping, |
78 | | * such as Camellia and Aria. |
79 | | */ |
80 | 13 | if (cipher != MBEDTLS_CIPHER_ID_AES) { |
81 | 0 | return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; |
82 | 0 | } |
83 | | |
84 | 13 | mbedtls_cipher_free(&ctx->cipher_ctx); |
85 | | |
86 | 13 | if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { |
87 | 0 | return ret; |
88 | 0 | } |
89 | | |
90 | 13 | if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, |
91 | 13 | is_wrap ? MBEDTLS_ENCRYPT : |
92 | 13 | MBEDTLS_DECRYPT) |
93 | 13 | ) != 0) { |
94 | 0 | return ret; |
95 | 0 | } |
96 | | |
97 | 13 | return 0; |
98 | 13 | } |
99 | | |
100 | | /* |
101 | | * Free context |
102 | | */ |
103 | | void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx) |
104 | 20 | { |
105 | 20 | if (ctx == NULL) { |
106 | 0 | return; |
107 | 0 | } |
108 | | |
109 | 20 | mbedtls_cipher_free(&ctx->cipher_ctx); |
110 | 20 | mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context)); |
111 | 20 | } |
112 | | |
113 | | /* |
114 | | * Helper function for Xoring the uint64_t "t" with the encrypted A. |
115 | | * Defined in NIST SP 800-38F section 6.1 |
116 | | */ |
117 | | static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t) |
118 | 0 | { |
119 | 0 | size_t i = 0; |
120 | 0 | for (i = 0; i < sizeof(t); i++) { |
121 | 0 | A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff; |
122 | 0 | } |
123 | 0 | } |
124 | | |
125 | | /* |
126 | | * KW-AE as defined in SP 800-38F section 6.2 |
127 | | * KWP-AE as defined in SP 800-38F section 6.3 |
128 | | */ |
129 | | int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx, |
130 | | mbedtls_nist_kw_mode_t mode, |
131 | | const unsigned char *input, size_t in_len, |
132 | | unsigned char *output, size_t *out_len, size_t out_size) |
133 | 0 | { |
134 | 0 | int ret = 0; |
135 | 0 | size_t semiblocks = 0; |
136 | 0 | size_t s; |
137 | 0 | size_t olen, padlen = 0; |
138 | 0 | uint64_t t = 0; |
139 | 0 | unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; |
140 | 0 | unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; |
141 | |
|
142 | 0 | *out_len = 0; |
143 | | /* |
144 | | * Generate the String to work on |
145 | | */ |
146 | 0 | if (mode == MBEDTLS_KW_MODE_KW) { |
147 | 0 | if (out_size < in_len + KW_SEMIBLOCK_LENGTH) { |
148 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
149 | 0 | } |
150 | | |
151 | | /* |
152 | | * According to SP 800-38F Table 1, the plaintext length for KW |
153 | | * must be between 2 to 2^54-1 semiblocks inclusive. |
154 | | */ |
155 | 0 | if (in_len < 16 || |
156 | 0 | #if SIZE_MAX > 0x1FFFFFFFFFFFFF8 |
157 | 0 | in_len > 0x1FFFFFFFFFFFFF8 || |
158 | 0 | #endif |
159 | 0 | in_len % KW_SEMIBLOCK_LENGTH != 0) { |
160 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
161 | 0 | } |
162 | | |
163 | 0 | memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH); |
164 | 0 | memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len); |
165 | 0 | } else { |
166 | 0 | if (in_len % 8 != 0) { |
167 | 0 | padlen = (8 - (in_len % 8)); |
168 | 0 | } |
169 | |
|
170 | 0 | if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) { |
171 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
172 | 0 | } |
173 | | |
174 | | /* |
175 | | * According to SP 800-38F Table 1, the plaintext length for KWP |
176 | | * must be between 1 and 2^32-1 octets inclusive. |
177 | | */ |
178 | 0 | if (in_len < 1 |
179 | 0 | #if SIZE_MAX > 0xFFFFFFFF |
180 | 0 | || in_len > 0xFFFFFFFF |
181 | 0 | #endif |
182 | 0 | ) { |
183 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
184 | 0 | } |
185 | | |
186 | 0 | memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2); |
187 | 0 | MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output, |
188 | 0 | KW_SEMIBLOCK_LENGTH / 2); |
189 | |
|
190 | 0 | memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len); |
191 | 0 | memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen); |
192 | 0 | } |
193 | 0 | semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1; |
194 | |
|
195 | 0 | s = 6 * (semiblocks - 1); |
196 | |
|
197 | 0 | if (mode == MBEDTLS_KW_MODE_KWP |
198 | 0 | && in_len <= KW_SEMIBLOCK_LENGTH) { |
199 | 0 | memcpy(inbuff, output, 16); |
200 | 0 | ret = mbedtls_cipher_update(&ctx->cipher_ctx, |
201 | 0 | inbuff, 16, output, &olen); |
202 | 0 | if (ret != 0) { |
203 | 0 | goto cleanup; |
204 | 0 | } |
205 | 0 | } else { |
206 | 0 | unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; |
207 | 0 | unsigned char *A = output; |
208 | | |
209 | | /* |
210 | | * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 |
211 | | */ |
212 | 0 | if (semiblocks < MIN_SEMIBLOCKS_COUNT) { |
213 | 0 | ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
214 | 0 | goto cleanup; |
215 | 0 | } |
216 | | |
217 | | /* Calculate intermediate values */ |
218 | 0 | for (t = 1; t <= s; t++) { |
219 | 0 | memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH); |
220 | 0 | memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH); |
221 | |
|
222 | 0 | ret = mbedtls_cipher_update(&ctx->cipher_ctx, |
223 | 0 | inbuff, 16, outbuff, &olen); |
224 | 0 | if (ret != 0) { |
225 | 0 | goto cleanup; |
226 | 0 | } |
227 | | |
228 | 0 | memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); |
229 | 0 | calc_a_xor_t(A, t); |
230 | |
|
231 | 0 | memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); |
232 | 0 | R2 += KW_SEMIBLOCK_LENGTH; |
233 | 0 | if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) { |
234 | 0 | R2 = output + KW_SEMIBLOCK_LENGTH; |
235 | 0 | } |
236 | 0 | } |
237 | 0 | } |
238 | | |
239 | 0 | *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; |
240 | |
|
241 | 0 | cleanup: |
242 | |
|
243 | 0 | if (ret != 0) { |
244 | 0 | memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH); |
245 | 0 | } |
246 | 0 | mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2); |
247 | 0 | mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2); |
248 | |
|
249 | 0 | return ret; |
250 | 0 | } |
251 | | |
252 | | /* |
253 | | * W-1 function as defined in RFC 3394 section 2.2.2 |
254 | | * This function assumes the following: |
255 | | * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. |
256 | | * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. |
257 | | * 3. Minimal number of semiblocks is 3. |
258 | | * 4. A is a buffer to hold the first semiblock of the input buffer. |
259 | | */ |
260 | | static int unwrap(mbedtls_nist_kw_context *ctx, |
261 | | const unsigned char *input, size_t semiblocks, |
262 | | unsigned char A[KW_SEMIBLOCK_LENGTH], |
263 | | unsigned char *output, size_t *out_len) |
264 | 0 | { |
265 | 0 | int ret = 0; |
266 | 0 | const size_t s = 6 * (semiblocks - 1); |
267 | 0 | size_t olen; |
268 | 0 | uint64_t t = 0; |
269 | 0 | unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; |
270 | 0 | unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; |
271 | 0 | unsigned char *R = NULL; |
272 | 0 | *out_len = 0; |
273 | |
|
274 | 0 | if (semiblocks < MIN_SEMIBLOCKS_COUNT) { |
275 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
276 | 0 | } |
277 | | |
278 | 0 | memcpy(A, input, KW_SEMIBLOCK_LENGTH); |
279 | 0 | memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH); |
280 | 0 | R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH; |
281 | | |
282 | | /* Calculate intermediate values */ |
283 | 0 | for (t = s; t >= 1; t--) { |
284 | 0 | calc_a_xor_t(A, t); |
285 | |
|
286 | 0 | memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH); |
287 | 0 | memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH); |
288 | |
|
289 | 0 | ret = mbedtls_cipher_update(&ctx->cipher_ctx, |
290 | 0 | inbuff, 16, outbuff, &olen); |
291 | 0 | if (ret != 0) { |
292 | 0 | goto cleanup; |
293 | 0 | } |
294 | | |
295 | 0 | memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); |
296 | | |
297 | | /* Set R as LSB64 of outbuff */ |
298 | 0 | memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); |
299 | |
|
300 | 0 | if (R == output) { |
301 | 0 | R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH; |
302 | 0 | } else { |
303 | 0 | R -= KW_SEMIBLOCK_LENGTH; |
304 | 0 | } |
305 | 0 | } |
306 | | |
307 | 0 | *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH; |
308 | |
|
309 | 0 | cleanup: |
310 | 0 | if (ret != 0) { |
311 | 0 | memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH); |
312 | 0 | } |
313 | 0 | mbedtls_platform_zeroize(inbuff, sizeof(inbuff)); |
314 | 0 | mbedtls_platform_zeroize(outbuff, sizeof(outbuff)); |
315 | |
|
316 | 0 | return ret; |
317 | 0 | } |
318 | | |
319 | | /* |
320 | | * KW-AD as defined in SP 800-38F section 6.2 |
321 | | * KWP-AD as defined in SP 800-38F section 6.3 |
322 | | */ |
323 | | int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, |
324 | | mbedtls_nist_kw_mode_t mode, |
325 | | const unsigned char *input, size_t in_len, |
326 | | unsigned char *output, size_t *out_len, size_t out_size) |
327 | 0 | { |
328 | 0 | int ret = 0; |
329 | 0 | size_t olen; |
330 | 0 | unsigned char A[KW_SEMIBLOCK_LENGTH]; |
331 | 0 | int diff; |
332 | |
|
333 | 0 | *out_len = 0; |
334 | 0 | if (out_size < in_len - KW_SEMIBLOCK_LENGTH) { |
335 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
336 | 0 | } |
337 | | |
338 | 0 | if (mode == MBEDTLS_KW_MODE_KW) { |
339 | | /* |
340 | | * According to SP 800-38F Table 1, the ciphertext length for KW |
341 | | * must be between 3 to 2^54 semiblocks inclusive. |
342 | | */ |
343 | 0 | if (in_len < 24 || |
344 | 0 | #if SIZE_MAX > 0x200000000000000 |
345 | 0 | in_len > 0x200000000000000 || |
346 | 0 | #endif |
347 | 0 | in_len % KW_SEMIBLOCK_LENGTH != 0) { |
348 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
349 | 0 | } |
350 | | |
351 | 0 | ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH, |
352 | 0 | A, output, out_len); |
353 | 0 | if (ret != 0) { |
354 | 0 | goto cleanup; |
355 | 0 | } |
356 | | |
357 | | /* Check ICV in "constant-time" */ |
358 | 0 | diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH); |
359 | |
|
360 | 0 | if (diff != 0) { |
361 | 0 | ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
362 | 0 | goto cleanup; |
363 | 0 | } |
364 | |
|
365 | 0 | } else if (mode == MBEDTLS_KW_MODE_KWP) { |
366 | 0 | size_t padlen = 0; |
367 | 0 | uint32_t Plen; |
368 | | /* |
369 | | * According to SP 800-38F Table 1, the ciphertext length for KWP |
370 | | * must be between 2 to 2^29 semiblocks inclusive. |
371 | | */ |
372 | 0 | if (in_len < KW_SEMIBLOCK_LENGTH * 2 || |
373 | 0 | #if SIZE_MAX > 0x100000000 |
374 | 0 | in_len > 0x100000000 || |
375 | 0 | #endif |
376 | 0 | in_len % KW_SEMIBLOCK_LENGTH != 0) { |
377 | 0 | return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; |
378 | 0 | } |
379 | | |
380 | 0 | if (in_len == KW_SEMIBLOCK_LENGTH * 2) { |
381 | 0 | unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; |
382 | 0 | ret = mbedtls_cipher_update(&ctx->cipher_ctx, |
383 | 0 | input, 16, outbuff, &olen); |
384 | 0 | if (ret != 0) { |
385 | 0 | goto cleanup; |
386 | 0 | } |
387 | | |
388 | 0 | memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); |
389 | 0 | memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); |
390 | 0 | mbedtls_platform_zeroize(outbuff, sizeof(outbuff)); |
391 | 0 | *out_len = KW_SEMIBLOCK_LENGTH; |
392 | 0 | } else { |
393 | | /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ |
394 | 0 | ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH, |
395 | 0 | A, output, out_len); |
396 | 0 | if (ret != 0) { |
397 | 0 | goto cleanup; |
398 | 0 | } |
399 | 0 | } |
400 | | |
401 | | /* Check ICV in "constant-time" */ |
402 | 0 | diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2); |
403 | |
|
404 | 0 | if (diff != 0) { |
405 | 0 | ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
406 | 0 | } |
407 | |
|
408 | 0 | Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2); |
409 | | |
410 | | /* |
411 | | * Plen is the length of the plaintext, when the input is valid. |
412 | | * If Plen is larger than the plaintext and padding, padlen will be |
413 | | * larger than 8, because of the type wrap around. |
414 | | */ |
415 | 0 | padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; |
416 | 0 | ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7), |
417 | 0 | MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); |
418 | 0 | padlen &= 7; |
419 | | |
420 | | /* Check padding in "constant-time" */ |
421 | 0 | const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 }; |
422 | 0 | diff = mbedtls_ct_memcmp_partial( |
423 | 0 | &output[*out_len - KW_SEMIBLOCK_LENGTH], zero, |
424 | 0 | KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0); |
425 | |
|
426 | 0 | if (diff != 0) { |
427 | 0 | ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; |
428 | 0 | } |
429 | |
|
430 | 0 | if (ret != 0) { |
431 | 0 | goto cleanup; |
432 | 0 | } |
433 | 0 | memset(output + Plen, 0, padlen); |
434 | 0 | *out_len = Plen; |
435 | 0 | } else { |
436 | 0 | ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; |
437 | 0 | goto cleanup; |
438 | 0 | } |
439 | | |
440 | 0 | cleanup: |
441 | 0 | if (ret != 0) { |
442 | 0 | memset(output, 0, *out_len); |
443 | 0 | *out_len = 0; |
444 | 0 | } |
445 | |
|
446 | 0 | mbedtls_platform_zeroize(&diff, sizeof(diff)); |
447 | 0 | mbedtls_platform_zeroize(A, sizeof(A)); |
448 | |
|
449 | 0 | return ret; |
450 | 0 | } |
451 | | |
452 | | #endif /* !MBEDTLS_NIST_KW_ALT */ |
453 | | |
454 | | #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) |
455 | | |
456 | | /* |
457 | | * Test vectors taken from NIST |
458 | | * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW |
459 | | */ |
460 | | static const unsigned int key_len[] = { |
461 | | 16, |
462 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
463 | | 24, |
464 | | 32 |
465 | | #endif |
466 | | }; |
467 | | |
468 | | static const unsigned char kw_key[][32] = { |
469 | | { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, |
470 | | 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, |
471 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
472 | | { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, |
473 | | 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, |
474 | | 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, |
475 | | { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, |
476 | | 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, |
477 | | 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, |
478 | | 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } |
479 | | #endif |
480 | | }; |
481 | | |
482 | | static const unsigned char kw_msg[][40] = { |
483 | | { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, |
484 | | 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, |
485 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
486 | | { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, |
487 | | 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, |
488 | | 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, |
489 | | 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, |
490 | | 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, |
491 | | { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, |
492 | | 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, |
493 | | 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } |
494 | | #endif |
495 | | }; |
496 | | |
497 | | static const size_t kw_msg_len[] = { |
498 | | 16, |
499 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
500 | | 40, |
501 | | 24 |
502 | | #endif |
503 | | }; |
504 | | static const size_t kw_out_len[] = { |
505 | | 24, |
506 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
507 | | 48, |
508 | | 32 |
509 | | #endif |
510 | | }; |
511 | | static const unsigned char kw_res[][48] = { |
512 | | { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, |
513 | | 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, |
514 | | 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, |
515 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
516 | | { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, |
517 | | 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, |
518 | | 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, |
519 | | 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, |
520 | | 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, |
521 | | 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, |
522 | | { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, |
523 | | 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, |
524 | | 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, |
525 | | 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } |
526 | | #endif |
527 | | }; |
528 | | |
529 | | static const unsigned char kwp_key[][32] = { |
530 | | { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, |
531 | | 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, |
532 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
533 | | { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, |
534 | | 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, |
535 | | 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, |
536 | | { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, |
537 | | 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, |
538 | | 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, |
539 | | 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } |
540 | | #endif |
541 | | }; |
542 | | |
543 | | static const unsigned char kwp_msg[][31] = { |
544 | | { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, |
545 | | 0x96 }, |
546 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
547 | | { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, |
548 | | 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, |
549 | | 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, |
550 | | 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, |
551 | | { 0xd1 } |
552 | | #endif |
553 | | }; |
554 | | static const size_t kwp_msg_len[] = { |
555 | | 9, |
556 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
557 | | 31, |
558 | | 1 |
559 | | #endif |
560 | | }; |
561 | | |
562 | | static const unsigned char kwp_res[][48] = { |
563 | | { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, |
564 | | 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, |
565 | | 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, |
566 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
567 | | { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, |
568 | | 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, |
569 | | 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, |
570 | | 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, |
571 | | 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, |
572 | | { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, |
573 | | 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } |
574 | | #endif |
575 | | }; |
576 | | static const size_t kwp_out_len[] = { |
577 | | 24, |
578 | | #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) |
579 | | 40, |
580 | | 16 |
581 | | #endif |
582 | | }; |
583 | | |
584 | | int mbedtls_nist_kw_self_test(int verbose) |
585 | 0 | { |
586 | 0 | mbedtls_nist_kw_context ctx; |
587 | 0 | unsigned char out[48]; |
588 | 0 | size_t olen; |
589 | 0 | int i; |
590 | 0 | int ret = 0; |
591 | 0 | mbedtls_nist_kw_init(&ctx); |
592 | | |
593 | | /* |
594 | | * KW mode |
595 | | */ |
596 | 0 | { |
597 | 0 | static const int num_tests = sizeof(kw_key) / sizeof(*kw_key); |
598 | |
|
599 | 0 | for (i = 0; i < num_tests; i++) { |
600 | 0 | if (verbose != 0) { |
601 | 0 | mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8); |
602 | 0 | } |
603 | |
|
604 | 0 | ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, |
605 | 0 | kw_key[i], key_len[i] * 8, 1); |
606 | 0 | if (ret != 0) { |
607 | 0 | if (verbose != 0) { |
608 | 0 | mbedtls_printf(" KW: setup failed "); |
609 | 0 | } |
610 | |
|
611 | 0 | goto end; |
612 | 0 | } |
613 | | |
614 | 0 | ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], |
615 | 0 | kw_msg_len[i], out, &olen, sizeof(out)); |
616 | 0 | if (ret != 0 || kw_out_len[i] != olen || |
617 | 0 | memcmp(out, kw_res[i], kw_out_len[i]) != 0) { |
618 | 0 | if (verbose != 0) { |
619 | 0 | mbedtls_printf("failed. "); |
620 | 0 | } |
621 | |
|
622 | 0 | ret = 1; |
623 | 0 | goto end; |
624 | 0 | } |
625 | | |
626 | 0 | if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, |
627 | 0 | kw_key[i], key_len[i] * 8, 0)) |
628 | 0 | != 0) { |
629 | 0 | if (verbose != 0) { |
630 | 0 | mbedtls_printf(" KW: setup failed "); |
631 | 0 | } |
632 | |
|
633 | 0 | goto end; |
634 | 0 | } |
635 | | |
636 | 0 | ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, |
637 | 0 | out, olen, out, &olen, sizeof(out)); |
638 | |
|
639 | 0 | if (ret != 0 || olen != kw_msg_len[i] || |
640 | 0 | memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) { |
641 | 0 | if (verbose != 0) { |
642 | 0 | mbedtls_printf("failed\n"); |
643 | 0 | } |
644 | |
|
645 | 0 | ret = 1; |
646 | 0 | goto end; |
647 | 0 | } |
648 | | |
649 | 0 | if (verbose != 0) { |
650 | 0 | mbedtls_printf(" passed\n"); |
651 | 0 | } |
652 | 0 | } |
653 | 0 | } |
654 | | |
655 | | /* |
656 | | * KWP mode |
657 | | */ |
658 | 0 | { |
659 | 0 | static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key); |
660 | |
|
661 | 0 | for (i = 0; i < num_tests; i++) { |
662 | 0 | olen = sizeof(out); |
663 | 0 | if (verbose != 0) { |
664 | 0 | mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8); |
665 | 0 | } |
666 | |
|
667 | 0 | ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], |
668 | 0 | key_len[i] * 8, 1); |
669 | 0 | if (ret != 0) { |
670 | 0 | if (verbose != 0) { |
671 | 0 | mbedtls_printf(" KWP: setup failed "); |
672 | 0 | } |
673 | |
|
674 | 0 | goto end; |
675 | 0 | } |
676 | 0 | ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], |
677 | 0 | kwp_msg_len[i], out, &olen, sizeof(out)); |
678 | |
|
679 | 0 | if (ret != 0 || kwp_out_len[i] != olen || |
680 | 0 | memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) { |
681 | 0 | if (verbose != 0) { |
682 | 0 | mbedtls_printf("failed. "); |
683 | 0 | } |
684 | |
|
685 | 0 | ret = 1; |
686 | 0 | goto end; |
687 | 0 | } |
688 | | |
689 | 0 | if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, |
690 | 0 | kwp_key[i], key_len[i] * 8, 0)) |
691 | 0 | != 0) { |
692 | 0 | if (verbose != 0) { |
693 | 0 | mbedtls_printf(" KWP: setup failed "); |
694 | 0 | } |
695 | |
|
696 | 0 | goto end; |
697 | 0 | } |
698 | | |
699 | 0 | ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out, |
700 | 0 | olen, out, &olen, sizeof(out)); |
701 | |
|
702 | 0 | if (ret != 0 || olen != kwp_msg_len[i] || |
703 | 0 | memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) { |
704 | 0 | if (verbose != 0) { |
705 | 0 | mbedtls_printf("failed. "); |
706 | 0 | } |
707 | |
|
708 | 0 | ret = 1; |
709 | 0 | goto end; |
710 | 0 | } |
711 | | |
712 | 0 | if (verbose != 0) { |
713 | 0 | mbedtls_printf(" passed\n"); |
714 | 0 | } |
715 | 0 | } |
716 | 0 | } |
717 | 0 | end: |
718 | 0 | mbedtls_nist_kw_free(&ctx); |
719 | |
|
720 | 0 | if (verbose != 0) { |
721 | 0 | mbedtls_printf("\n"); |
722 | 0 | } |
723 | |
|
724 | 0 | return ret; |
725 | 0 | } |
726 | | |
727 | | #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ |
728 | | |
729 | | #endif /* MBEDTLS_NIST_KW_C */ |