From 67863917806364eaf120ff8689eb42c7e070c655 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Wed, 2 Oct 2024 11:35:11 +0000 Subject: [PATCH] openssl compat: match openssl status cb behaviour for stapling 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. --- src/internal.c | 51 ++++++++++++++ src/ocsp.c | 25 ------- src/ssl.c | 2 + src/tls.c | 88 ++++++++++++++++++++++- tests/api.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 325 insertions(+), 26 deletions(-) diff --git a/src/internal.c b/src/internal.c index c66dfc4a35..c1373ba092 100644 --- a/src/internal.c +++ b/src/internal.c @@ -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) { @@ -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) */ @@ -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 diff --git a/src/ocsp.c b/src/ocsp.c index 41c038fd12..418544113f 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -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') diff --git a/src/ssl.c b/src/ssl.c index e4aecb0e84..33b874d064 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -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; diff --git a/src/tls.c b/src/tls.c index 039096967e..4733983f9b 100644 --- a/src/tls.c +++ b/src/tls.c @@ -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) { @@ -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); @@ -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; @@ -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 diff --git a/tests/api.c b/tests/api.c index 4821345cff..a955caec0a 100644 --- a/tests/api.c +++ b/tests/api.c @@ -95693,6 +95693,190 @@ static int test_ocsp_callback_fails(void) defined(HAVE_CERTIFICATE_STATUS_REQUEST) */ +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(HAVE_OCSP) && \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \ + !defined(WOLFSSL_NO_TLS12) && \ + (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) + +struct _test_ocsp_status_callback_ctx { + byte *ocsp_resp; + int ocsp_resp_sz; + int invoked; +}; + +static int test_ocsp_status_callback_cb(WOLFSSL *ssl, void *ctx) +{ + struct _test_ocsp_status_callback_ctx *_ctx = (struct _test_ocsp_status_callback_ctx*)ctx; + + _ctx->invoked++; + SSL_set_tlsext_status_ocsp_resp(ssl, _ctx->ocsp_resp, _ctx->ocsp_resp_sz); + return SSL_TLSEXT_ERR_OK; +} + +static int test_ocsp_status_callback_cb_noack(WOLFSSL *ssl, void *ctx) +{ + struct _test_ocsp_status_callback_ctx *_ctx = (struct _test_ocsp_status_callback_ctx*)ctx; + (void)ssl; + + _ctx->invoked++; + return SSL_TLSEXT_ERR_NOACK; +} + +static int test_ocsp_status_callback_cb_err(WOLFSSL *ssl, void *ctx) +{ + struct _test_ocsp_status_callback_ctx *_ctx = (struct _test_ocsp_status_callback_ctx*)ctx; + (void)ssl; + + _ctx->invoked++; + return SSL_TLSEXT_ERR_ALERT_FATAL; +} + +static int test_ocsp_status_callback_test_setup(struct _test_ocsp_status_callback_ctx *cb_ctx, + struct test_ssl_memio_ctx *test_ctx, method_provider cm, method_provider sm) +{ + int ret; + + cb_ctx->invoked = 0; + XMEMSET(test_ctx, 0, sizeof(*test_ctx)); + test_ctx->c_cb.caPemFile = "./certs/ocsp/root-ca-cert.pem"; + test_ctx->s_cb.certPemFile = "./certs/ocsp/server1-cert.pem"; + test_ctx->s_cb.keyPemFile = "./certs/ocsp/server1-key.pem"; + test_ctx->c_cb.method = cm; + test_ctx->s_cb.method = sm; + ret = test_ssl_memio_setup(test_ctx); + wolfSSL_set_verify(test_ctx->c_ssl, WOLFSSL_VERIFY_DEFAULT, NULL); + return ret; +} + +static int test_ocsp_status_callback(void) +{ + struct test_params { + method_provider c_method; + method_provider s_method; + }; + + const char* responseFile = "./certs/ocsp/test-leaf-response.der"; + struct _test_ocsp_status_callback_ctx cb_ctx; + struct test_ssl_memio_ctx test_ctx; + int enable_client_ocsp; + int enable_must_staple; + byte data[4096]; + unsigned int i; + EXPECT_DECLS; + + struct test_params params[] = { + { wolfTLSv1_2_client_method, wolfTLSv1_2_server_method }, +#if defined(WOLFSSL_TLS13) + { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method }, +#endif +#if defined(WOLFSSL_DTLS) + { wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method }, +#endif +#if defined(WOLFSSL_DTLS13) + { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method }, +#endif + }; + + XMEMSET(&cb_ctx, 0, sizeof(cb_ctx)); + XFILE f = XBADFILE; + f = XFOPEN(responseFile, "rb"); + if (f == XBADFILE) + return -1; + cb_ctx.ocsp_resp_sz = (word32)XFREAD(data, 1, 4096, f); + if (f != XBADFILE) { + XFCLOSE(f); + f = XBADFILE; + } + cb_ctx.ocsp_resp = data; + + for (i = 0; i < sizeof(params)/sizeof(params[0]); i++) { + for (enable_client_ocsp = 0; enable_client_ocsp <= 1; enable_client_ocsp++) { + ExpectIntEQ(test_ocsp_status_callback_test_setup(&cb_ctx, + &test_ctx, params[i].c_method, params[i].s_method), TEST_SUCCESS); + ExpectIntEQ(SSL_CTX_set_tlsext_status_cb(test_ctx.s_ctx, test_ocsp_status_callback_cb), SSL_SUCCESS); + ExpectIntEQ(SSL_CTX_set_tlsext_status_arg(test_ctx.s_ctx, (void*)&cb_ctx), SSL_SUCCESS); + if (enable_client_ocsp) { + ExpectIntEQ(wolfSSL_UseOCSPStapling(test_ctx.c_ssl, WOLFSSL_CSR_OCSP, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.c_ctx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableOCSPMustStaple(test_ctx.c_ctx), WOLFSSL_SUCCESS); + } + ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); + ExpectIntEQ(cb_ctx.invoked, enable_client_ocsp ? 1 : 0); + test_ssl_memio_cleanup(&test_ctx); + if (!EXPECT_SUCCESS()) + return EXPECT_RESULT(); + } + } +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + /* test client sending both OCSPv1 and OCSPv2/MultiOCSP */ + /* StatusCb only supports OCSPv1 */ + ExpectIntEQ(test_ocsp_status_callback_test_setup(&cb_ctx, &test_ctx, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), TEST_SUCCESS); + ExpectIntEQ(SSL_CTX_set_tlsext_status_cb(test_ctx.s_ctx, test_ocsp_status_callback_cb), SSL_SUCCESS); + ExpectIntEQ(SSL_CTX_set_tlsext_status_arg(test_ctx.s_ctx, (void*)&cb_ctx), SSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.c_ctx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableOCSPMustStaple(test_ctx.c_ctx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_UseOCSPStapling(test_ctx.c_ssl, WOLFSSL_CSR_OCSP, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_UseOCSPStaplingV2(test_ctx.c_ssl, WOLFSSL_CSR2_OCSP_MULTI, 0), WOLFSSL_SUCCESS); + wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_DEFAULT, NULL); + ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); + ExpectIntEQ(cb_ctx.invoked, 1); + test_ssl_memio_cleanup(&test_ctx); + + if (!EXPECT_SUCCESS()) + return EXPECT_RESULT(); +#endif /* defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) */ + /* test cb returning NO_ACK, not acking the OCSP */ + for (i = 0; i < sizeof(params)/sizeof(params[0]); i++) { + for (enable_must_staple = 0; enable_must_staple <= 1; enable_must_staple++) { + ExpectIntEQ(test_ocsp_status_callback_test_setup(&cb_ctx, &test_ctx, params[i].c_method, params[i].s_method), TEST_SUCCESS); + ExpectIntEQ(SSL_CTX_set_tlsext_status_cb(test_ctx.s_ctx, test_ocsp_status_callback_cb_noack), SSL_SUCCESS); + ExpectIntEQ(SSL_CTX_set_tlsext_status_arg(test_ctx.s_ctx, (void*)&cb_ctx), SSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.c_ctx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_UseOCSPStapling(test_ctx.c_ssl, WOLFSSL_CSR_OCSP, 0), WOLFSSL_SUCCESS); + if (enable_must_staple) + ExpectIntEQ(wolfSSL_CTX_EnableOCSPMustStaple(test_ctx.c_ctx), WOLFSSL_SUCCESS); + wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_DEFAULT, NULL); + ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), enable_must_staple ? TEST_FAIL : TEST_SUCCESS); + ExpectIntEQ(cb_ctx.invoked, 1); + test_ssl_memio_cleanup(&test_ctx); + if (!EXPECT_SUCCESS()) + return EXPECT_RESULT(); + } + } + + /* test cb returning err aborting handshake */ + for (i = 0; i < sizeof(params)/sizeof(params[0]); i++) { + for (enable_client_ocsp = 0; enable_client_ocsp <= 1; enable_client_ocsp++) { + ExpectIntEQ(test_ocsp_status_callback_test_setup(&cb_ctx, &test_ctx, params[i].c_method, params[i].s_method), TEST_SUCCESS); + ExpectIntEQ(SSL_CTX_set_tlsext_status_cb(test_ctx.s_ctx, test_ocsp_status_callback_cb_err), SSL_SUCCESS); + ExpectIntEQ(SSL_CTX_set_tlsext_status_arg(test_ctx.s_ctx, (void*)&cb_ctx), SSL_SUCCESS); + if (enable_client_ocsp) + ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.c_ctx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_UseOCSPStapling(test_ctx.c_ssl, WOLFSSL_CSR_OCSP, 0), WOLFSSL_SUCCESS); + wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_DEFAULT, NULL); + ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), enable_client_ocsp ? TEST_FAIL : TEST_SUCCESS); + ExpectIntEQ(cb_ctx.invoked, enable_client_ocsp ? 1: 0); + test_ssl_memio_cleanup(&test_ctx); + if (!EXPECT_SUCCESS()) + return EXPECT_RESULT(); + } + } + + return EXPECT_RESULT(); +} + +#else +static int test_ocsp_status_callback(void) +{ + return TEST_SKIPPED; +} +#endif /* defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(HAVE_OCSP) && \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \ + !defined(WOLFSSL_NO_TLS12) && \ + (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) */ + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -96945,6 +97129,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_UseOCSPStaplingV2), TEST_DECL(test_self_signed_stapling), TEST_DECL(test_ocsp_callback_fails), + TEST_DECL(test_ocsp_status_callback), /* Multicast */ TEST_DECL(test_wolfSSL_mcast),