Implement OCSP responder#9761
Conversation
2e8e934 to
8bbec1e
Compare
8bbec1e to
0225c4a
Compare
Depends on wolfSSL/wolfssl#9761 Core OCSP implementation: - Register the new WOLFCLU_OCSP mode enum value - The responder main loop accepts connections and handles the request in a transport-agnostic way. - Add the OCSP mode to the help text in src/tools/clu_funcs.c. New HTTP utilities (src/tools/clu_http.c): - Move the static `kHttpGetMsg` from src/client/client.c and the static `kHttpServerMsg` from src/server/server.c into shared accessor functions - Add HTTP builder and server helpers New SCGI protocol implementation (src/tools/clu_scgi.c): - Implement the SCGI wire protocol per https://python.ca/scgi/protocol.txt Certificate and config additions (certs/): - Add ocsp-responder-cert.pem which is an authorized responder for ca-cert.pem Test suites: - tests/ocsp/ocsp-test.sh: top-level test runner with four interop combinations (wolfssl↔openssl, wolfssl↔wolfssl, openssl↔wolfssl, openssl↔openssl) sequentially - tests/ocsp/ocsp-interop-test.sh: test script taking in $OCSP_CLIENT and $OCSP_RESPONDER. Written to take in the same commands when run with wolfssl or openssl on either side - tests/ocsp-scgi/ocsp-scgi-test.sh: SCGI integration test using nginx for HTTP termination
|
Retest this please |
Depends on wolfSSL/wolfssl#9761 Core OCSP implementation: - Register the new WOLFCLU_OCSP mode enum value - The responder main loop accepts connections and handles the request in a transport-agnostic way. - Add the OCSP mode to the help text in src/tools/clu_funcs.c. New HTTP utilities (src/tools/clu_http.c): - Move the static `kHttpGetMsg` from src/client/client.c and the static `kHttpServerMsg` from src/server/server.c into shared accessor functions - Add HTTP builder and server helpers New SCGI protocol implementation (src/tools/clu_scgi.c): - Implement the SCGI wire protocol per https://python.ca/scgi/protocol.txt Certificate and config additions (certs/): - Add ocsp-responder-cert.pem which is an authorized responder for ca-cert.pem Test suites: - tests/ocsp/ocsp-test.sh: top-level test runner with four interop combinations (wolfssl↔openssl, wolfssl↔wolfssl, openssl↔wolfssl, openssl↔openssl) sequentially - tests/ocsp/ocsp-interop-test.sh: test script taking in $OCSP_CLIENT and $OCSP_RESPONDER. Written to take in the same commands when run with wolfssl or openssl on either side - tests/ocsp-scgi/ocsp-scgi-test.sh: SCGI integration test using nginx for HTTP termination
0225c4a to
67d2ea2
Compare
Depends on wolfSSL/wolfssl#9761 Core OCSP implementation: - Register the new WOLFCLU_OCSP mode enum value - The responder main loop accepts connections and handles the request in a transport-agnostic way. - Add the OCSP mode to the help text in src/tools/clu_funcs.c. New HTTP utilities (src/tools/clu_http.c): - Move the static `kHttpGetMsg` from src/client/client.c and the static `kHttpServerMsg` from src/server/server.c into shared accessor functions - Add HTTP builder and server helpers New SCGI protocol implementation (src/tools/clu_scgi.c): - Implement the SCGI wire protocol per https://python.ca/scgi/protocol.txt Certificate and config additions (certs/): - Add ocsp-responder-cert.pem which is an authorized responder for ca-cert.pem Test suites: - tests/ocsp/ocsp-test.sh: top-level test runner with four interop combinations (wolfssl↔openssl, wolfssl↔wolfssl, openssl↔wolfssl, openssl↔openssl) sequentially - tests/ocsp/ocsp-interop-test.sh: test script taking in $OCSP_CLIENT and $OCSP_RESPONDER. Written to take in the same commands when run with wolfssl or openssl on either side - tests/ocsp-scgi/ocsp-scgi-test.sh: SCGI integration test using nginx for HTTP termination
67d2ea2 to
f5c19cb
Compare
f6b8408 to
4f1ba64
Compare
7dbedf9 to
5fd564a
Compare
5fd564a to
711b172
Compare
There was a problem hiding this comment.
Pull request overview
Implements a wolfSSL OCSP responder: adds a public API for creating/responding to OCSP requests, expands ASN/OCSP encode/decode support, and introduces an ocsp_responder example plus interop/stapling test scripts.
Changes:
- Add OCSP responder core API (creation, signer/status configuration, request decode + response encode).
- Refactor/extend ASN template utilities and OCSP structures to support responder workflows.
- Add new OCSP responder example and new scripts/tests for OpenSSL interop and stapling scenarios.
Reviewed changes
Copilot reviewed 33 out of 54 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| wolfssl/wolfcrypt/types.h | Add dynamic type for OCSP response allocations; widen CERTSIGN state feature gating. |
| wolfssl/wolfcrypt/settings.h | Enforce feature prerequisites when HAVE_OCSP_RESPONDER is enabled. |
| wolfssl/wolfcrypt/rsa.h | Remove ASN header include to avoid circular dependencies. |
| wolfssl/wolfcrypt/ecc.h | Remove ASN header include to avoid circular dependencies. |
| wolfssl/wolfcrypt/asn_public.h | Add public getters for subject/issuer/serial from DecodedCert. |
| wolfssl/wolfcrypt/asn.h | Extend OCSP-related structs and add responder-only fields/utilities declarations. |
| wolfssl/test.h | Switch some OCSP-related allocations/frees to XMALLOC/XFREE. |
| wolfssl/ocsp.h | Add public OCSP request/response wrappers and OCSP responder public API. |
| wolfssl/internal.h | Add WOLFSSL_ASSERT_SIZEOF_EQ helper macro. |
| wolfcrypt/test/test.c | Fix error path to use ERROR_OUT macro in RNG bank test. |
| wolfcrypt/src/memory.c | Use XMEMMOVE when shifting overlapping memZero entries. |
| wolfcrypt/src/asn.c | Add responder encode/decode helpers; make ASN template code more robust. |
| tests/api/test_pkcs7.c | Initialize ret to avoid potential uninitialized use. |
| tests/api/test_ocsp.h | Add declaration for new test_ocsp_responder. |
| tests/api/test_ocsp.c | Add API-level tests for OCSP responder (RSA/ECC, good/revoked/unknown). |
| tests/api/test_certman.c | Replace realloc/free with XREALLOC/XFREE for tmp buffers. |
| tests/api.c | Replace free with XFREE in tests; initialize locals; register new OCSP responder test. |
| src/tls13.c | Fix missing braces around a conditional block. |
| src/ocsp.c | Implement OCSP responder API, plus request/response object alloc/free wrappers. |
| scripts/ocsp-stapling_tls13multi.test | Adjust ready-file names and port output formatting. |
| scripts/ocsp-stapling-with-wolfssl-responder.test | New test script for stapling using wolfSSL responder example. |
| scripts/ocsp-responder-openssl-interop.test | New interop test script (wolfSSL responder ↔ OpenSSL client). |
| scripts/include.am | Wire new responder/stapling scripts into automake testsuite ordering. |
| examples/server/server.c | Adjust error cleanup ordering in accept failure path. |
| examples/ocsp_responder/ocsp_responder.h | New header for OCSP responder example thread entry. |
| examples/ocsp_responder/ocsp_responder.c | New OCSP responder example program (HTTP listener + responder API). |
| examples/ocsp_responder/include.am | Build rules for new ocsp_responder example. |
| examples/include.am | Include ocsp_responder example in build. |
| configure.ac | Add --enable-ocsp-responder; define/propagate HAVE_OCSP_RESPONDER; enable in some presets. |
| certs/ocsp/renewcerts.sh | Generate DER certificates/keys for OCSP test infrastructure. |
| certs/ocsp/renewcerts-for-test.sh | Provide minimal OpenSSL req config to avoid relying on system openssl.cnf. |
| certs/ocsp/include.am | Distribute new DER files for OCSP testing. |
| .gitignore | Ignore built ocsp_responder example binary. |
| .github/workflows/os-check.yml | Enable OCSP responder in CI build matrix entry. |
Comments suppressed due to low confidence (4)
wolfssl/ocsp.h:1
wc_InitOcspRequest/wc_EncodeOcspRequestare declared as public API unconditionally, but their implementations insrc/ocsp.care currently under#ifdef HAVE_OCSP_RESPONDER. This can cause link failures whenHAVE_OCSPis enabled butHAVE_OCSP_RESPONDERis not. Either (a) move the wrapper implementations out of the responder-only guard (they call existing internal OCSP functions), or (b) wrap these declarations in#ifdef HAVE_OCSP_RESPONDERto match the implementation availability.
wolfcrypt/src/asn.c:1- In
OcspResponseEncode()(successful response path,out != NULL),szis computed but never checked against*outSzbefore writing withSetASN_Items(). If a caller passes an undersized output buffer, this can write past the end (even if most internal callers do a size-probe first). Add the standard guard used elsewhere in this file (if (out != NULL && sz > (int)*outSz) ret = BUFFER_E;) before callingSetASN_Items().
src/ocsp.c:1 - Comparing
issueranddecoded->subjectwithXMEMCMP(..., WC_ASN_NAME_MAX)can yield false mismatches because these are fixed-size buffers and bytes beyond the NUL terminator may differ/contain stale data. Prefer comparing as strings (length +XSTRNCMP/XSTRCMP) or compare using the parsed hashes (e.g.,subjectHash/issuerHash) if available.
src/ocsp.c:1 - The trace string doesn't match the function name (
wc_OcspResponder_AddSigner). Updating it will make debug logs/searching clearer.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
711b172 to
6e5b8f2
Compare
|
Added windows testing coverage |
OCSP Responder Core API: - Add new public API for creating and managing an OCSP responder - Add public wrappers for internal OCSP request/response functions - OcspRespCheck: fix check when authorized responder is loaded into CM Header Cleanup: - Remove circular dependency when including `#include <wolfssl/wolfcrypt/asn.h>` from wolfssl/wolfcrypt/ecc.h and wolfssl/wolfcrypt/rsa.h OCSP Responder Example (examples/ocsp_responder/): - Add a command-line OCSP responder for interoperability testing with OpenSSL's `openssl ocsp` client Test Scripts (scripts/): - ocsp-responder-openssl-interop.test: Tests wolfSSL OCSP responder with `openssl ocsp` client - ocsp-stapling-with-wolfssl-responder.test: Tests wolfSSL OCSP responder when doing OCSP stapling Certificate Infrastructure (certs/ocsp/): - Add DER-format certificates and keys for OCSP testing - Update renewcerts.sh to generate DER versions Known Limitations (documented in src/ocsp.c header comment): - Single request/response per OCSP exchange only - Key-hash responder ID only (no name-based responder ID) - No singleExtensions support
…response truncation
1195e3a to
5a4c634
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 43 out of 64 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (13)
wolfcrypt/src/asn.c:1
- digestSz
is aword32, butwc_HashGetDigestSize()returns anintand can return negative values. Casting a negative digest size toword32will produce a large positive number, causing thedigestSz <= 0check to miss and potentially leading to out-of-bounds reads/writes when usingdigestSzas a length. Use a signedintfor the digest size, validate it before casting/assigning to an unsigned type, and only proceed when it is within expected bounds (and <=WC_MAX_DIGEST_SIZE`).
src/ocsp.c:1 - issuerHash
/single->issuerHashcan now be produced with variable digest algorithms/sizes (the OCSP code paths were updated to support non-SHA1 sizes viawc_HashGetDigestSize()andWC_MAX_DIGEST_SIZE). Hard-codingOCSP_DIGEST_SIZEhere risks incorrect authorization decisions (false positives/negatives) when the request/response uses SHA-256/SHA-384/etc. Derive the digest size from thesingleentry’s hash OID (e.g.,wc_HashGetDigestSize(wc_OidGetHash(single->hashAlgoOID))) and compare exactly that many bytes; also thread that size intoCheckOcspResponderChain()` so it does not assume SHA-1.
src/ocsp.c:1 - issuerHash
/single->issuerHashcan now be produced with variable digest algorithms/sizes (the OCSP code paths were updated to support non-SHA1 sizes viawc_HashGetDigestSize()andWC_MAX_DIGEST_SIZE). Hard-codingOCSP_DIGEST_SIZEhere risks incorrect authorization decisions (false positives/negatives) when the request/response uses SHA-256/SHA-384/etc. Derive the digest size from thesingleentry’s hash OID (e.g.,wc_HashGetDigestSize(wc_OidGetHash(single->hashAlgoOID))) and compare exactly that many bytes; also thread that size intoCheckOcspResponderChain()` so it does not assume SHA-1.
src/ocsp.c:1 - issuerHash
/single->issuerHashcan now be produced with variable digest algorithms/sizes (the OCSP code paths were updated to support non-SHA1 sizes viawc_HashGetDigestSize()andWC_MAX_DIGEST_SIZE). Hard-codingOCSP_DIGEST_SIZEhere risks incorrect authorization decisions (false positives/negatives) when the request/response uses SHA-256/SHA-384/etc. Derive the digest size from thesingleentry’s hash OID (e.g.,wc_HashGetDigestSize(wc_OidGetHash(single->hashAlgoOID))) and compare exactly that many bytes; also thread that size intoCheckOcspResponderChain()` so it does not assume SHA-1.
wolfcrypt/src/asn.c:1 - wc_GetDecodedCertSubject()
/wc_GetDecodedCertIssuer()return data via achar*buffer but do not NUL-terminate it (and report a size that excludes a terminator). That’s easy for API consumers to misuse as a C string and can lead to over-reads in downstream code. Consider either (a) guaranteeing NUL-termination (require*bufSz >= sz + 1, copyszbytes, and setbuf[sz] = '\0', and returnsz + 1` or a clearly documented size), or (b) explicitly documenting in the header that the returned buffer is not NUL-terminated and must be treated as a byte-span.
wolfcrypt/src/asn.c:1 - wc_GetDecodedCertSubject()
/wc_GetDecodedCertIssuer()return data via achar*buffer but do not NUL-terminate it (and report a size that excludes a terminator). That’s easy for API consumers to misuse as a C string and can lead to over-reads in downstream code. Consider either (a) guaranteeing NUL-termination (require*bufSz >= sz + 1, copyszbytes, and setbuf[sz] = '\0', and returnsz + 1` or a clearly documented size), or (b) explicitly documenting in the header that the returned buffer is not NUL-terminated and must be treated as a byte-span.
src/x509.c:1 - Casting
x509->pathLengthtobytecan silently wrap/truncate values > 255, producing an incorrectpathLen. It would be safer to validate the range before converting (e.g., clamp or return an error whenpathLengthexceeds the representable range ofcert->pathLen).`
examples/ocsp_responder/ocsp_responder.c:1 - The return value from
tcp_listen()is not checked. If bind/listen fails, the code proceeds and later callsaccept()on an invalid socket, causing repeated failures/spin. Capture and validate the return code (and/or confirmsockfd != INVALID_SOCKET) and exit with a clear error when the listener cannot be created.`
wolfcrypt/src/asn.c:1 - The added
depth + 1 >= GET_ASN_MAX_DEPTHcheck effectively reduces the maximum usable depth by one (because the implementation always indexesendIdx[depth + 1]). WithGET_ASN_MAX_DEPTHset to 8, templates using depth 7 will still fail, so the constant bump from 7→8 may not actually permit deeper templates as intended. Consider aligning the constant and theendIdxstorage strategy (e.g., sizeendIdxtoGET_ASN_MAX_DEPTH + 1, or adjust the depth definition/checks so the maximum supported template depth matches the constant).`
wolfcrypt/src/asn.c:1 - The added
depth + 1 >= GET_ASN_MAX_DEPTHcheck effectively reduces the maximum usable depth by one (because the implementation always indexesendIdx[depth + 1]). WithGET_ASN_MAX_DEPTHset to 8, templates using depth 7 will still fail, so the constant bump from 7→8 may not actually permit deeper templates as intended. Consider aligning the constant and theendIdxstorage strategy (e.g., sizeendIdxtoGET_ASN_MAX_DEPTH + 1, or adjust the depth definition/checks so the maximum supported template depth matches the constant).`
wolfcrypt/src/asn.c:1 - The added
depth + 1 >= GET_ASN_MAX_DEPTHcheck effectively reduces the maximum usable depth by one (because the implementation always indexesendIdx[depth + 1]). WithGET_ASN_MAX_DEPTHset to 8, templates using depth 7 will still fail, so the constant bump from 7→8 may not actually permit deeper templates as intended. Consider aligning the constant and theendIdxstorage strategy (e.g., sizeendIdxtoGET_ASN_MAX_DEPTH + 1, or adjust the depth definition/checks so the maximum supported template depth matches the constant).`
wolfcrypt/src/asn.c:1 - The added
depth + 1 >= GET_ASN_MAX_DEPTHcheck effectively reduces the maximum usable depth by one (because the implementation always indexesendIdx[depth + 1]). WithGET_ASN_MAX_DEPTHset to 8, templates using depth 7 will still fail, so the constant bump from 7→8 may not actually permit deeper templates as intended. Consider aligning the constant and theendIdxstorage strategy (e.g., sizeendIdxtoGET_ASN_MAX_DEPTH + 1, or adjust the depth definition/checks so the maximum supported template depth matches the constant).`
wolfcrypt/src/asn.c:1 - The added
depth + 1 >= GET_ASN_MAX_DEPTHcheck effectively reduces the maximum usable depth by one (because the implementation always indexesendIdx[depth + 1]). WithGET_ASN_MAX_DEPTHset to 8, templates using depth 7 will still fail, so the constant bump from 7→8 may not actually permit deeper templates as intended. Consider aligning the constant and theendIdxstorage strategy (e.g., sizeendIdxtoGET_ASN_MAX_DEPTH + 1, or adjust the depth definition/checks so the maximum supported template depth matches the constant).`
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Fix line length - Remove duplicate comment - Check return of `wc_HashGetDigestSize` - Use constant instead of magic number
Address final comments from #9761
OCSP Responder Core API:
Header Cleanup:
#include <wolfssl/wolfcrypt/asn.h>from wolfssl/wolfcrypt/ecc.h and wolfssl/wolfcrypt/rsa.hOCSP Responder Example (examples/ocsp_responder/):
openssl ocspclientTest Scripts (scripts/):
openssl ocspclientCertificate Infrastructure (certs/ocsp/):
Known Limitations (documented in src/ocsp.c header comment):