From 572d448ab234e8edaa3e7dc0dd95c49cf8c86382 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 23 Jul 2019 13:47:53 +0100 Subject: [PATCH] Enforce NULL context for hardcoded RNG --- configs/baremetal.h | 2 +- configs/baremetal_test.h | 2 -- include/mbedtls/config.h | 5 +++-- include/mbedtls/ssl.h | 11 +---------- include/mbedtls/ssl_internal.h | 16 +++++++++++----- library/ssl_tls.c | 6 ------ programs/ssl/dtls_client.c | 20 ++++++++++++++++++++ programs/ssl/dtls_server.c | 19 +++++++++++++++++++ programs/ssl/mini_client.c | 15 ++++++++++++++- programs/ssl/ssl_client1.c | 20 ++++++++++++++++++++ programs/ssl/ssl_client2.c | 16 +++++++++++++++- programs/ssl/ssl_fork_server.c | 19 +++++++++++++++++++ programs/ssl/ssl_mail_client.c | 19 +++++++++++++++++++ programs/ssl/ssl_pthread_server.c | 19 +++++++++++++++++++ programs/ssl/ssl_server.c | 19 +++++++++++++++++++ programs/ssl/ssl_server2.c | 16 +++++++++++++++- programs/x509/cert_app.c | 21 ++++++++++++++++++++- tests/suites/helpers.function | 12 ++++++++++++ 18 files changed, 227 insertions(+), 30 deletions(-) diff --git a/configs/baremetal.h b/configs/baremetal.h index 9929d5657..e4e3a2ac8 100644 --- a/configs/baremetal.h +++ b/configs/baremetal.h @@ -106,7 +106,7 @@ #define MBEDTLS_SSL_CONF_RECV mbedtls_net_recv #define MBEDTLS_SSL_CONF_SEND mbedtls_net_send #define MBEDTLS_SSL_CONF_RECV_TIMEOUT mbedtls_net_recv_timeout -#define MBEDTLS_SSL_CONF_RNG mbedtls_hmac_drbg_random +#define MBEDTLS_SSL_CONF_RNG rng_wrap #define MBEDTLS_SSL_CONF_MIN_MINOR_VER MBEDTLS_SSL_MINOR_VERSION_3 #define MBEDTLS_SSL_CONF_MAX_MINOR_VER MBEDTLS_SSL_MINOR_VERSION_3 #define MBEDTLS_SSL_CONF_MIN_MAJOR_VER MBEDTLS_SSL_MAJOR_VERSION_3 diff --git a/configs/baremetal_test.h b/configs/baremetal_test.h index 1b87474fc..82c0ed17c 100644 --- a/configs/baremetal_test.h +++ b/configs/baremetal_test.h @@ -51,8 +51,6 @@ /* ssl_client2 and ssl_server2 use CTR-DRBG so far. */ #define MBEDTLS_CTR_DRBG_C -#undef MBEDTLS_SSL_CONF_RNG -#define MBEDTLS_SSL_CONF_RNG mbedtls_ctr_drbg_random /* The ticket implementation hardcodes AES-GCM */ #define MBEDTLS_GCM_C diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 243678c62..96413f850 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -3668,9 +3668,10 @@ /* The PRNG to use by the SSL module. If defined, this must * evaluate to the name on externally defined function with signature * int f_rng(void *, unsigned char *, size_t), - * e.g. mbedtls_ctr_drbg_random or mbedtls_hmac_drbg_random. + * which ignores its first parameter (the stack will always + * pass NULL to this function). */ -//#define MBEDTLS_SSL_CONF_RNG mbedtls_ctr_drbg_random +//#define MBEDTLS_SSL_CONF_RNG rng_wrap /* TLS version */ //#define MBEDTLS_SSL_CONF_MIN_MINOR_VER MBEDTLS_SSL_MINOR_VERSION_3 diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index ec2cf4574..1f0997784 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1000,8 +1000,8 @@ struct mbedtls_ssl_config #if !defined(MBEDTLS_SSL_CONF_RNG) /** Callback for getting (pseudo-)random numbers */ int (*f_rng)(void *, unsigned char *, size_t); -#endif /* !MBEDTLS_SSL_CONF_RNG */ void *p_rng; /*!< context for the RNG function */ +#endif /* !MBEDTLS_SSL_CONF_RNG */ #if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_NO_SESSION_CACHE) /** Callback to retrieve a session from the cache */ @@ -1601,15 +1601,6 @@ void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); -#else /* !MBEDTLS_SSL_CONF_RNG */ -/** - * \brief Set the random number generator callback context. - * - * \param conf SSL configuration - * \param p_rng RNG parameter - */ -void mbedtls_ssl_conf_rng_ctx( mbedtls_ssl_config *conf, - void *p_rng ); #endif /* MBEDTLS_SSL_CONF_RNG */ #if defined(MBEDTLS_DEBUG_C) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index e5c37eade..9cf80efb4 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -1560,18 +1560,18 @@ static inline mbedtls_ssl_recv_timeout_t* mbedtls_ssl_get_recv_timeout( typedef int mbedtls_frng_t( void*, unsigned char*, size_t ); -static inline void* mbedtls_ssl_conf_get_prng( mbedtls_ssl_config const *conf ) -{ - return( conf->p_rng ); -} #if !defined(MBEDTLS_SSL_CONF_RNG) static inline mbedtls_frng_t* mbedtls_ssl_conf_get_frng( mbedtls_ssl_config const *conf ) { return( conf->f_rng ); } -#else /* !MBEDTLS_SSL_CONF_RNG */ +static inline void* mbedtls_ssl_conf_get_prng( mbedtls_ssl_config const *conf ) +{ + return( conf->p_rng ); +} +#else /* !MBEDTLS_SSL_CONF_RNG */ #define mbedtls_ssl_conf_rng_func MBEDTLS_SSL_CONF_RNG extern int mbedtls_ssl_conf_rng_func( void*, unsigned char*, size_t ); @@ -1581,6 +1581,12 @@ static inline mbedtls_frng_t* mbedtls_ssl_conf_get_frng( ((void) conf); return ((mbedtls_frng_t*) mbedtls_ssl_conf_rng_func); } + +static inline void* mbedtls_ssl_conf_get_prng( mbedtls_ssl_config const *conf ) +{ + ((void) conf); + return( NULL ); +} #endif /* MBEDTLS_SSL_CONF_RNG */ static inline int mbedtls_ssl_conf_get_max_major_ver( diff --git a/library/ssl_tls.c b/library/ssl_tls.c index c63e08090..2bb4fcd3c 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -8510,12 +8510,6 @@ void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, conf->f_rng = f_rng; conf->p_rng = p_rng; } -#else -void mbedtls_ssl_conf_rng_ctx( mbedtls_ssl_config *conf, - void *p_rng ) -{ - conf->p_rng = p_rng; -} #endif #if defined(MBEDTLS_DEBUG_C) diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c index 5bd5cbedd..39a9f769f 100644 --- a/programs/ssl/dtls_client.c +++ b/programs/ssl/dtls_client.c @@ -95,6 +95,20 @@ static void my_debug( void *ctx, int level, } #endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( int argc, char *argv[] ) { int ret, len; @@ -192,7 +206,13 @@ int main( int argc, char *argv[] ) * Production code should set a proper ca chain and use REQUIRED. */ mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + +#if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); +#else + rng_ctx_global = &ctr_drbg; +#endif + #if defined(MBEDTLS_DEBUG_C) mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); #endif diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c index 84b905d70..1dddf8e1f 100644 --- a/programs/ssl/dtls_server.c +++ b/programs/ssl/dtls_server.c @@ -104,6 +104,20 @@ static void my_debug( void *ctx, int level, } #endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( void ) { int ret, len; @@ -224,7 +238,12 @@ int main( void ) goto exit; } +#if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); +#else + rng_ctx_global = &ctr_drbg; +#endif + #if defined(MBEDTLS_DEBUG_C) mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); #endif diff --git a/programs/ssl/mini_client.c b/programs/ssl/mini_client.c index 4231c0c8f..87c48ff4a 100644 --- a/programs/ssl/mini_client.c +++ b/programs/ssl/mini_client.c @@ -166,6 +166,19 @@ enum exit_codes ssl_write_failed, }; +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ int main( void ) { @@ -212,7 +225,7 @@ int main( void ) #if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); #else - mbedtls_ssl_conf_rng_ctx( &conf, &ctr_drbg ); + rng_ctx_global = &ctr_drbg; #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c index 5f453dcb5..8629980f8 100644 --- a/programs/ssl/ssl_client1.c +++ b/programs/ssl/ssl_client1.c @@ -85,6 +85,20 @@ static void my_debug( void *ctx, int level, } #endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( void ) { int ret = 1, len; @@ -179,7 +193,13 @@ int main( void ) * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + +#if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); +#else + rng_ctx_global = &ctr_drbg; +#endif + #if defined(MBEDTLS_DEBUG_C) mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); #endif diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 716263b1a..a7fd2595d 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -889,6 +889,20 @@ int report_cid_usage( mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( int argc, char *argv[] ) { int ret = 0, len, tail_len, i, written, frags, retry_left; @@ -1942,7 +1956,7 @@ int main( int argc, char *argv[] ) #if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); #else - mbedtls_ssl_conf_rng_ctx( &conf, &ctr_drbg ); + rng_ctx_global = &ctr_drbg; #endif #if defined(MBEDTLS_DEBUG_C) diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c index 098761cc9..7033b86ce 100644 --- a/programs/ssl/ssl_fork_server.c +++ b/programs/ssl/ssl_fork_server.c @@ -102,6 +102,20 @@ static void my_debug( void *ctx, int level, } #endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( void ) { int ret = 1, len, cnt = 0, pid; @@ -196,7 +210,12 @@ int main( void ) goto exit; } +#if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); +#else + rng_ctx_global = &ctr_drbg; +#endif + #if defined(MBEDTLS_DEBUG_C) mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); #endif diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c index b2e4f7f39..205c93ec6 100644 --- a/programs/ssl/ssl_mail_client.c +++ b/programs/ssl/ssl_mail_client.c @@ -361,6 +361,20 @@ static int write_and_get_response( mbedtls_net_context *sock_fd, unsigned char * while( 1 ); } +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( int argc, char *argv[] ) { int ret = 1, len; @@ -620,7 +634,12 @@ int main( int argc, char *argv[] ) * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); +#if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); +#else + rng_ctx_global = &ctr_drbg; +#endif + #if defined(MBEDTLS_DEBUG_C) mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); #endif diff --git a/programs/ssl/ssl_pthread_server.c b/programs/ssl/ssl_pthread_server.c index fd6ca2613..80bb049b9 100644 --- a/programs/ssl/ssl_pthread_server.c +++ b/programs/ssl/ssl_pthread_server.c @@ -325,6 +325,20 @@ static int thread_create( mbedtls_net_context *client_fd ) return( 0 ); } +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( void ) { int ret; @@ -439,7 +453,12 @@ int main( void ) goto exit; } +#if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); +#else + rng_ctx_global = &ctr_drbg; +#endif + #if defined(MBEDTLS_DEBUG_C) mbedtls_ssl_conf_dbg( &conf, my_mutexed_debug, stdout ); #endif diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c index bf502a5a3..e13af918f 100644 --- a/programs/ssl/ssl_server.c +++ b/programs/ssl/ssl_server.c @@ -97,6 +97,20 @@ static void my_debug( void *ctx, int level, } #endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( void ) { int ret, len; @@ -212,7 +226,12 @@ int main( void ) goto exit; } +#if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); +#else + rng_ctx_global = &ctr_drbg; +#endif + #if defined(MBEDTLS_DEBUG_C) mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); #endif diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 3fa2b1502..e0e433714 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -1505,6 +1505,20 @@ int report_cid_usage( mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( int argc, char *argv[] ) { int ret = 0, len, written, frags, exchanges_left; @@ -2754,7 +2768,7 @@ int main( int argc, char *argv[] ) #if !defined(MBEDTLS_SSL_CONF_RNG) mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); #else - mbedtls_ssl_conf_rng_ctx( &conf, &ctr_drbg ); + rng_ctx_global = &ctr_drbg; #endif #if defined(MBEDTLS_DEBUG_C) diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c index cdd77f273..9b40fa71b 100644 --- a/programs/x509/cert_app.c +++ b/programs/x509/cert_app.c @@ -149,6 +149,20 @@ static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *fl return( 0 ); } +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ); + +mbedtls_ctr_drbg_context *rng_ctx_global = NULL; +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + /* We expect the NULL parameter here. */ + if( ctx != NULL ) + return( -1 ); + + return( mbedtls_ctr_drbg_random( rng_ctx_global, dst, len ) ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + int main( int argc, char *argv[] ) { int ret = 1; @@ -424,7 +438,12 @@ int main( int argc, char *argv[] ) else mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE ); - mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); +#if !defined(MBEDTLS_SSL_CONF_RNG) + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); +#else + rng_ctx_global = &ctr_drbg; +#endif + #if defined(MBEDTLS_DEBUG_C) mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); #endif diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function index ccd4d4255..f5b61f31c 100644 --- a/tests/suites/helpers.function +++ b/tests/suites/helpers.function @@ -356,6 +356,18 @@ void mbedtls_param_failed( const char *failure_condition, } #endif +#if defined(MBEDTLS_SSL_CONF_RNG) +int rng_wrap( void *ctx, unsigned char *dst, size_t len ) +{ + ((void) ctx); + ((void) dst); + ((void) len); + /* We don't expect test suites to use SSL functionality + * that would trigger the hardcoded RNG. */ + return( -1 ); +} +#endif /* MBEDTLS_SSL_CONF_RNG */ + #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) static int redirect_output( FILE** out_stream, const char* path ) {