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

#include <tls_session_manager_sqlite.h>

Inheritance diagram for Botan::TLS::Session_Manager_SQLite:
Botan::TLS::Session_Manager_SQL 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
 
virtual std::optional< Session_Handleestablish (const Session &session, const std::optional< Session_ID > &id=std::nullopt, bool tls12_no_ticket=false)
 Save a new Session and assign a Session_Handle (TLS Server)
 
virtual std::vector< Session_with_Handlefind (const Server_Information &info, Callbacks &callbacks, const Policy &policy)
 Find all sessions that match a given server info.
 
size_t remove (const Session_Handle &handle) override
 
size_t remove_all () override
 
virtual std::optional< Sessionretrieve (const Session_Handle &handle, Callbacks &callbacks, const Policy &policy)
 Retrieves a specific session given a handle.
 
 Session_Manager_SQLite (std::string_view passphrase, const std::shared_ptr< RandomNumberGenerator > &rng, std::string_view db_filename, size_t max_sessions=1000)
 
void store (const Session &session, const Session_Handle &handle) override
 Save a Session under a Session_Handle (TLS Client)
 

Protected Member Functions

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

Protected Attributes

std::shared_ptr< RandomNumberGeneratorm_rng
 

Detailed Description

An implementation of Session_Manager that saves values in a SQLite3 database file, with the session data encrypted using a passphrase.

Warning
For clients, the hostnames associated with the saved sessions are stored in the database in plaintext. This may be a serious privacy risk in some situations.

Definition at line 27 of file tls_session_manager_sqlite.h.

Constructor & Destructor Documentation

◆ Session_Manager_SQLite()

Botan::TLS::Session_Manager_SQLite::Session_Manager_SQLite ( std::string_view passphrase,
const std::shared_ptr< RandomNumberGenerator > & rng,
std::string_view db_filename,
size_t max_sessions = 1000 )
Parameters
passphraseused to encrypt the session data
rnga random number generator
db_filenamefilename of the SQLite database file. The table names tls_sessions and tls_sessions_metadata will be used
max_sessionsa hint on the maximum number of sessions to keep in memory at any one time. (If zero, don't cap)

Definition at line 14 of file tls_session_manager_sqlite.cpp.

17 :
18 Session_Manager_SQL(std::make_shared<Sqlite3_Database>(db_filename), passphrase, rng, max_sessions) {}
Session_Manager_SQL(std::shared_ptr< SQL_Database > db, std::string_view passphrase, const std::shared_ptr< RandomNumberGenerator > &rng, size_t max_sessions=1000)

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().

◆ database_is_threadsafe()

virtual bool Botan::TLS::Session_Manager_SQL::database_is_threadsafe ( ) const
inlineprotectedvirtualinherited

Decides whether the underlying database is considered threadsafe in the context the Session_Manager is used. If this returns false, accesses to the database are serialized with the base class' recursive mutex.

Definition at line 62 of file tls_session_manager_sql.h.

62{ return m_db->is_threadsafe(); }

Referenced by Botan::TLS::Session_Manager_SQL::find_some(), Botan::TLS::Session_Manager_SQL::retrieve_one(), and Botan::TLS::Session_Manager_SQL::store().

◆ emits_session_tickets()

bool Botan::TLS::Session_Manager_SQL::emits_session_tickets ( )
inlineoverridevirtualinherited

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 51 of file tls_session_manager_sql.h.

51{ return false; }

◆ establish()

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

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 in Botan::TLS::Session_Manager_Hybrid, Botan::TLS::Session_Manager_Noop, and Botan::TLS::Session_Manager_Stateless.

Definition at line 21 of file tls_session_manager.cpp.

23 {
24 // Establishing a session does not require locking at this level as
25 // concurrent TLS instances on a server will create unique sessions.
26
27 // By default, the session manager does not emit session tickets anyway
28 BOTAN_UNUSED(tls12_no_ticket);
29 BOTAN_ASSERT(session.side() == Connection_Side::Server, "Client tried to establish a session");
30
31 Session_Handle handle(id.value_or(m_rng->random_vec<Session_ID>(32)));
32 store(session, handle);
33 return handle;
34}
#define BOTAN_UNUSED
Definition assert.h:118
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
virtual void store(const Session &session, const Session_Handle &handle)=0
Save a Session under a Session_Handle (TLS Client)
std::shared_ptr< RandomNumberGenerator > m_rng
Strong< std::vector< uint8_t >, struct Session_ID_ > Session_ID
holds a TLS 1.2 session ID for stateful resumption
Definition tls_session.h:32

References BOTAN_ASSERT, BOTAN_UNUSED, Botan::TLS::Session_Manager::m_rng, Botan::TLS::Server, Botan::TLS::Session_Base::side(), and Botan::TLS::Session_Manager::store().

◆ find()

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

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 in Botan::TLS::Session_Manager_Hybrid.

Definition at line 161 of file tls_session_manager.cpp.

163 {
164 auto allow_reusing_tickets = policy.reuse_session_tickets();
165
166 // Session_Manager::find() must be an atomic getter if ticket reuse is not
167 // allowed. I.e. each ticket handed to concurrently requesting threads must
168 // be unique. In that case we must hold a lock while retrieving a ticket.
169 // Otherwise, no locking is required on this level.
170 std::optional<lock_guard_type<recursive_mutex_type>> lk;
171 if(!allow_reusing_tickets) {
172 lk.emplace(mutex());
173 }
174
175 auto sessions_and_handles = find_and_filter(info, callbacks, policy);
176
177 // std::vector::resize() cannot be used as the vector's members aren't
178 // default constructible.
179 const auto session_limit = policy.maximum_session_tickets_per_client_hello();
180 while(session_limit > 0 && sessions_and_handles.size() > session_limit) {
181 sessions_and_handles.pop_back();
182 }
183
184 // RFC 8446 Appendix C.4
185 // Clients SHOULD NOT reuse a ticket for multiple connections. Reuse of
186 // a ticket allows passive observers to correlate different connections.
187 //
188 // When reuse of session tickets is not allowed, remove all tickets to be
189 // returned from the implementation's internal storage.
190 if(!allow_reusing_tickets) {
191 // The lock must be held here, otherwise we cannot guarantee the
192 // transactional retrieval of tickets to concurrently requesting clients.
193 BOTAN_ASSERT_NOMSG(lk.has_value());
194 for(const auto& [session, handle] : sessions_and_handles) {
195 if(!session.version().is_pre_tls_13() || !handle.is_id()) {
196 remove(handle);
197 }
198 }
199 }
200
201 return sessions_and_handles;
202}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
virtual size_t remove(const Session_Handle &handle)=0
recursive_mutex_type & mutex()

References BOTAN_ASSERT_NOMSG, Botan::TLS::Policy::maximum_session_tickets_per_client_hello(), and Botan::TLS::Policy::reuse_session_tickets().

◆ find_some()

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

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 202 of file tls_session_manager_sql.cpp.

203 {
204 std::optional<lock_guard_type<recursive_mutex_type>> lk;
206 lk.emplace(mutex());
207 }
208
209 auto stmt = m_db->new_statement(
210 "SELECT session_id, session_ticket, session FROM tls_sessions"
211 " WHERE hostname = ?1 AND hostport = ?2"
212 " ORDER BY session_start DESC"
213 " LIMIT ?3");
214
215 stmt->bind(1, info.hostname());
216 stmt->bind(2, info.port());
217 stmt->bind(3, max_sessions_hint);
218
219 std::vector<Session_with_Handle> found_sessions;
220 while(stmt->step()) {
221 auto handle = [&]() -> Session_Handle {
222 auto ticket_blob = stmt->get_blob(1);
223 if(ticket_blob.second > 0) {
224 return Session_Ticket(std::span(ticket_blob.first, ticket_blob.second));
225 } else {
226 return Session_ID(Botan::hex_decode(stmt->get_str(0)));
227 }
228 }();
229
230 std::pair<const uint8_t*, size_t> blob = stmt->get_blob(2);
231
232 try {
233 found_sessions.emplace_back(
234 Session_with_Handle{Session::decrypt(blob.first, blob.second, m_session_key), std::move(handle)});
235 } catch(...) {}
236 }
237
238 return found_sessions;
239}
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)
Strong< std::vector< uint8_t >, struct Session_Ticket_ > Session_Ticket
holds a TLS 1.2 session ticket for stateless resumption
Definition tls_session.h:35
size_t hex_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool ignore_ws)
Definition hex.cpp:73

References Botan::TLS::Session_Manager_SQL::database_is_threadsafe(), Botan::TLS::Session::decrypt(), Botan::hex_decode(), Botan::TLS::Server_Information::hostname(), Botan::TLS::Session_Manager::mutex(), and Botan::TLS::Server_Information::port().

◆ mutex()

◆ remove()

size_t Botan::TLS::Session_Manager_SQL::remove ( const Session_Handle & handle)
overridevirtualinherited

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 241 of file tls_session_manager_sql.cpp.

241 {
242 // The number of deleted rows is taken globally from the database connection,
243 // therefore we need to serialize this implementation.
245
246 if(const auto id = handle.id()) {
247 auto stmt = m_db->new_statement("DELETE FROM tls_sessions WHERE session_id = ?1");
248 stmt->bind(1, hex_encode(id->get()));
249 stmt->spin();
250 } else if(const auto ticket = handle.ticket()) {
251 auto stmt = m_db->new_statement("DELETE FROM tls_sessions WHERE session_ticket = ?1");
252 stmt->bind(1, ticket->get());
253 stmt->spin();
254 } else {
255 // should not happen, as session handles are exclusively either an ID or a ticket
256 throw Invalid_Argument("provided a session handle that is neither ID nor ticket");
257 }
258
259 return m_db->rows_changed_by_last_statement();
260}
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition hex.cpp:35
lock_guard< T > lock_guard_type
Definition mutex.h:55

References Botan::hex_encode(), Botan::TLS::Session_Handle::id(), Botan::TLS::Session_Manager::mutex(), and Botan::TLS::Session_Handle::ticket().

◆ remove_all()

size_t Botan::TLS::Session_Manager_SQL::remove_all ( )
overridevirtualinherited

Remove all sessions from the cache

Returns
the number of sessions that were removed

Implements Botan::TLS::Session_Manager.

Definition at line 262 of file tls_session_manager_sql.cpp.

262 {
263 // The number of deleted rows is taken globally from the database connection,
264 // therefore we need to serialize this implementation.
266
267 m_db->exec("DELETE FROM tls_sessions");
268 return m_db->rows_changed_by_last_statement();
269}

References Botan::TLS::Session_Manager::mutex().

◆ retrieve()

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

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 in Botan::TLS::Session_Manager_Hybrid.

Definition at line 36 of file tls_session_manager.cpp.

38 {
39 // Retrieving a session for a given handle does not require locking on this
40 // level. Concurrent threads might handle the removal of an expired ticket
41 // more than once, but removing an already removed ticket is a harmless NOOP.
42
43 auto session = retrieve_one(handle);
44 if(!session.has_value()) {
45 return std::nullopt;
46 }
47
48 // A value of '0' means: No policy restrictions.
49 const std::chrono::seconds policy_lifetime =
50 (policy.session_ticket_lifetime().count() > 0) ? policy.session_ticket_lifetime() : std::chrono::seconds::max();
51
52 // RFC 5077 3.3 -- "Old Session Tickets"
53 // A server MAY treat a ticket as valid for a shorter or longer period of
54 // time than what is stated in the ticket_lifetime_hint.
55 //
56 // RFC 5246 F.1.4 -- TLS 1.2
57 // If either party suspects that the session may have been compromised, or
58 // that certificates may have expired or been revoked, it should force a
59 // full handshake. An upper limit of 24 hours is suggested for session ID
60 // lifetimes.
61 //
62 // RFC 8446 4.6.1 -- TLS 1.3
63 // A server MAY treat a ticket as valid for a shorter period of time than
64 // what is stated in the ticket_lifetime.
65 //
66 // Note: This disregards what is stored in the session (e.g. "lifetime_hint")
67 // and only takes the local policy into account. The lifetime stored in
68 // the sessions was taken from the same policy anyways and changes by
69 // the application should have an immediate effect.
70 const auto ticket_age =
71 std::chrono::duration_cast<std::chrono::seconds>(callbacks.tls_current_timestamp() - session->start_time());
72 const bool expired = ticket_age > policy_lifetime;
73
74 if(expired) {
75 remove(handle);
76 return std::nullopt;
77 } else {
78 return session;
79 }
80}
virtual std::optional< Session > retrieve_one(const Session_Handle &handle)=0
Internal retrieval function for a single session.

References Botan::TLS::Session_Manager::remove(), Botan::TLS::Session_Manager::retrieve_one(), Botan::TLS::Policy::session_ticket_lifetime(), and Botan::TLS::Callbacks::tls_current_timestamp().

◆ retrieve_one()

std::optional< Session > Botan::TLS::Session_Manager_SQL::retrieve_one ( const Session_Handle & handle)
overrideprotectedvirtualinherited

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 179 of file tls_session_manager_sql.cpp.

179 {
180 std::optional<lock_guard_type<recursive_mutex_type>> lk;
182 lk.emplace(mutex());
183 }
184
185 if(auto session_id = handle.id()) {
186 auto stmt = m_db->new_statement("SELECT session FROM tls_sessions WHERE session_id = ?1");
187
188 stmt->bind(1, hex_encode(session_id->get()));
189
190 while(stmt->step()) {
191 std::pair<const uint8_t*, size_t> blob = stmt->get_blob(0);
192
193 try {
194 return Session::decrypt(blob.first, blob.second, m_session_key);
195 } catch(...) {}
196 }
197 }
198
199 return std::nullopt;
200}

References Botan::TLS::Session_Manager_SQL::database_is_threadsafe(), Botan::TLS::Session::decrypt(), Botan::hex_encode(), Botan::TLS::Session_Handle::id(), and Botan::TLS::Session_Manager::mutex().

◆ store()

void Botan::TLS::Session_Manager_SQL::store ( const Session & session,
const Session_Handle & handle )
overridevirtualinherited

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 148 of file tls_session_manager_sql.cpp.

148 {
149 std::optional<lock_guard_type<recursive_mutex_type>> lk;
151 lk.emplace(mutex());
152 }
153
154 if(session.server_info().hostname().empty()) {
155 return;
156 }
157
158 auto stmt = m_db->new_statement(
159 "INSERT OR REPLACE INTO tls_sessions"
160 " VALUES (?1, ?2, ?3, ?4, ?5, ?6)");
161
162 // Generate a random session ID if the peer did not provide one. Note that
163 // this ID will not be returned on ::find(), as the ticket is preferred.
164 const auto id = handle.id().value_or(m_rng->random_vec<Session_ID>(32));
165 const auto ticket = handle.ticket().value_or(Session_Ticket());
166
167 stmt->bind(1, hex_encode(id.get()));
168 stmt->bind(2, ticket.get());
169 stmt->bind(3, session.start_time());
170 stmt->bind(4, session.server_info().hostname());
171 stmt->bind(5, session.server_info().port());
172 stmt->bind(6, session.encrypt(m_session_key, *m_rng));
173
174 stmt->spin();
175
176 prune_session_cache();
177}

References Botan::TLS::Session_Manager_SQL::database_is_threadsafe(), Botan::TLS::Session::encrypt(), Botan::hex_encode(), Botan::TLS::Server_Information::hostname(), Botan::TLS::Session_Handle::id(), Botan::TLS::Session_Manager::m_rng, Botan::TLS::Session_Manager::mutex(), Botan::TLS::Server_Information::port(), Botan::TLS::Session_Base::server_info(), Botan::TLS::Session_Base::start_time(), and Botan::TLS::Session_Handle::ticket().

Member Data Documentation

◆ m_rng


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