From f191cf206e4acda0431160b3e21f0358a3c0b65c Mon Sep 17 00:00:00 2001 From: toddouska Date: Fri, 16 Sep 2016 13:35:29 -0700 Subject: [PATCH] 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 */