Merge pull request #5884 from icing/ssl-set-ssl-ctx

Fix wolfSSL_set_SSL_CTX() to be usable during handshake.
This commit is contained in:
David Garske
2022-12-15 10:59:54 -08:00
committed by GitHub
2 changed files with 154 additions and 2 deletions

View File

@ -31987,9 +31987,68 @@ const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
{
if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == WOLFSSL_SUCCESS)
/* 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.
*/
WOLFSSL_ENTER("wolfSSL_set_SSL_CTX");
if (ssl == NULL || ctx == NULL)
return NULL;
if (ssl->ctx == ctx)
return ssl->ctx;
return NULL;
if (SSL_CTX_RefCount(ctx, 1) < 0) {
/* can only fail on serious stuff, like mutex not working
* or ctx refcount out of whack. */
return NULL;
}
if (ssl->ctx) {
wolfSSL_CTX_free(ssl->ctx);
}
ssl->ctx = ctx;
#ifndef NO_CERTS
/* ctx owns certificate, certChain and key */
ssl->buffers.certificate = ctx->certificate;
ssl->buffers.certChain = ctx->certChain;
#ifdef WOLFSSL_TLS13
ssl->buffers.certChainCnt = ctx->certChainCnt;
#endif
ssl->buffers.key = ctx->privateKey;
ssl->buffers.keyType = ctx->privateKeyType;
ssl->buffers.keyId = ctx->privateKeyId;
ssl->buffers.keyLabel = ctx->privateKeyLabel;
ssl->buffers.keySz = ctx->privateKeySz;
ssl->buffers.keyDevId = ctx->privateKeyDevId;
/* flags indicating what certs/keys are available */
ssl->options.haveRSA = ctx->haveRSA;
ssl->options.haveDH = ctx->haveDH;
ssl->options.haveECDSAsig = ctx->haveECDSAsig;
ssl->options.haveECC = ctx->haveECC;
ssl->options.haveStaticECC = ctx->haveStaticECC;
ssl->options.haveFalconSig = ctx->haveFalconSig;
ssl->options.haveDilithiumSig = ctx->haveDilithiumSig;
#endif
#ifdef OPENSSL_EXTRA
/* copy over application session context ID */
ssl->sessionCtxSz = ctx->sessionCtxSz;
XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz);
#endif
return ssl->ctx;
}

View File

@ -57299,6 +57299,93 @@ static int test_wolfSSL_CTX_get_min_proto_version(void)
return res;
}
#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
(defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \
defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB)))
static int test_wolfSSL_set_SSL_CTX(void)
{
int res = TEST_SKIPPED;
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) \
&& !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_TLS13)
WOLFSSL_CTX *ctx1, *ctx2;
WOLFSSL *ssl;
const byte *session_id1 = (const byte *)"CTX1";
const byte *session_id2 = (const byte *)"CTX2";
AssertNotNull(ctx1 = wolfSSL_CTX_new(wolfTLS_server_method()));
AssertTrue(wolfSSL_CTX_use_certificate_file(ctx1, svrCertFile,
WOLFSSL_FILETYPE_PEM));
AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx1, svrKeyFile,
WOLFSSL_FILETYPE_PEM));
AssertIntEQ(wolfSSL_CTX_set_min_proto_version(ctx1, TLS1_2_VERSION),
WOLFSSL_SUCCESS);
AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx1), TLS1_2_VERSION);
AssertIntEQ(wolfSSL_CTX_get_max_proto_version(ctx1), TLS1_3_VERSION);
AssertIntEQ(wolfSSL_CTX_set_session_id_context(ctx1, session_id1, 4),
WOLFSSL_SUCCESS);
AssertNotNull(ctx2 = wolfSSL_CTX_new(wolfTLS_server_method()));
AssertTrue(wolfSSL_CTX_use_certificate_file(ctx2, svrCertFile,
WOLFSSL_FILETYPE_PEM));
AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx2, svrKeyFile,
WOLFSSL_FILETYPE_PEM));
AssertIntEQ(wolfSSL_CTX_set_min_proto_version(ctx2, TLS1_2_VERSION),
WOLFSSL_SUCCESS);
AssertIntEQ(wolfSSL_CTX_set_max_proto_version(ctx2, TLS1_2_VERSION),
WOLFSSL_SUCCESS);
AssertIntEQ(wolfSSL_CTX_get_min_proto_version(ctx2), TLS1_2_VERSION);
AssertIntEQ(wolfSSL_CTX_get_max_proto_version(ctx2), TLS1_2_VERSION);
AssertIntEQ(wolfSSL_CTX_set_session_id_context(ctx2, session_id2, 4),
WOLFSSL_SUCCESS);
#ifdef HAVE_SESSION_TICKET
AssertIntEQ((wolfSSL_CTX_get_options(ctx1) & SSL_OP_NO_TICKET), 0);
wolfSSL_CTX_set_options(ctx2, SSL_OP_NO_TICKET);
AssertIntNE((wolfSSL_CTX_get_options(ctx2) & SSL_OP_NO_TICKET), 0);
#endif
AssertNotNull(ssl = wolfSSL_new(ctx2));
AssertIntNE((wolfSSL_get_options(ssl) & WOLFSSL_OP_NO_TLSv1_3), 0);
#ifdef WOLFSSL_INT_H
AssertIntEQ(XMEMCMP(ssl->sessionCtx, session_id2, 4), 0);
AssertTrue(ssl->buffers.certificate == ctx2->certificate);
AssertTrue(ssl->buffers.certChain == ctx2->certChain);
#endif
#ifdef HAVE_SESSION_TICKET
AssertIntNE((wolfSSL_get_options(ssl) & SSL_OP_NO_TICKET), 0);
#endif
/* Set the ctx1 that has TLSv1.3 as max proto version */
AssertNotNull(wolfSSL_set_SSL_CTX(ssl, ctx1));
/* MUST not change proto versions of ssl */
AssertIntNE((wolfSSL_get_options(ssl) & WOLFSSL_OP_NO_TLSv1_3), 0);
#ifdef HAVE_SESSION_TICKET
/* MUST not change */
AssertIntNE((wolfSSL_get_options(ssl) & SSL_OP_NO_TICKET), 0);
#endif
/* MUST change */
#ifdef WOLFSSL_INT_H
AssertTrue(ssl->buffers.certificate == ctx1->certificate);
AssertTrue(ssl->buffers.certChain == ctx1->certChain);
AssertIntEQ(XMEMCMP(ssl->sessionCtx, session_id1, 4), 0);
#endif
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx1);
wolfSSL_CTX_free(ctx2);
res = TEST_RES_CHECK(1);
#endif /* defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) */
return res;
}
#endif /* defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
(defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \
defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) */
static int test_wolfSSL_security_level(void)
{
int res = TEST_SKIPPED;
@ -60062,6 +60149,12 @@ TEST_CASE testCases[] = {
#endif
TEST_DECL(test_wolfSSL_CTX_get_min_proto_version),
#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \
(defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \
defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB)))
TEST_DECL(test_wolfSSL_set_SSL_CTX),
#endif
TEST_DECL(test_wolfSSL_security_level),
TEST_DECL(test_wolfSSL_SSL_in_init),