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 */
|
---|
61 | static 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. */
|
---|
81 | static 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. */
|
---|
83 | static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6};
|
---|
84 |
|
---|
85 | #ifndef GET_UINT32_BE
|
---|
86 | #define GET_UINT32_BE(n,b,i) \
|
---|
87 | do { \
|
---|
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) \
|
---|
97 | do { \
|
---|
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 | */
|
---|
108 | void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx )
|
---|
109 | {
|
---|
110 | memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) );
|
---|
111 | }
|
---|
112 |
|
---|
113 | int 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 | */
|
---|
162 | void 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 | */
|
---|
172 | static 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 | */
|
---|
185 | int 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 |
|
---|
306 | cleanup:
|
---|
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 | */
|
---|
326 | static 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 |
|
---|
374 | cleanup:
|
---|
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 | */
|
---|
387 | int 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 |
|
---|
521 | cleanup:
|
---|
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 | */
|
---|
545 | static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
|
---|
546 |
|
---|
547 | static 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 |
|
---|
559 | static 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 |
|
---|
572 | static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
|
---|
573 | static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
|
---|
574 | static 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 |
|
---|
590 | static 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 |
|
---|
602 | static 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 | };
|
---|
611 | static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
|
---|
612 |
|
---|
613 | static 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 | };
|
---|
625 | static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
|
---|
626 |
|
---|
627 | int 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 | }
|
---|
744 | end:
|
---|
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 */
|
---|