Expand description
macula 12’s post-quantum connection handshake, as macula_handshake and macula-go build and check it: the opener, challenge, CONNECT, HELLO and status frames (D16, D22), as CBOR bytes without the length prefix.
The client opens with an opener. The station answers with a challenge: its carried identity key, its TLS binding and status statement, and a fresh nonce. The client checks the challenge against the node_id it dialed and the leaf it received, before it signs anything, and answers with CONNECT: its identity and CONNECT keys, the CONNECT binding and status statement, and a proof by the CONNECT key. The station checks CONNECT, the puzzle before any signature, and answers with HELLO. Status frames renew a peer’s statement on the open connection.
Every frame decodes under the decoding rule and must hold exactly the keys of its type, each of its type and length. Close reasons are local: a refusing station sends only a HELLO with one coarse refusal code.
Version 5 (macula 13.2, DESIGN_NEIGHBOUR_CHANNEL_BINDING) binds both ends
to the TLS session. The opener and the challenge stay version 4; the client
picks 4 or 5 in CONNECT, and the station answers HELLO in the same version.
In version 5 the CONNECT proof (V2) also covers E, the session’s TLS
exporter value, and the client’s capabilities, and HELLO carries the
station’s session proof, signed by its identity key over E, both frames and
both node_ids, only after every check on CONNECT has passed. A station with
no exporter answers a v5 CONNECT as an old station does, with
unsupported_version.
Structs§
- Client
- What a station knows of an accepted client.
- Client
Session - What a client brings to a handshake: its profile, the node_id it dialed,
the leaf DER it received in this TLS handshake, its carried identity key,
its CONNECT key with binding and status statement, its capability bits,
the time in milliseconds, the realm membership endorsement CONNECT
carries, empty for a node that holds none, the version CONNECT carries
(
VERSIONorVERSION_5), and this connection’s TLS exporter, which version 5 needs. - Peer
- What a connection checks a peer’s status frames against: the profile, the identity key and binding the handshake verified, and the time in milliseconds.
- Station
- What a client knows of the station once it has checked the challenge, and what its HELLO must answer: the version the CONNECT carried and, in version 5, what the session proof covers.
- Station
Material - What a station precomputes for its challenges: its carried identity key, and the TLS binding and status statement for the leaf it presents.
- Station
Session - What a station brings to a CONNECT check: its profile, the challenge bytes
it sent, the leaf DER this connection presented, its puzzle difficulty and
mode, its capability bits, the time in milliseconds, and what it binds a v5
session with. Without
v5it answers only version 4. - Station
V5 - A station’s means to bind a v5 session: this connection’s TLS exporter, and its session proof signer.
Enums§
- Handshake
Error - The handshake’s close reasons, named as macula names them. A binding or
status statement that fails its check closes with its
BindingError. - Puzzle
Mode - How a station treats a client’s node_id puzzle.
- Puzzle
Result - What a station found of a client’s puzzle.
- Refusal
Code - The one coarse reason a refusing HELLO carries.
Constants§
- EXPORTER_
LABEL - The TLS 1.3 exporter label (RFC 8446 section 7.5) handshake v5 binds to, over the context client node_id || station node_id, 32 bytes.
- VERSION
- The handshake’s frame version: 4, as macula 12’s. A peer on another version
hears
unsupported_version. - VERSION_
5 - The channel-bound handshake: both proofs over the TLS session’s exporter value.
Functions§
- accept_
connect - Checks a CONNECT, and returns the verdict with the HELLO to send. It checks, in macula’s order: the frame, the carried keys and the proof’s length, that each key serves one purpose, the puzzle on the derived node_id before any signature, the CONNECT binding and status statement, and the proof against the challenge this station sent and the leaf it presented. A refusal is the local close reason, and the HELLO refuses with one coarse code.
- answer_
challenge - Checks a challenge and, when every check passes, returns the CONNECT to send. It checks, in macula’s order: the frame, the profile, the station’s carried key, that each key in view serves one purpose, the station’s node_id against the one dialed, the TLS binding against the leaf received, and the status statement. It signs nothing before all of them pass.
- challenge
- A station’s challenge, with a fresh nonce. The station keeps the bytes it sends, for the proof check.
- opener
- The client’s first frame on the control stream. It carries nothing that relates to identity.
- read_
hello - The client’s reading of HELLO against the version its CONNECT carried
(
station, asanswer_challengereturned it): the station’s capability bits, or why not. After a v5 CONNECT an accepting HELLO must be version 5 with a session proof that verifies under the station’s identity key over this session. A v4 refusal is how an old station answers (HandshakeError::Refused); a v4 acceptance is never taken as a v4 connection. - read_
opener - The station’s check of the first frame.
- read_
status - Checks a peer’s status frame, and returns when its statement expires.
- status_
frame - A status frame carrying a fresh status statement, sent at every reissue.
Type Aliases§
- Exporter
- A TLS 1.3 session’s exporter: label, context and length to bytes, or
Nonewhen the session gives none. Both ends of one session export the same bytes. - Session
Proof Signer - Signs a v5 session proof with the station’s identity key for the client
named, within the station’s budget (
HandshakeError::SessionProofRatepast it).