Skip to content

client, csr: copy the renewed cert's subject and SAN into reenroll CSRs - #44

Merged
Frauschi merged 1 commit into
wolfSSL:mainfrom
yosuke-wolfssl:fix/f_12109
Sep 30, 2026
Merged

Frauschi merged 1 commit into
wolfSSL:mainfrom
yosuke-wolfssl:fix/f_12109

Conversation

@yosuke-wolfssl

@yosuke-wolfssl yosuke-wolfssl commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

wolfcert_client_reenroll() built the /simplereenroll CSR from the caller's meta alone, so its Subject and SAN could differ from the certificate being renewed. RFC 7030 section 4.2.2 requires them to be identical. The CLI reenroll had the same flaw and required --subject. A conformant EST server rejects such a renewal; a lax one issues a renamed certificate. No privilege boundary is crossed (the caller already holds the current key), so this is a conformance fix.

Fix (src/csr.c)

A new internal wolfcert_csr_build_ex() takes the certificate being renewed. The public wolfcert_csr_build() passes none, so enrollment output is unchanged. For a renewal it:

  • rejects a meta that sets subject_dn or any san_* (WOLFCERT_ERR_BAD_ARG);
  • copies the certificate's raw Subject and SAN, with its criticality, after the customize callback, so the identity is byte-identical; an empty Subject stays empty;
  • refuses a Subject containing a 0x00 byte (e.g. BMPString), or a Subject or SAN too large for the wolfSSL Cert (WOLFCERT_ERR_UNSUPPORTED);
  • reads past an unrecognised critical extension, since it only reads the identity and does not validate the certificate.

The CSR buffer is now sized for the Subject and SAN it carries, which also lifts the old limit on large SANs at enrollment.

Caller Before After
wolfcert_client_reenroll() with meta.subject_dn / san_* used in the CSR WOLFCERT_ERR_BAD_ARG
wolfcert-client reenroll --subject / --san-* --subject required rejected

wolfcert-client reenroll now goes through wolfcert_client_reenroll() and prints the error detail. The link probes add GetASNTag / GetLength, which are exported under the same condition as the helpers already required. client.h lists the renewal error codes; types.h and ARCHITECTURE.md describe the copy; EMBEDDED.md adds the renewal Subject limit and corrects its Cert sizing figures (~23 CertName fields, ~5 KB for the trimmed example).

Closes f-12109.

Tests

  • test_csr: empty Subject with critical and non-critical SAN, kept against a customize callback that sets a CN; a reverse-order multi-RDN certificate with an unknown critical extension (raw Subject compared byte for byte); extensions without a SAN; BMPString Subject refused; 60-name SAN; SAN added by customize dropped; key PEM passed as the certificate; each identity field in meta rejected.
  • test_est_tls_roundtrip: meta rejection, renaming customize callback, rekey.
  • cli_proto_scoping: --subject and each --san-* rejected on reenroll.

Verification

  • 30/30 with CMake and autoconf; EST off 16/16, SCEP off 24/24; -Werror clean.
  • ASan+UBSan with leak detection clean (CI cmake-full-asan-ubsan, Linux).
  • Zephyr qemu_x86: wolfcert.unit.csr passes in 6-20 s against its 180 s limit.
  • Each new test fails when the behaviour it guards is reverted.

Not in this PR

  • A successful CLI reenroll test, which needs a CLI test driven against a running server.

@yosuke-wolfssl yosuke-wolfssl self-assigned this Sep 30, 2026
Copilot AI balanced review requested due to automatic review settings September 30, 2026 01:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #44

Scan targets checked: wolfcert-src, wolfcert-bugs
Coverage: 1 of 5 in-scope changed file(s) opened by the reviewer; not opened: tests/integration/test_est_tls_roundtrip.c, tests/unit/test_csr.c, wolfcert/client.h, wolfcert/types.h

Fenrir result: Approved ✅

No new issues found in the changed files.

Advisory only — this automated result does not count as a GitHub approval.

Review tier: Lite

- wolfcert_client_reenroll() builds its CSR with a new internal
  wolfcert_csr_build_ex(), which rejects a meta that sets the subject
  or any SAN and copies the renewed certificate's raw Subject and SAN
  after the customize callback.
- The CSR buffer is sized for the Subject and SAN carried.
- wolfcert-client reenroll rejects --subject and --san-* and uses
  wolfcert_client_reenroll().
- The link probes also check GetASNTag and GetLength.
- Headers and docs describe the renewal rule and its limits;
  EMBEDDED.md corrects the Cert sizing figures.
- Tests cover the copy, its refusals and the rejected options.

Issue: F-12109
@Frauschi
Frauschi merged commit adb5db4 into wolfSSL:main Sep 30, 2026
27 checks passed
@yosuke-wolfssl
yosuke-wolfssl deleted the fix/f_12109 branch September 30, 2026 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants