Target: 2.7.0 (tentative) (Tier 5 — TLS record layer & SNI, stretch)
Context
The record layer itself is trivial. What makes this a whole tier by
itself: a ClientHello's SNI (Server Name Indication) sits behind a
chain of nested, variable-length, length-prefixed structures, and
"no crypto, no full handshake" has to be an enforced boundary, not
an aspiration that erodes as the parsing gets harder.
Deliverable
Add netprotocols.TLS (layer 7, dispatched from tcp.port 443,
best-effort) scoped narrowly to record framing plus SNI extraction:
- Decode the 5-byte TLS record header (RFC 8446 §5.1): Content Type
(1 byte — Handshake is 22, the only one this issue cares about),
Legacy Version (2 bytes), Length (2 bytes).
- For a Handshake-type record, decode the 4-byte handshake header
(Handshake Type 1 byte — ClientHello is 1; Length 3 bytes) and, for
ClientHello only, walk far enough to reach the Extensions block:
Legacy Version (2), Random (32), Legacy Session ID (length-prefixed,
1-byte length), Cipher Suites (length-prefixed, 2-byte length — keep
as raw bytes, not decoded suite-by-suite), Legacy Compression
Methods (length-prefixed, 1-byte length), Extensions (length-
prefixed, 2-byte length).
- Within Extensions, decode only the shape needed to find
server_name (type 0x0000, RFC 6066 §3): each extension is Type (2
bytes), Length (2 bytes), Data. For server_name, Data is itself a
length-prefixed ServerNameList of ServerName entries (Type 1
byte — 0 is host_name, HostName length-prefixed 2 bytes, then the
hostname bytes). Every other extension type stays raw bytes,
correctly bounded by its own Length — this issue is not "decode TLS
extensions," it's "find SNI."
- Content types other than Handshake (Alert 21, ApplicationData 23,
ChangeCipherSpec 20) decode only the 5-byte record header; their
payload stays raw (it's ciphertext past the handshake anyway).
- Register
tcp.port 443 → TLS, best-effort.
Explicitly out of scope
ServerHello, Certificate, key exchange, any extension besides
server_name, TLS 1.2-and-earlier's different extension set, DTLS.
All are real follow-ups, not this issue.
Acceptance criteria
Documentation/marketing-claims cleanup for the roadmap as a whole is
its own issue now (#197), not an acceptance criterion here.
References
RFC 8446 (TLS 1.3 record layer / handshake), RFC 6066 §3 (SNI) ·
docs cleanup: #197
Part of #175
Target: 2.7.0 (tentative) (Tier 5 — TLS record layer & SNI, stretch)
Context
The record layer itself is trivial. What makes this a whole tier by
itself: a ClientHello's SNI (Server Name Indication) sits behind a
chain of nested, variable-length, length-prefixed structures, and
"no crypto, no full handshake" has to be an enforced boundary, not
an aspiration that erodes as the parsing gets harder.
Deliverable
Add
netprotocols.TLS(layer 7, dispatched fromtcp.port443,best-effort) scoped narrowly to record framing plus SNI extraction:
(1 byte — Handshake is 22, the only one this issue cares about),
Legacy Version (2 bytes), Length (2 bytes).
(Handshake Type 1 byte — ClientHello is 1; Length 3 bytes) and, for
ClientHello only, walk far enough to reach the Extensions block:
Legacy Version (2), Random (32), Legacy Session ID (length-prefixed,
1-byte length), Cipher Suites (length-prefixed, 2-byte length — keep
as raw
bytes, not decoded suite-by-suite), Legacy CompressionMethods (length-prefixed, 1-byte length), Extensions (length-
prefixed, 2-byte length).
server_name(type 0x0000, RFC 6066 §3): each extension is Type (2bytes), Length (2 bytes), Data. For
server_name, Data is itself alength-prefixed
ServerNameListofServerNameentries (Type 1byte — 0 is
host_name, HostName length-prefixed 2 bytes, then thehostname bytes). Every other extension type stays raw
bytes,correctly bounded by its own Length — this issue is not "decode TLS
extensions," it's "find SNI."
ChangeCipherSpec 20) decode only the 5-byte record header; their
payload stays raw (it's ciphertext past the handshake anyway).
tcp.port443 →TLS, best-effort.Explicitly out of scope
ServerHello, Certificate, key exchange, any extension besides
server_name, TLS 1.2-and-earlier's different extension set, DTLS.All are real follow-ups, not this issue.
Acceptance criteria
TLSdecodes the record header for every content type; forHandshake/ClientHello, decodes far enough to extract SNI when
present.
bytes(TLS.decode(x)) == x.at least two different browsers/clients (extension ordering and
padding conventions vary).
server_nameextension, and one with atruncated Extensions block, both decode without raising outside
the library's normal
ProtocolErrorcontract.TLS.boundary explicitly; full ladder green.
Documentation/marketing-claims cleanup for the roadmap as a whole is
its own issue now (#197), not an acceptance criterion here.
References
RFC 8446 (TLS 1.3 record layer / handshake), RFC 6066 §3 (SNI) ·
docs cleanup: #197
Part of #175