Skip to content

Commit 78fd5d7

Browse files
committed
Fix wolfSSL_set_SSL_CTX() to be usable during handshake.
This method requires some explanation. Its sibling is int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) which re-inits the WOLFSSL* with all settings in the new CTX. That one is the right one to use *before* a handshake is started. This method was added by OpenSSL to be used *during* the handshake, e.g. when a server inspects the SNI in a ClientHello callback and decides which set of certificates to use. Since, at the time the SNI callback is run, some decisions on Extensions or the ServerHello might already have been taken, this method is very restricted in what it does: - changing the server certificate(s) - changing the server id for session handling and everything else in WOLFSSL* needs to remain untouched.
1 parent a3f3c76 commit 78fd5d7

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)