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