diff --git a/include/oxen/quic/endpoint.hpp b/include/oxen/quic/endpoint.hpp index e4921ccb..9287b240 100644 --- a/include/oxen/quic/endpoint.hpp +++ b/include/oxen/quic/endpoint.hpp @@ -165,8 +165,8 @@ namespace oxen::quic bool stateless_reset_enabled() const { return _stateless_reset_enabled; } - int validate_anti_replay(gtls_session_ticket ticket, time_t exp); - void store_session_ticket(gtls_session_ticket ticket); + int validate_anti_replay(gtls_ticket_ptr ticket, time_t exp); + void store_session_ticket(gtls_ticket_ptr ticket); gtls_ticket_ptr get_session_ticket(const ustring_view& remote_pk); private: diff --git a/include/oxen/quic/gnutls_crypto.hpp b/include/oxen/quic/gnutls_crypto.hpp index df1e7af7..3c5b31fd 100644 --- a/include/oxen/quic/gnutls_crypto.hpp +++ b/include/oxen/quic/gnutls_crypto.hpp @@ -260,21 +260,21 @@ namespace oxen::quic } }; + struct gtls_session_ticket; + using gtls_ticket_ptr = std::unique_ptr; struct gtls_session_ticket { - std::vector _key; + private: + const std::vector _key; std::vector _ticket; gnutls_datum_t _data; explicit gtls_session_ticket( const unsigned char* key, unsigned int keysize, const unsigned char* ticket, unsigned int ticketsize) : - _key(keysize), _ticket(ticketsize) - { - std::memcpy(_key.data(), key, keysize); - std::memcpy(_ticket.data(), ticket, ticketsize); - _data.data = _ticket.data(); - _data.size = _ticket.size(); - } + _key{key, key + keysize}, + _ticket{ticket, ticket + ticketsize}, + _data{.data = _ticket.data(), .size = ticketsize} + {} explicit gtls_session_ticket(ustring_view key, ustring_view ticket) : gtls_session_ticket{ @@ -284,56 +284,33 @@ namespace oxen::quic static_cast(ticket.size())} {} - gtls_session_ticket(const gnutls_datum_t* key, const gnutls_datum_t* ticket) : - gtls_session_ticket{key->data, key->size, ticket->data, ticket->size} - {} - - gtls_session_ticket(const gtls_session_ticket& t) : - gtls_session_ticket{ - t._key.data(), - static_cast(t._key.size()), - t._ticket.data(), - static_cast(t._ticket.size())} - {} - - gtls_session_ticket& operator=(gtls_session_ticket&& other) - { - _key = std::move(other._key); - _ticket = std::move(other._ticket); - _data.data = _ticket.data(); - _data.size = _ticket.size(); - return *this; - } + public: + gtls_session_ticket() = delete; + gtls_session_ticket(gtls_session_ticket&& t) = delete; + gtls_session_ticket(const gtls_session_ticket& t) = delete; + gtls_session_ticket& operator=(gtls_session_ticket&&) = delete; + gtls_session_ticket& operator=(const gtls_session_ticket&) = delete; - static std::unique_ptr make(ustring_view key, ustring_view ticket) + static gtls_ticket_ptr make(ustring_view key, ustring_view ticket) { - return std::make_unique(key, ticket); + return gtls_ticket_ptr(new gtls_session_ticket{key, ticket}); } - - static std::unique_ptr make(gtls_session_ticket&& g) + static gtls_ticket_ptr make(const gnutls_datum_t* key, const gnutls_datum_t* ticket) { - return std::make_unique(std::move(g)); + return make({key->data, key->size}, {ticket->data, ticket->size}); } + // Returns a view of the key for this ticket. The view is valid as long as this + // gtls_session_ticket object remains alive, and so can be used (for example) as the key of + // a map containing the object in the value. ustring_view key() const { return {_key.data(), _key.size()}; } - bool operator==(const gtls_session_ticket& other) const { return _ticket == other._ticket; } - - bool operator==(const gnutls_datum_t* other) const - { - return gnutls_memcmp(_data.data, other->data, _data.size) == 0; - } + // Returns a view of the ticket data. + ustring_view ticket() const { return {_ticket.data(), _ticket.size()}; } - template - operator T*() - { - return &_data; - } - template - operator const T*() const - { - return &_data; - } + // Accesses the ticket data pointer as needed by gnutls API + const gnutls_datum_t* datum() const { return &_data; } + gnutls_datum_t* datum() { return &_data; } }; struct Packet; @@ -449,17 +426,3 @@ namespace oxen::quic Connection* get_connection_from_gnutls(gnutls_session_t g_session); } // namespace oxen::quic - -namespace std -{ - template <> - struct hash - { - size_t operator()(const oxen::quic::gtls_session_ticket& t) const noexcept - { - auto h = hash{}(oxen::quic::ustring_view{t._ticket.data(), t._ticket.size()}); - h ^= hash{}(t.key()) + oxen::quic::inverse_golden_ratio + (h << 7) + (h >> 3); - return h; - } - }; -} // namespace std diff --git a/include/oxen/quic/opt.hpp b/include/oxen/quic/opt.hpp index b7d8a2fc..3b67298c 100644 --- a/include/oxen/quic/opt.hpp +++ b/include/oxen/quic/opt.hpp @@ -204,8 +204,6 @@ namespace oxen::quic }; } // namespace opt - using gtls_ticket_ptr = std::unique_ptr; - using gtls_db_validate_cb = std::function; using gtls_db_get_cb = std::function; using gtls_db_put_cb = std::function; diff --git a/src/endpoint.cpp b/src/endpoint.cpp index 818fa9e1..60afb37f 100644 --- a/src/endpoint.cpp +++ b/src/endpoint.cpp @@ -96,7 +96,7 @@ namespace oxen::quic if (auto it = session_tickets.find(key); it != session_tickets.end()) { - if (auto exp = gnutls_db_check_entry_expire_time(*it->second); current < exp) + if (auto exp = gnutls_db_check_entry_expire_time(it->second->datum()); current < exp) { log::debug(log_cat, "Found existing anti-replay ticket for incoming connection; rejecting..."); return GNUTLS_E_DB_ENTRY_EXISTS; @@ -550,15 +550,15 @@ namespace oxen::quic } } - int Endpoint::validate_anti_replay(gtls_session_ticket ticket, time_t current) + int Endpoint::validate_anti_replay(gtls_ticket_ptr ticket, time_t current) { - return _validate_0rtt_ticket(gtls_session_ticket::make(std::move(ticket)), current) ? 0 : GNUTLS_E_DB_ENTRY_EXISTS; + return _validate_0rtt_ticket(std::move(ticket), current) ? 0 : GNUTLS_E_DB_ENTRY_EXISTS; } - void Endpoint::store_session_ticket(gtls_session_ticket ticket) + void Endpoint::store_session_ticket(gtls_ticket_ptr ticket) { log::trace(log_cat, "Storing session ticket..."); - return _put_session_ticket(gtls_session_ticket::make(std::move(ticket)), 0); + return _put_session_ticket(std::move(ticket), 0); } gtls_ticket_ptr Endpoint::get_session_ticket(const ustring_view& remote_pk) diff --git a/src/gnutls_session.cpp b/src/gnutls_session.cpp index 7d21c6b1..0b5e51eb 100644 --- a/src/gnutls_session.cpp +++ b/src/gnutls_session.cpp @@ -23,7 +23,7 @@ namespace oxen::quic if (not ep->zero_rtt_enabled()) throw std::runtime_error{"Anti-replay DB hook should not be called on 0rtt-disabled endpoint!"}; - return ep->validate_anti_replay({key, data}, exp_time); + return ep->validate_anti_replay(gtls_session_ticket::make(key, data), exp_time); } int gtls_session_callbacks::client_session_cb( @@ -53,8 +53,8 @@ namespace oxen::quic return rv; } - ep.store_session_ticket(gtls_session_ticket{ - remote_key.data(), static_cast(remote_key.size()), encoded.data, encoded.size}); + ep.store_session_ticket(gtls_session_ticket::make( + remote_key, {encoded.data, encoded.size})); } return 0; @@ -248,7 +248,7 @@ namespace oxen::quic { gnutls_datum_t d; - if (auto rv = gnutls_pem_base64_decode2(SESSION_TICKET_HEADER, &maybe_ticket->_data, &d); rv != 0) + if (auto rv = gnutls_pem_base64_decode2(SESSION_TICKET_HEADER, maybe_ticket->datum(), &d); rv != 0) { log::warning(log_cat, "Failed to decode session ticket: {}", ngtcp2_strerror(rv)); throw std::runtime_error("gnutls_pem_base64_decode2 failed");