Fix TLS 1.3 record padding handling in _nx_secure_tls_process_record (RFC 8446 §5.4)#401
Open
EdouardMALOT wants to merge 1 commit into
Open
Conversation
…C 8446 §5.4) The inner content type was read as the literal last byte of the decrypted plaintext. Per RFC 8446 §5.4 that byte is followed by an arbitrary-length zero padding, so the receiver must scan back from the end skipping zeros to find it. Without this, any client that pads its TLS 1.3 records gets a fatal `unexpected_message` alert on its first record. Java JDK HttpClient pads by default since 11 (traffic-analysis resistance), so every Java HTTPS client tripped on this. Reproducible with OpenSSL using `-record_padding N`.
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
A TLS 1.3 peer that pads its records cannot talk to NetX Duo: the very first padded record is rejected and the connection is torn down with a fatal alert.
Per RFC 8446 §5.4, the decrypted TLS 1.3 record is:
The receiver must scan from the end of the plaintext, skipping zero bytes, to find the inner content type.
_nx_secure_tls_process_record()instead reads the literal last byte as the content type and strips exactly one byte. For any padded record the extracted type is0x00(invalid, later rejected as an unrecognized message type), and the padding bytes would remain inside the message content.Record padding is not exotic: the Java JDK (11+) TLS 1.3 implementation sends padded records (encountered in the field with a Java client), and OpenSSL produces them with
-record_padding N.Changes
nx_secure/src/nx_secure_tls_process_record.c— after decryption of a TLS 1.3 record, scan backward from the end of the plaintext skipping zero bytes; the first non-zero byte is the inner content type, and the message length is set to exclude the type byte and the padding. A plaintext consisting only of zeros is rejected (NX_SECURE_TLS_INVALID_PACKET), as required by §5.4 ("If a receiving implementation does not find a non-zero octet in the cleartext, it MUST terminate the connection").Unpadded records take the same path as before: the first byte inspected (the last plaintext byte) is non-zero and the resulting length is unchanged.
Note: for the all-zeros case, RFC 8446 prescribes an
unexpected_messagealert;NX_SECURE_TLS_INVALID_PACKETcurrently maps to the internal-error alert group in_nx_secure_tls_map_error_to_alert(). The connection is still terminated with a fatal alert; happy to adjust the mapping if a stricter alert code is preferred.Test plan
-record_padding N: handshake and application data exchange succeed