Coverage Report

Created: 2025-04-11 06:34

/src/botan/src/lib/tls/tls13/tls_extensions_key_share.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* TLS Extension Key Share
3
* (C) 2011,2012,2015,2016 Jack Lloyd
4
*     2016 Juraj Somorovsky
5
*     2021 Elektrobit Automotive GmbH
6
*     2022 Hannes Rantzsch, René Meusel, neXenio GmbH
7
*
8
* Botan is released under the Simplified BSD License (see license.txt)
9
*/
10
11
#include <botan/tls_extensions.h>
12
13
#include <botan/rng.h>
14
#include <botan/tls_callbacks.h>
15
#include <botan/tls_exceptn.h>
16
#include <botan/tls_policy.h>
17
#include <botan/internal/ct_utils.h>
18
#include <botan/internal/stl_util.h>
19
#include <botan/internal/tls_reader.h>
20
21
#include <algorithm>
22
#include <utility>
23
24
#if defined(BOTAN_HAS_X25519)
25
   #include <botan/x25519.h>
26
#endif
27
28
#if defined(BOTAN_HAS_X448)
29
   #include <botan/x448.h>
30
#endif
31
32
#include <botan/dh.h>
33
#include <botan/dl_group.h>
34
#include <botan/ecdh.h>
35
36
namespace Botan::TLS {
37
38
namespace {
39
40
class Key_Share_Entry {
41
   public:
42
5.44k
      Key_Share_Entry(TLS_Data_Reader& reader) {
43
         // TODO check that the group actually exists before casting...
44
5.44k
         m_group = static_cast<Named_Group>(reader.get_uint16_t());
45
5.44k
         m_key_exchange = reader.get_tls_length_value(2);
46
5.44k
      }
47
48
      // Create an empty Key_Share_Entry with the selected group
49
      // but don't pre-generate a keypair, yet.
50
0
      Key_Share_Entry(const TLS::Group_Params group) : m_group(group) {}
51
52
      Key_Share_Entry(const TLS::Group_Params group, Callbacks& cb, RandomNumberGenerator& rng) :
53
0
            m_group(group), m_private_key(cb.tls_kem_generate_key(group, rng)) {
54
0
         if(!m_private_key) {
55
0
            throw TLS_Exception(Alert::InternalError, "Application did not provide a suitable ephemeral key pair");
56
0
         }
57
58
0
         if(group.is_kem()) {
59
0
            m_key_exchange = m_private_key->public_key_bits();
60
0
         } else if(group.is_ecdh_named_curve()) {
61
0
            auto pkey = dynamic_cast<ECDH_PublicKey*>(m_private_key.get());
62
0
            if(!pkey) {
63
0
               throw TLS_Exception(Alert::InternalError, "Application did not provide a ECDH_PublicKey");
64
0
            }
65
66
            // RFC 8446 Ch. 4.2.8.2
67
            //
68
            //   Note: Versions of TLS prior to 1.3 permitted point format
69
            //   negotiation; TLS 1.3 removes this feature in favor of a single point
70
            //   format for each curve.
71
            //
72
            // Hence, we neither need to take Policy::use_ecc_point_compression() nor
73
            // ClientHello::prefers_compressed_ec_points() into account here.
74
0
            m_key_exchange = pkey->public_value(EC_Point_Format::Uncompressed);
75
0
         } else {
76
0
            auto pkey = dynamic_cast<PK_Key_Agreement_Key*>(m_private_key.get());
77
0
            if(!pkey) {
78
0
               throw TLS_Exception(Alert::InternalError, "Application did not provide a key-agreement key");
79
0
            }
80
81
0
            m_key_exchange = pkey->public_value();
82
0
         }
83
0
      }
84
85
0
      bool empty() const { return (m_group == Group_Params::NONE) && m_key_exchange.empty(); }
86
87
0
      std::vector<uint8_t> serialize() const {
88
0
         std::vector<uint8_t> result;
89
0
         result.reserve(m_key_exchange.size() + 4);
90
91
0
         const uint16_t named_curve_id = m_group.wire_code();
92
0
         result.push_back(get_byte<0>(named_curve_id));
93
0
         result.push_back(get_byte<1>(named_curve_id));
94
0
         append_tls_length_value(result, m_key_exchange, 2);
95
96
0
         return result;
97
0
      }
98
99
71.7k
      Named_Group group() const { return m_group; }
100
101
      secure_vector<uint8_t> encapsulate(const Key_Share_Entry& client_share,
102
                                         const Policy& policy,
103
                                         Callbacks& cb,
104
0
                                         RandomNumberGenerator& rng) {
105
0
         auto [encapsulated_shared_key, shared_key] =
106
0
            KEM_Encapsulation::destructure(cb.tls_kem_encapsulate(m_group, client_share.m_key_exchange, rng, policy));
107
0
         m_key_exchange = std::move(encapsulated_shared_key);
108
0
         return std::move(shared_key);
109
0
      }
110
111
      /**
112
       * Perform KEM decapsulation with another Key_Share_Entry's public key
113
       *
114
       * The caller must ensure that both this and `received` have the same group.
115
       * This method must not be called on Key_Share_Entries without a private key.
116
       */
117
      secure_vector<uint8_t> decapsulate(const Key_Share_Entry& received,
118
                                         const Policy& policy,
119
                                         Callbacks& cb,
120
0
                                         RandomNumberGenerator& rng) {
121
0
         auto scope = scoped_cleanup([&] { m_private_key.reset(); });
122
0
         BOTAN_ASSERT_NOMSG(m_group == received.m_group);
123
0
         BOTAN_STATE_CHECK(m_private_key != nullptr);
124
0
         return cb.tls_kem_decapsulate(m_group, *m_private_key, received.m_key_exchange, rng, policy);
125
0
      }
126
127
   private:
128
      Named_Group m_group;
129
      std::vector<uint8_t> m_key_exchange;
130
      std::unique_ptr<Private_Key> m_private_key;
131
};
132
133
class Key_Share_ClientHello;
134
135
class Key_Share_ServerHello {
136
   public:
137
836
      Key_Share_ServerHello(TLS_Data_Reader& reader, uint16_t) : m_server_share(reader) {}
138
139
      Key_Share_ServerHello(Named_Group group,
140
                            const Key_Share_ClientHello& client_keyshare,
141
                            const Policy& policy,
142
                            Callbacks& cb,
143
                            RandomNumberGenerator& rng);
144
145
2.49k
      ~Key_Share_ServerHello() = default;
146
147
      Key_Share_ServerHello(const Key_Share_ServerHello&) = delete;
148
      Key_Share_ServerHello& operator=(const Key_Share_ServerHello&) = delete;
149
150
1.66k
      Key_Share_ServerHello(Key_Share_ServerHello&&) = default;
151
      Key_Share_ServerHello& operator=(Key_Share_ServerHello&&) = default;
152
153
0
      std::vector<uint8_t> serialize() const { return m_server_share.serialize(); }
154
155
0
      bool empty() const { return m_server_share.empty(); }
156
157
0
      Key_Share_Entry& get_singleton_entry() { return m_server_share; }
158
159
0
      const Key_Share_Entry& get_singleton_entry() const { return m_server_share; }
160
161
0
      std::vector<Named_Group> offered_groups() const { return {selected_group()}; }
162
163
0
      Named_Group selected_group() const { return m_server_share.group(); }
164
165
0
      secure_vector<uint8_t> take_shared_secret() {
166
0
         BOTAN_STATE_CHECK(!m_shared_secret.empty());
167
0
         return std::exchange(m_shared_secret, {});
168
0
      }
169
170
   private:
171
      Key_Share_Entry m_server_share;
172
      secure_vector<uint8_t> m_shared_secret;
173
};
174
175
class Key_Share_ClientHello {
176
   public:
177
2.01k
      Key_Share_ClientHello(TLS_Data_Reader& reader, uint16_t /* extension_size */) {
178
         // This construction is a crutch to make working with the incoming
179
         // TLS_Data_Reader bearable. Currently, this reader spans the entire
180
         // Client_Hello message. Hence, if offset or length fields are skewed
181
         // or maliciously fabricated, it is possible to read further than the
182
         // bounds of the current extension.
183
         // Note that this aplies to many locations in the code base.
184
         //
185
         // TODO: Overhaul the TLS_Data_Reader to allow for cheap "sub-readers"
186
         //       that enforce read bounds of sub-structures while parsing.
187
2.01k
         const auto client_key_share_length = reader.get_uint16_t();
188
2.01k
         const auto read_bytes_so_far_begin = reader.read_so_far();
189
9.28k
         auto remaining = [&] {
190
9.28k
            const auto read_so_far = reader.read_so_far() - read_bytes_so_far_begin;
191
9.28k
            BOTAN_STATE_CHECK(read_so_far <= client_key_share_length);
192
9.28k
            return client_key_share_length - read_so_far;
193
9.28k
         };
194
195
6.60k
         while(reader.has_remaining() && remaining() > 0) {
196
4.62k
            if(remaining() < 4) {
197
13
               throw TLS_Exception(Alert::DecodeError, "Not enough data to read another KeyShareEntry");
198
13
            }
199
200
4.61k
            Key_Share_Entry new_entry(reader);
201
202
            // RFC 8446 4.2.8
203
            //    Clients MUST NOT offer multiple KeyShareEntry values for the same
204
            //    group. [...]
205
            //    Servers MAY check for violations of these rules and abort the
206
            //    handshake with an "illegal_parameter" alert if one is violated.
207
35.4k
            if(std::find_if(m_client_shares.begin(), m_client_shares.end(), [&](const auto& entry) {
208
35.4k
                  return entry.group() == new_entry.group();
209
35.4k
               }) != m_client_shares.end()) {
210
18
               throw TLS_Exception(Alert::IllegalParameter, "Received multiple key share entries for the same group");
211
18
            }
212
213
4.59k
            m_client_shares.emplace_back(std::move(new_entry));
214
4.59k
         }
215
216
1.98k
         if((reader.read_so_far() - read_bytes_so_far_begin) != client_key_share_length) {
217
118
            throw Decoding_Error("Read bytes are not equal client KeyShare length");
218
118
         }
219
1.98k
      }
220
221
0
      Key_Share_ClientHello(const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng) {
222
0
         const auto supported = policy.key_exchange_groups();
223
0
         const auto offers = policy.key_exchange_groups_to_offer();
224
225
         // RFC 8446 P. 48
226
         //
227
         //   This vector MAY be empty if the client is requesting a
228
         //   HelloRetryRequest.  Each KeyShareEntry value MUST correspond to a
229
         //   group offered in the "supported_groups" extension and MUST appear in
230
         //   the same order.  However, the values MAY be a non-contiguous subset
231
         //   of the "supported_groups" extension and MAY omit the most preferred
232
         //   groups.
233
         //
234
         // ... hence, we're going through the supported groups and find those that
235
         //     should be used to offer a key exchange. This will satisfy above spec.
236
0
         for(const auto group : supported) {
237
0
            if(std::find(offers.begin(), offers.end(), group) == offers.end()) {
238
0
               continue;
239
0
            }
240
0
            m_client_shares.emplace_back(group, cb, rng);
241
0
         }
242
0
      }
243
244
5.14k
      ~Key_Share_ClientHello() = default;
245
246
      Key_Share_ClientHello(const Key_Share_ClientHello&) = delete;
247
      Key_Share_ClientHello& operator=(const Key_Share_ClientHello&) = delete;
248
249
3.43k
      Key_Share_ClientHello(Key_Share_ClientHello&&) = default;
250
      Key_Share_ClientHello& operator=(Key_Share_ClientHello&&) = default;
251
252
0
      void retry_offer(const TLS::Group_Params to_offer, Callbacks& cb, RandomNumberGenerator& rng) {
253
         // RFC 8446 4.2.8
254
         //    The selected_group field [MUST] not correspond to a group which was provided
255
         //    in the "key_share" extension in the original ClientHello.
256
0
         if(std::find_if(m_client_shares.cbegin(), m_client_shares.cend(), [&](const auto& kse) {
257
0
               return kse.group() == to_offer;
258
0
            }) != m_client_shares.cend()) {
259
0
            throw TLS_Exception(Alert::IllegalParameter, "group was already offered");
260
0
         }
261
262
0
         m_client_shares.clear();
263
0
         m_client_shares.emplace_back(to_offer, cb, rng);
264
0
      }
265
266
455
      std::vector<Named_Group> offered_groups() const {
267
455
         std::vector<Named_Group> offered_groups;
268
455
         offered_groups.reserve(m_client_shares.size());
269
915
         for(const auto& share : m_client_shares) {
270
915
            offered_groups.push_back(share.group());
271
915
         }
272
455
         return offered_groups;
273
455
      }
274
275
0
      Named_Group selected_group() const { throw Invalid_Argument("Client Hello Key Share does not select a group"); }
276
277
0
      std::vector<uint8_t> serialize() const {
278
0
         std::vector<uint8_t> shares;
279
0
         for(const auto& share : m_client_shares) {
280
0
            const auto serialized_share = share.serialize();
281
0
            shares.insert(shares.end(), serialized_share.cbegin(), serialized_share.cend());
282
0
         }
283
284
0
         std::vector<uint8_t> result;
285
0
         append_tls_length_value(result, shares, 2);
286
0
         return result;
287
0
      }
288
289
0
      bool empty() const {
290
         // RFC 8446 4.2.8
291
         //    Clients MAY send an empty client_shares vector in order to request
292
         //    group selection from the server, at the cost of an additional round
293
         //    trip [...].
294
0
         return false;
295
0
      }
296
297
      secure_vector<uint8_t> encapsulate(Key_Share_ServerHello& server_share,
298
                                         const Policy& policy,
299
                                         Callbacks& cb,
300
0
                                         RandomNumberGenerator& rng) const {
301
0
         auto& server_selected = server_share.get_singleton_entry();
302
303
         // find the client offer that matches the server offer
304
0
         auto match = std::find_if(m_client_shares.begin(), m_client_shares.end(), [&](const auto& offered) {
305
0
            return offered.group() == server_selected.group();
306
0
         });
307
308
         // We validated that the selected group was indeed offered by the
309
         // client before even constructing the Server Hello that contains the
310
         // Key_Share_ServerHello extension.
311
0
         BOTAN_STATE_CHECK(match != m_client_shares.end());
312
313
0
         return server_selected.encapsulate(*match, policy, cb, rng);
314
0
      }
315
316
      secure_vector<uint8_t> decapsulate(const Key_Share_ServerHello& server_share,
317
                                         const Policy& policy,
318
                                         Callbacks& cb,
319
0
                                         RandomNumberGenerator& rng) {
320
0
         const auto& server_selected = server_share.get_singleton_entry();
321
322
         // find the client offer that matches the server offer
323
0
         auto match = std::find_if(m_client_shares.begin(), m_client_shares.end(), [&](const auto& offered) {
324
0
            return offered.group() == server_selected.group();
325
0
         });
326
327
         // RFC 8446 4.2.8:
328
         //   [The KeyShareEntry in the ServerHello] MUST be in the same group
329
         //   as the KeyShareEntry value offered by the client that the server
330
         //   has selected for the negotiated key exchange.
331
0
         if(match == m_client_shares.end()) {
332
0
            throw TLS_Exception(Alert::IllegalParameter, "Server selected a key exchange group we didn't offer.");
333
0
         }
334
335
0
         return match->decapsulate(server_selected, policy, cb, rng);
336
0
      }
337
338
   private:
339
      std::vector<Key_Share_Entry> m_client_shares;
340
};
341
342
Key_Share_ServerHello::Key_Share_ServerHello(Named_Group group,
343
                                             const Key_Share_ClientHello& client_keyshare,
344
                                             const Policy& policy,
345
                                             Callbacks& cb,
346
                                             RandomNumberGenerator& rng) :
347
0
      m_server_share(group) {
348
0
   m_shared_secret = client_keyshare.encapsulate(*this, policy, cb, rng);
349
0
}
350
351
class Key_Share_HelloRetryRequest {
352
   public:
353
4
      Key_Share_HelloRetryRequest(TLS_Data_Reader& reader, uint16_t extension_size) {
354
4
         constexpr auto sizeof_uint16_t = sizeof(uint16_t);
355
356
4
         if(extension_size != sizeof_uint16_t) {
357
3
            throw Decoding_Error("Size of KeyShare extension in HelloRetryRequest must be " +
358
3
                                 std::to_string(sizeof_uint16_t) + " bytes");
359
3
         }
360
361
1
         m_selected_group = static_cast<Named_Group>(reader.get_uint16_t());
362
1
      }
363
364
0
      Key_Share_HelloRetryRequest(Named_Group selected_group) : m_selected_group(selected_group) {}
365
366
      ~Key_Share_HelloRetryRequest() = default;
367
368
      Key_Share_HelloRetryRequest(const Key_Share_HelloRetryRequest&) = delete;
369
      Key_Share_HelloRetryRequest& operator=(const Key_Share_HelloRetryRequest&) = delete;
370
371
      Key_Share_HelloRetryRequest(Key_Share_HelloRetryRequest&&) = default;
372
      Key_Share_HelloRetryRequest& operator=(Key_Share_HelloRetryRequest&&) = default;
373
374
0
      std::vector<uint8_t> serialize() const {
375
0
         auto code = m_selected_group.wire_code();
376
0
         return {get_byte<0>(code), get_byte<1>(code)};
377
0
      }
378
379
0
      Named_Group selected_group() const { return m_selected_group; }
380
381
0
      std::vector<Named_Group> offered_groups() const {
382
0
         throw Invalid_Argument("Hello Retry Request never offers any key exchange groups");
383
0
      }
384
385
0
      bool empty() const { return m_selected_group == Group_Params::NONE; }
386
387
   private:
388
      Named_Group m_selected_group;
389
};
390
391
}  // namespace
392
393
class Key_Share::Key_Share_Impl {
394
   public:
395
      using Key_Share_Type = std::variant<Key_Share_ClientHello, Key_Share_ServerHello, Key_Share_HelloRetryRequest>;
396
397
2.54k
      Key_Share_Impl(Key_Share_Type ks) : key_share(std::move(ks)) {}
398
399
      // NOLINTNEXTLINE(*-non-private-member-variables-in-classes)
400
      Key_Share_Type key_share;
401
};
402
403
2.85k
Key_Share::Key_Share(TLS_Data_Reader& reader, uint16_t extension_size, Handshake_Type message_type) {
404
2.85k
   if(message_type == Handshake_Type::ClientHello) {
405
2.01k
      m_impl = std::make_unique<Key_Share_Impl>(Key_Share_ClientHello(reader, extension_size));
406
2.01k
   } else if(message_type == Handshake_Type::HelloRetryRequest) {
407
      // Connection_Side::Server
408
4
      m_impl = std::make_unique<Key_Share_Impl>(Key_Share_HelloRetryRequest(reader, extension_size));
409
842
   } else if(message_type == Handshake_Type::ServerHello) {
410
      // Connection_Side::Server
411
836
      m_impl = std::make_unique<Key_Share_Impl>(Key_Share_ServerHello(reader, extension_size));
412
836
   } else {
413
6
      throw Invalid_Argument(std::string("cannot create a Key_Share extension for message of type: ") +
414
6
                             handshake_type_to_string(message_type));
415
6
   }
416
2.85k
}
417
418
// ClientHello
419
Key_Share::Key_Share(const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng) :
420
0
      m_impl(std::make_unique<Key_Share_Impl>(Key_Share_ClientHello(policy, cb, rng))) {}
421
422
// HelloRetryRequest
423
Key_Share::Key_Share(Named_Group selected_group) :
424
0
      m_impl(std::make_unique<Key_Share_Impl>(Key_Share_HelloRetryRequest(selected_group))) {}
425
426
// ServerHello
427
Key_Share::Key_Share(Group_Params selected_group,
428
                     const Key_Share& client_keyshare,
429
                     const Policy& policy,
430
                     Callbacks& cb,
431
                     RandomNumberGenerator& rng) :
432
0
      m_impl(std::make_unique<Key_Share_Impl>(Key_Share_ServerHello(
433
0
         selected_group, std::get<Key_Share_ClientHello>(client_keyshare.m_impl->key_share), policy, cb, rng))) {}
434
435
2.54k
Key_Share::~Key_Share() = default;
436
437
0
std::vector<uint8_t> Key_Share::serialize(Connection_Side /*whoami*/) const {
438
0
   return std::visit([](const auto& key_share) { return key_share.serialize(); }, m_impl->key_share);
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::serialize(Botan::TLS::Connection_Side) const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::serialize(Botan::TLS::Connection_Side) const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::serialize(Botan::TLS::Connection_Side) const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&) const
439
0
}
440
441
0
bool Key_Share::empty() const {
442
0
   return std::visit([](const auto& key_share) { return key_share.empty(); }, m_impl->key_share);
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::empty() const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::empty() const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::empty() const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&) const
443
0
}
444
445
std::unique_ptr<Key_Share> Key_Share::create_as_encapsulation(Group_Params selected_group,
446
                                                              const Key_Share& client_keyshare,
447
                                                              const Policy& policy,
448
                                                              Callbacks& cb,
449
0
                                                              RandomNumberGenerator& rng) {
450
0
   return std::unique_ptr<Key_Share>(new Key_Share(selected_group, client_keyshare, policy, cb, rng));
451
0
}
452
453
secure_vector<uint8_t> Key_Share::decapsulate(const Key_Share& server_keyshare,
454
                                              const Policy& policy,
455
                                              Callbacks& cb,
456
0
                                              RandomNumberGenerator& rng) {
457
0
   return std::visit(overloaded{[&](Key_Share_ClientHello& ch, const Key_Share_ServerHello& sh) {
458
0
                                   return ch.decapsulate(sh, policy, cb, rng);
459
0
                                },
460
0
                                [](const auto&, const auto&) -> secure_vector<uint8_t> {
461
0
                                   throw Invalid_Argument(
462
0
                                      "can only decapsulate in ClientHello Key_Share with a ServerHello Key_Share");
463
0
                                }},
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::decapsulate(Botan::TLS::Key_Share const&, Botan::TLS::Policy const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ClientHello, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::decapsulate(Botan::TLS::Key_Share const&, Botan::TLS::Policy const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ClientHello, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::decapsulate(Botan::TLS::Key_Share const&, Botan::TLS::Policy const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::decapsulate(Botan::TLS::Key_Share const&, Botan::TLS::Policy const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::decapsulate(Botan::TLS::Key_Share const&, Botan::TLS::Policy const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::decapsulate(Botan::TLS::Key_Share const&, Botan::TLS::Policy const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::decapsulate(Botan::TLS::Key_Share const&, Botan::TLS::Policy const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::decapsulate(Botan::TLS::Key_Share const&, Botan::TLS::Policy const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&) const
464
0
                     m_impl->key_share,
465
0
                     server_keyshare.m_impl->key_share);
466
0
}
467
468
455
std::vector<Named_Group> Key_Share::offered_groups() const {
469
455
   return std::visit([](const auto& keyshare) { return keyshare.offered_groups(); }, m_impl->key_share);
tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::offered_groups() const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Line
Count
Source
469
455
   return std::visit([](const auto& keyshare) { return keyshare.offered_groups(); }, m_impl->key_share);
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::offered_groups() const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::offered_groups() const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&) const
470
455
}
471
472
0
Named_Group Key_Share::selected_group() const {
473
0
   return std::visit([](const auto& keyshare) { return keyshare.selected_group(); }, m_impl->key_share);
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::selected_group() const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::selected_group() const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::selected_group() const::$_0::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&) const
474
0
}
475
476
0
secure_vector<uint8_t> Key_Share::take_shared_secret() {
477
0
   return std::visit(
478
0
      overloaded{[](Key_Share_ServerHello& server_keyshare) { return server_keyshare.take_shared_secret(); },
479
0
                 [](auto&) -> secure_vector<uint8_t> {
480
0
                    throw Invalid_Argument("Only the key share in Server Hello contains a shared secret");
481
0
                 }},
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::take_shared_secret()::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_ClientHello&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > Botan::TLS::Key_Share::take_shared_secret()::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest&) const
482
0
      m_impl->key_share);
483
0
}
484
485
void Key_Share::retry_offer(const Key_Share& retry_request_keyshare,
486
                            const std::vector<Named_Group>& supported_groups,
487
                            Callbacks& cb,
488
0
                            RandomNumberGenerator& rng) {
489
0
   std::visit(overloaded{[&](Key_Share_ClientHello& ch, const Key_Share_HelloRetryRequest& hrr) {
490
0
                            auto selected = hrr.selected_group();
491
                            // RFC 8446 4.2.8
492
                            //    [T]he selected_group field [MUST correspond] to a group which was provided in
493
                            //    the "supported_groups" extension in the original ClientHello
494
0
                            if(!value_exists(supported_groups, selected)) {
495
0
                               throw TLS_Exception(Alert::IllegalParameter, "group was not advertised as supported");
496
0
                            }
497
498
0
                            return ch.retry_offer(selected, cb, rng);
499
0
                         },
500
0
                         [](const auto&, const auto&) {
501
0
                            throw Invalid_Argument("can only retry with HelloRetryRequest on a ClientHello Key_Share");
502
0
                         }},
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::retry_offer(Botan::TLS::Key_Share const&, std::__1::vector<Botan::TLS::Group_Params, std::__1::allocator<Botan::TLS::Group_Params> > const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ClientHello, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::retry_offer(Botan::TLS::Key_Share const&, std::__1::vector<Botan::TLS::Group_Params, std::__1::allocator<Botan::TLS::Group_Params> > const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ClientHello, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello>(Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::retry_offer(Botan::TLS::Key_Share const&, std::__1::vector<Botan::TLS::Group_Params, std::__1::allocator<Botan::TLS::Group_Params> > const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::retry_offer(Botan::TLS::Key_Share const&, std::__1::vector<Botan::TLS::Group_Params, std::__1::allocator<Botan::TLS::Group_Params> > const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::retry_offer(Botan::TLS::Key_Share const&, std::__1::vector<Botan::TLS::Group_Params, std::__1::allocator<Botan::TLS::Group_Params> > const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_ServerHello, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::retry_offer(Botan::TLS::Key_Share const&, std::__1::vector<Botan::TLS::Group_Params, std::__1::allocator<Botan::TLS::Group_Params> > const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&, Botan::TLS::(anonymous namespace)::Key_Share_ClientHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::retry_offer(Botan::TLS::Key_Share const&, std::__1::vector<Botan::TLS::Group_Params, std::__1::allocator<Botan::TLS::Group_Params> > const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&, Botan::TLS::(anonymous namespace)::Key_Share_ServerHello const&) const
Unexecuted instantiation: tls_extensions_key_share.cpp:auto Botan::TLS::Key_Share::retry_offer(Botan::TLS::Key_Share const&, std::__1::vector<Botan::TLS::Group_Params, std::__1::allocator<Botan::TLS::Group_Params> > const&, Botan::TLS::Callbacks&, Botan::RandomNumberGenerator&)::$_1::operator()<Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest>(Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&, Botan::TLS::(anonymous namespace)::Key_Share_HelloRetryRequest const&) const
503
0
              m_impl->key_share,
504
0
              retry_request_keyshare.m_impl->key_share);
505
0
}
506
507
}  // namespace Botan::TLS