Coverage Report

Created: 2021-02-21 07:20

/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
21.4k
   {
43
21.4k
   const std::string hostname = state.client_hello()->sni_hostname();
44
21.4k
   const Kex_Algo kex_algo = state.ciphersuite().kex_method();
45
46
21.4k
   if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK)
47
21.4k
      {
48
21.4k
      std::string identity_hint =
49
21.4k
         creds.psk_identity_hint("tls-server", hostname);
50
51
21.4k
      append_tls_length_value(m_params, identity_hint, 2);
52
21.4k
      }
53
54
21.4k
   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
      std::unique_ptr<DH_PrivateKey> dh(new 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
21.4k
   else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK)
89
20.8k
      {
90
20.8k
      const std::vector<Group_Params> ec_groups = state.client_hello()->supported_ecc_curves();
91
92
20.8k
      if(ec_groups.empty())
93
0
         throw Internal_Error("Client sent no ECC extension but we negotiated ECDH");
94
95
20.8k
      Group_Params shared_group = policy.choose_key_exchange_group(ec_groups);
96
97
20.8k
      if(shared_group == Group_Params::NONE)
98
0
         throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "No shared ECC group with client");
99
100
20.8k
      std::vector<uint8_t> ecdh_public_val;
101
102
20.8k
      if(shared_group == Group_Params::X25519)
103
575
         {
104
575
#if defined(BOTAN_HAS_CURVE_25519)
105
575
         std::unique_ptr<Curve25519_PrivateKey> x25519(new Curve25519_PrivateKey(rng));
106
575
         ecdh_public_val = x25519->public_value();
107
575
         m_kex_key.reset(x25519.release());
108
#else
109
         throw Internal_Error("Negotiated X25519 somehow, but it is disabled");
110
#endif
111
575
         }
112
20.3k
      else
113
20.3k
         {
114
20.3k
         Group_Params curve = policy.choose_key_exchange_group(ec_groups);
115
116
20.3k
         const std::string curve_name = state.callbacks().tls_decode_group_param(curve);
117
118
20.3k
         EC_Group ec_group(curve_name);
119
20.3k
         std::unique_ptr<ECDH_PrivateKey> ecdh(new ECDH_PrivateKey(rng, ec_group));
120
121
         // follow client's preference for point compression
122
20.3k
         ecdh_public_val = ecdh->public_value(
123
20.3k
            state.client_hello()->prefers_compressed_ec_points() ?
124
12.0k
            PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED);
125
126
20.3k
         m_kex_key.reset(ecdh.release());
127
20.3k
         }
128
129
20.8k
      const uint16_t named_curve_id = static_cast<uint16_t>(shared_group);
130
20.8k
      m_params.push_back(3); // named curve
131
20.8k
      m_params.push_back(get_byte(0, named_curve_id));
132
20.8k
      m_params.push_back(get_byte(1, named_curve_id));
133
134
20.8k
      append_tls_length_value(m_params, ecdh_public_val, 1);
135
20.8k
      }
136
569
#if defined(BOTAN_HAS_CECPQ1)
137
569
   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
569
#endif
145
569
   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
21.4k
   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
21.4k
   state.hash().update(io.send(*this));
169
21.4k
   }
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
1.40k
   {
179
1.40k
   TLS_Data_Reader reader("ServerKeyExchange", buf);
180
181
   /*
182
   * Here we are deserializing enough to find out what offset the
183
   * signature is at. All processing is done when the Client Key Exchange
184
   * is prepared.
185
   */
186
187
1.40k
   if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::ECDHE_PSK)
188
1.10k
      {
189
1.10k
      reader.get_string(2, 0, 65535); // identity hint
190
1.10k
      }
191
192
1.40k
   if(kex_algo == Kex_Algo::DH)
193
3
      {
194
      // 3 bigints, DH p, g, Y
195
196
11
      for(size_t i = 0; i != 3; ++i)
197
8
         {
198
8
         reader.get_range<uint8_t>(2, 1, 65535);
199
8
         }
200
3
      }
201
1.40k
   else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK)
202
1.03k
      {
203
1.03k
      reader.get_byte(); // curve type
204
1.03k
      reader.get_uint16_t(); // curve id
205
1.03k
      reader.get_range<uint8_t>(1, 1, 255); // public key
206
1.03k
      }
207
369
   else if(kex_algo == Kex_Algo::CECPQ1)
208
1
      {
209
      // u16 blob
210
1
      reader.get_range<uint8_t>(2, 1, 65535);
211
1
      }
212
368
   else if(kex_algo != Kex_Algo::PSK)
213
0
      throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " +
214
0
                           kex_method_to_string(kex_algo));
215
216
1.40k
   m_params.assign(buf.data(), buf.data() + reader.read_so_far());
217
218
1.40k
   if(auth_method != Auth_Method::IMPLICIT)
219
304
      {
220
304
      if(version.supports_negotiable_signature_algorithms())
221
304
         {
222
304
         m_scheme = static_cast<Signature_Scheme>(reader.get_uint16_t());
223
304
         }
224
225
304
      m_signature = reader.get_range<uint8_t>(2, 0, 65535);
226
304
      }
227
228
1.40k
   reader.assert_done();
229
1.40k
   }
230
231
/**
232
* Serialize a Server Key Exchange message
233
*/
234
std::vector<uint8_t> Server_Key_Exchange::serialize() const
235
21.4k
   {
236
21.4k
   std::vector<uint8_t> buf = params();
237
238
21.4k
   if(m_signature.size())
239
0
      {
240
0
      if(m_scheme != Signature_Scheme::NONE)
241
0
         {
242
0
         const uint16_t scheme_code = static_cast<uint16_t>(m_scheme);
243
0
         buf.push_back(get_byte(0, scheme_code));
244
0
         buf.push_back(get_byte(1, scheme_code));
245
0
         }
246
247
0
      append_tls_length_value(buf, m_signature, 2);
248
0
      }
249
250
21.4k
   return buf;
251
21.4k
   }
252
253
/**
254
* Verify a Server Key Exchange message
255
*/
256
bool Server_Key_Exchange::verify(const Public_Key& server_key,
257
                                 const Handshake_State& state,
258
                                 const Policy& policy) const
259
301
   {
260
301
   policy.check_peer_key_acceptable(server_key);
261
262
301
   std::pair<std::string, Signature_Format> format =
263
301
      state.parse_sig_format(server_key, m_scheme, false, policy);
264
265
301
   std::vector<uint8_t> buf = state.client_hello()->random();
266
267
301
   buf += state.server_hello()->random();
268
301
   buf += params();
269
270
301
   const bool signature_valid =
271
301
      state.callbacks().tls_verify_message(server_key, format.first, format.second,
272
301
                                           buf, m_signature);
273
274
301
#if defined(BOTAN_UNSAFE_FUZZER_MODE)
275
301
   BOTAN_UNUSED(signature_valid);
276
301
   return true;
277
#else
278
   return signature_valid;
279
#endif
280
301
   }
281
282
const Private_Key& Server_Key_Exchange::server_kex_key() const
283
9.30k
   {
284
9.30k
   BOTAN_ASSERT_NONNULL(m_kex_key);
285
9.30k
   return *m_kex_key;
286
9.30k
   }
287
288
}
289
290
}