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