handshake

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 20, 2026 License: BSD-2-Clause Imports: 19 Imported by: 0

Documentation

Overview

Package handshake provides TLS 1.2 handshake message marshaling/unmarshaling and the multi-hash transcript accumulator (RFC 5246 §7.4).

Only wire-format work is done here. No TLS state machine, no key derivation.

Index

Constants

This section is empty.

Variables

View Source
var ErrGOSTRootsRequired = errors.New("tls: GOST-signed server certificate but no GOSTRoots configured")

ErrGOSTRootsRequired is returned when the server presents a GOST-signed certificate but ClientParams.GOSTRoots is empty. Set GOSTRoots (a []*x509gost.Certificate) before calling Handshake, or set InsecureSkipVerify to bypass verification entirely.

Functions

func AvailableSuites

func AvailableSuites() []uint16

AvailableSuites returns the list of cipher suite IDs that can be negotiated in this phase, filtered to the cipher families listed in availableCipherNames.

func MarshalMessage

func MarshalMessage(m Message) []byte

MarshalMessage wraps a Message in the 4-byte handshake envelope: uint8 msg_type + uint24 length + body. Per RFC 5246 §7.4, this is what goes into the transcript hash.

Types

type Certificate

type Certificate struct {
	// Certificates holds parsed *x509.Certificate values when available.
	// May be nil if the certs were not parsed (e.g. raw test data).
	Certificates []*x509.Certificate

	// RawCerts holds the DER-encoded certificates as received on the wire.
	// This is the authoritative source for marshaling and is always populated.
	RawCerts [][]byte
}

Certificate is the TLS 1.2 Certificate message (RFC 5246 §7.4.2). The certificate_list uses 24-bit length prefixes both for the outer list and for each individual certificate.

func (*Certificate) Marshal

func (m *Certificate) Marshal() []byte

Marshal serializes the Certificate body.

func (*Certificate) Type

func (m *Certificate) Type() Type

type CertificateRequest

type CertificateRequest struct {
	CertificateTypes       []uint8
	SupportedSignatureAlgs []SigAndHash
	CertificateAuthorities [][]byte
}

CertificateRequest is the TLS 1.2 CertificateRequest message (RFC 5246 §7.4.4). This message is sent by the server when it requires client authentication. The client never sends this message; Marshal returns nil.

func (*CertificateRequest) Marshal

func (m *CertificateRequest) Marshal() []byte

Marshal returns nil — the client never sends CertificateRequest.

func (*CertificateRequest) Type

func (m *CertificateRequest) Type() Type

type CertificateVerify

type CertificateVerify struct {
	Algorithm SigAndHash
	Signature []byte
}

CertificateVerify is the TLS 1.2 CertificateVerify message (RFC 5246 §7.4.8). Format: SignatureAndHashAlgorithm (2 bytes) + uint16 signature length + signature.

func (*CertificateVerify) Marshal

func (m *CertificateVerify) Marshal() []byte

func (*CertificateVerify) Type

func (m *CertificateVerify) Type() Type

type ClientCertificate

type ClientCertificate struct {
	// RawCertificate holds the DER-encoded certificate. Must be non-empty when
	// used for authentication.
	RawCertificate []byte
	// PrivateKey is the private key corresponding to the certificate's public
	// key. Must be *rsa.PrivateKey or *ecdsa.PrivateKey.
	PrivateKey crypto.PrivateKey
	// Certificate is the parsed certificate (optional; parsed from RawCertificate
	// on demand if nil).
	Certificate *x509.Certificate
}

ClientCertificate holds a client certificate and its private key for mutual TLS authentication. It mirrors tls.Certificate in structure but is internal to the handshake package.

type ClientHello

type ClientHello struct {
	Version            uint16
	Random             [32]byte
	SessionID          []byte
	CipherSuites       []uint16
	CompressionMethods []uint8

	// Extensions — only the subset defined in extensions.go is supported.
	ServerName           string
	SupportedGroups      []uint16
	ECPointFormats       []uint8
	SignatureAlgorithms  []SigAndHash
	ExtendedMasterSecret bool
	RenegotiationInfo    bool
}

ClientHello is the TLS 1.2 ClientHello message (RFC 5246 §7.4.1.2).

func (*ClientHello) Marshal

func (m *ClientHello) Marshal() []byte

Marshal serializes the ClientHello body (without the 4-byte handshake envelope).

func (*ClientHello) Type

func (m *ClientHello) Type() Type

type ClientKeyExchange

type ClientKeyExchange struct {
	Body []byte
}

ClientKeyExchange is the TLS 1.2 ClientKeyExchange message (RFC 5246 §7.4.7). The body is suite-dependent and treated as an opaque blob at this layer.

func (*ClientKeyExchange) Marshal

func (m *ClientKeyExchange) Marshal() []byte

func (*ClientKeyExchange) Type

func (m *ClientKeyExchange) Type() Type

type ClientParams

type ClientParams struct {
	// Rand is the source of randomness for client random and ephemeral keys.
	Rand io.Reader

	// ServerName is sent in the SNI extension (if non-empty).
	ServerName string

	// OfferedSuites is the list of cipher suite IDs to offer. Must not be empty.
	OfferedSuites []uint16

	// RootCAs is the trust store for certificate verification. If nil, the
	// platform default is used.
	RootCAs *x509.CertPool

	// InsecureSkipVerify skips certificate verification when true.
	InsecureSkipVerify bool

	// VerifyPeerCertificate is called after normal cert verification.
	VerifyPeerCertificate func([][]byte, [][]*x509.Certificate) error

	// GOSTRoots is the trust store for GOST-signed server certificates.
	// It must be a []*x509gost.Certificate. Typed as any so the field's
	// signature does not force every importer of this package to depend on
	// x509gost; cert_gost.go type-asserts it.
	GOSTRoots any

	// GOSTIntermediates is an optional pool of GOST-signed intermediate CA
	// certificates used to bridge a GOST leaf to a root in GOSTRoots, mirroring
	// x509gost.VerifyOptions.GOSTIntermediates. Leave nil for a direct
	// leaf-signed-by-root (depth-1) chain. Like GOSTRoots it must be a
	// []*x509gost.Certificate and is typed as any so the field does not force
	// importers to depend on x509gost; cert_gost.go type-asserts it.
	GOSTIntermediates any

	// Certificates contains client certificates for mutual TLS authentication.
	// When the server sends a CertificateRequest, the first entry is offered.
	// If empty or no supported signature algorithm is found, an empty Certificate
	// message is sent (which is legal per RFC 5246 §7.4.6).
	Certificates []ClientCertificate
}

ClientParams carries the inputs the client state machine needs.

type ClientState

type ClientState struct {
	// contains filtered or unexported fields
}

ClientState holds the mutable state for a client handshake.

func NewClientState

func NewClientState(layer *record.Layer, params ClientParams) *ClientState

NewClientState creates a new client handshake state machine.

func (*ClientState) Handshake

func (c *ClientState) Handshake() error

Handshake runs the full TLS 1.2 client handshake. On success, layer is fully configured for application data. On failure, a fatal alert has been sent and the error is returned.

type Finished

type Finished struct {
	VerifyData []byte
}

Finished is the TLS 1.2 Finished message (RFC 5246 §7.4.9). verify_data is 12 bytes for standard TLS 1.2. For GOST 2018 key-exchange suites (0xC100 / 0xC101) it is 32 bytes (ssl/t1_enc.c:tls1_final_finish_mac).

func (*Finished) Marshal

func (m *Finished) Marshal() []byte

func (*Finished) Type

func (m *Finished) Type() Type

type Message

type Message interface {
	// Type returns the handshake message type byte.
	Type() Type
	// Marshal returns the serialized body of the message (without the 4-byte envelope).
	Marshal() []byte
}

Message is a handshake message that can report its type and marshal its body.

func ParseMessage

func ParseMessage(data []byte) (Message, []byte, error)

ParseMessage parses a single handshake message from data. It returns the parsed Message, any remaining bytes after the message, and an error. Returns an error for unknown message types, truncated data, or malformed bodies.

type RawMessage

type RawMessage struct {
	MsgType Type
	Body    []byte
}

RawMessage allows constructing arbitrary wire-format messages for testing. It uses a pre-built body and a specified type. Used in tests to inject malformed extension data without going through the high-level constructors.

func (*RawMessage) Marshal

func (r *RawMessage) Marshal() []byte

func (*RawMessage) Type

func (r *RawMessage) Type() Type

type ServerHello

type ServerHello struct {
	Version           uint16
	Random            [32]byte
	SessionID         []byte
	CipherSuite       uint16
	CompressionMethod uint8

	// Extensions.
	ExtendedMasterSecret bool
	RenegotiationInfo    bool

	// ExtensionTypes lists the extension type codes present in the message, in
	// the order received, so the caller can verify the server only returned
	// extensions the client offered (RFC 5246 §7.4.1.4).
	ExtensionTypes []uint16
}

ServerHello is the TLS 1.2 ServerHello message (RFC 5246 §7.4.1.3).

func (*ServerHello) Marshal

func (m *ServerHello) Marshal() []byte

Marshal serializes the ServerHello body.

func (*ServerHello) Type

func (m *ServerHello) Type() Type

type ServerHelloDone

type ServerHelloDone struct{}

ServerHelloDone is the TLS 1.2 ServerHelloDone message (RFC 5246 §7.4.5). It has a zero-length body.

func (*ServerHelloDone) Marshal

func (m *ServerHelloDone) Marshal() []byte

func (*ServerHelloDone) Type

func (m *ServerHelloDone) Type() Type

type ServerKeyExchange

type ServerKeyExchange struct {
	Body []byte
}

ServerKeyExchange is the TLS 1.2 ServerKeyExchange message (RFC 5246 §7.4.3). The body is suite-dependent and treated as an opaque blob at this layer. Phase 5 parses the inner structure per key-exchange algorithm.

func (*ServerKeyExchange) Marshal

func (m *ServerKeyExchange) Marshal() []byte

func (*ServerKeyExchange) Type

func (m *ServerKeyExchange) Type() Type

type SigAndHash

type SigAndHash struct {
	Hash uint8
	Sig  uint8
}

SigAndHash is the SignatureAndHashAlgorithm struct from RFC 5246 §7.4.1.4.1. Hash and Sig are raw byte values from the TLS registry.

type Transcript

type Transcript struct {
	// contains filtered or unexported fields
}

Transcript accumulates the bytes of handshake messages for use in the PRF and CertificateVerify computation (RFC 5246 §7.4.9).

Every call to Write appends its argument to an internal buffer. Sum(factory) creates a fresh hash via factory(), feeds the accumulated buffer into it, and returns the resulting digest. The buffer is never reset; successive calls to Sum with different factories each replay the full byte sequence independently.

Accumulation is bounded by maxTranscriptBytes: once the buffer would exceed the cap, Write stops appending and marks the transcript overflowed, and every subsequent Sum returns an error so the handshake fails closed rather than trusting a truncated transcript or exhausting memory.

There is no internal hash tracking, no identity state, and no Collapse method. Two factories with identical BlockSize and Size (e.g. SHA-256 and a shape-matched fake) produce distinct digests because the factory itself, not its shape, determines the hash computation.

func NewTranscript

func NewTranscript() *Transcript

NewTranscript returns a new, empty Transcript.

func (*Transcript) Overflowed

func (t *Transcript) Overflowed() bool

Overflowed reports whether Write has rejected data because the transcript reached maxTranscriptBytes. Once true it stays true.

func (*Transcript) Sum

func (t *Transcript) Sum(factory func() hash.Hash) ([]byte, error)

Sum computes the transcript hash using factory. It calls factory() to obtain a fresh hash instance, writes all buffered bytes into it, and returns the digest via h.Sum(nil).

factory must not be nil. If factory is nil, Sum returns errors.New("handshake: transcript: nil hash factory").

func (*Transcript) Write

func (t *Transcript) Write(msg []byte)

Write appends msg to the transcript buffer. It is the caller's responsibility to pass the full 4-byte-enveloped handshake message (msg_type + uint24 length + body), as required by RFC 5246 §7.4.9.

If appending msg would push the buffer past maxTranscriptBytes, Write appends nothing and marks the transcript overflowed; Sum then fails (see Overflowed).

type Type

type Type uint8

Type identifies a handshake message type (RFC 5246 §7.4).

const (
	TypeHelloRequest       Type = 0
	TypeClientHello        Type = 1
	TypeServerHello        Type = 2
	TypeCertificate        Type = 11
	TypeServerKeyExchange  Type = 12
	TypeCertificateRequest Type = 13
	TypeServerHelloDone    Type = 14
	TypeCertificateVerify  Type = 15
	TypeClientKeyExchange  Type = 16
	TypeFinished           Type = 20
)

func (Type) String

func (t Type) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL