diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index 461c0b0df9..e37e79f8a8 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -91,7 +91,7 @@ jobs: '--enable-all CPPFLAGS=''-DNO_WOLFSSL_SERVER -DWOLFSSL_NO_CLIENT_AUTH''', '--enable-curve25519=nonblock --enable-ecc=nonblock --enable-sp=yes,nonblock CPPFLAGS="-DWOLFSSL_PUBLIC_MP -DWOLFSSL_DEBUG_NONBLOCK"', '--enable-certreq --enable-certext --enable-certgen --disable-secure-renegotiation-info CPPFLAGS="-DNO_TLS"', - '--enable-ocsp --enable-ocsp-responder --enable-ocspstapling', + '--enable-ocsp --enable-ocsp-responder --enable-ocspstapling CPPFLAGS="-DWOLFSSL_NONBLOCK_OCSP" --enable-maxfragment', ] name: make check if: github.repository_owner == 'wolfssl' diff --git a/src/tls13.c b/src/tls13.c index 27d1ec0c3f..67ef351ddc 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -13453,8 +13453,9 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, &idx, ssl->arrays->pendingMsgType, ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ, ssl->arrays->pendingMsgSz); - #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) || + ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) { /* setup to process fragment again */ ssl->arrays->pendingMsgOffset -= inputLength; *inOutIdx -= inputLength + ssl->keys.padSz; diff --git a/tests/api.c b/tests/api.c index f256c06814..d86c7215b2 100644 --- a/tests/api.c +++ b/tests/api.c @@ -4871,7 +4871,8 @@ int test_ssl_memio_do_handshake(test_ssl_memio_ctx* ctx, int max_rounds, /* retry non-blocking math */ } else if (err != WOLFSSL_ERROR_WANT_READ && - err != WOLFSSL_ERROR_WANT_WRITE) { + err != WOLFSSL_ERROR_WANT_WRITE && + err != WC_NO_ERR_TRACE(OCSP_WANT_READ)) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string((word32)err, buff)); @@ -4896,7 +4897,8 @@ int test_ssl_memio_do_handshake(test_ssl_memio_ctx* ctx, int max_rounds, /* retry non-blocking math */ } else if (err != WOLFSSL_ERROR_WANT_READ && - err != WOLFSSL_ERROR_WANT_WRITE) { + err != WOLFSSL_ERROR_WANT_WRITE && + err != WC_NO_ERR_TRACE(OCSP_WANT_READ)) { char buff[WOLFSSL_MAX_ERROR_SZ]; fprintf(stderr, "error = %d, %s\n", err, wolfSSL_ERR_error_string((word32)err, buff)); @@ -34575,6 +34577,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_ocsp_tls_cert_cb), TEST_DECL(test_ocsp_cert_unknown_crl_fallback), TEST_DECL(test_ocsp_cert_unknown_crl_fallback_nonleaf), + TEST_DECL(test_tls13_nonblock_ocsp_low_mfl), TEST_DECL(test_ocsp_responder), TEST_TLS_DECLS, TEST_DECL(test_wc_DhSetNamedKey), diff --git a/tests/api/test_ocsp.c b/tests/api/test_ocsp.c index 1fe45f15f0..06c527bf82 100644 --- a/tests/api/test_ocsp.c +++ b/tests/api/test_ocsp.c @@ -1241,6 +1241,98 @@ int test_ocsp_cert_unknown_crl_fallback_nonleaf(void) } #endif /* HAVE_OCSP && HAVE_CRL && HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */ +#if defined(HAVE_OCSP) && defined(WOLFSSL_TLS13) && \ + defined(WOLFSSL_NONBLOCK_OCSP) && defined(HAVE_MAX_FRAGMENT) && \ + defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ + !defined(NO_RSA) && !defined(NO_SHA) + +/* Number of times the OCSP IO callback has been called. */ +static int test_tls13_nonblock_ocsp_mfl_cb_cnt; + +/* + * OCSP IO callback: simulates a nonblocking responder. Returns WANT_READ + * a few times before finally returning the OCSP response. + */ +static int test_tls13_nonblock_ocsp_mfl_io_cb(void* ioCtx, const char* url, + int urlSz, unsigned char* req, int reqSz, unsigned char** respBuf) +{ + (void)ioCtx; + (void)url; + (void)urlSz; + (void)req; + (void)reqSz; + + if (test_tls13_nonblock_ocsp_mfl_cb_cnt++ < 5) + return WOLFSSL_CBIO_ERR_WANT_READ; + + *respBuf = (unsigned char*)resp_server1_cert; + return (int)sizeof(resp_server1_cert); +} + +/* CTX-ready callback: enable client-side OCSP with URL override. */ +static int test_tls13_nonblock_ocsp_mfl_ctx_ready(WOLFSSL_CTX* ctx) +{ + EXPECT_DECLS; + ExpectIntEQ(wolfSSL_CTX_EnableOCSP(ctx, + WOLFSSL_OCSP_URL_OVERRIDE | WOLFSSL_OCSP_NO_NONCE), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_SetOCSP_OverrideURL(ctx, "http://example.com"), + WOLFSSL_SUCCESS); + /* NULL free-callback: resp points to static array, must not be freed. */ + ExpectIntEQ(wolfSSL_CTX_SetOCSP_Cb(ctx, + test_tls13_nonblock_ocsp_mfl_io_cb, NULL, NULL), + WOLFSSL_SUCCESS); + return EXPECT_RESULT(); +} + +/* SSL-ready callback: cap record payload at 1024 bytes. */ +static int test_tls13_nonblock_ocsp_mfl_ssl_ready(WOLFSSL* ssl) +{ + EXPECT_DECLS; + ExpectIntEQ(wolfSSL_UseMaxFragment(ssl, WOLFSSL_MFL_2_10), WOLFSSL_SUCCESS); + return EXPECT_RESULT(); +} + +int test_tls13_nonblock_ocsp_low_mfl(void) +{ + EXPECT_DECLS; + struct test_ssl_memio_ctx test_ctx; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + test_tls13_nonblock_ocsp_mfl_cb_cnt = 0; + + /* + * Server: two-cert chain (server1 + intermediate1, no root). + * Total DER size ~2534 bytes -> splits into 3 TLS records at MFL=1024. + */ + test_ctx.s_cb.certPemFile = "./certs/ocsp/server1-chain-noroot.pem"; + test_ctx.s_cb.keyPemFile = "./certs/ocsp/server1-key.pem"; + test_ctx.s_cb.method = wolfTLSv1_3_server_method; + + /* Client: trust root-ca, TLS 1.3, OCSP + MFL=1024. */ + test_ctx.c_cb.caPemFile = "./certs/ocsp/root-ca-cert.pem"; + test_ctx.c_cb.method = wolfTLSv1_3_client_method; + test_ctx.c_cb.ctx_ready = test_tls13_nonblock_ocsp_mfl_ctx_ready; + test_ctx.c_cb.ssl_ready = test_tls13_nonblock_ocsp_mfl_ssl_ready; + + ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); + ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), + TEST_SUCCESS); + + /* The OCSP callback must have been retried (called more than once). */ + ExpectIntGT(test_tls13_nonblock_ocsp_mfl_cb_cnt, 1); + + test_ssl_memio_cleanup(&test_ctx); + return EXPECT_RESULT(); +} + +#else +int test_tls13_nonblock_ocsp_low_mfl(void) +{ + return TEST_SKIPPED; +} +#endif + #if defined(HAVE_OCSP_RESPONDER) && defined(WOLFSSL_ASN_TEMPLATE) && \ !defined(NO_SHA) && !defined(NO_RSA) /* Structure to hold test configuration */ diff --git a/tests/api/test_ocsp.h b/tests/api/test_ocsp.h index 1b3ccc2351..b6e328f2df 100644 --- a/tests/api/test_ocsp.h +++ b/tests/api/test_ocsp.h @@ -29,6 +29,7 @@ int test_ocsp_response_parsing(void); int test_ocsp_tls_cert_cb(void); int test_ocsp_cert_unknown_crl_fallback(void); int test_ocsp_cert_unknown_crl_fallback_nonleaf(void); +int test_tls13_nonblock_ocsp_low_mfl(void); int test_ocsp_responder(void); #endif /* WOLFSSL_TEST_OCSP_H */