Botan 3.11.0
Crypto and TLS for C&
Botan::TLS::Server_Key_Exchange Class Referencefinal

#include <tls_messages_12.h>

Inheritance diagram for Botan::TLS::Server_Key_Exchange:
Botan::TLS::Handshake_Message

Public Member Functions

Server_Key_Exchangeoperator= (const Server_Key_Exchange &other)=delete
Server_Key_Exchangeoperator= (Server_Key_Exchange &&other)=delete
const std::vector< uint8_t > & params () const
const PK_Key_Agreement_Keyserver_kex_key () const
 Server_Key_Exchange (const Server_Key_Exchange &other)=delete
 Server_Key_Exchange (const std::vector< uint8_t > &buf, Kex_Algo kex_alg, Auth_Method sig_alg, Protocol_Version version)
 Server_Key_Exchange (Handshake_IO &io, Handshake_State &state, const Policy &policy, Credentials_Manager &creds, RandomNumberGenerator &rng, const Private_Key *signing_key=nullptr)
 Server_Key_Exchange (Server_Key_Exchange &&other)=delete
const std::optional< Group_Params > & shared_group () const
Handshake_Type type () const override
std::string type_string () const
bool verify (const Public_Key &server_key, const Handshake_State &state, const Policy &policy) const
virtual Handshake_Type wire_type () const
 ~Server_Key_Exchange () override

Detailed Description

Server Key Exchange Message

Definition at line 322 of file tls_messages_12.h.

Constructor & Destructor Documentation

◆ Server_Key_Exchange() [1/4]

Botan::TLS::Server_Key_Exchange::Server_Key_Exchange ( Handshake_IO & io,
Handshake_State & state,
const Policy & policy,
Credentials_Manager & creds,
RandomNumberGenerator & rng,
const Private_Key * signing_key = nullptr )

Create a new Server Key Exchange message

Definition at line 31 of file msg_server_kex.cpp.

36 {
37 const std::string hostname = state.client_hello()->sni_hostname();
38 const Kex_Algo kex_algo = state.ciphersuite().kex_method();
39
40 if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK) {
41 const std::string identity_hint = creds.psk_identity_hint("tls-server", hostname);
42
43 append_tls_length_value(m_params, identity_hint, 2);
44 }
45
46 if(kex_algo == Kex_Algo::DH) {
47 const std::vector<Group_Params> dh_groups = state.client_hello()->supported_dh_groups();
48
49 m_shared_group = Group_Params::NONE;
50
51 /*
52 RFC 7919 requires that if the client sends any groups in the FFDHE
53 range, that we must select one of these. If this is not possible,
54 then we are required to reject the connection.
55
56 If the client did not send any DH groups, but did offer DH ciphersuites
57 and we selected one, then consult the policy for which DH group to pick.
58 */
59
60 if(dh_groups.empty()) {
61 m_shared_group = policy.default_dh_group();
62 } else {
63 m_shared_group = policy.choose_key_exchange_group(dh_groups, {});
64 }
65
66 if(m_shared_group.value() == Group_Params::NONE) {
67 throw TLS_Exception(Alert::HandshakeFailure, "Could not agree on a DH group with the client");
68 }
69
70 // The policy had better return a group we know about:
71 BOTAN_ASSERT(m_shared_group.value().is_dh_named_group(), "DH ciphersuite is using a known finite field group");
72
73 // Note: TLS 1.2 allows defining and using arbitrary DH groups (additional
74 // to the named and standardized ones). This API doesn't allow the
75 // server to make use of that at the moment. TLS 1.3 does not
76 // provide this flexibility!
77 //
78 // A possible implementation strategy in case one would ever need that:
79 // `Policy::default_dh_group()` could return a `std::variant<Group_Params,
80 // DL_Group>`, allowing it to define arbitrary groups.
81 m_kex_key = state.callbacks().tls_generate_ephemeral_key(m_shared_group.value(), rng);
82 auto* dh = dynamic_cast<DH_PrivateKey*>(m_kex_key.get());
83 if(dh == nullptr) {
84 throw TLS_Exception(Alert::InternalError, "Application did not provide a Diffie-Hellman key");
85 }
86
87 append_tls_length_value(m_params, dh->get_int_field("p").serialize(), 2);
88 append_tls_length_value(m_params, dh->get_int_field("g").serialize(), 2);
89 append_tls_length_value(m_params, dh->public_value(), 2);
90 } else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK) {
91 const std::vector<Group_Params> ec_groups = state.client_hello()->supported_ecc_curves();
92
93 if(ec_groups.empty()) {
94 throw Internal_Error("Client sent no ECC extension but we negotiated ECDH");
95 }
96
97 m_shared_group = policy.choose_key_exchange_group(ec_groups, {});
98
99 if(m_shared_group.value() == Group_Params::NONE) {
100 throw TLS_Exception(Alert::HandshakeFailure, "No shared ECC group with client");
101 }
102
103 m_kex_key = [&] {
104 if(m_shared_group->is_ecdh_named_curve()) {
105 const auto pubkey_point_format = state.client_hello()->prefers_compressed_ec_points()
108 return state.callbacks().tls12_generate_ephemeral_ecdh_key(*m_shared_group, rng, pubkey_point_format);
109 } else {
110 return state.callbacks().tls_generate_ephemeral_key(*m_shared_group, rng);
111 }
112 }();
113
114 if(!m_kex_key) {
115 throw TLS_Exception(Alert::InternalError, "Application did not provide an EC key");
116 }
117
118 const uint16_t named_curve_id = m_shared_group.value().wire_code();
119 m_params.push_back(3); // named curve
120 m_params.push_back(get_byte<0>(named_curve_id));
121 m_params.push_back(get_byte<1>(named_curve_id));
122
123 // Note: In contrast to public_value(), raw_public_key_bits() takes the
124 // point format (compressed vs. uncompressed) into account that was set
125 // in its construction within tls_generate_ephemeral_key().
126 append_tls_length_value(m_params, m_kex_key->raw_public_key_bits(), 1);
127 } else if(kex_algo != Kex_Algo::PSK) {
128 throw Internal_Error("Server_Key_Exchange: Unknown kex type " + kex_method_to_string(kex_algo));
129 }
130
131 if(state.ciphersuite().signature_used()) {
132 BOTAN_ASSERT(signing_key, "Signing key was set");
133
134 const std::pair<std::string, Signature_Format> format =
135 state.choose_sig_format(*signing_key, m_scheme, false, policy);
136
137 std::vector<uint8_t> buf = state.client_hello()->random();
138
139 buf += state.server_hello()->random();
140 buf += params();
141
142 m_signature = state.callbacks().tls_sign_message(*signing_key, rng, format.first, format.second, buf);
143 }
144
145 state.hash().update(io.send(*this));
146}
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
const std::vector< uint8_t > & params() const
void append_tls_length_value(std::vector< uint8_t, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
Definition tls_reader.h:177
std::string kex_method_to_string(Kex_Algo method)
Definition tls_algos.cpp:27
constexpr uint8_t get_byte(T input)
Definition loadstor.h:79

References Botan::TLS::append_tls_length_value(), BOTAN_ASSERT, Botan::TLS::Handshake_State::callbacks(), Botan::TLS::Policy::choose_key_exchange_group(), Botan::TLS::Handshake_State::choose_sig_format(), Botan::TLS::Handshake_State::ciphersuite(), Botan::TLS::Handshake_State::client_hello(), Botan::Compressed, Botan::TLS::Policy::default_dh_group(), Botan::TLS::DH, Botan::TLS::ECDH, Botan::TLS::ECDHE_PSK, Botan::get_byte(), Botan::TLS::Handshake_State::hash(), Botan::TLS::Ciphersuite::kex_method(), Botan::TLS::kex_method_to_string(), params(), Botan::TLS::PSK, Botan::Credentials_Manager::psk_identity_hint(), Botan::TLS::Handshake_IO::send(), Botan::TLS::Handshake_State::server_hello(), Botan::TLS::Ciphersuite::signature_used(), Botan::TLS::Callbacks::tls12_generate_ephemeral_ecdh_key(), Botan::TLS::Callbacks::tls_generate_ephemeral_key(), Botan::TLS::Callbacks::tls_sign_message(), Botan::Uncompressed, Botan::TLS::Handshake_Hash::update(), and Botan::TLS::Group_Params::wire_code().

Referenced by operator=(), operator=(), Server_Key_Exchange(), and Server_Key_Exchange().

◆ Server_Key_Exchange() [2/4]

Botan::TLS::Server_Key_Exchange::Server_Key_Exchange ( const std::vector< uint8_t > & buf,
Kex_Algo kex_alg,
Auth_Method sig_alg,
Protocol_Version version )

Deserialize a Server Key Exchange message

Definition at line 151 of file msg_server_kex.cpp.

154 {
155 BOTAN_UNUSED(version); // remove this
156 TLS_Data_Reader reader("ServerKeyExchange", buf);
157
158 /*
159 * Here we are deserializing enough to find out what offset the
160 * signature is at. All processing is done when the Client Key Exchange
161 * is prepared.
162 */
163
164 if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK) {
165 reader.get_string(2, 0, 65535); // identity hint
166 }
167
168 if(kex_algo == Kex_Algo::DH) {
169 // 3 bigints, DH p, g, Y
170
171 for(size_t i = 0; i != 3; ++i) {
172 reader.get_range<uint8_t>(2, 1, 65535);
173 }
174 } else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK) {
175 reader.get_byte(); // curve type
176 reader.get_uint16_t(); // curve id
177 reader.get_range<uint8_t>(1, 1, 255); // public key
178 } else if(kex_algo != Kex_Algo::PSK) {
179 throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " + kex_method_to_string(kex_algo));
180 }
181
182 m_params.assign(buf.data(), buf.data() + reader.read_so_far());
183
184 if(auth_method != Auth_Method::IMPLICIT) {
185 m_scheme = Signature_Scheme(reader.get_uint16_t());
186 m_signature = reader.get_range<uint8_t>(2, 0, 65535);
187 }
188
189 reader.assert_done();
190}
#define BOTAN_UNUSED
Definition assert.h:144

References Botan::TLS::TLS_Data_Reader::assert_done(), BOTAN_UNUSED, Botan::TLS::DH, Botan::TLS::ECDH, Botan::TLS::ECDHE_PSK, Botan::TLS::TLS_Data_Reader::get_byte(), Botan::TLS::TLS_Data_Reader::get_range(), Botan::TLS::TLS_Data_Reader::get_string(), Botan::TLS::TLS_Data_Reader::get_uint16_t(), Botan::TLS::IMPLICIT, Botan::TLS::kex_method_to_string(), Botan::TLS::PSK, and Botan::TLS::TLS_Data_Reader::read_so_far().

◆ ~Server_Key_Exchange()

Botan::TLS::Server_Key_Exchange::~Server_Key_Exchange ( )
overridedefault

◆ Server_Key_Exchange() [3/4]

Botan::TLS::Server_Key_Exchange::Server_Key_Exchange ( const Server_Key_Exchange & other)
delete

References Server_Key_Exchange().

◆ Server_Key_Exchange() [4/4]

Botan::TLS::Server_Key_Exchange::Server_Key_Exchange ( Server_Key_Exchange && other)
delete

References Server_Key_Exchange().

Member Function Documentation

◆ operator=() [1/2]

Server_Key_Exchange & Botan::TLS::Server_Key_Exchange::operator= ( const Server_Key_Exchange & other)
delete

References Server_Key_Exchange().

◆ operator=() [2/2]

Server_Key_Exchange & Botan::TLS::Server_Key_Exchange::operator= ( Server_Key_Exchange && other)
delete

References Server_Key_Exchange().

◆ params()

const std::vector< uint8_t > & Botan::TLS::Server_Key_Exchange::params ( ) const
inline

Definition at line 326 of file tls_messages_12.h.

326{ return m_params; }

Referenced by Server_Key_Exchange(), and verify().

◆ server_kex_key()

const PK_Key_Agreement_Key & Botan::TLS::Server_Key_Exchange::server_kex_key ( ) const

Definition at line 237 of file msg_server_kex.cpp.

237 {
238 BOTAN_ASSERT_NONNULL(m_kex_key);
239 return *m_kex_key;
240}
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114

References BOTAN_ASSERT_NONNULL.

◆ shared_group()

const std::optional< Group_Params > & Botan::TLS::Server_Key_Exchange::shared_group ( ) const
inline
Returns
the agreed upon KEX group or std::nullopt if the KEX type does not depend on a group

Definition at line 337 of file tls_messages_12.h.

337{ return m_shared_group; }

◆ type()

Handshake_Type Botan::TLS::Server_Key_Exchange::type ( ) const
inlineoverridevirtual
Returns
the message type

Implements Botan::TLS::Handshake_Message.

Definition at line 324 of file tls_messages_12.h.

References Botan::TLS::ServerKeyExchange.

◆ type_string()

std::string Botan::TLS::Handshake_Message::type_string ( ) const
inherited
Returns
string representation of this message type

Definition at line 21 of file tls_handshake_state.cpp.

21 {
23}
virtual Handshake_Type type() const =0
const char * handshake_type_to_string(Handshake_Type type)
Definition tls_magic.cpp:15

References Botan::TLS::handshake_type_to_string(), and type().

◆ verify()

bool Botan::TLS::Server_Key_Exchange::verify ( const Public_Key & server_key,
const Handshake_State & state,
const Policy & policy ) const

Verify a Server Key Exchange message

Definition at line 213 of file msg_server_kex.cpp.

215 {
216 policy.check_peer_key_acceptable(server_key);
217
218 const std::pair<std::string, Signature_Format> format =
219 state.parse_sig_format(server_key, m_scheme, state.client_hello()->signature_schemes(), false, policy);
220
221 std::vector<uint8_t> buf = state.client_hello()->random();
222
223 buf += state.server_hello()->random();
224 buf += params();
225
226 const bool signature_valid =
227 state.callbacks().tls_verify_message(server_key, format.first, format.second, buf, m_signature);
228
229#if defined(BOTAN_UNSAFE_FUZZER_MODE)
230 BOTAN_UNUSED(signature_valid);
231 return true;
232#else
233 return signature_valid;
234#endif
235}

References BOTAN_UNUSED, Botan::TLS::Handshake_State::callbacks(), Botan::TLS::Policy::check_peer_key_acceptable(), Botan::TLS::Handshake_State::client_hello(), params(), Botan::TLS::Handshake_State::parse_sig_format(), Botan::TLS::Handshake_State::server_hello(), and Botan::TLS::Callbacks::tls_verify_message().

◆ wire_type()

virtual Handshake_Type Botan::TLS::Handshake_Message::wire_type ( ) const
inlinevirtualinherited
Returns
the wire representation of the message's type

Reimplemented in Botan::TLS::Hello_Retry_Request.

Definition at line 39 of file tls_handshake_msg.h.

39 {
40 // Usually equal to the Handshake_Type enum value,
41 // with the exception of TLS 1.3 Hello Retry Request.
42 return type();
43 }

References type().

Referenced by Botan::TLS::Stream_Handshake_IO::send().


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