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