Fix TLS 1.3 CertificateVerify transcript hash length (use ciphersuite hash) - #417
Open
EdouardMALOT wants to merge 2 commits into
Open
Conversation
… hash) Per RFC 8446 §4.4.3 the CertificateVerify content embeds Transcript-Hash(Handshake Context), whose length is fixed by the negotiated ciphersuite's hash — not by the signature scheme's hash. The dynamic length introduced during the eclipse-threadx#377 review keyed it to the signature scheme's hash; the two differ whenever the peer signs with a hash other than the suite's, e.g. an ECDSA P-384 certificate (ecdsa_secp384r1_sha384) with TLS_AES_128_GCM_SHA256 — the only TLS 1.3 suite currently enabled. In that case 48 bytes were copied from a 32-byte transcript hash slot, corrupting the signed content on the send side and rejecting valid peer signatures on the verify side. Key the transcript length to the session ciphersuite hash (with the same SHA-256 fallback as _nx_secure_tls_1_3_transcript_hash_save); the signature scheme's hash still digests the assembled content and parameterizes RSA-PSS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
EdouardMALOT
force-pushed
the
fix/tls13-certverify-transcript-hash-length
branch
2 times, most recently
from
August 6, 2026 12:19
0016490 to
ced5aae
Compare
…sh length Calls _nx_secure_tls_send_certificate_verify and _nx_secure_tls_process_certificate_verify directly with a signature-scheme hash (SHA-384) that differs from the ciphersuite hash (SHA-256), and captures via a spy hash method the exact byte count copied into the CertificateVerify content. Asserts 32 bytes (the ciphersuite's SHA-256, correct per RFC 8446 §4.4.3), not 48 (the signature scheme's SHA-384, what the bug copied).
EdouardMALOT
force-pushed
the
fix/tls13-certverify-transcript-hash-length
branch
from
August 6, 2026 12:40
ced5aae to
9de2760
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to the #377 review discussion (#377 (comment)):
the dynamic transcript-hash length introduced there is keyed to the signature scheme's
hash, but per RFC 8446 §4.4.3 the
CertificateVerify content embeds
Transcript-Hash(Handshake Context), whose length is fixedby the negotiated ciphersuite's hash. The two differ whenever a peer signs with a hash
other than the suite's.
Concrete case with the only TLS 1.3 suite currently enabled (
TLS_AES_128_GCM_SHA256):an ECDSA P-384 certificate signs
ecdsa_secp384r1_sha384, so 48 bytes are copied from a32-byte transcript-hash slot (
nx_secure_tls_transcript_hashes[..][NX_SECURE_TLS_MAX_HASH_SIZE]with
NX_SECURE_TLS_MAX_HASH_SIZE == 32). This corrupts the signed content on the send sideand rejects valid peer signatures on the verify side — TLS 1.3 no longer works with ECDSA
P-384/P-521 certificates (it did before #377, when the copy length was a constant 32,
which was correct for every configuration shipped at the time).
The concern raised in the review remains fully addressed: the length is not hardcoded, and
SHA-384/512 ciphersuites will produce 48/64-byte transcript hashes when they are enabled.
Changes
nx_secure/src/nx_secure_tls_send_certificate_verify.c— key the transcript-hash copylength to
nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash(SHA-256 fallback,mirroring
_nx_secure_tls_1_3_transcript_hash_save). The signature scheme's hash stilldigests the assembled content and parameterizes RSA-PSS.
nx_secure/src/nx_secure_tls_process_certificate_verify.c— same fix on the verify side.test/regression/nx_secure_test/nx_secure_tls_1_3_certverify_transcript_hash_test.c—regression test calling both functions directly with a signature-scheme hash (SHA-384) that
differs from the ciphersuite hash (SHA-256), capturing via a spy hash method the exact byte
count copied into the CertificateVerify content. Asserts 32 bytes (ciphersuite SHA-256,
correct), not 48 (signature-scheme SHA-384, what the bug copied).
Test plan
completes the handshake against a broker presenting EC P-384 and P-521 server
certificates (
ecdsa_secp384r1_sha384/ecdsa_secp521r1_sha512), where it previouslyrejected the broker's valid CertificateVerify signature. A P-256 control case (unaffected
by the bug, same hash on both sides) continues to pass throughout.
Related: #377, #399, #161.