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