blob: 5b5aa1caf15ced466453712319ab9381a840e1d4 [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 Nowicki5d5841f2020-06-05 16:33:24 +0200225 if( 0 != mbedtls_platform_memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ) )
226 {
227 return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
228 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300229 }
230 else
231 {
232 if( in_len % 8 != 0 )
233 {
234 padlen = ( 8 - ( in_len % 8 ) );
235 }
236
237 if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen )
238 {
239 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
240 }
241
242 /*
243 * According to SP 800-38F Table 1, the plaintext length for KWP
244 * must be between 1 and 2^32-1 octets inclusive.
245 */
246 if( in_len < 1
247#if SIZE_MAX > 0xFFFFFFFF
248 || in_len > 0xFFFFFFFF
249#endif
250 )
251 {
252 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
253 }
254
Teppo Järvelin91d79382019-10-02 09:09:31 +0300255 mbedtls_platform_memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300256 PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
257 KW_SEMIBLOCK_LENGTH / 2 );
258
Teppo Järvelin91d79382019-10-02 09:09:31 +0300259 mbedtls_platform_memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200260 mbedtls_platform_memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300261 }
262 semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1;
263
264 s = 6 * ( semiblocks - 1 );
265
266 if( mode == MBEDTLS_KW_MODE_KWP
267 && in_len <= KW_SEMIBLOCK_LENGTH )
268 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300269 mbedtls_platform_memcpy( inbuff, output, 16 );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300270 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
271 inbuff, 16, output, &olen );
272 if( ret != 0 )
273 goto cleanup;
274 }
275 else
276 {
277 /*
278 * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
279 */
280 if( semiblocks < MIN_SEMIBLOCKS_COUNT )
281 {
282 ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
283 goto cleanup;
284 }
285
286 /* Calculate intermediate values */
287 for( t = 1; t <= s; t++ )
288 {
Teppo Järvelin91d79382019-10-02 09:09:31 +0300289 mbedtls_platform_memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
290 mbedtls_platform_memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300291
292 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
293 inbuff, 16, outbuff, &olen );
294 if( ret != 0 )
295 goto cleanup;
296
Teppo Järvelin91d79382019-10-02 09:09:31 +0300297 mbedtls_platform_memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300298 calc_a_xor_t( A, t );
299
Teppo Järvelin91d79382019-10-02 09:09:31 +0300300 mbedtls_platform_memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300301 R2 += KW_SEMIBLOCK_LENGTH;
302 if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) )
303 R2 = output + KW_SEMIBLOCK_LENGTH;
304 }
305 }
306
307 *out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
308
309cleanup:
310
311 if( ret != 0)
312 {
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200313 mbedtls_platform_memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300314 }
315 mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
316 mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
Manuel Pégourié-Gonnard01d4b762018-12-20 12:09:07 +0100317
Ron Eldorcb349ac2018-07-15 09:29:47 +0300318 return( ret );
319}
320
321/*
322 * W-1 function as defined in RFC 3394 section 2.2.2
323 * This function assumes the following:
324 * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
325 * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
326 * 3. Minimal number of semiblocks is 3.
327 * 4. A is a buffer to hold the first semiblock of the input buffer.
328 */
329static int unwrap( mbedtls_nist_kw_context *ctx,
330 const unsigned char *input, size_t semiblocks,
331 unsigned char A[KW_SEMIBLOCK_LENGTH],
332 unsigned char *output, size_t* out_len )
333{
334 int ret = 0;
335 const size_t s = 6 * ( semiblocks - 1 );
336 size_t olen;
337 uint64_t t = 0;
338 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
339 unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
340 unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
341 *out_len = 0;
342
343 if( semiblocks < MIN_SEMIBLOCKS_COUNT )
344 {
345 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
346 }
347
Teppo Järvelin91d79382019-10-02 09:09:31 +0300348 mbedtls_platform_memcpy( A, input, KW_SEMIBLOCK_LENGTH );
Piotr Nowicki5d5841f2020-06-05 16:33:24 +0200349 if( 0 != mbedtls_platform_memmove( output, input + KW_SEMIBLOCK_LENGTH,
350 ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ) )
351 {
352 return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
353 }
Ron Eldorcb349ac2018-07-15 09:29:47 +0300354
355 /* Calculate intermediate values */
356 for( t = s; t >= 1; t-- )
357 {
358 calc_a_xor_t( A, t );
359
Teppo Järvelin91d79382019-10-02 09:09:31 +0300360 mbedtls_platform_memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
361 mbedtls_platform_memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300362
363 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
364 inbuff, 16, outbuff, &olen );
365 if( ret != 0 )
366 goto cleanup;
367
Teppo Järvelin91d79382019-10-02 09:09:31 +0300368 mbedtls_platform_memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300369
370 /* Set R as LSB64 of outbuff */
Teppo Järvelin91d79382019-10-02 09:09:31 +0300371 mbedtls_platform_memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300372
373 if( R == output )
374 R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
375 else
376 R -= KW_SEMIBLOCK_LENGTH;
377 }
378
379 *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH;
380
381cleanup:
382 if( ret != 0)
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200383 mbedtls_platform_memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300384 mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) );
385 mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
386
387 return( ret );
388}
389
390/*
391 * KW-AD as defined in SP 800-38F section 6.2
392 * KWP-AD as defined in SP 800-38F section 6.3
393 */
394int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx,
395 mbedtls_nist_kw_mode_t mode,
396 const unsigned char *input, size_t in_len,
397 unsigned char *output, size_t *out_len, size_t out_size )
398{
399 int ret = 0;
400 size_t i, olen;
401 unsigned char A[KW_SEMIBLOCK_LENGTH];
402 unsigned char diff, bad_padding = 0;
403
404 *out_len = 0;
405 if( out_size < in_len - KW_SEMIBLOCK_LENGTH )
406 {
407 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
408 }
409
410 if( mode == MBEDTLS_KW_MODE_KW )
411 {
412 /*
413 * According to SP 800-38F Table 1, the ciphertext length for KW
414 * must be between 3 to 2^54 semiblocks inclusive.
415 */
416 if( in_len < 24 ||
417#if SIZE_MAX > 0x200000000000000
418 in_len > 0x200000000000000 ||
419#endif
420 in_len % KW_SEMIBLOCK_LENGTH != 0 )
421 {
422 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
423 }
424
425 ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
426 A, output, out_len );
427 if( ret != 0 )
428 goto cleanup;
429
430 /* Check ICV in "constant-time" */
431 diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
432
433 if( diff != 0 )
434 {
435 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
436 goto cleanup;
437 }
438
439 }
440 else if( mode == MBEDTLS_KW_MODE_KWP )
441 {
442 size_t padlen = 0;
443 uint32_t Plen;
444 /*
445 * According to SP 800-38F Table 1, the ciphertext length for KWP
446 * must be between 2 to 2^29 semiblocks inclusive.
447 */
448 if( in_len < KW_SEMIBLOCK_LENGTH * 2 ||
449#if SIZE_MAX > 0x100000000
450 in_len > 0x100000000 ||
451#endif
452 in_len % KW_SEMIBLOCK_LENGTH != 0 )
453 {
454 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
455 }
456
457 if( in_len == KW_SEMIBLOCK_LENGTH * 2 )
458 {
459 unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
460 ret = mbedtls_cipher_update( &ctx->cipher_ctx,
461 input, 16, outbuff, &olen );
462 if( ret != 0 )
463 goto cleanup;
464
Teppo Järvelin91d79382019-10-02 09:09:31 +0300465 mbedtls_platform_memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
466 mbedtls_platform_memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300467 mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
468 *out_len = KW_SEMIBLOCK_LENGTH;
469 }
470 else
471 {
472 /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
473 ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
474 A, output, out_len );
475 if( ret != 0 )
476 goto cleanup;
477 }
478
479 /* Check ICV in "constant-time" */
480 diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
481
482 if( diff != 0 )
483 {
484 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
485 }
486
487 GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 );
488
489 /*
490 * Plen is the length of the plaintext, when the input is valid.
491 * If Plen is larger than the plaintext and padding, padlen will be
492 * larger than 8, because of the type wrap around.
493 */
494 padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
495 if ( padlen > 7 )
496 {
497 padlen &= 7;
498 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
499 }
500
501 /* Check padding in "constant-time" */
502 for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ )
503 {
504 if( i >= KW_SEMIBLOCK_LENGTH - padlen )
505 diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
506 else
507 bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
508 }
509
510 if( diff != 0 )
511 {
512 ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
513 }
514
515 if( ret != 0 )
516 {
517 goto cleanup;
518 }
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200519 mbedtls_platform_memset( output + Plen, 0, padlen );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300520 *out_len = Plen;
521 }
522 else
523 {
524 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
525 goto cleanup;
526 }
527
528cleanup:
529 if( ret != 0 )
530 {
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200531 mbedtls_platform_memset( output, 0, *out_len );
Ron Eldorcb349ac2018-07-15 09:29:47 +0300532 *out_len = 0;
533 }
534
535 mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
536 mbedtls_platform_zeroize( &diff, sizeof( diff ) );
537 mbedtls_platform_zeroize( A, sizeof( A ) );
Manuel Pégourié-Gonnard01d4b762018-12-20 12:09:07 +0100538
Ron Eldorcb349ac2018-07-15 09:29:47 +0300539 return( ret );
540}
541
542#endif /* !MBEDTLS_NIST_KW_ALT */
543
Ron Eldor9ab746c2018-07-15 09:33:07 +0300544#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
545
546#define KW_TESTS 3
547
548/*
549 * Test vectors taken from NIST
550 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
551 */
552static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
553
554static const unsigned char kw_key[KW_TESTS][32] = {
555 { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
556 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
557 { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
558 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
559 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
560 { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
561 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
562 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
563 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
564};
565
566static const unsigned char kw_msg[KW_TESTS][40] = {
567 { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
568 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
569 { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
570 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
571 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
572 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
573 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
574 { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
575 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
576 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
577};
578
579static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
580static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
581static const unsigned char kw_res[KW_TESTS][48] = {
582 { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
583 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
584 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
585 { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
586 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
587 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
588 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
589 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
590 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
591 { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
592 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
593 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
594 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
595};
596
597static const unsigned char kwp_key[KW_TESTS][32] = {
598 { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
599 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
600 { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
601 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
602 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
603 { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
604 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
605 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
606 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
607};
608
609static const unsigned char kwp_msg[KW_TESTS][31] = {
610 { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
611 0x96 },
612 { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
613 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
614 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
615 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
616 { 0xd1 }
617};
618static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
619
620static const unsigned char kwp_res[KW_TESTS][48] = {
621 { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
622 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
623 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
624 { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
625 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
626 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
627 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
628 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
629 { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
630 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
631};
632static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
633
634int mbedtls_nist_kw_self_test( int verbose )
635{
636 mbedtls_nist_kw_context ctx;
637 unsigned char out[48];
638 size_t olen;
639 int i;
640 int ret = 0;
641 mbedtls_nist_kw_init( &ctx );
642
643 for( i = 0; i < KW_TESTS; i++ )
644 {
645 if( verbose != 0 )
646 mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 );
647
648 ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
649 kw_key[i], key_len[i] * 8, 1 );
650 if( ret != 0 )
651 {
652 if( verbose != 0 )
653 mbedtls_printf( " KW: setup failed " );
654
655 goto end;
656 }
657
658 ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
659 kw_msg_len[i], out, &olen, sizeof( out ) );
660 if( ret != 0 || kw_out_len[i] != olen ||
Teppo Järvelin61f412e2019-10-03 12:25:22 +0300661 memcmp( out, kw_res[i], kw_out_len[i] ) != 0 )
Ron Eldor9ab746c2018-07-15 09:33:07 +0300662 {
663 if( verbose != 0 )
664 mbedtls_printf( "failed. ");
665
666 ret = 1;
667 goto end;
668 }
669
670 if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
671 kw_key[i], key_len[i] * 8, 0 ) )
672 != 0 )
673 {
674 if( verbose != 0 )
675 mbedtls_printf( " KW: setup failed ");
676
677 goto end;
678 }
679
680 ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW,
681 out, olen, out, &olen, sizeof( out ) );
682
683 if( ret != 0 || olen != kw_msg_len[i] ||
Teppo Järvelin61f412e2019-10-03 12:25:22 +0300684 memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 )
Ron Eldor9ab746c2018-07-15 09:33:07 +0300685 {
686 if( verbose != 0 )
687 mbedtls_printf( "failed\n" );
688
689 ret = 1;
690 goto end;
691 }
692
693 if( verbose != 0 )
694 mbedtls_printf( " passed\n" );
695 }
696
697 for( i = 0; i < KW_TESTS; i++ )
698 {
699 olen = sizeof( out );
700 if( verbose != 0 )
701 mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 );
702
703 ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
704 key_len[i] * 8, 1 );
705 if( ret != 0 )
706 {
707 if( verbose != 0 )
708 mbedtls_printf( " KWP: setup failed " );
709
710 goto end;
711 }
712 ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
713 kwp_msg_len[i], out, &olen, sizeof( out ) );
714
715 if( ret != 0 || kwp_out_len[i] != olen ||
Teppo Järvelin61f412e2019-10-03 12:25:22 +0300716 memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 )
Ron Eldor9ab746c2018-07-15 09:33:07 +0300717 {
718 if( verbose != 0 )
719 mbedtls_printf( "failed. ");
720
721 ret = 1;
722 goto end;
723 }
724
725 if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
726 kwp_key[i], key_len[i] * 8, 0 ) )
727 != 0 )
728 {
729 if( verbose != 0 )
730 mbedtls_printf( " KWP: setup failed ");
731
732 goto end;
733 }
734
735 ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out,
736 olen, out, &olen, sizeof( out ) );
737
738 if( ret != 0 || olen != kwp_msg_len[i] ||
Teppo Järvelin61f412e2019-10-03 12:25:22 +0300739 memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 )
Ron Eldor9ab746c2018-07-15 09:33:07 +0300740 {
741 if( verbose != 0 )
742 mbedtls_printf( "failed. ");
743
744 ret = 1;
745 goto end;
746 }
747
748 if( verbose != 0 )
749 mbedtls_printf( " passed\n" );
750 }
751end:
752 mbedtls_nist_kw_free( &ctx );
753
754 if( verbose != 0 )
755 mbedtls_printf( "\n" );
756
757 return( ret );
758}
759
760#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
761
Ron Eldorcb349ac2018-07-15 09:29:47 +0300762#endif /* MBEDTLS_NIST_KW_C */