source: azure_iot_hub_mbedtls/trunk/mbedtls-2.16.1/library/nist_kw.c@ 398

Last change on this file since 398 was 398, checked in by coas-nagasima, 5 years ago

mbedTLS版Azure IoT Hub接続サンプルのソースコードを追加

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