1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 57901324dSJerome Forissier * SPDX-License-Identifier: Apache-2.0 6817466cbSJens Wiklander * 7817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8817466cbSJens Wiklander * not use this file except in compliance with the License. 9817466cbSJens Wiklander * You may obtain a copy of the License at 10817466cbSJens Wiklander * 11817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12817466cbSJens Wiklander * 13817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16817466cbSJens Wiklander * See the License for the specific language governing permissions and 17817466cbSJens Wiklander * limitations under the License. 18817466cbSJens Wiklander */ 19817466cbSJens Wiklander /* 203d3b0591SJens Wiklander * The NIST SP 800-90 DRBGs are described in the following publication. 21817466cbSJens Wiklander * 22817466cbSJens Wiklander * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf 23817466cbSJens Wiklander */ 24817466cbSJens Wiklander 257901324dSJerome Forissier #include "common.h" 26817466cbSJens Wiklander 27817466cbSJens Wiklander #if defined(MBEDTLS_CTR_DRBG_C) 28817466cbSJens Wiklander 29817466cbSJens Wiklander #include "mbedtls/ctr_drbg.h" 303d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 3111fa71b9SJerome Forissier #include "mbedtls/error.h" 32817466cbSJens Wiklander 33817466cbSJens Wiklander #include <string.h> 34817466cbSJens Wiklander 35817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 36817466cbSJens Wiklander #include <stdio.h> 37817466cbSJens Wiklander #endif 38817466cbSJens Wiklander 39817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 40817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 41817466cbSJens Wiklander #include "mbedtls/platform.h" 42817466cbSJens Wiklander #else 43817466cbSJens Wiklander #include <stdio.h> 44817466cbSJens Wiklander #define mbedtls_printf printf 45817466cbSJens Wiklander #endif /* MBEDTLS_PLATFORM_C */ 46817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 47817466cbSJens Wiklander 48817466cbSJens Wiklander /* 49817466cbSJens Wiklander * CTR_DRBG context initialization 50817466cbSJens Wiklander */ 51817466cbSJens Wiklander void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) 52817466cbSJens Wiklander { 53817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); 5411fa71b9SJerome Forissier /* Indicate that the entropy nonce length is not set explicitly. 5511fa71b9SJerome Forissier * See mbedtls_ctr_drbg_set_nonce_len(). */ 5611fa71b9SJerome Forissier ctx->reseed_counter = -1; 57817466cbSJens Wiklander 587901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 59817466cbSJens Wiklander } 60817466cbSJens Wiklander 617901324dSJerome Forissier /* 627901324dSJerome Forissier * This function resets CTR_DRBG context to the state immediately 637901324dSJerome Forissier * after initial call of mbedtls_ctr_drbg_init(). 647901324dSJerome Forissier */ 65817466cbSJens Wiklander void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) 66817466cbSJens Wiklander { 67817466cbSJens Wiklander if( ctx == NULL ) 68817466cbSJens Wiklander return; 69817466cbSJens Wiklander 70817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 717901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */ 727901324dSJerome Forissier if( ctx->f_entropy != NULL ) 73817466cbSJens Wiklander mbedtls_mutex_free( &ctx->mutex ); 74817466cbSJens Wiklander #endif 75817466cbSJens Wiklander mbedtls_aes_free( &ctx->aes_ctx ); 763d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); 777901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 787901324dSJerome Forissier ctx->reseed_counter = -1; 79817466cbSJens Wiklander } 80817466cbSJens Wiklander 8111fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, 8211fa71b9SJerome Forissier int resistance ) 83817466cbSJens Wiklander { 84817466cbSJens Wiklander ctx->prediction_resistance = resistance; 85817466cbSJens Wiklander } 86817466cbSJens Wiklander 8711fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, 8811fa71b9SJerome Forissier size_t len ) 89817466cbSJens Wiklander { 90817466cbSJens Wiklander ctx->entropy_len = len; 91817466cbSJens Wiklander } 92817466cbSJens Wiklander 9311fa71b9SJerome Forissier int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx, 9411fa71b9SJerome Forissier size_t len ) 9511fa71b9SJerome Forissier { 9611fa71b9SJerome Forissier /* If mbedtls_ctr_drbg_seed() has already been called, it's 9711fa71b9SJerome Forissier * too late. Return the error code that's closest to making sense. */ 9811fa71b9SJerome Forissier if( ctx->f_entropy != NULL ) 9911fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 10011fa71b9SJerome Forissier 10111fa71b9SJerome Forissier if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 10211fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 10311fa71b9SJerome Forissier #if SIZE_MAX > INT_MAX 10411fa71b9SJerome Forissier /* This shouldn't be an issue because 10511fa71b9SJerome Forissier * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible 10611fa71b9SJerome Forissier * configuration, but make sure anyway. */ 10711fa71b9SJerome Forissier if( len > INT_MAX ) 10811fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 10911fa71b9SJerome Forissier #endif 11011fa71b9SJerome Forissier 11111fa71b9SJerome Forissier /* For backward compatibility with Mbed TLS <= 2.19, store the 11211fa71b9SJerome Forissier * entropy nonce length in a field that already exists, but isn't 11311fa71b9SJerome Forissier * used until after the initial seeding. */ 11411fa71b9SJerome Forissier /* Due to the capping of len above, the value fits in an int. */ 11511fa71b9SJerome Forissier ctx->reseed_counter = (int) len; 11611fa71b9SJerome Forissier return( 0 ); 11711fa71b9SJerome Forissier } 11811fa71b9SJerome Forissier 11911fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, 12011fa71b9SJerome Forissier int interval ) 121817466cbSJens Wiklander { 122817466cbSJens Wiklander ctx->reseed_interval = interval; 123817466cbSJens Wiklander } 124817466cbSJens Wiklander 125817466cbSJens Wiklander static int block_cipher_df( unsigned char *output, 126817466cbSJens Wiklander const unsigned char *data, size_t data_len ) 127817466cbSJens Wiklander { 12811fa71b9SJerome Forissier unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 12911fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; 130817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 131817466cbSJens Wiklander unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 132817466cbSJens Wiklander unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 133817466cbSJens Wiklander unsigned char *p, *iv; 134817466cbSJens Wiklander mbedtls_aes_context aes_ctx; 1353d3b0591SJens Wiklander int ret = 0; 136817466cbSJens Wiklander 137817466cbSJens Wiklander int i, j; 138817466cbSJens Wiklander size_t buf_len, use_len; 139817466cbSJens Wiklander 140817466cbSJens Wiklander if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 141817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 142817466cbSJens Wiklander 14311fa71b9SJerome Forissier memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 14411fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); 145817466cbSJens Wiklander mbedtls_aes_init( &aes_ctx ); 146817466cbSJens Wiklander 147817466cbSJens Wiklander /* 148817466cbSJens Wiklander * Construct IV (16 bytes) and S in buffer 149817466cbSJens Wiklander * IV = Counter (in 32-bits) padded to 16 with zeroes 150817466cbSJens Wiklander * S = Length input string (in 32-bits) || Length of output (in 32-bits) || 151817466cbSJens Wiklander * data || 0x80 152817466cbSJens Wiklander * (Total is padded to a multiple of 16-bytes with zeroes) 153817466cbSJens Wiklander */ 154817466cbSJens Wiklander p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; 155*039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE( data_len, p, 0); 156*039e02dfSJerome Forissier p += 4 + 3; 157817466cbSJens Wiklander *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; 158817466cbSJens Wiklander memcpy( p, data, data_len ); 159817466cbSJens Wiklander p[data_len] = 0x80; 160817466cbSJens Wiklander 161817466cbSJens Wiklander buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; 162817466cbSJens Wiklander 163817466cbSJens Wiklander for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) 164817466cbSJens Wiklander key[i] = i; 165817466cbSJens Wiklander 16611fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, 16711fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 1683d3b0591SJens Wiklander { 1693d3b0591SJens Wiklander goto exit; 1703d3b0591SJens Wiklander } 171817466cbSJens Wiklander 172817466cbSJens Wiklander /* 173817466cbSJens Wiklander * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data 174817466cbSJens Wiklander */ 175817466cbSJens Wiklander for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 176817466cbSJens Wiklander { 177817466cbSJens Wiklander p = buf; 178817466cbSJens Wiklander memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 179817466cbSJens Wiklander use_len = buf_len; 180817466cbSJens Wiklander 181817466cbSJens Wiklander while( use_len > 0 ) 182817466cbSJens Wiklander { 183817466cbSJens Wiklander for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) 184817466cbSJens Wiklander chain[i] ^= p[i]; 185817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 186817466cbSJens Wiklander use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? 187817466cbSJens Wiklander MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; 188817466cbSJens Wiklander 18911fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, 19011fa71b9SJerome Forissier chain, chain ) ) != 0 ) 1913d3b0591SJens Wiklander { 1923d3b0591SJens Wiklander goto exit; 1933d3b0591SJens Wiklander } 194817466cbSJens Wiklander } 195817466cbSJens Wiklander 196817466cbSJens Wiklander memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 197817466cbSJens Wiklander 198817466cbSJens Wiklander /* 199817466cbSJens Wiklander * Update IV 200817466cbSJens Wiklander */ 201817466cbSJens Wiklander buf[3]++; 202817466cbSJens Wiklander } 203817466cbSJens Wiklander 204817466cbSJens Wiklander /* 205817466cbSJens Wiklander * Do final encryption with reduced data 206817466cbSJens Wiklander */ 20711fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, 20811fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 2093d3b0591SJens Wiklander { 2103d3b0591SJens Wiklander goto exit; 2113d3b0591SJens Wiklander } 212817466cbSJens Wiklander iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; 213817466cbSJens Wiklander p = output; 214817466cbSJens Wiklander 215817466cbSJens Wiklander for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 216817466cbSJens Wiklander { 21711fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, 21811fa71b9SJerome Forissier iv, iv ) ) != 0 ) 2193d3b0591SJens Wiklander { 2203d3b0591SJens Wiklander goto exit; 2213d3b0591SJens Wiklander } 222817466cbSJens Wiklander memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 223817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 224817466cbSJens Wiklander } 2253d3b0591SJens Wiklander exit: 226817466cbSJens Wiklander mbedtls_aes_free( &aes_ctx ); 2273d3b0591SJens Wiklander /* 2283d3b0591SJens Wiklander * tidy up the stack 2293d3b0591SJens Wiklander */ 2303d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, sizeof( buf ) ); 2313d3b0591SJens Wiklander mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 2323d3b0591SJens Wiklander mbedtls_platform_zeroize( key, sizeof( key ) ); 2333d3b0591SJens Wiklander mbedtls_platform_zeroize( chain, sizeof( chain ) ); 2343d3b0591SJens Wiklander if( 0 != ret ) 2353d3b0591SJens Wiklander { 2363d3b0591SJens Wiklander /* 2373d3b0591SJens Wiklander * wipe partial seed from memory 2383d3b0591SJens Wiklander */ 2393d3b0591SJens Wiklander mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); 240817466cbSJens Wiklander } 241817466cbSJens Wiklander 2423d3b0591SJens Wiklander return( ret ); 2433d3b0591SJens Wiklander } 2443d3b0591SJens Wiklander 2453d3b0591SJens Wiklander /* CTR_DRBG_Update (SP 800-90A §10.2.1.2) 2463d3b0591SJens Wiklander * ctr_drbg_update_internal(ctx, provided_data) 2473d3b0591SJens Wiklander * implements 2483d3b0591SJens Wiklander * CTR_DRBG_Update(provided_data, Key, V) 2493d3b0591SJens Wiklander * with inputs and outputs 2503d3b0591SJens Wiklander * ctx->aes_ctx = Key 2513d3b0591SJens Wiklander * ctx->counter = V 2523d3b0591SJens Wiklander */ 253817466cbSJens Wiklander static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, 254817466cbSJens Wiklander const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) 255817466cbSJens Wiklander { 256817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 257817466cbSJens Wiklander unsigned char *p = tmp; 258817466cbSJens Wiklander int i, j; 2593d3b0591SJens Wiklander int ret = 0; 260817466cbSJens Wiklander 261817466cbSJens Wiklander memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 262817466cbSJens Wiklander 263817466cbSJens Wiklander for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 264817466cbSJens Wiklander { 265817466cbSJens Wiklander /* 266817466cbSJens Wiklander * Increase counter 267817466cbSJens Wiklander */ 268817466cbSJens Wiklander for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 269817466cbSJens Wiklander if( ++ctx->counter[i - 1] != 0 ) 270817466cbSJens Wiklander break; 271817466cbSJens Wiklander 272817466cbSJens Wiklander /* 273817466cbSJens Wiklander * Crypt counter block 274817466cbSJens Wiklander */ 27511fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 27611fa71b9SJerome Forissier ctx->counter, p ) ) != 0 ) 27711fa71b9SJerome Forissier { 2783d3b0591SJens Wiklander goto exit; 27911fa71b9SJerome Forissier } 280817466cbSJens Wiklander 281817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 282817466cbSJens Wiklander } 283817466cbSJens Wiklander 284817466cbSJens Wiklander for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) 285817466cbSJens Wiklander tmp[i] ^= data[i]; 286817466cbSJens Wiklander 287817466cbSJens Wiklander /* 288817466cbSJens Wiklander * Update key and counter 289817466cbSJens Wiklander */ 29011fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, 29111fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 29211fa71b9SJerome Forissier { 2933d3b0591SJens Wiklander goto exit; 29411fa71b9SJerome Forissier } 29511fa71b9SJerome Forissier memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, 29611fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE ); 297817466cbSJens Wiklander 2983d3b0591SJens Wiklander exit: 2993d3b0591SJens Wiklander mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 3003d3b0591SJens Wiklander return( ret ); 301817466cbSJens Wiklander } 302817466cbSJens Wiklander 3033d3b0591SJens Wiklander /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 3043d3b0591SJens Wiklander * mbedtls_ctr_drbg_update(ctx, additional, add_len) 3053d3b0591SJens Wiklander * implements 3063d3b0591SJens Wiklander * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 3073d3b0591SJens Wiklander * security_strength) -> initial_working_state 3083d3b0591SJens Wiklander * with inputs 3093d3b0591SJens Wiklander * ctx->counter = all-bits-0 3103d3b0591SJens Wiklander * ctx->aes_ctx = context from all-bits-0 key 3113d3b0591SJens Wiklander * additional[:add_len] = entropy_input || nonce || personalization_string 3123d3b0591SJens Wiklander * and with outputs 3133d3b0591SJens Wiklander * ctx = initial_working_state 3143d3b0591SJens Wiklander */ 3153d3b0591SJens Wiklander int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, 3163d3b0591SJens Wiklander const unsigned char *additional, 3173d3b0591SJens Wiklander size_t add_len ) 318817466cbSJens Wiklander { 319817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 32011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 321817466cbSJens Wiklander 3223d3b0591SJens Wiklander if( add_len == 0 ) 3233d3b0591SJens Wiklander return( 0 ); 3243d3b0591SJens Wiklander 3253d3b0591SJens Wiklander if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 3263d3b0591SJens Wiklander goto exit; 3273d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 3283d3b0591SJens Wiklander goto exit; 3293d3b0591SJens Wiklander 3303d3b0591SJens Wiklander exit: 3313d3b0591SJens Wiklander mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 3323d3b0591SJens Wiklander return( ret ); 3333d3b0591SJens Wiklander } 3343d3b0591SJens Wiklander 3353d3b0591SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED) 3363d3b0591SJens Wiklander void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, 3373d3b0591SJens Wiklander const unsigned char *additional, 3383d3b0591SJens Wiklander size_t add_len ) 339817466cbSJens Wiklander { 340817466cbSJens Wiklander /* MAX_INPUT would be more logical here, but we have to match 341817466cbSJens Wiklander * block_cipher_df()'s limits since we can't propagate errors */ 342817466cbSJens Wiklander if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 343817466cbSJens Wiklander add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; 3443d3b0591SJens Wiklander (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); 345817466cbSJens Wiklander } 3463d3b0591SJens Wiklander #endif /* MBEDTLS_DEPRECATED_REMOVED */ 347817466cbSJens Wiklander 3483d3b0591SJens Wiklander /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) 34911fa71b9SJerome Forissier * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) 3503d3b0591SJens Wiklander * implements 3513d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) 3523d3b0591SJens Wiklander * -> new_working_state 3533d3b0591SJens Wiklander * with inputs 3543d3b0591SJens Wiklander * ctx contains working_state 3553d3b0591SJens Wiklander * additional[:len] = additional_input 3563d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 35711fa71b9SJerome Forissier * for (ctx->entropy_len + nonce_len) bytes 3583d3b0591SJens Wiklander * and with output 3593d3b0591SJens Wiklander * ctx contains new_working_state 3603d3b0591SJens Wiklander */ 36111fa71b9SJerome Forissier static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx, 36211fa71b9SJerome Forissier const unsigned char *additional, 36311fa71b9SJerome Forissier size_t len, 36411fa71b9SJerome Forissier size_t nonce_len ) 365817466cbSJens Wiklander { 366817466cbSJens Wiklander unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; 367817466cbSJens Wiklander size_t seedlen = 0; 36811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 369817466cbSJens Wiklander 37011fa71b9SJerome Forissier if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 37111fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 37211fa71b9SJerome Forissier if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) 37311fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 37411fa71b9SJerome Forissier if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len ) 375817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 376817466cbSJens Wiklander 377817466cbSJens Wiklander memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); 378817466cbSJens Wiklander 37911fa71b9SJerome Forissier /* Gather entropy_len bytes of entropy to seed state. */ 38011fa71b9SJerome Forissier if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) ) 381817466cbSJens Wiklander { 382817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 383817466cbSJens Wiklander } 384817466cbSJens Wiklander seedlen += ctx->entropy_len; 385817466cbSJens Wiklander 38611fa71b9SJerome Forissier /* Gather entropy for a nonce if requested. */ 38711fa71b9SJerome Forissier if( nonce_len != 0 ) 38811fa71b9SJerome Forissier { 3897901324dSJerome Forissier if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) ) 39011fa71b9SJerome Forissier { 39111fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 39211fa71b9SJerome Forissier } 39311fa71b9SJerome Forissier seedlen += nonce_len; 39411fa71b9SJerome Forissier } 39511fa71b9SJerome Forissier 39611fa71b9SJerome Forissier /* Add additional data if provided. */ 39711fa71b9SJerome Forissier if( additional != NULL && len != 0 ) 398817466cbSJens Wiklander { 399817466cbSJens Wiklander memcpy( seed + seedlen, additional, len ); 400817466cbSJens Wiklander seedlen += len; 401817466cbSJens Wiklander } 402817466cbSJens Wiklander 40311fa71b9SJerome Forissier /* Reduce to 384 bits. */ 4043d3b0591SJens Wiklander if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) 4053d3b0591SJens Wiklander goto exit; 406817466cbSJens Wiklander 40711fa71b9SJerome Forissier /* Update state. */ 4083d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) 4093d3b0591SJens Wiklander goto exit; 410817466cbSJens Wiklander ctx->reseed_counter = 1; 411817466cbSJens Wiklander 4123d3b0591SJens Wiklander exit: 4133d3b0591SJens Wiklander mbedtls_platform_zeroize( seed, sizeof( seed ) ); 4143d3b0591SJens Wiklander return( ret ); 415817466cbSJens Wiklander } 416817466cbSJens Wiklander 41711fa71b9SJerome Forissier int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, 41811fa71b9SJerome Forissier const unsigned char *additional, size_t len ) 41911fa71b9SJerome Forissier { 42011fa71b9SJerome Forissier return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) ); 42111fa71b9SJerome Forissier } 42211fa71b9SJerome Forissier 42311fa71b9SJerome Forissier /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length 42411fa71b9SJerome Forissier * is sufficient to achieve the maximum security strength given the key 42511fa71b9SJerome Forissier * size and entropy length. If there is enough entropy in the initial 42611fa71b9SJerome Forissier * call to the entropy function to serve as both the entropy input and 42711fa71b9SJerome Forissier * the nonce, don't make a second call to get a nonce. */ 42811fa71b9SJerome Forissier static size_t good_nonce_len( size_t entropy_len ) 42911fa71b9SJerome Forissier { 43011fa71b9SJerome Forissier if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 ) 43111fa71b9SJerome Forissier return( 0 ); 43211fa71b9SJerome Forissier else 43311fa71b9SJerome Forissier return( ( entropy_len + 1 ) / 2 ); 43411fa71b9SJerome Forissier } 43511fa71b9SJerome Forissier 4365b25c76aSJerome Forissier /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 4375b25c76aSJerome Forissier * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) 4385b25c76aSJerome Forissier * implements 4395b25c76aSJerome Forissier * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 4405b25c76aSJerome Forissier * security_strength) -> initial_working_state 4415b25c76aSJerome Forissier * with inputs 4425b25c76aSJerome Forissier * custom[:len] = nonce || personalization_string 4435b25c76aSJerome Forissier * where entropy_input comes from f_entropy for ctx->entropy_len bytes 4445b25c76aSJerome Forissier * and with outputs 4455b25c76aSJerome Forissier * ctx = initial_working_state 4465b25c76aSJerome Forissier */ 4475b25c76aSJerome Forissier int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, 4485b25c76aSJerome Forissier int (*f_entropy)(void *, unsigned char *, size_t), 4495b25c76aSJerome Forissier void *p_entropy, 4505b25c76aSJerome Forissier const unsigned char *custom, 4515b25c76aSJerome Forissier size_t len ) 4525b25c76aSJerome Forissier { 45311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 4545b25c76aSJerome Forissier unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 45511fa71b9SJerome Forissier size_t nonce_len; 4565b25c76aSJerome Forissier 4575b25c76aSJerome Forissier memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); 4585b25c76aSJerome Forissier 4597901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */ 4607901324dSJerome Forissier #if defined(MBEDTLS_THREADING_C) 4617901324dSJerome Forissier mbedtls_mutex_init( &ctx->mutex ); 4627901324dSJerome Forissier #endif 4637901324dSJerome Forissier 4645b25c76aSJerome Forissier mbedtls_aes_init( &ctx->aes_ctx ); 4655b25c76aSJerome Forissier 4665b25c76aSJerome Forissier ctx->f_entropy = f_entropy; 4675b25c76aSJerome Forissier ctx->p_entropy = p_entropy; 4685b25c76aSJerome Forissier 4695b25c76aSJerome Forissier if( ctx->entropy_len == 0 ) 4705b25c76aSJerome Forissier ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; 47111fa71b9SJerome Forissier /* ctx->reseed_counter contains the desired amount of entropy to 47211fa71b9SJerome Forissier * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). 47311fa71b9SJerome Forissier * If it's -1, indicating that the entropy nonce length was not set 47411fa71b9SJerome Forissier * explicitly, use a sufficiently large nonce for security. */ 47511fa71b9SJerome Forissier nonce_len = ( ctx->reseed_counter >= 0 ? 47611fa71b9SJerome Forissier (size_t) ctx->reseed_counter : 47711fa71b9SJerome Forissier good_nonce_len( ctx->entropy_len ) ); 47811fa71b9SJerome Forissier 47911fa71b9SJerome Forissier /* Initialize with an empty key. */ 48011fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, 48111fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 4825b25c76aSJerome Forissier { 4835b25c76aSJerome Forissier return( ret ); 4845b25c76aSJerome Forissier } 4855b25c76aSJerome Forissier 48611fa71b9SJerome Forissier /* Do the initial seeding. */ 48711fa71b9SJerome Forissier if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len, 48811fa71b9SJerome Forissier nonce_len ) ) != 0 ) 4895b25c76aSJerome Forissier { 4905b25c76aSJerome Forissier return( ret ); 4915b25c76aSJerome Forissier } 4925b25c76aSJerome Forissier return( 0 ); 4935b25c76aSJerome Forissier } 4945b25c76aSJerome Forissier 4953d3b0591SJens Wiklander /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) 4963d3b0591SJens Wiklander * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) 4973d3b0591SJens Wiklander * implements 4983d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) 4993d3b0591SJens Wiklander * -> working_state_after_reseed 5003d3b0591SJens Wiklander * if required, then 5013d3b0591SJens Wiklander * CTR_DRBG_Generate(working_state_after_reseed, 5023d3b0591SJens Wiklander * requested_number_of_bits, additional_input) 5033d3b0591SJens Wiklander * -> status, returned_bits, new_working_state 5043d3b0591SJens Wiklander * with inputs 5053d3b0591SJens Wiklander * ctx contains working_state 5063d3b0591SJens Wiklander * requested_number_of_bits = 8 * output_len 5073d3b0591SJens Wiklander * additional[:add_len] = additional_input 5083d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 5093d3b0591SJens Wiklander * and with outputs 5103d3b0591SJens Wiklander * status = SUCCESS (this function does the reseed internally) 5113d3b0591SJens Wiklander * returned_bits = output[:output_len] 5123d3b0591SJens Wiklander * ctx contains new_working_state 5133d3b0591SJens Wiklander */ 514817466cbSJens Wiklander int mbedtls_ctr_drbg_random_with_add( void *p_rng, 515817466cbSJens Wiklander unsigned char *output, size_t output_len, 516817466cbSJens Wiklander const unsigned char *additional, size_t add_len ) 517817466cbSJens Wiklander { 518817466cbSJens Wiklander int ret = 0; 519817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 520817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 521817466cbSJens Wiklander unsigned char *p = output; 522817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 523817466cbSJens Wiklander int i; 524817466cbSJens Wiklander size_t use_len; 525817466cbSJens Wiklander 526817466cbSJens Wiklander if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) 527817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); 528817466cbSJens Wiklander 529817466cbSJens Wiklander if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) 530817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 531817466cbSJens Wiklander 532817466cbSJens Wiklander memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 533817466cbSJens Wiklander 534817466cbSJens Wiklander if( ctx->reseed_counter > ctx->reseed_interval || 535817466cbSJens Wiklander ctx->prediction_resistance ) 536817466cbSJens Wiklander { 537817466cbSJens Wiklander if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) 5383d3b0591SJens Wiklander { 539817466cbSJens Wiklander return( ret ); 5403d3b0591SJens Wiklander } 541817466cbSJens Wiklander add_len = 0; 542817466cbSJens Wiklander } 543817466cbSJens Wiklander 544817466cbSJens Wiklander if( add_len > 0 ) 545817466cbSJens Wiklander { 5463d3b0591SJens Wiklander if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 5473d3b0591SJens Wiklander goto exit; 5483d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 5493d3b0591SJens Wiklander goto exit; 550817466cbSJens Wiklander } 551817466cbSJens Wiklander 552817466cbSJens Wiklander while( output_len > 0 ) 553817466cbSJens Wiklander { 554817466cbSJens Wiklander /* 555817466cbSJens Wiklander * Increase counter 556817466cbSJens Wiklander */ 557817466cbSJens Wiklander for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 558817466cbSJens Wiklander if( ++ctx->counter[i - 1] != 0 ) 559817466cbSJens Wiklander break; 560817466cbSJens Wiklander 561817466cbSJens Wiklander /* 562817466cbSJens Wiklander * Crypt counter block 563817466cbSJens Wiklander */ 56411fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 56511fa71b9SJerome Forissier ctx->counter, tmp ) ) != 0 ) 56611fa71b9SJerome Forissier { 5673d3b0591SJens Wiklander goto exit; 56811fa71b9SJerome Forissier } 569817466cbSJens Wiklander 57011fa71b9SJerome Forissier use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) 57111fa71b9SJerome Forissier ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; 572817466cbSJens Wiklander /* 573817466cbSJens Wiklander * Copy random block to destination 574817466cbSJens Wiklander */ 575817466cbSJens Wiklander memcpy( p, tmp, use_len ); 576817466cbSJens Wiklander p += use_len; 577817466cbSJens Wiklander output_len -= use_len; 578817466cbSJens Wiklander } 579817466cbSJens Wiklander 5803d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 5813d3b0591SJens Wiklander goto exit; 582817466cbSJens Wiklander 583817466cbSJens Wiklander ctx->reseed_counter++; 584817466cbSJens Wiklander 5853d3b0591SJens Wiklander exit: 5863d3b0591SJens Wiklander mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 5873d3b0591SJens Wiklander mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 5885b25c76aSJerome Forissier return( ret ); 589817466cbSJens Wiklander } 590817466cbSJens Wiklander 59111fa71b9SJerome Forissier int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, 59211fa71b9SJerome Forissier size_t output_len ) 593817466cbSJens Wiklander { 59411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 595817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 596817466cbSJens Wiklander 597817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 598817466cbSJens Wiklander if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 599817466cbSJens Wiklander return( ret ); 600817466cbSJens Wiklander #endif 601817466cbSJens Wiklander 602817466cbSJens Wiklander ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); 603817466cbSJens Wiklander 604817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 605817466cbSJens Wiklander if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 606817466cbSJens Wiklander return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 607817466cbSJens Wiklander #endif 608817466cbSJens Wiklander 609817466cbSJens Wiklander return( ret ); 610817466cbSJens Wiklander } 611817466cbSJens Wiklander 612817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 61311fa71b9SJerome Forissier int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, 61411fa71b9SJerome Forissier const char *path ) 615817466cbSJens Wiklander { 616817466cbSJens Wiklander int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 617817466cbSJens Wiklander FILE *f; 618817466cbSJens Wiklander unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 619817466cbSJens Wiklander 620817466cbSJens Wiklander if( ( f = fopen( path, "wb" ) ) == NULL ) 621817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 622817466cbSJens Wiklander 62311fa71b9SJerome Forissier if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, 62411fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) 625817466cbSJens Wiklander goto exit; 626817466cbSJens Wiklander 62711fa71b9SJerome Forissier if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != 62811fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_MAX_INPUT ) 62911fa71b9SJerome Forissier { 630817466cbSJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 63111fa71b9SJerome Forissier } 6323d3b0591SJens Wiklander else 63311fa71b9SJerome Forissier { 634817466cbSJens Wiklander ret = 0; 63511fa71b9SJerome Forissier } 636817466cbSJens Wiklander 637817466cbSJens Wiklander exit: 6383d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, sizeof( buf ) ); 6393d3b0591SJens Wiklander 640817466cbSJens Wiklander fclose( f ); 641817466cbSJens Wiklander return( ret ); 642817466cbSJens Wiklander } 643817466cbSJens Wiklander 64411fa71b9SJerome Forissier int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, 64511fa71b9SJerome Forissier const char *path ) 646817466cbSJens Wiklander { 6473d3b0591SJens Wiklander int ret = 0; 6483d3b0591SJens Wiklander FILE *f = NULL; 649817466cbSJens Wiklander size_t n; 650817466cbSJens Wiklander unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 6513d3b0591SJens Wiklander unsigned char c; 652817466cbSJens Wiklander 653817466cbSJens Wiklander if( ( f = fopen( path, "rb" ) ) == NULL ) 654817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 655817466cbSJens Wiklander 6563d3b0591SJens Wiklander n = fread( buf, 1, sizeof( buf ), f ); 6573d3b0591SJens Wiklander if( fread( &c, 1, 1, f ) != 0 ) 658817466cbSJens Wiklander { 6593d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 6603d3b0591SJens Wiklander goto exit; 661817466cbSJens Wiklander } 6623d3b0591SJens Wiklander if( n == 0 || ferror( f ) ) 663817466cbSJens Wiklander { 6643d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 6653d3b0591SJens Wiklander goto exit; 666817466cbSJens Wiklander } 667817466cbSJens Wiklander fclose( f ); 6683d3b0591SJens Wiklander f = NULL; 669817466cbSJens Wiklander 6703d3b0591SJens Wiklander ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); 671817466cbSJens Wiklander 6723d3b0591SJens Wiklander exit: 6733d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, sizeof( buf ) ); 6743d3b0591SJens Wiklander if( f != NULL ) 6753d3b0591SJens Wiklander fclose( f ); 6763d3b0591SJens Wiklander if( ret != 0 ) 6773d3b0591SJens Wiklander return( ret ); 678817466cbSJens Wiklander return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); 679817466cbSJens Wiklander } 680817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */ 681817466cbSJens Wiklander 682817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 683817466cbSJens Wiklander 6847901324dSJerome Forissier /* The CTR_DRBG NIST test vectors used here are available at 6857901324dSJerome Forissier * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip 6867901324dSJerome Forissier * 6877901324dSJerome Forissier * The parameters used to derive the test data are: 6887901324dSJerome Forissier * 6897901324dSJerome Forissier * [AES-128 use df] 6907901324dSJerome Forissier * [PredictionResistance = True/False] 6917901324dSJerome Forissier * [EntropyInputLen = 128] 6927901324dSJerome Forissier * [NonceLen = 64] 6937901324dSJerome Forissier * [PersonalizationStringLen = 128] 6947901324dSJerome Forissier * [AdditionalInputLen = 0] 6957901324dSJerome Forissier * [ReturnedBitsLen = 512] 6967901324dSJerome Forissier * 6977901324dSJerome Forissier * [AES-256 use df] 6987901324dSJerome Forissier * [PredictionResistance = True/False] 6997901324dSJerome Forissier * [EntropyInputLen = 256] 7007901324dSJerome Forissier * [NonceLen = 128] 7017901324dSJerome Forissier * [PersonalizationStringLen = 256] 7027901324dSJerome Forissier * [AdditionalInputLen = 0] 7037901324dSJerome Forissier * [ReturnedBitsLen = 512] 7047901324dSJerome Forissier * 7057901324dSJerome Forissier */ 706817466cbSJens Wiklander 70711fa71b9SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) 7087901324dSJerome Forissier static const unsigned char entropy_source_pr[] = 7097901324dSJerome Forissier { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, 7107901324dSJerome Forissier 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92, 7117901324dSJerome Forissier 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8, 7127901324dSJerome Forissier 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, 7137901324dSJerome Forissier 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0, 7147901324dSJerome Forissier 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad, 7157901324dSJerome Forissier 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 }; 71611fa71b9SJerome Forissier 7177901324dSJerome Forissier static const unsigned char entropy_source_nopr[] = 7187901324dSJerome Forissier { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, 7197901324dSJerome Forissier 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, 7207901324dSJerome Forissier 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20, 7217901324dSJerome Forissier 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f, 7227901324dSJerome Forissier 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c }; 7237901324dSJerome Forissier 7247901324dSJerome Forissier static const unsigned char pers_pr[] = 7257901324dSJerome Forissier { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a, 7267901324dSJerome Forissier 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad }; 7277901324dSJerome Forissier 7287901324dSJerome Forissier static const unsigned char pers_nopr[] = 7297901324dSJerome Forissier { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c, 7307901324dSJerome Forissier 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f }; 7317901324dSJerome Forissier 7327901324dSJerome Forissier static const unsigned char result_pr[] = 7337901324dSJerome Forissier { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, 7347901324dSJerome Forissier 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff, 7357901324dSJerome Forissier 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10, 7367901324dSJerome Forissier 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, 7377901324dSJerome Forissier 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, 7387901324dSJerome Forissier 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc, 7397901324dSJerome Forissier 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06, 7407901324dSJerome Forissier 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf }; 7417901324dSJerome Forissier 7427901324dSJerome Forissier static const unsigned char result_nopr[] = 7437901324dSJerome Forissier { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, 7447901324dSJerome Forissier 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0, 7457901324dSJerome Forissier 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf, 7467901324dSJerome Forissier 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, 7477901324dSJerome Forissier 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, 7487901324dSJerome Forissier 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2, 7497901324dSJerome Forissier 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02, 7507901324dSJerome Forissier 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 }; 75111fa71b9SJerome Forissier #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 752817466cbSJens Wiklander 7537901324dSJerome Forissier static const unsigned char entropy_source_pr[] = 7547901324dSJerome Forissier { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, 7557901324dSJerome Forissier 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a, 7567901324dSJerome Forissier 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85, 7577901324dSJerome Forissier 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, 7587901324dSJerome Forissier 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15, 7597901324dSJerome Forissier 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45, 7607901324dSJerome Forissier 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, 7617901324dSJerome Forissier 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c, 7627901324dSJerome Forissier 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3, 7637901324dSJerome Forissier 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, 7647901324dSJerome Forissier 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e, 7657901324dSJerome Forissier 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76, 7667901324dSJerome Forissier 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, 7677901324dSJerome Forissier 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe }; 7687901324dSJerome Forissier 7697901324dSJerome Forissier static const unsigned char entropy_source_nopr[] = 7707901324dSJerome Forissier { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, 7717901324dSJerome Forissier 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0, 7727901324dSJerome Forissier 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73, 7737901324dSJerome Forissier 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, 7747901324dSJerome Forissier 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2, 7757901324dSJerome Forissier 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1, 7767901324dSJerome Forissier 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, 7777901324dSJerome Forissier 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb, 7787901324dSJerome Forissier 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a, 7797901324dSJerome Forissier 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 }; 7807901324dSJerome Forissier 7817901324dSJerome Forissier static const unsigned char pers_pr[] = 7827901324dSJerome Forissier { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, 7837901324dSJerome Forissier 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e, 7847901324dSJerome Forissier 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0, 7857901324dSJerome Forissier 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 }; 7867901324dSJerome Forissier 7877901324dSJerome Forissier static const unsigned char pers_nopr[] = 7887901324dSJerome Forissier { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, 7897901324dSJerome Forissier 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf, 7907901324dSJerome Forissier 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb, 7917901324dSJerome Forissier 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b }; 7927901324dSJerome Forissier 7937901324dSJerome Forissier static const unsigned char result_pr[] = 7947901324dSJerome Forissier { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, 7957901324dSJerome Forissier 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d, 7967901324dSJerome Forissier 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62, 7977901324dSJerome Forissier 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, 7987901324dSJerome Forissier 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, 7997901324dSJerome Forissier 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39, 8007901324dSJerome Forissier 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40, 8017901324dSJerome Forissier 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 }; 8027901324dSJerome Forissier 8037901324dSJerome Forissier static const unsigned char result_nopr[] = 8047901324dSJerome Forissier { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, 8057901324dSJerome Forissier 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3, 8067901324dSJerome Forissier 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b, 8077901324dSJerome Forissier 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, 8087901324dSJerome Forissier 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, 8097901324dSJerome Forissier 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30, 8107901324dSJerome Forissier 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a, 8117901324dSJerome Forissier 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 }; 81211fa71b9SJerome Forissier #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 813817466cbSJens Wiklander 814817466cbSJens Wiklander static size_t test_offset; 815817466cbSJens Wiklander static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, 816817466cbSJens Wiklander size_t len ) 817817466cbSJens Wiklander { 818817466cbSJens Wiklander const unsigned char *p = data; 819817466cbSJens Wiklander memcpy( buf, p + test_offset, len ); 820817466cbSJens Wiklander test_offset += len; 821817466cbSJens Wiklander return( 0 ); 822817466cbSJens Wiklander } 823817466cbSJens Wiklander 824817466cbSJens Wiklander #define CHK( c ) if( (c) != 0 ) \ 825817466cbSJens Wiklander { \ 826817466cbSJens Wiklander if( verbose != 0 ) \ 827817466cbSJens Wiklander mbedtls_printf( "failed\n" ); \ 828817466cbSJens Wiklander return( 1 ); \ 829817466cbSJens Wiklander } 830817466cbSJens Wiklander 831*039e02dfSJerome Forissier #define SELF_TEST_OUTPUT_DISCARD_LENGTH 64 8327901324dSJerome Forissier 833817466cbSJens Wiklander /* 834817466cbSJens Wiklander * Checkup routine 835817466cbSJens Wiklander */ 836817466cbSJens Wiklander int mbedtls_ctr_drbg_self_test( int verbose ) 837817466cbSJens Wiklander { 838817466cbSJens Wiklander mbedtls_ctr_drbg_context ctx; 8397901324dSJerome Forissier unsigned char buf[ sizeof( result_pr ) ]; 840817466cbSJens Wiklander 841817466cbSJens Wiklander mbedtls_ctr_drbg_init( &ctx ); 842817466cbSJens Wiklander 843817466cbSJens Wiklander /* 844817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = True) 845817466cbSJens Wiklander */ 846817466cbSJens Wiklander if( verbose != 0 ) 847817466cbSJens Wiklander mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); 848817466cbSJens Wiklander 849817466cbSJens Wiklander test_offset = 0; 8507901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE ); 8517901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 ); 8525b25c76aSJerome Forissier CHK( mbedtls_ctr_drbg_seed( &ctx, 8535b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 8545b25c76aSJerome Forissier (void *) entropy_source_pr, 8557901324dSJerome Forissier pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); 856817466cbSJens Wiklander mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); 857*039e02dfSJerome Forissier CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) ); 8587901324dSJerome Forissier CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) ); 8597901324dSJerome Forissier CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) ); 860817466cbSJens Wiklander 861817466cbSJens Wiklander mbedtls_ctr_drbg_free( &ctx ); 862817466cbSJens Wiklander 863817466cbSJens Wiklander if( verbose != 0 ) 864817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 865817466cbSJens Wiklander 866817466cbSJens Wiklander /* 867817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = FALSE) 868817466cbSJens Wiklander */ 869817466cbSJens Wiklander if( verbose != 0 ) 870817466cbSJens Wiklander mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); 871817466cbSJens Wiklander 872817466cbSJens Wiklander mbedtls_ctr_drbg_init( &ctx ); 873817466cbSJens Wiklander 874817466cbSJens Wiklander test_offset = 0; 8757901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE); 8767901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 ); 8775b25c76aSJerome Forissier CHK( mbedtls_ctr_drbg_seed( &ctx, 8785b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 8795b25c76aSJerome Forissier (void *) entropy_source_nopr, 8807901324dSJerome Forissier pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); 881817466cbSJens Wiklander CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); 882*039e02dfSJerome Forissier CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) ); 8837901324dSJerome Forissier CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) ); 8847901324dSJerome Forissier CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) ); 885817466cbSJens Wiklander 886817466cbSJens Wiklander mbedtls_ctr_drbg_free( &ctx ); 887817466cbSJens Wiklander 888817466cbSJens Wiklander if( verbose != 0 ) 889817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 890817466cbSJens Wiklander 891817466cbSJens Wiklander if( verbose != 0 ) 892817466cbSJens Wiklander mbedtls_printf( "\n" ); 893817466cbSJens Wiklander 894817466cbSJens Wiklander return( 0 ); 895817466cbSJens Wiklander } 896817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 897817466cbSJens Wiklander 898817466cbSJens Wiklander #endif /* MBEDTLS_CTR_DRBG_C */ 899