From f191cf206e4acda0431160b3e21f0358a3c0b65c Mon Sep 17 00:00:00 2001 From: toddouska Date: Fri, 16 Sep 2016 13:35:29 -0700 Subject: [PATCH 1/3] allow single threaded mode to share an RNG at WOLFSSL_CTX level --- examples/client/client.c | 6 ++++ src/internal.c | 65 ++++++++++++++++++++++++++-------------- src/ssl.c | 33 ++++++++++++++++++++ wolfssl/internal.h | 6 +++- wolfssl/ssl.h | 5 ++++ 5 files changed, 91 insertions(+), 24 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 14ef26245..cd31f8f15 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1084,6 +1084,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (ctx == NULL) err_sys("unable to get ctx"); +#ifdef SINGLE_THREADED + if (wolfSSL_CTX_new_rng(ctx) != SSL_SUCCESS) { + err_sys("Single Threaded new rng at CTX failed"); + } +#endif + if (cipherList) { if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) err_sys("client can't set cipher list 1"); diff --git a/src/internal.c b/src/internal.c index de6a8e6f9..96d251c99 100755 --- a/src/internal.c +++ b/src/internal.c @@ -1449,6 +1449,13 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); #endif +#ifdef SINGLE_THREADED + if (ctx->rng) { + wc_FreeRng(ctx->rng); + XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG); + } +#endif + #ifndef NO_CERTS FreeDer(&ctx->privateKey); FreeDer(&ctx->certificate); @@ -3475,26 +3482,33 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) } #endif - /* RNG */ - ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap, DYNAMIC_TYPE_RNG); - if (ssl->rng == NULL) { - WOLFSSL_MSG("RNG Memory error"); - return MEMORY_E; - } - - /* FIPS RNG API does not accept a heap hint */ -#ifndef HAVE_FIPS - if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap)) != 0) { - WOLFSSL_MSG("RNG Init error"); - return ret; - } -#else - if ( (ret = wc_InitRng(ssl->rng)) != 0) { - WOLFSSL_MSG("RNG Init error"); - return ret; - } +#ifdef SINGLE_THREADED + ssl->rng = ctx->rng; /* CTX may have one, if so use it */ #endif + if (ssl->rng == NULL) { + /* RNG */ + ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG); + if (ssl->rng == NULL) { + WOLFSSL_MSG("RNG Memory error"); + return MEMORY_E; + } + ssl->options.weOwnRng = 1; + + /* FIPS RNG API does not accept a heap hint */ +#ifndef HAVE_FIPS + if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap)) != 0) { + WOLFSSL_MSG("RNG Init error"); + return ret; + } +#else + if ( (ret = wc_InitRng(ssl->rng)) != 0) { + WOLFSSL_MSG("RNG Init error"); + return ret; + } +#endif + } + #if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) { ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0); @@ -3591,8 +3605,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) FreeCiphers(ssl); FreeArrays(ssl, 0); FreeKeyExchange(ssl); - wc_FreeRng(ssl->rng); - XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + if (ssl->options.weOwnRng) { + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + } XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); @@ -3783,9 +3799,12 @@ void FreeHandshakeResources(WOLFSSL* ssl) /* RNG */ if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) { - wc_FreeRng(ssl->rng); - XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); - ssl->rng = NULL; + if (ssl->options.weOwnRng) { + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + ssl->rng = NULL; + ssl->options.weOwnRng = 0; + } } #ifdef WOLFSSL_DTLS diff --git a/src/ssl.c b/src/ssl.c index f04ec1287..496381750 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2323,6 +2323,39 @@ int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm) } +#ifdef SINGLE_THREADED +/* no locking in single threaded mode, allow a CTX level rng to be shared with + * WOLFSSL objects, SSL_SUCCESS on ok */ +int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx) +{ + WC_RNG* rng; + int ret; + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + rng = XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG); + if (rng == NULL) { + return MEMORY_E; + } + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(rng, ctx->heap); +#else + ret = wc_InitRng(rng); +#endif + if (ret != 0) { + XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG); + return ret; + } + + ctx->rng = rng; + return SSL_SUCCESS; +} +#endif + + #ifdef WOLFSSL_TRUST_PEER_CERT int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 5f67dc33e..d60882f9f 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1902,7 +1902,10 @@ WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name); /* wolfSSL context type */ struct WOLFSSL_CTX { WOLFSSL_METHOD* method; - wolfSSL_Mutex countMutex; /* reference count mutex */ +#ifdef SINGLE_THREADED + WC_RNG* rng; /* to be shared with WOLFSSL w/o locking */ +#endif + wolfSSL_Mutex countMutex; /* reference count mutex */ int refCount; /* reference count */ int err; /* error code in case of mutex not created */ #ifndef NO_DH @@ -2396,6 +2399,7 @@ typedef struct Options { word16 usingNonblock:1; /* are we using nonblocking socket */ word16 saveArrays:1; /* save array Memory for user get keys or psk */ + word16 weOwnRng:1; /* will be true unless CTX owns */ #ifdef HAVE_POLY1305 word16 oldPoly:1; /* set when to use old rfc way of poly*/ #endif diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index e83749cd2..160bdef62 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1418,6 +1418,11 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX*); #endif /* !NO_CERTS */ + +#ifdef SINGLE_THREADED + WOLFSSL_API int wolfSSL_CTX_new_rng(WOLFSSL_CTX*); +#endif + /* end of handshake frees temporary arrays, if user needs for get_keys or psk hints, call KeepArrays before handshake and then FreeArrays when done if don't want to wait for object free */ From c51444bec5d18c571de71357c9f51d49c8ce251d Mon Sep 17 00:00:00 2001 From: toddouska Date: Fri, 16 Sep 2016 18:54:47 -0700 Subject: [PATCH 2/3] update rdseed to 64bit get, more retries, fallback to /dev/urandom on failure --- wolfcrypt/src/random.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 75ba61a8f..86b155a2b 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1029,29 +1029,28 @@ static int wc_InitRng_IntelRD() return 1 ; } -#define INTELRD_RETRY 10 +#define INTELRD_RETRY 32 #if defined(HAVE_HASHDRBG) || defined(NO_RC4) /* return 0 on success */ -static INLINE int IntelRDseed32(unsigned int *seed) +static INLINE int IntelRDseed64(word64* seed) { - int rdseed; unsigned char ok ; + unsigned char ok; - __asm__ volatile("rdseed %0; setc %1":"=r"(rdseed), "=qm"(ok)); + __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok)); if(ok){ - *seed = rdseed ; return 0 ; } else return 1; } /* return 0 on success */ -static INLINE int IntelRDseed32_r(unsigned int *rnd) +static INLINE int IntelRDseed64_r(word64* rnd) { - int i ; + int i; for(i=0; i 0; sz-=4, output+=4) { - if(IS_INTEL_RDSEED)ret = IntelRDseed32_r((word32 *)output) ; + for( ; sz/8 > 0; sz-=8, output+=8) { + if(IS_INTEL_RDSEED)ret = IntelRDseed64_r((word64*)output); else return 1 ; if(ret) return 1 ; } if(sz == 0)return 0 ; - if(IS_INTEL_RDSEED)ret = IntelRDseed32_r(&rndTmp) ; + if(IS_INTEL_RDSEED)ret = IntelRDseed64_r(&rndTmp) ; else return 1 ; if(ret) return 1 ; @@ -1621,8 +1620,21 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #if defined(HAVE_INTEL_RDGEN) && (defined(HAVE_HASHDRBG) || defined(NO_RC4)) wc_InitRng_IntelRD() ; /* set cpuid_flags if not yet */ - if(IS_INTEL_RDSEED) - return wc_GenerateSeed_IntelRD(NULL, output, sz) ; + if(IS_INTEL_RDSEED) { + ret = wc_GenerateSeed_IntelRD(NULL, output, sz); + if (ret == 0) { + /* success, we're done */ + return ret; + } +#ifdef FORCE_FAILURE_RDSEED + /* don't fallback to /dev/urandom */ + return ret; +#else + /* fallback to /dev/urrandom attempt */ + ret = 0; +#endif + } + #endif os->fd = open("/dev/urandom",O_RDONLY); From 0718aba655579a8a0f9df8497771c5aa1c42bd13 Mon Sep 17 00:00:00 2001 From: toddouska Date: Mon, 19 Sep 2016 13:28:14 -0700 Subject: [PATCH 3/3] fix comment typo --- wolfcrypt/src/random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 86b155a2b..61c2e8455 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -1630,7 +1630,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) /* don't fallback to /dev/urandom */ return ret; #else - /* fallback to /dev/urrandom attempt */ + /* fallback to /dev/urandom attempt */ ret = 0; #endif }