Coverage Report

Created: 2022-06-23 06:44

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