Coverage Report

Created: 2021-05-04 09:02

/src/botan/src/lib/tls/msg_server_kex.cpp
Line
Count
Source (jump to first uncovered line)
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/internal/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
namespace Botan {
30
31
namespace TLS {
32
33
/**
34
* Create a new Server Key Exchange message
35
*/
36
Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io,
37
                                         Handshake_State& state,
38
                                         const Policy& policy,
39
                                         Credentials_Manager& creds,
40
                                         RandomNumberGenerator& rng,
41
                                         const Private_Key* signing_key)
42
22.1k
   {
43
22.1k
   const std::string hostname = state.client_hello()->sni_hostname();
44
22.1k
   const Kex_Algo kex_algo = state.ciphersuite().kex_method();
45
46
22.1k
   if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK)
47
22.1k
      {
48
22.1k
      std::string identity_hint =
49
22.1k
         creds.psk_identity_hint("tls-server", hostname);
50
51
22.1k
      append_tls_length_value(m_params, identity_hint, 2);
52
22.1k
      }
53
54
22.1k
   if(kex_algo == Kex_Algo::DH)
55
0
      {
56
0
      const std::vector<Group_Params> dh_groups = state.client_hello()->supported_dh_groups();
57
58
0
      Group_Params shared_group = Group_Params::NONE;
59
60
      /*
61
      If the client does not send any DH groups in the supported groups
62
      extension, but does offer DH ciphersuites, we select a group arbitrarily
63
      */
64
65
0
      if(dh_groups.empty())
66
0
         {
67
0
         shared_group = policy.default_dh_group();
68
0
         }
69
0
      else
70
0
         {
71
0
         shared_group = policy.choose_key_exchange_group(dh_groups);
72
0
         }
73
74
0
      if(shared_group == Group_Params::NONE)
75
0
         throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
76
0
               "Could not agree on a DH group with the client");
77
78
0
      BOTAN_ASSERT(group_param_is_dh(shared_group), "DH groups for the DH ciphersuites god");
79
80
0
      const std::string group_name = state.callbacks().tls_decode_group_param(shared_group);
81
0
      auto dh = std::make_unique<DH_PrivateKey>(rng, DL_Group(group_name));
82
83
0
      append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_p()), 2);
84
0
      append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_g()), 2);
85
0
      append_tls_length_value(m_params, dh->public_value(), 2);
86
0
      m_kex_key.reset(dh.release());
87
0
      }
88
22.1k
   else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK)
89
21.6k
      {
90
21.6k
      const std::vector<Group_Params> ec_groups = state.client_hello()->supported_ecc_curves();
91
92
21.6k
      if(ec_groups.empty())
93
0
         throw Internal_Error("Client sent no ECC extension but we negotiated ECDH");
94
95
21.6k
      Group_Params shared_group = policy.choose_key_exchange_group(ec_groups);
96
97
21.6k
      if(shared_group == Group_Params::NONE)
98
0
         throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "No shared ECC group with client");
99
100
21.6k
      std::vector<uint8_t> ecdh_public_val;
101
102
21.6k
      if(shared_group == Group_Params::X25519)
103
524
         {
104
524
#if defined(BOTAN_HAS_CURVE_25519)
105
524
         auto x25519 = std::make_unique<X25519_PrivateKey>(rng);
106
524
         ecdh_public_val = x25519->public_value();
107
524
         m_kex_key.reset(x25519.release());
108
#else
109
         throw Internal_Error("Negotiated X25519 somehow, but it is disabled");
110
#endif
111
524
         }
112
21.0k
      else
113
21.0k
         {
114
21.0k
         Group_Params curve = policy.choose_key_exchange_group(ec_groups);
115
116
21.0k
         const std::string curve_name = state.callbacks().tls_decode_group_param(curve);
117
118
21.0k
         EC_Group ec_group(curve_name);
119
21.0k
         auto ecdh = std::make_unique<ECDH_PrivateKey>(rng, ec_group);
120
121
         // follow client's preference for point compression
122
21.0k
         ecdh_public_val = ecdh->public_value(
123
21.0k
            state.client_hello()->prefers_compressed_ec_points() ?
124
12.0k
            PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED);
125
126
21.0k
         m_kex_key.reset(ecdh.release());
127
21.0k
         }
128
129
21.6k
      const uint16_t named_curve_id = static_cast<uint16_t>(shared_group);
130
21.6k
      m_params.push_back(3); // named curve
131
21.6k
      m_params.push_back(get_byte<0>(named_curve_id));
132
21.6k
      m_params.push_back(get_byte<1>(named_curve_id));
133
134
21.6k
      append_tls_length_value(m_params, ecdh_public_val, 1);
135
21.6k
      }
136
565
#if defined(BOTAN_HAS_CECPQ1)
137
565
   else if(kex_algo == Kex_Algo::CECPQ1)
138
0
      {
139
0
      std::vector<uint8_t> cecpq1_offer(CECPQ1_OFFER_BYTES);
140
0
      m_cecpq1_key.reset(new CECPQ1_key);
141
0
      CECPQ1_offer(cecpq1_offer.data(), m_cecpq1_key.get(), rng);
142
0
      append_tls_length_value(m_params, cecpq1_offer, 2);
143
0
      }
144
565
#endif
145
565
   else if(kex_algo != Kex_Algo::PSK)
146
0
      {
147
0
      throw Internal_Error("Server_Key_Exchange: Unknown kex type " +
148
0
                           kex_method_to_string(kex_algo));
149
0
      }
150
151
22.1k
   if(state.ciphersuite().signature_used())
152
0
      {
153
0
      BOTAN_ASSERT(signing_key, "Signing key was set");
154
155
0
      std::pair<std::string, Signature_Format> format =
156
0
         state.choose_sig_format(*signing_key, m_scheme, false, policy);
157
158
0
      std::vector<uint8_t> buf = state.client_hello()->random();
159
160
0
      buf += state.server_hello()->random();
161
0
      buf += params();
162
163
0
      m_signature =
164
0
         state.callbacks().tls_sign_message(*signing_key, rng,
165
0
                                            format.first, format.second, buf);
166
0
      }
167
168
22.1k
   state.hash().update(io.send(*this));
169
22.1k
   }
170
171
/**
172
* Deserialize a Server Key Exchange message
173
*/
174
Server_Key_Exchange::Server_Key_Exchange(const std::vector<uint8_t>& buf,
175
                                         const Kex_Algo kex_algo,
176
                                         const Auth_Method auth_method,
177
                                         Protocol_Version version)
178
0
   {
179
0
   BOTAN_UNUSED(version); // remove this
180
0
   TLS_Data_Reader reader("ServerKeyExchange", buf);
181
182
   /*
183
   * Here we are deserializing enough to find out what offset the
184
   * signature is at. All processing is done when the Client Key Exchange
185
   * is prepared.
186
   */
187
188
0
   if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK)
189
0
      {
190
0
      reader.get_string(2, 0, 65535); // identity hint
191
0
      }
192
193
0
   if(kex_algo == Kex_Algo::DH)
194
0
      {
195
      // 3 bigints, DH p, g, Y
196
197
0
      for(size_t i = 0; i != 3; ++i)
198
0
         {
199
0
         reader.get_range<uint8_t>(2, 1, 65535);
200
0
         }
201
0
      }
202
0
   else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK)
203
0
      {
204
0
      reader.get_byte(); // curve type
205
0
      reader.get_uint16_t(); // curve id
206
0
      reader.get_range<uint8_t>(1, 1, 255); // public key
207
0
      }
208
0
   else if(kex_algo == Kex_Algo::CECPQ1)
209
0
      {
210
      // u16 blob
211
0
      reader.get_range<uint8_t>(2, 1, 65535);
212
0
      }
213
0
   else if(kex_algo != Kex_Algo::PSK)
214
0
      throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " +
215
0
                           kex_method_to_string(kex_algo));
216
217
0
   m_params.assign(buf.data(), buf.data() + reader.read_so_far());
218
219
0
   if(auth_method != Auth_Method::IMPLICIT)
220
0
      {
221
0
      m_scheme = static_cast<Signature_Scheme>(reader.get_uint16_t());
222
0
      m_signature = reader.get_range<uint8_t>(2, 0, 65535);
223
0
      }
224
225
0
   reader.assert_done();
226
0
   }
227
228
/**
229
* Serialize a Server Key Exchange message
230
*/
231
std::vector<uint8_t> Server_Key_Exchange::serialize() const
232
22.1k
   {
233
22.1k
   std::vector<uint8_t> buf = params();
234
235
22.1k
   if(m_signature.size())
236
0
      {
237
0
      if(m_scheme != Signature_Scheme::NONE)
238
0
         {
239
0
         const uint16_t scheme_code = static_cast<uint16_t>(m_scheme);
240
0
         buf.push_back(get_byte<0>(scheme_code));
241
0
         buf.push_back(get_byte<1>(scheme_code));
242
0
         }
243
244
0
      append_tls_length_value(buf, m_signature, 2);
245
0
      }
246
247
22.1k
   return buf;
248
22.1k
   }
249
250
/**
251
* Verify a Server Key Exchange message
252
*/
253
bool Server_Key_Exchange::verify(const Public_Key& server_key,
254
                                 const Handshake_State& state,
255
                                 const Policy& policy) const
256
0
   {
257
0
   policy.check_peer_key_acceptable(server_key);
258
259
0
   std::pair<std::string, Signature_Format> format =
260
0
      state.parse_sig_format(server_key, m_scheme, false, policy);
261
262
0
   std::vector<uint8_t> buf = state.client_hello()->random();
263
264
0
   buf += state.server_hello()->random();
265
0
   buf += params();
266
267
0
   const bool signature_valid =
268
0
      state.callbacks().tls_verify_message(server_key, format.first, format.second,
269
0
                                           buf, m_signature);
270
271
0
#if defined(BOTAN_UNSAFE_FUZZER_MODE)
272
0
   BOTAN_UNUSED(signature_valid);
273
0
   return true;
274
#else
275
   return signature_valid;
276
#endif
277
0
   }
278
279
const Private_Key& Server_Key_Exchange::server_kex_key() const
280
10.4k
   {
281
10.4k
   BOTAN_ASSERT_NONNULL(m_kex_key);
282
10.4k
   return *m_kex_key;
283
10.4k
   }
284
285
}
286
287
}