cli: pin the SCEP GetCACert response - #17
Conversation
There was a problem hiding this comment.
Pull request overview
This PR hardens the reference CLI’s SCEP flow by adding CA fingerprint pinning so the client can authenticate the GetCACert response out-of-band and avoid trusting attacker-supplied CA/RA material over an untrusted transport.
Changes:
- Add
--ca-fingerprint(SCEP-only) and enforce pin validation before network access; use only the pinned cert as the envelope recipient and CertRep trust anchor. - Print SHA-256 fingerprints in
getcacertsto support operator pin acquisition; apply the same pin resolution togetnextca. - Extend the existing CLI integration test to cover option scoping, argument validation, and end-to-end pinning against
wolfcert-server; update docs accordingly.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| cli/wolfcert_client.c | Implements --ca-fingerprint parsing/enforcement and pins SCEP enroll/getnextca trust decisions to the matched cert. |
| tests/integration/cli_proto_scoping.sh | Adds argument-validation cases and an end-to-end pinning group using the in-tree test server. |
| README.md | Documents why/when to pin SCEP GetCACert and how to obtain/use the fingerprint via the CLI. |
| docs/MIGRATING-FROM-WOLFSCEP.md | Updates migration guidance to mention the new CLI fingerprint pinning option. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
2804065 to
e451137
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #17
Scan targets checked: wolfcert-bugs, wolfcert-src
Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
e451137 to
d6fc617
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #17
Scan targets checked: wolfcert-bugs, wolfcert-src
Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
d6fc617 to
386b2ff
Compare
Frauschi
left a comment
There was a problem hiding this comment.
Read through the pinning change. The trust bootstrap itself looks right - find_pinned_cert selects, frees the rejected certificates and fails closed, and making the pinned certificate the sole envelope recipient and CertRep anchor is the correct call. What is below is one design question plus coverage and documentation gaps; nothing blocking.
The one worth a decision is getnextca. Pinning the RA for enroll, as the README now tells you to, makes getnextca fail with a message that reads like a broken pin, because the roll-over is signed by the CA. I think the narrowing is right and the answer is to say so rather than widen the anchor back - details inline.
The recurring theme in the rest is that wolfcert-server serves a single CA certificate, so the multi-certificate half of the pin selection never runs, and the case that claims to guard the stale-error path never reaches it.
ctest registration comment for cli_proto_scoping is now false — the test starts a network server (tests/CMakeLists.txt:117-118)
The comment above add_test(NAME cli_proto_scoping ...) still reads "Every case fails before any network access, so no server is involved". The new pinning group binds 18088/18188/18288/18388 and forks wolfcert-server, so that is no longer true - worth fixing, since that comment is what the next person uses to decide whether this test is safe to run in a sandbox or in parallel.
The registration also declares no dependency or fixture on the wolfcert-server target and passes only $<TARGET_FILE:wolfcert-client>, relying on the script deriving its sibling. That works under both CMake and the automake AM_TESTS_ENVIRONMENT, so nothing is broken, but a build dependency (or FIXTURES_REQUIRED) would stop the group silently skipping itself when ctest is driven without a full build.
386b2ff to
fd7ab7b
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #17
Scan targets checked: wolfcert-bugs, wolfcert-src
Fenrir result: Approved ✅
No new issues found in the changed files.
Advisory only — this automated result does not count as a GitHub approval.
|
Hello @Frauschi , |
- --ca-fingerprint takes [sha256:|sha1:|sha512:]HEX, and is refused under EST. parse_ca_fingerprint decodes it into a CaPin; scep_pin_setup resolves it, and notes that an unpinned run trusts the served CA. - pem_cert_at, find_pinned_cert, der_to_pem and print_ca_fingerprints select, re-encode and report the certificates of a GetCACert response, numbered over the ones that decode. - With a pin, scep_enroll makes the match the envelope recipient and the only CertRep anchor and skips the bundle fetch; cmd_getcacerts writes only the match; cmd_getnextca resolves the current CA through the pin, and on WOLFCERT_ERR_AUTH names the CA as the signer of the roll-over. - cli_proto_scoping.sh adds the option scoping, the argument rejections, and a wolfcert-server group covering a mismatched and a matching pin, with a shell repeat helper and a whole-second sleep fallback; tests/CMakeLists.txt and Makefile.am describe the registration. - README.md and docs/MIGRATING-FROM-WOLFSCEP.md document the flag, which certificate getnextca wants pinned, and that the pin leaves GetCACaps unauthenticated. Issue: F-8046
fd7ab7b to
94a22f7
Compare
|
Hi @Frauschi , |
Problem
The reference CLI never authenticated the SCEP CA it enrolled against.
cmd_enrollfetchedGetCACertover the same (usually plaintext) transport it was about to trust, made the first certificate the CSR envelope recipient, and made the whole response the CertRep trust set. Sincewolfcert_scep_verify_rep_signeraccepts any signer whose SPKI matches any bundle member, an active attacker answeringGetCACertwith their own RSA certificate both decrypts the CSR with itschallengePasswordand returns a certificate the client accepts.wolfcert_scep_verify_ca_fingerprintwas written for exactly this bootstrap and had zero callers incli/. A caller using the library API correctly is unaffected.Fix (
cli/wolfcert_client.c)Adds
--ca-fingerprint [sha256:|sha1:|sha512:]HEX, rejected under EST and validated before any network access.getcacertsprints each certificate's SHA-256, so the value can be read once over a trusted path and pinned thereafter.getnextcaresolves the current CA through the same pin, closing the circularity its own comment documented.getnextcawants the CA's own fingerprint, not the RA's — RFC 8894 section 4.6.1 has the current CA sign the roll-over, while a CertRep in an RA deployment is signed by the RA.getcacertsprints both, so one trusted read covers it.Closes
f-8046.Tests
tests/integration/cli_proto_scoping.sh, the repo's existing CLI test, gains the option scoping and argument rejections plus a group that startswolfcert-server, reads the fingerprint fromgetcacerts, and runsenrollandgetnextcaagainst a mismatched and a matching pin. The group skips itself when the server was not built, so no new build-file registration is needed.Not in this PR
Deferred to follow-up issues, all raised in review:
GetCACertfixture, so pin selection is exercised on the split CA/RA shape. Needs new test infrastructure.wolfcert_scep_get_ca_caps's discarded return inscep_enroll— a distinct issue from this one; the pin cannot address it, and the README now documents the exposure.XMALLOCinwolfcert_scep_parse_pki_messagesurfacing asWOLFCERT_ERR_AUTHrather than a memory error.FIXTURES_REQUIREDon the ctest registration.Verification
scep_enrollorcmd_getnextcamakes the matching mismatched-pin case pass.