quic_ticket (quic v1.3.0)

View Source

Session ticket storage and PSK derivation for 0-RTT.

This module handles: - Storing and retrieving NewSessionTicket messages - Deriving PSK from resumption_master_secret - Managing ticket lifetimes and early data limits

Summary

Functions

Build a NewSessionTicket message.

Remove all expired tickets from the store.

Remove a ticket for a server.

Create a session ticket from connection state. This is used by the server to issue tickets to clients.

Derive PSK from resumption_master_secret and ticket nonce. RFC 8446 Section 4.6.1: PSK = HKDF-Expand-Label(resumption_master_secret, "resumption", ticket_nonce, Hash.length)

Derive the resumption_master_secret from the master secret. RFC 8446 Section 7.1: resumption_master_secret = Derive-Secret(Master Secret, "res master", ClientHello..client Finished)

Look up a ticket for a server. Returns {ok, Ticket} if found and not expired, error otherwise.

Create a new empty ticket store.

Parse a NewSessionTicket message from the server. RFC 8446 Section 4.6.1: struct { uint32 ticket_lifetime; uint32 ticket_age_add; opaque ticket_nonce<0..255>; opaque ticket<1..2^16-1>; Extension extensions<0..2^16-2>; } NewSessionTicket;

Store a session ticket for a server. The ticket is indexed by server name.

Types

session_ticket/0

-type session_ticket() ::
          #session_ticket{server_name :: binary(),
                          ticket :: binary(),
                          lifetime :: non_neg_integer(),
                          age_add :: non_neg_integer(),
                          nonce :: binary(),
                          resumption_secret :: binary(),
                          max_early_data :: non_neg_integer(),
                          received_at :: non_neg_integer(),
                          cipher :: atom(),
                          alpn :: binary() | undefined}.

ticket_store/0

-type ticket_store() ::
          #{binary() =>
                #session_ticket{server_name :: binary(),
                                ticket :: binary(),
                                lifetime :: non_neg_integer(),
                                age_add :: non_neg_integer(),
                                nonce :: binary(),
                                resumption_secret :: binary(),
                                max_early_data :: non_neg_integer(),
                                received_at :: non_neg_integer(),
                                cipher :: atom(),
                                alpn :: binary() | undefined}}.

Functions

build_new_session_ticket(Session_ticket)

-spec build_new_session_ticket(#session_ticket{server_name :: binary(),
                                               ticket :: binary(),
                                               lifetime :: non_neg_integer(),
                                               age_add :: non_neg_integer(),
                                               nonce :: binary(),
                                               resumption_secret :: binary(),
                                               max_early_data :: non_neg_integer(),
                                               received_at :: non_neg_integer(),
                                               cipher :: atom(),
                                               alpn :: binary() | undefined}) ->
                                  binary().

Build a NewSessionTicket message.

clear_expired(Store)

-spec clear_expired(ticket_store()) -> ticket_store().

Remove all expired tickets from the store.

clear_ticket(ServerName, Store)

-spec clear_ticket(binary(), ticket_store()) -> ticket_store().

Remove a ticket for a server.

create_ticket(ServerName, ResumptionSecret, MaxEarlyData, Cipher, ALPN)

-spec create_ticket(binary(), binary(), non_neg_integer(), atom(), binary() | undefined) ->
                       #session_ticket{server_name :: binary(),
                                       ticket :: binary(),
                                       lifetime :: non_neg_integer(),
                                       age_add :: non_neg_integer(),
                                       nonce :: binary(),
                                       resumption_secret :: binary(),
                                       max_early_data :: non_neg_integer(),
                                       received_at :: non_neg_integer(),
                                       cipher :: atom(),
                                       alpn :: binary() | undefined}.

Create a session ticket from connection state. This is used by the server to issue tickets to clients.

derive_psk(ResumptionSecret, Session_ticket)

-spec derive_psk(binary(),
                 #session_ticket{server_name :: binary(),
                                 ticket :: binary(),
                                 lifetime :: non_neg_integer(),
                                 age_add :: non_neg_integer(),
                                 nonce :: binary(),
                                 resumption_secret :: binary(),
                                 max_early_data :: non_neg_integer(),
                                 received_at :: non_neg_integer(),
                                 cipher :: atom(),
                                 alpn :: binary() | undefined}) ->
                    binary().

Derive PSK from resumption_master_secret and ticket nonce. RFC 8446 Section 4.6.1: PSK = HKDF-Expand-Label(resumption_master_secret, "resumption", ticket_nonce, Hash.length)

derive_resumption_secret(Cipher, MasterSecret, TranscriptHash, ClientFinished)

-spec derive_resumption_secret(atom(), binary(), binary(), binary()) -> binary().

Derive the resumption_master_secret from the master secret. RFC 8446 Section 7.1: resumption_master_secret = Derive-Secret(Master Secret, "res master", ClientHello..client Finished)

lookup_ticket(ServerName, Store)

-spec lookup_ticket(binary(), ticket_store()) -> {ok, session_ticket()} | error.

Look up a ticket for a server. Returns {ok, Ticket} if found and not expired, error otherwise.

new_store()

-spec new_store() -> ticket_store().

Create a new empty ticket store.

parse_new_session_ticket(_)

-spec parse_new_session_ticket(binary()) ->
                                  {ok,
                                   #{lifetime := non_neg_integer(),
                                     age_add := non_neg_integer(),
                                     nonce := binary(),
                                     ticket := binary(),
                                     max_early_data := non_neg_integer()}} |
                                  {error, term()}.

Parse a NewSessionTicket message from the server. RFC 8446 Section 4.6.1: struct { uint32 ticket_lifetime; uint32 ticket_age_add; opaque ticket_nonce<0..255>; opaque ticket<1..2^16-1>; Extension extensions<0..2^16-2>; } NewSessionTicket;

store_ticket(ServerName, Ticket, Store)

-spec store_ticket(binary(), session_ticket(), ticket_store()) -> ticket_store().

Store a session ticket for a server. The ticket is indexed by server name.