Skip to main content
Experimental Crate: codec

seleniumbase_rs_codec::client_hello parses a captured TLS ClientHello incrementally, from the record header onwards, without trusting its lengths. ClientHello::needed_len tells a capture loop how many bytes make up the first handshake message while it is still arriving, and ClientHello::parse decodes the whole message, which may span several TLS records. Every length is checked against the bytes that remain, so hostile or truncated input returns a ClientHelloError and never panics. GREASE values (RFC 8701) are kept as received; the JA3, JA4 and spec builders strip them.

ClientHello#

struct

A parsed ClientHello, with the typed fields the fingerprints read. Lists keep GREASE values and wire order. When an extension occurs twice, the typed field holds the value of its first occurrence; extensions keeps both.

record_versionu16#

Version in the record header of the first record.

legacy_versionu16#

The client_version field of the handshake message (771 for TLS 1.2 and 1.3 clients).

random[u8; 32]#

The 32 random bytes.

session_idVec<u8>#

The legacy session id (at most 32 bytes).

cipher_suitesVec<u16>#

Cipher suites in wire order.

compression_methodsVec<u8>#

Compression methods in wire order.

extensionsVec<Extension>#

Every extension in wire order, with its raw body.

sniOption<String>#

The first host name of server_name.

alpnVec<Vec<u8>>#

ALPN protocol names in wire order.

supported_versions, supported_groupsVec<u16>#

The two lists as sent.

key_share_groupsVec<u16>#

The group of each key_share entry, in wire order; the key exchange bytes are skipped.

point_formatsVec<u8>#

ec_point_formats as sent.

signature_algorithmsVec<u16>#

signature_algorithms as sent.

psk_modesVec<u8>#

psk_key_exchange_modes as sent.

cert_compressionVec<u16>#

compress_certificate algorithms as sent.

alpsVec<Vec<u8>>#

Protocols of application_settings, on either codepoint.

record_size_limitOption<u16>#

The value of record_size_limit.

delegated_credentialsVec<u16>#

delegated_credential signature schemes as sent.

ClientHello::needed_len#

method

How many bytes the first ClientHello occupies, as far as prefix shows. Returns the byte length of all records that carry the message once the headers seen so far make it known (it may exceed prefix.len()), and None while more bytes are needed. A capture loop reads until the answer is at most the bytes it holds. Each call costs at most MAX_HELLO_RECORDS record headers, however the prefix arrived.

returnsResult<Option<usize>, ClientHelloError>#

Fails as soon as the bytes cannot be a ClientHello: NotHandshake, NotClientHello, Length for a bad record length, TooLarge and TooManyRecords.

ClientHello::parse#

method

Parses the first ClientHello in records, reassembled across handshake records. Bytes after the message (further records) are ignored. Returns ClientHelloError::Truncated when the message is incomplete and another variant when it is malformed; nothing in the input can make it panic.

ClientHello::extension, has_extension, extension_ids, has_grease#

method

The first extension with this id; whether the hello carries one; the extension ids in wire order, GREASE included; and whether a GREASE value appears in the ciphers, extensions, versions, groups or key shares.

Extension#

struct

One extension as it arrived.

idu16#

The extension type.

dataVec<u8>#

The body, without the id and length prefix.

ClientHelloError#

enum

Why a byte stream is not a usable ClientHello.

ClientHelloErrorenum#

without_grease#

fn

Returns values without its GREASE entries, in the same order.

is_grease#

fn

Whether id is a GREASE value (RFC 8701): both bytes are equal and the low nibble is 0xA. Defined in ids and re-exported here.

Constants#

const

The largest ClientHello handshake message, header included, that the parser accepts; and the most TLS records one ClientHello may span. A 64 KiB message fits four full records, so the record limit allows any fragmentation a client stack would use, and no peer can make the readers walk more than that many record headers per call.

ext_id#

mod

The extension ids the parser decodes, plus the ones the spec layer reasons about. ALPS_OLD and ALPS are application_settings on its old and new codepoint; TRUST_ANCHORS is the extension that BoringSSL as vendored by btls 0.5.6 cannot emit.