Skip to content

Commit

Permalink
openssl compat: match openssl status cb behaviour for stapling
Browse files Browse the repository at this point in the history
On the server side, OpenSSL offloads the creation and the verification of
the ocsp response to staple to the user application. This commit moves
the invocation point of the StatusCB so that wolfSSL doesn't try to
verify the response and/or the server certificate.
  • Loading branch information
rizlik committed Oct 2, 2024
1 parent cde6cbb commit 0c707be
Show file tree
Hide file tree
Showing 5 changed files with 330 additions and 26 deletions.
51 changes: 51 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -8730,6 +8730,12 @@ void FreeHandshakeResources(WOLFSSL* ssl)
* !WOLFSSL_POST_HANDSHAKE_AUTH */
#endif /* HAVE_TLS_EXTENSIONS && !NO_TLS */

#ifdef OPENSSL_EXTRA
if (ssl->ocspResp != NULL)
XFREE(ssl->ocspResp, NULL, 0);
ssl->ocspResp = NULL;
#endif

#ifdef WOLFSSL_STATIC_MEMORY
/* when done with handshake decrement current handshake count */
if (ssl->heap != NULL) {
Expand Down Expand Up @@ -24158,6 +24164,43 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
return ret;
}
#endif

#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
(defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA))
static int BuildCertificateStatusWithStatusCB(WOLFSSL* ssl)
{
WOLFSSL_OCSP *ocsp;
void *ioCtx = NULL;
buffer response;
int ret;

ocsp = SSL_CM(ssl)->ocsp_stapling;
if (ocsp == NULL || ocsp->statusCb == NULL)
return BAD_FUNC_ARG;
ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
XMEMSET(&response, 0, sizeof(response));
WOLFSSL_MSG("Calling ocsp->statusCb");
ret = ocsp->statusCb(ssl, ioCtx);
switch (ret) {
case SSL_TLSEXT_ERR_OK:
response.buffer = ssl->ocspResp;
response.length = ssl->ocspRespSz;
ret = BuildCertificateStatus(ssl, WOLFSSL_CSR_OCSP, &response, 1);
break;
case SSL_TLSEXT_ERR_NOACK:
/* No OCSP response to send */
ret = 0;
break;
case SSL_TLSEXT_ERR_ALERT_FATAL:
/* fall through */
default:
ret = WOLFSSL_FATAL_ERROR;
break;
}
return ret;
}
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)) */
#endif /* NO_WOLFSSL_SERVER */

/* handle generation of certificate_status (22) */
Expand All @@ -24179,6 +24222,14 @@ int SendCertificateStatus(WOLFSSL* ssl)
status_type = status_type ? status_type : ssl->status_request_v2;
#endif

#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
(defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA))
if (ssl != NULL && SSL_CM(ssl) != NULL && SSL_CM(ssl)->ocsp_stapling != NULL && SSL_CM(ssl)->ocsp_stapling->statusCb != NULL) {
if (ssl->status_request == WOLFSSL_CSR_OCSP)
return BuildCertificateStatusWithStatusCB(ssl);
}
#endif

switch (status_type) {

#ifndef NO_WOLFSSL_SERVER
Expand Down
25 changes: 0 additions & 25 deletions src/ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,31 +480,6 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest,
ioCtx = (ssl && ssl->ocspIOCtx != NULL) ?
ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;

#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
if (ocsp->statusCb != NULL && ssl != NULL) {
WOLFSSL_MSG("Calling ocsp->statusCb");
ret = ocsp->statusCb(ssl, ioCtx);
switch (ret) {
case SSL_TLSEXT_ERR_OK:
ret = wolfSSL_get_ocsp_response(ssl, &response);
ret = CheckOcspResponse(ocsp, response, ret, responseBuffer,
status, entry, NULL, heap);
XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
break;
case SSL_TLSEXT_ERR_NOACK:
ret = OCSP_LOOKUP_FAIL;
break;
case SSL_TLSEXT_ERR_ALERT_FATAL:
default:
WOLFSSL_LEAVE("CheckOcspRequest", ocsp->error);
ret = WOLFSSL_FATAL_ERROR;
break;
}
WOLFSSL_LEAVE("CheckOcspRequest", ret);
return ret;
}
#endif

if (ocsp->cm->ocspUseOverrideURL) {
url = ocsp->cm->ocspOverrideURL;
if (url != NULL && url[0] != '\0')
Expand Down
2 changes: 2 additions & 0 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -16410,6 +16410,8 @@ long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp,
if (s == NULL)
return WOLFSSL_FAILURE;

if (s->ocspResp)
XFREE(s->ocspResp, NULL, 0);
s->ocspResp = resp;
s->ocspRespSz = len;

Expand Down
88 changes: 87 additions & 1 deletion src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -3215,13 +3215,80 @@ static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
}
#endif
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
if (!isRequest && csr->ssl->options.tls1_3)
if (!isRequest && csr->ssl->options.tls1_3) {
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
if (csr->ssl != NULL && SSL_CM(csr->ssl) != NULL && SSL_CM(csr->ssl)->ocsp_stapling != NULL
&& SSL_CM(csr->ssl)->ocsp_stapling->statusCb != NULL) {
return OPAQUE8_LEN + OPAQUE24_LEN + csr->ssl->ocspRespSz;
}
#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA */
return OPAQUE8_LEN + OPAQUE24_LEN + csr->response.length;
}
#endif

return size;
}

#if (defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA))
static int TLSX_CSR_SetResponseWithStatusCB(WOLFSSL *ssl)
{
void *ioCtx = NULL;
WOLFSSL_OCSP *ocsp;
int ret;

if (ssl == NULL || SSL_CM(ssl) == NULL)
return BAD_FUNC_ARG;
ocsp = SSL_CM(ssl)->ocsp_stapling;
if (ocsp == NULL || ocsp->statusCb == NULL)
return BAD_FUNC_ARG;
ioCtx = (ssl->ocspIOCtx != NULL) ? ssl->ocspIOCtx : ocsp->cm->ocspIOCtx;
ret = ocsp->statusCb(ssl, ioCtx);
switch (ret) {
case SSL_TLSEXT_ERR_OK:
if (ssl->ocspRespSz > 0) {
/* ack the extension, status cb provided the response in ssl->ocspResp */
TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST);
ssl->status_request = WOLFSSL_CSR_OCSP;
}
ret = 0;
break;
case SSL_TLSEXT_ERR_NOACK:
/* suppressing as not critical */
ret = 0;
break;
case SSL_TLSEXT_ERR_ALERT_FATAL:
default:
ret = WOLFSSL_FATAL_ERROR;
break;
}
return ret;
}

static int TLSX_CSR_WriteWithStatusCB(CertificateStatusRequest* csr, byte* output)
{
WOLFSSL *ssl = csr->ssl;
WOLFSSL_OCSP *ocsp;
word16 offset = 0;
byte *response;
int respSz;

response = ssl->ocspResp;
respSz = ssl->ocspRespSz;
if (ssl == NULL || SSL_CM(ssl) == NULL)
return BAD_FUNC_ARG;
ocsp = SSL_CM(ssl)->ocsp_stapling;
if (ocsp == NULL || ocsp->statusCb == NULL)
return BAD_FUNC_ARG;
if (respSz == 0)
return BAD_FUNC_ARG;
output[offset++] = WOLFSSL_CSR_OCSP;
c32to24(respSz, output + offset);
offset += OPAQUE24_LEN;
XMEMCPY(output + offset, response, respSz);
return offset + respSz;
}
#endif /* (TLS13 && !NO_WOLFSLL_SERVER) && (OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA) */

static int TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
byte isRequest)
{
Expand Down Expand Up @@ -3268,6 +3335,12 @@ static int TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
#endif
#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
if (!isRequest && csr->ssl->options.tls1_3) {
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
if (csr->ssl != NULL && SSL_CM(csr->ssl) != NULL && SSL_CM(csr->ssl)->ocsp_stapling != NULL
&& SSL_CM(csr->ssl)->ocsp_stapling->statusCb != NULL) {
return TLSX_CSR_WriteWithStatusCB(csr, output);
}
#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || defined(OPENSSL_EXTRA) */
word16 offset = 0;
output[offset++] = csr->status_type;
c32to24(csr->response.length, output + offset);
Expand Down Expand Up @@ -3445,6 +3518,12 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length,

#if defined(WOLFSSL_TLS13)
if (ssl->options.tls1_3) {
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
if (ssl != NULL && SSL_CM(ssl) != NULL && SSL_CM(ssl)->ocsp_stapling != NULL
&& SSL_CM(ssl)->ocsp_stapling->statusCb != NULL) {
return TLSX_CSR_SetResponseWithStatusCB(ssl);
}
#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || defined(OPENSSL_EXTRA) */
if (ssl->buffers.certificate == NULL) {
WOLFSSL_MSG("Certificate buffer not set!");
return BUFFER_ERROR;
Expand Down Expand Up @@ -3894,6 +3973,13 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, const byte* input, word16 length,
continue;
}

#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA)
/* OpenSSL status CB supports only CERTIFICATE STATUS REQ V1 */
if (ssl != NULL && SSL_CM(ssl) != NULL && SSL_CM(ssl)->ocsp_stapling != NULL &&
SSL_CM(ssl)->ocsp_stapling->statusCb != NULL) {
return 0;
}
#endif
/* if using status_request and already sending it, remove it
* and prefer to use the v2 version */
#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
Expand Down
Loading

0 comments on commit 0c707be

Please sign in to comment.