11#include <botan/tls_extensions.h>
14#include <botan/tls_callbacks.h>
15#include <botan/tls_exceptn.h>
16#include <botan/tls_policy.h>
17#include <botan/internal/ct_utils.h>
18#include <botan/internal/stl_util.h>
19#include <botan/internal/tls_reader.h>
25#if defined(BOTAN_HAS_X25519)
26 #include <botan/x25519.h>
29#if defined(BOTAN_HAS_X448)
30 #include <botan/x448.h>
34#include <botan/dl_group.h>
35#include <botan/ecdh.h>
41class Key_Share_Entry {
43 Key_Share_Entry(TLS_Data_Reader& reader) {
45 m_group =
static_cast<Named_Group>(reader.get_uint16_t());
46 m_key_exchange = reader.get_tls_length_value(2);
51 Key_Share_Entry(
const TLS::Group_Params group) : m_group(group) {}
53 Key_Share_Entry(
const TLS::Group_Params group, Callbacks& cb, RandomNumberGenerator& rng) :
54 m_group(group), m_private_key(cb.tls_kem_generate_key(group, rng)) {
56 throw TLS_Exception(Alert::InternalError,
"Application did not provide a suitable ephemeral key pair");
60 m_key_exchange = m_private_key->public_key_bits();
61 }
else if(group.is_ecdh_named_curve()) {
62 auto pkey =
dynamic_cast<ECDH_PublicKey*
>(m_private_key.get());
64 throw TLS_Exception(Alert::InternalError,
"Application did not provide a ECDH_PublicKey");
77 auto pkey =
dynamic_cast<PK_Key_Agreement_Key*
>(m_private_key.get());
79 throw TLS_Exception(Alert::InternalError,
"Application did not provide a key-agreement key");
82 m_key_exchange = pkey->public_value();
86 bool empty()
const {
return (m_group == Group_Params::NONE) && m_key_exchange.empty(); }
88 std::vector<uint8_t> serialize()
const {
89 std::vector<uint8_t> result;
90 result.reserve(m_key_exchange.size() + 4);
92 const uint16_t named_curve_id = m_group.wire_code();
103 const Policy& policy,
105 RandomNumberGenerator& rng) {
106 auto [encapsulated_shared_key, shared_key] =
108 m_key_exchange = std::move(encapsulated_shared_key);
109 return std::move(shared_key);
119 const Policy& policy,
121 RandomNumberGenerator& rng) {
125 auto shared_secret = cb.tls_kem_decapsulate(m_group, *m_private_key, received.m_key_exchange, rng, policy);
126 m_private_key.reset();
132 if((m_group == Named_Group::X25519 || m_group == Named_Group::X448) &&
133 CT::all_zeros(shared_secret.data(), shared_secret.size()).as_bool()) {
134 throw TLS_Exception(Alert::DecryptError,
"Bad X25519 or X448 key exchange");
137 return shared_secret;
142 std::vector<uint8_t> m_key_exchange;
143 std::unique_ptr<Private_Key> m_private_key;
146class Key_Share_ClientHello;
148class Key_Share_ServerHello {
150 Key_Share_ServerHello(TLS_Data_Reader& reader, uint16_t) : m_server_share(reader) {}
153 const Key_Share_ClientHello& client_keyshare,
154 const Policy& policy,
156 RandomNumberGenerator& rng);
158 ~Key_Share_ServerHello() =
default;
160 Key_Share_ServerHello(
const Key_Share_ServerHello&) =
delete;
161 Key_Share_ServerHello& operator=(
const Key_Share_ServerHello&) =
delete;
163 Key_Share_ServerHello(Key_Share_ServerHello&&) =
default;
164 Key_Share_ServerHello& operator=(Key_Share_ServerHello&&) =
default;
166 std::vector<uint8_t> serialize()
const {
return m_server_share.serialize(); }
168 bool empty()
const {
return m_server_share.empty(); }
170 Key_Share_Entry& get_singleton_entry() {
return m_server_share; }
172 const Key_Share_Entry& get_singleton_entry()
const {
return m_server_share; }
174 std::vector<Named_Group> offered_groups()
const {
return {selected_group()}; }
176 Named_Group selected_group()
const {
return m_server_share.group(); }
180 return std::exchange(m_shared_secret, {});
184 Key_Share_Entry m_server_share;
188class Key_Share_ClientHello {
190 Key_Share_ClientHello(TLS_Data_Reader& reader, uint16_t ) {
200 const auto client_key_share_length = reader.get_uint16_t();
201 const auto read_bytes_so_far_begin = reader.read_so_far();
202 auto remaining = [&] {
203 const auto read_so_far = reader.read_so_far() - read_bytes_so_far_begin;
205 return client_key_share_length - read_so_far;
208 while(reader.has_remaining() && remaining() > 0) {
209 if(remaining() < 4) {
210 throw TLS_Exception(Alert::DecodeError,
"Not enough data to read another KeyShareEntry");
213 Key_Share_Entry new_entry(reader);
220 if(std::find_if(m_client_shares.begin(), m_client_shares.end(), [&](
const auto& entry) {
221 return entry.group() == new_entry.group();
222 }) != m_client_shares.end()) {
223 throw TLS_Exception(Alert::IllegalParameter,
"Received multiple key share entries for the same group");
226 m_client_shares.emplace_back(std::move(new_entry));
229 if((reader.read_so_far() - read_bytes_so_far_begin) != client_key_share_length) {
230 throw Decoding_Error(
"Read bytes are not equal client KeyShare length");
234 Key_Share_ClientHello(
const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng) {
235 const auto supported = policy.key_exchange_groups();
236 const auto offers = policy.key_exchange_groups_to_offer();
249 for(
const auto group : supported) {
250 if(std::find(offers.begin(), offers.end(), group) == offers.end()) {
253 m_client_shares.emplace_back(group, cb, rng);
257 ~Key_Share_ClientHello() =
default;
259 Key_Share_ClientHello(
const Key_Share_ClientHello&) =
delete;
260 Key_Share_ClientHello& operator=(
const Key_Share_ClientHello&) =
delete;
262 Key_Share_ClientHello(Key_Share_ClientHello&&) =
default;
263 Key_Share_ClientHello& operator=(Key_Share_ClientHello&&) =
default;
265 void retry_offer(
const TLS::Group_Params to_offer, Callbacks& cb, RandomNumberGenerator& rng) {
269 if(std::find_if(m_client_shares.cbegin(), m_client_shares.cend(), [&](
const auto& kse) {
270 return kse.group() == to_offer;
271 }) != m_client_shares.cend()) {
272 throw TLS_Exception(Alert::IllegalParameter,
"group was already offered");
275 m_client_shares.clear();
276 m_client_shares.emplace_back(to_offer, cb, rng);
279 std::vector<Named_Group> offered_groups()
const {
280 std::vector<Named_Group> offered_groups;
281 offered_groups.reserve(m_client_shares.size());
282 for(
const auto& share : m_client_shares) {
283 offered_groups.push_back(share.group());
285 return offered_groups;
288 Named_Group selected_group()
const {
throw Invalid_Argument(
"Client Hello Key Share does not select a group"); }
290 std::vector<uint8_t> serialize()
const {
291 std::vector<uint8_t> shares;
292 for(
const auto& share : m_client_shares) {
293 const auto serialized_share = share.serialize();
294 shares.insert(shares.end(), serialized_share.cbegin(), serialized_share.cend());
297 std::vector<uint8_t> result;
311 const Policy& policy,
313 RandomNumberGenerator& rng)
const {
314 auto& server_selected = server_share.get_singleton_entry();
317 auto match = std::find_if(m_client_shares.begin(), m_client_shares.end(), [&](
const auto& offered) {
318 return offered.group() == server_selected.group();
326 return server_selected.encapsulate(*match, policy, cb, rng);
330 const Policy& policy,
332 RandomNumberGenerator& rng) {
333 const auto& server_selected = server_share.get_singleton_entry();
336 auto match = std::find_if(m_client_shares.begin(), m_client_shares.end(), [&](
const auto& offered) {
337 return offered.group() == server_selected.group();
344 if(match == m_client_shares.end()) {
345 throw TLS_Exception(Alert::IllegalParameter,
"Server selected a key exchange group we didn't offer.");
348 return match->decapsulate(server_selected, policy, cb, rng);
352 std::vector<Key_Share_Entry> m_client_shares;
355Key_Share_ServerHello::Key_Share_ServerHello(
Named_Group group,
356 const Key_Share_ClientHello& client_keyshare,
357 const Policy& policy,
359 RandomNumberGenerator& rng) :
360 m_server_share(group) {
361 m_shared_secret = client_keyshare.encapsulate(*
this, policy, cb, rng);
364class Key_Share_HelloRetryRequest {
366 Key_Share_HelloRetryRequest(TLS_Data_Reader& reader, uint16_t extension_size) {
367 constexpr auto sizeof_uint16_t =
sizeof(uint16_t);
369 if(extension_size != sizeof_uint16_t) {
370 throw Decoding_Error(
"Size of KeyShare extension in HelloRetryRequest must be " +
371 std::to_string(sizeof_uint16_t) +
" bytes");
374 m_selected_group =
static_cast<Named_Group>(reader.get_uint16_t());
377 Key_Share_HelloRetryRequest(Named_Group selected_group) : m_selected_group(selected_group) {}
379 ~Key_Share_HelloRetryRequest() =
default;
381 Key_Share_HelloRetryRequest(
const Key_Share_HelloRetryRequest&) =
delete;
382 Key_Share_HelloRetryRequest& operator=(
const Key_Share_HelloRetryRequest&) =
delete;
384 Key_Share_HelloRetryRequest(Key_Share_HelloRetryRequest&&) =
default;
385 Key_Share_HelloRetryRequest& operator=(Key_Share_HelloRetryRequest&&) =
default;
387 std::vector<uint8_t> serialize()
const {
388 auto code = m_selected_group.wire_code();
389 return {get_byte<0>(code), get_byte<1>(code)};
392 Named_Group selected_group()
const {
return m_selected_group; }
394 std::vector<Named_Group> offered_groups()
const {
395 throw Invalid_Argument(
"Hello Retry Request never offers any key exchange groups");
398 bool empty()
const {
return m_selected_group == Group_Params::NONE; }
406class Key_Share::Key_Share_Impl {
408 using Key_Share_Type = std::variant<Key_Share_ClientHello, Key_Share_ServerHello, Key_Share_HelloRetryRequest>;
410 Key_Share_Impl(Key_Share_Type ks) : key_share(std::move(ks)) {}
413 Key_Share_Type key_share;
417 if(message_type == Handshake_Type::ClientHello) {
418 m_impl = std::make_unique<Key_Share_Impl>(Key_Share_ClientHello(reader, extension_size));
419 }
else if(message_type == Handshake_Type::HelloRetryRequest)
421 m_impl = std::make_unique<Key_Share_Impl>(Key_Share_HelloRetryRequest(reader, extension_size));
422 }
else if(message_type == Handshake_Type::ServerHello)
424 m_impl = std::make_unique<Key_Share_Impl>(Key_Share_ServerHello(reader, extension_size));
426 throw Invalid_Argument(std::string(
"cannot create a Key_Share extension for message of type: ") +
433 m_impl(std::make_unique<Key_Share_Impl>(Key_Share_ClientHello(policy, cb, rng))) {}
437 m_impl(std::make_unique<Key_Share_Impl>(Key_Share_HelloRetryRequest(selected_group))) {}
445 m_impl(std::make_unique<Key_Share_Impl>(Key_Share_ServerHello(
446 selected_group, std::get<Key_Share_ClientHello>(client_keyshare.m_impl->key_share), policy, cb, rng))) {}
451 return std::visit([](
const auto& key_share) {
return key_share.serialize(); }, m_impl->key_share);
455 return std::visit([](
const auto& key_share) {
return key_share.empty(); }, m_impl->key_share);
470 return std::visit(
overloaded{[&](Key_Share_ClientHello& ch,
const Key_Share_ServerHello& sh) {
471 return ch.decapsulate(sh, policy, cb, rng);
475 "can only decapsulate in ClientHello Key_Share with a ServerHello Key_Share");
478 server_keyshare.m_impl->key_share);
482 return std::visit([](
const auto& keyshare) {
return keyshare.offered_groups(); }, m_impl->key_share);
486 return std::visit([](
const auto& keyshare) {
return keyshare.selected_group(); }, m_impl->key_share);
491 overloaded{[](Key_Share_ServerHello& server_keyshare) {
return server_keyshare.take_shared_secret(); },
493 throw Invalid_Argument(
"Only the key share in Server Hello contains a shared secret");
499 const std::vector<Named_Group>& supported_groups,
502 std::visit(
overloaded{[&](Key_Share_ClientHello& ch,
const Key_Share_HelloRetryRequest& hrr) {
503 auto selected = hrr.selected_group();
508 throw TLS_Exception(Alert::IllegalParameter,
"group was not advertised as supported");
511 return ch.retry_offer(selected, cb, rng);
513 [](
const auto&,
const auto&) {
514 throw Invalid_Argument(
"can only retry with HelloRetryRequest on a ClientHello Key_Share");
517 retry_request_keyshare.m_impl->key_share);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
static std::pair< std::vector< uint8_t >, secure_vector< uint8_t > > destructure(KEM_Encapsulation &&kem)
Named_Group selected_group() const
std::vector< Named_Group > offered_groups() const
Key_Share(TLS_Data_Reader &reader, uint16_t extension_size, Handshake_Type message_type)
secure_vector< uint8_t > decapsulate(const Key_Share &server_keyshare, const Policy &policy, Callbacks &cb, RandomNumberGenerator &rng)
void retry_offer(const Key_Share &retry_request_keyshare, const std::vector< Named_Group > &supported_groups, Callbacks &cb, RandomNumberGenerator &rng)
static std::unique_ptr< Key_Share > create_as_encapsulation(Group_Params selected_group, const Key_Share &client_keyshare, const Policy &policy, Callbacks &cb, RandomNumberGenerator &rng)
std::vector< uint8_t > serialize(Connection_Side whoami) const override
bool empty() const override
secure_vector< uint8_t > take_shared_secret()
constexpr CT::Mask< T > all_zeros(const T elem[], size_t len)
const char * handshake_type_to_string(Handshake_Type type)
void append_tls_length_value(std::vector< uint8_t, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
constexpr uint8_t get_byte(T input)
bool value_exists(const std::vector< T > &vec, const OT &val)
std::vector< T, secure_allocator< T > > secure_vector