Botan  2.4.0
Crypto and TLS for C++11
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/loadstor.h>
16 #include <botan/pubkey.h>
17 
18 #include <botan/dh.h>
19 #include <botan/ecdh.h>
20 
21 #if defined(BOTAN_HAS_CURVE_25519)
22  #include <botan/curve25519.h>
23 #endif
24 
25 #if defined(BOTAN_HAS_CECPQ1)
26  #include <botan/cecpq1.h>
27 #endif
28 
29 #if defined(BOTAN_HAS_SRP6)
30  #include <botan/srp6.h>
31 #endif
32 
33 namespace Botan {
34 
35 namespace TLS {
36 
37 /**
38 * Create a new Server Key Exchange message
39 */
41  Handshake_State& state,
42  const Policy& policy,
43  Credentials_Manager& creds,
45  const Private_Key* signing_key)
46  {
47  const std::string hostname = state.client_hello()->sni_hostname();
48  const std::string kex_algo = state.ciphersuite().kex_algo();
49 
50  if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
51  {
52  std::string identity_hint =
53  creds.psk_identity_hint("tls-server", hostname);
54 
55  append_tls_length_value(m_params, identity_hint, 2);
56  }
57 
58  if(kex_algo == "DH" || kex_algo == "DHE_PSK")
59  {
60  const std::vector<std::string>& dh_groups =
61  state.client_hello()->supported_dh_groups();
62 
63  std::string group_name;
64 
65  // if the client does not send any DH groups in
66  // the supported groups extension, but does offer DH ciphersuites,
67  // we select a group arbitrarily
68  if (dh_groups.empty())
69  {
70  group_name = policy.dh_group();
71  }
72  else
73  {
74  group_name = policy.choose_dh_group(dh_groups);
75  }
76 
77  if (group_name.empty())
79  "Could not agree on a DH group with the client");
80 
81  std::unique_ptr<DH_PrivateKey> dh(new DH_PrivateKey(rng, DL_Group(group_name)));
82 
83  append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_p()), 2);
84  append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_g()), 2);
85  append_tls_length_value(m_params, dh->public_value(), 2);
86  m_kex_key.reset(dh.release());
87  }
88  else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
89  {
90  const std::vector<std::string>& curves =
91  state.client_hello()->supported_ecc_curves();
92 
93  if(curves.empty())
94  throw Internal_Error("Client sent no ECC extension but we negotiated ECDH");
95 
96  const std::string curve_name = policy.choose_curve(curves);
97 
98  if(curve_name == "")
100  "Could not agree on an ECC curve with the client");
101 
102  const uint16_t named_curve_id = Supported_Elliptic_Curves::name_to_curve_id(curve_name);
103  if(named_curve_id == 0)
104  throw Internal_Error("TLS does not support ECC with " + curve_name);
105 
106  std::vector<uint8_t> ecdh_public_val;
107 
108  if(curve_name == "x25519")
109  {
110 #if defined(BOTAN_HAS_CURVE_25519)
111  std::unique_ptr<Curve25519_PrivateKey> x25519(new Curve25519_PrivateKey(rng));
112  ecdh_public_val = x25519->public_value();
113  m_kex_key.reset(x25519.release());
114 #else
115  throw Internal_Error("Negotiated X25519 somehow, but it is disabled");
116 #endif
117  }
118  else
119  {
120  EC_Group ec_group(curve_name);
121  std::unique_ptr<ECDH_PrivateKey> ecdh(new ECDH_PrivateKey(rng, ec_group));
122 
123  // follow client's preference for point compression
124  ecdh_public_val = ecdh->public_value(
125  state.client_hello()->prefers_compressed_ec_points() ?
127 
128  m_kex_key.reset(ecdh.release());
129  }
130 
131  m_params.push_back(3); // named curve
132  m_params.push_back(get_byte(0, named_curve_id));
133  m_params.push_back(get_byte(1, named_curve_id));
134 
135  append_tls_length_value(m_params, ecdh_public_val, 1);
136  }
137 #if defined(BOTAN_HAS_SRP6)
138  else if(kex_algo == "SRP_SHA")
139  {
140  const std::string srp_identifier = state.client_hello()->srp_identifier();
141 
142  std::string group_id;
143  BigInt v;
144  std::vector<uint8_t> salt;
145 
146  const bool found = creds.srp_verifier("tls-server", hostname,
147  srp_identifier,
148  group_id, v, salt,
149  policy.hide_unknown_users());
150 
151  if(!found)
153  "Unknown SRP user " + srp_identifier);
154 
155  m_srp_params.reset(new SRP6_Server_Session);
156 
157  BigInt B = m_srp_params->step1(v, group_id,
158  "SHA-1", rng);
159 
160  DL_Group group(group_id);
161 
162  append_tls_length_value(m_params, BigInt::encode(group.get_p()), 2);
163  append_tls_length_value(m_params, BigInt::encode(group.get_g()), 2);
164  append_tls_length_value(m_params, salt, 1);
165  append_tls_length_value(m_params, BigInt::encode(B), 2);
166  }
167 #endif
168 #if defined(BOTAN_HAS_CECPQ1)
169  else if(kex_algo == "CECPQ1")
170  {
171  std::vector<uint8_t> cecpq1_offer(CECPQ1_OFFER_BYTES);
172  m_cecpq1_key.reset(new CECPQ1_key);
173  CECPQ1_offer(cecpq1_offer.data(), m_cecpq1_key.get(), rng);
174  append_tls_length_value(m_params, cecpq1_offer, 2);
175  }
176 #endif
177  else if(kex_algo != "PSK")
178  {
179  throw Internal_Error("Server_Key_Exchange: Unknown kex type " + kex_algo);
180  }
181 
182  if(state.ciphersuite().sig_algo() != "")
183  {
184  BOTAN_ASSERT(signing_key, "Signing key was set");
185 
186  std::pair<std::string, Signature_Format> format =
187  state.choose_sig_format(*signing_key, m_hash_algo, m_sig_algo, false, policy);
188 
189  std::vector<uint8_t> buf = state.client_hello()->random();
190 
191  buf += state.server_hello()->random();
192  buf += params();
193 
194  m_signature =
195  state.callbacks().tls_sign_message(*signing_key, rng,
196  format.first, format.second, buf);
197  }
198 
199  state.hash().update(io.send(*this));
200  }
201 
202 /**
203 * Deserialize a Server Key Exchange message
204 */
205 Server_Key_Exchange::Server_Key_Exchange(const std::vector<uint8_t>& buf,
206  const std::string& kex_algo,
207  const std::string& sig_algo,
208  Protocol_Version version)
209  {
210  TLS_Data_Reader reader("ServerKeyExchange", buf);
211 
212  /*
213  * Here we are deserializing enough to find out what offset the
214  * signature is at. All processing is done when the Client Key Exchange
215  * is prepared.
216  */
217 
218  if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
219  {
220  reader.get_string(2, 0, 65535); // identity hint
221  }
222 
223  if(kex_algo == "DH" || kex_algo == "DHE_PSK")
224  {
225  // 3 bigints, DH p, g, Y
226 
227  for(size_t i = 0; i != 3; ++i)
228  {
229  reader.get_range<uint8_t>(2, 1, 65535);
230  }
231  }
232  else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
233  {
234  reader.get_byte(); // curve type
235  reader.get_uint16_t(); // curve id
236  reader.get_range<uint8_t>(1, 1, 255); // public key
237  }
238  else if(kex_algo == "SRP_SHA")
239  {
240  // 2 bigints (N,g) then salt, then server B
241 
242  reader.get_range<uint8_t>(2, 1, 65535);
243  reader.get_range<uint8_t>(2, 1, 65535);
244  reader.get_range<uint8_t>(1, 1, 255);
245  reader.get_range<uint8_t>(2, 1, 65535);
246  }
247  else if(kex_algo == "CECPQ1")
248  {
249  // u16 blob
250  reader.get_range<uint8_t>(2, 1, 65535);
251  }
252  else if(kex_algo != "PSK")
253  throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " + kex_algo);
254 
255  m_params.assign(buf.data(), buf.data() + reader.read_so_far());
256 
257  if(sig_algo != "")
258  {
260  {
261  m_hash_algo = Signature_Algorithms::hash_algo_name(reader.get_byte());
262  m_sig_algo = Signature_Algorithms::sig_algo_name(reader.get_byte());
263  }
264 
265  m_signature = reader.get_range<uint8_t>(2, 0, 65535);
266  }
267 
268  reader.assert_done();
269  }
270 
271 /**
272 * Serialize a Server Key Exchange message
273 */
274 std::vector<uint8_t> Server_Key_Exchange::serialize() const
275  {
276  std::vector<uint8_t> buf = params();
277 
278  if(m_signature.size())
279  {
280  // This should be an explicit version check
281  if(m_hash_algo != "" && m_sig_algo != "")
282  {
283  buf.push_back(Signature_Algorithms::hash_algo_code(m_hash_algo));
284  buf.push_back(Signature_Algorithms::sig_algo_code(m_sig_algo));
285  }
286 
287  append_tls_length_value(buf, m_signature, 2);
288  }
289 
290  return buf;
291  }
292 
293 /**
294 * Verify a Server Key Exchange message
295 */
297  const Handshake_State& state,
298  const Policy& policy) const
299  {
300  policy.check_peer_key_acceptable(server_key);
301 
302  std::pair<std::string, Signature_Format> format =
303  state.parse_sig_format(server_key, m_hash_algo, m_sig_algo,
304  false, policy);
305 
306  std::vector<uint8_t> buf = state.client_hello()->random();
307 
308  buf += state.server_hello()->random();
309  buf += params();
310 
311  const bool signature_valid =
312  state.callbacks().tls_verify_message(server_key, format.first, format.second,
313  buf, m_signature);
314 
315 #if defined(BOTAN_UNSAFE_FUZZER_MODE)
316  return true;
317 #else
318  return signature_valid;
319 #endif
320  }
321 
323  {
324  BOTAN_ASSERT_NONNULL(m_kex_key);
325  return *m_kex_key;
326  }
327 
328 }
329 
330 }
Server_Key_Exchange(Handshake_IO &io, Handshake_State &state, const Policy &policy, Credentials_Manager &creds, RandomNumberGenerator &rng, const Private_Key *signing_key=nullptr)
virtual std::vector< uint8_t > send(const Handshake_Message &msg)=0
static uint8_t sig_algo_code(const std::string &name)
void server_hello(Server_Hello *server_hello)
const std::vector< uint8_t > & params() const
Definition: tls_messages.h:515
size_t read_so_far() const
Definition: tls_reader.h:36
virtual bool tls_verify_message(const Public_Key &key, const std::string &emsa, Signature_Format format, const std::vector< uint8_t > &msg, const std::vector< uint8_t > &sig)
std::pair< std::string, Signature_Format > parse_sig_format(const Public_Key &key, const std::string &hash_algo, const std::string &sig_algo, bool for_client_auth, const Policy &policy) const
std::string kex_algo() const
virtual void check_peer_key_acceptable(const Public_Key &public_key) const
Definition: tls_policy.cpp:236
virtual std::string psk_identity_hint(const std::string &type, const std::string &context)
const BigInt & get_g() const
Definition: dl_group.cpp:203
virtual std::string dh_group() const
Definition: tls_policy.cpp:166
std::pair< std::string, Signature_Format > choose_sig_format(const Private_Key &key, std::string &hash_algo, std::string &sig_algo, bool for_client_auth, const Policy &policy) const
bool supports_negotiable_signature_algorithms() const
Definition: tls_version.cpp:60
const Ciphersuite & ciphersuite() const
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:29
static uint8_t hash_algo_code(const std::string &name)
virtual std::string choose_dh_group(const std::vector< std::string > &dh_group_names) const
Definition: tls_policy.cpp:154
std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes)
Definition: tls_reader.h:115
const BigInt & get_p() const
Definition: dl_group.cpp:194
virtual std::vector< uint8_t > tls_sign_message(const Private_Key &key, RandomNumberGenerator &rng, const std::string &emsa, Signature_Format format, const std::vector< uint8_t > &msg)
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:81
void client_hello(Client_Hello *client_hello)
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:94
void update(const uint8_t in[], size_t length)
virtual bool srp_verifier(const std::string &type, const std::string &context, const std::string &identifier, std::string &group_name, BigInt &verifier, std::vector< uint8_t > &salt, bool generate_fake_on_unknown)
Definition: alg_id.cpp:13
const Private_Key & server_kex_key() const
static std::string sig_algo_name(uint8_t code)
bool verify(const Public_Key &server_key, const Handshake_State &state, const Policy &policy) const
std::string sig_algo() const
void CECPQ1_offer(uint8_t send[CECPQ1_OFFER_BYTES], CECPQ1_key *offer_key_output, RandomNumberGenerator &rng)
Definition: cecpq1.cpp:15
uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:39
virtual bool hide_unknown_users() const
Definition: tls_policy.cpp:342
virtual std::string choose_curve(const std::vector< std::string > &curve_names) const
Definition: tls_policy.cpp:139
static std::vector< uint8_t > encode(const BigInt &n, Base base=Binary)
Definition: big_code.cpp:54
static uint16_t name_to_curve_id(const std::string &name)
static std::string hash_algo_name(uint8_t code)
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:185