1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) 3817466cbSJens Wiklander * 4*7901324dSJerome Forissier * Copyright The Mbed TLS Contributors 5*7901324dSJerome 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 25*7901324dSJerome 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 58*7901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 59817466cbSJens Wiklander } 60817466cbSJens Wiklander 61*7901324dSJerome Forissier /* 62*7901324dSJerome Forissier * This function resets CTR_DRBG context to the state immediately 63*7901324dSJerome Forissier * after initial call of mbedtls_ctr_drbg_init(). 64*7901324dSJerome 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) 71*7901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */ 72*7901324dSJerome 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 ) ); 77*7901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 78*7901324dSJerome 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; 155817466cbSJens Wiklander *p++ = ( data_len >> 24 ) & 0xff; 156817466cbSJens Wiklander *p++ = ( data_len >> 16 ) & 0xff; 157817466cbSJens Wiklander *p++ = ( data_len >> 8 ) & 0xff; 158817466cbSJens Wiklander *p++ = ( data_len ) & 0xff; 159817466cbSJens Wiklander p += 3; 160817466cbSJens Wiklander *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; 161817466cbSJens Wiklander memcpy( p, data, data_len ); 162817466cbSJens Wiklander p[data_len] = 0x80; 163817466cbSJens Wiklander 164817466cbSJens Wiklander buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; 165817466cbSJens Wiklander 166817466cbSJens Wiklander for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) 167817466cbSJens Wiklander key[i] = i; 168817466cbSJens Wiklander 16911fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, 17011fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 1713d3b0591SJens Wiklander { 1723d3b0591SJens Wiklander goto exit; 1733d3b0591SJens Wiklander } 174817466cbSJens Wiklander 175817466cbSJens Wiklander /* 176817466cbSJens Wiklander * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data 177817466cbSJens Wiklander */ 178817466cbSJens Wiklander for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 179817466cbSJens Wiklander { 180817466cbSJens Wiklander p = buf; 181817466cbSJens Wiklander memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 182817466cbSJens Wiklander use_len = buf_len; 183817466cbSJens Wiklander 184817466cbSJens Wiklander while( use_len > 0 ) 185817466cbSJens Wiklander { 186817466cbSJens Wiklander for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) 187817466cbSJens Wiklander chain[i] ^= p[i]; 188817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 189817466cbSJens Wiklander use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? 190817466cbSJens Wiklander MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; 191817466cbSJens Wiklander 19211fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, 19311fa71b9SJerome Forissier chain, chain ) ) != 0 ) 1943d3b0591SJens Wiklander { 1953d3b0591SJens Wiklander goto exit; 1963d3b0591SJens Wiklander } 197817466cbSJens Wiklander } 198817466cbSJens Wiklander 199817466cbSJens Wiklander memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 200817466cbSJens Wiklander 201817466cbSJens Wiklander /* 202817466cbSJens Wiklander * Update IV 203817466cbSJens Wiklander */ 204817466cbSJens Wiklander buf[3]++; 205817466cbSJens Wiklander } 206817466cbSJens Wiklander 207817466cbSJens Wiklander /* 208817466cbSJens Wiklander * Do final encryption with reduced data 209817466cbSJens Wiklander */ 21011fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, 21111fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 2123d3b0591SJens Wiklander { 2133d3b0591SJens Wiklander goto exit; 2143d3b0591SJens Wiklander } 215817466cbSJens Wiklander iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; 216817466cbSJens Wiklander p = output; 217817466cbSJens Wiklander 218817466cbSJens Wiklander for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 219817466cbSJens Wiklander { 22011fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, 22111fa71b9SJerome Forissier iv, iv ) ) != 0 ) 2223d3b0591SJens Wiklander { 2233d3b0591SJens Wiklander goto exit; 2243d3b0591SJens Wiklander } 225817466cbSJens Wiklander memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 226817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 227817466cbSJens Wiklander } 2283d3b0591SJens Wiklander exit: 229817466cbSJens Wiklander mbedtls_aes_free( &aes_ctx ); 2303d3b0591SJens Wiklander /* 2313d3b0591SJens Wiklander * tidy up the stack 2323d3b0591SJens Wiklander */ 2333d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, sizeof( buf ) ); 2343d3b0591SJens Wiklander mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 2353d3b0591SJens Wiklander mbedtls_platform_zeroize( key, sizeof( key ) ); 2363d3b0591SJens Wiklander mbedtls_platform_zeroize( chain, sizeof( chain ) ); 2373d3b0591SJens Wiklander if( 0 != ret ) 2383d3b0591SJens Wiklander { 2393d3b0591SJens Wiklander /* 2403d3b0591SJens Wiklander * wipe partial seed from memory 2413d3b0591SJens Wiklander */ 2423d3b0591SJens Wiklander mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); 243817466cbSJens Wiklander } 244817466cbSJens Wiklander 2453d3b0591SJens Wiklander return( ret ); 2463d3b0591SJens Wiklander } 2473d3b0591SJens Wiklander 2483d3b0591SJens Wiklander /* CTR_DRBG_Update (SP 800-90A §10.2.1.2) 2493d3b0591SJens Wiklander * ctr_drbg_update_internal(ctx, provided_data) 2503d3b0591SJens Wiklander * implements 2513d3b0591SJens Wiklander * CTR_DRBG_Update(provided_data, Key, V) 2523d3b0591SJens Wiklander * with inputs and outputs 2533d3b0591SJens Wiklander * ctx->aes_ctx = Key 2543d3b0591SJens Wiklander * ctx->counter = V 2553d3b0591SJens Wiklander */ 256817466cbSJens Wiklander static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, 257817466cbSJens Wiklander const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) 258817466cbSJens Wiklander { 259817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 260817466cbSJens Wiklander unsigned char *p = tmp; 261817466cbSJens Wiklander int i, j; 2623d3b0591SJens Wiklander int ret = 0; 263817466cbSJens Wiklander 264817466cbSJens Wiklander memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 265817466cbSJens Wiklander 266817466cbSJens Wiklander for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 267817466cbSJens Wiklander { 268817466cbSJens Wiklander /* 269817466cbSJens Wiklander * Increase counter 270817466cbSJens Wiklander */ 271817466cbSJens Wiklander for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 272817466cbSJens Wiklander if( ++ctx->counter[i - 1] != 0 ) 273817466cbSJens Wiklander break; 274817466cbSJens Wiklander 275817466cbSJens Wiklander /* 276817466cbSJens Wiklander * Crypt counter block 277817466cbSJens Wiklander */ 27811fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 27911fa71b9SJerome Forissier ctx->counter, p ) ) != 0 ) 28011fa71b9SJerome Forissier { 2813d3b0591SJens Wiklander goto exit; 28211fa71b9SJerome Forissier } 283817466cbSJens Wiklander 284817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 285817466cbSJens Wiklander } 286817466cbSJens Wiklander 287817466cbSJens Wiklander for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) 288817466cbSJens Wiklander tmp[i] ^= data[i]; 289817466cbSJens Wiklander 290817466cbSJens Wiklander /* 291817466cbSJens Wiklander * Update key and counter 292817466cbSJens Wiklander */ 29311fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, 29411fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 29511fa71b9SJerome Forissier { 2963d3b0591SJens Wiklander goto exit; 29711fa71b9SJerome Forissier } 29811fa71b9SJerome Forissier memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, 29911fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE ); 300817466cbSJens Wiklander 3013d3b0591SJens Wiklander exit: 3023d3b0591SJens Wiklander mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 3033d3b0591SJens Wiklander return( ret ); 304817466cbSJens Wiklander } 305817466cbSJens Wiklander 3063d3b0591SJens Wiklander /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 3073d3b0591SJens Wiklander * mbedtls_ctr_drbg_update(ctx, additional, add_len) 3083d3b0591SJens Wiklander * implements 3093d3b0591SJens Wiklander * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 3103d3b0591SJens Wiklander * security_strength) -> initial_working_state 3113d3b0591SJens Wiklander * with inputs 3123d3b0591SJens Wiklander * ctx->counter = all-bits-0 3133d3b0591SJens Wiklander * ctx->aes_ctx = context from all-bits-0 key 3143d3b0591SJens Wiklander * additional[:add_len] = entropy_input || nonce || personalization_string 3153d3b0591SJens Wiklander * and with outputs 3163d3b0591SJens Wiklander * ctx = initial_working_state 3173d3b0591SJens Wiklander */ 3183d3b0591SJens Wiklander int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, 3193d3b0591SJens Wiklander const unsigned char *additional, 3203d3b0591SJens Wiklander size_t add_len ) 321817466cbSJens Wiklander { 322817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 32311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 324817466cbSJens Wiklander 3253d3b0591SJens Wiklander if( add_len == 0 ) 3263d3b0591SJens Wiklander return( 0 ); 3273d3b0591SJens Wiklander 3283d3b0591SJens Wiklander if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 3293d3b0591SJens Wiklander goto exit; 3303d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 3313d3b0591SJens Wiklander goto exit; 3323d3b0591SJens Wiklander 3333d3b0591SJens Wiklander exit: 3343d3b0591SJens Wiklander mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 3353d3b0591SJens Wiklander return( ret ); 3363d3b0591SJens Wiklander } 3373d3b0591SJens Wiklander 3383d3b0591SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED) 3393d3b0591SJens Wiklander void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, 3403d3b0591SJens Wiklander const unsigned char *additional, 3413d3b0591SJens Wiklander size_t add_len ) 342817466cbSJens Wiklander { 343817466cbSJens Wiklander /* MAX_INPUT would be more logical here, but we have to match 344817466cbSJens Wiklander * block_cipher_df()'s limits since we can't propagate errors */ 345817466cbSJens Wiklander if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 346817466cbSJens Wiklander add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; 3473d3b0591SJens Wiklander (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); 348817466cbSJens Wiklander } 3493d3b0591SJens Wiklander #endif /* MBEDTLS_DEPRECATED_REMOVED */ 350817466cbSJens Wiklander 3513d3b0591SJens Wiklander /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) 35211fa71b9SJerome Forissier * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) 3533d3b0591SJens Wiklander * implements 3543d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) 3553d3b0591SJens Wiklander * -> new_working_state 3563d3b0591SJens Wiklander * with inputs 3573d3b0591SJens Wiklander * ctx contains working_state 3583d3b0591SJens Wiklander * additional[:len] = additional_input 3593d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 36011fa71b9SJerome Forissier * for (ctx->entropy_len + nonce_len) bytes 3613d3b0591SJens Wiklander * and with output 3623d3b0591SJens Wiklander * ctx contains new_working_state 3633d3b0591SJens Wiklander */ 36411fa71b9SJerome Forissier static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx, 36511fa71b9SJerome Forissier const unsigned char *additional, 36611fa71b9SJerome Forissier size_t len, 36711fa71b9SJerome Forissier size_t nonce_len ) 368817466cbSJens Wiklander { 369817466cbSJens Wiklander unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; 370817466cbSJens Wiklander size_t seedlen = 0; 37111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 372817466cbSJens Wiklander 37311fa71b9SJerome Forissier if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 37411fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 37511fa71b9SJerome Forissier if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) 37611fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 37711fa71b9SJerome Forissier if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len ) 378817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 379817466cbSJens Wiklander 380817466cbSJens Wiklander memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); 381817466cbSJens Wiklander 38211fa71b9SJerome Forissier /* Gather entropy_len bytes of entropy to seed state. */ 38311fa71b9SJerome Forissier if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) ) 384817466cbSJens Wiklander { 385817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 386817466cbSJens Wiklander } 387817466cbSJens Wiklander seedlen += ctx->entropy_len; 388817466cbSJens Wiklander 38911fa71b9SJerome Forissier /* Gather entropy for a nonce if requested. */ 39011fa71b9SJerome Forissier if( nonce_len != 0 ) 39111fa71b9SJerome Forissier { 392*7901324dSJerome Forissier if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) ) 39311fa71b9SJerome Forissier { 39411fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 39511fa71b9SJerome Forissier } 39611fa71b9SJerome Forissier seedlen += nonce_len; 39711fa71b9SJerome Forissier } 39811fa71b9SJerome Forissier 39911fa71b9SJerome Forissier /* Add additional data if provided. */ 40011fa71b9SJerome Forissier if( additional != NULL && len != 0 ) 401817466cbSJens Wiklander { 402817466cbSJens Wiklander memcpy( seed + seedlen, additional, len ); 403817466cbSJens Wiklander seedlen += len; 404817466cbSJens Wiklander } 405817466cbSJens Wiklander 40611fa71b9SJerome Forissier /* Reduce to 384 bits. */ 4073d3b0591SJens Wiklander if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) 4083d3b0591SJens Wiklander goto exit; 409817466cbSJens Wiklander 41011fa71b9SJerome Forissier /* Update state. */ 4113d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) 4123d3b0591SJens Wiklander goto exit; 413817466cbSJens Wiklander ctx->reseed_counter = 1; 414817466cbSJens Wiklander 4153d3b0591SJens Wiklander exit: 4163d3b0591SJens Wiklander mbedtls_platform_zeroize( seed, sizeof( seed ) ); 4173d3b0591SJens Wiklander return( ret ); 418817466cbSJens Wiklander } 419817466cbSJens Wiklander 42011fa71b9SJerome Forissier int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, 42111fa71b9SJerome Forissier const unsigned char *additional, size_t len ) 42211fa71b9SJerome Forissier { 42311fa71b9SJerome Forissier return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) ); 42411fa71b9SJerome Forissier } 42511fa71b9SJerome Forissier 42611fa71b9SJerome Forissier /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length 42711fa71b9SJerome Forissier * is sufficient to achieve the maximum security strength given the key 42811fa71b9SJerome Forissier * size and entropy length. If there is enough entropy in the initial 42911fa71b9SJerome Forissier * call to the entropy function to serve as both the entropy input and 43011fa71b9SJerome Forissier * the nonce, don't make a second call to get a nonce. */ 43111fa71b9SJerome Forissier static size_t good_nonce_len( size_t entropy_len ) 43211fa71b9SJerome Forissier { 43311fa71b9SJerome Forissier if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 ) 43411fa71b9SJerome Forissier return( 0 ); 43511fa71b9SJerome Forissier else 43611fa71b9SJerome Forissier return( ( entropy_len + 1 ) / 2 ); 43711fa71b9SJerome Forissier } 43811fa71b9SJerome Forissier 4395b25c76aSJerome Forissier /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 4405b25c76aSJerome Forissier * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) 4415b25c76aSJerome Forissier * implements 4425b25c76aSJerome Forissier * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 4435b25c76aSJerome Forissier * security_strength) -> initial_working_state 4445b25c76aSJerome Forissier * with inputs 4455b25c76aSJerome Forissier * custom[:len] = nonce || personalization_string 4465b25c76aSJerome Forissier * where entropy_input comes from f_entropy for ctx->entropy_len bytes 4475b25c76aSJerome Forissier * and with outputs 4485b25c76aSJerome Forissier * ctx = initial_working_state 4495b25c76aSJerome Forissier */ 4505b25c76aSJerome Forissier int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, 4515b25c76aSJerome Forissier int (*f_entropy)(void *, unsigned char *, size_t), 4525b25c76aSJerome Forissier void *p_entropy, 4535b25c76aSJerome Forissier const unsigned char *custom, 4545b25c76aSJerome Forissier size_t len ) 4555b25c76aSJerome Forissier { 45611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 4575b25c76aSJerome Forissier unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 45811fa71b9SJerome Forissier size_t nonce_len; 4595b25c76aSJerome Forissier 4605b25c76aSJerome Forissier memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); 4615b25c76aSJerome Forissier 462*7901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */ 463*7901324dSJerome Forissier #if defined(MBEDTLS_THREADING_C) 464*7901324dSJerome Forissier mbedtls_mutex_init( &ctx->mutex ); 465*7901324dSJerome Forissier #endif 466*7901324dSJerome Forissier 4675b25c76aSJerome Forissier mbedtls_aes_init( &ctx->aes_ctx ); 4685b25c76aSJerome Forissier 4695b25c76aSJerome Forissier ctx->f_entropy = f_entropy; 4705b25c76aSJerome Forissier ctx->p_entropy = p_entropy; 4715b25c76aSJerome Forissier 4725b25c76aSJerome Forissier if( ctx->entropy_len == 0 ) 4735b25c76aSJerome Forissier ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; 47411fa71b9SJerome Forissier /* ctx->reseed_counter contains the desired amount of entropy to 47511fa71b9SJerome Forissier * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). 47611fa71b9SJerome Forissier * If it's -1, indicating that the entropy nonce length was not set 47711fa71b9SJerome Forissier * explicitly, use a sufficiently large nonce for security. */ 47811fa71b9SJerome Forissier nonce_len = ( ctx->reseed_counter >= 0 ? 47911fa71b9SJerome Forissier (size_t) ctx->reseed_counter : 48011fa71b9SJerome Forissier good_nonce_len( ctx->entropy_len ) ); 48111fa71b9SJerome Forissier 48211fa71b9SJerome Forissier /* Initialize with an empty key. */ 48311fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, 48411fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 4855b25c76aSJerome Forissier { 4865b25c76aSJerome Forissier return( ret ); 4875b25c76aSJerome Forissier } 4885b25c76aSJerome Forissier 48911fa71b9SJerome Forissier /* Do the initial seeding. */ 49011fa71b9SJerome Forissier if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len, 49111fa71b9SJerome Forissier nonce_len ) ) != 0 ) 4925b25c76aSJerome Forissier { 4935b25c76aSJerome Forissier return( ret ); 4945b25c76aSJerome Forissier } 4955b25c76aSJerome Forissier return( 0 ); 4965b25c76aSJerome Forissier } 4975b25c76aSJerome Forissier 4983d3b0591SJens Wiklander /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) 4993d3b0591SJens Wiklander * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) 5003d3b0591SJens Wiklander * implements 5013d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) 5023d3b0591SJens Wiklander * -> working_state_after_reseed 5033d3b0591SJens Wiklander * if required, then 5043d3b0591SJens Wiklander * CTR_DRBG_Generate(working_state_after_reseed, 5053d3b0591SJens Wiklander * requested_number_of_bits, additional_input) 5063d3b0591SJens Wiklander * -> status, returned_bits, new_working_state 5073d3b0591SJens Wiklander * with inputs 5083d3b0591SJens Wiklander * ctx contains working_state 5093d3b0591SJens Wiklander * requested_number_of_bits = 8 * output_len 5103d3b0591SJens Wiklander * additional[:add_len] = additional_input 5113d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 5123d3b0591SJens Wiklander * and with outputs 5133d3b0591SJens Wiklander * status = SUCCESS (this function does the reseed internally) 5143d3b0591SJens Wiklander * returned_bits = output[:output_len] 5153d3b0591SJens Wiklander * ctx contains new_working_state 5163d3b0591SJens Wiklander */ 517817466cbSJens Wiklander int mbedtls_ctr_drbg_random_with_add( void *p_rng, 518817466cbSJens Wiklander unsigned char *output, size_t output_len, 519817466cbSJens Wiklander const unsigned char *additional, size_t add_len ) 520817466cbSJens Wiklander { 521817466cbSJens Wiklander int ret = 0; 522817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 523817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 524817466cbSJens Wiklander unsigned char *p = output; 525817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 526817466cbSJens Wiklander int i; 527817466cbSJens Wiklander size_t use_len; 528817466cbSJens Wiklander 529817466cbSJens Wiklander if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) 530817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); 531817466cbSJens Wiklander 532817466cbSJens Wiklander if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) 533817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 534817466cbSJens Wiklander 535817466cbSJens Wiklander memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 536817466cbSJens Wiklander 537817466cbSJens Wiklander if( ctx->reseed_counter > ctx->reseed_interval || 538817466cbSJens Wiklander ctx->prediction_resistance ) 539817466cbSJens Wiklander { 540817466cbSJens Wiklander if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) 5413d3b0591SJens Wiklander { 542817466cbSJens Wiklander return( ret ); 5433d3b0591SJens Wiklander } 544817466cbSJens Wiklander add_len = 0; 545817466cbSJens Wiklander } 546817466cbSJens Wiklander 547817466cbSJens Wiklander if( add_len > 0 ) 548817466cbSJens Wiklander { 5493d3b0591SJens Wiklander if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 5503d3b0591SJens Wiklander goto exit; 5513d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 5523d3b0591SJens Wiklander goto exit; 553817466cbSJens Wiklander } 554817466cbSJens Wiklander 555817466cbSJens Wiklander while( output_len > 0 ) 556817466cbSJens Wiklander { 557817466cbSJens Wiklander /* 558817466cbSJens Wiklander * Increase counter 559817466cbSJens Wiklander */ 560817466cbSJens Wiklander for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 561817466cbSJens Wiklander if( ++ctx->counter[i - 1] != 0 ) 562817466cbSJens Wiklander break; 563817466cbSJens Wiklander 564817466cbSJens Wiklander /* 565817466cbSJens Wiklander * Crypt counter block 566817466cbSJens Wiklander */ 56711fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 56811fa71b9SJerome Forissier ctx->counter, tmp ) ) != 0 ) 56911fa71b9SJerome Forissier { 5703d3b0591SJens Wiklander goto exit; 57111fa71b9SJerome Forissier } 572817466cbSJens Wiklander 57311fa71b9SJerome Forissier use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) 57411fa71b9SJerome Forissier ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; 575817466cbSJens Wiklander /* 576817466cbSJens Wiklander * Copy random block to destination 577817466cbSJens Wiklander */ 578817466cbSJens Wiklander memcpy( p, tmp, use_len ); 579817466cbSJens Wiklander p += use_len; 580817466cbSJens Wiklander output_len -= use_len; 581817466cbSJens Wiklander } 582817466cbSJens Wiklander 5833d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 5843d3b0591SJens Wiklander goto exit; 585817466cbSJens Wiklander 586817466cbSJens Wiklander ctx->reseed_counter++; 587817466cbSJens Wiklander 5883d3b0591SJens Wiklander exit: 5893d3b0591SJens Wiklander mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 5903d3b0591SJens Wiklander mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 5915b25c76aSJerome Forissier return( ret ); 592817466cbSJens Wiklander } 593817466cbSJens Wiklander 59411fa71b9SJerome Forissier int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, 59511fa71b9SJerome Forissier size_t output_len ) 596817466cbSJens Wiklander { 59711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 598817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 599817466cbSJens Wiklander 600817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 601817466cbSJens Wiklander if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 602817466cbSJens Wiklander return( ret ); 603817466cbSJens Wiklander #endif 604817466cbSJens Wiklander 605817466cbSJens Wiklander ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); 606817466cbSJens Wiklander 607817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 608817466cbSJens Wiklander if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 609817466cbSJens Wiklander return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 610817466cbSJens Wiklander #endif 611817466cbSJens Wiklander 612817466cbSJens Wiklander return( ret ); 613817466cbSJens Wiklander } 614817466cbSJens Wiklander 615817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 61611fa71b9SJerome Forissier int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, 61711fa71b9SJerome Forissier const char *path ) 618817466cbSJens Wiklander { 619817466cbSJens Wiklander int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 620817466cbSJens Wiklander FILE *f; 621817466cbSJens Wiklander unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 622817466cbSJens Wiklander 623817466cbSJens Wiklander if( ( f = fopen( path, "wb" ) ) == NULL ) 624817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 625817466cbSJens Wiklander 62611fa71b9SJerome Forissier if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, 62711fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) 628817466cbSJens Wiklander goto exit; 629817466cbSJens Wiklander 63011fa71b9SJerome Forissier if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != 63111fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_MAX_INPUT ) 63211fa71b9SJerome Forissier { 633817466cbSJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 63411fa71b9SJerome Forissier } 6353d3b0591SJens Wiklander else 63611fa71b9SJerome Forissier { 637817466cbSJens Wiklander ret = 0; 63811fa71b9SJerome Forissier } 639817466cbSJens Wiklander 640817466cbSJens Wiklander exit: 6413d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, sizeof( buf ) ); 6423d3b0591SJens Wiklander 643817466cbSJens Wiklander fclose( f ); 644817466cbSJens Wiklander return( ret ); 645817466cbSJens Wiklander } 646817466cbSJens Wiklander 64711fa71b9SJerome Forissier int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, 64811fa71b9SJerome Forissier const char *path ) 649817466cbSJens Wiklander { 6503d3b0591SJens Wiklander int ret = 0; 6513d3b0591SJens Wiklander FILE *f = NULL; 652817466cbSJens Wiklander size_t n; 653817466cbSJens Wiklander unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 6543d3b0591SJens Wiklander unsigned char c; 655817466cbSJens Wiklander 656817466cbSJens Wiklander if( ( f = fopen( path, "rb" ) ) == NULL ) 657817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 658817466cbSJens Wiklander 6593d3b0591SJens Wiklander n = fread( buf, 1, sizeof( buf ), f ); 6603d3b0591SJens Wiklander if( fread( &c, 1, 1, f ) != 0 ) 661817466cbSJens Wiklander { 6623d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 6633d3b0591SJens Wiklander goto exit; 664817466cbSJens Wiklander } 6653d3b0591SJens Wiklander if( n == 0 || ferror( f ) ) 666817466cbSJens Wiklander { 6673d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 6683d3b0591SJens Wiklander goto exit; 669817466cbSJens Wiklander } 670817466cbSJens Wiklander fclose( f ); 6713d3b0591SJens Wiklander f = NULL; 672817466cbSJens Wiklander 6733d3b0591SJens Wiklander ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); 674817466cbSJens Wiklander 6753d3b0591SJens Wiklander exit: 6763d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, sizeof( buf ) ); 6773d3b0591SJens Wiklander if( f != NULL ) 6783d3b0591SJens Wiklander fclose( f ); 6793d3b0591SJens Wiklander if( ret != 0 ) 6803d3b0591SJens Wiklander return( ret ); 681817466cbSJens Wiklander return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); 682817466cbSJens Wiklander } 683817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */ 684817466cbSJens Wiklander 685817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 686817466cbSJens Wiklander 687*7901324dSJerome Forissier /* The CTR_DRBG NIST test vectors used here are available at 688*7901324dSJerome Forissier * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip 689*7901324dSJerome Forissier * 690*7901324dSJerome Forissier * The parameters used to derive the test data are: 691*7901324dSJerome Forissier * 692*7901324dSJerome Forissier * [AES-128 use df] 693*7901324dSJerome Forissier * [PredictionResistance = True/False] 694*7901324dSJerome Forissier * [EntropyInputLen = 128] 695*7901324dSJerome Forissier * [NonceLen = 64] 696*7901324dSJerome Forissier * [PersonalizationStringLen = 128] 697*7901324dSJerome Forissier * [AdditionalInputLen = 0] 698*7901324dSJerome Forissier * [ReturnedBitsLen = 512] 699*7901324dSJerome Forissier * 700*7901324dSJerome Forissier * [AES-256 use df] 701*7901324dSJerome Forissier * [PredictionResistance = True/False] 702*7901324dSJerome Forissier * [EntropyInputLen = 256] 703*7901324dSJerome Forissier * [NonceLen = 128] 704*7901324dSJerome Forissier * [PersonalizationStringLen = 256] 705*7901324dSJerome Forissier * [AdditionalInputLen = 0] 706*7901324dSJerome Forissier * [ReturnedBitsLen = 512] 707*7901324dSJerome Forissier * 708*7901324dSJerome Forissier */ 709817466cbSJens Wiklander 71011fa71b9SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) 711*7901324dSJerome Forissier static const unsigned char entropy_source_pr[] = 712*7901324dSJerome Forissier { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, 713*7901324dSJerome Forissier 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92, 714*7901324dSJerome Forissier 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8, 715*7901324dSJerome Forissier 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, 716*7901324dSJerome Forissier 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0, 717*7901324dSJerome Forissier 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad, 718*7901324dSJerome Forissier 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 }; 71911fa71b9SJerome Forissier 720*7901324dSJerome Forissier static const unsigned char entropy_source_nopr[] = 721*7901324dSJerome Forissier { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, 722*7901324dSJerome Forissier 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, 723*7901324dSJerome Forissier 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20, 724*7901324dSJerome Forissier 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f, 725*7901324dSJerome Forissier 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c }; 726*7901324dSJerome Forissier 727*7901324dSJerome Forissier static const unsigned char pers_pr[] = 728*7901324dSJerome Forissier { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a, 729*7901324dSJerome Forissier 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad }; 730*7901324dSJerome Forissier 731*7901324dSJerome Forissier static const unsigned char pers_nopr[] = 732*7901324dSJerome Forissier { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c, 733*7901324dSJerome Forissier 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f }; 734*7901324dSJerome Forissier 735*7901324dSJerome Forissier static const unsigned char result_pr[] = 736*7901324dSJerome Forissier { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, 737*7901324dSJerome Forissier 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff, 738*7901324dSJerome Forissier 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10, 739*7901324dSJerome Forissier 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, 740*7901324dSJerome Forissier 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, 741*7901324dSJerome Forissier 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc, 742*7901324dSJerome Forissier 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06, 743*7901324dSJerome Forissier 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf }; 744*7901324dSJerome Forissier 745*7901324dSJerome Forissier static const unsigned char result_nopr[] = 746*7901324dSJerome Forissier { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, 747*7901324dSJerome Forissier 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0, 748*7901324dSJerome Forissier 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf, 749*7901324dSJerome Forissier 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, 750*7901324dSJerome Forissier 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, 751*7901324dSJerome Forissier 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2, 752*7901324dSJerome Forissier 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02, 753*7901324dSJerome Forissier 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 }; 75411fa71b9SJerome Forissier #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 755817466cbSJens Wiklander 756*7901324dSJerome Forissier static const unsigned char entropy_source_pr[] = 757*7901324dSJerome Forissier { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, 758*7901324dSJerome Forissier 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a, 759*7901324dSJerome Forissier 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85, 760*7901324dSJerome Forissier 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, 761*7901324dSJerome Forissier 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15, 762*7901324dSJerome Forissier 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45, 763*7901324dSJerome Forissier 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, 764*7901324dSJerome Forissier 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c, 765*7901324dSJerome Forissier 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3, 766*7901324dSJerome Forissier 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, 767*7901324dSJerome Forissier 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e, 768*7901324dSJerome Forissier 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76, 769*7901324dSJerome Forissier 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, 770*7901324dSJerome Forissier 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe }; 771*7901324dSJerome Forissier 772*7901324dSJerome Forissier static const unsigned char entropy_source_nopr[] = 773*7901324dSJerome Forissier { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, 774*7901324dSJerome Forissier 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0, 775*7901324dSJerome Forissier 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73, 776*7901324dSJerome Forissier 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, 777*7901324dSJerome Forissier 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2, 778*7901324dSJerome Forissier 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1, 779*7901324dSJerome Forissier 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, 780*7901324dSJerome Forissier 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb, 781*7901324dSJerome Forissier 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a, 782*7901324dSJerome Forissier 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 }; 783*7901324dSJerome Forissier 784*7901324dSJerome Forissier static const unsigned char pers_pr[] = 785*7901324dSJerome Forissier { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, 786*7901324dSJerome Forissier 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e, 787*7901324dSJerome Forissier 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0, 788*7901324dSJerome Forissier 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 }; 789*7901324dSJerome Forissier 790*7901324dSJerome Forissier static const unsigned char pers_nopr[] = 791*7901324dSJerome Forissier { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, 792*7901324dSJerome Forissier 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf, 793*7901324dSJerome Forissier 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb, 794*7901324dSJerome Forissier 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b }; 795*7901324dSJerome Forissier 796*7901324dSJerome Forissier static const unsigned char result_pr[] = 797*7901324dSJerome Forissier { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, 798*7901324dSJerome Forissier 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d, 799*7901324dSJerome Forissier 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62, 800*7901324dSJerome Forissier 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, 801*7901324dSJerome Forissier 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, 802*7901324dSJerome Forissier 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39, 803*7901324dSJerome Forissier 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40, 804*7901324dSJerome Forissier 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 }; 805*7901324dSJerome Forissier 806*7901324dSJerome Forissier static const unsigned char result_nopr[] = 807*7901324dSJerome Forissier { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, 808*7901324dSJerome Forissier 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3, 809*7901324dSJerome Forissier 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b, 810*7901324dSJerome Forissier 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, 811*7901324dSJerome Forissier 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, 812*7901324dSJerome Forissier 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30, 813*7901324dSJerome Forissier 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a, 814*7901324dSJerome Forissier 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 }; 81511fa71b9SJerome Forissier #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 816817466cbSJens Wiklander 817817466cbSJens Wiklander static size_t test_offset; 818817466cbSJens Wiklander static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, 819817466cbSJens Wiklander size_t len ) 820817466cbSJens Wiklander { 821817466cbSJens Wiklander const unsigned char *p = data; 822817466cbSJens Wiklander memcpy( buf, p + test_offset, len ); 823817466cbSJens Wiklander test_offset += len; 824817466cbSJens Wiklander return( 0 ); 825817466cbSJens Wiklander } 826817466cbSJens Wiklander 827817466cbSJens Wiklander #define CHK( c ) if( (c) != 0 ) \ 828817466cbSJens Wiklander { \ 829817466cbSJens Wiklander if( verbose != 0 ) \ 830817466cbSJens Wiklander mbedtls_printf( "failed\n" ); \ 831817466cbSJens Wiklander return( 1 ); \ 832817466cbSJens Wiklander } 833817466cbSJens Wiklander 834*7901324dSJerome Forissier #define SELF_TEST_OUPUT_DISCARD_LENGTH 64 835*7901324dSJerome Forissier 836817466cbSJens Wiklander /* 837817466cbSJens Wiklander * Checkup routine 838817466cbSJens Wiklander */ 839817466cbSJens Wiklander int mbedtls_ctr_drbg_self_test( int verbose ) 840817466cbSJens Wiklander { 841817466cbSJens Wiklander mbedtls_ctr_drbg_context ctx; 842*7901324dSJerome Forissier unsigned char buf[ sizeof( result_pr ) ]; 843817466cbSJens Wiklander 844817466cbSJens Wiklander mbedtls_ctr_drbg_init( &ctx ); 845817466cbSJens Wiklander 846817466cbSJens Wiklander /* 847817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = True) 848817466cbSJens Wiklander */ 849817466cbSJens Wiklander if( verbose != 0 ) 850817466cbSJens Wiklander mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); 851817466cbSJens Wiklander 852817466cbSJens Wiklander test_offset = 0; 853*7901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE ); 854*7901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 ); 8555b25c76aSJerome Forissier CHK( mbedtls_ctr_drbg_seed( &ctx, 8565b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 8575b25c76aSJerome Forissier (void *) entropy_source_pr, 858*7901324dSJerome Forissier pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); 859817466cbSJens Wiklander mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); 860*7901324dSJerome Forissier CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) ); 861*7901324dSJerome Forissier CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) ); 862*7901324dSJerome Forissier CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) ); 863817466cbSJens Wiklander 864817466cbSJens Wiklander mbedtls_ctr_drbg_free( &ctx ); 865817466cbSJens Wiklander 866817466cbSJens Wiklander if( verbose != 0 ) 867817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 868817466cbSJens Wiklander 869817466cbSJens Wiklander /* 870817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = FALSE) 871817466cbSJens Wiklander */ 872817466cbSJens Wiklander if( verbose != 0 ) 873817466cbSJens Wiklander mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); 874817466cbSJens Wiklander 875817466cbSJens Wiklander mbedtls_ctr_drbg_init( &ctx ); 876817466cbSJens Wiklander 877817466cbSJens Wiklander test_offset = 0; 878*7901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE); 879*7901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 ); 8805b25c76aSJerome Forissier CHK( mbedtls_ctr_drbg_seed( &ctx, 8815b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 8825b25c76aSJerome Forissier (void *) entropy_source_nopr, 883*7901324dSJerome Forissier pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); 884817466cbSJens Wiklander CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); 885*7901324dSJerome Forissier CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) ); 886*7901324dSJerome Forissier CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) ); 887*7901324dSJerome Forissier CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) ); 888817466cbSJens Wiklander 889817466cbSJens Wiklander mbedtls_ctr_drbg_free( &ctx ); 890817466cbSJens Wiklander 891817466cbSJens Wiklander if( verbose != 0 ) 892817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 893817466cbSJens Wiklander 894817466cbSJens Wiklander if( verbose != 0 ) 895817466cbSJens Wiklander mbedtls_printf( "\n" ); 896817466cbSJens Wiklander 897817466cbSJens Wiklander return( 0 ); 898817466cbSJens Wiklander } 899817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 900817466cbSJens Wiklander 901817466cbSJens Wiklander #endif /* MBEDTLS_CTR_DRBG_C */ 902