quic_tls (quic v1.3.0)
View SourceTLS 1.3 message generation and parsing for QUIC.
This module handles TLS 1.3 handshake messages as they appear in QUIC CRYPTO frames. Messages are encoded without the TLS record layer.
TLS Messages in QUIC
QUIC uses TLS 1.3 for the cryptographic handshake, but without the TLS record layer. TLS handshake messages are sent directly in CRYPTO frames.
Summary
Functions
Build Certificate message. Certs is a list of DER-encoded certificates (server cert first).
Build a CertificateRequest message (RFC 8446 Section 4.3.2). Context is the certificate_request_context (typically empty for TLS 1.3).
Build CertificateVerify message. PrivateKey is the server's private key. TranscriptHash is the hash of all handshake messages up to (not including) CertificateVerify.
Build a CertificateVerify message for client (RFC 8446 Section 4.4.3). Uses "TLS 1.3, client CertificateVerify" context string.
Build a TLS 1.3 ClientHello message for QUIC. Options: - server_name: SNI hostname (binary) - alpn: List of ALPN protocols (list of binaries) - transport_params: QUIC transport parameters (map) - session_ticket: #session_ticket{} for resumption with PSK (optional)
Build EncryptedExtensions message. Options: - alpn: Selected ALPN protocol - transport_params: QUIC transport parameters
Build a Finished message. VerifyData should be computed using quic_crypto:compute_finished_verify/2.
Build a ServerHello message. Options: - random: Server random (32 bytes, generated if not provided) - session_id: Legacy session ID to echo - cipher_suite: Selected cipher suite - key_share: Server's public key
Decode a TLS handshake message. Returns {Type, Body, Rest} or {error, Reason}.
Decode preferred_address transport parameter (RFC 9000 Section 18.2). Format: IPv4 address: 4 bytes IPv4 port: 2 bytes IPv6 address: 16 bytes IPv6 port: 2 bytes CID length: 1 byte Connection ID: variable (0-20 bytes) Stateless reset: 16 bytes
Decode QUIC transport parameters. RFC 9000 Section 7.4: Validates against duplicate parameters and semantic constraints
Encode a TLS handshake message with type and length.
Encode preferred_address transport parameter (RFC 9000 Section 18.2).
Encode QUIC transport parameters. Params is a map with keys like: original_dcid, max_idle_timeout, max_udp_payload_size, initial_max_data, initial_max_stream_data_bidi_local, etc.
Parse Certificate message.
Parse a CertificateRequest message.
Parse CertificateVerify message.
Parse a ClientHello message. Returns a map with: - random: 32-byte client random - session_id: Legacy session ID - cipher_suites: List of cipher suites offered - extensions: Map of extensions - key_share: Client's public key for key exchange - server_name: SNI hostname (if present) - alpn_protocols: List of ALPN protocols (if present) - transport_params: QUIC transport parameters (if present)
Parse EncryptedExtensions message.
Parse Finished message.
Parse a ServerHello message. Returns server's public key and selected cipher suite.
Verify CertificateVerify signature. Role is 'client' or 'server' - determines context string.
Verify a Finished message (default SHA-256). TrafficSecret is the sender's traffic secret. TranscriptHash is the hash of all messages up to (but not including) Finished.
Verify a Finished message with cipher-specific hash.
Functions
Build Certificate message. Certs is a list of DER-encoded certificates (server cert first).
Build a CertificateRequest message (RFC 8446 Section 4.3.2). Context is the certificate_request_context (typically empty for TLS 1.3).
-spec build_certificate_verify(non_neg_integer(), crypto:key_id(), binary()) -> binary().
Build CertificateVerify message. PrivateKey is the server's private key. TranscriptHash is the hash of all handshake messages up to (not including) CertificateVerify.
-spec build_certificate_verify_client(non_neg_integer(), term(), binary()) -> binary().
Build a CertificateVerify message for client (RFC 8446 Section 4.4.3). Uses "TLS 1.3, client CertificateVerify" context string.
Build a TLS 1.3 ClientHello message for QUIC. Options: - server_name: SNI hostname (binary) - alpn: List of ALPN protocols (list of binaries) - transport_params: QUIC transport parameters (map) - session_ticket: #session_ticket{} for resumption with PSK (optional)
Returns: {ClientHelloMsg, PrivateKey, Random}
Build EncryptedExtensions message. Options: - alpn: Selected ALPN protocol - transport_params: QUIC transport parameters
Build a Finished message. VerifyData should be computed using quic_crypto:compute_finished_verify/2.
Build a ServerHello message. Options: - random: Server random (32 bytes, generated if not provided) - session_id: Legacy session ID to echo - cipher_suite: Selected cipher suite - key_share: Server's public key
-spec decode_handshake_message(binary()) -> {ok, {non_neg_integer(), binary()}, binary()} | {error, term()}.
Decode a TLS handshake message. Returns {Type, Body, Rest} or {error, Reason}.
-spec decode_preferred_address(binary()) -> #preferred_address{ipv4_addr :: inet:ip4_address() | undefined, ipv4_port :: inet:port_number() | undefined, ipv6_addr :: inet:ip6_address() | undefined, ipv6_port :: inet:port_number() | undefined, cid :: binary(), stateless_reset_token :: binary()}.
Decode preferred_address transport parameter (RFC 9000 Section 18.2). Format: IPv4 address: 4 bytes IPv4 port: 2 bytes IPv6 address: 16 bytes IPv6 port: 2 bytes CID length: 1 byte Connection ID: variable (0-20 bytes) Stateless reset: 16 bytes
Decode QUIC transport parameters. RFC 9000 Section 7.4: Validates against duplicate parameters and semantic constraints
-spec encode_handshake_message(non_neg_integer(), binary()) -> binary().
Encode a TLS handshake message with type and length.
-spec encode_preferred_address(#preferred_address{ipv4_addr :: inet:ip4_address() | undefined, ipv4_port :: inet:port_number() | undefined, ipv6_addr :: inet:ip6_address() | undefined, ipv6_port :: inet:port_number() | undefined, cid :: binary(), stateless_reset_token :: binary()}) -> binary().
Encode preferred_address transport parameter (RFC 9000 Section 18.2).
Encode QUIC transport parameters. Params is a map with keys like: original_dcid, max_idle_timeout, max_udp_payload_size, initial_max_data, initial_max_stream_data_bidi_local, etc.
-spec parse_certificate(binary()) -> {ok, #{context := binary(), certificates := [binary()]}} | {error, term()}.
Parse Certificate message.
Parse a CertificateRequest message.
-spec parse_certificate_verify(binary()) -> {ok, #{algorithm := non_neg_integer(), signature := binary()}} | {error, term()}.
Parse CertificateVerify message.
Parse a ClientHello message. Returns a map with: - random: 32-byte client random - session_id: Legacy session ID - cipher_suites: List of cipher suites offered - extensions: Map of extensions - key_share: Client's public key for key exchange - server_name: SNI hostname (if present) - alpn_protocols: List of ALPN protocols (if present) - transport_params: QUIC transport parameters (if present)
-spec parse_encrypted_extensions(binary()) -> {ok, #{alpn => binary(), transport_params => map()}} | {error, term()}.
Parse EncryptedExtensions message.
Parse Finished message.
-spec parse_server_hello(binary()) -> {ok, #{public_key := binary(), cipher := atom(), random := binary()}} | {error, term()}.
Parse a ServerHello message. Returns server's public key and selected cipher suite.
Verify CertificateVerify signature. Role is 'client' or 'server' - determines context string.
Verify a Finished message (default SHA-256). TrafficSecret is the sender's traffic secret. TranscriptHash is the hash of all messages up to (but not including) Finished.
Verify a Finished message with cipher-specific hash.