Skip to content

RFC compliance: TLS 1.3 (RFC 9846), cert_with_extern_psk (RFC 9973), SSLKEYLOGFILE (RFC 9850)#30

Closed
Frauschi wants to merge 6 commits into
masterfrom
rfc_compliance
Closed

RFC compliance: TLS 1.3 (RFC 9846), cert_with_extern_psk (RFC 9973), SSLKEYLOGFILE (RFC 9850)#30
Frauschi wants to merge 6 commits into
masterfrom
rfc_compliance

Conversation

@Frauschi

Copy link
Copy Markdown
Owner

Summary

Aligns wolfSSL with three recently published RFCs. Each change is scoped to the
specific normative delta; default-build behavior is preserved.

RFC 9846 (TLS 1.3bis, obsoletes RFC 8446)

  • Add the new general_error(117) alert (Section 6.2).
  • Cap the sender key-update count at 2^48-1 in SendTls13KeyUpdate
    (Section 4.7.3). The receive path is deliberately left unlimited, since the
    RFC states receivers MUST NOT enforce this. Includes a boundary unit test.
  • Accept an empty CertificateRequest.extensions block (Section 4.4.2), which
    is then rejected by the existing mandatory signature_algorithms check with
    a missing_extension alert.
  • Warn when WOLFSSL_STATIC_EPHEMERAL reuses a TLS 1.3 client key_share across
    connections (Section 4.3.8). Behavior is unchanged for the documented
    server-side use case.

RFC 9973 (obsoletes RFC 8773), cert_with_extern_psk

  • Documentation only: update RFC 8773bis references to RFC 9973. No logic,
    macro, public API, or extension codepoint (33 / 0x0021) changes. Historical
    ChangeLog and README entries are left as they shipped.

RFC 9850 (SSLKEYLOGFILE format)

  • Sniffer keylog reader now parses line by line: it ignores comment and empty
    lines and tolerates malformed lines instead of desynchronizing
    (Sections 1 and 2). Field buffers are cleared per line and the line buffer is
    zeroized on every return path. Variable-length secrets (SHA-256 and SHA-384)
    are preserved. Test data extended with comment, blank, and malformed lines.
  • Honor the SSLKEYLOGFILE environment variable in the key-log writers, behind
    the existing SHOW_SECRETS / WOLFSSL_SSLKEYLOGFILE compile-time guards, so
    production builds cannot log secrets regardless of the environment.

Testing

  • Default make builds clean with warnings-as-errors.
  • New KeyUpdate ceiling test in tests/api/test_tls13.c; run under make check
    in an --enable-all build.
  • Sniffer keylog test data updated; run scripts/sniffer-testsuite.test in an
    --enable-sniffer build.

Notes

  • Opened against the fork for review.

RFC 9846 section 6.2 defines a new generic alert, general_error(117),
sent to indicate an error condition when no more specific alert is
available or the sender wishes to conceal the specific error code.

Define the alert in the AlertDescription enumeration and add its name to
AlertTypeToString so it is recognized and logged. In TLS 1.3 it is
handled as a fatal alert by the existing alert processing, which matches
the specification.
Comment thread scripts/sniffer-tls13-keylog.sslkeylog Outdated
Comment thread src/ssl.c Outdated
Comment thread src/ssl_api_pk.c Outdated
Comment thread src/tls13.c
@Frauschi
Frauschi force-pushed the rfc_compliance branch 2 times, most recently from c46df6c to 87547ff Compare July 17, 2026 08:22
Frauschi added 5 commits July 17, 2026 10:54
RFC 9846 Section 4.7.3 upgrades the key update bound so that sending
implementations MUST NOT allow the number of key updates to exceed
2^48-1, while receiving implementations MUST NOT enforce this on the
peer. The DTLS 1.3 path already gated its sending epoch, but stream
TLS 1.3 tracked no key update count.

Add a keyUpdateCount field at the end of the Keys structure TLS 1.3
block, refuse to send a KeyUpdate in SendTls13KeyUpdate once the sender
reaches the ceiling, and increment the count after deriving each new
sending key. The receive path is left unchanged so it never enforces a
limit on the peer.

Add a test that seeds the sender count at the ceiling and confirms the
next KeyUpdate is refused with BAD_STATE_E.
RFC 9846 Section 4.4.2 corrects the lower bound on
CertificateRequest.extensions to 0, so a zero length extensions block is
syntactically valid. The client rejected it early with INVALID_PARAMETER
before parsing.

Remove the early rejection so the extensions are parsed and an empty
block is instead caught by the existing mandatory signature_algorithms
check, which returns the correct missing_extension alert. TLSX_Parse
handles a zero length input by parsing no extensions.
RFC 9973 "TLS 1.3 Extension for Using Certificates with an External
Pre-Shared Key" is now published and obsoletes RFC 8773. The
cert_with_extern_psk implementation was written against the 8773bis
draft that became RFC 9973, so it is already compliant.

Update the textual references in comments, the configure help comment,
the extension codepoint comment, a test comment, and the Doxygen docs.
This is a documentation only change. The WOLFSSL_CERT_WITH_EXTERN_PSK
macro, the --enable-cert-with-extern-psk option, the public API names,
and the extension codepoint 33 (0x0021) are all unchanged, and no logic
is affected. Historical ChangeLog and README entries are left as they
shipped.
The keylog reader used fscanf with three whitespace delimited tokens,
which is not line aware. RFC 9850 Section 1 requires readers to ignore
empty lines and lines whose first character is '#', and Section 2
recommends ignoring lines that do not conform to the format so secrets
can still be recovered from corrupted files. A comment line such as
"# note" was parsed as three fields spanning the line boundary, which
desynchronized the rest of the file.

Read one line at a time with fgets, skip empty and comment lines, and
parse each line with sscanf, skipping any line that does not yield the
three expected fields instead of aborting. Clear the field buffers each
iteration so a short field cannot pick up stale bytes from a previous
line, validate that the fixed length client random field is the exact
expected length, and leave the secret length variable because it depends
on the negotiated hash. Zero the new line buffer on every return path,
matching the existing ForceZero handling of the secret buffers.

Add a comment line, a blank line, and a malformed line to the TLS 1.3
keylog test data so the sniffer keylog test exercises the skip paths.
RFC 9850 notes that implementations informally use an environment
variable named SSLKEYLOGFILE to select the key log path, which lets tools
such as curl, NSS and Wireshark share one file. The key log writers only
used the compile-time WOLFSSL_SSLKEYLOGFILE_OUTPUT path.

Prefer XGETENV("SSLKEYLOGFILE") when it is set and non-empty, falling
back to the compile-time path otherwise, in both tls13ShowSecrets and
tlsShowSecrets. XGETENV resolves to NULL on targets without environment
support, so those fall back automatically. This stays behind the existing
SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE compile-time guards, so production
builds that do not define them cannot log secrets regardless of the
environment, as required by the RFC security considerations.
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.

1 participant