Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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