Botan 3.0.0-alpha0
Crypto and TLS for C&
Public Member Functions | List of all members
Botan::TLS::Server_Key_Exchange Class Referencefinal

#include <tls_messages.h>

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

Public Member Functions

const std::vector< uint8_t > & params () const
 
const Private_Keyserver_kex_key () const
 
 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)
 
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
 

Detailed Description

Server Key Exchange Message

Definition at line 780 of file tls_messages.h.

Constructor & Destructor Documentation

◆ Server_Key_Exchange() [1/2]

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 34 of file msg_server_kex.cpp.

40 {
41 const std::string hostname = state.client_hello()->sni_hostname();
42 const Kex_Algo kex_algo = state.ciphersuite().kex_method();
43
44 if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK)
45 {
46 std::string identity_hint =
47 creds.psk_identity_hint("tls-server", hostname);
48
49 append_tls_length_value(m_params, identity_hint, 2);
50 }
51
52 if(kex_algo == Kex_Algo::DH)
53 {
54 const std::vector<Group_Params> dh_groups = state.client_hello()->supported_dh_groups();
55
56 Group_Params shared_group = Group_Params::NONE;
57
58 /*
59 If the client does not send any DH groups in the supported groups
60 extension, but does offer DH ciphersuites, we select a group arbitrarily
61 */
62
63 if(dh_groups.empty())
64 {
65 shared_group = policy.default_dh_group();
66 }
67 else
68 {
69 shared_group = policy.choose_key_exchange_group(dh_groups);
70 }
71
72 if(shared_group == Group_Params::NONE)
73 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
74 "Could not agree on a DH group with the client");
75
76 BOTAN_ASSERT(group_param_is_dh(shared_group), "DH groups for the DH ciphersuites god");
77
78 const std::string group_name = state.callbacks().tls_decode_group_param(shared_group);
79 auto dh = std::make_unique<DH_PrivateKey>(rng, DL_Group(group_name));
80
81 append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_p()), 2);
82 append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_g()), 2);
83 append_tls_length_value(m_params, dh->public_value(), 2);
84 m_kex_key.reset(dh.release());
85 }
86 else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK)
87 {
88 const std::vector<Group_Params> ec_groups = state.client_hello()->supported_ecc_curves();
89
90 if(ec_groups.empty())
91 throw Internal_Error("Client sent no ECC extension but we negotiated ECDH");
92
93 Group_Params shared_group = policy.choose_key_exchange_group(ec_groups);
94
95 if(shared_group == Group_Params::NONE)
96 throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "No shared ECC group with client");
97
98 std::vector<uint8_t> ecdh_public_val;
99
100 if(shared_group == Group_Params::X25519)
101 {
102#if defined(BOTAN_HAS_CURVE_25519)
103 auto x25519 = std::make_unique<X25519_PrivateKey>(rng);
104 ecdh_public_val = x25519->public_value();
105 m_kex_key.reset(x25519.release());
106#else
107 throw Internal_Error("Negotiated X25519 somehow, but it is disabled");
108#endif
109 }
110 else
111 {
112 Group_Params curve = policy.choose_key_exchange_group(ec_groups);
113
114 const std::string curve_name = state.callbacks().tls_decode_group_param(curve);
115
116 EC_Group ec_group(curve_name);
117 auto ecdh = std::make_unique<ECDH_PrivateKey>(rng, ec_group);
118
119 // follow client's preference for point compression
120 ecdh_public_val = ecdh->public_value(
121 state.client_hello()->prefers_compressed_ec_points() ?
123
124 m_kex_key.reset(ecdh.release());
125 }
126
127 const uint16_t named_curve_id = static_cast<uint16_t>(shared_group);
128 m_params.push_back(3); // named curve
129 m_params.push_back(get_byte<0>(named_curve_id));
130 m_params.push_back(get_byte<1>(named_curve_id));
131
132 append_tls_length_value(m_params, ecdh_public_val, 1);
133 }
134#if defined(BOTAN_HAS_CECPQ1)
135 else if(kex_algo == Kex_Algo::CECPQ1)
136 {
137 std::vector<uint8_t> cecpq1_offer(CECPQ1_OFFER_BYTES);
138 m_cecpq1_key.reset(new CECPQ1_key);
139 CECPQ1_offer(cecpq1_offer.data(), m_cecpq1_key.get(), rng);
140 append_tls_length_value(m_params, cecpq1_offer, 2);
141 }
142#endif
143 else if(kex_algo != Kex_Algo::PSK)
144 {
145 throw Internal_Error("Server_Key_Exchange: Unknown kex type " +
146 kex_method_to_string(kex_algo));
147 }
148
149 if(state.ciphersuite().signature_used())
150 {
151 BOTAN_ASSERT(signing_key, "Signing key was set");
152
153 std::pair<std::string, Signature_Format> format =
154 state.choose_sig_format(*signing_key, m_scheme, false, policy);
155
156 std::vector<uint8_t> buf = state.client_hello()->random();
157
158 buf += state.server_hello()->random();
159 buf += params();
160
161 m_signature =
162 state.callbacks().tls_sign_message(*signing_key, rng,
163 format.first, format.second, buf);
164 }
165
166 state.hash().update(io.send(*this));
167 }
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
static std::vector< uint8_t > encode(const BigInt &n)
Definition: bigint.h:765
const std::vector< uint8_t > & params() const
Definition: tls_messages.h:785
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:212
std::string kex_method_to_string(Kex_Algo method)
Definition: tls_algos.cpp:29
bool group_param_is_dh(Group_Params group)
Definition: tls_algos.cpp:109
void CECPQ1_offer(uint8_t send[CECPQ1_OFFER_BYTES], CECPQ1_key *offer_key_output, RandomNumberGenerator &rng)
Definition: cecpq1.cpp:15
@ CECPQ1_OFFER_BYTES
Definition: newhope.h:47

References Botan::TLS::append_tls_length_value(), BOTAN_ASSERT, Botan::TLS::Handshake_State::callbacks(), Botan::TLS::CECPQ1, Botan::CECPQ1_offer(), Botan::CECPQ1_OFFER_BYTES, 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::PointGFp::COMPRESSED, Botan::TLS::Policy::default_dh_group(), Botan::TLS::DH, Botan::TLS::ECDH, Botan::TLS::ECDHE_PSK, Botan::BigInt::encode(), Botan::TLS::group_param_is_dh(), Botan::TLS::Alert::HANDSHAKE_FAILURE, Botan::TLS::Handshake_State::hash(), Botan::TLS::Ciphersuite::kex_method(), Botan::TLS::kex_method_to_string(), Botan::TLS::NONE, 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::tls_decode_group_param(), Botan::TLS::Callbacks::tls_sign_message(), Botan::PointGFp::UNCOMPRESSED, Botan::TLS::Handshake_Hash::update(), and Botan::TLS::X25519.

◆ Server_Key_Exchange() [2/2]

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 172 of file msg_server_kex.cpp.

176 {
177 BOTAN_UNUSED(version); // remove this
178 TLS_Data_Reader reader("ServerKeyExchange", buf);
179
180 /*
181 * Here we are deserializing enough to find out what offset the
182 * signature is at. All processing is done when the Client Key Exchange
183 * is prepared.
184 */
185
186 if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK)
187 {
188 reader.get_string(2, 0, 65535); // identity hint
189 }
190
191 if(kex_algo == Kex_Algo::DH)
192 {
193 // 3 bigints, DH p, g, Y
194
195 for(size_t i = 0; i != 3; ++i)
196 {
197 reader.get_range<uint8_t>(2, 1, 65535);
198 }
199 }
200 else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK)
201 {
202 reader.get_byte(); // curve type
203 reader.get_uint16_t(); // curve id
204 reader.get_range<uint8_t>(1, 1, 255); // public key
205 }
206 else if(kex_algo == Kex_Algo::CECPQ1)
207 {
208 // u16 blob
209 reader.get_range<uint8_t>(2, 1, 65535);
210 }
211 else if(kex_algo != Kex_Algo::PSK)
212 throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " +
213 kex_method_to_string(kex_algo));
214
215 m_params.assign(buf.data(), buf.data() + reader.read_so_far());
216
217 if(auth_method != Auth_Method::IMPLICIT)
218 {
219 m_scheme = Signature_Scheme(reader.get_uint16_t());
220 m_signature = reader.get_range<uint8_t>(2, 0, 65535);
221 }
222
223 reader.assert_done();
224 }
#define BOTAN_UNUSED(...)
Definition: assert.h:141

References Botan::TLS::TLS_Data_Reader::assert_done(), BOTAN_UNUSED, Botan::TLS::CECPQ1, 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().

Member Function Documentation

◆ params()

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

Definition at line 785 of file tls_messages.h.

785{ return m_params; }

Referenced by Server_Key_Exchange(), and verify().

◆ server_kex_key()

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

Definition at line 276 of file msg_server_kex.cpp.

277 {
278 BOTAN_ASSERT_NONNULL(m_kex_key);
279 return *m_kex_key;
280 }
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:106

References BOTAN_ASSERT_NONNULL.

◆ type()

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

Implements Botan::TLS::Handshake_Message.

Definition at line 783 of file tls_messages.h.

783{ return SERVER_KEX; }
@ SERVER_KEX
Definition: tls_magic.h:74

References Botan::TLS::SERVER_KEX.

◆ type_string()

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

Definition at line 18 of file tls_handshake_state.cpp.

19 {
21 }
virtual Handshake_Type type() const =0
const char * handshake_type_to_string(Handshake_Type type)

References Botan::TLS::handshake_type_to_string(), and Botan::TLS::Handshake_Message::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 250 of file msg_server_kex.cpp.

253 {
254 policy.check_peer_key_acceptable(server_key);
255
256 std::pair<std::string, Signature_Format> format =
257 state.parse_sig_format(server_key, m_scheme, state.client_hello()->signature_schemes(), false, policy);
258
259 std::vector<uint8_t> buf = state.client_hello()->random();
260
261 buf += state.server_hello()->random();
262 buf += params();
263
264 const bool signature_valid =
265 state.callbacks().tls_verify_message(server_key, format.first, format.second,
266 buf, m_signature);
267
268#if defined(BOTAN_UNSAFE_FUZZER_MODE)
269 BOTAN_UNUSED(signature_valid);
270 return true;
271#else
272 return signature_valid;
273#endif
274 }

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

Definition at line 42 of file tls_handshake_msg.h.

43 {
44 // Usually equal to the Handshake_Type enum value,
45 // with the exception of TLS 1.3 Hello Retry Request.
46 return type();
47 }

References type.

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


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