Modern Cryptography · Module 13

TLS 1.3
Handshake

From ClientHello to Application Data —
The Protocol That Secures the Internet

ECDHE AEAD X.509 RFC 8446

Why TLS Matters

Transport Layer Security is the most widely deployed cryptographic protocol on Earth. Every HTTPS connection, every email transmission, every API call depends on it.

95%+
Web traffic encrypted

Chrome reports over 95% of pages
loaded over HTTPS as of 2025

~4.5B
TLS handshakes/day

Cloudflare alone handles billions
of connections daily

1-RTT
TLS 1.3 handshake

Down from 2-RTT in TLS 1.2 —
faster, simpler, more secure

TLS is the integration point: It combines key exchange (Module 02), symmetric encryption (Module 03/04), hash functions (Module 05), and digital signatures (Module 06) into a single coherent protocol.

TLS Evolution

Two decades of protocol refinement, driven by real-world attacks and performance demands.

VersionYearRFCKey ChangesStatus
SSL 3.01996RFC 6101First practical deploymentDeprecated (POODLE)
TLS 1.01999RFC 2246SSL renamed, minor fixesDeprecated (BEAST)
TLS 1.12006RFC 4346Explicit IV for CBCDeprecated
TLS 1.22008RFC 5246AEAD ciphers, SHA-256, configurable PRFLegacy (still ~20%)
TLS 1.32018RFC 84461-RTT, ECDHE-only, AEAD-only, encrypted handshakeCurrent standard
28 drafts over 4 years: TLS 1.3 went through extensive review. The IETF process eliminated features that had caused vulnerabilities — the result is a radically simplified protocol compared to TLS 1.2's 37 cipher suites and negotiable options.

What TLS 1.3 Removed

The most important design decision in TLS 1.3 was what to delete. Every removed feature had been the source of real-world attacks.

Removed Algorithms

RSA key exchange No forward secrecy
CBC mode ciphers BEAST, Lucky13, POODLE
RC4 Statistical biases
SHA-1 Collision attacks (SHAttered)
3DES Sweet32 birthday attack
MD5 Broken since 2004

Removed Features

Renegotiation Triple Handshake attack
Compression CRIME/BREACH attacks
Static DH/ECDH No forward secrecy
ChangeCipherSpec Simplified state machine
Custom DHE groups Logjam attack vector
Export ciphers FREAK/Logjam

Forward secrecy is mandatory: By removing RSA key exchange entirely, TLS 1.3 guarantees that a compromised server private key cannot decrypt past sessions. Every connection uses ephemeral ECDHE.

TLS 1.3 Cipher Suites

TLS 1.2 had 37+ cipher suites with complex negotiation. TLS 1.3 has exactly 5, all AEAD-only. Key exchange and authentication are negotiated separately.

Cipher SuiteAEADHKDF HashKey SizeNotes
TLS_AES_128_GCM_SHA256AES-128-GCMSHA-256128-bitMost common; mandatory to implement
TLS_AES_256_GCM_SHA384AES-256-GCMSHA-384256-bitHigher security margin
TLS_CHACHA20_POLY1305_SHA256ChaCha20-Poly1305SHA-256256-bitFast on devices without AES-NI
TLS_AES_128_CCM_SHA256AES-128-CCMSHA-256128-bitIoT / constrained environments
TLS_AES_128_CCM_8_SHA256AES-128-CCM-8SHA-256128-bit8-byte tag; IoT only
Separation of concerns: In TLS 1.3, the cipher suite specifies only the AEAD algorithm and hash. Key exchange (ECDHE group) and signature algorithm are negotiated via extensions — a cleaner, more modular design from Module 03 (AES) and Module 04 (ChaCha20).

The Full Handshake — 1-RTT

TLS 1.3 completes the handshake in a single round trip. The client sends key shares speculatively, enabling encrypted data after just one flight.

Client Server ClientHello + key_share + supported_versions + sig_algs PLAIN ServerHello + key_share + supported_versions ENCRYPTED FROM HERE {EncryptedExtensions} {Certificate} {CertificateVerify} {Finished} 1-RTT {Finished} [Application Data]

ClientHello in Detail

The ClientHello is the only unencrypted message from the client. It must contain enough information for the server to complete key exchange in a single round trip.

ClientHello Structure

ClientHello {
    legacy_version:           0x0303        // TLS 1.2 for middlebox compat
    random:                   32 bytes      // Client random nonce
    legacy_session_id:        32 bytes      // Compatibility mode
    cipher_suites:            [0x1301, 0x1302, 0x1303]
    legacy_compression:       [0x00]        // Null only
    extensions: {
        supported_versions:   [0x0304]      // TLS 1.3
        key_share:            X25519 pubkey (32 bytes)
                              P-256 pubkey  (65 bytes)
        signature_algorithms: [ed25519, ecdsa_secp256r1_sha256,
                               rsa_pss_rsae_sha256, ...]
        server_name (SNI):    "example.com"
        psk_key_exchange_modes: [psk_dhe_ke]
    }
}
Speculative key shares: The client sends public keys for its preferred groups (often both X25519 and P-256). If the server supports neither, it responds with HelloRetryRequest — adding one extra round trip.

ServerHello + EncryptedExtensions

The server selects one cipher suite, one key share group, and sends its ephemeral public key. Everything after ServerHello is encrypted.

ServerHello

Sent in plaintext (last unencrypted server message):

ServerHello {
  legacy_version: 0x0303
  random:         32 bytes
  cipher_suite:   0x1301
                  (AES_128_GCM_SHA256)
  extensions: {
    supported_versions: 0x0304
    key_share: X25519 pubkey
  }
}

{EncryptedExtensions}

First encrypted message — uses handshake traffic keys:

{EncryptedExtensions} {
  server_name:          ack
  max_fragment_length:  ...
  alpn:                 "h2"
  // No key-exchange or
  // auth-related extensions
  // (those stay in ServerHello)
}
Why encrypt extensions? In TLS 1.2, all extensions were plaintext — leaking ALPN negotiation, supported features, and other metadata. TLS 1.3 encrypts everything except what's strictly needed for key agreement.

ECDHE Key Exchange

The core of TLS 1.3 security — ephemeral Elliptic Curve Diffie-Hellman. Connects directly to Module 02 (ECC).

X25519 (Curve25519)

Field: GF(2255 - 19)
Key size: 32 bytes public, 32 bytes private
Speed: ~50,000 ops/sec on modern CPU
Properties: Constant-time by design, no invalid-curve attacks, Montgomery ladder

Preferred ~70% of connections

P-256 (secp256r1)

Field: GF(p) where p = 2256 - 2224 + ...
Key size: 65 bytes public (uncompressed)
Speed: ~20,000 ops/sec on modern CPU
Properties: NIST standard, HSM support, FIPS validated

NIST Compliance required

Shared secret derivation: Both parties compute shared_secret = ECDH(my_private, peer_public). The result is a 32-byte value fed into the HKDF key schedule. New ephemeral keys are generated for every single connection — guaranteeing forward secrecy.

Key Schedule — HKDF Derivation

TLS 1.3 derives all keys through a structured HKDF pipeline. Two primitives from Module 05 (Hashing): HKDF-Extract (combine entropy) and HKDF-Expand (derive keys).

PSK (or 0s) HKDF-Extract Early Secret client_early_traffic_secret (0-RTT) early_exporter_master_secret Derive-Secret (EC)DHE HKDF-Extract Handshake Secret client_handshake_traffic_secret server_handshake_traffic_secret Derive-Secret 0 (no input) HKDF-Extract Master Secret client_application_traffic_secret server_application_traffic_secret resumption_master_secret

Server Authentication

After key exchange, the server proves its identity with three encrypted messages. All sent under handshake traffic keys.

Certificate

X.509 certificate chain sent to client. Contains server's public key, signed by a Certificate Authority. Encoded as a sequence of CertificateEntry structures with optional per-certificate extensions (OCSP, SCT).

Identity

CertificateVerify

Digital signature over the handshake transcript hash using the server's private key. Proves the server possesses the private key matching the certificate. Uses signature algorithms from Module 06.

Proof of possession

Finished

HMAC over the entire handshake transcript using a key derived from the handshake secret. Provides key confirmation and transcript integrity — proves the handshake was not tampered with.

Integrity

Transcript binding: CertificateVerify signs Hash(Handshake Context || messages). This binds the server's identity to the specific key exchange that occurred — preventing mismatch attacks where an attacker substitutes a different server's response.

Client Finished — Handshake Complete

The client verifies the server's Certificate, CertificateVerify, and Finished. Then it sends its own Finished message to complete the handshake.

Client-Side Verification Steps

Verify Chain
X.509 path validation
to trusted root CA
Check Signature
CertificateVerify
over transcript hash
Verify Finished
HMAC matches
expected value
Send Finished
Client's HMAC
over full transcript
1-RTT
Handshake latency

Application data can flow immediately
after client sends Finished

~1ms
Crypto computation

ECDHE + signature verification
dominates CPU time

3
Key phases

Early → Handshake → Application
each with separate traffic keys

0-RTT Resumption

Returning clients can send encrypted application data in the very first flight — zero round trips before data. But this comes with significant security trade-offs.

Client Server ClientHello + PSK identity + key_share [0-RTT Application Data] Encrypted with early_traffic_secret 0-RTT ServerHello ... Finished [Application Data - full 1-RTT keys]
Replay risk: 0-RTT data is not replay-protected. An attacker who captures the ClientHello + early data can replay it. Servers must implement application-layer replay protection (e.g., idempotency tokens). 0-RTT also lacks forward secrecy against PSK compromise.

Pre-Shared Key Modes

TLS 1.3 supports two PSK modes for resumption and external PSK use cases.

PSK-Only (psk_ke)

Key derived solely from the pre-shared key. No ephemeral key exchange is performed.

Forward secrecy: None — if the PSK is compromised, all sessions using it are exposed.
Use case: IoT devices with pre-provisioned keys, constrained environments where ECDHE is too expensive.

No forward secrecy Constrained only

PSK with (EC)DHE (psk_dhe_ke)

PSK combined with ephemeral ECDHE exchange. Both the PSK and ECDHE shared secret feed into HKDF-Extract.

Forward secrecy: Yes — even if PSK is later compromised, past sessions are safe.
Use case: Normal TLS 1.3 session resumption. This is the recommended mode.

Forward secrecy Recommended

Key schedule integration: In PSK + (EC)DHE mode, the Early Secret comes from the PSK, but the Handshake Secret additionally incorporates the ECDHE shared secret. This provides dual protection — an attacker must compromise both the PSK and solve the discrete log problem.

Session Tickets

After the handshake completes, the server sends NewSessionTicket messages enabling future resumption without server-side state.

NewSessionTicket Structure

NewSessionTicket {
    ticket_lifetime:    7200                // Max 604800s (7 days)
    ticket_age_add:     0x4a2bc8e1          // Obfuscate ticket age
    ticket_nonce:       0x0000000000000001  // Unique per ticket
    ticket:             <encrypted blob>    // Server-encrypted state
    extensions: {
        early_data:     max_early_data_size: 16384
    }
}

Stateless Servers

The ticket is an encrypted container holding the resumption secret, cipher suite, and expiry. The server encrypts with a ticket encryption key (STEK) known only to the server cluster — no session database needed.

Ticket Age Obfuscation

The client reports obfuscated_age = (age_ms + ticket_age_add) mod 2^32. This prevents observers from correlating ticket reuse across connections — a privacy improvement over TLS 1.2 session IDs.

STEK rotation: Session Ticket Encryption Keys must be rotated regularly (every few hours). If an STEK is compromised, an attacker can decrypt all tickets encrypted with it, deriving resumption secrets and decrypting 0-RTT data.

Certificate Handling

TLS 1.3 carries X.509 certificate chains with inline extensions for revocation checking and certificate transparency.

X.509 Chain

Server sends its leaf certificate plus intermediates. The client validates the chain to a trusted root CA. Chain is typically 2-3 certificates, ~3-5 KB total.

Identity binding

OCSP Stapling

Server includes a signed OCSP response in the CertificateEntry extension. Client verifies revocation status without contacting the CA — reduces latency and improves privacy.

Revocation

SCTs (CT Logs)

Signed Certificate Timestamps prove the certificate was logged in a public Certificate Transparency log. Detects misissued certificates. Required by Chrome since 2018.

Transparency

Certificate compression (RFC 8879): TLS 1.3 supports Brotli/zlib compression of certificate chains via the compress_certificate extension. This reduces certificate data by ~60%, saving ~2-3 KB per handshake — significant at scale.

Signature Schemes

TLS 1.3 defines specific signature algorithms for CertificateVerify. Connecting to Module 06 (Digital Signatures).

SchemeAlgorithmHashKey SizeNotes
ecdsa_secp256r1_sha256ECDSA over P-256SHA-256256-bitMost widely deployed
ecdsa_secp384r1_sha384ECDSA over P-384SHA-384384-bitHigher security level
ed25519EdDSA / Curve25519SHA-512256-bitDeterministic, fast; from Module 06
ed448EdDSA / Ed448SHAKE256448-bit~224-bit security
rsa_pss_rsae_sha256RSA-PSS (RSAE)SHA-2562048+ bitPSS padding mandatory
rsa_pss_rsae_sha384RSA-PSS (RSAE)SHA-3842048+ bitRSA-PSS only; no PKCS#1 v1.5
rsa_pss_pss_sha256RSA-PSS (PSS key)SHA-2562048+ bitKey restricted to PSS
No PKCS#1 v1.5 for handshake: TLS 1.3 requires RSA-PSS for CertificateVerify signatures. PKCS#1 v1.5 is only allowed in certificate chain signatures (for compatibility with existing CA infrastructure). This eliminates Bleichenbacher-style padding oracle attacks.

Record Protocol — AEAD Encryption

All application data (and handshake messages after ServerHello) is encrypted using the AEAD cipher from the negotiated suite. Connects to Module 03 (AES-GCM) and Module 04 (ChaCha20-Poly1305).

TLSCiphertext Record

TLSCiphertext {
    opaque_type:     0x17 (application_data)  // Always 0x17!
    legacy_version:  0x0303                    // Always TLS 1.2
    length:          uint16                    // Encrypted payload length
    encrypted_record:
        AEAD-Encrypt(
            key:   write_key,
            nonce: write_iv XOR sequence_number,
            aad:   TLSCiphertext header (5 bytes),
            plaintext: content || ContentType || zeros
        )
}

Content Type Hiding

The real content type (handshake, alert, application_data) is encrypted inside the record. The outer header always says 0x17. This prevents traffic analysis that distinguishes handshake from data.

Nonce Construction

Each record uses nonce = write_iv XOR padded_sequence_number. The sequence number is implicit (not sent on wire), incrementing from 0. This guarantees nonce uniqueness without transmitting it.

Middlebox Compatibility Mode

The most pragmatic hack in TLS 1.3: it disguises itself as TLS 1.2 on the wire to avoid being broken by enterprise middleboxes.

The Problem

Enterprise firewalls, load balancers, and inspection devices parse TLS headers. When TLS 1.3 was first deployed, many middleboxes:

• Dropped connections with unknown version numbers
• Expected ChangeCipherSpec messages
• Failed on missing session IDs
• Caused ~3-8% connection failures in field trials

The Solution

TLS 1.3 includes deliberate lies for compatibility:

legacy_version = 0x0303 (claims TLS 1.2)
• Sends a dummy ChangeCipherSpec message
• Includes a random legacy_session_id
• Real version negotiated in supported_versions extension

Lesson for protocol design: The internet ossifies around deployed behavior. Even a clean, well-designed protocol must accommodate broken implementations. TLS 1.3's compatibility mode adds ~100 bytes of waste per handshake but saved the protocol from deployment failure.

Security Analysis

TLS 1.3 is the most formally analyzed cryptographic protocol in history. Multiple independent verification efforts proved its security properties.

Formal Verification

Tamarin Prover — Symbolic analysis of the handshake state machine. Proved authentication, secrecy, and forward secrecy properties.

ProVerif — Automated Dolev-Yao model verification. Confirmed no protocol-level attacks on the 1-RTT and 0-RTT modes.

miTLS (F*) — Verified reference implementation in F* language. Crypto proofs composed with code correctness proofs.

Attacks Prevented

BEAST CBC IV predictability → no CBC
CRIME Compression oracle → no compression
Lucky13 CBC padding oracle → no CBC
POODLE SSL 3.0 downgrade → no fallback
FREAK Export cipher downgrade → no export
Logjam Weak DH groups → no custom groups
ROBOT RSA padding oracle → no RSA KE
Triple HS Renegotiation → no renegotiation

Downgrade protection: The server random includes a sentinel value (44 4F 57 4E 47 52 44 01 = "DOWNGRD\x01") when negotiating TLS 1.2. If a client sees this sentinel while expecting 1.3, it detects a downgrade attack and aborts.

TLS 1.3 vs TLS 1.2

A side-by-side comparison of the two protocol generations.

TLS 1.2 Handshake: 2-RTT Key exchange: RSA, DHE, ECDHE (optional) Cipher suites: 37+ (CBC, RC4, AEAD mixed) Handshake encryption: None (all plaintext) Forward secrecy: Optional (only with DHE/ECDHE) Resumption: Session ID / Session Ticket Signature: RSA PKCS#1 v1.5, ECDSA Renegotiation: Supported Messages: 6-10 in full handshake TLS 1.3 Handshake: 1-RTT (0-RTT resumption) Key exchange: ECDHE only (mandatory) Cipher suites: 5 (AEAD-only) Handshake encryption: After ServerHello Forward secrecy: Always (ephemeral ECDHE) Resumption: PSK + (EC)DHE tickets Signature: RSA-PSS, EdDSA, ECDSA Renegotiation: Removed Messages: 4-5 in full handshake

Post-Quantum TLS

Quantum computers threaten ECDHE key exchange. The transition to post-quantum TLS is already underway. Connecting to Module 07 (Post-Quantum Cryptography).

Hybrid Key Exchange

Combines classical ECDHE with a PQ KEM in a single key_share. The shared secret is derived from both — secure even if one scheme is broken.

shared_secret = HKDF(ECDHE_secret || ML-KEM_secret)

Chrome since M131

ML-KEM (Kyber) Integration

X25519MLKEM768 — X25519 + ML-KEM-768 hybrid. Now the most common PQ key exchange on the web.

ClientHello size: Grows from ~300 bytes to ~1100 bytes (ML-KEM public key is 1184 bytes for level 3).

FIPS 203

Deployment reality (2026): Cloudflare and Google report that >30% of TLS connections now use hybrid PQ key exchange. The main challenge is not cryptography but packet size — ML-KEM key shares can cause ClientHello fragmentation, triggering middlebox failures similar to the early TLS 1.3 deployment.

On the Wire — What Wireshark Sees

A TLS 1.3 handshake as captured in a packet trace. Note how everything after ServerHello appears as opaque Application Data.

Frame 1: ClientHello (227 bytes)
  16 03 01 00 e0        # Record: Handshake, TLS 1.0 (compat!)
  01 00 00 dc           # ClientHello, length 220
  03 03                 # legacy_version: TLS 1.2
  [32 bytes random]
  20 [32 bytes session_id]     # Compatibility mode
  00 06 13 01 13 02 13 03      # 3 cipher suites
  01 00                        # Compression: null
  00 91                        # Extensions length
    00 2b 00 03 02 03 04       # supported_versions: TLS 1.3
    00 33 00 47 00 45          # key_share: X25519
      00 1d 00 20 [32 bytes pubkey]
    00 0d 00 14 ...            # signature_algorithms
    00 00 00 0f ...            # server_name: example.com

Frame 2: ServerHello (155 bytes)
  16 03 03 00 97        # Record: Handshake, TLS 1.2 (compat!)
  02 00 00 93           # ServerHello
  03 03 [32 bytes random]
  20 [32 bytes session_id]     # Echo client's session_id
  13 01                        # Selected: TLS_AES_128_GCM_SHA256
    00 2b 00 02 03 04          # supported_versions: TLS 1.3
    00 33 00 24 00 1d 00 20    # key_share: X25519
      [32 bytes server pubkey]

Frame 3: Change Cipher Spec (6 bytes)  # Fake! Compatibility mode
  14 03 03 00 01 01

Frame 4-7: Application Data (opaque)   # All encrypted from here
  17 03 03 [len] [encrypted EncryptedExtensions]
  17 03 03 [len] [encrypted Certificate]
  17 03 03 [len] [encrypted CertificateVerify]
  17 03 03 [len] [encrypted Finished]

TLS 1.3 Implementations

Major implementations with different design philosophies and security profiles.

LibraryLanguage0-RTTPQ HybridNotes
OpenSSL 3.xCYesYes (3.5+)Most widely deployed; provider architecture
BoringSSLC++YesYesGoogle's fork; Chrome, Android; first PQ deploy
rustlsRustYesYesMemory-safe; no C code; ~10K LoC
Go crypto/tlsGoYesYesStandard library; simple API
mbedTLSCYesPartialEmbedded/IoT focus; ARM-maintained
wolfSSLCYesYesEmbedded + FIPS 140-3 certified
NSSCYesYesMozilla/Firefox; PKCS#11 based
s2n-tlsCYesYesAWS; minimal code footprint
rustls momentum: Memory-safe TLS is gaining traction. rustls is now used by Cloudflare (Pingora), the curl project, and the Apache httpd mod_tls module. Its ~10K lines of Rust replace ~500K lines of OpenSSL C, eliminating entire classes of vulnerabilities (buffer overflows, use-after-free).
DEEP DIVE

Protocol Internals

HKDF details · Finished computation · Key update

HKDF Internals

HKDF (HMAC-based Key Derivation Function, RFC 5869) is the engine behind TLS 1.3's key schedule. Two operations, each a single HMAC call.

HKDF-Extract(salt, IKM)

PRK = HMAC-Hash(salt, IKM)
// Extracts entropy from input
// keying material (IKM) into a
// fixed-length pseudorandom key
// salt = previous Derive-Secret
// IKM = PSK or ECDHE secret

HKDF-Expand-Label

HKDF-Expand-Label(Secret, Label,
                   Context, Length)
= HKDF-Expand(Secret,
    HkdfLabel, Length)

HkdfLabel = Length ||
  "tls13 " || Label ||
  Hash(Context)

Derive-Secret

Derive-Secret(Secret, Label, Messages)
    = HKDF-Expand-Label(Secret, Label, Transcript-Hash(Messages), Hash.length)

// Example: deriving handshake traffic secret
client_handshake_traffic_secret =
    Derive-Secret(Handshake Secret, "c hs traffic", ClientHello...ServerHello)

Finished Message & Key Update

Finished Computation

finished_key = HKDF-Expand-Label(
    base_key,           // {client,server}_handshake_traffic_secret
    "finished", "", Hash.length
)

verify_data = HMAC(finished_key, Transcript-Hash(
    Handshake Context ... last message before Finished
))

The Finished message is a MAC over the entire transcript, keyed with a value derived from the handshake secret. It provides key confirmation — both parties prove they computed the same keys.

Post-Handshake Key Update

application_traffic_secret_N+1 =
    HKDF-Expand-Label(application_traffic_secret_N,
                       "traffic upd", "", Hash.length)

// New write key and IV derived from new secret
// Triggered via KeyUpdate message (encrypted)
// Provides key rotation without new handshake

Key update allows rekeying application traffic keys without a new handshake. This limits the amount of data encrypted under a single key, mitigating potential nonce-reuse issues.

References & Standards

Core RFCs

RFC 8446 — TLS 1.3 Protocol
RFC 8447 — IANA Registry Updates for TLS
RFC 8448 — Example TLS 1.3 Handshake Traces
RFC 8449 — Record Size Limit Extension
RFC 8879 — Certificate Compression
RFC 5869 — HKDF (HMAC-based KDF)
RFC 9001 — QUIC uses TLS 1.3
RFC 8998 — ShangMi Cipher Suites for TLS 1.3

Post-Quantum

draft-ietf-tls-hybrid-design — Hybrid Key Exchange
FIPS 203 — ML-KEM (Kyber)
Chrome: X25519MLKEM768 deployment
Cloudflare: PQ key exchange telemetry

Formal Analysis

Cremers et al., "A Comprehensive Symbolic Analysis of TLS 1.3" (CCS 2017)
Bhargavan et al., "miTLS: Verified Reference Implementation" (S&P 2017)
Dowling & Paterson, "A Cryptographic Analysis of TLS 1.3" (JoC 2021)
Delignat-Lavaud et al., "Implementing TLS with Verified Cryptographic Security" (S&P 2014)

Implementations

OpenSSL — openssl.org
BoringSSL — boringssl.googlesource.com
rustls — github.com/rustls/rustls
s2n-tls — github.com/aws/s2n-tls
wolfSSL — wolfssl.com

Summary

Protocol design — TLS 1.3 achieves 1-RTT handshakes by removing legacy features, mandating ECDHE forward secrecy, and encrypting the handshake after ServerHello. Only 5 AEAD-only cipher suites remain.

Key exchange (Module 02) — Ephemeral ECDHE with X25519 or P-256 provides the shared secret. Post-quantum hybrid key exchange with ML-KEM is actively deploying.

Symmetric encryption (Modules 03/04) — AES-128-GCM, AES-256-GCM, and ChaCha20-Poly1305 protect all application data via AEAD. Content type hiding prevents traffic analysis.

Hash functions (Module 05) — HKDF-Extract and HKDF-Expand (built on HMAC-SHA256/384) drive the three-stage key schedule from Early Secret through Master Secret.

Digital signatures (Module 06) — RSA-PSS, Ed25519, and ECDSA authenticate servers in CertificateVerify. PKCS#1 v1.5 is banned for handshake signatures.

Modern Cryptography · Module 13