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