You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
Richard Wheeler
committed
net.quic: 13a - ServerHello + EncryptedExtensions construction
First slice of the TLS 1.3 server handshake (Phase 13a): build_server_hello
and build_encrypted_extensions, the server-role mirror of the existing
client-role build_client_hello. Both round-trip through this file's own
parse_server_hello/parse_encrypted_extensions, which is a real cross-check
since build and parse were each derived independently from the RFC 8446
text rather than from each other.
Caught one real bug via the round-trip test before committing: a server's
key_share extension is a bare KeyShareEntry (RFC 8446 SS4.2.8), not the
list-wrapped KeyShareClientHello shape build_client_hello's own
encode_key_share_extension produces -- needed a dedicated
encode_key_share_extension_server. Same asymmetry already existed and was
handled correctly for supported_versions (bare 2 bytes server-side vs. a
length-prefixed list client-side); this is the identical class for
key_share, not a new discovery about the protocol.
build_encrypted_extensions enforces the two mandatory transport parameters
RFC 9000 SS7.3 requires an endpoint (initial_source_connection_id) and a
server specifically (original_destination_connection_id) to always include,
mirroring build_client_hello's identical enforcement of its own mandatory
field.
Still to come within 13a: Certificate presentation, CertificateVerify
signing, server Finished, HelloRetryRequest generation.
returnerror('quic: ServerHello random must be exactly 32 bytes, got ${p.random.len}')
376
+
}
377
+
if p.random== hello_retry_request_random[..] {
378
+
returnerror('quic: ServerHello random must not equal the RFC 8446 §4.1.3 HelloRetryRequest magic value -- use build_hello_retry_request to send an HRR')
379
+
}
380
+
381
+
mutbody:= []u8{}
382
+
// legacy_version MUST be 0x0303 (RFC 8446 §4.1.3), matching
383
+
// build_client_hello's identical fixed value -- the real version is
384
+
// negotiated via supported_versions below.
385
+
body <<u8(0x03)
386
+
body <<u8(0x03)
387
+
body << p.random
388
+
// legacy_session_id_echo: always empty, see the doc comment above.
389
+
body <<u8(0)
390
+
body <<u8(cipher_suite_tls_aes_128_gcm_sha256>>8)
391
+
body <<u8(cipher_suite_tls_aes_128_gcm_sha256)
392
+
// legacy_compression_method MUST be 0 (null), RFC 8446 §4.1.3.
returnerror('quic: EncryptedExtensions must select exactly one ALPN protocol (RFC 7301 §3.2) -- a server with no match must fail the handshake before reaching here (RFC 9001 §8.1)')
445
+
}
446
+
// RFC 9000 §7.3 / §18.2: "An endpoint MUST treat the absence of the
447
+
// initial_source_connection_id transport parameter from either endpoint
448
+
// ... as a connection error of type TRANSPORT_PARAMETER_ERROR" -- this
449
+
// server's own SCID choice, mirroring build_client_hello's identical
450
+
// check for the client's own value.
451
+
if p.transport_parameters.initial_source_connection_id==none {
452
+
returnerror('quic: EncryptedExtensions transport parameters must include initial_source_connection_id (RFC 9000 §7.3)')
453
+
}
454
+
// RFC 9000 §7.3/§18.2: "...or the absence of the
455
+
// original_destination_connection_id transport parameter from the
456
+
// server as a connection error of type TRANSPORT_PARAMETER_ERROR" --
457
+
// unlike initial_source_connection_id, this one is server-only and has
458
+
// no client-side analog to mirror.
459
+
if p.transport_parameters.original_destination_connection_id==none {
460
+
returnerror('quic: EncryptedExtensions transport parameters must include original_destination_connection_id (RFC 9000 §7.3, server-only)')
0 commit comments