Botan 3.6.1
Crypto and TLS for C&
Botan::TLS::Session_Manager_Hybrid Class Referencefinal

#include <tls_session_manager_hybrid.h>

Inheritance diagram for Botan::TLS::Session_Manager_Hybrid:
Botan::TLS::Session_Manager

Public Member Functions

virtual std::optional< std::pair< Session, uint16_t > > choose_from_offered_tickets (const std::vector< PskIdentity > &tickets, std::string_view hash_function, Callbacks &callbacks, const Policy &policy)
 
bool emits_session_tickets () override
 
std::optional< Session_Handleestablish (const Session &session, const std::optional< Session_ID > &id=std::nullopt, bool tls12_no_ticket=false) override
 Save a new Session and assign a Session_Handle (TLS Server)
 
std::vector< Session_with_Handlefind (const Server_Information &info, Callbacks &callbacks, const Policy &policy) override
 Find all sessions that match a given server info.
 
size_t remove (const Session_Handle &handle) override
 
size_t remove_all () override
 
std::optional< Sessionretrieve (const Session_Handle &handle, Callbacks &callbacks, const Policy &policy) override
 Retrieves a specific session given a handle.
 
 Session_Manager_Hybrid (std::unique_ptr< Session_Manager > stateful_manager, const std::shared_ptr< Credentials_Manager > &credentials_manager, const std::shared_ptr< RandomNumberGenerator > &rng, bool prefer_tickets=true)
 
void store (const Session &session, const Session_Handle &handle) override
 Save a Session under a Session_Handle (TLS Client)
 
Session_Managerunderlying_stateful_manager ()
 

Protected Member Functions

std::vector< Session_with_Handlefind_some (const Server_Information &, const size_t) override
 Internal retrieval function to find sessions to resume.
 
recursive_mutex_typemutex ()
 
std::optional< Sessionretrieve_one (const Session_Handle &) override
 Internal retrieval function for a single session.
 

Protected Attributes

std::shared_ptr< RandomNumberGeneratorm_rng
 

Detailed Description

A combination of the Session_Manager_Stateless and an arbitrary stateful Session_Manager.

This extends any stateful session manager to provide TLS 1.2 session ticket support. Session_Handle objects may either be a Session_Ticket or Session_ID when working with TLS 1.2 servers and depending on the peer's capability to support session tickets.

For TLS 1.3 sessions it will provide one of both, depending on the preference defined in the class' constructor.

For applications that implement a TLS server that allows handshakes with both TLS 1.2 and TLS 1.3 clients, this is typically a good default option. Combine it with the Session_Manager_SQLite or Session_Manager_In_Memory as needed.

Definition at line 39 of file tls_session_manager_hybrid.h.

Constructor & Destructor Documentation

◆ Session_Manager_Hybrid()

Botan::TLS::Session_Manager_Hybrid::Session_Manager_Hybrid ( std::unique_ptr< Session_Manager > stateful_manager,
const std::shared_ptr< Credentials_Manager > & credentials_manager,
const std::shared_ptr< RandomNumberGenerator > & rng,
bool prefer_tickets = true )
Parameters
stateful_managerthe underlying stateful manager instance as a non-owning reference
credentials_managerthe credentials manager to take the ticket key in the stateless memory manager from
rnga RNG used for generating session key and for session encryption
prefer_ticketsfor TLS 1.3 connections, servers need to choose whether to go for self-contained tickets or short database handles

Definition at line 17 of file tls_session_manager_hybrid.cpp.

20 :
21 Session_Manager(rng),
22 m_stateful(std::move(stateful)),
23 m_stateless(credentials_manager, rng),
24 m_prefer_tickets(prefer_tickets) {
25 BOTAN_ASSERT_NONNULL(m_stateful);
26}
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:86
Session_Manager(const std::shared_ptr< RandomNumberGenerator > &rng)

References BOTAN_ASSERT_NONNULL.

Member Function Documentation

◆ choose_from_offered_tickets()

std::optional< std::pair< Session, uint16_t > > Botan::TLS::Session_Manager::choose_from_offered_tickets ( const std::vector< PskIdentity > & tickets,
std::string_view hash_function,
Callbacks & callbacks,
const Policy & policy )
virtualinherited

Lets the server application choose a PSK to use for a new TLS connection. Implementers must make sure that the PSK's associated hash function is equal to the passed hash_function.

RFC 8446 4.2.11 The server MUST ensure that it selects a compatible PSK (if any) and cipher suite.

The default implementation simply tries to retrieve all tickets in the order offered by the peer and picks the first that is found and features a matching hash algorithm.

This method is called only by TLS 1.3 servers.

Parameters
ticketsa list of tickets that were offered by the client
hash_functionthe hash algorithm name we are going to use for the to-be-negotiated connection
callbackscallbacks to be used for session policy decisions
policypolicy to be used for session policy decisions
Returns
a std::pair of the Session associated to the choosen PSK and the index of the selected ticket; std::nullopt if no PSK was chosen for usage (will result in a full handshake)
Note
if no PSK is chosen, the server will attempt a regular handshake.

Definition at line 206 of file tls_session_manager.cpp.

210 {
211 // Note that the TLS server currently does not ensure that tickets aren't
212 // reused. As a result, no locking is required on this level.
213
214 for(uint16_t i = 0; const auto& ticket : tickets) {
215 auto session = retrieve(Opaque_Session_Handle(ticket.identity()), callbacks, policy);
216 if(session.has_value() && session->ciphersuite().prf_algo() == hash_function &&
217 session->version().is_tls_13_or_later()) {
218 return std::pair{std::move(session.value()), i};
219 }
220
221 // RFC 8446 4.2.10
222 // For PSKs provisioned via NewSessionTicket, a server MUST validate
223 // that the ticket age for the selected PSK identity [...] is within a
224 // small tolerance of the time since the ticket was issued. If it is
225 // not, the server SHOULD proceed with the handshake but reject 0-RTT,
226 // and SHOULD NOT take any other action that assumes that this
227 // ClientHello is fresh.
228 //
229 // TODO: The ticket-age is currently not checked (as 0-RTT is not
230 // implemented) and we simply take the SHOULD at face value.
231 // Instead we could add a policy check letting the user decide.
232
233 ++i;
234 }
235
236 return std::nullopt;
237}
virtual std::optional< Session > retrieve(const Session_Handle &handle, Callbacks &callbacks, const Policy &policy)
Retrieves a specific session given a handle.
Strong< std::vector< uint8_t >, struct Opaque_Session_Handle_ > Opaque_Session_Handle
holds an opaque session handle as used in TLS 1.3 that could be either a ticket for stateless resumpt...
Definition tls_session.h:39

Referenced by Botan::TLS::PSK::select_offered_psk().

◆ emits_session_tickets()

bool Botan::TLS::Session_Manager_Hybrid::emits_session_tickets ( )
overridevirtual

Declares whether the given Session_Manager implementation may emit session tickets. Note that this does not mean that the implementation must always emit tickets.

Concrete implementations should declare this, to allow the TLS implementations to act accordingly. E.g. to advertise support for session tickets in their Server Hello.

Returns
true if the Session_Manager produces session tickets

Reimplemented from Botan::TLS::Session_Manager.

Definition at line 83 of file tls_session_manager_hybrid.cpp.

83 {
84 return m_stateless.emits_session_tickets() || m_stateful->emits_session_tickets();
85}

References Botan::TLS::Session_Manager_Stateless::emits_session_tickets().

◆ establish()

std::optional< Session_Handle > Botan::TLS::Session_Manager_Hybrid::establish ( const Session & session,
const std::optional< Session_ID > & id = std::nullopt,
bool tls12_no_ticket = false )
overridevirtual

Save a new Session and assign a Session_Handle (TLS Server)

Save a new session on a best effort basis; the manager may not in fact be able to save the session for whatever reason; this is not an error. Callers cannot assume that calling establish() followed immediately by retrieve() or choose_from_offered_tickets() will result in a successful lookup. In case no session was stored, std::nullopt is returned.

This method is only called on TLS servers.

Note that implementations will silently refrain from sending session tickets to the client when this method returns std::nullopt.

Parameters
sessionto save
idto use (instead of an ID chosen by the manager)
tls12_no_ticketdisable tickets for this establishment (set when TLS 1.2 client does not support them)
Returns
a Session_Handle containing either an ID or a ticket if the session was saved, otherwise std::nullopt

Reimplemented from Botan::TLS::Session_Manager.

Definition at line 28 of file tls_session_manager_hybrid.cpp.

30 {
31 auto create_ticket = [&]() -> std::optional<Session_Handle> {
32 if(tls12_no_ticket) {
33 return std::nullopt;
34 }
35
36 auto ticket_handle = m_stateless.establish(session, id, false /* always allow tickets */);
37 BOTAN_ASSERT_IMPLICATION(ticket_handle.has_value(),
38 ticket_handle->is_ticket(),
39 "Session_Manager_Stateless produced unexpected Session_Handle");
40 return ticket_handle;
41 };
42
43 auto create_id = [&] {
44 // If we're dealing with a TLS 1.2 connection, we opportunistically
45 // disable tickets for the underlying manager.
46 auto id_handle = m_stateful->establish(session, id, session.version().is_pre_tls_13());
48 id_handle.has_value(), id_handle->is_id(), "Session_Manager_In_Memory produced unexpected Session_Handle");
49 return id_handle;
50 };
51
52 std::function preferred = create_ticket;
53 std::function fallback = create_id;
54
55 if(!m_prefer_tickets) {
56 std::swap(preferred, fallback);
57 }
58
59 if(auto result = preferred()) {
60 return result;
61 }
62
63 return fallback();
64}
#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg)
Definition assert.h:77
std::optional< Session_Handle > establish(const Session &session, const std::optional< Session_ID > &id=std::nullopt, bool tls12_no_ticket=false) override
Save a new Session and assign a Session_Handle (TLS Server)

References BOTAN_ASSERT_IMPLICATION, Botan::TLS::Session_Manager_Stateless::establish(), Botan::TLS::Protocol_Version::is_pre_tls_13(), and Botan::TLS::Session_Base::version().

◆ find()

std::vector< Session_with_Handle > Botan::TLS::Session_Manager_Hybrid::find ( const Server_Information & info,
Callbacks & callbacks,
const Policy & policy )
inlineoverridevirtual

Find all sessions that match a given server info.

TLS clients use this to obtain session resumption information for a server they are wishing to handshake with. Typically, session info will have been received in prior connections to that same server and stored using Session_Manager::store().

The default implementation will invoke Session_Manager::find_some() and filter the result against a policy. Most notably an expiry check. Expired sessions will be removed via Session_Manager::remove().

The TLS client implementations will query the session manager exactly once per handshake attempt. If no reuse is desired, the session manager may remove the sessions internally when handing them out to the client. The default implementation adheres to Policy::reuse_session_tickets().

For TLS 1.2 the client implementation will attempt a resumption with the first session in the returned list. For TLS 1.3, it will offer all found sessions to the server.

Applications that wish to implement their own Session_Manager may override the default implementation to add further policy checks. Though, typically implementing Session_Manager::find_some() and relying on the default implementation is enough.

Parameters
infothe info about the server we want to handshake with
callbackscallbacks to be used for session policy decisions
policypolicy to be used for session policy decisions
Returns
a list of usable sessions that might be empty if no such session exists or passed the policy validation

Reimplemented from Botan::TLS::Session_Manager.

Definition at line 65 of file tls_session_manager_hybrid.h.

67 {
68 return m_stateful->find(info, callbacks, policy);
69 }

◆ find_some()

std::vector< Session_with_Handle > Botan::TLS::Session_Manager_Hybrid::find_some ( const Server_Information & info,
const size_t max_sessions_hint )
inlineoverrideprotectedvirtual

Internal retrieval function to find sessions to resume.

Try to find saved sessions using info about the server we're planning to connect to. It should return a list of sessions in preference order of the session manager.

Applications that wish to implement their own Session_Manager will have to provide an implementation for it.

Note that the TLS client implementations do not perform any checks on the validity of the session for a given info. Particularly, it is the Session_Manager's responsibility to ensure the restrictions posed in RFC 8446 4.6.1 regarding server certificate validity for the given info.

This is called for TLS clients only.

Parameters
infothe information about the server
max_sessions_hinta non-binding guideline for an upper bound of sessions to return from this method (will be at least 1 but potentially more)
Returns
the found sessions along with their handles (containing either a session ID or a ticket)

Implements Botan::TLS::Session_Manager.

Definition at line 89 of file tls_session_manager_hybrid.h.

89 {
90 BOTAN_ASSERT(false, "This should never be called");
91 }
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50

References BOTAN_ASSERT.

◆ mutex()

◆ remove()

size_t Botan::TLS::Session_Manager_Hybrid::remove ( const Session_Handle & handle)
inlineoverridevirtual

Remove a specific session from the cache, if it exists. The handle might contain either a session ID or a ticket.

Parameters
handlea Session_Handle of the session to be removed
Returns
the number of sessions that were removed

Implements Botan::TLS::Session_Manager.

Definition at line 73 of file tls_session_manager_hybrid.h.

73{ return m_stateful->remove(handle); }

◆ remove_all()

size_t Botan::TLS::Session_Manager_Hybrid::remove_all ( )
inlineoverridevirtual

Remove all sessions from the cache

Returns
the number of sessions that were removed

Implements Botan::TLS::Session_Manager.

Definition at line 75 of file tls_session_manager_hybrid.h.

75{ return m_stateful->remove_all(); }

◆ retrieve()

std::optional< Session > Botan::TLS::Session_Manager_Hybrid::retrieve ( const Session_Handle & handle,
Callbacks & callbacks,
const Policy & policy )
overridevirtual

Retrieves a specific session given a handle.

This is typically used by TLS servers to obtain resumption information for a previous call to Session_Manager::establish() when a client requested resumption using the handle.

Even if the session is found successfully, it is returned only if it passes policy validations. Most notably an expiry check. If the expiry check fails, the default implementation calls Session_Manager::remove() for the provided handle.

Applications that wish to implement their own Session_Manager may override the default implementation to add further policy checks. Though, typically implementing Session_Manager::retrieve_one() and relying on the default implementation is enough.

Parameters
handlethe Session_Handle to be retrieved
callbackscallbacks to be used for session policy decisions
policypolicy to be used for session policy decisions
Returns
the obtained session or std::nullopt if no session was found or the policy checks failed

Reimplemented from Botan::TLS::Session_Manager.

Definition at line 66 of file tls_session_manager_hybrid.cpp.

68 {
69 std::reference_wrapper<Session_Manager> preferred = m_stateless;
70 std::reference_wrapper<Session_Manager> fallback = *m_stateful;
71
72 if(!m_prefer_tickets) {
73 std::swap(preferred, fallback);
74 }
75
76 if(auto session = preferred.get().retrieve(handle, callbacks, policy)) {
77 return session;
78 }
79
80 return fallback.get().retrieve(handle, callbacks, policy);
81}

◆ retrieve_one()

std::optional< Session > Botan::TLS::Session_Manager_Hybrid::retrieve_one ( const Session_Handle & handle)
inlineoverrideprotectedvirtual

Internal retrieval function for a single session.

Try to obtain a Session from a Session_Handle that contains either a session ID or a session ticket. This method should not apply any policy decision (such as ticket expiry) but simply be a storage interface.

Applications that wish to implement their own Session_Manager will have to provide an implementation for it.

This method is called only by servers.

Parameters
handlea Session_Handle containing either an ID or a ticket
Returns
the obtained session or std::nullopt if none can be obtained

Implements Botan::TLS::Session_Manager.

Definition at line 85 of file tls_session_manager_hybrid.h.

85 {
86 BOTAN_ASSERT(false, "This should never be called");
87 }

References BOTAN_ASSERT.

◆ store()

void Botan::TLS::Session_Manager_Hybrid::store ( const Session & session,
const Session_Handle & handle )
inlineoverridevirtual

Save a Session under a Session_Handle (TLS Client)

Save a session on a best effort basis; the manager may not in fact be able to save the session for whatever reason; this is not an error. Callers cannot assume that calling store() followed immediately by find() will result in a successful lookup.

In contrast to establish(), this stores sessions that were created by the server along with a Session_Handle also coined by the server.

This method is only called on TLS clients.

Parameters
sessionto save
handlea Session_Handle on which this session shoud by stored

Implements Botan::TLS::Session_Manager.

Definition at line 71 of file tls_session_manager_hybrid.h.

71{ m_stateful->store(session, handle); }

◆ underlying_stateful_manager()

Session_Manager * Botan::TLS::Session_Manager_Hybrid::underlying_stateful_manager ( )
inline

Definition at line 79 of file tls_session_manager_hybrid.h.

79{ return m_stateful.get(); }

Member Data Documentation

◆ m_rng


The documentation for this class was generated from the following files: