Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8774 rgimad 1
/*
2
 *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
3
 *
4
 *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5
 *  SPDX-License-Identifier: GPL-2.0
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License along
18
 *  with this program; if not, write to the Free Software Foundation, Inc.,
19
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 *
21
 *  This file is part of mbed TLS (https://tls.mbed.org)
22
 */
23
/*
24
 *  The NIST SP 800-90 DRBGs are described in the following publication.
25
 *
26
 *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
27
 */
28
 
29
#if !defined(MBEDTLS_CONFIG_FILE)
30
#include "mbedtls/config.h"
31
#else
32
#include MBEDTLS_CONFIG_FILE
33
#endif
34
 
35
#if defined(MBEDTLS_CTR_DRBG_C)
36
 
37
#include "mbedtls/ctr_drbg.h"
38
#include "mbedtls/platform_util.h"
39
 
40
#include 
41
 
42
#if defined(MBEDTLS_FS_IO)
43
#include 
44
#endif
45
 
46
#if defined(MBEDTLS_SELF_TEST)
47
#if defined(MBEDTLS_PLATFORM_C)
48
#include "mbedtls/platform.h"
49
#else
50
#include 
51
#define mbedtls_printf printf
52
#endif /* MBEDTLS_PLATFORM_C */
53
#endif /* MBEDTLS_SELF_TEST */
54
 
55
/*
56
 * CTR_DRBG context initialization
57
 */
58
void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
59
{
60
    memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
61
 
62
#if defined(MBEDTLS_THREADING_C)
63
    mbedtls_mutex_init( &ctx->mutex );
64
#endif
65
}
66
 
67
void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
68
{
69
    if( ctx == NULL )
70
        return;
71
 
72
#if defined(MBEDTLS_THREADING_C)
73
    mbedtls_mutex_free( &ctx->mutex );
74
#endif
75
    mbedtls_aes_free( &ctx->aes_ctx );
76
    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
77
}
78
 
79
void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
80
{
81
    ctx->prediction_resistance = resistance;
82
}
83
 
84
void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
85
{
86
    ctx->entropy_len = len;
87
}
88
 
89
void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
90
{
91
    ctx->reseed_interval = interval;
92
}
93
 
94
static int block_cipher_df( unsigned char *output,
95
                            const unsigned char *data, size_t data_len )
96
{
97
    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
98
    unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
99
    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
100
    unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
101
    unsigned char *p, *iv;
102
    mbedtls_aes_context aes_ctx;
103
    int ret = 0;
104
 
105
    int i, j;
106
    size_t buf_len, use_len;
107
 
108
    if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
109
        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
110
 
111
    memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
112
    mbedtls_aes_init( &aes_ctx );
113
 
114
    /*
115
     * Construct IV (16 bytes) and S in buffer
116
     * IV = Counter (in 32-bits) padded to 16 with zeroes
117
     * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
118
     *     data || 0x80
119
     *     (Total is padded to a multiple of 16-bytes with zeroes)
120
     */
121
    p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
122
    *p++ = ( data_len >> 24 ) & 0xff;
123
    *p++ = ( data_len >> 16 ) & 0xff;
124
    *p++ = ( data_len >> 8  ) & 0xff;
125
    *p++ = ( data_len       ) & 0xff;
126
    p += 3;
127
    *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
128
    memcpy( p, data, data_len );
129
    p[data_len] = 0x80;
130
 
131
    buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
132
 
133
    for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
134
        key[i] = i;
135
 
136
    if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
137
    {
138
        goto exit;
139
    }
140
 
141
    /*
142
     * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
143
     */
144
    for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
145
    {
146
        p = buf;
147
        memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
148
        use_len = buf_len;
149
 
150
        while( use_len > 0 )
151
        {
152
            for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
153
                chain[i] ^= p[i];
154
            p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
155
            use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
156
                       MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
157
 
158
            if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
159
            {
160
                goto exit;
161
            }
162
        }
163
 
164
        memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
165
 
166
        /*
167
         * Update IV
168
         */
169
        buf[3]++;
170
    }
171
 
172
    /*
173
     * Do final encryption with reduced data
174
     */
175
    if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
176
    {
177
        goto exit;
178
    }
179
    iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
180
    p = output;
181
 
182
    for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
183
    {
184
        if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
185
        {
186
            goto exit;
187
        }
188
        memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
189
        p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
190
    }
191
exit:
192
    mbedtls_aes_free( &aes_ctx );
193
    /*
194
    * tidy up the stack
195
    */
196
    mbedtls_platform_zeroize( buf, sizeof( buf ) );
197
    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
198
    mbedtls_platform_zeroize( key, sizeof( key ) );
199
    mbedtls_platform_zeroize( chain, sizeof( chain ) );
200
    if( 0 != ret )
201
    {
202
        /*
203
        * wipe partial seed from memory
204
        */
205
        mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
206
    }
207
 
208
    return( ret );
209
}
210
 
211
/* CTR_DRBG_Update (SP 800-90A §10.2.1.2)
212
 * ctr_drbg_update_internal(ctx, provided_data)
213
 * implements
214
 * CTR_DRBG_Update(provided_data, Key, V)
215
 * with inputs and outputs
216
 *   ctx->aes_ctx = Key
217
 *   ctx->counter = V
218
 */
219
static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
220
                              const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
221
{
222
    unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
223
    unsigned char *p = tmp;
224
    int i, j;
225
    int ret = 0;
226
 
227
    memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
228
 
229
    for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
230
    {
231
        /*
232
         * Increase counter
233
         */
234
        for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
235
            if( ++ctx->counter[i - 1] != 0 )
236
                break;
237
 
238
        /*
239
         * Crypt counter block
240
         */
241
        if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
242
            goto exit;
243
 
244
        p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
245
    }
246
 
247
    for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
248
        tmp[i] ^= data[i];
249
 
250
    /*
251
     * Update key and counter
252
     */
253
    if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
254
        goto exit;
255
    memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
256
 
257
exit:
258
    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
259
    return( ret );
260
}
261
 
262
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
263
 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
264
 * implements
265
 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
266
 *                      security_strength) -> initial_working_state
267
 * with inputs
268
 *   ctx->counter = all-bits-0
269
 *   ctx->aes_ctx = context from all-bits-0 key
270
 *   additional[:add_len] = entropy_input || nonce || personalization_string
271
 * and with outputs
272
 *   ctx = initial_working_state
273
 */
274
int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
275
                                 const unsigned char *additional,
276
                                 size_t add_len )
277
{
278
    unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
279
    int ret;
280
 
281
    if( add_len == 0 )
282
        return( 0 );
283
 
284
    if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
285
        goto exit;
286
    if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
287
        goto exit;
288
 
289
exit:
290
    mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
291
    return( ret );
292
}
293
 
294
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
295
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
296
                              const unsigned char *additional,
297
                              size_t add_len )
298
{
299
    /* MAX_INPUT would be more logical here, but we have to match
300
     * block_cipher_df()'s limits since we can't propagate errors */
301
    if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
302
        add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
303
    (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
304
}
305
#endif /* MBEDTLS_DEPRECATED_REMOVED */
306
 
307
/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
308
 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
309
 * implements
310
 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
311
 *                -> new_working_state
312
 * with inputs
313
 *   ctx contains working_state
314
 *   additional[:len] = additional_input
315
 * and entropy_input comes from calling ctx->f_entropy
316
 * and with output
317
 *   ctx contains new_working_state
318
 */
319
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
320
                     const unsigned char *additional, size_t len )
321
{
322
    unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
323
    size_t seedlen = 0;
324
    int ret;
325
 
326
    if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
327
        len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
328
        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
329
 
330
    memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
331
 
332
    /*
333
     * Gather entropy_len bytes of entropy to seed state
334
     */
335
    if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
336
                             ctx->entropy_len ) )
337
    {
338
        return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
339
    }
340
 
341
    seedlen += ctx->entropy_len;
342
 
343
    /*
344
     * Add additional data
345
     */
346
    if( additional && len )
347
    {
348
        memcpy( seed + seedlen, additional, len );
349
        seedlen += len;
350
    }
351
 
352
    /*
353
     * Reduce to 384 bits
354
     */
355
    if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
356
        goto exit;
357
 
358
    /*
359
     * Update state
360
     */
361
    if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
362
        goto exit;
363
    ctx->reseed_counter = 1;
364
 
365
exit:
366
    mbedtls_platform_zeroize( seed, sizeof( seed ) );
367
    return( ret );
368
}
369
 
370
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
371
 * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
372
 * implements
373
 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
374
 *                      security_strength) -> initial_working_state
375
 * with inputs
376
 *   custom[:len] = nonce || personalization_string
377
 * where entropy_input comes from f_entropy for ctx->entropy_len bytes
378
 * and with outputs
379
 *   ctx = initial_working_state
380
 */
381
int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
382
                           int (*f_entropy)(void *, unsigned char *, size_t),
383
                           void *p_entropy,
384
                           const unsigned char *custom,
385
                           size_t len )
386
{
387
    int ret;
388
    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
389
 
390
    memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
391
 
392
    mbedtls_aes_init( &ctx->aes_ctx );
393
 
394
    ctx->f_entropy = f_entropy;
395
    ctx->p_entropy = p_entropy;
396
 
397
    if( ctx->entropy_len == 0 )
398
        ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
399
    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
400
 
401
    /*
402
     * Initialize with an empty key
403
     */
404
    if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
405
    {
406
        return( ret );
407
    }
408
 
409
    if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
410
    {
411
        return( ret );
412
    }
413
    return( 0 );
414
}
415
 
416
/* Backward compatibility wrapper */
417
int mbedtls_ctr_drbg_seed_entropy_len(
418
    mbedtls_ctr_drbg_context *ctx,
419
    int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
420
    const unsigned char *custom, size_t len,
421
    size_t entropy_len )
422
{
423
    mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
424
    return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
425
}
426
 
427
/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
428
 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
429
 * implements
430
 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
431
 *                -> working_state_after_reseed
432
 *                if required, then
433
 * CTR_DRBG_Generate(working_state_after_reseed,
434
 *                   requested_number_of_bits, additional_input)
435
 *                -> status, returned_bits, new_working_state
436
 * with inputs
437
 *   ctx contains working_state
438
 *   requested_number_of_bits = 8 * output_len
439
 *   additional[:add_len] = additional_input
440
 * and entropy_input comes from calling ctx->f_entropy
441
 * and with outputs
442
 *   status = SUCCESS (this function does the reseed internally)
443
 *   returned_bits = output[:output_len]
444
 *   ctx contains new_working_state
445
 */
446
int mbedtls_ctr_drbg_random_with_add( void *p_rng,
447
                              unsigned char *output, size_t output_len,
448
                              const unsigned char *additional, size_t add_len )
449
{
450
    int ret = 0;
451
    mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
452
    unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
453
    unsigned char *p = output;
454
    unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
455
    int i;
456
    size_t use_len;
457
 
458
    if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
459
        return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
460
 
461
    if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
462
        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
463
 
464
    memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
465
 
466
    if( ctx->reseed_counter > ctx->reseed_interval ||
467
        ctx->prediction_resistance )
468
    {
469
        if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
470
        {
471
            return( ret );
472
        }
473
        add_len = 0;
474
    }
475
 
476
    if( add_len > 0 )
477
    {
478
        if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
479
            goto exit;
480
        if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
481
            goto exit;
482
    }
483
 
484
    while( output_len > 0 )
485
    {
486
        /*
487
         * Increase counter
488
         */
489
        for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
490
            if( ++ctx->counter[i - 1] != 0 )
491
                break;
492
 
493
        /*
494
         * Crypt counter block
495
         */
496
        if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
497
            goto exit;
498
 
499
        use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
500
                                                       output_len;
501
        /*
502
         * Copy random block to destination
503
         */
504
        memcpy( p, tmp, use_len );
505
        p += use_len;
506
        output_len -= use_len;
507
    }
508
 
509
    if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
510
        goto exit;
511
 
512
    ctx->reseed_counter++;
513
 
514
exit:
515
    mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
516
    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
517
    return( ret );
518
}
519
 
520
int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
521
{
522
    int ret;
523
    mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
524
 
525
#if defined(MBEDTLS_THREADING_C)
526
    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
527
        return( ret );
528
#endif
529
 
530
    ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
531
 
532
#if defined(MBEDTLS_THREADING_C)
533
    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
534
        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
535
#endif
536
 
537
    return( ret );
538
}
539
 
540
#if defined(MBEDTLS_FS_IO)
541
int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
542
{
543
    int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
544
    FILE *f;
545
    unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
546
 
547
    if( ( f = fopen( path, "wb" ) ) == NULL )
548
        return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
549
 
550
    if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
551
        goto exit;
552
 
553
    if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
554
        ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
555
    else
556
        ret = 0;
557
 
558
exit:
559
    mbedtls_platform_zeroize( buf, sizeof( buf ) );
560
 
561
    fclose( f );
562
    return( ret );
563
}
564
 
565
int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
566
{
567
    int ret = 0;
568
    FILE *f = NULL;
569
    size_t n;
570
    unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
571
    unsigned char c;
572
 
573
    if( ( f = fopen( path, "rb" ) ) == NULL )
574
        return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
575
 
576
    n = fread( buf, 1, sizeof( buf ), f );
577
    if( fread( &c, 1, 1, f ) != 0 )
578
    {
579
        ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
580
        goto exit;
581
    }
582
    if( n == 0 || ferror( f ) )
583
    {
584
        ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
585
        goto exit;
586
    }
587
    fclose( f );
588
    f = NULL;
589
 
590
    ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
591
 
592
exit:
593
    mbedtls_platform_zeroize( buf, sizeof( buf ) );
594
    if( f != NULL )
595
        fclose( f );
596
    if( ret != 0 )
597
        return( ret );
598
    return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
599
}
600
#endif /* MBEDTLS_FS_IO */
601
 
602
#if defined(MBEDTLS_SELF_TEST)
603
 
604
static const unsigned char entropy_source_pr[96] =
605
    { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
606
      0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
607
      0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
608
      0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
609
      0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
610
      0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
611
      0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
612
      0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
613
      0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
614
      0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
615
      0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
616
      0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
617
 
618
static const unsigned char entropy_source_nopr[64] =
619
    { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
620
      0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
621
      0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
622
      0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
623
      0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
624
      0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
625
      0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
626
      0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
627
 
628
static const unsigned char nonce_pers_pr[16] =
629
    { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
630
      0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
631
 
632
static const unsigned char nonce_pers_nopr[16] =
633
    { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
634
      0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
635
 
636
static const unsigned char result_pr[16] =
637
    { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
638
      0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
639
 
640
static const unsigned char result_nopr[16] =
641
    { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
642
      0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
643
 
644
static size_t test_offset;
645
static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
646
                                       size_t len )
647
{
648
    const unsigned char *p = data;
649
    memcpy( buf, p + test_offset, len );
650
    test_offset += len;
651
    return( 0 );
652
}
653
 
654
#define CHK( c )    if( (c) != 0 )                          \
655
                    {                                       \
656
                        if( verbose != 0 )                  \
657
                            mbedtls_printf( "failed\n" );  \
658
                        return( 1 );                        \
659
                    }
660
 
661
/*
662
 * Checkup routine
663
 */
664
int mbedtls_ctr_drbg_self_test( int verbose )
665
{
666
    mbedtls_ctr_drbg_context ctx;
667
    unsigned char buf[16];
668
 
669
    mbedtls_ctr_drbg_init( &ctx );
670
 
671
    /*
672
     * Based on a NIST CTR_DRBG test vector (PR = True)
673
     */
674
    if( verbose != 0 )
675
        mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
676
 
677
    test_offset = 0;
678
    mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
679
    CHK( mbedtls_ctr_drbg_seed( &ctx,
680
                                ctr_drbg_self_test_entropy,
681
                                (void *) entropy_source_pr,
682
                                nonce_pers_pr, 16 ) );
683
    mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
684
    CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
685
    CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
686
    CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
687
 
688
    mbedtls_ctr_drbg_free( &ctx );
689
 
690
    if( verbose != 0 )
691
        mbedtls_printf( "passed\n" );
692
 
693
    /*
694
     * Based on a NIST CTR_DRBG test vector (PR = FALSE)
695
     */
696
    if( verbose != 0 )
697
        mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
698
 
699
    mbedtls_ctr_drbg_init( &ctx );
700
 
701
    test_offset = 0;
702
    mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
703
    CHK( mbedtls_ctr_drbg_seed( &ctx,
704
                                ctr_drbg_self_test_entropy,
705
                                (void *) entropy_source_nopr,
706
                                nonce_pers_nopr, 16 ) );
707
    CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
708
    CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
709
    CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
710
    CHK( memcmp( buf, result_nopr, 16 ) );
711
 
712
    mbedtls_ctr_drbg_free( &ctx );
713
 
714
    if( verbose != 0 )
715
        mbedtls_printf( "passed\n" );
716
 
717
    if( verbose != 0 )
718
            mbedtls_printf( "\n" );
719
 
720
    return( 0 );
721
}
722
#endif /* MBEDTLS_SELF_TEST */
723
 
724
#endif /* MBEDTLS_CTR_DRBG_C */