Skip to content

Commit 668efea

Browse files
authored
Merge pull request #5884 from icing/ssl-set-ssl-ctx
Fix wolfSSL_set_SSL_CTX() to be usable during handshake.
2 parents 908744d + 78fd5d7 commit 668efea

2 files changed

Lines changed: 154 additions & 2 deletions

File tree

src/ssl.c

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31987,9 +31987,68 @@ const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
3198731987

3198831988
WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
3198931989
{
31990-
if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == WOLFSSL_SUCCESS)
31990+
/* This method requires some explanation. Its sibling is
31991+
* int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
31992+
* which re-inits the WOLFSSL* with all settings in the new CTX.
31993+
* That one is the right one to use *before* a handshake is started.
31994+
*
31995+
* This method was added by OpenSSL to be used *during* the handshake, e.g.
31996+
* when a server inspects the SNI in a ClientHello callback and
31997+
* decides which set of certificates to use.
31998+
*
31999+
* Since, at the time the SNI callback is run, some decisions on
32000+
* Extensions or the ServerHello might already have been taken, this
32001+
* method is very restricted in what it does:
32002+
* - changing the server certificate(s)
32003+
* - changing the server id for session handling
32004+
* and everything else in WOLFSSL* needs to remain untouched.
32005+
*/
32006+
WOLFSSL_ENTER("wolfSSL_set_SSL_CTX");
32007+
if (ssl == NULL || ctx == NULL)
32008+
return NULL;
32009+
if (ssl->ctx == ctx)
3199132010
return ssl->ctx;
31992-
return NULL;
32011+
32012+
if (SSL_CTX_RefCount(ctx, 1) < 0) {
32013+
/* can only fail on serious stuff, like mutex not working
32014+
* or ctx refcount out of whack. */
32015+
return NULL;
32016+
}
32017+
if (ssl->ctx) {
32018+
wolfSSL_CTX_free(ssl->ctx);
32019+
}
32020+
ssl->ctx = ctx;
32021+
32022+
#ifndef NO_CERTS
32023+
/* ctx owns certificate, certChain and key */
32024+
ssl->buffers.certificate = ctx->certificate;
32025+
ssl->buffers.certChain = ctx->certChain;
32026+
#ifdef WOLFSSL_TLS13
32027+
ssl->buffers.certChainCnt = ctx->certChainCnt;
32028+
#endif
32029+
ssl->buffers.key = ctx->privateKey;
32030+
ssl->buffers.keyType = ctx->privateKeyType;
32031+
ssl->buffers.keyId = ctx->privateKeyId;
32032+
ssl->buffers.keyLabel = ctx->privateKeyLabel;
32033+
ssl->buffers.keySz = ctx->privateKeySz;
32034+
ssl->buffers.keyDevId = ctx->privateKeyDevId;
32035+
/* flags indicating what certs/keys are available */
32036+
ssl->options.haveRSA = ctx->haveRSA;
32037+
ssl->options.haveDH = ctx->haveDH;
32038+
ssl->options.haveECDSAsig = ctx->haveECDSAsig;
32039+
ssl->options.haveECC = ctx->haveECC;
32040+
ssl->options.haveStaticECC = ctx->haveStaticECC;
32041+
ssl->options.haveFalconSig = ctx->haveFalconSig;
32042+
ssl->options.haveDilithiumSig = ctx->haveDilithiumSig;
32043+
#endif
32044+
32045+
#ifdef OPENSSL_EXTRA
32046+
/* copy over application session context ID */
32047+
ssl->sessionCtxSz = ctx->sessionCtxSz;
32048+
XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz);
32049+
#endif
32050+
32051+
return ssl->ctx;
3199332052
}
3199432053

3199532054

tests/api.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57299,6 +57299,93 @@ static int test_wolfSSL_CTX_get_min_proto_version(void)
5729957299
return res;
5730057300
}
5730157301

57302+
#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
57303+
(defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
57304+
defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \
57305+
defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB)))
57306+
static int test_wolfSSL_set_SSL_CTX(void)
57307+
{
57308+
int res = TEST_SKIPPED;
57309+
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) \
57310+
&& !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_TLS13)
57311+
WOLFSSL_CTX *ctx1, *ctx2;
57312+
WOLFSSL *ssl;
57313+
const byte *session_id1 = (const byte *)"CTX1";
57314+
const byte *session_id2 = (const byte *)"CTX2";
57315+
57316+
AssertNotNull(ctx1 = wolfSSL_CTX_new(wolfTLS_server_method()));
57317+
AssertTrue(wolfSSL_CTX_use_certificate_file(ctx1, svrCertFile,
57318+
WOLFSSL_FILETYPE_PEM));
57319+
AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx1, svrKeyFile,
57320+
WOLFSSL_FILETYPE_PEM));
57321+
AssertIntEQ(wolfSSL_CTX_set_min_proto_version(ctx1, TLS1_2_VERSION),
57322+
WOLFSSL_SUCCESS);
57323+
AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx1), TLS1_2_VERSION);
57324+
AssertIntEQ(wolfSSL_CTX_get_max_proto_version(ctx1), TLS1_3_VERSION);
57325+
AssertIntEQ(wolfSSL_CTX_set_session_id_context(ctx1, session_id1, 4),
57326+
WOLFSSL_SUCCESS);
57327+
57328+
AssertNotNull(ctx2 = wolfSSL_CTX_new(wolfTLS_server_method()));
57329+
AssertTrue(wolfSSL_CTX_use_certificate_file(ctx2, svrCertFile,
57330+
WOLFSSL_FILETYPE_PEM));
57331+
AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx2, svrKeyFile,
57332+
WOLFSSL_FILETYPE_PEM));
57333+
AssertIntEQ(wolfSSL_CTX_set_min_proto_version(ctx2, TLS1_2_VERSION),
57334+
WOLFSSL_SUCCESS);
57335+
AssertIntEQ(wolfSSL_CTX_set_max_proto_version(ctx2, TLS1_2_VERSION),
57336+
WOLFSSL_SUCCESS);
57337+
AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx2), TLS1_2_VERSION);
57338+
AssertIntEQ(wolfSSL_CTX_get_max_proto_version(ctx2), TLS1_2_VERSION);
57339+
AssertIntEQ(wolfSSL_CTX_set_session_id_context(ctx2, session_id2, 4),
57340+
WOLFSSL_SUCCESS);
57341+
57342+
#ifdef HAVE_SESSION_TICKET
57343+
AssertIntEQ((wolfSSL_CTX_get_options(ctx1) & SSL_OP_NO_TICKET), 0);
57344+
wolfSSL_CTX_set_options(ctx2, SSL_OP_NO_TICKET);
57345+
AssertIntNE((wolfSSL_CTX_get_options(ctx2) & SSL_OP_NO_TICKET), 0);
57346+
#endif
57347+
57348+
AssertNotNull(ssl = wolfSSL_new(ctx2));
57349+
AssertIntNE((wolfSSL_get_options(ssl) & WOLFSSL_OP_NO_TLSv1_3), 0);
57350+
#ifdef WOLFSSL_INT_H
57351+
AssertIntEQ(XMEMCMP(ssl->sessionCtx, session_id2, 4), 0);
57352+
AssertTrue(ssl->buffers.certificate == ctx2->certificate);
57353+
AssertTrue(ssl->buffers.certChain == ctx2->certChain);
57354+
#endif
57355+
57356+
#ifdef HAVE_SESSION_TICKET
57357+
AssertIntNE((wolfSSL_get_options(ssl) & SSL_OP_NO_TICKET), 0);
57358+
#endif
57359+
57360+
/* Set the ctx1 that has TLSv1.3 as max proto version */
57361+
AssertNotNull(wolfSSL_set_SSL_CTX(ssl, ctx1));
57362+
57363+
/* MUST not change proto versions of ssl */
57364+
AssertIntNE((wolfSSL_get_options(ssl) & WOLFSSL_OP_NO_TLSv1_3), 0);
57365+
#ifdef HAVE_SESSION_TICKET
57366+
/* MUST not change */
57367+
AssertIntNE((wolfSSL_get_options(ssl) & SSL_OP_NO_TICKET), 0);
57368+
#endif
57369+
/* MUST change */
57370+
#ifdef WOLFSSL_INT_H
57371+
AssertTrue(ssl->buffers.certificate == ctx1->certificate);
57372+
AssertTrue(ssl->buffers.certChain == ctx1->certChain);
57373+
AssertIntEQ(XMEMCMP(ssl->sessionCtx, session_id1, 4), 0);
57374+
#endif
57375+
57376+
wolfSSL_free(ssl);
57377+
wolfSSL_CTX_free(ctx1);
57378+
wolfSSL_CTX_free(ctx2);
57379+
57380+
res = TEST_RES_CHECK(1);
57381+
#endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) */
57382+
return res;
57383+
}
57384+
#endif /* defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
57385+
(defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
57386+
defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \
57387+
defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) */
57388+
5730257389
static int test_wolfSSL_security_level(void)
5730357390
{
5730457391
int res = TEST_SKIPPED;
@@ -60062,6 +60149,12 @@ TEST_CASE testCases[] = {
6006260149
#endif
6006360150

6006460151
TEST_DECL(test_wolfSSL_CTX_get_min_proto_version),
60152+
#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
60153+
(defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
60154+
defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \
60155+
defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB)))
60156+
TEST_DECL(test_wolfSSL_set_SSL_CTX),
60157+
#endif
6006560158

6006660159
TEST_DECL(test_wolfSSL_security_level),
6006760160
TEST_DECL(test_wolfSSL_SSL_in_init),

0 commit comments

Comments
 (0)