Botan 3.9.0
Crypto and TLS for C&
tls_session_manager_stateless.cpp
Go to the documentation of this file.
1/**
2 * TLS Stateless Session Manager for stateless servers
3 * (C) 2023 Jack Lloyd
4 * 2023 René Meusel - Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9#include <botan/tls_session_manager_stateless.h>
10
11#include <botan/credentials_manager.h>
12#include <botan/exceptn.h>
13#include <botan/rng.h>
14
15#include <botan/internal/stl_util.h>
16
17namespace Botan::TLS {
18
19Session_Manager_Stateless::Session_Manager_Stateless(const std::shared_ptr<Credentials_Manager>& creds,
20 const std::shared_ptr<RandomNumberGenerator>& rng) :
21 Session_Manager(rng), m_credentials_manager(creds) {
22 BOTAN_ASSERT_NONNULL(m_credentials_manager);
23}
24
25std::optional<Session_Handle> Session_Manager_Stateless::establish(const Session& session,
26 const std::optional<Session_ID>& /*session_id*/,
27 bool tls12_no_ticket) {
28 BOTAN_ASSERT(session.side() == Connection_Side::Server, "Client tried to establish a session");
29 if(tls12_no_ticket) {
30 return std::nullopt;
31 }
32
33 const auto key = get_ticket_key();
34 if(!key.has_value()) {
35 return std::nullopt;
36 }
37
38 return Session_Handle(Session_Ticket{session.encrypt(key.value(), *m_rng)});
39}
40
41void Session_Manager_Stateless::store(const Session& /*session*/, const Session_Handle& /*handle*/) {
42 throw Invalid_Argument("A stateless Session Manager cannot store Sessions with their handle");
43}
44
45std::optional<Session> Session_Manager_Stateless::retrieve_one(const Session_Handle& handle) {
46 auto ticket = handle.ticket();
47 if(!ticket.has_value()) {
48 return std::nullopt;
49 }
50
51 const auto key = get_ticket_key();
52 if(!key.has_value()) {
53 return std::nullopt;
54 }
55
56 try {
57 return Session::decrypt(ticket.value(), key.value());
58 } catch(const std::exception&) {
59 // RFC 8446 4.2.11
60 // Any unknown PSKs (e.g., ones not in the PSK database or encrypted
61 // with an unknown key) SHOULD simply be ignored.
62 return std::nullopt;
63 }
64}
65
67 return get_ticket_key().has_value();
68}
69
70std::optional<SymmetricKey> Session_Manager_Stateless::get_ticket_key() noexcept {
71 try {
72 auto key = m_credentials_manager->psk("tls-server", "session-ticket", "");
73 if(key.empty()) {
74 return std::nullopt;
75 }
76 return key;
77 } catch(...) {
78 return std::nullopt;
79 }
80}
81
82} // namespace Botan::TLS
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
Connection_Side side() const
Helper class to embody a session handle in all protocol versions.
Definition tls_session.h:63
std::optional< Session_Ticket > ticket() const
Session_Manager_Stateless(const std::shared_ptr< Credentials_Manager > &credentials_manager, const std::shared_ptr< RandomNumberGenerator > &rng)
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)
void store(const Session &session, const Session_Handle &handle) override
Save a Session under a Session_Handle (TLS Client)
std::optional< Session > retrieve_one(const Session_Handle &handle) override
Internal retrieval function for a single session.
BOTAN_FUTURE_EXPLICIT Session_Manager(const std::shared_ptr< RandomNumberGenerator > &rng)
std::shared_ptr< RandomNumberGenerator > m_rng
std::vector< uint8_t > encrypt(const SymmetricKey &key, RandomNumberGenerator &rng) const
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:34