Class TlsSession
crypto::Session. There is no record layer: handshake messages travel in CRYPTO frames at an
EncryptionLevel, and the traffic secrets for each level are handed to the connection as
Secrets.
The connection layer drives a session like this:
- Create it with
client(TlsConfig, byte[])orserver(TlsConfig, byte[]), passing the encoded local transport parameters. A client has its ClientHello ready at once. - Feed each level's in-order CRYPTO stream bytes to
readHandshake(io.github.mahmoudimus.quic.EncryptionLevel, java.nio.ByteBuffer). Messages may be split or coalesced arbitrarily. - After each call (and after creating a client), install any keys
nextSecrets()returns, then send whatwriteHandshake(EncryptionLevel)returns for each level. - When the handshake is complete, use
nextOneRttSecrets()for key updates.
Secrets arrive in this order. A client gets the EncryptionLevel.HANDSHAKE secrets
after the ServerHello, and the EncryptionLevel.ONE_RTT secrets once it has checked the
server's Finished and queued its own; the handshake is then complete for it. A server gets both
as soon as it has processed the ClientHello and queued its whole flight, ending with its
Finished: it may send 1-RTT (0.5-RTT) data at once but, as RFC 9001 section 5.7 requires, must
not process 1-RTT packets from the client until isHandshakeComplete(), which happens
when the client's Finished has been verified. Confirming the handshake (HANDSHAKE_DONE) and
discarding keys are left to the connection layer.
Errors are QuicExceptions: TLS alerts become CRYPTO_ERROR codes (
0x0100 + alert, see TlsAlert), a message longer than the configured limit becomes
CRYPTO_BUFFER_EXCEEDED, and a non-empty legacy_session_id sent to a server
becomes PROTOCOL_VIOLATION. After an error the session is dead and every further
readHandshake throws the same error.
A session is not thread-safe and takes no locks: a handshake is a single-threaded state
machine, driven by one connection at a time. Its certificate and ALPN selectors run on the
thread that calls readHandshake(io.github.mahmoudimus.quic.EncryptionLevel, java.nio.ByteBuffer).
Resumption and 0-RTT. A server with a ticketer
queues NewSessionTicket messages at EncryptionLevel.ONE_RTT when its handshake completes,
and resumes the sessions they seal. A client hands each ticket it receives out through pollNewTicket() and resumes with one passed to client(TlsConfig, String, byte[], SessionTicket). When a client offers early data, its first secrets are the EncryptionLevel.ZERO_RTT ones, available at once: Secrets(ZERO_RTT, suite,
client_early_traffic_secret, empty). A server that accepts the early data hands out the same
secrets first, before the Handshake ones. Whether it was accepted is known to the client after
EncryptedExtensions (isEarlyDataAccepted()).
-
Method Summary
Modifier and TypeMethodDescriptionThe negotiated cipher suite.static TlsSessionStarts a client handshake to the configuration'sserver name.static TlsSessionStarts a client handshake to a server name.static TlsSessionclient(TlsConfig config, String serverName, byte[] transportParameters, SessionTicket ticket) Starts a client handshake that offers to resume a session.byte[]The ClientHello's random value, which names the secrets of this handshake in theSSLKEYLOGFILEformat that packet analyzers read.byte[]exportKeyingMaterial(String label, byte[] context, int length) Keying material from the TLS exporter (RFC 8446 section 7.5).booleanhasHandshakeData(EncryptionLevel level) Whether handshake bytes are queued at a level.booleanisClient()Whether this is the client side.booleanWhether the server accepted 0-RTT data.booleanWhether the client offered 0-RTT data in its first ClientHello.booleanWhether the handshake is complete (RFC 9001 section 4.1.1): for a client, once it has verified the server's Finished and queued its own; for a server, once it has verified the client's Finished.booleanWhether the handshake is still in progress: true until it completes, and also after it has failed.booleanWhether the handshake resumed a session with a PSK from a ticket.The application protocol agreed with ALPN.The key exchange group used.Derives the next generation of 1-RTT secrets for a key update (RFC 9001 section 6):HKDF-Expand-Label(secret, "quic ku", "", Hash.length)on both traffic secrets, with the suite's hash.Takes the next newly available secrets, in the order they became available.The peer's certificate chain, end-entity first: the server's for a client, and the client's for a server that asked for one.The signature scheme of the peer's CertificateVerify.byte[]The peer's encoded QUIC transport parameters, which the connection layer decodes.Client: takes the next ticket received in a NewSessionTicket message, to keep for a later connection.voidreadHandshake(EncryptionLevel level, ByteBuffer data) Feeds CRYPTO stream bytes received at an encryption level, in stream order.static TlsSessionStarts a server handshake, which waits for a ClientHello.static TlsSessionStarts a server handshake with a check on the QUIC transport parameters a ticket remembers.The server name: for a client, the one it connects to; for a server, the client's SNI.booleanWhether the server sent a HelloRetryRequest, asking for a key share in another group.byte[]writeHandshake(EncryptionLevel level) Takes the handshake bytes queued for sending at a level, in order.
-
Method Details
-
client
Starts a client handshake to the configuration'sserver name. The ClientHello is queued atEncryptionLevel.INITIALbefore this returns.- Parameters:
config- the configuration, with ALPN protocolstransportParameters- the encoded local QUIC transport parameters- Returns:
- the session
- Throws:
IllegalArgumentException- if the configuration has no ALPN protocols, or no server name while it verifies host names
-
client
Starts a client handshake to a server name. The ClientHello is queued atEncryptionLevel.INITIALbefore this returns.- Parameters:
config- the configuration, with ALPN protocolsserverName- the host name (sent as SNI) or IP literal the certificate must match; may be null only if the configuration does not verify host namestransportParameters- the encoded local QUIC transport parameters- Returns:
- the session
- Throws:
IllegalArgumentException- if the configuration has no ALPN protocols, or no server name while it verifies host names
-
client
public static TlsSession client(TlsConfig config, String serverName, byte[] transportParameters, SessionTicket ticket) Starts a client handshake that offers to resume a session. The ticket is used only if it has not expired, is for the same server name and has a cipher suite the configuration offers; withearlyDataand a ticket that allows it, the client also offers 0-RTT, and itsEncryptionLevel.ZERO_RTTsecrets are ready at once.- Parameters:
config- the configuration, with ALPN protocolsserverName- the host name (sent as SNI) or IP literal the certificate must match; may be null only if the configuration does not verify host namestransportParameters- the encoded local QUIC transport parametersticket- a ticket from an earlier session with this server, used once; or null- Returns:
- the session
- Throws:
IllegalArgumentException- if the configuration has no ALPN protocols, or no server name while it verifies host names
-
server
Starts a server handshake, which waits for a ClientHello.- Parameters:
config- the configuration, with a certificate or certificate selector, and ALPN protocols or an ALPN selectortransportParameters- the encoded local QUIC transport parameters- Returns:
- the session
- Throws:
IllegalArgumentException- if the configuration has no certificate or no ALPN
-
server
public static TlsSession server(TlsConfig config, byte[] transportParameters, Predicate<byte[]> earlyDataParameters) Starts a server handshake with a check on the QUIC transport parameters a ticket remembers. Before accepting 0-RTT, the handshake passes the encoded parameters the server had when it issued the ticket toearlyDataParameters; returning false rejects the early data, as RFC 9000 section 7.4.1 requires when the current limits are smaller.- Parameters:
config- the configurationtransportParameters- the encoded local QUIC transport parameters, also sealed in ticketsearlyDataParameters- accepts the remembered parameters, or null to accept any- Returns:
- the session
- Throws:
IllegalArgumentException- if the configuration has no certificate or no ALPN
-
isClient
public boolean isClient()Whether this is the client side.- Returns:
- true for a client session
-
readHandshake
Feeds CRYPTO stream bytes received at an encryption level, in stream order. All ofdatais consumed. Messages may be split across calls or coalesced in one; each complete message is processed at once, which may queue output and secrets.- Parameters:
level- the encryption level the bytes arrived atdata- the bytes; its position is advanced to its limit- Throws:
QuicException- if the bytes are at the wrong level, malformed, or fail the handshake
-
writeHandshake
Takes the handshake bytes queued for sending at a level, in order.- Parameters:
level- the encryption level- Returns:
- the bytes for CRYPTO frames at that level; empty if there are none
-
hasHandshakeData
Whether handshake bytes are queued at a level.- Parameters:
level- the encryption level- Returns:
- true if
writeHandshake(EncryptionLevel)would return bytes
-
nextSecrets
Takes the next newly available secrets, in the order they became available.- Returns:
- the secrets for one level, or null if there are no new ones
-
nextOneRttSecrets
Derives the next generation of 1-RTT secrets for a key update (RFC 9001 section 6):HKDF-Expand-Label(secret, "quic ku", "", Hash.length)on both traffic secrets, with the suite's hash. Each call moves one generation on.- Returns:
- the next 1-RTT secrets
- Throws:
IllegalStateException- if the 1-RTT secrets are not available yet
-
isHandshaking
public boolean isHandshaking()Whether the handshake is still in progress: true until it completes, and also after it has failed.- Returns:
- true until
isHandshakeComplete()
-
isHandshakeComplete
public boolean isHandshakeComplete()Whether the handshake is complete (RFC 9001 section 4.1.1): for a client, once it has verified the server's Finished and queued its own; for a server, once it has verified the client's Finished.- Returns:
- true when complete
-
peerTransportParameters
public byte[] peerTransportParameters()The peer's encoded QUIC transport parameters, which the connection layer decodes.- Returns:
- a copy of the parameters, or null until they have been received (a server has them after the ClientHello, a client after EncryptedExtensions)
-
negotiatedAlpn
The application protocol agreed with ALPN.- Returns:
- the protocol, or null until it has been agreed
-
serverName
The server name: for a client, the one it connects to; for a server, the client's SNI.- Returns:
- the name, or null if there is none (yet)
-
peerCertificates
The peer's certificate chain, end-entity first: the server's for a client, and the client's for a server that asked for one.- Returns:
- the chain, empty until received or if the peer sent none
-
peerSignatureScheme
The signature scheme of the peer's CertificateVerify.- Returns:
- the scheme, or null until it has been verified or if the peer signed nothing
-
cipherSuite
The negotiated cipher suite.- Returns:
- the suite, or null until it is known
-
negotiatedGroup
The key exchange group used.- Returns:
- the group, or null until it is known
-
usedHelloRetryRequest
public boolean usedHelloRetryRequest()Whether the server sent a HelloRetryRequest, asking for a key share in another group.- Returns:
- true after a retry
-
isResumed
public boolean isResumed()Whether the handshake resumed a session with a PSK from a ticket. A client knows after the ServerHello; a server after the ClientHello.- Returns:
- true if resumed
-
isEarlyDataOffered
public boolean isEarlyDataOffered()Whether the client offered 0-RTT data in its first ClientHello.- Returns:
- true if offered
-
isEarlyDataAccepted
public boolean isEarlyDataAccepted()Whether the server accepted 0-RTT data. A client knows after EncryptedExtensions; until then, and if the early data was rejected, this is false.- Returns:
- true if accepted
-
pollNewTicket
Client: takes the next ticket received in a NewSessionTicket message, to keep for a later connection.- Returns:
- the ticket, or null if there is none
-
clientRandom
public byte[] clientRandom()The ClientHello's random value, which names the secrets of this handshake in theSSLKEYLOGFILEformat that packet analyzers read.- Returns:
- a copy of the 32 bytes, or null until known (a server learns it from the ClientHello)
-
exportKeyingMaterial
Keying material from the TLS exporter (RFC 8446 section 7.5).- Parameters:
label- the exporter label, ASCIIcontext- the context; null and empty are the same in TLS 1.3length- the number of bytes, at most 255 times the suite's hash length- Returns:
- the keying material
- Throws:
IllegalStateException- if the 1-RTT secrets are not available yetIllegalArgumentException- if the label or length is too long
-