ddn.net.tls.tls13client

TLS 1.3 client handshake (RFC 8446).

Implements the full TLS 1.3 client handshake as a resumable state machine. Each call to handshake() progresses through one or more phases until I/O is needed or the handshake completes.

Phases:

  1. Send ClientHello (key_share + supported_versions + supported_groups + signature_algorithms)
  2. Receive ServerHello (select cipher suite, key share group, compute shared secret)
  3. Receive EncryptedExtensions, Certificate, CertificateVerify, Finished
  4. Send client Finished
  5. Switch to application data keys

Types 2

TLS 1.3 client handshake phases.

Each phase represents a discrete step in the handshake state machine. The handshake progresses forward through these phases.

NOT_STARTEDHandshake has not been initiated
SEND_CLIENT_HELLOBuild and send ClientHello
SEND_DUMMY_CCSSend dummy CCS for middlebox compatibility
FLUSH_CLIENT_HELLOFlush pending ClientHello and CCS bytes
RECV_SERVER_HELLOWait for ServerHello record
SEND_SECOND_CLIENT_HELLOBuild and send second ClientHello after HRR
FLUSH_SECOND_CLIENT_HELLOFlush pending second ClientHello bytes
RECV_SERVER_HELLO_2Wait for real ServerHello after second ClientHello
SWITCH_TO_HANDSHAKE_KEYSDerive handshake traffic keys (no I/O)
RECV_ENCRYPTED_EXTENSIONSWait for EncryptedExtensions record
RECV_CERTIFICATEWait for Certificate record
RECV_CERTIFICATE_VERIFYWait for CertificateVerify record
RECV_SERVER_FINISHEDWait for server Finished record
SEND_CLIENT_FINISHED_CCSSend dummy CCS for client Finished
SEND_CLIENT_FINISHEDBuild and send client Finished
FLUSH_CLIENT_FINISHEDFlush pending Finished bytes
SWITCH_TO_APP_KEYSDerive application traffic secrets (no I/O)
DONEHandshake complete

TLS 1.3 client handshake engine.

Drives the client side of a TLS 1.3 handshake over a record layer using a resumable state machine. After successful handshake, provides the AEAD cipher and negotiated parameters for application data exchange.

Call handshake() repeatedly until it returns TlsProgress.DONE. On NEED_READ, wait for the transport to become readable before calling again. On NEED_WRITE, wait for writability.

Fields
RecordLayer recordLayer_
Tls13KeySchedule keySchedule_
TranscriptHash transcript_
string serverName_
TlsVerifyMode verifyMode_
TlsVerifyCallback verifyCallback_
string[] alpnProtocols_
string negotiatedAlpn_
CipherSuiteId negotiatedCipher_
ProtocolVersion negotiatedVersion_
TlsSession tlsSession_
X25519PrivateKey ecdhePrivate_
ubyte[] sharedSecret_
ubyte[32] clientRandom_
ubyte[32] legacySessionId_
bool firstHelloDone_
EcdhP256Store * ecdhP256Store_
TlsAead clientWriteAead_
TlsAead serverReadAead_
TlsAead clientAppAead_
TlsAead serverAppAead_
NamedGroup hrrSelectedGroup_
ubyte[] hrrCookie_
ubyte[] pendingPlaintext_
ubyte[] pendingHandshakeData_
Methods
TlsProgress handshake()Performs or continues the TLS 1.3 client handshake.
private TlsProgress ensureHandshakeData()Ensures we have at least 4 bytes of handshake data to read the message header. If we need more data for a complete message, reads and decrypts more records. Returns TlsProgress.DONE when enough dat...
private ubyte[] consumeHandshakeMessage()Consumes a handshake message from the pending buffer. Updates the transcript and returns the message data.
Tls13HandshakePhase phase() @property constReturns: The current handshake phase.
TlsAead clientAead() @propertyReturns: The client application data AEAD cipher.
TlsAead serverAead() @propertyReturns: The server application data AEAD cipher.
CipherSuiteId cipherSuite() @property constReturns: The negotiated cipher suite ID.
string alpn() @property constReturns: The negotiated ALPN protocol.
TlsCertificateChain peerCertificates() @propertyReturns: The peer certificate chain.
TlsSession session() @propertyReturns: The TLS session for resumption.
private ubyte[] buildClientHello(SecureRandom rng, NamedGroup forcedGroup = NamedGroup.init, const(ubyte)[] cookie = null)
private void processServerHello(TlsRecord rec)
private void parseServerKeyShare(const(ubyte)[] extData)
private void deriveSharedSecret()
private bool isHelloRetryRequest(TlsRecord rec)
private void processHelloRetryRequest(const(ubyte)[] data, size_t off, size_t msgEnd)
private void switchToHandshakeKeys()
private void processCertificate()
private void verifyPeerCertificates()
private void verifyCertificateVerify(SignatureScheme sigScheme, const(ubyte)[] signature, const(ubyte)[] message)
private void processServerFinished()
private ubyte[] buildClientFinished()
private ubyte[] decryptRecord(TlsRecord rec, TlsAead aead)
private ubyte[] encryptRecord(ubyte[] handshakeMsg, TlsAead aead)
private size_t cipherKeyLength(CipherSuiteId cs) @safe pure nothrow @nogc
Constructors
this(RecordLayer recordLayer, string serverName, TlsVerifyMode verifyMode, TlsVerifyCallback verifyCallback, string[] alpnProtocols, NativeTlsTrustStore trustStore = null)Constructs a TLS 1.3 client handshake engine.
Nested Templates
EcdhP256StoreHeap storage for EcdhP256 since it's a struct.