Botan 3.0.0-alpha0
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
26namespace Botan::TLS {
27
28/*
29* Create a new Client Key Exchange message
30*/
32 Handshake_State& state,
33 const Policy& policy,
36 const std::string& hostname,
38 {
39 const Kex_Algo kex_algo = state.ciphersuite().kex_method();
40
41 if(kex_algo == Kex_Algo::PSK)
42 {
43 std::string identity_hint = "";
44
45 if(state.server_kex())
46 {
47 TLS_Data_Reader reader("ClientKeyExchange", state.server_kex()->params());
48 identity_hint = reader.get_string(2, 0, 65535);
49 }
50
51 const std::string psk_identity =
52 creds.psk_identity("tls-client", hostname, identity_hint);
53
54 append_tls_length_value(m_key_material, psk_identity, 2);
55
56 SymmetricKey psk = creds.psk("tls-client", hostname, psk_identity);
57
58 std::vector<uint8_t> zeros(psk.length());
59
60 append_tls_length_value(m_pre_master, zeros, 2);
61 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
62 }
63 else if(state.server_kex())
64 {
65 TLS_Data_Reader reader("ClientKeyExchange", state.server_kex()->params());
66
67 SymmetricKey psk;
68
69 if(kex_algo == Kex_Algo::ECDHE_PSK)
70 {
71 std::string identity_hint = reader.get_string(2, 0, 65535);
72
73 const std::string psk_identity =
74 creds.psk_identity("tls-client", hostname, identity_hint);
75
76 append_tls_length_value(m_key_material, psk_identity, 2);
77
78 psk = creds.psk("tls-client", hostname, psk_identity);
79 }
80
81 if(kex_algo == Kex_Algo::DH)
82 {
83 const std::vector<uint8_t> modulus = reader.get_range<uint8_t>(2, 1, 65535);
84 const std::vector<uint8_t> generator = reader.get_range<uint8_t>(2, 1, 65535);
85 const std::vector<uint8_t> peer_public_value = reader.get_range<uint8_t>(2, 1, 65535);
86
87 if(reader.remaining_bytes())
88 throw Decoding_Error("Bad params size for DH key exchange");
89
90 const std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> dh_result =
91 state.callbacks().tls_dh_agree(modulus, generator, peer_public_value, policy, rng);
92
93 if(kex_algo == Kex_Algo::DH)
94 m_pre_master = dh_result.first;
95 else
96 {
97 append_tls_length_value(m_pre_master, dh_result.first, 2);
98 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
99 }
100
101 append_tls_length_value(m_key_material, dh_result.second, 2);
102 }
103 else if(kex_algo == Kex_Algo::ECDH ||
104 kex_algo == Kex_Algo::ECDHE_PSK)
105 {
106 const uint8_t curve_type = reader.get_byte();
107 if(curve_type != 3)
108 throw Decoding_Error("Server sent non-named ECC curve");
109
110 const Group_Params curve_id = static_cast<Group_Params>(reader.get_uint16_t());
111 const std::vector<uint8_t> peer_public_value = reader.get_range<uint8_t>(1, 1, 255);
112
113 if(policy.choose_key_exchange_group({curve_id}) != curve_id)
114 {
116 "Server sent ECC curve prohibited by policy");
117 }
118
119 const std::string curve_name = state.callbacks().tls_decode_group_param(curve_id);
120
121 if(curve_name.empty())
122 throw Decoding_Error("Server sent unknown named curve " +
123 std::to_string(static_cast<uint16_t>(curve_id)));
124
125 const std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> ecdh_result =
126 state.callbacks().tls_ecdh_agree(curve_name, peer_public_value, policy, rng,
127 state.server_hello()->prefers_compressed_ec_points());
128
129 if(kex_algo == Kex_Algo::ECDH)
130 {
131 m_pre_master = ecdh_result.first;
132 }
133 else
134 {
135 append_tls_length_value(m_pre_master, ecdh_result.first, 2);
136 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
137 }
138
139 append_tls_length_value(m_key_material, ecdh_result.second, 1);
140 }
141#if defined(BOTAN_HAS_CECPQ1)
142 else if(kex_algo == Kex_Algo::CECPQ1)
143 {
144 const std::vector<uint8_t> cecpq1_offer = reader.get_range<uint8_t>(2, 1, 65535);
145
146 if(cecpq1_offer.size() != CECPQ1_OFFER_BYTES)
147 throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid CECPQ1 key size");
148
149 std::vector<uint8_t> newhope_accept(CECPQ1_ACCEPT_BYTES);
151 CECPQ1_accept(shared_secret.data(), newhope_accept.data(), cecpq1_offer.data(), rng);
152 append_tls_length_value(m_key_material, newhope_accept, 2);
153 m_pre_master = shared_secret;
154 }
155#endif
156 else
157 {
158 throw Internal_Error("Client_Key_Exchange: Unknown key exchange method was negotiated");
159 }
160
161 reader.assert_done();
162 }
163 else
164 {
165 // No server key exchange msg better mean RSA kex + RSA key in cert
166
167 if(kex_algo != Kex_Algo::STATIC_RSA)
168 throw Unexpected_Message("No server kex message, but negotiated a key exchange that required it");
169
171 throw Internal_Error("No server public key for RSA exchange");
172
173 if(auto rsa_pub = dynamic_cast<const RSA_PublicKey*>(server_public_key))
174 {
175 const Protocol_Version offered_version = state.client_hello()->legacy_version();
176
177 rng.random_vec(m_pre_master, 48);
178 m_pre_master[0] = offered_version.major_version();
179 m_pre_master[1] = offered_version.minor_version();
180
181 PK_Encryptor_EME encryptor(*rsa_pub, rng, "PKCS1v15");
182
183 const std::vector<uint8_t> encrypted_key = encryptor.encrypt(m_pre_master, rng);
184
185 append_tls_length_value(m_key_material, encrypted_key, 2);
186 }
187 else
188 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
189 "Expected a RSA key in server cert but got " +
190 server_public_key->algo_name());
191 }
192
193 state.hash().update(io.send(*this));
194 }
195
196/*
197* Read a Client Key Exchange message
198*/
199Client_Key_Exchange::Client_Key_Exchange(const std::vector<uint8_t>& contents,
200 const Handshake_State& state,
201 const Private_Key* server_rsa_kex_key,
202 Credentials_Manager& creds,
203 const Policy& policy,
205 {
206 const Kex_Algo kex_algo = state.ciphersuite().kex_method();
207
208 if(kex_algo == Kex_Algo::STATIC_RSA)
209 {
210 BOTAN_ASSERT(state.server_certs() && !state.server_certs()->cert_chain().empty(),
211 "RSA key exchange negotiated so server sent a certificate");
212
213 if(!server_rsa_kex_key)
214 throw Internal_Error("Expected RSA kex but no server kex key set");
215
216 if(server_rsa_kex_key->algo_name() != "RSA")
217 throw Internal_Error("Expected RSA key but got " + server_rsa_kex_key->algo_name());
218
219 TLS_Data_Reader reader("ClientKeyExchange", contents);
220 const std::vector<uint8_t> encrypted_pre_master = reader.get_range<uint8_t>(2, 0, 65535);
221 reader.assert_done();
222
223 PK_Decryptor_EME decryptor(*server_rsa_kex_key, rng, "PKCS1v15");
224
225 const uint8_t client_major = state.client_hello()->legacy_version().major_version();
226 const uint8_t client_minor = state.client_hello()->legacy_version().minor_version();
227
228 /*
229 * PK_Decryptor::decrypt_or_random will return a random value if
230 * either the length does not match the expected value or if the
231 * version number embedded in the PMS does not match the one sent
232 * in the client hello.
233 */
234 const size_t expected_plaintext_size = 48;
235 const size_t expected_content_size = 2;
236 const uint8_t expected_content_bytes[expected_content_size] = { client_major, client_minor };
237 const uint8_t expected_content_pos[expected_content_size] = { 0, 1 };
238
239 m_pre_master =
240 decryptor.decrypt_or_random(encrypted_pre_master.data(),
241 encrypted_pre_master.size(),
242 expected_plaintext_size,
243 rng,
244 expected_content_bytes,
245 expected_content_pos,
246 expected_content_size);
247 }
248 else
249 {
250 TLS_Data_Reader reader("ClientKeyExchange", contents);
251
252 SymmetricKey psk;
253
254 if(key_exchange_is_psk(kex_algo))
255 {
256 const std::string psk_identity = reader.get_string(2, 0, 65535);
257
258 psk = creds.psk("tls-server",
259 state.client_hello()->sni_hostname(),
260 psk_identity);
261
262 if(psk.length() == 0)
263 {
264 if(policy.hide_unknown_users())
265 psk = SymmetricKey(rng, 16);
266 else
267 throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
268 "No PSK for identifier " + psk_identity);
269 }
270 }
271
272 if(kex_algo == Kex_Algo::PSK)
273 {
274 std::vector<uint8_t> zeros(psk.length());
275 append_tls_length_value(m_pre_master, zeros, 2);
276 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
277 }
278#if defined(BOTAN_HAS_CECPQ1)
279 else if(kex_algo == Kex_Algo::CECPQ1)
280 {
281 const CECPQ1_key& cecpq1_offer = state.server_kex()->cecpq1_key();
282
283 const std::vector<uint8_t> cecpq1_accept = reader.get_range<uint8_t>(2, 0, 65535);
284 if(cecpq1_accept.size() != CECPQ1_ACCEPT_BYTES)
285 throw Decoding_Error("Invalid size for CECPQ1 accept message");
286
287 m_pre_master.resize(CECPQ1_SHARED_KEY_BYTES);
288 CECPQ1_finish(m_pre_master.data(), cecpq1_offer, cecpq1_accept.data());
289 }
290#endif
291 else if(kex_algo == Kex_Algo::DH ||
292 kex_algo == Kex_Algo::ECDH ||
293 kex_algo == Kex_Algo::ECDHE_PSK)
294 {
295 const Private_Key& private_key = state.server_kex()->server_kex_key();
296
297 const PK_Key_Agreement_Key* ka_key =
298 dynamic_cast<const PK_Key_Agreement_Key*>(&private_key);
299
300 if(!ka_key)
301 throw Internal_Error("Expected key agreement key type but got " +
302 private_key.algo_name());
303
304 std::vector<uint8_t> client_pubkey;
305
306 if(ka_key->algo_name() == "DH")
307 {
308 client_pubkey = reader.get_range<uint8_t>(2, 0, 65535);
309 }
310 else
311 {
312 client_pubkey = reader.get_range<uint8_t>(1, 1, 255);
313 }
314
315 try
316 {
317 PK_Key_Agreement ka(*ka_key, rng, "Raw");
318
319 secure_vector<uint8_t> shared_secret = ka.derive_key(0, client_pubkey).bits_of();
320
321 if(ka_key->algo_name() == "DH")
322 shared_secret = CT::strip_leading_zeros(shared_secret);
323
324 if(kex_algo == Kex_Algo::ECDHE_PSK)
325 {
326 append_tls_length_value(m_pre_master, shared_secret, 2);
327 append_tls_length_value(m_pre_master, psk.bits_of(), 2);
328 }
329 else
330 m_pre_master = shared_secret;
331 }
332 catch(Invalid_Argument& e)
333 {
334 throw TLS_Exception(Alert::ILLEGAL_PARAMETER, e.what());
335 }
336 catch(std::exception&)
337 {
338 /*
339 * Something failed in the DH/ECDH computation. To avoid possible
340 * attacks which are based on triggering and detecting some edge
341 * failure condition, randomize the pre-master output and carry on,
342 * allowing the protocol to fail later in the finished checks.
343 */
344 rng.random_vec(m_pre_master, ka_key->public_value().size());
345 }
346
347 reader.assert_done();
348 }
349 else
350 throw Internal_Error("Client_Key_Exchange: Unknown key exchange negotiated");
351 }
352 }
353
354}
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
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)
const char * what() const noexcept override
Definition: exceptn.h:94
secure_vector< uint8_t > bits_of() const
Definition: symkey.h:33
size_t length() const
Definition: symkey.h:27
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:207
virtual std::string algo_name() const =0
secure_vector< uint8_t > random_vec(size_t bytes)
Definition: rng.h:167
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_12 *server_certs)
void server_hello(Server_Hello_12 *server_hello)
void server_kex(Server_Key_Exchange *server_kex)
const Ciphersuite & ciphersuite() const
void client_hello(Client_Hello_12 *client_hello)
virtual bool hide_unknown_users() const
Definition: tls_policy.cpp:340
virtual Group_Params choose_key_exchange_group(const std::vector< Group_Params > &peer_groups) const
Definition: tls_policy.cpp:127
uint8_t major_version() const
Definition: tls_version.h:83
uint8_t minor_version() const
Definition: tls_version.h:88
std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes)
Definition: tls_reader.h:140
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:119
size_t remaining_bytes() const
Definition: tls_reader.h:38
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:209
secure_vector< uint8_t > strip_leading_zeros(const uint8_t in[], size_t length)
Definition: ct_utils.cpp:87
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
bool key_exchange_is_psk(Kex_Algo m)
Definition: tls_algos.h:121
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:143
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