Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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