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