Skip to content

TLS Extensions: add more extensions and improve current - #11362

Open
SparkiDev wants to merge 1 commit into
wolfSSL:masterfrom
SparkiDev:tls_ext_add
Open

SparkiDev wants to merge 1 commit into
wolfSSL:masterfrom
SparkiDev:tls_ext_add

Conversation

@SparkiDev

@SparkiDev SparkiDev commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

Description

Added support for record_size_limit in TLS 1.3 and TLS 1.2.
Added compress_certificate support for TLS 1.3.
Added signed_certificate_timestamp TLS 1.2 and 1.3.
Added handshake-message fragmentation to EncryptedExtension, CertificateRequest
and NewSessionTicket.
Accepts server_name in CertificateRequest.
Added API for setting signature algorithms for signature_algorithms_cert.

SHA-1 certificate chain fix: a peer advertising ecdsa_sha1 against a chain
with an RSA-SHA1 intermediates will see a failed handshake.

Tests added and interop performed where possible.

Testing

Regression tested TLS.

@SparkiDev SparkiDev self-assigned this Sep 3, 2026
@SparkiDev
SparkiDev force-pushed the tls_ext_add branch 2 times, most recently from 81d6404 to e16541a Compare September 3, 2026 06:51
@SparkiDev
SparkiDev removed the request for review from wolfSSL-Fenrir-bot September 3, 2026 06:51
@github-actions

github-actions Bot commented Sep 3, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report · Explore what changed →

gcc-arm-cortex-m4-dtls13

  • FLASH: .text +320 B (+0.2%, 196,248 B / 1,048,576 B, total: 19% used)

gcc-arm-cortex-m4-openssl-compat

  • FLASH: .text +704 B (+0.1%, 801,380 B / 1,048,576 B, total: 76% used)

gcc-arm-cortex-m4-pq

  • FLASH: .text +576 B (+0.2%, 313,360 B / 1,048,576 B, total: 30% used)

gcc-arm-cortex-m4-rsa-only

  • FLASH: .text +512 B (+0.1%, 344,144 B / 1,048,576 B, total: 33% used)

gcc-arm-cortex-m4-tls13

  • FLASH: .text +576 B (+0.2%, 250,082 B / 262,144 B, total: 95% used)

gcc-arm-cortex-m7-pq

  • FLASH: .text +576 B (+0.2%, 314,192 B / 1,048,576 B, total: 30% used)

gcc-arm-cortex-m7-tls13

  • FLASH: .text +576 B (+0.2%, 250,082 B / 262,144 B, total: 95% used)

zephyr-frdm_rw612

  • FLASH: log_const_area -8 B, rodata -8 B, text +1,592 B (+0.6%, 284,040 B / 67,108,864 B, total: 0% used)

No memory changes detected for:


Catch memory regressions in CI with MemBrowse. Free for open source.

@SparkiDev
SparkiDev force-pushed the tls_ext_add branch 5 times, most recently from 646253f to 55ec736 Compare September 4, 2026 05:26

@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 #11362

Scan targets checked: wolfcrypt-rs-bugs, wolfssl-bugs, wolfssl-src

Findings: 3
3 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread src/internal.c Resolved
Comment thread src/tls.c Resolved
Comment thread src/internal.c Resolved
Comment thread src/internal.c Resolved
Comment thread src/tls.c Resolved
Comment thread src/internal.c Resolved

@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 #11362

Scan targets checked: wolfcrypt-rs-bugs, wolfssl-bugs, wolfssl-src

Findings: 3
3 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread src/tls.c Resolved
Comment thread src/tls13.c Resolved
Comment thread src/tls.c Resolved
Comment thread src/tls.c Resolved
Comment thread src/tls13.c Resolved
Comment thread src/tls.c Resolved

@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 #11362

Scan targets checked: wolfcrypt-rs-bugs, wolfssl-bugs, wolfssl-src

Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread src/tls13.c Resolved
Comment thread src/tls13.c Resolved

@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 #11362

Scan targets checked: wolfcrypt-rs-bugs, wolfssl-bugs, wolfssl-src

Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Comment thread src/tls.c Resolved
@SparkiDev SparkiDev assigned wolfSSL-Bot and unassigned wolfSSL-Bot and SparkiDev Nov 2, 2026
@philljj philljj self-assigned this Nov 4, 2026
@philljj

philljj commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

@claude review

Comment thread src/ssl_api_ext.c Resolved

@claude claude 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.

Findings marked 🟡 are optional suggestions and need no follow-up push.

Additional findings (outside the current diff — GitHub can't attach inline comments there):

  • 🔴 src/internal.c — SCT-only builds leak the leaf's CertificateEntry extension buffer when a server frees a connection before its Certificate message is fully sent. wolfSSL_ResourceFree() frees ssl->buffers.certExts only under HAVE_CERTIFICATE_STATUS_REQUEST. Since this change, WriteCertEntryExts() also allocates certExts[0] for the SCT list under WOLFSSL_CERT_ENTRY_EXTS. Fix: guard this cleanup with WOLFSSL_CERT_ENTRY_EXTS (with !NO_CERTS and WOLFSSL_TLS13), the macro wolfssl/internal.h says every site that builds, indexes or frees these buffers must share.

    Why this was flagged

    The trigger is a build with --enable-sct but not OCSP stapling, so HAVE_SIGNED_CERT_TIMESTAMP is defined and HAVE_CERTIFICATE_STATUS_REQUEST is not. In that build WOLFSSL_CERT_ENTRY_EXTS is defined (wolfssl/internal.h). A TLS 1.3 server answering an SCT request calls WriteCertEntryExts() (src/tls13.c:11712), which AllocDer()s ssl->buffers.certExts[0] for the leaf's SCT list. That buffer is freed only once the leaf has been completely copied out (src/tls13.c:11889). Two cases leave it allocated: the send stops part way, or it fails before the leaf is written. Examples are a WANT_WRITE between fragments under a small max_fragment_length or record_size_limit followed by wolfSSL_free(), or a CheckAvailableSize() failure. The only teardown free, src/internal.c:10541-10550, is compiled out in this build, so each such connection leaks the buffer. On the base branch certExts was only allocated in builds that also compiled this free.

    Verification: In SCT-only builds, WriteCertEntryExts calls AllocDer(&certExts[extIdx], ...) for the SCT list (src/tls13.c:10677), freed only once the leaf is fully sent (tls13.c:11889). The only fallback cleanup is wolfSSL_ResourceFree at src/internal.c:10541-10550. It is guarded by defined(HAVE_CERTIFICATE_STATUS_REQUEST), so it compiles out in SCT-only builds.

  • 🔴 src/ssl.c — Apps using wolfSSL_write_dup() will send records larger than a peer's negotiated record_size_limit, so an RFC 8449 peer aborts with record_overflow. DupSSL() copies max_fragment and maxSendFragment to the write-only object but not peerRecordSizeLimit. The dup starts that field at 0 from InitSSL(), so wolfSSL_GetMaxFragSize() never caps its sends. Fix: copy peerRecordSizeLimit into the dup next to max_fragment, under HAVE_RECORD_SIZE_LIMIT, so every record the writer sends respects the peer's limit.

    Why this was flagged

    The trigger is a build with HAVE_WRITE_DUP and HAVE_RECORD_SIZE_LIMIT, where the peer advertised a limit below 2^14 (e.g. wolfSSL_UseRecordSizeLimit(ssl, 512) on a wolfSSL peer, or a constrained embedded stack). wolfSSL_write_dup() (src/ssl.c:1037) zero-inits the dup in InitSSL() (src/internal.c:9215), then DupSSL() copies only max_fragment (src/ssl.c:953) and maxSendFragment (src/ssl.c:1006). peerRecordSizeLimit, set only on the read object by TLSX_RecordSizeLimit_Parse() (src/tls.c:8559), stays 0 on the dup. So the HAVE_RECORD_SIZE_LIMIT cap in wolfSSL_GetMaxFragSize() (src/internal.c:48519) is skipped, and wolfSSL_write() on the dup sends records of up to MAX_RECORD_SIZE. A wolfSSL peer rejects them in GetRecordHeader() (src/internal.c:14187) with LENGTH_ERROR / record_overflow, and the connection dies on the first large write. Without write-dup the same object sends correctly sized records. The max_fragment copy shows DupSSL() is meant to carry negotiated send limits, but the new field was left out.

    Verification: DupSSL() copies dup->max_fragment = ssl->max_fragment; (src/ssl.c:953) but never peerRecordSizeLimit, which InitSSL zeroes (src/internal.c:9215). wolfSSL_GetMaxFragSize applies the RFC 8449 cap only if peerRecordSizeLimit != 0 (src/internal.c:48519). On the dup that field is 0, so records go out at up to MAX_RECORD_SIZE (16384).

  • 🔴 src/internal.c — A TLS or DTLS connection exported and re-imported with wolfSSL_tls_export()/wolfSSL_dtls_export() loses the peer's negotiated record_size_limit. After import it sends full-size records the peer must reject with record_overflow. ExportOptions() and ImportOptions() do not serialize peerRecordSizeLimit, so the imported object starts at 0 and wolfSSL_GetMaxFragSize() applies no cap. Fix: add peerRecordSizeLimit (and recordSizeLimit, for the receive check) to the export blob under HAVE_RECORD_SIZE_LIMIT with an export version bump, so an imported session keeps honouring the peer's limit.

    Why this was flagged

    The trigger is an application built with WOLFSSL_SESSION_EXPORT and HAVE_RECORD_SIZE_LIMIT that exports a live connection (src/ssl_sess.c:3725 / 3792) after the peer advertised a limit below 2^14, then imports it with wolfSSL_tls_import()/wolfSSL_dtls_import(). ExportOptions() (src/internal.c:1514) and ImportOptions() (src/internal.c:1707) do not carry the new peerRecordSizeLimit field from TLSX_RecordSizeLimit_Parse() (src/tls.c:8559). The importing WOLFSSL has peerRecordSizeLimit 0, so wolfSSL_GetMaxFragSize() (src/internal.c:48519) does not cap sends, and the GetRecordHeader() receive check (src/internal.c:14187) is disabled too. Any write above the peer's limit then produces a record the peer must answer with a fatal record_overflow alert, while the original object would have fragmented it. max_fragment is not exported either, so this matches an existing gap for MFL; that shows the path was never covered, not that it is safe now that record_size_limit is advertised by default.

    Verification: Trigger: a build with WOLFSSL_SESSION_EXPORT and HAVE_RECORD_SIZE_LIMIT exports, then imports, a connection whose peer advertised a record_size_limit below 2^14. ExportOptions() (src/internal.c:1514-1690) writes nothing from peerRecordSizeLimit, so wolfSSL_GetMaxFragSize() (48519) returns MAX_RECORD_SIZE and the peer rejects records with record_overflow. On the base, wolfSSL never negotiated record_size_limit.

Comment thread src/tls.c Resolved
Comment thread src/tls.c Resolved
Comment thread src/ssl_api_ext.c Resolved
Comment thread src/ssl_api_ext.c Resolved
@philljj

philljj commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Tests good with multi-test with all-gcc-c89, c89-clang-tidy, sanitize, wolfssl-all, sanitize-tls13, dtls13, etc scenarios.

@philljj philljj left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

merge conflict, and see review items

@philljj philljj assigned SparkiDev and unassigned wolfSSL-Bot Nov 4, 2026
@SparkiDev SparkiDev assigned SparkiDev and unassigned SparkiDev Nov 5, 2026
@SparkiDev
SparkiDev requested review from wolfSSL-Fenrir-bot and a balanced review from Copilot November 5, 2026 07:03
@SparkiDev

Copy link
Copy Markdown
Contributor Author

@claude review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread src/internal.c Resolved
Comment thread src/tls.c Resolved
Comment thread src/tls13.c Resolved
Comment thread src/internal.c Resolved
Comment thread src/internal.c Resolved
Comment thread src/ssl_api_ext.c Resolved
Comment thread src/ssl_api_ext.c Resolved
Comment thread wolfssl/internal.h Resolved

@claude claude 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.

Findings marked 🟡 are optional suggestions and need no follow-up push.

Comment thread src/tls13.c Resolved
Comment thread src/tls.c Resolved
Comment thread src/internal.c Resolved
Comment thread src/ssl_api_ext.c Resolved
Comment thread src/ssl_api_ext.c Resolved

@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 #11362

Scan targets checked: wolfssl-src, wolfssl-bugs
Not reviewed (no scan target covers them): .github/configs/os-check-linux.json, CMakeLists.txt, cmake/options.h.in, configure.ac, doc/dox_comments/header_files/ssl.h, examples/client/client.c, tests/api/test_tls.h, tests/api/test_tls13.h
Coverage: 12 of 21 in-scope changed file(s) opened by the reviewer; not opened: src/dtls13.c, src/ssl_load.c, src/ssl_sess.c, tests/api.c, tests/api/test_compress.c, tests/api/test_dtls13.c, tests/api/test_tls.c, tests/api/test_tls13.c, wolfssl/openssl/ssl.h

Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Review tier: Lite

Comment thread src/internal.c Resolved
Comment thread src/tls13.c Resolved
@philljj philljj removed their assignment Nov 5, 2026
@SparkiDev

Copy link
Copy Markdown
Contributor Author

@claude review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread src/internal.c Resolved
Comment thread src/ssl.c Resolved

@claude claude 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.

Additional findings (outside the current diff — GitHub can't attach inline comments there):

  • 🔴 src/dtls13.c — DTLS 1.3 endpoints that negotiate a small record_size_limit can send ACK records larger than the peer's limit. The peer drops them, so the unacknowledged side retransmits until it times out fatally. Dtls13WriteAckMessage() packs every seen record number, up to DTLS13_ACK_MAX_RECORDS (128), into one protected record. It never checks the peer limit that the handshake fragmentation now honours. Fix: cap each ACK at (wolfssl_local_GetMaxPlaintextSize(ssl) - OPAQUE16_LEN) / DTLS13_RN_SIZE record numbers, and send the rest in further ACK records.

    Why this was flagged

    The trigger is a DTLS 1.3 connection where both ends set a small limit with wolfSSL_CTX_UseRecordSizeLimit(), for example 64 or 256. Dtls13HandshakeSend() splits handshake messages using wolfssl_local_GetMaxPlaintextSize(), which wolfSSL_GetMaxFragSize() now caps at peerRecordSizeLimit, so a flight becomes many small records. SendDtls13Ack() then calls Dtls13WriteAckMessage() (src/dtls13.c:3241-3291), which writes 2 + 16*N bytes into one record and never consults the peer limit. In the peer's GetRecordHeader() (src/internal.c:14509-14611), the record exceeds recordSizeLimitSent + aead_mac_size and gets LENGTH_ERROR. DtlsShouldDrop() then drops it silently. The sender never sees the ACK, keeps retransmitting, and Dtls13RtxTimeout() eventually makes wolfSSL_dtls_got_timeout() return WOLFSSL_FATAL_ERROR. The base branch has no record_size_limit, so this does not happen there.

    Verification: Severity: normal. Dtls13WriteAckMessage() (src/dtls13.c:3241-3243) only checks recordsCount > DTLS13_ACK_MAX_RECORDS and sets msgSz = DTLS13_RN_SIZE * recordsCount. Nothing compares the ACK size against peerRecordSizeLimit. For DTLS, DtlsShouldDrop() (internal.c:26821) silently drops records with LENGTH_ERROR, so the ACK is thrown away.

Comment thread src/internal.c Resolved
Comment thread src/ssl_api_ext.c Resolved

@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 #11362

Scan targets checked: wolfssl-src, wolfssl-bugs
Not reviewed (no scan target covers them): .github/configs/os-check-linux.json, CMakeLists.txt, cmake/options.h.in, configure.ac, doc/dox_comments/header_files/ssl.h, examples/client/client.c, tests/api/test_tls.h, tests/api/test_tls13.h
Coverage: 16 of 22 in-scope changed file(s) opened by the reviewer; not opened: src/ssl_sess.c, tests/api.c, tests/api/test_compress.c, tests/api/test_dtls13.c, tests/api/test_tls.c, wolfssl/openssl/ssl.h

Findings: 3
3 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Review tier: Max

Comment thread src/internal.c Resolved
Comment thread src/ssl_api_ext.c Resolved
Comment thread src/tls.c Resolved
Added support for record_size_limit in TLS 1.3 and TLS 1.2.
Added compress_certificate support for TLS 1.3.
Added signed_certificate_timestamp TLS 1.2 and 1.3.
Added handshake-message fragmentation to EncryptedExtension, CertificateRequest
and NewSessionTicket.
Accepts server_name in CertificateRequest.
Added API for setting signature algorithms for signature_algorithms_cert.

SHA-1 certificate chain fix: a peer advertising ecdsa_sha1 against a chain
with an RSA-SHA1 intermediates will see a failed handshake.

Tests added and interop performed where possible.
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