Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/scripts/zephyr-4.x/builds.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
native_sim samples/wolfssl_tls_sock
native_sim samples/wolfssl_tls_sock external_libc.conf
native_sim samples/wolfssl_tls_sock tls_cert.conf
native_sim samples/wolfssl_tls_sock ocsp.conf
native_sim samples/wolfssl_test
native_sim samples/wolfssl_test external_libc.conf
native_sim samples/wolfssl_benchmark
Expand Down
3 changes: 3 additions & 0 deletions .github/scripts/zephyr-4.x/ocsp.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# OCSP and stapling
CONFIG_WOLFSSL_OCSP=y
CONFIG_WOLFSSL_OCSP_STAPLING=y
2 changes: 2 additions & 0 deletions doc/dox_comments/header_files-ja/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4869,6 +4869,8 @@ int wolfSSL_set_tlsext_status_ocsp_resp_multi(WOLFSSL* ssl, unsigned char *resp,

\brief OCSPステータスレスポンスを検証するコールバックを設定します。

クライアントは処理するステープルOCSPレスポンスごとに、デコードできないものも含めてこのコールバックを呼び出します。クライアント証明書を検証するTLS 1.3サーバーも同様です。errにはライブラリの判定結果(0または負のエラーコード)が渡されます。証明書チェーンの処理は最初に失敗したレスポンスで停止するため、それ以降のレスポンスは渡されません。戻り値がerrを置き換えます。0はレスポンスを受け入れ、負の値はハンドシェイクを失敗させ、正の値はBAD_CERTIFICATE_STATUS_ERRORとして扱われます。

OCSP検証中にピアの証明書チェーンにアクセスできるようにするため、SESSION_CERTSを有効にすることを推奨します。

\param ctx WOLFSSL_CTXオブジェクト。
Expand Down
9 changes: 9 additions & 0 deletions doc/dox_comments/header_files/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -6611,6 +6611,15 @@ int wolfSSL_set_tlsext_status_ocsp_resp_multi(WOLFSSL* ssl, unsigned char *resp,

\brief Sets a callback to verify the OCSP status response.

The client calls it for each stapled OCSP response it processes, as does a
TLS 1.3 server checking the client's certificate, including a response
that does not decode. err holds the library's result (0 or a negative
error code). Processing of a certificate chain stops at the first
response that fails, so later responses are not passed to it. The return
value replaces err: 0 accepts the response, a negative value fails the
handshake, and a positive value is treated as
BAD_CERTIFICATE_STATUS_ERROR.

It is recommended to enable SESSION_CERTS in order to have access to the
peer's certificate chain during OCSP verification.

Expand Down
14 changes: 5 additions & 9 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -16596,7 +16596,6 @@ int CsrDoChainFallbackLookup(WOLFSSL* ssl, OcspRequest* request, int idx)
(defined(HAVE_OCSP) && defined(WOLFSSL_TLS13) && \
defined(HAVE_CERTIFICATE_STATUS_REQUEST)))
#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
#ifndef NO_WOLFSSL_SERVER
static int CsrDoStatusVerifyCb(WOLFSSL* ssl, byte* input, word32 inputSz, word32 idx,
int ret)
{
Expand All @@ -16619,7 +16618,6 @@ static int CsrDoStatusVerifyCb(WOLFSSL* ssl, byte* input, word32 inputSz, word32
}
return ret;
}
#endif /* !NO_WOLFSSL_SERVER */

/* Parses one certificate_status message. TLS 1.3 reads the per-certificate
* entries of the chain through this, so it is not tied to TLS 1.2. */
Expand Down Expand Up @@ -16703,8 +16701,10 @@ static int ProcessCSR_ex(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ssl->heap);

/* Extract producedDate */
if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 1, 1) != 0)
if (OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 1, 1) != 0) {
ssl->ocspProducedDateFormat = 0;
ret = BAD_CERTIFICATE_STATUS_ERROR;
}
if (ret == 0) {
XMEMCPY(ssl->ocspProducedDate, response->producedDate,
sizeof(ssl->ocspProducedDate));
Expand All @@ -16725,12 +16725,10 @@ static int ProcessCSR_ex(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = OCSP_CERT_REVOKED;
else if (response->single->status->status != CERT_GOOD)
ret = BAD_CERTIFICATE_STATUS_ERROR;

#ifndef NO_WOLFSSL_SERVER
ret = CsrDoStatusVerifyCb(ssl, input + *inOutIdx, status_length, idx, ret);
#endif
}

ret = CsrDoStatusVerifyCb(ssl, input + *inOutIdx, status_length, idx, ret);

*inOutIdx += status_length;

/* FreeOcspResponse frees status and single only if
Expand Down Expand Up @@ -20976,10 +20974,8 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* only frees 'single' if single->isDynamic is set */
FreeOcspResponse(response);

#ifndef NO_WOLFSSL_SERVER
ret = CsrDoStatusVerifyCb(ssl, input + *inOutIdx,
status_length, idx, ret);
#endif
if (ret == 0 && idx == 0) /* server cert must be OK */
endCertificateOK = 1;
#if defined(HAVE_OCSP) && defined(WOLFSSL_NONBLOCK_OCSP)
Expand Down
2 changes: 0 additions & 2 deletions src/ssl_api_crl_ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,6 @@ int wolfSSL_set_tlsext_status_ocsp_resp_multi(WOLFSSL* ssl, unsigned char *resp,
return ret;
}

#ifndef NO_WOLFSSL_SERVER
/* Set the callback that verifies a stapled OCSP response.
*
* @param [in, out] ctx SSL/TLS context.
Expand All @@ -1304,7 +1303,6 @@ void wolfSSL_CTX_set_ocsp_status_verify_cb(WOLFSSL_CTX* ctx,
ctx->ocspStatusVerifyCbArg = cbArg;
}
}
#endif /* NO_WOLFSSL_SERVER */
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST ||
* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */

Expand Down
1 change: 1 addition & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -47395,6 +47395,7 @@ TEST_CASE testCases[] = {
TEST_DECL_GROUP("ocsp", test_ocsp_resp_times),
TEST_DECL(test_ocsp_tls_cert_cb),
TEST_DECL_GROUP("ocsp", test_ocsp_status_request_v2_multi_revoked_single),
TEST_DECL_GROUP("ocsp", test_ocsp_status_verify_cb_undecodable_staple),
TEST_DECL_GROUP("ocsp", test_ocsp_cert_unknown_crl_fallback),
TEST_DECL_GROUP("ocsp", test_ocsp_cert_unknown_crl_fallback_nonleaf),
TEST_DECL_GROUP("ocsp", test_ocsp_no_url_policy),
Expand Down
154 changes: 154 additions & 0 deletions tests/api/test_ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1973,11 +1973,165 @@ int test_ocsp_status_request_v2_multi_revoked_single(void)
}
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 && !WOLFSSL_NO_TLS12 */

#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
/* A SEQUENCE header that claims more bytes than follow */
static const byte test_ocsp_undecodable_staple_junk[] = {
0x30, 0x05, 0x0a, 0x01, 0x00
};
static int test_ocsp_undecodable_staple_calls;
static int test_ocsp_undecodable_staple_err;
static word32 test_ocsp_undecodable_staple_idx;
static word32 test_ocsp_undecodable_staple_sz;

static int test_ocsp_undecodable_staple_status_cb(WOLFSSL* ssl, void* ioCtx)
{
byte* staple;

(void)ioCtx;
staple = (byte*)XMALLOC(sizeof(test_ocsp_undecodable_staple_junk), NULL,
0);
if (staple == NULL)
return WOLFSSL_OCSP_STATUS_CB_ALERT_FATAL;
XMEMCPY(staple, test_ocsp_undecodable_staple_junk,
sizeof(test_ocsp_undecodable_staple_junk));
if (wolfSSL_set_tlsext_status_ocsp_resp_multi(ssl, staple,
sizeof(test_ocsp_undecodable_staple_junk), 0) != WOLFSSL_SUCCESS) {
XFREE(staple, NULL, 0);
return WOLFSSL_OCSP_STATUS_CB_ALERT_FATAL;
}
return WOLFSSL_OCSP_STATUS_CB_OK;
}

static int test_ocsp_undecodable_staple_verify_cb(WOLFSSL* ssl, int err,
byte* staple, word32 stapleSz, word32 idx, void* arg)
{
(void)ssl;
(void)staple;
test_ocsp_undecodable_staple_calls++;
test_ocsp_undecodable_staple_err = err;
test_ocsp_undecodable_staple_idx = idx;
test_ocsp_undecodable_staple_sz = stapleSz;
return (arg != NULL) ? 0 : err;
}

/*
* The OCSP status verify callback sees a stapled response that does not
* decode, and can override the error like any other staple failure.
*/
int test_ocsp_status_verify_cb_undecodable_staple(void)
{
EXPECT_DECLS;
size_t i;
int override;
WOLFSSL_ALERT_HISTORY h;
#ifndef NO_ASN_TIME
byte date[MAX_DATE_SIZE];
int fmt = 0;
#endif
struct {
method_provider client_meth;
method_provider server_meth;
const char* tls_version;
} params[] = {
#if !defined(WOLFSSL_NO_TLS12)
{ wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLSv1_2" },
#endif
#ifdef WOLFSSL_TLS13
{ wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLSv1_3" },
#endif
};

for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) {
for (override = 0; override <= 1 && !EXPECT_FAIL(); override++) {
struct test_ssl_memio_ctx test_ctx;

printf("\nTesting %s, %s\n", params[i].tls_version,
override ? "callback overrides" : "callback keeps error");

XMEMSET(&test_ctx, 0, sizeof(test_ctx));
test_ctx.c_cb.caPemFile = "";
test_ctx.s_cb.certPemFile = "";
test_ctx.s_cb.keyPemFile = "";
test_ctx.c_cb.method = params[i].client_meth;
test_ctx.s_cb.method = params[i].server_meth;
test_ocsp_tls_cert_cb_opts.chainLen = 1;
test_ocsp_tls_cert_cb_opts.failStaple = 0;
test_ctx.s_cb.ctx_ready = test_ocsp_tls_cert_cb_ctx_ready;

ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS);
ExpectIntEQ(wolfSSL_UnloadCertsKeys(test_ctx.s_ssl),
WOLFSSL_SUCCESS);

ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.s_ctx),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CTX_set_tlsext_status_cb(test_ctx.s_ctx,
test_ocsp_undecodable_staple_status_cb), WOLFSSL_SUCCESS);

wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_DEFAULT,
test_ocsp_tls_cert_cb_verify_cb);
wolfSSL_SetCertCbCtx(test_ctx.c_ssl, test_ctx.c_ssl);
wolfSSL_CTX_set_ocsp_status_verify_cb(test_ctx.c_ctx,
test_ocsp_undecodable_staple_verify_cb,
override ? &test_ctx : NULL);
ExpectIntEQ(wolfSSL_CTX_EnableOCSPStapling(test_ctx.c_ctx),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_UseOCSPStapling(test_ctx.c_ssl,
WOLFSSL_CSR_OCSP, 0), WOLFSSL_SUCCESS);

#ifndef NO_ASN_TIME
/* Stale date from an earlier staple */
if (test_ctx.c_ssl != NULL) {
XSTRNCPY((char*)test_ctx.c_ssl->ocspProducedDate,
"260101000000Z",
sizeof(test_ctx.c_ssl->ocspProducedDate));
test_ctx.c_ssl->ocspProducedDateFormat = ASN_UTC_TIME;
}
#endif

test_ocsp_undecodable_staple_calls = 0;
test_ocsp_undecodable_staple_err = 0;
test_ocsp_undecodable_staple_idx = 1;
test_ocsp_undecodable_staple_sz = 0;
ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL),
override ? TEST_SUCCESS : TEST_FAIL);
ExpectIntEQ(test_ocsp_undecodable_staple_calls, 1);
ExpectIntEQ(test_ocsp_undecodable_staple_err,
WC_NO_ERR_TRACE(BAD_CERTIFICATE_STATUS_ERROR));
ExpectIntEQ(test_ocsp_undecodable_staple_idx, 0);
ExpectIntEQ(test_ocsp_undecodable_staple_sz,
sizeof(test_ocsp_undecodable_staple_junk));
if (!override) {
ExpectIntEQ(wolfSSL_get_alert_history(test_ctx.s_ssl, &h),
WOLFSSL_SUCCESS);
ExpectIntEQ(h.last_rx.level, alert_fatal);
ExpectIntEQ(h.last_rx.code, bad_certificate_status_response);
}
#ifndef NO_ASN_TIME
ExpectIntEQ(wolfSSL_get_ocsp_producedDate(test_ctx.c_ssl, date,
sizeof(date), &fmt), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
#endif

test_ssl_memio_cleanup(&test_ctx);
}
}
return EXPECT_RESULT();
}
#else
int test_ocsp_status_verify_cb_undecodable_staple(void)
{
return TEST_SKIPPED;
}
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */

#else /* feature guards */
int test_ocsp_tls_cert_cb(void)
{
return TEST_SKIPPED;
}
int test_ocsp_status_verify_cb_undecodable_staple(void)
{
return TEST_SKIPPED;
}
int test_ocsp_status_request_v2_multi_revoked_single(void)
{
return TEST_SKIPPED;
Expand Down
1 change: 1 addition & 0 deletions tests/api/test_ocsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ int test_ocsp_responder_keyhash_binding(void);
int test_ocsp_response_parsing(void);
int test_ocsp_tls_cert_cb(void);
int test_ocsp_status_request_v2_multi_revoked_single(void);
int test_ocsp_status_verify_cb_undecodable_staple(void);
int test_ocsp_cert_unknown_crl_fallback(void);
int test_ocsp_cert_unknown_crl_fallback_nonleaf(void);
int test_ocsp_no_url_policy(void);
Expand Down
43 changes: 43 additions & 0 deletions tests/api/test_ssl_crl_ocsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,49 @@ int test_wolfSSL_CTX_tlsext_status_cb(void)
return EXPECT_RESULT();
}

#if (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) && \
!defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT)
static int test_ssl_crl_ocsp_verify_cb(WOLFSSL* ssl, int err, byte* resp,
word32 respSz, word32 idx, void* arg)
{
(void)ssl;
(void)resp;
(void)respSz;
(void)idx;
(void)arg;
return err;
}
#endif

/* Test setting the OCSP status verify callback on a client CTX.
*
* @return TEST_SUCCESS on success.
*/
int test_wolfSSL_CTX_set_ocsp_status_verify_cb(void)
{
EXPECT_DECLS;
#if (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) && \
!defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT)
WOLFSSL_CTX* ctx = NULL;
int arg = 0;

ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
wolfSSL_CTX_set_ocsp_status_verify_cb(ctx, test_ssl_crl_ocsp_verify_cb,
&arg);
ExpectTrue((ctx != NULL) &&
(ctx->ocspStatusVerifyCb == test_ssl_crl_ocsp_verify_cb));
ExpectTrue((ctx != NULL) && (ctx->ocspStatusVerifyCbArg == &arg));

wolfSSL_CTX_set_ocsp_status_verify_cb(ctx, NULL, NULL);
ExpectTrue((ctx != NULL) && (ctx->ocspStatusVerifyCb == NULL));

wolfSSL_CTX_free(ctx);
#endif
return EXPECT_RESULT();
}

/* Test storing and retrieving a stapled OCSP response.
*
* @return TEST_SUCCESS on success.
Expand Down
3 changes: 3 additions & 0 deletions tests/api/test_ssl_crl_ocsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int test_wolfSSL_ocsp_url_api(void);
int test_wolfSSL_get_ocsp_producedDate(void);
int test_wolfSSL_tlsext_status_type(void);
int test_wolfSSL_CTX_tlsext_status_cb(void);
int test_wolfSSL_CTX_set_ocsp_status_verify_cb(void);
int test_wolfSSL_tlsext_status_ocsp_resp(void);
int test_wolfSSL_OCSP_parse_url_api(void);

Expand All @@ -36,6 +37,8 @@ int test_wolfSSL_OCSP_parse_url_api(void);
TEST_DECL_GROUP("ssl_crl_ocsp", test_wolfSSL_get_ocsp_producedDate), \
TEST_DECL_GROUP("ssl_crl_ocsp", test_wolfSSL_tlsext_status_type), \
TEST_DECL_GROUP("ssl_crl_ocsp", test_wolfSSL_CTX_tlsext_status_cb), \
TEST_DECL_GROUP("ssl_crl_ocsp", \
test_wolfSSL_CTX_set_ocsp_status_verify_cb), \
TEST_DECL_GROUP("ssl_crl_ocsp", test_wolfSSL_tlsext_status_ocsp_resp), \
TEST_DECL_GROUP("ssl_crl_ocsp", test_wolfSSL_OCSP_parse_url_api)

Expand Down
17 changes: 11 additions & 6 deletions tests/unit-mcdc/test_internal_status_whitebox.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,16 @@ static int wb_send_sink(WOLFSSL* ssl, char* buf, int sz, void* ctx)

/* ------------------------------------------------- CsrDoStatusVerifyCb */

#if !defined(NO_WOLFSSL_SERVER) && \
(defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
#if (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) && \
(!defined(WOLFSSL_NO_TLS12) || \
(defined(HAVE_OCSP) && defined(WOLFSSL_TLS13) && \
defined(HAVE_CERTIFICATE_STATUS_REQUEST))) && \
(!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH))
#define WB_HAVE_CSR_VERIFY_CB
#endif

#ifdef WB_HAVE_CSR_VERIFY_CB

static int g_verRet; /* what the mock callback returns */

Expand Down Expand Up @@ -207,9 +214,7 @@ int main(void)
goto done;
}

#if !defined(NO_WOLFSSL_SERVER) && \
(defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
#ifdef WB_HAVE_CSR_VERIFY_CB
wb_csr_status_verify(ssl, ctx);
#endif
wb_do_certificate_status(ssl, ctx);
Expand Down
Loading
Loading