blob: 36ea251fc5b3d931066c1cc3d2039c0fa0ec78bb [file] [log] [blame]
Jaeden Ameroe54e6932018-08-06 16:19:58 +01001/*
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: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of Mbed Crypto (https://tls.mbed.org)
20 */
21/*
22 * The NIST SP 800-90 DRBGs are described in the following publication.
23 *
24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
25 */
26
27#if !defined(MBEDCRYPTO_CONFIG_FILE)
28#include "mbedcrypto/config.h"
29#else
30#include MBEDCRYPTO_CONFIG_FILE
31#endif
32
33#if defined(MBEDCRYPTO_CTR_DRBG_C)
34
35#include "mbedcrypto/ctr_drbg.h"
36#include "mbedcrypto/platform_util.h"
37
38#include <string.h>
39
40#if defined(MBEDCRYPTO_FS_IO)
41#include <stdio.h>
42#endif
43
44#if defined(MBEDCRYPTO_SELF_TEST)
45#if defined(MBEDCRYPTO_PLATFORM_C)
46#include "mbedcrypto/platform.h"
47#else
48#include <stdio.h>
49#define mbedcrypto_printf printf
50#endif /* MBEDCRYPTO_PLATFORM_C */
51#endif /* MBEDCRYPTO_SELF_TEST */
52
53/*
54 * CTR_DRBG context initialization
55 */
56void mbedcrypto_ctr_drbg_init( mbedcrypto_ctr_drbg_context *ctx )
57{
58 memset( ctx, 0, sizeof( mbedcrypto_ctr_drbg_context ) );
59
60#if defined(MBEDCRYPTO_THREADING_C)
61 mbedcrypto_mutex_init( &ctx->mutex );
62#endif
63}
64
65/*
66 * Non-public function wrapped by mbedcrypto_ctr_drbg_seed(). Necessary to allow
67 * NIST tests to succeed (which require known length fixed entropy)
68 */
69int mbedcrypto_ctr_drbg_seed_entropy_len(
70 mbedcrypto_ctr_drbg_context *ctx,
71 int (*f_entropy)(void *, unsigned char *, size_t),
72 void *p_entropy,
73 const unsigned char *custom,
74 size_t len,
75 size_t entropy_len )
76{
77 int ret;
78 unsigned char key[MBEDCRYPTO_CTR_DRBG_KEYSIZE];
79
80 memset( key, 0, MBEDCRYPTO_CTR_DRBG_KEYSIZE );
81
82 mbedcrypto_aes_init( &ctx->aes_ctx );
83
84 ctx->f_entropy = f_entropy;
85 ctx->p_entropy = p_entropy;
86
87 ctx->entropy_len = entropy_len;
88 ctx->reseed_interval = MBEDCRYPTO_CTR_DRBG_RESEED_INTERVAL;
89
90 /*
91 * Initialize with an empty key
92 */
93 if( ( ret = mbedcrypto_aes_setkey_enc( &ctx->aes_ctx, key, MBEDCRYPTO_CTR_DRBG_KEYBITS ) ) != 0 )
94 {
95 return( ret );
96 }
97
98 if( ( ret = mbedcrypto_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
99 {
100 return( ret );
101 }
102 return( 0 );
103}
104
105int mbedcrypto_ctr_drbg_seed( mbedcrypto_ctr_drbg_context *ctx,
106 int (*f_entropy)(void *, unsigned char *, size_t),
107 void *p_entropy,
108 const unsigned char *custom,
109 size_t len )
110{
111 return( mbedcrypto_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
112 MBEDCRYPTO_CTR_DRBG_ENTROPY_LEN ) );
113}
114
115void mbedcrypto_ctr_drbg_free( mbedcrypto_ctr_drbg_context *ctx )
116{
117 if( ctx == NULL )
118 return;
119
120#if defined(MBEDCRYPTO_THREADING_C)
121 mbedcrypto_mutex_free( &ctx->mutex );
122#endif
123 mbedcrypto_aes_free( &ctx->aes_ctx );
124 mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_ctr_drbg_context ) );
125}
126
127void mbedcrypto_ctr_drbg_set_prediction_resistance( mbedcrypto_ctr_drbg_context *ctx, int resistance )
128{
129 ctx->prediction_resistance = resistance;
130}
131
132void mbedcrypto_ctr_drbg_set_entropy_len( mbedcrypto_ctr_drbg_context *ctx, size_t len )
133{
134 ctx->entropy_len = len;
135}
136
137void mbedcrypto_ctr_drbg_set_reseed_interval( mbedcrypto_ctr_drbg_context *ctx, int interval )
138{
139 ctx->reseed_interval = interval;
140}
141
142static int block_cipher_df( unsigned char *output,
143 const unsigned char *data, size_t data_len )
144{
145 unsigned char buf[MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT + MBEDCRYPTO_CTR_DRBG_BLOCKSIZE + 16];
146 unsigned char tmp[MBEDCRYPTO_CTR_DRBG_SEEDLEN];
147 unsigned char key[MBEDCRYPTO_CTR_DRBG_KEYSIZE];
148 unsigned char chain[MBEDCRYPTO_CTR_DRBG_BLOCKSIZE];
149 unsigned char *p, *iv;
150 mbedcrypto_aes_context aes_ctx;
151 int ret = 0;
152
153 int i, j;
154 size_t buf_len, use_len;
155
156 if( data_len > MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT )
157 return( MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG );
158
159 memset( buf, 0, MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT + MBEDCRYPTO_CTR_DRBG_BLOCKSIZE + 16 );
160 mbedcrypto_aes_init( &aes_ctx );
161
162 /*
163 * Construct IV (16 bytes) and S in buffer
164 * IV = Counter (in 32-bits) padded to 16 with zeroes
165 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
166 * data || 0x80
167 * (Total is padded to a multiple of 16-bytes with zeroes)
168 */
169 p = buf + MBEDCRYPTO_CTR_DRBG_BLOCKSIZE;
170 *p++ = ( data_len >> 24 ) & 0xff;
171 *p++ = ( data_len >> 16 ) & 0xff;
172 *p++ = ( data_len >> 8 ) & 0xff;
173 *p++ = ( data_len ) & 0xff;
174 p += 3;
175 *p++ = MBEDCRYPTO_CTR_DRBG_SEEDLEN;
176 memcpy( p, data, data_len );
177 p[data_len] = 0x80;
178
179 buf_len = MBEDCRYPTO_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
180
181 for( i = 0; i < MBEDCRYPTO_CTR_DRBG_KEYSIZE; i++ )
182 key[i] = i;
183
184 if( ( ret = mbedcrypto_aes_setkey_enc( &aes_ctx, key, MBEDCRYPTO_CTR_DRBG_KEYBITS ) ) != 0 )
185 {
186 goto exit;
187 }
188
189 /*
190 * Reduce data to MBEDCRYPTO_CTR_DRBG_SEEDLEN bytes of data
191 */
192 for( j = 0; j < MBEDCRYPTO_CTR_DRBG_SEEDLEN; j += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE )
193 {
194 p = buf;
195 memset( chain, 0, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE );
196 use_len = buf_len;
197
198 while( use_len > 0 )
199 {
200 for( i = 0; i < MBEDCRYPTO_CTR_DRBG_BLOCKSIZE; i++ )
201 chain[i] ^= p[i];
202 p += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE;
203 use_len -= ( use_len >= MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) ?
204 MBEDCRYPTO_CTR_DRBG_BLOCKSIZE : use_len;
205
206 if( ( ret = mbedcrypto_aes_crypt_ecb( &aes_ctx, MBEDCRYPTO_AES_ENCRYPT, chain, chain ) ) != 0 )
207 {
208 goto exit;
209 }
210 }
211
212 memcpy( tmp + j, chain, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE );
213
214 /*
215 * Update IV
216 */
217 buf[3]++;
218 }
219
220 /*
221 * Do final encryption with reduced data
222 */
223 if( ( ret = mbedcrypto_aes_setkey_enc( &aes_ctx, tmp, MBEDCRYPTO_CTR_DRBG_KEYBITS ) ) != 0 )
224 {
225 goto exit;
226 }
227 iv = tmp + MBEDCRYPTO_CTR_DRBG_KEYSIZE;
228 p = output;
229
230 for( j = 0; j < MBEDCRYPTO_CTR_DRBG_SEEDLEN; j += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE )
231 {
232 if( ( ret = mbedcrypto_aes_crypt_ecb( &aes_ctx, MBEDCRYPTO_AES_ENCRYPT, iv, iv ) ) != 0 )
233 {
234 goto exit;
235 }
236 memcpy( p, iv, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE );
237 p += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE;
238 }
239exit:
240 mbedcrypto_aes_free( &aes_ctx );
241 /*
242 * tidy up the stack
243 */
244 mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
245 mbedcrypto_platform_zeroize( tmp, sizeof( tmp ) );
246 mbedcrypto_platform_zeroize( key, sizeof( key ) );
247 mbedcrypto_platform_zeroize( chain, sizeof( chain ) );
248 if( 0 != ret )
249 {
250 /*
251 * wipe partial seed from memory
252 */
253 mbedcrypto_platform_zeroize( output, MBEDCRYPTO_CTR_DRBG_SEEDLEN );
254 }
255
256 return( ret );
257}
258
259static int ctr_drbg_update_internal( mbedcrypto_ctr_drbg_context *ctx,
260 const unsigned char data[MBEDCRYPTO_CTR_DRBG_SEEDLEN] )
261{
262 unsigned char tmp[MBEDCRYPTO_CTR_DRBG_SEEDLEN];
263 unsigned char *p = tmp;
264 int i, j;
265 int ret = 0;
266
267 memset( tmp, 0, MBEDCRYPTO_CTR_DRBG_SEEDLEN );
268
269 for( j = 0; j < MBEDCRYPTO_CTR_DRBG_SEEDLEN; j += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE )
270 {
271 /*
272 * Increase counter
273 */
274 for( i = MBEDCRYPTO_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
275 if( ++ctx->counter[i - 1] != 0 )
276 break;
277
278 /*
279 * Crypt counter block
280 */
281 if( ( ret = mbedcrypto_aes_crypt_ecb( &ctx->aes_ctx, MBEDCRYPTO_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
282 {
283 return( ret );
284 }
285
286 p += MBEDCRYPTO_CTR_DRBG_BLOCKSIZE;
287 }
288
289 for( i = 0; i < MBEDCRYPTO_CTR_DRBG_SEEDLEN; i++ )
290 tmp[i] ^= data[i];
291
292 /*
293 * Update key and counter
294 */
295 if( ( ret = mbedcrypto_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDCRYPTO_CTR_DRBG_KEYBITS ) ) != 0 )
296 {
297 return( ret );
298 }
299 memcpy( ctx->counter, tmp + MBEDCRYPTO_CTR_DRBG_KEYSIZE, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE );
300
301 return( 0 );
302}
303
304void mbedcrypto_ctr_drbg_update( mbedcrypto_ctr_drbg_context *ctx,
305 const unsigned char *additional, size_t add_len )
306{
307 unsigned char add_input[MBEDCRYPTO_CTR_DRBG_SEEDLEN];
308
309 if( add_len > 0 )
310 {
311 /* MAX_INPUT would be more logical here, but we have to match
312 * block_cipher_df()'s limits since we can't propagate errors */
313 if( add_len > MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT )
314 add_len = MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT;
315
316 block_cipher_df( add_input, additional, add_len );
317 ctr_drbg_update_internal( ctx, add_input );
318 }
319}
320
321int mbedcrypto_ctr_drbg_reseed( mbedcrypto_ctr_drbg_context *ctx,
322 const unsigned char *additional, size_t len )
323{
324 unsigned char seed[MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT];
325 size_t seedlen = 0;
326 int ret;
327
328 if( ctx->entropy_len > MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT ||
329 len > MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
330 return( MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG );
331
332 memset( seed, 0, MBEDCRYPTO_CTR_DRBG_MAX_SEED_INPUT );
333
334 /*
335 * Gather entropy_len bytes of entropy to seed state
336 */
337 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
338 ctx->entropy_len ) )
339 {
340 return( MBEDCRYPTO_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
341 }
342
343 seedlen += ctx->entropy_len;
344
345 /*
346 * Add additional data
347 */
348 if( additional && len )
349 {
350 memcpy( seed + seedlen, additional, len );
351 seedlen += len;
352 }
353
354 /*
355 * Reduce to 384 bits
356 */
357 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
358 {
359 return( ret );
360 }
361
362 /*
363 * Update state
364 */
365 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
366 {
367 return( ret );
368 }
369 ctx->reseed_counter = 1;
370
371 return( 0 );
372}
373
374int mbedcrypto_ctr_drbg_random_with_add( void *p_rng,
375 unsigned char *output, size_t output_len,
376 const unsigned char *additional, size_t add_len )
377{
378 int ret = 0;
379 mbedcrypto_ctr_drbg_context *ctx = (mbedcrypto_ctr_drbg_context *) p_rng;
380 unsigned char add_input[MBEDCRYPTO_CTR_DRBG_SEEDLEN];
381 unsigned char *p = output;
382 unsigned char tmp[MBEDCRYPTO_CTR_DRBG_BLOCKSIZE];
383 int i;
384 size_t use_len;
385
386 if( output_len > MBEDCRYPTO_CTR_DRBG_MAX_REQUEST )
387 return( MBEDCRYPTO_ERR_CTR_DRBG_REQUEST_TOO_BIG );
388
389 if( add_len > MBEDCRYPTO_CTR_DRBG_MAX_INPUT )
390 return( MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG );
391
392 memset( add_input, 0, MBEDCRYPTO_CTR_DRBG_SEEDLEN );
393
394 if( ctx->reseed_counter > ctx->reseed_interval ||
395 ctx->prediction_resistance )
396 {
397 if( ( ret = mbedcrypto_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
398 {
399 return( ret );
400 }
401 add_len = 0;
402 }
403
404 if( add_len > 0 )
405 {
406 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
407 {
408 return( ret );
409 }
410 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
411 {
412 return( ret );
413 }
414 }
415
416 while( output_len > 0 )
417 {
418 /*
419 * Increase counter
420 */
421 for( i = MBEDCRYPTO_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
422 if( ++ctx->counter[i - 1] != 0 )
423 break;
424
425 /*
426 * Crypt counter block
427 */
428 if( ( ret = mbedcrypto_aes_crypt_ecb( &ctx->aes_ctx, MBEDCRYPTO_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
429 {
430 return( ret );
431 }
432
433 use_len = ( output_len > MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) ? MBEDCRYPTO_CTR_DRBG_BLOCKSIZE :
434 output_len;
435 /*
436 * Copy random block to destination
437 */
438 memcpy( p, tmp, use_len );
439 p += use_len;
440 output_len -= use_len;
441 }
442
443 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
444 {
445 return( ret );
446 }
447
448 ctx->reseed_counter++;
449
450 return( 0 );
451}
452
453int mbedcrypto_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
454{
455 int ret;
456 mbedcrypto_ctr_drbg_context *ctx = (mbedcrypto_ctr_drbg_context *) p_rng;
457
458#if defined(MBEDCRYPTO_THREADING_C)
459 if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
460 return( ret );
461#endif
462
463 ret = mbedcrypto_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
464
465#if defined(MBEDCRYPTO_THREADING_C)
466 if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
467 return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
468#endif
469
470 return( ret );
471}
472
473#if defined(MBEDCRYPTO_FS_IO)
474int mbedcrypto_ctr_drbg_write_seed_file( mbedcrypto_ctr_drbg_context *ctx, const char *path )
475{
476 int ret = MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR;
477 FILE *f;
478 unsigned char buf[ MBEDCRYPTO_CTR_DRBG_MAX_INPUT ];
479
480 if( ( f = fopen( path, "wb" ) ) == NULL )
481 return( MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR );
482
483 if( ( ret = mbedcrypto_ctr_drbg_random( ctx, buf, MBEDCRYPTO_CTR_DRBG_MAX_INPUT ) ) != 0 )
484 goto exit;
485
486 if( fwrite( buf, 1, MBEDCRYPTO_CTR_DRBG_MAX_INPUT, f ) != MBEDCRYPTO_CTR_DRBG_MAX_INPUT )
487 ret = MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR;
488 else
489 ret = 0;
490
491exit:
492 mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
493
494 fclose( f );
495 return( ret );
496}
497
498int mbedcrypto_ctr_drbg_update_seed_file( mbedcrypto_ctr_drbg_context *ctx, const char *path )
499{
500 int ret = 0;
501 FILE *f;
502 size_t n;
503 unsigned char buf[ MBEDCRYPTO_CTR_DRBG_MAX_INPUT ];
504
505 if( ( f = fopen( path, "rb" ) ) == NULL )
506 return( MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR );
507
508 fseek( f, 0, SEEK_END );
509 n = (size_t) ftell( f );
510 fseek( f, 0, SEEK_SET );
511
512 if( n > MBEDCRYPTO_CTR_DRBG_MAX_INPUT )
513 {
514 fclose( f );
515 return( MBEDCRYPTO_ERR_CTR_DRBG_INPUT_TOO_BIG );
516 }
517
518 if( fread( buf, 1, n, f ) != n )
519 ret = MBEDCRYPTO_ERR_CTR_DRBG_FILE_IO_ERROR;
520 else
521 mbedcrypto_ctr_drbg_update( ctx, buf, n );
522
523 fclose( f );
524
525 mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
526
527 if( ret != 0 )
528 return( ret );
529
530 return( mbedcrypto_ctr_drbg_write_seed_file( ctx, path ) );
531}
532#endif /* MBEDCRYPTO_FS_IO */
533
534#if defined(MBEDCRYPTO_SELF_TEST)
535
536static const unsigned char entropy_source_pr[96] =
537 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
538 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
539 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
540 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
541 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
542 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
543 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
544 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
545 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
546 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
547 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
548 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
549
550static const unsigned char entropy_source_nopr[64] =
551 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
552 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
553 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
554 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
555 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
556 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
557 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
558 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
559
560static const unsigned char nonce_pers_pr[16] =
561 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
562 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
563
564static const unsigned char nonce_pers_nopr[16] =
565 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
566 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
567
568static const unsigned char result_pr[16] =
569 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
570 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
571
572static const unsigned char result_nopr[16] =
573 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
574 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
575
576static size_t test_offset;
577static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
578 size_t len )
579{
580 const unsigned char *p = data;
581 memcpy( buf, p + test_offset, len );
582 test_offset += len;
583 return( 0 );
584}
585
586#define CHK( c ) if( (c) != 0 ) \
587 { \
588 if( verbose != 0 ) \
589 mbedcrypto_printf( "failed\n" ); \
590 return( 1 ); \
591 }
592
593/*
594 * Checkup routine
595 */
596int mbedcrypto_ctr_drbg_self_test( int verbose )
597{
598 mbedcrypto_ctr_drbg_context ctx;
599 unsigned char buf[16];
600
601 mbedcrypto_ctr_drbg_init( &ctx );
602
603 /*
604 * Based on a NIST CTR_DRBG test vector (PR = True)
605 */
606 if( verbose != 0 )
607 mbedcrypto_printf( " CTR_DRBG (PR = TRUE) : " );
608
609 test_offset = 0;
610 CHK( mbedcrypto_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
611 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
612 mbedcrypto_ctr_drbg_set_prediction_resistance( &ctx, MBEDCRYPTO_CTR_DRBG_PR_ON );
613 CHK( mbedcrypto_ctr_drbg_random( &ctx, buf, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) );
614 CHK( mbedcrypto_ctr_drbg_random( &ctx, buf, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) );
615 CHK( memcmp( buf, result_pr, MBEDCRYPTO_CTR_DRBG_BLOCKSIZE ) );
616
617 mbedcrypto_ctr_drbg_free( &ctx );
618
619 if( verbose != 0 )
620 mbedcrypto_printf( "passed\n" );
621
622 /*
623 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
624 */
625 if( verbose != 0 )
626 mbedcrypto_printf( " CTR_DRBG (PR = FALSE): " );
627
628 mbedcrypto_ctr_drbg_init( &ctx );
629
630 test_offset = 0;
631 CHK( mbedcrypto_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
632 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
633 CHK( mbedcrypto_ctr_drbg_random( &ctx, buf, 16 ) );
634 CHK( mbedcrypto_ctr_drbg_reseed( &ctx, NULL, 0 ) );
635 CHK( mbedcrypto_ctr_drbg_random( &ctx, buf, 16 ) );
636 CHK( memcmp( buf, result_nopr, 16 ) );
637
638 mbedcrypto_ctr_drbg_free( &ctx );
639
640 if( verbose != 0 )
641 mbedcrypto_printf( "passed\n" );
642
643 if( verbose != 0 )
644 mbedcrypto_printf( "\n" );
645
646 return( 0 );
647}
648#endif /* MBEDCRYPTO_SELF_TEST */
649
650#endif /* MBEDCRYPTO_CTR_DRBG_C */