From ef500c2e6222209b2559c8e6938a00badb2d52c9 Mon Sep 17 00:00:00 2001 From: Colton Willey Date: Tue, 13 Aug 2024 13:32:25 -0700 Subject: [PATCH] Add new option to always copy cert buffer for each SSL object --- src/internal.c | 30 ++++++++++++++++++++++++++++++ src/ssl.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/ssl_load.c | 11 +++++++++++ tests/api.c | 18 ++++++++++++++++++ 4 files changed, 99 insertions(+) diff --git a/src/internal.c b/src/internal.c index b08e6f7715..5ae5382d34 100644 --- a/src/internal.c +++ b/src/internal.c @@ -6803,9 +6803,39 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #endif /* HAVE_RPK */ #ifndef NO_CERTS +#ifdef WOLFSSL_COPY_CERT + /* If WOLFSSL_COPY_CERT is defined, always copy the cert */ + if (ctx->certificate != NULL) { + if (ssl->buffers.certificate != NULL) { + FreeDer(&ssl->buffers.certificate); + } + ret = AllocCopyDer(&ssl->buffers.certificate, ctx->certificate->buffer, + ctx->certificate->length, ctx->certificate->type, + ctx->certificate->heap); + if (ret != 0) { + return ret; + } + + ret = WOLFSSL_SUCCESS; + } + if (ctx->certChain != NULL) { + if (ssl->buffers.certChain != NULL) { + FreeDer(&ssl->buffers.certChain); + } + ret = AllocCopyDer(&ssl->buffers.certChain, ctx->certChain->buffer, + ctx->certChain->length, ctx->certChain->type, + ctx->certChain->heap); + if (ret != 0) { + return ret; + } + + ret = WOLFSSL_SUCCESS; + } +#else /* ctx still owns certificate, certChain, key, dh, and cm */ ssl->buffers.certificate = ctx->certificate; ssl->buffers.certChain = ctx->certChain; +#endif #ifdef WOLFSSL_TLS13 ssl->buffers.certChainCnt = ctx->certChainCnt; #endif diff --git a/src/ssl.c b/src/ssl.c index afd505027a..a0f377bb9b 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -10806,6 +10806,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return BAD_FUNC_ARG; } + #ifdef WOLFSSL_COPY_CERT + /* If WOLFSSL_COPY_CERT defined, always free cert buffers in SSL obj */ + FreeDer(&ssl->buffers.certificate); + FreeDer(&ssl->buffers.certChain); + #endif if (ssl->buffers.weOwnCert && !ssl->keepCert) { WOLFSSL_MSG("Unloading cert"); FreeDer(&ssl->buffers.certificate); @@ -19549,6 +19554,11 @@ void wolfSSL_certs_clear(WOLFSSL* ssl) /* ctx still owns certificate, certChain, key, dh, and cm */ if (ssl->buffers.weOwnCert) FreeDer(&ssl->buffers.certificate); +#ifdef WOLFSSL_COPY_CERT + /* If WOLFSSL_COPY_CERT defined, always free cert buffers in SSL obj */ + FreeDer(&ssl->buffers.certificate); + FreeDer(&ssl->buffers.certChain); +#endif ssl->buffers.certificate = NULL; if (ssl->buffers.weOwnCertChain) FreeDer(&ssl->buffers.certChain); @@ -20151,9 +20161,39 @@ WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->ctx = ctx; #ifndef NO_CERTS +#ifdef WOLFSSL_COPY_CERT + /* If WOLFSSL_COPY_CERT defined, always make new copy of cert */ + if (ctx->certificate != NULL) { + if (ssl->buffers.certificate != NULL) { + FreeDer(&ssl->buffers.certificate); + } + ret = AllocCopyDer(&ssl->buffers.certificate, ctx->certificate->buffer, + ctx->certificate->length, ctx->certificate->type, + ctx->certificate->heap); + if (ret != 0) { + return NULL; + } + + ret = WOLFSSL_SUCCESS; + } + if (ctx->certChain != NULL) { + if (ssl->buffers.certChain != NULL) { + FreeDer(&ssl->buffers.certChain); + } + ret = AllocCopyDer(&ssl->buffers.certChain, ctx->certChain->buffer, + ctx->certChain->length, ctx->certChain->type, + ctx->certChain->heap); + if (ret != 0) { + return NULL; + } + + ret = WOLFSSL_SUCCESS; + } +#else /* ctx owns certificate, certChain and key */ ssl->buffers.certificate = ctx->certificate; ssl->buffers.certChain = ctx->certChain; +#endif #ifdef WOLFSSL_TLS13 ssl->buffers.certChainCnt = ctx->certChainCnt; #endif diff --git a/src/ssl_load.c b/src/ssl_load.c index da4279e39e..ee11273bf3 100644 --- a/src/ssl_load.c +++ b/src/ssl_load.c @@ -236,6 +236,9 @@ static int ProcessUserChainRetain(WOLFSSL_CTX* ctx, WOLFSSL* ssl, /* Store in SSL object if available. */ if (ssl != NULL) { /* Dispose of old chain if not reference to context's. */ + #ifdef WOLFSSL_COPY_CERT + FreeDer(&ssl->buffers.certChain); + #endif if (ssl->buffers.weOwnCertChain) { FreeDer(&ssl->buffers.certChain); } @@ -2079,6 +2082,10 @@ static int ProcessBufferCertHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, /* Leaf certificate - our certificate. */ else if (type == CERT_TYPE) { if (ssl != NULL) { +#ifdef WOLFSSL_COPY_CERT + /* Always Free previously set if WOLFSSL_COPY_CERT defined */ + FreeDer(&ssl->buffers.certificate); +#endif /* Free previous certificate if we own it. */ if (ssl->buffers.weOwnCert) { FreeDer(&ssl->buffers.certificate); @@ -4560,6 +4567,10 @@ static int wolfssl_add_to_chain(DerBuffer** chain, int weOwn, const byte* cert, c32to24(certSz, newChain->buffer + len); XMEMCPY(newChain->buffer + len + CERT_HEADER_SZ, cert, certSz); +#ifdef WOLFSSL_COPY_CERT + FreeDer(chain); +#endif + /* Dispose of old chain if we own it. */ if (weOwn) { FreeDer(chain); diff --git a/tests/api.c b/tests/api.c index 39b9933c09..c7fb37b9b4 100644 --- a/tests/api.c +++ b/tests/api.c @@ -77291,9 +77291,18 @@ static int test_wolfSSL_set_SSL_CTX(void) #ifdef WOLFSSL_SESSION_ID_CTX ExpectIntEQ(XMEMCMP(ssl->sessionCtx, session_id2, 4), 0); #endif +#ifdef WOLFSSL_COPY_CERT + if (ctx2->certificate != NULL) { + ExpectFalse(ssl->buffers.certificate == ctx2->certificate); + } + if (ctx2->certChain != NULL) { + ExpectFalse(ssl->buffers.certChain == ctx2->certChain); + } +#else ExpectTrue(ssl->buffers.certificate == ctx2->certificate); ExpectTrue(ssl->buffers.certChain == ctx2->certChain); #endif +#endif #ifdef HAVE_SESSION_TICKET ExpectIntNE((wolfSSL_get_options(ssl) & SSL_OP_NO_TICKET), 0); @@ -77310,8 +77319,17 @@ static int test_wolfSSL_set_SSL_CTX(void) #endif /* MUST change */ #ifdef WOLFSSL_INT_H +#ifdef WOLFSSL_COPY_CERT + if (ctx1->certificate != NULL) { + ExpectFalse(ssl->buffers.certificate == ctx1->certificate); + } + if (ctx1->certChain != NULL) { + ExpectFalse(ssl->buffers.certChain == ctx1->certChain); + } +#else ExpectTrue(ssl->buffers.certificate == ctx1->certificate); ExpectTrue(ssl->buffers.certChain == ctx1->certChain); +#endif #ifdef WOLFSSL_SESSION_ID_CTX ExpectIntEQ(XMEMCMP(ssl->sessionCtx, session_id1, 4), 0); #endif