/* * (C) 2022 René Meusel - Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_TLS_SESSION_ID_H_ #define BOTAN_TLS_SESSION_ID_H_ #include #include #include #include #include namespace Botan::TLS { // Different flavors of session handles are used, depending on the usage // scenario and the TLS protocol version. /// @brief holds a TLS 1.2 session ID for stateful resumption using Session_ID = Strong, struct Session_ID_>; /// @brief holds a TLS 1.2 session ticket for stateless resumption using Session_Ticket = Strong, struct Session_Ticket_>; /// @brief holds an opaque session handle as used in TLS 1.3 that could be /// either a ticket for stateless resumption or a database handle. using Opaque_Session_Handle = Strong, struct Opaque_Session_Handle_>; inline auto operator<(const Session_ID& id1, const Session_ID& id2) { return id1.get() < id2.get(); } /** * @brief Helper class to embody a session handle in all protocol versions * * Sessions in TLS 1.2 are identified by an arbitrary and unique ID of up to * 32 bytes or by a self-contained arbitrary-length ticket (RFC 5077). * * TLS 1.3 does not distinct between the two and handles both as tickets. Also * a TLS 1.3 server can issue multiple tickets in one connection and the * resumption mechanism is compatible with the PSK establishment. * * Concrete implementations of Session_Manager use this helper to distinguish * the different states and manage sessions for TLS 1.2 and 1.3 connections. * * Note that all information stored in a Session_Handle might be transmitted in * unprotected form. Hence, it should not contain any confidential information. */ class BOTAN_PUBLIC_API(3, 0) Session_Handle { public: // NOLINTBEGIN(*-explicit-conversions) /** * Constructs a Session_Handle from a session ID which is an * arbitrary byte vector that must be 32 bytes long at most. */ Session_Handle(Session_ID id) : m_handle(std::move(id)) { validate_constraints(); } /** * Constructs a Session_Handle from a session ticket which is a * non-empty byte vector that must be 64kB long at most. * Typically, tickets facilitate stateless server implementations * and contain all relevant context in encrypted/authenticated form. * * Note that (for technical reasons) we enforce that tickets are * longer than 32 bytes. */ Session_Handle(Session_Ticket ticket) : m_handle(std::move(ticket)) { validate_constraints(); } /** * Constructs a Session_Handle from an Opaque_Handle such as TLS 1.3 * uses them in its resumption mechanism. This could be either a * Session_ID or a Session_Ticket and it is up to the Session_Manager * to figure out what it actually is. */ Session_Handle(Opaque_Session_Handle ticket) : m_handle(std::move(ticket)) { validate_constraints(); } // NOLINTEND(*-explicit-conversions) bool is_id() const { return std::holds_alternative(m_handle); } bool is_ticket() const { return std::holds_alternative(m_handle); } bool is_opaque_handle() const { return std::holds_alternative(m_handle); } /** * Returns the Session_Handle as an opaque handle. If the object was not * constructed as an Opaque_Session_Handle, the contained value is * converted. */ Opaque_Session_Handle opaque_handle() const; /** * If the Session_Handle was constructed with a Session_ID or an * Opaque_Session_Handle that can be converted to a Session_ID (up to * 32 bytes long), this returns the handle as a Session_ID. Otherwise, * std::nullopt is returned. */ std::optional id() const; /** * If the Session_Handle was constructed with a Session_Ticket or an * Opaque_Session_Handle this returns the handle as a Session_ID. * Otherwise, std::nullopt is returned. */ std::optional ticket() const; decltype(auto) get() const { return m_handle; } private: void validate_constraints() const; private: std::variant m_handle; }; } // namespace Botan::TLS #endif