Botan 3.0.0
Crypto and TLS for C&
msg_server_kex.cpp
Go to the documentation of this file.
1/*
2* Server Key Exchange Message
3* (C) 2004-2010,2012,2015,2016 Jack Lloyd
4* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/tls_messages.h>
10#include <botan/tls_extensions.h>
11#include <botan/internal/tls_reader.h>
12#include <botan/internal/tls_handshake_io.h>
13#include <botan/internal/tls_handshake_state.h>
14#include <botan/credentials_manager.h>
15#include <botan/internal/loadstor.h>
16#include <botan/pubkey.h>
17
18#include <botan/dl_group.h>
19#include <botan/dh.h>
20#include <botan/ecdh.h>
21
22#if defined(BOTAN_HAS_CURVE_25519)
23 #include <botan/curve25519.h>
24#endif
25
26namespace Botan::TLS {
27
28/**
29* Create a new Server Key Exchange message
30*/
32 Handshake_State& state,
33 const Policy& policy,
36 const Private_Key* signing_key)
37 {
38 const std::string hostname = state.client_hello()->sni_hostname();
39 const Kex_Algo kex_algo = state.ciphersuite().kex_method();
40
41 if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK)
42 {
43 std::string identity_hint =
44 creds.psk_identity_hint("tls-server", hostname);
45
46 append_tls_length_value(m_params, identity_hint, 2);
47 }
48
49 if(kex_algo == Kex_Algo::DH)
50 {
51 const std::vector<Group_Params> dh_groups = state.client_hello()->supported_dh_groups();
52
53 Group_Params shared_group = Group_Params::NONE;
54
55 /*
56 If the client does not send any DH groups in the supported groups
57 extension, but does offer DH ciphersuites, we select a group arbitrarily
58 */
59
60 if(dh_groups.empty())
61 {
62 shared_group = policy.default_dh_group();
63 }
64 else
65 {
66 shared_group = policy.choose_key_exchange_group(dh_groups, {});
67 }
68
69 if(shared_group == Group_Params::NONE)
70 throw TLS_Exception(Alert::HandshakeFailure,
71 "Could not agree on a DH group with the client");
72
73 BOTAN_ASSERT(group_param_is_dh(shared_group), "DH groups for the DH ciphersuites god");
74
75 m_kex_key = state.callbacks().tls_generate_ephemeral_key(shared_group, rng);
76 auto dh = dynamic_cast<DH_PrivateKey*>(m_kex_key.get());
77 if(!dh)
78 {
79 throw TLS_Exception(Alert::InternalError, "Application did not provide a Diffie-Hellman key");
80 }
81
82 append_tls_length_value(m_params, BigInt::encode(dh->get_int_field("p")), 2);
83 append_tls_length_value(m_params, BigInt::encode(dh->get_int_field("g")), 2);
84 append_tls_length_value(m_params, dh->public_value(), 2);
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::HandshakeFailure, "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 m_kex_key = state.callbacks().tls_generate_ephemeral_key(shared_group, rng);
103 if(!m_kex_key)
104 {
105 throw TLS_Exception(Alert::InternalError,
106 "Application did not provide a X25519 key");
107 }
108 ecdh_public_val = m_kex_key->public_value();
109 }
110 else
111 {
112 m_kex_key = state.callbacks().tls_generate_ephemeral_key(shared_group, rng);
113 auto ecdh = dynamic_cast<ECDH_PrivateKey*>(m_kex_key.get());
114 if(!ecdh)
115 {
116 throw TLS_Exception(Alert::InternalError, "Application did not provide a EC-Diffie-Hellman key");
117 }
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
125 const uint16_t named_curve_id = static_cast<uint16_t>(shared_group);
126 m_params.push_back(3); // named curve
127 m_params.push_back(get_byte<0>(named_curve_id));
128 m_params.push_back(get_byte<1>(named_curve_id));
129
130 append_tls_length_value(m_params, ecdh_public_val, 1);
131 }
132 else if(kex_algo != Kex_Algo::PSK)
133 {
134 throw Internal_Error("Server_Key_Exchange: Unknown kex type " +
135 kex_method_to_string(kex_algo));
136 }
137
138 if(state.ciphersuite().signature_used())
139 {
140 BOTAN_ASSERT(signing_key, "Signing key was set");
141
142 std::pair<std::string, Signature_Format> format =
143 state.choose_sig_format(*signing_key, m_scheme, false, policy);
144
145 std::vector<uint8_t> buf = state.client_hello()->random();
146
147 buf += state.server_hello()->random();
148 buf += params();
149
150 m_signature =
151 state.callbacks().tls_sign_message(*signing_key, rng,
152 format.first, format.second, buf);
153 }
154
155 state.hash().update(io.send(*this));
156 }
157
158/**
159* Deserialize a Server Key Exchange message
160*/
161Server_Key_Exchange::Server_Key_Exchange(const std::vector<uint8_t>& buf,
162 const Kex_Algo kex_algo,
163 const Auth_Method auth_method,
164 Protocol_Version version)
165 {
166 BOTAN_UNUSED(version); // remove this
167 TLS_Data_Reader reader("ServerKeyExchange", buf);
168
169 /*
170 * Here we are deserializing enough to find out what offset the
171 * signature is at. All processing is done when the Client Key Exchange
172 * is prepared.
173 */
174
175 if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK)
176 {
177 reader.get_string(2, 0, 65535); // identity hint
178 }
179
180 if(kex_algo == Kex_Algo::DH)
181 {
182 // 3 bigints, DH p, g, Y
183
184 for(size_t i = 0; i != 3; ++i)
185 {
186 reader.get_range<uint8_t>(2, 1, 65535);
187 }
188 }
189 else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK)
190 {
191 reader.get_byte(); // curve type
192 reader.get_uint16_t(); // curve id
193 reader.get_range<uint8_t>(1, 1, 255); // public key
194 }
195 else if(kex_algo != Kex_Algo::PSK)
196 throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " +
197 kex_method_to_string(kex_algo));
198
199 m_params.assign(buf.data(), buf.data() + reader.read_so_far());
200
201 if(auth_method != Auth_Method::IMPLICIT)
202 {
203 m_scheme = Signature_Scheme(reader.get_uint16_t());
204 m_signature = reader.get_range<uint8_t>(2, 0, 65535);
205 }
206
207 reader.assert_done();
208 }
209
210/**
211* Serialize a Server Key Exchange message
212*/
213std::vector<uint8_t> Server_Key_Exchange::serialize() const
214 {
215 std::vector<uint8_t> buf = params();
216
217 if(!m_signature.empty())
218 {
219 if(m_scheme.is_set())
220 {
221 buf.push_back(get_byte<0>(m_scheme.wire_code()));
222 buf.push_back(get_byte<1>(m_scheme.wire_code()));
223 }
224
225 append_tls_length_value(buf, m_signature, 2);
226 }
227
228 return buf;
229 }
230
231/**
232* Verify a Server Key Exchange message
233*/
235 const Handshake_State& state,
236 const Policy& policy) const
237 {
238 policy.check_peer_key_acceptable(server_key);
239
240 std::pair<std::string, Signature_Format> format =
241 state.parse_sig_format(server_key, m_scheme, state.client_hello()->signature_schemes(), false, policy);
242
243 std::vector<uint8_t> buf = state.client_hello()->random();
244
245 buf += state.server_hello()->random();
246 buf += params();
247
248 const bool signature_valid =
249 state.callbacks().tls_verify_message(server_key, format.first, format.second,
250 buf, m_signature);
251
252#if defined(BOTAN_UNSAFE_FUZZER_MODE)
253 BOTAN_UNUSED(signature_valid);
254 return true;
255#else
256 return signature_valid;
257#endif
258 }
259
261 {
262 BOTAN_ASSERT_NONNULL(m_kex_key);
263 return *m_kex_key;
264 }
265
266}
#define BOTAN_UNUSED(...)
Definition: assert.h:141
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:106
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
static std::vector< uint8_t > encode(const BigInt &n)
Definition: bigint.h:780
virtual std::string psk_identity_hint(const std::string &type, const std::string &context)
virtual std::vector< uint8_t > tls_sign_message(const Private_Key &key, RandomNumberGenerator &rng, std::string_view padding, Signature_Format format, const std::vector< uint8_t > &msg)
virtual std::unique_ptr< PK_Key_Agreement_Key > tls_generate_ephemeral_key(const std::variant< TLS::Group_Params, DL_Group > &group, RandomNumberGenerator &rng)
virtual bool tls_verify_message(const Public_Key &key, std::string_view padding, Signature_Format format, const std::vector< uint8_t > &msg, const std::vector< uint8_t > &sig)
Kex_Algo kex_method() const
void update(const uint8_t in[], size_t length)
virtual std::vector< uint8_t > send(const Handshake_Message &msg)=0
std::pair< std::string, Signature_Format > parse_sig_format(const Public_Key &key, Signature_Scheme scheme, const std::vector< Signature_Scheme > &offered_schemes, bool for_client_auth, const Policy &policy) const
void server_hello(Server_Hello_12 *server_hello)
const Ciphersuite & ciphersuite() const
void client_hello(Client_Hello_12 *client_hello)
std::pair< std::string, Signature_Format > choose_sig_format(const Private_Key &key, Signature_Scheme &scheme, bool for_client_auth, const Policy &policy) const
virtual void check_peer_key_acceptable(const Public_Key &public_key) const
Definition: tls_policy.cpp:245
virtual Group_Params default_dh_group() const
Definition: tls_policy.cpp:158
virtual Group_Params choose_key_exchange_group(const std::vector< Group_Params > &supported_by_peer, const std::vector< Group_Params > &offered_by_peer) const
Definition: tls_policy.cpp:131
bool verify(const Public_Key &server_key, const Handshake_State &state, const Policy &policy) const
const std::vector< uint8_t > & params() const
Definition: tls_messages.h:867
const Private_Key & server_kex_key() const
Server_Key_Exchange(Handshake_IO &io, Handshake_State &state, const Policy &policy, Credentials_Manager &creds, RandomNumberGenerator &rng, const Private_Key *signing_key=nullptr)
Signature_Scheme::Code wire_code() const noexcept
std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes)
Definition: tls_reader.h:142
size_t read_so_far() const
Definition: tls_reader.h:38
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:121
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:214
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