diff --git a/src/internal.c b/src/internal.c index 077a56bb75..6fc41e8735 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4833,7 +4833,15 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) WOLFSSL_MSG("Suites Memory error"); return MEMORY_E; } +#ifdef SINGLE_THREADED + ssl->options.ownSuites = 1; +#endif } +#ifdef SINGLE_THREADED + else { + ssl->options.ownSuites = 0; + } +#endif } /* Initialize SSL with the appropriate fields from it's ctx */ @@ -5192,9 +5200,13 @@ void SSL_ResourceFree(WOLFSSL* ssl) XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); } #ifdef SINGLE_THREADED - if (ssl->suites != ssl->ctx->suites) + if (ssl->options.ownSuites) #endif + { XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); + } + ssl->suites = NULL; + FreeHandshakeHashes(ssl); XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); @@ -5416,9 +5428,11 @@ void FreeHandshakeResources(WOLFSSL* ssl) { /* suites */ #ifdef SINGLE_THREADED - if (ssl->suites != ssl->ctx->suites) + if (ssl->options.ownSuites) #endif + { XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); + } ssl->suites = NULL; /* hsHashes */ diff --git a/src/ssl.c b/src/ssl.c index 9eb2597f4d..bc88f60479 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -8728,6 +8728,18 @@ int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) { WOLFSSL_ENTER("wolfSSL_set_cipher_list"); +#ifdef SINGLE_THREADED + if (ssl->ctx->suites == ssl->suites) { + ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + DYNAMIC_TYPE_SUITES); + if (ssl->suites == NULL) { + WOLFSSL_MSG("Suites Memory error"); + return MEMORY_E; + } + ssl->options.ownSuites = 1; + } +#endif + return (SetCipherList(ssl->ctx, ssl->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } diff --git a/tests/api.c b/tests/api.c index 01bdc0bc20..99b2382afc 100644 --- a/tests/api.c +++ b/tests/api.c @@ -607,6 +607,114 @@ static void test_wolfSSL_CTX_new(WOLFSSL_METHOD *method) } #endif +#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ +(!defined(NO_RSA) || defined(HAVE_ECC)) +static void test_for_double_Free(void) +{ + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + int skipTest = 0; + const char* testCertFile; + const char* testKeyFile; + char optionsCiphers[] = "RC4-SHA:RC4-MD5:DES-CBC3-SHA:AES128-SHA:AES256-SHA" +":NULL-SHA:NULL-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-PSK-AES256-GCM" +"-SHA384:DHE-PSK-AES128-GCM-SHA256:PSK-AES256-GCM-SHA384:PSK-AES128-GCM-SHA256:" +"DHE-PSK-AES256-CBC-SHA384:DHE-PSK-AES128-CBC-SHA256:PSK-AES256-CBC-SHA384:PSK-" +"AES128-CBC-SHA256:PSK-AES128-CBC-SHA:PSK-AES256-CBC-SHA:DHE-PSK-AES128-CCM:DHE" +"-PSK-AES256-CCM:PSK-AES128-CCM:PSK-AES256-CCM:PSK-AES128-CCM-8:PSK-AES256-CCM-" +"8:DHE-PSK-NULL-SHA384:DHE-PSK-NULL-SHA256:PSK-NULL-SHA384:PSK-NULL-SHA256:PSK-" +"NULL-SHA:HC128-MD5:HC128-SHA:RABBIT-SHA:AES128-CCM-8:AES256-CCM-8:ECDHE-ECDSA-" +"AES128-CCM:ECDHE-ECDSA-AES128-CCM-8:ECDHE-ECDSA-AES256-CCM-8:ECDHE-RSA-AES128-" +"SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-R" +"SA-RC4-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-ECDSA-DES-CBC3-SHA" +":AES128-SHA256:AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:ECDH-" +"RSA-AES128-SHA:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES128-SHA:ECDH-ECDSA-AES256-SHA" +":ECDH-RSA-RC4-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-RC4-SHA:ECDH-ECDSA-DES-CBC3" +"-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES" +"256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-E" +"CDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES128-GCM-SHA25" +"6:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-ECDSA-AES256-GC" +"M-SHA384:CAMELLIA128-SHA:DHE-RSA-CAMELLIA128-SHA:CAMELLIA256-SHA:DHE-RSA-CAMEL" +"LIA256-SHA:CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA256:CAMELLIA256-SHA256:DH" +"E-RSA-CAMELLIA256-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECD" +"H-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECD" +"SA-AES256-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDHE-RSA-CHA" +"CHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-R" +"SA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-PO" +"LY1305-OLD:IDEA-CBC-SHA:ECDHE-ECDSA-NULL-SHA:ECDHE-PSK-NULL-SHA256:ECDHE-PSK-A" +"ES128-CBC-SHA256:PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:DHE-PSK-CHA" +"CHA20-POLY1305:EDH-RSA-DES-CBC3-SHA:TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-S" +"HA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES128-CCM-SHA256:TLS13-AES128-CCM-" +"8-SHA256"; +#ifndef NO_RSA + testCertFile = svrCertFile; + testKeyFile = svrKeyFile; +#elif defined(HAVE_ECC) + testCertFile = eccCertFile; + testKeyFile = eccKeyFile; +#else + skipTest = 1; +#endif + + if (skipTest != 1) { +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#endif + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); + + AssertNotNull(ssl = wolfSSL_new(ctx)); + + /* First test freeing SSL, then CTX */ + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + wolfSSL_Cleanup(); + +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#endif + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); + + AssertNotNull(ssl = wolfSSL_new(ctx)); + + /* Next test freeing CTX then SSL */ + wolfSSL_CTX_free(ctx); + wolfSSL_free(ssl); + +#ifndef NO_WOLFSSL_SERVER + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#endif + /* Test setting ciphers at ctx level */ + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_set_cipher_list(ctx, optionsCiphers)); + AssertNotNull(ssl = wolfSSL_new(ctx)); + wolfSSL_CTX_free(ctx); + wolfSSL_free(ssl); + +#ifndef NO_WOLFSSL_CLIENT + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); +#else + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); +#endif + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, testCertFile, WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, testKeyFile, WOLFSSL_FILETYPE_PEM)); + AssertNotNull(ssl = wolfSSL_new(ctx)); + /* test setting ciphers at SSL level */ + AssertTrue(wolfSSL_set_cipher_list(ssl, optionsCiphers)); + wolfSSL_CTX_free(ctx); + wolfSSL_free(ssl); + } +} +#endif + static void test_wolfSSL_CTX_use_certificate_file(void) { @@ -23267,6 +23375,10 @@ void ApiTest(void) test_wolfSSL_Method_Allocators(); #ifndef NO_WOLFSSL_SERVER test_wolfSSL_CTX_new(wolfSSLv23_server_method()); +#endif +#if (!defined(NO_WOLFSSL_CLIENT) || !defined(NO_WOLFSSL_SERVER)) && \ +(!defined(NO_RSA) || defined(HAVE_ECC)) + test_for_double_Free(); #endif test_wolfSSL_CTX_use_certificate_file(); AssertIntEQ(test_wolfSSL_CTX_use_certificate_buffer(), WOLFSSL_SUCCESS); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 5d52e29ae8..e4746a4bfb 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3257,6 +3257,10 @@ typedef struct Options { word16 dhKeyTested:1; /* Set when key has been tested. */ #endif #endif +#ifdef SINGLE_THREADED + word16 ownSuites:1; /* if suites are malloced in ssl object */ +#endif + /* need full byte values for this section */ byte processReply; /* nonblocking resume */ byte cipherSuite0; /* first byte, normally 0 */