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