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>
19 #include <botan/ecdh.h>
21 #if defined(BOTAN_HAS_CURVE_25519)
22 #include <botan/curve25519.h>
25 #if defined(BOTAN_HAS_CECPQ1)
26 #include <botan/cecpq1.h>
29 #if defined(BOTAN_HAS_SRP6)
30 #include <botan/srp6.h>
47 const std::string hostname = state.
client_hello()->sni_hostname();
50 if(kex_algo ==
"PSK" || kex_algo ==
"DHE_PSK" || kex_algo ==
"ECDHE_PSK")
52 std::string identity_hint =
58 if(kex_algo ==
"DH" || kex_algo ==
"DHE_PSK")
65 m_kex_key.reset(dh.release());
67 else if(kex_algo ==
"ECDH" || kex_algo ==
"ECDHE_PSK")
69 const std::vector<std::string>& curves =
73 throw Internal_Error(
"Client sent no ECC extension but we negotiated ECDH");
75 const std::string curve_name = policy.
choose_curve(curves);
79 "Could not agree on an ECC curve with the client");
82 if(named_curve_id == 0)
83 throw Internal_Error(
"TLS does not support ECC with " + curve_name);
85 std::vector<uint8_t> ecdh_public_val;
87 if(curve_name ==
"x25519")
89 #if defined(BOTAN_HAS_CURVE_25519)
91 ecdh_public_val = x25519->public_value();
92 m_kex_key.reset(x25519.release());
94 throw Internal_Error(
"Negotiated X25519 somehow, but it is disabled");
100 std::unique_ptr<ECDH_PrivateKey> ecdh(
new ECDH_PrivateKey(rng, ec_group));
103 ecdh_public_val = ecdh->public_value(
107 m_kex_key.reset(ecdh.release());
110 m_params.push_back(3);
111 m_params.push_back(
get_byte(0, named_curve_id));
112 m_params.push_back(
get_byte(1, named_curve_id));
116 #if defined(BOTAN_HAS_SRP6)
117 else if(kex_algo ==
"SRP_SHA")
119 const std::string srp_identifier = state.
client_hello()->srp_identifier();
121 std::string group_id;
123 std::vector<uint8_t> salt;
125 const bool found = creds.
srp_verifier(
"tls-server", hostname,
132 "Unknown SRP user " + srp_identifier);
136 BigInt B = m_srp_params->step1(v, group_id,
147 #if defined(BOTAN_HAS_CECPQ1)
148 else if(kex_algo ==
"CECPQ1")
152 CECPQ1_offer(cecpq1_offer.data(), m_cecpq1_key.get(), rng);
156 else if(kex_algo !=
"PSK")
158 throw Internal_Error(
"Server_Key_Exchange: Unknown kex type " + kex_algo);
165 std::pair<std::string, Signature_Format> format =
168 PK_Signer signer(*signing_key, rng, format.first, format.second);
183 const std::string& kex_algo,
184 const std::string& sig_algo,
195 if(kex_algo ==
"PSK" || kex_algo ==
"DHE_PSK" || kex_algo ==
"ECDHE_PSK")
200 if(kex_algo ==
"DH" || kex_algo ==
"DHE_PSK")
204 for(
size_t i = 0; i != 3; ++i)
209 else if(kex_algo ==
"ECDH" || kex_algo ==
"ECDHE_PSK")
215 else if(kex_algo ==
"SRP_SHA")
224 else if(kex_algo ==
"CECPQ1")
229 else if(kex_algo !=
"PSK")
230 throw Decoding_Error(
"Server_Key_Exchange: Unsupported kex type " + kex_algo);
232 m_params.assign(buf.data(), buf.data() + reader.
read_so_far());
242 m_signature = reader.
get_range<uint8_t>(2, 0, 65535);
251 std::vector<uint8_t> Server_Key_Exchange::serialize()
const
253 std::vector<uint8_t> buf =
params();
255 if(m_signature.size())
258 if(m_hash_algo !=
"" && m_sig_algo !=
"")
275 const Policy& policy)
const
279 std::pair<std::string, Signature_Format> format =
283 PK_Verifier verifier(server_key, format.first, format.second);
291 #if defined(BOTAN_UNSAFE_FUZZER_MODE)
294 return signature_valid;
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)
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 sig_algo() const
static uint16_t name_to_curve_id(const std::string &name)
const std::vector< uint8_t > & params() const
virtual std::string psk_identity_hint(const std::string &type, const std::string &context)
std::vector< uint8_t > signature(RandomNumberGenerator &rng)
const BigInt & get_p() const
bool verify(const Public_Key &server_key, const Handshake_State &state, const Policy &policy) const
virtual bool hide_unknown_users() const
virtual std::string choose_curve(const std::vector< std::string > &curve_names) const
#define BOTAN_ASSERT(expr, assertion_made)
static uint8_t hash_algo_code(const std::string &name)
std::string get_string(size_t len_bytes, size_t min_bytes, size_t max_bytes)
const BigInt & get_g() const
virtual std::string dh_group() const
#define BOTAN_ASSERT_NONNULL(ptr)
void client_hello(Client_Hello *client_hello)
const Private_Key & server_kex_key() const
std::string kex_algo() const
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
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)
static std::string sig_algo_name(uint8_t code)
bool check_signature(const uint8_t sig[], size_t length)
void CECPQ1_offer(uint8_t send[CECPQ1_OFFER_BYTES], CECPQ1_key *offer_key_output, RandomNumberGenerator &rng)
virtual void check_peer_key_acceptable(const Public_Key &public_key) const
uint8_t get_byte(size_t byte_num, T input)
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
const Ciphersuite & ciphersuite() const
static std::vector< uint8_t > encode(const BigInt &n, Base base=Binary)
size_t read_so_far() const
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)