Botan 2.19.1
Crypto and TLS for C&
msg_client_kex.cpp
Go to the documentation of this file.
1/*
2* Client Key Exchange Message
3* (C) 2004-2010,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/rng.h>
12
13#include <botan/internal/tls_reader.h>
14#include <botan/internal/tls_handshake_io.h>
15#include <botan/internal/tls_handshake_state.h>
16#include <botan/internal/tls_handshake_hash.h>
17#include <botan/credentials_manager.h>
18#include <botan/internal/ct_utils.h>
19
20#include <botan/rsa.h>
21
22#if defined(BOTAN_HAS_CECPQ1)
23 #include <botan/cecpq1.h>
24#endif
25
26#if defined(BOTAN_HAS_SRP6)
27 #include <botan/srp6.h>
28#endif
29
30namespace Botan {
31
32namespace TLS {
33
34/*
35* Create a new Client Key Exchange message
36*/
38 Handshake_State& state,
39 const Policy& policy,
42 const std::string& hostname,
44 {
45 const Kex_Algo kex_algo = state.ciphersuite().kex_method();
46
47 if(kex_algo == Kex_Algo::PSK)
48 {
49 std::string identity_hint = "";
50
51 if(state.server_kex())
52 {
53 TLS_Data_Reader reader("ClientKeyExchange", state.server_kex()->params());
54 identity_hint = reader.get_string(2, 0, 65535);
55 }
56
57 const std::string psk_identity =
58 creds.psk_identity("tls-client", hostname, identity_hint);
59
60 append_tls_length_value(m_key_material, psk_identity, 2);
61
62 SymmetricKey psk = creds.psk("tls-client", hostname, psk_identity);
63
64 std::vector<uint8_t> zeros(psk.length());
65
66 append_tls_length_value(m_pre_master, zeros, 2);
67 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
68 }
69 else if(state.server_kex())
70 {
71 TLS_Data_Reader reader("ClientKeyExchange", state.server_kex()->params());
72
73 SymmetricKey psk;
74
75 if(kex_algo == Kex_Algo::DHE_PSK ||
76 kex_algo == Kex_Algo::ECDHE_PSK)
77 {
78 std::string identity_hint = reader.get_string(2, 0, 65535);
79
80 const std::string psk_identity =
81 creds.psk_identity("tls-client", hostname, identity_hint);
82
83 append_tls_length_value(m_key_material, psk_identity, 2);
84
85 psk = creds.psk("tls-client", hostname, psk_identity);
86 }
87
88 if(kex_algo == Kex_Algo::DH ||
89 kex_algo == Kex_Algo::DHE_PSK)
90 {
91 const std::vector<uint8_t> modulus = reader.get_range<uint8_t>(2, 1, 65535);
92 const std::vector<uint8_t> generator = reader.get_range<uint8_t>(2, 1, 65535);
93 const std::vector<uint8_t> peer_public_value = reader.get_range<uint8_t>(2, 1, 65535);
94
95 if(reader.remaining_bytes())
96 throw Decoding_Error("Bad params size for DH key exchange");
97
98 const std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> dh_result =
99 state.callbacks().tls_dh_agree(modulus, generator, peer_public_value, policy, rng);
100
101 if(kex_algo == Kex_Algo::DH)
102 m_pre_master = dh_result.first;
103 else
104 {
105 append_tls_length_value(m_pre_master, dh_result.first, 2);
106 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
107 }
108
109 append_tls_length_value(m_key_material, dh_result.second, 2);
110 }
111 else if(kex_algo == Kex_Algo::ECDH ||
112 kex_algo == Kex_Algo::ECDHE_PSK)
113 {
114 const uint8_t curve_type = reader.get_byte();
115 if(curve_type != 3)
116 throw Decoding_Error("Server sent non-named ECC curve");
117
118 const Group_Params curve_id = static_cast<Group_Params>(reader.get_uint16_t());
119 const std::vector<uint8_t> peer_public_value = reader.get_range<uint8_t>(1, 1, 255);
120
121 if(policy.choose_key_exchange_group({curve_id}) != curve_id)
122 {
124 "Server sent ECC curve prohibited by policy");
125 }
126
127 const std::string curve_name = state.callbacks().tls_decode_group_param(curve_id);
128
129 if(curve_name == "")
130 throw Decoding_Error("Server sent unknown named curve " +
131 std::to_string(static_cast<uint16_t>(curve_id)));
132
133 const std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> ecdh_result =
134 state.callbacks().tls_ecdh_agree(curve_name, peer_public_value, policy, rng,
135 state.server_hello()->prefers_compressed_ec_points());
136
137 if(kex_algo == Kex_Algo::ECDH)
138 {
139 m_pre_master = ecdh_result.first;
140 }
141 else
142 {
143 append_tls_length_value(m_pre_master, ecdh_result.first, 2);
144 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
145 }
146
147 append_tls_length_value(m_key_material, ecdh_result.second, 1);
148 }
149#if defined(BOTAN_HAS_SRP6)
150 else if(kex_algo == Kex_Algo::SRP_SHA)
151 {
152 const BigInt N = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535));
153 const BigInt g = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535));
154 std::vector<uint8_t> salt = reader.get_range<uint8_t>(1, 1, 255);
155 const BigInt B = BigInt::decode(reader.get_range<uint8_t>(2, 1, 65535));
156
157 const std::string srp_group = srp6_group_identifier(N, g);
158
159 const std::string srp_identifier =
160 creds.srp_identifier("tls-client", hostname);
161
162 const std::string srp_password =
163 creds.srp_password("tls-client", hostname, srp_identifier);
164
165 std::pair<BigInt, SymmetricKey> srp_vals =
166 srp6_client_agree(srp_identifier,
167 srp_password,
168 srp_group,
169 "SHA-1",
170 salt,
171 B,
172 rng);
173
174 append_tls_length_value(m_key_material, BigInt::encode(srp_vals.first), 2);
175 m_pre_master = srp_vals.second.bits_of();
176 }
177#endif
178
179#if defined(BOTAN_HAS_CECPQ1)
180 else if(kex_algo == Kex_Algo::CECPQ1)
181 {
182 const std::vector<uint8_t> cecpq1_offer = reader.get_range<uint8_t>(2, 1, 65535);
183
184 if(cecpq1_offer.size() != CECPQ1_OFFER_BYTES)
185 throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid CECPQ1 key size");
186
187 std::vector<uint8_t> newhope_accept(CECPQ1_ACCEPT_BYTES);
189 CECPQ1_accept(shared_secret.data(), newhope_accept.data(), cecpq1_offer.data(), rng);
190 append_tls_length_value(m_key_material, newhope_accept, 2);
191 m_pre_master = shared_secret;
192 }
193#endif
194 else
195 {
196 throw Internal_Error("Client_Key_Exchange: Unknown key exchange method was negotiated");
197 }
198
199 reader.assert_done();
200 }
201 else
202 {
203 // No server key exchange msg better mean RSA kex + RSA key in cert
204
205 if(kex_algo != Kex_Algo::STATIC_RSA)
206 throw Unexpected_Message("No server kex message, but negotiated a key exchange that required it");
207
209 throw Internal_Error("No server public key for RSA exchange");
210
211 if(auto rsa_pub = dynamic_cast<const RSA_PublicKey*>(server_public_key))
212 {
213 const Protocol_Version offered_version = state.client_hello()->version();
214
215 rng.random_vec(m_pre_master, 48);
216 m_pre_master[0] = offered_version.major_version();
217 m_pre_master[1] = offered_version.minor_version();
218
219 PK_Encryptor_EME encryptor(*rsa_pub, rng, "PKCS1v15");
220
221 const std::vector<uint8_t> encrypted_key = encryptor.encrypt(m_pre_master, rng);
222
223 append_tls_length_value(m_key_material, encrypted_key, 2);
224 }
225 else
226 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
227 "Expected a RSA key in server cert but got " +
228 server_public_key->algo_name());
229 }
230
231 state.hash().update(io.send(*this));
232 }
233
234/*
235* Read a Client Key Exchange message
236*/
237Client_Key_Exchange::Client_Key_Exchange(const std::vector<uint8_t>& contents,
238 const Handshake_State& state,
239 const Private_Key* server_rsa_kex_key,
240 Credentials_Manager& creds,
241 const Policy& policy,
243 {
244 const Kex_Algo kex_algo = state.ciphersuite().kex_method();
245
246 if(kex_algo == Kex_Algo::STATIC_RSA)
247 {
248 BOTAN_ASSERT(state.server_certs() && !state.server_certs()->cert_chain().empty(),
249 "RSA key exchange negotiated so server sent a certificate");
250
251 if(!server_rsa_kex_key)
252 throw Internal_Error("Expected RSA kex but no server kex key set");
253
254 if(!dynamic_cast<const RSA_PrivateKey*>(server_rsa_kex_key))
255 throw Internal_Error("Expected RSA key but got " + server_rsa_kex_key->algo_name());
256
257 TLS_Data_Reader reader("ClientKeyExchange", contents);
258 const std::vector<uint8_t> encrypted_pre_master = reader.get_range<uint8_t>(2, 0, 65535);
259 reader.assert_done();
260
261 PK_Decryptor_EME decryptor(*server_rsa_kex_key, rng, "PKCS1v15");
262
263 const uint8_t client_major = state.client_hello()->version().major_version();
264 const uint8_t client_minor = state.client_hello()->version().minor_version();
265
266 /*
267 * PK_Decryptor::decrypt_or_random will return a random value if
268 * either the length does not match the expected value or if the
269 * version number embedded in the PMS does not match the one sent
270 * in the client hello.
271 */
272 const size_t expected_plaintext_size = 48;
273 const size_t expected_content_size = 2;
274 const uint8_t expected_content_bytes[expected_content_size] = { client_major, client_minor };
275 const uint8_t expected_content_pos[expected_content_size] = { 0, 1 };
276
277 m_pre_master =
278 decryptor.decrypt_or_random(encrypted_pre_master.data(),
279 encrypted_pre_master.size(),
280 expected_plaintext_size,
281 rng,
282 expected_content_bytes,
283 expected_content_pos,
284 expected_content_size);
285 }
286 else
287 {
288 TLS_Data_Reader reader("ClientKeyExchange", contents);
289
290 SymmetricKey psk;
291
292 if(key_exchange_is_psk(kex_algo))
293 {
294 const std::string psk_identity = reader.get_string(2, 0, 65535);
295
296 psk = creds.psk("tls-server",
297 state.client_hello()->sni_hostname(),
298 psk_identity);
299
300 if(psk.length() == 0)
301 {
302 if(policy.hide_unknown_users())
303 psk = SymmetricKey(rng, 16);
304 else
305 throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
306 "No PSK for identifier " + psk_identity);
307 }
308 }
309
310 if(kex_algo == Kex_Algo::PSK)
311 {
312 std::vector<uint8_t> zeros(psk.length());
313 append_tls_length_value(m_pre_master, zeros, 2);
314 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
315 }
316#if defined(BOTAN_HAS_SRP6)
317 else if(kex_algo == Kex_Algo::SRP_SHA)
318 {
319 SRP6_Server_Session& srp = state.server_kex()->server_srp_params();
320
321 m_pre_master = srp.step2(BigInt::decode(reader.get_range<uint8_t>(2, 0, 65535))).bits_of();
322 }
323#endif
324#if defined(BOTAN_HAS_CECPQ1)
325 else if(kex_algo == Kex_Algo::CECPQ1)
326 {
327 const CECPQ1_key& cecpq1_offer = state.server_kex()->cecpq1_key();
328
329 const std::vector<uint8_t> cecpq1_accept = reader.get_range<uint8_t>(2, 0, 65535);
330 if(cecpq1_accept.size() != CECPQ1_ACCEPT_BYTES)
331 throw Decoding_Error("Invalid size for CECPQ1 accept message");
332
333 m_pre_master.resize(CECPQ1_SHARED_KEY_BYTES);
334 CECPQ1_finish(m_pre_master.data(), cecpq1_offer, cecpq1_accept.data());
335 }
336#endif
337 else if(kex_algo == Kex_Algo::DH ||
338 kex_algo == Kex_Algo::DHE_PSK ||
339 kex_algo == Kex_Algo::ECDH ||
340 kex_algo == Kex_Algo::ECDHE_PSK)
341 {
342 const Private_Key& private_key = state.server_kex()->server_kex_key();
343
344 const PK_Key_Agreement_Key* ka_key =
345 dynamic_cast<const PK_Key_Agreement_Key*>(&private_key);
346
347 if(!ka_key)
348 throw Internal_Error("Expected key agreement key type but got " +
349 private_key.algo_name());
350
351 std::vector<uint8_t> client_pubkey;
352
353 if(ka_key->algo_name() == "DH")
354 {
355 client_pubkey = reader.get_range<uint8_t>(2, 0, 65535);
356 }
357 else
358 {
359 client_pubkey = reader.get_range<uint8_t>(1, 1, 255);
360 }
361
362 try
363 {
364 PK_Key_Agreement ka(*ka_key, rng, "Raw");
365
366 secure_vector<uint8_t> shared_secret = ka.derive_key(0, client_pubkey).bits_of();
367
368 if(ka_key->algo_name() == "DH")
369 shared_secret = CT::strip_leading_zeros(shared_secret);
370
371 if(kex_algo == Kex_Algo::DHE_PSK ||
372 kex_algo == Kex_Algo::ECDHE_PSK)
373 {
374 append_tls_length_value(m_pre_master, shared_secret, 2);
375 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
376 }
377 else
378 m_pre_master = shared_secret;
379 }
380 catch(Invalid_Argument& e)
381 {
382 throw TLS_Exception(Alert::ILLEGAL_PARAMETER, e.what());
383 }
384 catch(std::exception&)
385 {
386 /*
387 * Something failed in the DH/ECDH computation. To avoid possible
388 * attacks which are based on triggering and detecting some edge
389 * failure condition, randomize the pre-master output and carry on,
390 * allowing the protocol to fail later in the finished checks.
391 */
392 rng.random_vec(m_pre_master, ka_key->public_value().size());
393 }
394
395 reader.assert_done();
396 }
397 else
398 throw Internal_Error("Client_Key_Exchange: Unknown key exchange negotiated");
399 }
400 }
401
402}
403
404}
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
static BigInt decode(const uint8_t buf[], size_t length)
Definition: bigint.h:805
static std::vector< uint8_t > encode(const BigInt &n)
Definition: bigint.h:770
virtual std::string srp_password(const std::string &type, const std::string &context, const std::string &identifier)
virtual std::string psk_identity(const std::string &type, const std::string &context, const std::string &identity_hint)
virtual SymmetricKey psk(const std::string &type, const std::string &context, const std::string &identity)
virtual std::string srp_identifier(const std::string &type, const std::string &context)
const char * what() const noexcept override
Definition: exceptn.h:96
secure_vector< uint8_t > bits_of() const
Definition: symkey.h:31
size_t length() const
Definition: symkey.h:25
secure_vector< uint8_t > decrypt_or_random(const uint8_t in[], size_t length, size_t expected_pt_len, RandomNumberGenerator &rng) const
Definition: pubkey.cpp:78
virtual std::vector< uint8_t > public_value() const =0
SymmetricKey derive_key(size_t key_len, const uint8_t in[], size_t in_len, const uint8_t params[], size_t params_len) const
Definition: pubkey.cpp:218
virtual std::string algo_name() const =0
secure_vector< uint8_t > random_vec(size_t bytes)
Definition: rng.h:143
SymmetricKey step2(const BigInt &A)
Definition: srp6.cpp:181
virtual std::string tls_decode_group_param(Group_Params group_param)
virtual std::pair< secure_vector< uint8_t >, std::vector< uint8_t > > tls_dh_agree(const std::vector< uint8_t > &modulus, const std::vector< uint8_t > &generator, const std::vector< uint8_t > &peer_public_value, const Policy &policy, RandomNumberGenerator &rng)
virtual std::pair< secure_vector< uint8_t >, std::vector< uint8_t > > tls_ecdh_agree(const std::string &curve_name, const std::vector< uint8_t > &peer_public_value, const Policy &policy, RandomNumberGenerator &rng, bool compressed)
Kex_Algo kex_method() const
Client_Key_Exchange(Handshake_IO &io, Handshake_State &state, const Policy &policy, Credentials_Manager &creds, const Public_Key *server_public_key, const std::string &hostname, RandomNumberGenerator &rng)
void server_certs(Certificate *server_certs)
void server_kex(Server_Key_Exchange *server_kex)
void client_hello(Client_Hello *client_hello)
const Ciphersuite & ciphersuite() const
void server_hello(Server_Hello *server_hello)
virtual bool hide_unknown_users() const
Definition: tls_policy.cpp:341
virtual Group_Params choose_key_exchange_group(const std::vector< Group_Params > &peer_groups) const
Definition: tls_policy.cpp:132
uint8_t major_version() const
Definition: tls_version.h:79
uint8_t minor_version() const
Definition: tls_version.h:84
std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes)
Definition: tls_reader.h:115
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:94
size_t remaining_bytes() const
Definition: tls_reader.h:38
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
secure_vector< uint8_t > strip_leading_zeros(const uint8_t in[], size_t length)
Definition: ct_utils.cpp:66
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
bool key_exchange_is_psk(Kex_Algo m)
Definition: tls_algos.h:160
Definition: alg_id.cpp:13
std::pair< BigInt, SymmetricKey > srp6_client_agree(const std::string &identifier, const std::string &password, const std::string &group_id, const std::string &hash_id, const std::vector< uint8_t > &salt, const BigInt &B, RandomNumberGenerator &rng)
Definition: srp6.cpp:77
void CECPQ1_finish(uint8_t shared_key[CECPQ1_SHARED_KEY_BYTES], const CECPQ1_key &offer_key, const uint8_t received[CECPQ1_ACCEPT_BYTES])
Definition: cecpq1.cpp:41
@ CECPQ1_ACCEPT_BYTES
Definition: newhope.h:48
@ CECPQ1_SHARED_KEY_BYTES
Definition: newhope.h:49
@ CECPQ1_OFFER_BYTES
Definition: newhope.h:47
OctetString SymmetricKey
Definition: symkey.h:141
std::string srp6_group_identifier(const BigInt &N, const BigInt &g)
Definition: srp6.cpp:53
void CECPQ1_accept(uint8_t shared_key[CECPQ1_SHARED_KEY_BYTES], uint8_t send[CECPQ1_ACCEPT_BYTES], const uint8_t received[CECPQ1_OFFER_BYTES], RandomNumberGenerator &rng)
Definition: cecpq1.cpp:26
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
std::unique_ptr< Public_Key > server_public_key
Definition: tls_client.cpp:53