• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 30496461195

29 Jul 2026 08:43PM UTC coverage: 89.519% (+0.09%) from 89.425%
30496461195

push

github

web-flow
Merge pull request #5776 from Rohde-Schwarz/fix/tls_anvil

116233 of 129841 relevant lines covered (89.52%)

10620449.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.18
/src/tests/test_tls_rfc8448.cpp
1
/*
2
* (C) 2021 Jack Lloyd
3
*     2021, 2022 René Meusel, Hannes Rantzsch - neXenio GmbH
4
*     2022       René Meusel - Rohde & Schwarz Cybersecurity GmbH
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include "tests.h"
10
#include <fstream>
11
#include <memory>
12
#include <utility>
13

14
// Since RFC 8448 uses a specific set of cipher suites we can only run this
15
// test if all of them are enabled.
16
#if defined(BOTAN_HAS_TLS_12) && defined(BOTAN_HAS_TLS_13) && defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) &&             \
17
   defined(BOTAN_HAS_AEAD_GCM) && defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_X25519) && defined(BOTAN_HAS_SHA2_32) && \
18
   defined(BOTAN_HAS_SHA2_64) && defined(BOTAN_HAS_ECDSA) && defined(BOTAN_HAS_PSS)
19
   #define BOTAN_CAN_RUN_TEST_TLS_RFC8448
20
#endif
21

22
#if defined(BOTAN_CAN_RUN_TEST_TLS_RFC8448)
23
   #include "test_rng.h"
24

25
   #include <botan/assert.h>
26
   #include <botan/credentials_manager.h>
27
   #include <botan/data_src.h>
28
   #include <botan/dl_group.h>
29
   #include <botan/ec_group.h>
30
   #include <botan/hex.h>
31
   #include <botan/pk_algs.h>
32
   #include <botan/pkcs8.h>
33
   #include <botan/tls_callbacks.h>
34
   #include <botan/tls_client.h>
35
   #include <botan/tls_extensions_12.h>
36
   #include <botan/tls_extensions_13.h>
37
   #include <botan/tls_messages.h>
38
   #include <botan/tls_policy.h>
39
   #include <botan/tls_server.h>
40
   #include <botan/tls_session_manager.h>
41
   #include <botan/x509_key.h>
42
   #include <botan/x509cert.h>
43
   #include <botan/internal/concat_util.h>
44
   #include <botan/internal/fmt.h>
45
   #include <botan/internal/stl_util.h>
46
#endif
47

48
namespace Botan_Tests {
49

50
namespace {
51

52
#if defined(BOTAN_CAN_RUN_TEST_TLS_RFC8448)
53

54
void add_entropy(Fixed_Output_RNG& rng, const std::vector<uint8_t>& bin) {
14✔
55
   rng.add_entropy(bin.data(), bin.size());
28✔
56
}
57

58
Botan::X509_Certificate server_certificate() {
4✔
59
   // self-signed certificate with an RSA1024 public key valid until:
60
   //   Jul 30 01:23:59 2026 GMT
61
   Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/server_certificate.pem"));
8✔
62
   return Botan::X509_Certificate(in);
4✔
63
}
4✔
64

65
Botan::X509_Certificate alternative_server_certificate() {
1✔
66
   // self-signed certificate with a P-256 public key valid until:
67
   //   Jul 30 01:24:00 2026 GMT
68
   //
69
   // This certificate is presented by the server in the "Client Authentication"
70
   // test case. Why the certificate differs in that case remains unclear.
71
   Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/server_certificate_client_auth.pem"));
2✔
72
   return Botan::X509_Certificate(in);
1✔
73
}
1✔
74

75
Botan::X509_Certificate client_certificate() {
2✔
76
   // self-signed certificate with an RSA1024 public key valid until:
77
   //   Jul 30 01:23:59 2026 GMT
78
   Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/client_certificate.pem"));
4✔
79
   return Botan::X509_Certificate(in);
2✔
80
}
2✔
81

82
std::unique_ptr<Botan::Private_Key> client_raw_public_key_pair() {
4✔
83
   // P-256 private key (independently generated)
84
   Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/client_raw_public_keypair.pem"));
8✔
85
   return Botan::PKCS8::load_key(in);
4✔
86
}
4✔
87

88
std::unique_ptr<Botan::Private_Key> server_raw_public_key_pair() {
4✔
89
   // P-256 private key (independently generated)
90
   Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/server_raw_public_keypair.pem"));
8✔
91
   return Botan::PKCS8::load_key(in);
4✔
92
}
4✔
93

94
/**
95
* Simple version of the Padding extension (RFC 7685) to reproduce the
96
* 2nd Client_Hello in RFC8448 Section 5 (HelloRetryRequest)
97
*/
98
class Padding final : public Botan::TLS::Extension {
99
   public:
100
      static Botan::TLS::Extension_Code static_type() {
101
         // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
102
         return Botan::TLS::Extension_Code(21);
103
      }
104

105
      Botan::TLS::Extension_Code type() const override { return static_type(); }
2✔
106

107
      explicit Padding(const size_t padding_bytes) : m_padding_bytes(padding_bytes) {}
2✔
108

109
      std::vector<uint8_t> serialize(Botan::TLS::Connection_Side /*whoami*/) const override {
5✔
110
         return std::vector<uint8_t>(m_padding_bytes, 0x00);
5✔
111
      }
112

113
      bool empty() const override { return m_padding_bytes == 0; }
8✔
114

115
   private:
116
      size_t m_padding_bytes;
117
};
118

119
using namespace Botan;
120
using namespace Botan::TLS;
121

122
std::chrono::system_clock::time_point from_milliseconds_since_epoch(uint64_t msecs) {
14✔
123
   const int64_t secs_since_epoch = msecs / 1000;
14✔
124
   const uint32_t additional_millis = msecs % 1000;
14✔
125

126
   BOTAN_ASSERT_NOMSG(secs_since_epoch <= std::numeric_limits<time_t>::max());
14✔
127
   return std::chrono::system_clock::from_time_t(static_cast<time_t>(secs_since_epoch)) +
14✔
128
          std::chrono::milliseconds(additional_millis);
14✔
129
}
130

131
using Modify_Exts_Fn =
132
   std::function<void(Botan::TLS::Extensions&, Botan::TLS::Connection_Side, Botan::TLS::Handshake_Type)>;
133

134
/**
135
 * We cannot actually reproduce the signatures stated in RFC 8448 as their
136
 * signature scheme is probabilistic and we're lacking the correct RNG
137
 * input. Hence, signatures are know beforehand and just reproduced by the
138
 * TLS callback when requested.
139
 */
140
struct MockSignature {
26✔
141
      std::vector<uint8_t> message_to_sign;
142
      std::vector<uint8_t> signature_to_produce;
143
};
144

145
/**
146
 * Subclass of the Botan::TLS::Callbacks instrumenting all available callbacks.
147
 * The invocation counts can be checked in the integration tests to make sure
148
 * all expected callbacks are hit. Furthermore collects the received application
149
 * data and sent record bytes for further inspection by the test cases.
150
 */
151
class Test_TLS_13_Callbacks : public Botan::TLS::Callbacks {
152
   public:
153
      Test_TLS_13_Callbacks(Modify_Exts_Fn modify_exts_cb,
14✔
154
                            std::vector<MockSignature> mock_signatures,
155
                            uint64_t timestamp) :
14✔
156
            session_activated_called(false),
14✔
157
            m_modify_exts(std::move(modify_exts_cb)),
14✔
158
            m_mock_signatures(std::move(mock_signatures)),
14✔
159
            m_timestamp(from_milliseconds_since_epoch(timestamp)) {}
14✔
160

161
      void tls_emit_data(std::span<const uint8_t> data) override {
48✔
162
         count_callback_invocation("tls_emit_data");
48✔
163
         send_buffer.insert(send_buffer.end(), data.begin(), data.end());
48✔
164
      }
48✔
165

166
      void tls_record_received(uint64_t seq_no, std::span<const uint8_t> data) override {
4✔
167
         count_callback_invocation("tls_record_received");
4✔
168
         received_seq_no = seq_no;
4✔
169
         receive_buffer.insert(receive_buffer.end(), data.begin(), data.end());
4✔
170
      }
4✔
171

172
      void tls_alert(Botan::TLS::Alert alert) override {
12✔
173
         count_callback_invocation("tls_alert");
12✔
174
         BOTAN_UNUSED(alert);
12✔
175
         // handle a tls alert received from the tls server
176
      }
12✔
177

178
      bool tls_peer_closed_connection() override {
12✔
179
         count_callback_invocation("tls_peer_closed_connection");
12✔
180
         // we want to handle the closure ourselves
181
         return false;
12✔
182
      }
183

184
      void tls_session_established(const Botan::TLS::Session_Summary& summary) override {
12✔
185
         if(const auto& psk_id = summary.external_psk_identity()) {
12✔
186
            negotiated_psk_identity = *psk_id;
2✔
187
         }
188
         count_callback_invocation("tls_session_established");
12✔
189
      }
12✔
190

191
      void tls_session_activated() override {
12✔
192
         count_callback_invocation("tls_session_activated");
12✔
193
         session_activated_called = true;
12✔
194
      }
12✔
195

196
      bool tls_should_persist_resumption_information(const Session& /*session*/) override {
2✔
197
         count_callback_invocation("tls_should_persist_resumption_information");
2✔
198
         return true;  // should always store the session
2✔
199
      }
200

201
      void tls_verify_cert_chain(const std::vector<Botan::X509_Certificate>& cert_chain,
5✔
202
                                 const std::vector<std::optional<Botan::OCSP::Response>>& /*ocsp*/,
203
                                 const std::vector<Botan::Certificate_Store*>& /*trusted*/,
204
                                 Botan::Usage_Type /*usage*/,
205
                                 std::string_view /*hostname*/,
206
                                 const Botan::TLS::Policy& /*policy*/) override {
207
         count_callback_invocation("tls_verify_cert_chain");
5✔
208
         certificate_chain = cert_chain;
5✔
209
      }
5✔
210

211
      void tls_verify_raw_public_key(const Public_Key& raw_pk,
2✔
212
                                     Usage_Type /*usage*/,
213
                                     std::string_view /*hostname*/,
214
                                     const TLS::Policy& /*policy*/) override {
215
         count_callback_invocation("tls_verify_raw_public_key");
2✔
216
         // TODO: is there a better way to copy a generic public key?
217
         raw_public_key = Botan::X509::load_key(raw_pk.subject_public_key());
2✔
218
      }
2✔
219

220
      std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const override {
×
221
         count_callback_invocation("tls_verify_cert_chain");
×
222
         return std::chrono::milliseconds(0);
×
223
      }
224

225
      std::vector<uint8_t> tls_provide_cert_status(const std::vector<X509_Certificate>& chain,
×
226
                                                   const Certificate_Status_Request& csr) override {
227
         count_callback_invocation("tls_provide_cert_status");
×
228
         return Callbacks::tls_provide_cert_status(chain, csr);
×
229
      }
230

231
      std::vector<uint8_t> tls_sign_message(const Private_Key& key,
7✔
232
                                            RandomNumberGenerator& rng,
233
                                            std::string_view padding,
234
                                            Signature_Format format,
235
                                            const std::vector<uint8_t>& msg) override {
236
         BOTAN_UNUSED(key, rng);
7✔
237
         count_callback_invocation("tls_sign_message");
7✔
238

239
         if(key.algo_name() == "RSA") {
7✔
240
            if(format != Signature_Format::Standard) {
4✔
241
               throw Test_Error("TLS implementation selected unexpected signature format for RSA");
×
242
            }
243

244
            if(padding != "PSS(SHA-256,MGF1,32)") {
8✔
245
               throw Test_Error("TLS implementation selected unexpected padding for RSA: " + std::string(padding));
×
246
            }
247
         } else if(key.algo_name() == "ECDSA") {
3✔
248
            if(format != Signature_Format::DerSequence) {
3✔
249
               throw Test_Error("TLS implementation selected unexpected signature format for ECDSA");
×
250
            }
251

252
            if(padding != "SHA-256") {
6✔
253
               throw Test_Error("TLS implementation selected unexpected padding for ECDSA: " + std::string(padding));
×
254
            }
255
         } else {
256
            throw Test_Error("TLS implementation trying to sign with unexpected algorithm (" + key.algo_name() + ")");
×
257
         }
258

259
         for(const auto& mock : m_mock_signatures) {
9✔
260
            if(mock.message_to_sign == msg) {
9✔
261
               return mock.signature_to_produce;
7✔
262
            }
263
         }
264

265
         throw Test_Error("TLS implementation produced an unexpected message to be signed: " + Botan::hex_encode(msg));
×
266
      }
×
267

268
      bool tls_verify_message(const Public_Key& key,
7✔
269
                              std::string_view padding,
270
                              Signature_Format format,
271
                              const std::vector<uint8_t>& msg,
272
                              const std::vector<uint8_t>& sig) override {
273
         count_callback_invocation("tls_verify_message");
7✔
274
         return Callbacks::tls_verify_message(key, padding, format, msg, sig);
7✔
275
      }
276

277
      std::unique_ptr<PK_Key_Agreement_Key> tls_generate_ephemeral_key(
15✔
278
         const std::variant<TLS::Group_Params, DL_Group>& group, RandomNumberGenerator& rng) override {
279
         count_callback_invocation("tls_generate_ephemeral_key");
15✔
280
         return Callbacks::tls_generate_ephemeral_key(group, rng);
15✔
281
      }
282

283
      secure_vector<uint8_t> tls_ephemeral_key_agreement(const std::variant<TLS::Group_Params, DL_Group>& group,
13✔
284
                                                         const PK_Key_Agreement_Key& private_key,
285
                                                         const std::vector<uint8_t>& public_value,
286
                                                         RandomNumberGenerator& rng,
287
                                                         const Policy& policy) override {
288
         count_callback_invocation("tls_ephemeral_key_agreement");
13✔
289
         return Callbacks::tls_ephemeral_key_agreement(group, private_key, public_value, rng, policy);
13✔
290
      }
291

292
      void tls_inspect_handshake_msg(const Handshake_Message& message) override {
102✔
293
         count_callback_invocation("tls_inspect_handshake_msg_" + message.type_string());
306✔
294

295
         try {
102✔
296
            auto serialized_message = message.serialize();
102✔
297

298
            serialized_messages.try_emplace(message.type_string())
102✔
299
               .first->second.emplace_back(std::move(serialized_message));
102✔
300
         } catch(const Not_Implemented&) {
102✔
301
            // TODO: Once the server implementation is finished, this crutch
302
            //       can likely be removed, as all message types will have a
303
            //       serialization method with actual business logic. :o)
304
         }
×
305

306
         return Callbacks::tls_inspect_handshake_msg(message);
102✔
307
      }
308

309
      std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos) override {
×
310
         count_callback_invocation("tls_server_choose_app_protocol");
×
311
         return Callbacks::tls_server_choose_app_protocol(client_protos);
×
312
      }
313

314
      void tls_modify_extensions(Botan::TLS::Extensions& exts,
33✔
315
                                 Botan::TLS::Connection_Side side,
316
                                 Botan::TLS::Handshake_Type which_message) override {
317
         count_callback_invocation(std::string("tls_modify_extensions_") + handshake_type_to_string(which_message));
99✔
318
         m_modify_exts(exts, side, which_message);
33✔
319
         Callbacks::tls_modify_extensions(exts, side, which_message);
33✔
320
      }
33✔
321

322
      void tls_examine_extensions(const Botan::TLS::Extensions& extn,
31✔
323
                                  Connection_Side which_side,
324
                                  Botan::TLS::Handshake_Type which_message) override {
325
         count_callback_invocation(std::string("tls_examine_extensions_") + handshake_type_to_string(which_message));
93✔
326
         return Callbacks::tls_examine_extensions(extn, which_side, which_message);
31✔
327
      }
328

329
      std::string tls_peer_network_identity() override {
×
330
         count_callback_invocation("tls_peer_network_identity");
×
331
         return Callbacks::tls_peer_network_identity();
×
332
      }
333

334
      std::chrono::system_clock::time_point tls_current_timestamp() override {
23✔
335
         count_callback_invocation("tls_current_timestamp");
23✔
336
         return m_timestamp;
23✔
337
      }
338

339
      std::vector<uint8_t> pull_send_buffer() { return std::exchange(send_buffer, std::vector<uint8_t>()); }
39✔
340

341
      std::vector<uint8_t> pull_receive_buffer() { return std::exchange(receive_buffer, std::vector<uint8_t>()); }
4✔
342

343
      uint64_t last_received_seq_no() const { return received_seq_no; }
4✔
344

345
      const std::map<std::string, unsigned int>& callback_invocations() const { return m_callback_invocations; }
60✔
346

347
      void reset_callback_invocation_counters() { m_callback_invocations.clear(); }
60✔
348

349
   private:
350
      void count_callback_invocation(const std::string& callback_name) const {
340✔
351
         if(!m_callback_invocations.contains(callback_name)) {
340✔
352
            m_callback_invocations[callback_name] = 0;
320✔
353
         }
354

355
         m_callback_invocations[callback_name]++;
340✔
356
      }
340✔
357

358
   public:
359
      bool session_activated_called;                           // NOLINT(*-non-private-member-variable*)
360
      std::vector<Botan::X509_Certificate> certificate_chain;  // NOLINT(*-non-private-member-variable*)
361
      std::unique_ptr<Botan::Public_Key> raw_public_key;       // NOLINT(*-non-private-member-variable*)
362
      std::string negotiated_psk_identity;                     // NOLINT(*-non-private-member-variable*)
363
      std::map<std::string, std::vector<std::vector<uint8_t>>>
364
         serialized_messages;  // NOLINT(*-non-private-member-variable*)
365

366
   private:
367
      std::vector<uint8_t> send_buffer;
368
      std::vector<uint8_t> receive_buffer;
369
      uint64_t received_seq_no = 0;
370
      Modify_Exts_Fn m_modify_exts;
371
      std::vector<MockSignature> m_mock_signatures;
372
      std::chrono::system_clock::time_point m_timestamp;
373

374
      mutable std::map<std::string, unsigned int> m_callback_invocations;
375
};
376

377
class Test_Credentials : public Botan::Credentials_Manager {
378
   public:
379
      explicit Test_Credentials(bool use_alternative_server_certificate, std::optional<ExternalPSK> external_psk) :
14✔
380
            m_alternative_server_certificate(use_alternative_server_certificate),
14✔
381
            m_external_psk(std::move(external_psk)) {
16✔
382
         Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/server_key.pem"));
28✔
383
         m_server_private_key.reset(Botan::PKCS8::load_key(in).release());
14✔
384

385
         // RFC 8448 does not actually provide these keys. Hence we generate one on the
386
         // fly as a stand-in. Instead of actually using it, the signatures generated
387
         // by this private key must be hard-coded in `Callbacks::sign_message()`; see
388
         // `MockSignature_Fn` for more details.
389
         auto rng = Test::new_rng(__func__);
14✔
390
         m_bogus_alternative_server_private_key.reset(create_private_key("ECDSA", *rng, "secp256r1").release());
14✔
391

392
         m_client_private_key.reset(create_private_key("RSA", *rng, "1024").release());
28✔
393
      }
28✔
394

395
      std::vector<Botan::X509_Certificate> cert_chain(const std::vector<std::string>& cert_key_types,
5✔
396
                                                      const std::vector<AlgorithmIdentifier>& cert_signature_schemes,
397
                                                      const std::string& type,
398
                                                      const std::string& context) override {
399
         BOTAN_UNUSED(cert_key_types, cert_signature_schemes, context);
5✔
400
         if(type == "tls-client") {
5✔
401
            return {client_certificate()};
2✔
402
         } else if(m_alternative_server_certificate) {
4✔
403
            return {alternative_server_certificate()};
2✔
404
         } else {
405
            return {server_certificate()};
6✔
406
         }
407
      }
5✔
408

409
      std::shared_ptr<Public_Key> find_raw_public_key(const std::vector<std::string>& key_types,
2✔
410
                                                      const std::string& type,
411
                                                      const std::string& context) override {
412
         BOTAN_UNUSED(key_types, type, context);
2✔
413
         return (type == "tls-client") ? client_raw_public_key_pair()->public_key()
4✔
414
                                       : server_raw_public_key_pair()->public_key();
5✔
415
      }
416

417
      std::shared_ptr<Botan::Private_Key> private_key_for(const Botan::X509_Certificate& cert,
5✔
418
                                                          const std::string& type,
419
                                                          const std::string& context) override {
420
         BOTAN_UNUSED(cert, context);
5✔
421

422
         if(type == "tls-client") {
5✔
423
            return m_client_private_key;
1✔
424
         }
425

426
         if(m_alternative_server_certificate) {
4✔
427
            return m_bogus_alternative_server_private_key;
1✔
428
         }
429

430
         return m_server_private_key;
3✔
431
      }
432

433
      std::shared_ptr<Botan::Private_Key> private_key_for(const Public_Key& raw_public_key,
2✔
434
                                                          const std::string& type,
435
                                                          const std::string& context) override {
436
         BOTAN_UNUSED(type, context);
2✔
437
         std::vector<std::unique_ptr<Botan::Private_Key>> keys;
2✔
438
         keys.emplace_back(client_raw_public_key_pair());
2✔
439
         keys.emplace_back(server_raw_public_key_pair());
2✔
440
         for(auto& key : keys) {
3✔
441
            if(key->fingerprint_public() == raw_public_key.fingerprint_public()) {
3✔
442
               return std::move(key);
2✔
443
            }
444
         }
445
         return nullptr;
×
446
      }
2✔
447

448
      std::vector<TLS::ExternalPSK> find_preshared_keys(std::string_view /* host */,
8✔
449
                                                        TLS::Connection_Side /* whoami */,
450
                                                        const std::vector<std::string>& identities,
451
                                                        const std::optional<std::string>& prf) override {
452
         if(!m_external_psk.has_value()) {
8✔
453
            return {};
6✔
454
         }
455

456
         ExternalPSK& epsk = m_external_psk.value();
2✔
457
         const auto found = std::find(identities.begin(), identities.end(), epsk.identity());
2✔
458
         if(!identities.empty() && found == identities.end()) {
2✔
459
            return {};
×
460
         }
461

462
         if(prf && prf != epsk.prf_algo()) {
2✔
463
            return {};
×
464
         }
465

466
         // ExternalPSK has a deleted copy constructor. We need to do some gymnastics
467
         // to copy it and leave the data in m_external_psk intact
468
         const auto secret = epsk.extract_master_secret();
2✔
469
         m_external_psk = ExternalPSK(epsk.identity(), epsk.prf_algo(), secret);
2✔
470
         std::vector<ExternalPSK> psks;
2✔
471
         psks.emplace_back(epsk.identity(), epsk.prf_algo(), secret);
2✔
472
         return psks;
2✔
473
      }
4✔
474

475
   private:
476
      bool m_alternative_server_certificate;
477
      std::optional<ExternalPSK> m_external_psk;
478
      std::shared_ptr<Private_Key> m_client_private_key;
479
      std::shared_ptr<Private_Key> m_bogus_alternative_server_private_key;
480
      std::shared_ptr<Private_Key> m_server_private_key;
481
};
482

483
class RFC8448_Text_Policy : public Botan::TLS::Text_Policy {
14✔
484
   private:
485
      Botan::TLS::Text_Policy read_policy(const std::string& policy_file) {
14✔
486
         const std::string fspath = Test::data_file("tls-policy/" + policy_file + ".txt");
42✔
487

488
         std::ifstream is(fspath.c_str());
14✔
489
         if(!is.good()) {
14✔
490
            throw Test_Error("Missing policy file " + fspath);
×
491
         }
492

493
         return Botan::TLS::Text_Policy(is);
14✔
494
      }
14✔
495

496
   public:
497
      explicit RFC8448_Text_Policy(const std::string& policy_file) :
14✔
498
            Botan::TLS::Text_Policy(read_policy(policy_file)) {}
14✔
499

500
      // Overriding the key exchange group selection to favour the server's key
501
      // exchange group preference. This is required to enforce a Hello Retry Request
502
      // when testing RFC 8448 5. from the server side.
503
      Named_Group choose_key_exchange_group(const std::vector<Group_Params>& supported_by_peer,
8✔
504
                                            const std::vector<Group_Params>& offered_by_peer) const override {
505
         BOTAN_UNUSED(offered_by_peer);
8✔
506

507
         const auto supported_by_us = key_exchange_groups();
8✔
508
         const auto selected_group =
8✔
509
            std::find_if(supported_by_us.begin(), supported_by_us.end(), [&](const auto group) {
8✔
510
               return value_exists(supported_by_peer, group);
16✔
511
            });
512

513
         return selected_group != supported_by_us.end() ? *selected_group : Named_Group::NONE;
8✔
514
      }
8✔
515
};
516

517
/**
518
 * In-Memory Session Manager that stores sessions verbatim, without encryption.
519
 * Therefor it is not dependent on a random number generator and can easily be
520
 * instrumented for test inspection.
521
 */
522
class RFC8448_Session_Manager : public Botan::TLS::Session_Manager {
523
   private:
524
      decltype(auto) find_by_handle(const Session_Handle& handle) {
3✔
525
         return [=](const Session_with_Handle& session) {
18✔
526
            if(session.handle.id().has_value() && handle.id().has_value() &&
4✔
527
               session.handle.id().value() == handle.id().value()) {
2✔
528
               return true;
529
            }
530
            if(session.handle.ticket().has_value() && handle.ticket().has_value() &&
10✔
531
               session.handle.ticket().value() == handle.ticket().value()) {
10✔
532
               return true;
533
            }
534
            return false;
535
         };
6✔
536
      }
537

538
   public:
539
      RFC8448_Session_Manager() : Session_Manager(std::make_shared<Botan::Null_RNG>()) {}
28✔
540

541
      const std::vector<Session_with_Handle>& all_sessions() const { return m_sessions; }
3✔
542

543
      void store(const Session& session, const Session_Handle& handle) override {
4✔
544
         m_sessions.push_back({session, handle});
4✔
545
      }
12✔
546

547
      std::optional<Session_Handle> establish(const Session& session,
1✔
548
                                              const std::optional<Session_ID>& /*session*/,
549
                                              bool /*no_ticket*/) override {
550
         // we assume that the 'mocked' session is already stored in the manager,
551
         // verify that it is equivalent to the one created by the testee and
552
         // return the associated handle stored with it
553

554
         if(m_sessions.size() != 1) {
1✔
555
            throw Test_Error("No mocked session handle available; Test bug?");
×
556
         }
557

558
         const auto& [mocked_session, handle] = m_sessions.front();
1✔
559
         if(mocked_session.master_secret() != session.master_secret()) {
1✔
560
            throw Test_Error("Generated session object does not match the expected mock");
×
561
         }
562

563
         return handle;
1✔
564
      }
565

566
      std::optional<Session> retrieve_one(const Session_Handle& handle) override {
2✔
567
         auto itr = std::find_if(m_sessions.begin(), m_sessions.end(), find_by_handle(handle));
2✔
568
         if(itr == m_sessions.end()) {
2✔
569
            return std::nullopt;
1✔
570
         } else {
571
            return itr->session;
1✔
572
         }
573
      }
574

575
      std::vector<Session_with_Handle> find_some(const Server_Information& info,
7✔
576
                                                 const size_t /*max_sessions_hint*/) override {
577
         std::vector<Session_with_Handle> found_sessions;
7✔
578
         for(const auto& [session, handle] : m_sessions) {
8✔
579
            if(session.server_info() == info) {
1✔
580
               found_sessions.emplace_back(Session_with_Handle{session, handle});
2✔
581
            }
582
         }
583

584
         return found_sessions;
7✔
585
      }
×
586

587
      size_t remove(const Session_Handle& handle) override { return std::erase_if(m_sessions, find_by_handle(handle)); }
2✔
588

589
      size_t remove_all() override {
×
590
         const auto sessions = m_sessions.size();
×
591
         m_sessions.clear();
×
592
         return sessions;
×
593
      }
594

595
   private:
596
      std::vector<Session_with_Handle> m_sessions;
597
};
598

599
/**
600
 * This steers the TLS client handle and is the central entry point for the
601
 * test cases to interact with the TLS 1.3 implementation.
602
 *
603
 * Note: This class is abstract to be subclassed for both client and server tests.
604
 */
605
class TLS_Context {
606
   protected:
607
      TLS_Context(std::shared_ptr<Botan::RandomNumberGenerator> rng_in,
14✔
608
                  std::shared_ptr<const RFC8448_Text_Policy> policy,
609
                  Modify_Exts_Fn modify_exts_cb,
610
                  std::vector<MockSignature> mock_signatures,
611
                  uint64_t timestamp,
612
                  std::optional<std::pair<Session, Session_Ticket>> session_and_ticket,
613
                  std::optional<ExternalPSK> external_psk,
614
                  bool use_alternative_server_certificate) :
14✔
615
            m_callbacks(std::make_shared<Test_TLS_13_Callbacks>(
14✔
616
               std::move(modify_exts_cb), std::move(mock_signatures), timestamp)),
617
            m_creds(std::make_shared<Test_Credentials>(use_alternative_server_certificate, std::move(external_psk))),
14✔
618
            m_rng(std::move(rng_in)),
14✔
619
            m_session_mgr(std::make_shared<RFC8448_Session_Manager>()),
620
            m_policy(std::move(policy)) {
28✔
621
         if(session_and_ticket.has_value()) {
14✔
622
            m_session_mgr->store(std::get<Session>(session_and_ticket.value()),
6✔
623
                                 Botan::TLS::Session_Handle(std::get<Session_Ticket>(session_and_ticket.value())));
9✔
624
         }
625
      }
14✔
626

627
   public:
628
      virtual ~TLS_Context() = default;
70✔
629

630
      TLS_Context(TLS_Context&) = delete;
631
      TLS_Context& operator=(const TLS_Context&) = delete;
632

633
      TLS_Context(TLS_Context&&) = delete;
634
      TLS_Context& operator=(TLS_Context&&) = delete;
635

636
      std::vector<uint8_t> pull_send_buffer() { return m_callbacks->pull_send_buffer(); }
39✔
637

638
      std::vector<uint8_t> pull_receive_buffer() { return m_callbacks->pull_receive_buffer(); }
4✔
639

640
      uint64_t last_received_seq_no() const { return m_callbacks->last_received_seq_no(); }
4✔
641

642
      /**
643
       * Checks that all of the listed callbacks were called at least once, no other
644
       * callbacks were called in addition to the expected ones. After the checks are
645
       * done, the callback invocation counters are reset.
646
       */
647
      void check_callback_invocations(Test::Result& result,
60✔
648
                                      const std::string& context,
649
                                      const std::vector<std::string>& callback_names) {
650
         const auto& invokes = m_callbacks->callback_invocations();
60✔
651
         for(const auto& cbn : callback_names) {
371✔
652
            result.test_is_true(Botan::fmt("{} was invoked (Context: {})", cbn, context),
933✔
653
                                invokes.contains(cbn) && invokes.at(cbn) > 0);
311✔
654
         }
655

656
         for(const auto& invoke : invokes) {
371✔
657
            if(invoke.second == 0) {
311✔
658
               continue;
×
659
            }
660
            result.test_is_true(
622✔
661
               invoke.first + " was expected (Context: " + context + ")",
1,244✔
662
               std::find(callback_names.cbegin(), callback_names.cend(), invoke.first) != callback_names.cend());
622✔
663
         }
664

665
         m_callbacks->reset_callback_invocation_counters();
60✔
666
      }
60✔
667

668
      const std::vector<Session_with_Handle>& stored_sessions() const { return m_session_mgr->all_sessions(); }
3✔
669

670
      const std::vector<Botan::X509_Certificate>& certs_verified() const { return m_callbacks->certificate_chain; }
2✔
671

672
      const std::string& psk_identity_negotiated() const { return m_callbacks->negotiated_psk_identity; }
2✔
673

674
      decltype(auto) observed_handshake_messages() const { return m_callbacks->serialized_messages; }
7✔
675

676
      /**
677
       * Send application data through the secure channel
678
       */
679
      virtual void send(const std::vector<uint8_t>& data) = 0;
680

681
   protected:
682
      std::shared_ptr<Test_TLS_13_Callbacks> m_callbacks;  // NOLINT(*-non-private-member-variable*)
683
      std::shared_ptr<Test_Credentials> m_creds;           // NOLINT(*-non-private-member-variable*)
684

685
      std::shared_ptr<Botan::RandomNumberGenerator> m_rng;     // NOLINT(*-non-private-member-variable*)
686
      std::shared_ptr<RFC8448_Session_Manager> m_session_mgr;  // NOLINT(*-non-private-member-variable*)
687
      std::shared_ptr<const RFC8448_Text_Policy> m_policy;     // NOLINT(*-non-private-member-variable*)
688
};
689

690
class Client_Context : public TLS_Context {
691
   public:
692
      Client_Context(std::shared_ptr<Botan::RandomNumberGenerator> rng_in,
7✔
693
                     std::shared_ptr<const RFC8448_Text_Policy> policy,
694
                     uint64_t timestamp,
695
                     Modify_Exts_Fn modify_exts_cb,
696
                     std::optional<std::pair<Session, Session_Ticket>> session_and_ticket = std::nullopt,
697
                     std::optional<ExternalPSK> external_psk = std::nullopt,
698
                     std::vector<MockSignature> mock_signatures = {}) :
7✔
699
            TLS_Context(std::move(rng_in),
700
                        std::move(policy),
701
                        std::move(modify_exts_cb),
702
                        std::move(mock_signatures),
703
                        timestamp,
704
                        std::move(session_and_ticket),
705
                        std::move(external_psk),
706
                        false),
707
            client(m_callbacks,
35✔
708
                   m_session_mgr,
7✔
709
                   m_creds,
7✔
710
                   m_policy,
7✔
711
                   m_rng,
7✔
712
                   Botan::TLS::Server_Information("server"),
14✔
713
                   Botan::TLS::Protocol_Version::TLS_V13) {}
30✔
714

715
      void send(const std::vector<uint8_t>& data) override { client.send(data.data(), data.size()); }
2✔
716

717
      Botan::TLS::Client client;  // NOLINT(*-non-private-member-variable*)
718
};
719

720
class Server_Context : public TLS_Context {
721
   public:
722
      Server_Context(std::shared_ptr<Botan::RandomNumberGenerator> rng,
7✔
723
                     std::shared_ptr<const RFC8448_Text_Policy> policy,
724
                     uint64_t timestamp,
725
                     Modify_Exts_Fn modify_exts_cb,
726
                     std::vector<MockSignature> mock_signatures,
727
                     bool use_alternative_server_certificate = false,
728
                     std::optional<std::pair<Session, Session_Ticket>> session_and_ticket = std::nullopt,
729
                     std::optional<ExternalPSK> external_psk = std::nullopt) :
7✔
730
            TLS_Context(std::move(rng),
731
                        std::move(policy),
732
                        std::move(modify_exts_cb),
733
                        std::move(mock_signatures),
734
                        timestamp,
735
                        std::move(session_and_ticket),
736
                        std::move(external_psk),
737
                        use_alternative_server_certificate),
738
            server(m_callbacks, m_session_mgr, m_creds, m_policy, m_rng, false /* DTLS NYI */) {}
51✔
739

740
      void send(const std::vector<uint8_t>& data) override { server.send(data.data(), data.size()); }
2✔
741

742
      Botan::TLS::Server server;  // NOLINT(*-non-private-member-variable*)
743
};
744

745
/**
746
 * Because of the nature of the RFC 8448 test data we need to produce bit-compatible
747
 * TLS messages. Hence we sort the generated TLS extensions exactly as expected.
748
 */
749
void sort_rfc8448_extensions(Botan::TLS::Extensions& exts,
23✔
750
                             Botan::TLS::Connection_Side side,
751
                             Botan::TLS::Handshake_Type /*type*/ = Botan::TLS::Handshake_Type::ClientHello) {
752
   if(side == Botan::TLS::Connection_Side::Client) {
23✔
753
      exts.reorder(std::array{
6✔
754
         Botan::TLS::Extension_Code::ServerNameIndication,
755
         Botan::TLS::Extension_Code::SafeRenegotiation,
756
         Botan::TLS::Extension_Code::SupportedGroups,
757
         Botan::TLS::Extension_Code::SessionTicket,
758
         Botan::TLS::Extension_Code::KeyShare,
759
         Botan::TLS::Extension_Code::EarlyData,
760
         Botan::TLS::Extension_Code::SupportedVersions,
761
         Botan::TLS::Extension_Code::SignatureAlgorithms,
762
         Botan::TLS::Extension_Code::Cookie,
763
         Botan::TLS::Extension_Code::PskKeyExchangeModes,
764
         Botan::TLS::Extension_Code::RecordSizeLimit,
765
         Padding::static_type(),
766
         Botan::TLS::Extension_Code::PresharedKey,
767
      });
768
   } else {
769
      exts.reorder(std::array{
17✔
770
         Botan::TLS::Extension_Code::SupportedGroups,
771
         Botan::TLS::Extension_Code::KeyShare,
772
         Botan::TLS::Extension_Code::Cookie,
773
         Botan::TLS::Extension_Code::SupportedVersions,
774
         Botan::TLS::Extension_Code::SignatureAlgorithms,
775
         Botan::TLS::Extension_Code::RecordSizeLimit,
776
         Botan::TLS::Extension_Code::ServerNameIndication,
777
         Botan::TLS::Extension_Code::EarlyData,
778
      });
779
   }
780
}
23✔
781

782
void add_renegotiation_extension(Botan::TLS::Extensions& exts) {
5✔
783
   // Renegotiation is not possible in TLS 1.3. Nevertheless, RFC 8448 requires
784
   // to add this to the Client Hello for reasons.
785
   exts.add(new Renegotiation_Extension());  // NOLINT(*-owning-memory)
5✔
786
}
5✔
787

788
void add_early_data_indication(Botan::TLS::Extensions& exts) {
1✔
789
   exts.add(new Botan::TLS::EarlyDataIndication());  // NOLINT(*-owning-memory)
1✔
790
}
1✔
791

792
std::vector<uint8_t> strip_message_header(const std::vector<uint8_t>& msg) {
31✔
793
   BOTAN_ASSERT_NOMSG(msg.size() >= 4);
31✔
794
   return {msg.begin() + 4, msg.end()};
31✔
795
}
796

797
std::vector<MockSignature> make_mock_signatures(const VarMap& vars) {
9✔
798
   std::vector<MockSignature> result;
9✔
799

800
   auto mock = [&](const std::string& msg, const std::string& sig) {
27✔
801
      if(vars.has_key(msg) && vars.has_key(sig)) {
18✔
802
         result.push_back({vars.get_opt_bin(msg), vars.get_opt_bin(sig)});
22✔
803
      }
804
   };
29✔
805

806
   mock("Server_MessageToSign", "Server_MessageSignature");
18✔
807
   mock("Client_MessageToSign", "Client_MessageSignature");
18✔
808

809
   return result;
9✔
810
}
×
811

812
/**
813
 * Traffic transcripts and supporting data for the TLS RFC 8448 and TLS policy
814
 * configuration is kept in data files (accessible via `Test:::data_file()`).
815
 *
816
 * tls_13_rfc8448/transcripts.vec
817
 *   The record transcripts and RNG outputs as defined/required in RFC 8448 in
818
 *   Botan's Text_Based_Test vector format. Data from each RFC 8448 section is
819
 *   placed in a sub-section of the *.vec file. Each of those sections needs a
820
 *   specific test case implementation that is dispatched in `run_one_test()`.
821
 *
822
 * tls_13_rfc8448/client_certificate.pem
823
 *   The client certificate provided in RFC 8448 used to perform client auth.
824
 *   Note that RFC 8448 _does not_ provide the associated private key but only
825
 *   the resulting signature in the client's CertificateVerify message.
826
 *
827
 * tls_13_rfc8448/server_certificate.pem
828
 * tls_13_rfc8448/server_key.pem
829
 *   The server certificate and its associated private key.
830
 *
831
 * tls_13_rfc8448/server_certificate_client_auth.pem
832
 *   The server certificate used in the Client Authentication test case.
833
 *
834
 * tls_13_rfc8448/client_raw_public_keypair.pem
835
 * tls_13_rfc8448/server_raw_public_keypair.pem
836
 *   The raw public key pairs for client and server authentication in the
837
 *   equally named test cases.
838
 *
839
 * tls-policy/rfc8448_*.txt
840
 *   Each RFC 8448 section test required a slightly adapted Botan TLS policy
841
 *   to enable/disable certain features under test.
842
 *
843
 * While the test cases are split into Client-side and Server-side tests, the
844
 * transcript data is reused. See the concrete implementations of the abstract
845
 * Test_TLS_RFC8448 test class.
846
 */
847
class Test_TLS_RFC8448 : public Text_Based_Test {
×
848
   protected:
849
      // Those tests are based on the test vectors in RFC8448.
850
      virtual std::vector<Test::Result> simple_1_rtt(const VarMap& vars) = 0;
851
      virtual std::vector<Test::Result> resumed_handshake_with_0_rtt(const VarMap& vars) = 0;
852
      virtual std::vector<Test::Result> hello_retry_request(const VarMap& vars) = 0;
853
      virtual std::vector<Test::Result> client_authentication(const VarMap& vars) = 0;
854
      virtual std::vector<Test::Result> middlebox_compatibility(const VarMap& vars) = 0;
855

856
      // Those tests provide the same information as RFC8448 test vectors but
857
      // were sourced otherwise. Typically by temporarily instrumenting our implementation.
858
      virtual std::vector<Test::Result> externally_provided_psk_with_ephemeral_key(const VarMap& vars) = 0;
859
      virtual std::vector<Test::Result> raw_public_key_with_client_authentication(const VarMap& vars) = 0;
860

861
      virtual std::string side() const = 0;
862

863
   public:
864
      Test_TLS_RFC8448() :
2✔
865
            Text_Based_Test("tls_13_rfc8448/transcripts.vec",
866
                            // mandatory data fields
867
                            "Client_RNG_Pool,"
868
                            "Server_RNG_Pool,"
869
                            "CurrentTimestamp,"
870
                            "Record_ClientHello_1,"
871
                            "Record_ServerHello,"
872
                            "Record_ServerHandshakeMessages,"
873
                            "Record_ClientFinished,"
874
                            "Record_Client_CloseNotify,"
875
                            "Record_Server_CloseNotify",
876
                            // optional data fields
877
                            "Message_ServerHello,"
878
                            "Message_EncryptedExtensions,"
879
                            "Message_CertificateRequest,"
880
                            "Message_Server_Certificate,"
881
                            "Message_Server_CertificateVerify,"
882
                            "Message_Server_Finished,"
883
                            "Record_HelloRetryRequest,"
884
                            "Record_ClientHello_2,"
885
                            "Record_NewSessionTicket,"
886
                            "Client_AppData,"
887
                            "Record_Client_AppData,"
888
                            "Server_AppData,"
889
                            "Record_Server_AppData,"
890
                            "Client_EarlyAppData,"
891
                            "Record_Client_EarlyAppData,"
892
                            "SessionTicket,"
893
                            "Client_SessionData,"
894
                            "Server_MessageToSign,"
895
                            "Server_MessageSignature,"
896
                            "Client_MessageToSign,"
897
                            "Client_MessageSignature,"
898
                            "HelloRetryRequest_Cookie,"
899
                            "PskIdentity,"
900
                            "PskPRF,"
901
                            "PskSecret") {}
4✔
902

903
      Test::Result run_one_test(const std::string& header, const VarMap& vars) override {
14✔
904
         if(header == "Simple_1RTT_Handshake") {
14✔
905
            return Test::Result("Simple 1-RTT (" + side() + " side)", simple_1_rtt(vars));
8✔
906
         } else if(header == "Resumed_0RTT_Handshake") {
12✔
907
            return Test::Result("Resumption with 0-RTT data (" + side() + " side)", resumed_handshake_with_0_rtt(vars));
8✔
908
         } else if(header == "HelloRetryRequest_Handshake") {
10✔
909
            return Test::Result("Handshake involving Hello Retry Request (" + side() + " side)",
8✔
910
                                hello_retry_request(vars));
6✔
911
         } else if(header == "Client_Authentication_Handshake") {
8✔
912
            return Test::Result("Client Authentication (" + side() + " side)", client_authentication(vars));
8✔
913
         } else if(header == "Middlebox_Compatibility_Mode") {
6✔
914
            return Test::Result("Middlebox Compatibility Mode (" + side() + " side)", middlebox_compatibility(vars));
8✔
915
         } else if(header == "Externally_Provided_PSK_with_Ephemeral_Key") {
4✔
916
            return Test::Result("Externally Provided PSK with ephemeral key (" + side() + " side)",
8✔
917
                                externally_provided_psk_with_ephemeral_key(vars));
6✔
918
         } else if(header == "RawPublicKey_With_Client_Authentication") {
2✔
919
            return Test::Result("RawPublicKey with Client Authentication (" + side() + " side)",
8✔
920
                                raw_public_key_with_client_authentication(vars));
6✔
921
         } else {
922
            return Test::Result::Failure("test dispatcher", "unknown sub-test: " + header);
×
923
         }
924
      }
925
};
926

927
class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 {
1✔
928
   private:
929
      std::string side() const override { return "Client"; }
7✔
930

931
      std::vector<Test::Result> simple_1_rtt(const VarMap& vars) override {
1✔
932
         auto rng = std::make_shared<Fixed_Output_RNG>("");
1✔
933

934
         // 32 - for client hello random
935
         // 32 - for KeyShare (eph. x25519 key pair)
936
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
1✔
937

938
         auto add_extensions_and_sort = [](Botan::TLS::Extensions& exts,
2✔
939
                                           Botan::TLS::Connection_Side side,
940
                                           Botan::TLS::Handshake_Type which_message) {
941
            if(which_message == Handshake_Type::ClientHello) {
1✔
942
               // For some reason, presumably checking compatibility, the RFC 8448 Client
943
               // Hello includes a (TLS 1.2) Session_Ticket extension. We don't normally add
944
               // this obsoleted extension in a TLS 1.3 client.
945
               exts.add(new Botan::TLS::Session_Ticket_Extension());  // NOLINT(*-owning-memory)
1✔
946

947
               add_renegotiation_extension(exts);
1✔
948
               sort_rfc8448_extensions(exts, side);
1✔
949
            }
950
         };
1✔
951

952
         std::unique_ptr<Client_Context> ctx;
1✔
953

954
         return {
1✔
955
            CHECK("Client Hello",
956
                  [&](Test::Result& result) {
1✔
957
                     ctx = std::make_unique<Client_Context>(rng,
1✔
958
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
1✔
959
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
960
                                                            add_extensions_and_sort);
1✔
961

962
                     result.test_is_true("client not closed", !ctx->client.is_closed());
1✔
963
                     ctx->check_callback_invocations(result,
2✔
964
                                                     "client hello prepared",
965
                                                     {
966
                                                        "tls_emit_data",
967
                                                        "tls_inspect_handshake_msg_client_hello",
968
                                                        "tls_modify_extensions_client_hello",
969
                                                        "tls_generate_ephemeral_key",
970
                                                        "tls_current_timestamp",
971
                                                     });
972

973
                     result.test_bin_eq(
1✔
974
                        "TLS client hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
1✔
975
                  }),
1✔
976

977
            CHECK("Server Hello",
978
                  [&](Test::Result& result) {
1✔
979
                     result.require("ctx is available", ctx != nullptr);
1✔
980
                     const auto server_hello = vars.get_req_bin("Record_ServerHello");
1✔
981
                     // splitting the input data to test partial reads
982
                     const std::vector<uint8_t> server_hello_a(server_hello.begin(), server_hello.begin() + 20);
1✔
983
                     const std::vector<uint8_t> server_hello_b(server_hello.begin() + 20, server_hello.end());
1✔
984

985
                     ctx->client.received_data(server_hello_a);
1✔
986
                     ctx->check_callback_invocations(result, "server hello partially received", {});
2✔
987

988
                     ctx->client.received_data(server_hello_b);
1✔
989
                     ctx->check_callback_invocations(result,
2✔
990
                                                     "server hello received",
991
                                                     {"tls_inspect_handshake_msg_server_hello",
992
                                                      "tls_examine_extensions_server_hello",
993
                                                      "tls_ephemeral_key_agreement"});
994

995
                     result.test_is_true("client is not yet active", !ctx->client.is_active());
1✔
996
                     result.test_is_true("handshake is not yet complete", !ctx->client.is_handshake_complete());
1✔
997
                  }),
1✔
998

999
            CHECK("Server HS messages .. Client Finished",
1000
                  [&](Test::Result& result) {
1✔
1001
                     result.require("ctx is available", ctx != nullptr);
1✔
1002
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
1✔
1003

1004
                     ctx->check_callback_invocations(result,
2✔
1005
                                                     "encrypted handshake messages received",
1006
                                                     {"tls_inspect_handshake_msg_encrypted_extensions",
1007
                                                      "tls_inspect_handshake_msg_certificate",
1008
                                                      "tls_inspect_handshake_msg_certificate_verify",
1009
                                                      "tls_inspect_handshake_msg_finished",
1010
                                                      "tls_examine_extensions_encrypted_extensions",
1011
                                                      "tls_examine_extensions_certificate",
1012
                                                      "tls_emit_data",
1013
                                                      "tls_current_timestamp",
1014
                                                      "tls_session_established",
1015
                                                      "tls_session_activated",
1016
                                                      "tls_verify_cert_chain",
1017
                                                      "tls_verify_message"});
1018
                     result.require("certificate exists", !ctx->certs_verified().empty());
1✔
1019
                     result.require("correct certificate", ctx->certs_verified().front() == server_certificate());
1✔
1020
                     result.require("client is active", ctx->client.is_active());
1✔
1021
                     result.test_is_true("handshake is complete", ctx->client.is_handshake_complete());
1✔
1022

1023
                     result.test_bin_eq("correct handshake finished",
1✔
1024
                                        ctx->pull_send_buffer(),
1✔
1025
                                        vars.get_req_bin("Record_ClientFinished"));
2✔
1026
                  }),
1✔
1027

1028
            CHECK("Post-Handshake: NewSessionTicket",
1029
                  [&](Test::Result& result) {
1✔
1030
                     result.require("ctx is available", ctx != nullptr);
1✔
1031
                     result.require("no sessions so far", ctx->stored_sessions().empty());
1✔
1032
                     ctx->client.received_data(vars.get_req_bin("Record_NewSessionTicket"));
1✔
1033

1034
                     ctx->check_callback_invocations(result,
2✔
1035
                                                     "new session ticket received",
1036
                                                     {"tls_examine_extensions_new_session_ticket",
1037
                                                      "tls_should_persist_resumption_information",
1038
                                                      "tls_current_timestamp"});
1039
                     if(result.test_sz_eq("session was stored", ctx->stored_sessions().size(), 1)) {
1✔
1040
                        const auto& [stored_session, stored_handle] = ctx->stored_sessions().front();
1✔
1041
                        result.require("session handle contains a ticket", stored_handle.ticket().has_value());
1✔
1042
                        result.test_bin_eq("session was serialized as expected",
1✔
1043
                                           stored_session.DER_encode(),
1✔
1044
                                           vars.get_req_bin("Client_SessionData"));
2✔
1045
                     }
1046
                  }),
1✔
1047

1048
            CHECK("Send Application Data",
1049
                  [&](Test::Result& result) {
1✔
1050
                     result.require("ctx is available", ctx != nullptr);
1✔
1051
                     ctx->send(vars.get_req_bin("Client_AppData"));
2✔
1052

1053
                     ctx->check_callback_invocations(result, "application data sent", {"tls_emit_data"});
2✔
1054

1055
                     result.test_bin_eq("correct client application data",
1✔
1056
                                        ctx->pull_send_buffer(),
1✔
1057
                                        vars.get_req_bin("Record_Client_AppData"));
2✔
1058
                  }),
1✔
1059

1060
            CHECK("Receive Application Data",
1061
                  [&](Test::Result& result) {
1✔
1062
                     result.require("ctx is available", ctx != nullptr);
1✔
1063
                     ctx->client.received_data(vars.get_req_bin("Record_Server_AppData"));
1✔
1064

1065
                     ctx->check_callback_invocations(result, "application data sent", {"tls_record_received"});
2✔
1066

1067
                     const auto rcvd = ctx->pull_receive_buffer();
1✔
1068
                     result.test_bin_eq("decrypted application traffic", rcvd, vars.get_req_bin("Server_AppData"));
1✔
1069
                     result.test_u64_eq("sequence number", ctx->last_received_seq_no(), uint64_t(1));
1✔
1070
                  }),
1✔
1071

1072
            CHECK("Close Connection",
1073
                  [&](Test::Result& result) {
1✔
1074
                     result.require("ctx is available", ctx != nullptr);
1✔
1075
                     ctx->client.close();
1✔
1076

1077
                     result.test_bin_eq(
1✔
1078
                        "close payload", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
1✔
1079
                     ctx->check_callback_invocations(result, "CLOSE_NOTIFY sent", {"tls_emit_data"});
2✔
1080

1081
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
1✔
1082
                     ctx->check_callback_invocations(
2✔
1083
                        result, "CLOSE_NOTIFY received", {"tls_alert", "tls_peer_closed_connection"});
1084

1085
                     result.test_is_true("connection is closed", ctx->client.is_closed());
1✔
1086
                  }),
1✔
1087
         };
8✔
1088
      }
3✔
1089

1090
      std::vector<Test::Result> resumed_handshake_with_0_rtt(const VarMap& vars) override {
1✔
1091
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
1092

1093
         // 32 - for client hello random
1094
         // 32 - for KeyShare (eph. x25519 key pair)
1095
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
1✔
1096

1097
         auto add_extensions_and_sort = [](Botan::TLS::Extensions& exts,
2✔
1098
                                           Botan::TLS::Connection_Side side,
1099
                                           Botan::TLS::Handshake_Type which_message) {
1100
            if(which_message == Handshake_Type::ClientHello) {
1✔
1101
               exts.add(new Padding(87));  // NOLINT(*-owning-memory)
1✔
1102

1103
               add_renegotiation_extension(exts);
1✔
1104

1105
               // TODO: Implement early data support and remove this 'hack'.
1106
               //
1107
               // Currently, the production implementation will never add this
1108
               // extension even if the resumed session would allow early data.
1109
               add_early_data_indication(exts);
1✔
1110
               sort_rfc8448_extensions(exts, side);
1✔
1111
            }
1112
         };
1✔
1113

1114
         std::unique_ptr<Client_Context> ctx;
1✔
1115

1116
         return {
1✔
1117
            CHECK("Client Hello",
1118
                  [&](Test::Result& result) {
1✔
1119
                     ctx = std::make_unique<Client_Context>(
1✔
1120
                        std::move(rng),
1121
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
1✔
1122
                        vars.get_req_u64("CurrentTimestamp"),
2✔
1123
                        add_extensions_and_sort,
1124
                        std::pair{Botan::TLS::Session(vars.get_req_bin("Client_SessionData")),
4✔
1125
                                  Botan::TLS::Session_Ticket(vars.get_req_bin("SessionTicket"))});
3✔
1126

1127
                     result.test_is_true("client not closed", !ctx->client.is_closed());
1✔
1128
                     ctx->check_callback_invocations(result,
2✔
1129
                                                     "client hello prepared",
1130
                                                     {
1131
                                                        "tls_emit_data",
1132
                                                        "tls_inspect_handshake_msg_client_hello",
1133
                                                        "tls_modify_extensions_client_hello",
1134
                                                        "tls_current_timestamp",
1135
                                                        "tls_generate_ephemeral_key",
1136
                                                     });
1137

1138
                     result.test_bin_eq(
1✔
1139
                        "TLS client hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
1✔
1140
                  })
1✔
1141

1142
            // TODO: The rest of this test vector requires 0-RTT which is not
1143
            //       yet implemented. For now we can only test the client's
1144
            //       ability to offer a session resumption via PSK.
1145
         };
2✔
1146
      }
2✔
1147

1148
      std::vector<Test::Result> hello_retry_request(const VarMap& vars) override {
1✔
1149
         auto add_extensions_and_sort = [flights = 0](Botan::TLS::Extensions& exts,
3✔
1150
                                                      Botan::TLS::Connection_Side side,
1151
                                                      Botan::TLS::Handshake_Type which_message) mutable {
1152
            if(which_message == Handshake_Type::ClientHello) {
2✔
1153
               ++flights;
2✔
1154

1155
               if(flights == 1) {
2✔
1156
                  add_renegotiation_extension(exts);
1✔
1157
               }
1158

1159
               // For some reason RFC8448 decided to require this (fairly obscure) extension
1160
               // in the second flight of the Client_Hello.
1161
               if(flights == 2) {
2✔
1162
                  exts.add(new Padding(175));  // NOLINT(*-owning-memory)
1✔
1163
               }
1164

1165
               sort_rfc8448_extensions(exts, side);
2✔
1166
            }
1167
         };
2✔
1168

1169
         // Fallback RNG is required to for blinding in ECDH with P-256
1170
         auto& fallback_rng = this->rng();
1✔
1171
         auto rng = std::make_unique<Fixed_Output_RNG>(fallback_rng);
1✔
1172

1173
         // 32 - client hello random
1174
         // 32 - eph. x25519 key pair
1175
         // 32 - eph. P-256 key pair
1176
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
1✔
1177

1178
         std::unique_ptr<Client_Context> ctx;
1✔
1179

1180
         return {
1✔
1181
            CHECK("Client Hello",
1182
                  [&](Test::Result& result) {
1✔
1183
                     ctx = std::make_unique<Client_Context>(std::move(rng),
1✔
1184
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_hrr_client"),
1✔
1185
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
1186
                                                            add_extensions_and_sort);
1✔
1187
                     result.test_is_true("client not closed", !ctx->client.is_closed());
1✔
1188

1189
                     ctx->check_callback_invocations(result,
2✔
1190
                                                     "client hello prepared",
1191
                                                     {
1192
                                                        "tls_emit_data",
1193
                                                        "tls_inspect_handshake_msg_client_hello",
1194
                                                        "tls_modify_extensions_client_hello",
1195
                                                        "tls_generate_ephemeral_key",
1196
                                                        "tls_current_timestamp",
1197
                                                     });
1198

1199
                     result.test_bin_eq(
1✔
1200
                        "TLS client hello (1)", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
1✔
1201
                  }),
1✔
1202

1203
            CHECK("Hello Retry Request .. second Client Hello",
1204
                  [&](Test::Result& result) {
1✔
1205
                     result.require("ctx is available", ctx != nullptr);
1✔
1206
                     ctx->client.received_data(vars.get_req_bin("Record_HelloRetryRequest"));
1✔
1207

1208
                     ctx->check_callback_invocations(result,
2✔
1209
                                                     "hello retry request received",
1210
                                                     {
1211
                                                        "tls_emit_data",
1212
                                                        "tls_inspect_handshake_msg_hello_retry_request",
1213
                                                        "tls_examine_extensions_hello_retry_request",
1214
                                                        "tls_inspect_handshake_msg_client_hello",
1215
                                                        "tls_modify_extensions_client_hello",
1216
                                                        "tls_generate_ephemeral_key",
1217
                                                     });
1218

1219
                     result.test_bin_eq(
1✔
1220
                        "TLS client hello (2)", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_2"));
1✔
1221
                  }),
1✔
1222

1223
            CHECK("Server Hello",
1224
                  [&](Test::Result& result) {
1✔
1225
                     result.require("ctx is available", ctx != nullptr);
1✔
1226
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHello"));
1✔
1227

1228
                     ctx->check_callback_invocations(result,
2✔
1229
                                                     "server hello received",
1230
                                                     {
1231
                                                        "tls_inspect_handshake_msg_server_hello",
1232
                                                        "tls_examine_extensions_server_hello",
1233
                                                        "tls_ephemeral_key_agreement",
1234
                                                     });
1235
                  }),
1✔
1236

1237
            CHECK("Server HS Messages .. Client Finished",
1238
                  [&](Test::Result& result) {
1✔
1239
                     result.require("ctx is available", ctx != nullptr);
1✔
1240
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
1✔
1241

1242
                     ctx->check_callback_invocations(result,
2✔
1243
                                                     "encrypted handshake messages received",
1244
                                                     {"tls_inspect_handshake_msg_encrypted_extensions",
1245
                                                      "tls_inspect_handshake_msg_certificate",
1246
                                                      "tls_inspect_handshake_msg_certificate_verify",
1247
                                                      "tls_inspect_handshake_msg_finished",
1248
                                                      "tls_examine_extensions_encrypted_extensions",
1249
                                                      "tls_examine_extensions_certificate",
1250
                                                      "tls_emit_data",
1251
                                                      "tls_current_timestamp",
1252
                                                      "tls_session_established",
1253
                                                      "tls_session_activated",
1254
                                                      "tls_verify_cert_chain",
1255
                                                      "tls_verify_message"});
1256

1257
                     result.test_bin_eq(
1✔
1258
                        "client finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished"));
1✔
1259
                  }),
1✔
1260

1261
            CHECK("Close Connection",
1262
                  [&](Test::Result& result) {
1✔
1263
                     result.require("ctx is available", ctx != nullptr);
1✔
1264
                     ctx->client.close();
1✔
1265
                     ctx->check_callback_invocations(
2✔
1266
                        result, "encrypted handshake messages received", {"tls_emit_data"});
1267
                     result.test_bin_eq(
1✔
1268
                        "client close notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
1✔
1269

1270
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
1✔
1271
                     ctx->check_callback_invocations(
2✔
1272
                        result, "encrypted handshake messages received", {"tls_alert", "tls_peer_closed_connection"});
1273

1274
                     result.test_is_true("connection is closed", ctx->client.is_closed());
1✔
1275
                  }),
1✔
1276
         };
6✔
1277
      }
2✔
1278

1279
      std::vector<Test::Result> client_authentication(const VarMap& vars) override {
1✔
1280
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
1281

1282
         // 32 - for client hello random
1283
         // 32 - for eph. x25519 key pair
1284
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
1✔
1285

1286
         auto add_extensions_and_sort = [&](Botan::TLS::Extensions& exts,
3✔
1287
                                            Botan::TLS::Connection_Side side,
1288
                                            Botan::TLS::Handshake_Type which_message) {
1289
            if(which_message == Handshake_Type::ClientHello) {
2✔
1290
               add_renegotiation_extension(exts);
1✔
1291
               sort_rfc8448_extensions(exts, side);
1✔
1292
            }
1293
         };
1294

1295
         std::unique_ptr<Client_Context> ctx;
1✔
1296

1297
         return {
1✔
1298
            CHECK("Client Hello",
1299
                  [&](Test::Result& result) {
1✔
1300
                     ctx = std::make_unique<Client_Context>(std::move(rng),
1✔
1301
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
1✔
1302
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
1303
                                                            add_extensions_and_sort,
1304
                                                            std::nullopt,
1305
                                                            std::nullopt,
1306
                                                            make_mock_signatures(vars));
2✔
1307

1308
                     ctx->check_callback_invocations(result,
2✔
1309
                                                     "initial callbacks",
1310
                                                     {
1311
                                                        "tls_emit_data",
1312
                                                        "tls_inspect_handshake_msg_client_hello",
1313
                                                        "tls_modify_extensions_client_hello",
1314
                                                        "tls_generate_ephemeral_key",
1315
                                                        "tls_current_timestamp",
1316
                                                     });
1317

1318
                     result.test_bin_eq(
1✔
1319
                        "Client Hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
1✔
1320
                  }),
1✔
1321

1322
            CHECK("Server Hello",
1323
                  [&](auto& result) {
1✔
1324
                     result.require("ctx is available", ctx != nullptr);
1✔
1325
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHello"));
1✔
1326

1327
                     ctx->check_callback_invocations(result,
2✔
1328
                                                     "callbacks after server hello",
1329
                                                     {
1330
                                                        "tls_examine_extensions_server_hello",
1331
                                                        "tls_inspect_handshake_msg_server_hello",
1332
                                                        "tls_ephemeral_key_agreement",
1333
                                                     });
1334
                  }),
1✔
1335

1336
            CHECK("other handshake messages and client auth",
1337
                  [&](Test::Result& result) {
1✔
1338
                     result.require("ctx is available", ctx != nullptr);
1✔
1339
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
1✔
1340

1341
                     ctx->check_callback_invocations(result,
2✔
1342
                                                     "signing callbacks invoked",
1343
                                                     {
1344
                                                        "tls_sign_message",
1345
                                                        "tls_emit_data",
1346
                                                        "tls_examine_extensions_encrypted_extensions",
1347
                                                        "tls_examine_extensions_certificate",
1348
                                                        "tls_examine_extensions_certificate_request",
1349
                                                        "tls_modify_extensions_certificate",
1350
                                                        "tls_inspect_handshake_msg_certificate",
1351
                                                        "tls_inspect_handshake_msg_certificate_request",
1352
                                                        "tls_inspect_handshake_msg_certificate_verify",
1353
                                                        "tls_inspect_handshake_msg_encrypted_extensions",
1354
                                                        "tls_inspect_handshake_msg_finished",
1355
                                                        "tls_current_timestamp",
1356
                                                        "tls_session_established",
1357
                                                        "tls_session_activated",
1358
                                                        "tls_verify_cert_chain",
1359
                                                        "tls_verify_message",
1360
                                                     });
1361

1362
                     // ClientFinished contains the entire coalesced client authentication flight
1363
                     // Messages: Certificate, CertificateVerify, Finished
1364
                     result.test_bin_eq(
1✔
1365
                        "Client Auth and Finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished"));
1✔
1366
                  }),
1✔
1367

1368
            CHECK("Close Connection",
1369
                  [&](Test::Result& result) {
1✔
1370
                     result.require("ctx is available", ctx != nullptr);
1✔
1371
                     ctx->client.close();
1✔
1372
                     result.test_bin_eq(
1✔
1373
                        "Client close_notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
1✔
1374

1375
                     ctx->check_callback_invocations(result,
2✔
1376
                                                     "after sending close notify",
1377
                                                     {
1378
                                                        "tls_emit_data",
1379
                                                     });
1380

1381
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
1✔
1382
                     result.test_is_true("connection closed", ctx->client.is_closed());
1✔
1383

1384
                     ctx->check_callback_invocations(
2✔
1385
                        result, "after receiving close notify", {"tls_alert", "tls_peer_closed_connection"});
1386
                  }),
1✔
1387
         };
5✔
1388
      }
2✔
1389

1390
      std::vector<Test::Result> middlebox_compatibility(const VarMap& vars) override {
1✔
1391
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
1392

1393
         // 32 - client hello random
1394
         // 32 - legacy session ID
1395
         // 32 - eph. x25519 key pair
1396
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
1✔
1397

1398
         auto add_extensions_and_sort = [&](Botan::TLS::Extensions& exts,
2✔
1399
                                            Botan::TLS::Connection_Side side,
1400
                                            Botan::TLS::Handshake_Type which_message) {
1401
            if(which_message == Handshake_Type::ClientHello) {
1✔
1402
               add_renegotiation_extension(exts);
1✔
1403
               sort_rfc8448_extensions(exts, side);
1✔
1404
            }
1405
         };
1406

1407
         std::unique_ptr<Client_Context> ctx;
1✔
1408

1409
         return {
1✔
1410
            CHECK(
1411
               "Client Hello",
1412
               [&](Test::Result& result) {
1✔
1413
                  ctx = std::make_unique<Client_Context>(std::move(rng),
1✔
1414
                                                         std::make_shared<RFC8448_Text_Policy>("rfc8448_compat_client"),
1✔
1415
                                                         vars.get_req_u64("CurrentTimestamp"),
1✔
1416
                                                         add_extensions_and_sort);
1✔
1417

1418
                  result.test_bin_eq("Client Hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
1✔
1419

1420
                  ctx->check_callback_invocations(result,
2✔
1421
                                                  "client hello prepared",
1422
                                                  {
1423
                                                     "tls_emit_data",
1424
                                                     "tls_inspect_handshake_msg_client_hello",
1425
                                                     "tls_modify_extensions_client_hello",
1426
                                                     "tls_generate_ephemeral_key",
1427
                                                     "tls_current_timestamp",
1428
                                                  });
1429
               }),
1✔
1430

1431
            CHECK("Server Hello + other handshake messages",
1432
                  [&](Test::Result& result) {
1✔
1433
                     result.require("ctx is available", ctx != nullptr);
1✔
1434
                     ctx->client.received_data(
2✔
1435
                        Botan::concat(vars.get_req_bin("Record_ServerHello"),
2✔
1436
                                      // ServerHandshakeMessages contains the expected ChangeCipherSpec record
1437
                                      vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
1438

1439
                     ctx->check_callback_invocations(result,
2✔
1440
                                                     "callbacks after server's first flight",
1441
                                                     {
1442
                                                        "tls_inspect_handshake_msg_server_hello",
1443
                                                        "tls_inspect_handshake_msg_encrypted_extensions",
1444
                                                        "tls_inspect_handshake_msg_certificate",
1445
                                                        "tls_inspect_handshake_msg_certificate_verify",
1446
                                                        "tls_inspect_handshake_msg_finished",
1447
                                                        "tls_examine_extensions_server_hello",
1448
                                                        "tls_examine_extensions_encrypted_extensions",
1449
                                                        "tls_examine_extensions_certificate",
1450
                                                        "tls_emit_data",
1451
                                                        "tls_current_timestamp",
1452
                                                        "tls_session_established",
1453
                                                        "tls_session_activated",
1454
                                                        "tls_verify_cert_chain",
1455
                                                        "tls_verify_message",
1456
                                                        "tls_ephemeral_key_agreement",
1457
                                                     });
1458

1459
                     result.test_bin_eq("CCS + Client Finished",
1✔
1460
                                        ctx->pull_send_buffer(),
1✔
1461
                                        // ClientFinished contains the expected ChangeCipherSpec record
1462
                                        vars.get_req_bin("Record_ClientFinished"));
2✔
1463

1464
                     result.test_is_true("client is ready to send application traffic", ctx->client.is_active());
1✔
1465
                     result.test_is_true("handshake is complete", ctx->client.is_handshake_complete());
1✔
1466
                  }),
1✔
1467

1468
            CHECK("Close connection",
1469
                  [&](Test::Result& result) {
1✔
1470
                     result.require("ctx is available", ctx != nullptr);
1✔
1471
                     ctx->client.close();
1✔
1472

1473
                     result.test_bin_eq(
1✔
1474
                        "Client close_notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
1✔
1475

1476
                     result.require("client cannot send application traffic anymore", !ctx->client.is_active());
1✔
1477
                     result.require("client is not fully closed yet", !ctx->client.is_closed());
1✔
1478
                     result.test_is_true("handshake stays completed", ctx->client.is_handshake_complete());
1✔
1479

1480
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
1✔
1481

1482
                     result.test_is_true("client connection was terminated", ctx->client.is_closed());
1✔
1483
                  }),
1✔
1484
         };
4✔
1485
      }
2✔
1486

1487
      std::vector<Test::Result> externally_provided_psk_with_ephemeral_key(const VarMap& vars) override {
1✔
1488
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
1489

1490
         // 32 - for client hello random
1491
         // 32 - for KeyShare (eph. x25519 key pair)
1492
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
1✔
1493

1494
         auto sort_our_extensions = [](Botan::TLS::Extensions& exts,
2✔
1495
                                       Botan::TLS::Connection_Side /* side */,
1496
                                       Botan::TLS::Handshake_Type msg_type) {
1497
            if(msg_type == Handshake_Type::ClientHello) {
1✔
1498
               exts.remove_extension(Signature_Algorithms::static_type());
1✔
1499
               // This is the preference order of signature algorithms that we
1500
               // used when we first implemented this test case. To stay
1501
               // compatible with the now hard-coded transcript, we pin the
1502
               // algorithm order of preference.
1503
               //
1504
               // NOLINTNEXTLINE(*-owning-memory)
1505
               exts.add(new Signature_Algorithms({
2✔
1506
                  Signature_Scheme::RSA_PSS_SHA384,
1507
                  Signature_Scheme::RSA_PSS_SHA256,
1508
                  Signature_Scheme::RSA_PSS_SHA512,
1509
                  Signature_Scheme::RSA_PKCS1_SHA384,
1510
                  Signature_Scheme::RSA_PKCS1_SHA512,
1511
                  Signature_Scheme::RSA_PKCS1_SHA256,
1512
                  Signature_Scheme::ECDSA_SHA384,
1513
                  Signature_Scheme::ECDSA_SHA512,
1514
                  Signature_Scheme::ECDSA_SHA256,
1515
               }));
1✔
1516
            }
1517

1518
            // This is the order of extensions when we first introduced the PSK
1519
            // implementation and generated the transcript. To stay compatible
1520
            // with the now hard-coded transcript, we pin the extension order.
1521
            exts.reorder(std::array{
1✔
1522
               Botan::TLS::Extension_Code::ServerNameIndication,
1523
               Botan::TLS::Extension_Code::SupportedGroups,
1524
               Botan::TLS::Extension_Code::KeyShare,
1525
               Botan::TLS::Extension_Code::SupportedVersions,
1526
               Botan::TLS::Extension_Code::SignatureAlgorithms,
1527
               Botan::TLS::Extension_Code::PskKeyExchangeModes,
1528
               Botan::TLS::Extension_Code::RecordSizeLimit,
1529
               Botan::TLS::Extension_Code::PresharedKey,
1530
            });
1531
         };
1✔
1532

1533
         std::unique_ptr<Client_Context> ctx;
1✔
1534

1535
         return {
1✔
1536
            CHECK("Client Hello",
1537
                  [&](Test::Result& result) {
1✔
1538
                     ctx = std::make_unique<Client_Context>(std::move(rng),
1✔
1539
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_psk_dhe"),
1✔
1540
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
1541
                                                            sort_our_extensions,
1542
                                                            std::nullopt,
1543
                                                            ExternalPSK(vars.get_req_str("PskIdentity"),
2✔
1544
                                                                        vars.get_req_str("PskPRF"),
1✔
1545
                                                                        lock(vars.get_req_bin("PskSecret"))));
4✔
1546

1547
                     result.test_is_true("client not closed", !ctx->client.is_closed());
1✔
1548
                     ctx->check_callback_invocations(result,
2✔
1549
                                                     "client hello prepared",
1550
                                                     {
1551
                                                        "tls_emit_data",
1552
                                                        "tls_inspect_handshake_msg_client_hello",
1553
                                                        "tls_modify_extensions_client_hello",
1554
                                                        "tls_current_timestamp",
1555
                                                        "tls_generate_ephemeral_key",
1556
                                                     });
1557

1558
                     result.test_bin_eq(
1✔
1559
                        "TLS client hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
1✔
1560
                  }),
1✔
1561

1562
            CHECK("Server Hello",
1563
                  [&](Test::Result& result) {
1✔
1564
                     result.require("ctx is available", ctx != nullptr);
1✔
1565
                     const auto server_hello = vars.get_req_bin("Record_ServerHello");
1✔
1566
                     ctx->client.received_data(server_hello);
1✔
1567
                     ctx->check_callback_invocations(result,
2✔
1568
                                                     "server hello received",
1569
                                                     {"tls_inspect_handshake_msg_server_hello",
1570
                                                      "tls_examine_extensions_server_hello",
1571
                                                      "tls_ephemeral_key_agreement"});
1572

1573
                     result.test_is_true("client is not yet active", !ctx->client.is_active());
1✔
1574
                     result.test_is_true("handshake is not yet complete", !ctx->client.is_handshake_complete());
1✔
1575
                  }),
1✔
1576

1577
            CHECK(
1578
               "Server HS messages .. Client Finished",
1579
               [&](Test::Result& result) {
1✔
1580
                  result.require("ctx is available", ctx != nullptr);
1✔
1581
                  ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
1✔
1582

1583
                  ctx->check_callback_invocations(result,
2✔
1584
                                                  "encrypted handshake messages received",
1585
                                                  {"tls_inspect_handshake_msg_encrypted_extensions",
1586
                                                   "tls_inspect_handshake_msg_finished",
1587
                                                   "tls_examine_extensions_encrypted_extensions",
1588
                                                   "tls_emit_data",
1589
                                                   "tls_current_timestamp",
1590
                                                   "tls_session_established",
1591
                                                   "tls_session_activated"});
1592
                  result.require("PSK negotiated", ctx->psk_identity_negotiated() == vars.get_req_str("PskIdentity"));
1✔
1593
                  result.require("client is active", ctx->client.is_active());
1✔
1594
                  result.test_is_true("handshake is complete", ctx->client.is_handshake_complete());
1✔
1595

1596
                  result.test_bin_eq(
1✔
1597
                     "correct handshake finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished"));
1✔
1598
               }),
1✔
1599

1600
            CHECK("Send Application Data",
1601
                  [&](Test::Result& result) {
1✔
1602
                     result.require("ctx is available", ctx != nullptr);
1✔
1603
                     ctx->send(vars.get_req_bin("Client_AppData"));
2✔
1604

1605
                     ctx->check_callback_invocations(result, "application data sent", {"tls_emit_data"});
2✔
1606

1607
                     result.test_bin_eq("correct client application data",
1✔
1608
                                        ctx->pull_send_buffer(),
1✔
1609
                                        vars.get_req_bin("Record_Client_AppData"));
2✔
1610
                  }),
1✔
1611

1612
            CHECK("Receive Application Data",
1613
                  [&](Test::Result& result) {
1✔
1614
                     result.require("ctx is available", ctx != nullptr);
1✔
1615
                     ctx->client.received_data(vars.get_req_bin("Record_Server_AppData"));
1✔
1616

1617
                     ctx->check_callback_invocations(result, "application data sent", {"tls_record_received"});
2✔
1618

1619
                     const auto rcvd = ctx->pull_receive_buffer();
1✔
1620
                     result.test_bin_eq("decrypted application traffic", rcvd, vars.get_req_bin("Server_AppData"));
1✔
1621
                     result.test_u64_eq("sequence number", ctx->last_received_seq_no(), uint64_t(0));
1✔
1622
                  }),
1✔
1623

1624
            CHECK("Close Connection",
1625
                  [&](Test::Result& result) {
1✔
1626
                     result.require("ctx is available", ctx != nullptr);
1✔
1627
                     ctx->client.close();
1✔
1628

1629
                     result.test_bin_eq(
1✔
1630
                        "close payload", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
1✔
1631
                     ctx->check_callback_invocations(result, "CLOSE_NOTIFY sent", {"tls_emit_data"});
2✔
1632

1633
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
1✔
1634
                     ctx->check_callback_invocations(
2✔
1635
                        result, "CLOSE_NOTIFY received", {"tls_alert", "tls_peer_closed_connection"});
1636

1637
                     result.test_is_true("connection is closed", ctx->client.is_closed());
1✔
1638
                  }),
1✔
1639
         };
7✔
1640
      }
2✔
1641

1642
      std::vector<Test::Result> raw_public_key_with_client_authentication(const VarMap& vars) override {
1✔
1643
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
1644

1645
         // 32 - for client hello random
1646
         // 32 - for KeyShare (eph. x25519 key pair)
1647
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
1✔
1648

1649
         auto sort_our_extensions = [&](Botan::TLS::Extensions& exts,
3✔
1650
                                        Botan::TLS::Connection_Side /* side */,
1651
                                        Botan::TLS::Handshake_Type /* which_message */) {
1652
            // This is the order of extensions when we first introduced the raw
1653
            // public key authentication implementation and generated the transcript.
1654
            // To stay compatible with the now hard-coded transcript, we pin the
1655
            // extension order.
1656
            exts.reorder(std::array{
2✔
1657
               Botan::TLS::Extension_Code::ServerNameIndication,
1658
               Botan::TLS::Extension_Code::SupportedGroups,
1659
               Botan::TLS::Extension_Code::KeyShare,
1660
               Botan::TLS::Extension_Code::SupportedVersions,
1661
               Botan::TLS::Extension_Code::SignatureAlgorithms,
1662
               Botan::TLS::Extension_Code::PskKeyExchangeModes,
1663
               Botan::TLS::Extension_Code::RecordSizeLimit,
1664
               Botan::TLS::Extension_Code::ClientCertificateType,
1665
               Botan::TLS::Extension_Code::ServerCertificateType,
1666
            });
1667
         };
2✔
1668

1669
         std::unique_ptr<Client_Context> ctx;
1✔
1670

1671
         return {
1✔
1672
            CHECK("Client Hello",
1673
                  [&](Test::Result& result) {
1✔
1674
                     ctx = std::make_unique<Client_Context>(std::move(rng),
1✔
1675
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_rawpubkey"),
1✔
1676
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
1677
                                                            sort_our_extensions,
1678
                                                            std::nullopt,
1679
                                                            std::nullopt,
1680
                                                            make_mock_signatures(vars));
2✔
1681

1682
                     ctx->check_callback_invocations(result,
2✔
1683
                                                     "initial callbacks",
1684
                                                     {
1685
                                                        "tls_emit_data",
1686
                                                        "tls_inspect_handshake_msg_client_hello",
1687
                                                        "tls_modify_extensions_client_hello",
1688
                                                        "tls_generate_ephemeral_key",
1689
                                                        "tls_current_timestamp",
1690
                                                     });
1691

1692
                     result.test_bin_eq(
1✔
1693
                        "Client Hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
1✔
1694
                  }),
1✔
1695

1696
            CHECK("Server Hello",
1697
                  [&](auto& result) {
1✔
1698
                     result.require("ctx is available", ctx != nullptr);
1✔
1699
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHello"));
1✔
1700

1701
                     ctx->check_callback_invocations(result,
2✔
1702
                                                     "callbacks after server hello",
1703
                                                     {
1704
                                                        "tls_examine_extensions_server_hello",
1705
                                                        "tls_inspect_handshake_msg_server_hello",
1706
                                                        "tls_ephemeral_key_agreement",
1707
                                                     });
1708
                  }),
1✔
1709

1710
            CHECK("other handshake messages and client auth",
1711
                  [&](Test::Result& result) {
1✔
1712
                     result.require("ctx is available", ctx != nullptr);
1✔
1713
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
1✔
1714

1715
                     ctx->check_callback_invocations(result,
2✔
1716
                                                     "signing callbacks invoked",
1717
                                                     {
1718
                                                        "tls_sign_message",
1719
                                                        "tls_emit_data",
1720
                                                        "tls_examine_extensions_encrypted_extensions",
1721
                                                        "tls_examine_extensions_certificate",
1722
                                                        "tls_examine_extensions_certificate_request",
1723
                                                        "tls_modify_extensions_certificate",
1724
                                                        "tls_inspect_handshake_msg_certificate",
1725
                                                        "tls_inspect_handshake_msg_certificate_request",
1726
                                                        "tls_inspect_handshake_msg_certificate_verify",
1727
                                                        "tls_inspect_handshake_msg_encrypted_extensions",
1728
                                                        "tls_inspect_handshake_msg_finished",
1729
                                                        "tls_current_timestamp",
1730
                                                        "tls_session_established",
1731
                                                        "tls_session_activated",
1732
                                                        "tls_verify_raw_public_key",
1733
                                                        "tls_verify_message",
1734
                                                     });
1735

1736
                     const auto raw_pk = ctx->client.peer_raw_public_key();
1✔
1737
                     result.test_is_true(
1✔
1738
                        "Received server's raw public key",
1739
                        raw_pk && raw_pk->fingerprint_public() == server_raw_public_key_pair()->fingerprint_public());
5✔
1740

1741
                     // ClientFinished contains the entire coalesced client authentication flight
1742
                     // Messages: Certificate, CertificateVerify, Finished
1743
                     result.test_bin_eq(
1✔
1744
                        "Client Auth and Finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished"));
1✔
1745
                  }),
1✔
1746

1747
            CHECK("Close Connection",
1748
                  [&](Test::Result& result) {
1✔
1749
                     result.require("ctx is available", ctx != nullptr);
1✔
1750
                     ctx->client.close();
1✔
1751
                     result.test_bin_eq(
1✔
1752
                        "Client close_notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
1✔
1753

1754
                     ctx->check_callback_invocations(result,
2✔
1755
                                                     "after sending close notify",
1756
                                                     {
1757
                                                        "tls_emit_data",
1758
                                                     });
1759

1760
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
1✔
1761
                     result.test_is_true("connection closed", ctx->client.is_closed());
1✔
1762

1763
                     ctx->check_callback_invocations(
2✔
1764
                        result, "after receiving close notify", {"tls_alert", "tls_peer_closed_connection"});
1765
                  }),
1✔
1766
         };
5✔
1767
      }
2✔
1768
};
1769

1770
class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 {
1✔
1771
   private:
1772
      std::string side() const override { return "Server"; }
7✔
1773

1774
      std::vector<Test::Result> simple_1_rtt(const VarMap& vars) override {
1✔
1775
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
1776

1777
         // 32 - for server hello random
1778
         // 32 - for KeyShare (eph. x25519 key pair)  --  I guess?
1779
         //  4 - for ticket_age_add (in New Session Ticket)
1780
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
1✔
1781

1782
         std::unique_ptr<Server_Context> ctx;
1✔
1783

1784
         return {
1✔
1785
            CHECK("Send Client Hello",
1786
                  [&](Test::Result& result) {
1✔
1787
                     auto add_early_data_and_sort = [&](Botan::TLS::Extensions& exts,
5✔
1788
                                                        Botan::TLS::Connection_Side side,
1789
                                                        Botan::TLS::Handshake_Type type) {
1790
                        if(type == Handshake_Type::NewSessionTicket) {
4✔
1791
                           exts.add(new EarlyDataIndication(1024));  // NOLINT(*-owning-memory)
1✔
1792
                        }
1793
                        sort_rfc8448_extensions(exts, side, type);
4✔
1794
                     };
4✔
1795

1796
                     ctx = std::make_unique<Server_Context>(
1✔
1797
                        std::move(rng),
1798
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
1✔
1799
                        vars.get_req_u64("CurrentTimestamp"),
1✔
1800
                        add_early_data_and_sort,
1801
                        make_mock_signatures(vars),
1✔
1802
                        false,
1✔
1803
                        std::pair{Botan::TLS::Session(vars.get_req_bin("Client_SessionData")),
4✔
1804
                                  Botan::TLS::Session_Ticket(vars.get_req_bin("SessionTicket"))});
3✔
1805
                     result.test_is_true("server not closed", !ctx->server.is_closed());
1✔
1806

1807
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
1✔
1808

1809
                     ctx->check_callback_invocations(result,
2✔
1810
                                                     "client hello received",
1811
                                                     {"tls_emit_data",
1812
                                                      "tls_examine_extensions_client_hello",
1813
                                                      "tls_modify_extensions_server_hello",
1814
                                                      "tls_modify_extensions_encrypted_extensions",
1815
                                                      "tls_modify_extensions_certificate",
1816
                                                      "tls_sign_message",
1817
                                                      "tls_generate_ephemeral_key",
1818
                                                      "tls_ephemeral_key_agreement",
1819
                                                      "tls_inspect_handshake_msg_client_hello",
1820
                                                      "tls_inspect_handshake_msg_server_hello",
1821
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
1822
                                                      "tls_inspect_handshake_msg_certificate",
1823
                                                      "tls_inspect_handshake_msg_certificate_verify",
1824
                                                      "tls_inspect_handshake_msg_finished"});
1825
                  }),
1✔
1826

1827
            CHECK("Verify generated messages in server's first flight",
1828
                  [&](Test::Result& result) {
1✔
1829
                     result.require("ctx is available", ctx != nullptr);
1✔
1830
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
1831

1832
                     result.test_bin_eq("Server Hello",
2✔
1833
                                        msgs.at("server_hello")[0],
1✔
1834
                                        strip_message_header(vars.get_opt_bin("Message_ServerHello")));
2✔
1835
                     result.test_bin_eq("Encrypted Extensions",
2✔
1836
                                        msgs.at("encrypted_extensions")[0],
1✔
1837
                                        strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
2✔
1838
                     result.test_bin_eq("Certificate",
2✔
1839
                                        msgs.at("certificate")[0],
1✔
1840
                                        strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
2✔
1841
                     result.test_bin_eq("CertificateVerify",
2✔
1842
                                        msgs.at("certificate_verify")[0],
1✔
1843
                                        strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
2✔
1844

1845
                     result.test_bin_eq("Server's entire first flight",
1✔
1846
                                        ctx->pull_send_buffer(),
1✔
1847
                                        concat(vars.get_req_bin("Record_ServerHello"),
3✔
1848
                                               vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
1849

1850
                     // Note: is_active() defines that we can send application data.
1851
                     //       RFC 8446 Section 4.4.4 explicitly allows that for servers
1852
                     //       that did not receive the client's Finished message, yet.
1853
                     //       However, before receiving and validating this message,
1854
                     //       the handshake is not yet finished.
1855
                     result.test_is_true("Server can now send application data", ctx->server.is_active());
1✔
1856
                     result.test_is_true("handshake is not yet complete", !ctx->server.is_handshake_complete());
1✔
1857
                  }),
1✔
1858

1859
            CHECK("Send Client Finished",
1860
                  [&](Test::Result& result) {
1✔
1861
                     result.require("ctx is available", ctx != nullptr);
1✔
1862
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
1✔
1863

1864
                     ctx->check_callback_invocations(result,
2✔
1865
                                                     "client finished received",
1866
                                                     {"tls_inspect_handshake_msg_finished",
1867
                                                      "tls_current_timestamp",
1868
                                                      "tls_session_established",
1869
                                                      "tls_session_activated"});
1870
                  }),
1✔
1871

1872
            CHECK("Send Session Ticket",
1873
                  [&](Test::Result& result) {
1✔
1874
                     result.require("ctx is available", ctx != nullptr);
1✔
1875
                     const auto new_tickets = ctx->server.send_new_session_tickets(1);
1✔
1876

1877
                     result.test_sz_eq("session ticket was sent", new_tickets, 1);
1✔
1878

1879
                     ctx->check_callback_invocations(result,
2✔
1880
                                                     "issued new session ticket",
1881
                                                     {"tls_inspect_handshake_msg_new_session_ticket",
1882
                                                      "tls_current_timestamp",
1883
                                                      "tls_emit_data",
1884
                                                      "tls_modify_extensions_new_session_ticket",
1885
                                                      "tls_should_persist_resumption_information"});
1886
                  }),
1✔
1887

1888
            CHECK("Verify generated new session ticket message",
1889
                  [&](Test::Result& result) {
1✔
1890
                     result.require("ctx is available", ctx != nullptr);
1✔
1891
                     result.test_bin_eq(
1✔
1892
                        "New Session Ticket", ctx->pull_send_buffer(), vars.get_req_bin("Record_NewSessionTicket"));
1✔
1893
                  }),
1✔
1894

1895
            CHECK("Receive Application Data",
1896
                  [&](Test::Result& result) {
1✔
1897
                     result.require("ctx is available", ctx != nullptr);
1✔
1898
                     ctx->server.received_data(vars.get_req_bin("Record_Client_AppData"));
1✔
1899
                     ctx->check_callback_invocations(result, "application data received", {"tls_record_received"});
2✔
1900

1901
                     const auto rcvd = ctx->pull_receive_buffer();
1✔
1902
                     result.test_bin_eq("decrypted application traffic", rcvd, vars.get_req_bin("Client_AppData"));
1✔
1903
                     result.test_u64_eq("sequence number", ctx->last_received_seq_no(), uint64_t(0));
1✔
1904
                  }),
1✔
1905

1906
            CHECK("Send Application Data",
1907
                  [&](Test::Result& result) {
1✔
1908
                     result.require("ctx is available", ctx != nullptr);
1✔
1909
                     ctx->send(vars.get_req_bin("Server_AppData"));
2✔
1910

1911
                     ctx->check_callback_invocations(result, "application data sent", {"tls_emit_data"});
2✔
1912

1913
                     result.test_bin_eq("correct server application data",
1✔
1914
                                        ctx->pull_send_buffer(),
1✔
1915
                                        vars.get_req_bin("Record_Server_AppData"));
2✔
1916
                  }),
1✔
1917

1918
            CHECK("Receive Client's close_notify",
1919
                  [&](Test::Result& result) {
1✔
1920
                     result.require("ctx is available", ctx != nullptr);
1✔
1921
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
1✔
1922

1923
                     ctx->check_callback_invocations(
2✔
1924
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
1925

1926
                     result.test_is_true("connection is not yet closed", !ctx->server.is_closed());
1✔
1927
                     result.test_is_true("connection is still active", ctx->server.is_active());
1✔
1928
                     result.test_is_true("handshake is still finished", ctx->server.is_handshake_complete());
1✔
1929
                  }),
1✔
1930

1931
            CHECK("Expect Server close_notify",
1932
                  [&](Test::Result& result) {
1✔
1933
                     result.require("ctx is available", ctx != nullptr);
1✔
1934
                     ctx->server.close();
1✔
1935

1936
                     result.test_is_true("connection is now inactive", !ctx->server.is_active());
1✔
1937
                     result.test_is_true("connection is now closed", ctx->server.is_closed());
1✔
1938
                     result.test_is_true("handshake is still finished", ctx->server.is_handshake_complete());
1✔
1939
                     result.test_bin_eq("Server's close notify",
1✔
1940
                                        ctx->pull_send_buffer(),
1✔
1941
                                        vars.get_req_bin("Record_Server_CloseNotify"));
2✔
1942
                  }),
1✔
1943
         };
10✔
1944
      }
2✔
1945

1946
      std::vector<Test::Result> resumed_handshake_with_0_rtt(const VarMap& vars) override {
1✔
1947
         auto rng = std::make_unique<Fixed_Output_RNG>();
1✔
1948

1949
         // 32 - for server hello random
1950
         // 32 - for KeyShare (eph. x25519 key pair)
1951
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
1✔
1952

1953
         std::unique_ptr<Server_Context> ctx;
1✔
1954

1955
         return {
1✔
1956
            CHECK("Receive Client Hello",
1957
                  [&](Test::Result& result) {
1✔
1958
                     auto add_cookie_and_sort = [&](Botan::TLS::Extensions& exts,
3✔
1959
                                                    Botan::TLS::Connection_Side side,
1960
                                                    Botan::TLS::Handshake_Type type) {
1961
                        if(type == Handshake_Type::EncryptedExtensions) {
2✔
1962
                           exts.add(new EarlyDataIndication());  // NOLINT(*-owning-memory)
1✔
1963
                        }
1964
                        sort_rfc8448_extensions(exts, side, type);
2✔
1965
                     };
2✔
1966

1967
                     ctx = std::make_unique<Server_Context>(
1✔
1968
                        std::move(rng),
1969
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
1✔
1970
                        vars.get_req_u64("CurrentTimestamp"),
1✔
1971
                        add_cookie_and_sort,
1972
                        make_mock_signatures(vars),
1✔
1973
                        false,
1✔
1974
                        std::pair{Botan::TLS::Session(vars.get_req_bin("Client_SessionData")),
4✔
1975
                                  Botan::TLS::Session_Ticket(vars.get_req_bin("SessionTicket"))});
3✔
1976
                     result.test_is_true("server not closed", !ctx->server.is_closed());
1✔
1977

1978
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
1✔
1979

1980
                     ctx->check_callback_invocations(result,
2✔
1981
                                                     "client hello received",
1982
                                                     {
1983
                                                        "tls_emit_data",
1984
                                                        "tls_current_timestamp",
1985
                                                        "tls_generate_ephemeral_key",
1986
                                                        "tls_ephemeral_key_agreement",
1987
                                                        "tls_examine_extensions_client_hello",
1988
                                                        "tls_modify_extensions_server_hello",
1989
                                                        "tls_modify_extensions_encrypted_extensions",
1990
                                                        "tls_inspect_handshake_msg_client_hello",
1991
                                                        "tls_inspect_handshake_msg_server_hello",
1992
                                                        "tls_inspect_handshake_msg_encrypted_extensions",
1993
                                                        "tls_inspect_handshake_msg_finished",
1994
                                                     });
1995
                  }),
1✔
1996

1997
            CHECK("Verify generated messages in server's first flight",
1998
                  [&](Test::Result& result) {
1✔
1999
                     result.require("ctx is available", ctx != nullptr);
1✔
2000
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2001

2002
                     result.test_bin_eq("Server Hello",
2✔
2003
                                        msgs.at("server_hello")[0],
1✔
2004
                                        strip_message_header(vars.get_opt_bin("Message_ServerHello")));
2✔
2005
                     result.test_bin_eq("Encrypted Extensions",
2✔
2006
                                        msgs.at("encrypted_extensions")[0],
1✔
2007
                                        strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
2✔
2008

2009
                     result.test_bin_eq("Server's entire first flight",
1✔
2010
                                        ctx->pull_send_buffer(),
1✔
2011
                                        concat(vars.get_req_bin("Record_ServerHello"),
3✔
2012
                                               vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2013

2014
                     // Note: is_active() defines that we can send application data.
2015
                     //       RFC 8446 Section 4.4.4 explicitly allows that for servers
2016
                     //       that did not receive the client's Finished message, yet.
2017
                     //       However, before receiving and validating this message,
2018
                     //       the handshake is not yet finished.
2019
                     result.test_is_true("Server can now send application data", ctx->server.is_active());
1✔
2020
                     result.test_is_true("handshake is not yet complete", !ctx->server.is_handshake_complete());
1✔
2021
                  }),
1✔
2022

2023
            // TODO: The rest of this test vector requires 0-RTT which is not
2024
            //       yet implemented. For now we can only test the server's
2025
            //       ability to acknowledge a session resumption via PSK.
2026
         };
3✔
2027
      }
2✔
2028

2029
      std::vector<Test::Result> hello_retry_request(const VarMap& vars) override {
1✔
2030
         // Fallback RNG is required to for blinding in ECDH with P-256
2031
         auto& fallback_rng = this->rng();
1✔
2032
         auto rng = std::make_unique<Fixed_Output_RNG>(fallback_rng);
1✔
2033

2034
         // 32 - for server hello random
2035
         // 32 - for KeyShare (eph. P-256 key pair)
2036
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
1✔
2037

2038
         std::unique_ptr<Server_Context> ctx;
1✔
2039

2040
         return {
1✔
2041
            CHECK("Receive Client Hello",
2042
                  [&](Test::Result& result) {
1✔
2043
                     auto add_cookie_and_sort = [&](Botan::TLS::Extensions& exts,
5✔
2044
                                                    Botan::TLS::Connection_Side side,
2045
                                                    Botan::TLS::Handshake_Type type) {
2046
                        if(type == Handshake_Type::HelloRetryRequest) {
4✔
2047
                           // This cookie needs to be mocked into the HRR since RFC 8448 contains it.
2048
                           exts.add(
1✔
2049
                              new Cookie(vars.get_opt_bin("HelloRetryRequest_Cookie")));  // NOLINT(*-owning-memory)
2✔
2050
                        }
2051
                        sort_rfc8448_extensions(exts, side, type);
4✔
2052
                     };
4✔
2053

2054
                     ctx = std::make_unique<Server_Context>(std::move(rng),
1✔
2055
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_hrr_server"),
1✔
2056
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
2057
                                                            add_cookie_and_sort,
2058
                                                            make_mock_signatures(vars));
2✔
2059
                     result.test_is_true("server not closed", !ctx->server.is_closed());
1✔
2060

2061
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
1✔
2062

2063
                     ctx->check_callback_invocations(result,
2✔
2064
                                                     "client hello received",
2065
                                                     {"tls_emit_data",
2066
                                                      "tls_examine_extensions_client_hello",
2067
                                                      "tls_modify_extensions_hello_retry_request",
2068
                                                      "tls_inspect_handshake_msg_client_hello",
2069
                                                      "tls_inspect_handshake_msg_hello_retry_request"});
2070
                  }),
1✔
2071

2072
            CHECK("Verify generated Hello Retry Request message",
2073
                  [&](Test::Result& result) {
1✔
2074
                     result.require("ctx is available", ctx != nullptr);
1✔
2075
                     result.test_bin_eq("Server's Hello Retry Request record",
1✔
2076
                                        ctx->pull_send_buffer(),
1✔
2077
                                        vars.get_req_bin("Record_HelloRetryRequest"));
2✔
2078
                     result.test_is_true("TLS handshake not yet finished", !ctx->server.is_active());
1✔
2079
                     result.test_is_true("handshake is not yet complete", !ctx->server.is_handshake_complete());
1✔
2080
                  }),
1✔
2081

2082
            CHECK("Receive updated Client Hello message",
2083
                  [&](Test::Result& result) {
1✔
2084
                     result.require("ctx is available", ctx != nullptr);
1✔
2085
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_2"));
1✔
2086

2087
                     ctx->check_callback_invocations(result,
2✔
2088
                                                     "updated client hello received",
2089
                                                     {"tls_emit_data",
2090
                                                      "tls_examine_extensions_client_hello",
2091
                                                      "tls_modify_extensions_server_hello",
2092
                                                      "tls_modify_extensions_encrypted_extensions",
2093
                                                      "tls_modify_extensions_certificate",
2094
                                                      "tls_sign_message",
2095
                                                      "tls_generate_ephemeral_key",
2096
                                                      "tls_ephemeral_key_agreement",
2097
                                                      "tls_inspect_handshake_msg_client_hello",
2098
                                                      "tls_inspect_handshake_msg_server_hello",
2099
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2100
                                                      "tls_inspect_handshake_msg_certificate",
2101
                                                      "tls_inspect_handshake_msg_certificate_verify",
2102
                                                      "tls_inspect_handshake_msg_finished"});
2103
                  }),
1✔
2104

2105
            CHECK("Verify generated messages in server's second flight",
2106
                  [&](Test::Result& result) {
1✔
2107
                     result.require("ctx is available", ctx != nullptr);
1✔
2108
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2109

2110
                     result.test_bin_eq("Server Hello",
2✔
2111
                                        msgs.at("server_hello")[0],
1✔
2112
                                        strip_message_header(vars.get_opt_bin("Message_ServerHello")));
2✔
2113
                     result.test_bin_eq("Encrypted Extensions",
2✔
2114
                                        msgs.at("encrypted_extensions")[0],
1✔
2115
                                        strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
2✔
2116
                     result.test_bin_eq("Certificate",
2✔
2117
                                        msgs.at("certificate")[0],
1✔
2118
                                        strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
2✔
2119
                     result.test_bin_eq("CertificateVerify",
2✔
2120
                                        msgs.at("certificate_verify")[0],
1✔
2121
                                        strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
2✔
2122
                     result.test_bin_eq("Finished",
2✔
2123
                                        msgs.at("finished")[0],
1✔
2124
                                        strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
2✔
2125

2126
                     result.test_bin_eq("Server's entire second flight",
1✔
2127
                                        ctx->pull_send_buffer(),
1✔
2128
                                        concat(vars.get_req_bin("Record_ServerHello"),
3✔
2129
                                               vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2130
                     result.test_is_true("Server could now send application data", ctx->server.is_active());
1✔
2131
                     result.test_is_true("handshake is not yet complete",
1✔
2132
                                         !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2133
                  }),
1✔
2134

2135
            CHECK("Receive Client Finished",
2136
                  [&](Test::Result& result) {
1✔
2137
                     result.require("ctx is available", ctx != nullptr);
1✔
2138
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
1✔
2139

2140
                     ctx->check_callback_invocations(result,
2✔
2141
                                                     "client finished received",
2142
                                                     {"tls_inspect_handshake_msg_finished",
2143
                                                      "tls_current_timestamp",
2144
                                                      "tls_session_established",
2145
                                                      "tls_session_activated"});
2146

2147
                     result.test_is_true("TLS handshake finished", ctx->server.is_active());
1✔
2148
                     result.test_is_true("handshake is complete", ctx->server.is_handshake_complete());
1✔
2149
                  }),
1✔
2150

2151
            CHECK("Receive Client close_notify",
2152
                  [&](Test::Result& result) {
1✔
2153
                     result.require("ctx is available", ctx != nullptr);
1✔
2154
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
1✔
2155

2156
                     ctx->check_callback_invocations(
2✔
2157
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2158

2159
                     result.test_is_true("connection is not yet closed", !ctx->server.is_closed());
1✔
2160
                     result.test_is_true("connection is still active", ctx->server.is_active());
1✔
2161
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2162
                  }),
1✔
2163

2164
            CHECK("Expect Server close_notify",
2165
                  [&](Test::Result& result) {
1✔
2166
                     result.require("ctx is available", ctx != nullptr);
1✔
2167
                     ctx->server.close();
1✔
2168

2169
                     result.test_is_true("connection is now inactive", !ctx->server.is_active());
1✔
2170
                     result.test_is_true("connection is now closed", ctx->server.is_closed());
1✔
2171
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2172
                     result.test_bin_eq("Server's close notify",
1✔
2173
                                        ctx->pull_send_buffer(),
1✔
2174
                                        vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2175
                  }),
1✔
2176

2177
         };
8✔
2178
      }
2✔
2179

2180
      std::vector<Test::Result> client_authentication(const VarMap& vars) override {
1✔
2181
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
2182

2183
         // 32 - for server hello random
2184
         // 32 - for KeyShare (eph. x25519 pair)
2185
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
1✔
2186

2187
         std::unique_ptr<Server_Context> ctx;
1✔
2188

2189
         return {
1✔
2190
            CHECK("Receive Client Hello",
2191
                  [&](Test::Result& result) {
1✔
2192
                     ctx = std::make_unique<Server_Context>(
1✔
2193
                        std::move(rng),
2194
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_client_auth_server"),
1✔
2195
                        vars.get_req_u64("CurrentTimestamp"),
1✔
2196
                        sort_rfc8448_extensions,
2197
                        make_mock_signatures(vars),
1✔
2198
                        true /* use alternative certificate */);
2✔
2199
                     result.test_is_true("server not closed", !ctx->server.is_closed());
1✔
2200

2201
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
1✔
2202

2203
                     ctx->check_callback_invocations(result,
2✔
2204
                                                     "client hello received",
2205
                                                     {"tls_emit_data",
2206
                                                      "tls_examine_extensions_client_hello",
2207
                                                      "tls_modify_extensions_server_hello",
2208
                                                      "tls_modify_extensions_encrypted_extensions",
2209
                                                      "tls_modify_extensions_certificate_request",
2210
                                                      "tls_modify_extensions_certificate",
2211
                                                      "tls_sign_message",
2212
                                                      "tls_generate_ephemeral_key",
2213
                                                      "tls_ephemeral_key_agreement",
2214
                                                      "tls_inspect_handshake_msg_client_hello",
2215
                                                      "tls_inspect_handshake_msg_server_hello",
2216
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2217
                                                      "tls_inspect_handshake_msg_certificate_request",
2218
                                                      "tls_inspect_handshake_msg_certificate",
2219
                                                      "tls_inspect_handshake_msg_certificate_verify",
2220
                                                      "tls_inspect_handshake_msg_finished"});
2221
                  }),
1✔
2222

2223
            CHECK("Verify server's generated handshake messages",
2224
                  [&](Test::Result& result) {
1✔
2225
                     result.require("ctx is available", ctx != nullptr);
1✔
2226
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2227

2228
                     result.test_bin_eq("Server Hello",
2✔
2229
                                        msgs.at("server_hello")[0],
1✔
2230
                                        strip_message_header(vars.get_opt_bin("Message_ServerHello")));
2✔
2231
                     result.test_bin_eq("Encrypted Extensions",
2✔
2232
                                        msgs.at("encrypted_extensions")[0],
1✔
2233
                                        strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
2✔
2234
                     result.test_bin_eq("Certificate Request",
2✔
2235
                                        msgs.at("certificate_request")[0],
1✔
2236
                                        strip_message_header(vars.get_opt_bin("Message_CertificateRequest")));
2✔
2237
                     result.test_bin_eq("Certificate",
2✔
2238
                                        msgs.at("certificate")[0],
1✔
2239
                                        strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
2✔
2240
                     result.test_bin_eq("CertificateVerify",
2✔
2241
                                        msgs.at("certificate_verify")[0],
1✔
2242
                                        strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
2✔
2243
                     result.test_bin_eq("Finished",
2✔
2244
                                        msgs.at("finished")[0],
1✔
2245
                                        strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
2✔
2246

2247
                     result.test_bin_eq("Server's entire first flight",
1✔
2248
                                        ctx->pull_send_buffer(),
1✔
2249
                                        concat(vars.get_req_bin("Record_ServerHello"),
3✔
2250
                                               vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2251

2252
                     result.test_is_true("Not yet aware of client's cert chain", ctx->server.peer_cert_chain().empty());
1✔
2253
                     result.test_is_true("Server could now send application data", ctx->server.is_active());
1✔
2254
                     result.test_is_true("handshake is not yet complete",
1✔
2255
                                         !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2256
                  }),
1✔
2257

2258
            CHECK("Receive Client's second flight",
2259
                  [&](Test::Result& result) {
1✔
2260
                     result.require("ctx is available", ctx != nullptr);
1✔
2261
                     // This encrypted message contains the following messages:
2262
                     // * client's Certificate message
2263
                     // * client's Certificate_Verify message
2264
                     // * client's Finished message
2265
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
1✔
2266

2267
                     ctx->check_callback_invocations(result,
2✔
2268
                                                     "client finished received",
2269
                                                     {"tls_inspect_handshake_msg_certificate",
2270
                                                      "tls_inspect_handshake_msg_certificate_verify",
2271
                                                      "tls_inspect_handshake_msg_finished",
2272
                                                      "tls_examine_extensions_certificate",
2273
                                                      "tls_verify_cert_chain",
2274
                                                      "tls_verify_message",
2275
                                                      "tls_current_timestamp",
2276
                                                      "tls_session_established",
2277
                                                      "tls_session_activated"});
2278

2279
                     const auto cert_chain = ctx->server.peer_cert_chain();
1✔
2280
                     result.test_is_true("Received client's cert chain",
1✔
2281
                                         !cert_chain.empty() && cert_chain.front() == client_certificate());
2✔
2282

2283
                     result.test_is_true("TLS handshake finished", ctx->server.is_active());
1✔
2284
                     result.test_is_true("handshake is complete", ctx->server.is_handshake_complete());
1✔
2285
                  }),
1✔
2286

2287
            CHECK("Receive Client close_notify",
2288
                  [&](Test::Result& result) {
1✔
2289
                     result.require("ctx is available", ctx != nullptr);
1✔
2290
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
1✔
2291

2292
                     ctx->check_callback_invocations(
2✔
2293
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2294

2295
                     result.test_is_true("connection is not yet closed", !ctx->server.is_closed());
1✔
2296
                     result.test_is_true("connection is still active", ctx->server.is_active());
1✔
2297
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2298
                  }),
1✔
2299

2300
            CHECK("Expect Server close_notify",
2301
                  [&](Test::Result& result) {
1✔
2302
                     result.require("ctx is available", ctx != nullptr);
1✔
2303
                     ctx->server.close();
1✔
2304

2305
                     result.test_is_true("connection is now inactive", !ctx->server.is_active());
1✔
2306
                     result.test_is_true("connection is now closed", ctx->server.is_closed());
1✔
2307
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2308
                     result.test_bin_eq("Server's close notify",
1✔
2309
                                        ctx->pull_send_buffer(),
1✔
2310
                                        vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2311
                  }),
1✔
2312

2313
         };
6✔
2314
      }
2✔
2315

2316
      std::vector<Test::Result> middlebox_compatibility(const VarMap& vars) override {
1✔
2317
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
2318

2319
         // 32 - for server hello random
2320
         // 32 - for KeyShare (eph. x25519 pair)
2321
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
1✔
2322

2323
         std::unique_ptr<Server_Context> ctx;
1✔
2324

2325
         return {
1✔
2326
            CHECK("Receive Client Hello",
2327
                  [&](Test::Result& result) {
1✔
2328
                     ctx =
1✔
2329
                        std::make_unique<Server_Context>(std::move(rng),
1✔
2330
                                                         std::make_shared<RFC8448_Text_Policy>("rfc8448_compat_server"),
1✔
2331
                                                         vars.get_req_u64("CurrentTimestamp"),
1✔
2332
                                                         sort_rfc8448_extensions,
2333
                                                         make_mock_signatures(vars));
2✔
2334
                     result.test_is_true("server not closed", !ctx->server.is_closed());
1✔
2335

2336
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
1✔
2337

2338
                     ctx->check_callback_invocations(result,
2✔
2339
                                                     "client hello received",
2340
                                                     {"tls_emit_data",
2341
                                                      "tls_examine_extensions_client_hello",
2342
                                                      "tls_modify_extensions_server_hello",
2343
                                                      "tls_modify_extensions_encrypted_extensions",
2344
                                                      "tls_modify_extensions_certificate",
2345
                                                      "tls_sign_message",
2346
                                                      "tls_generate_ephemeral_key",
2347
                                                      "tls_ephemeral_key_agreement",
2348
                                                      "tls_inspect_handshake_msg_client_hello",
2349
                                                      "tls_inspect_handshake_msg_server_hello",
2350
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2351
                                                      "tls_inspect_handshake_msg_certificate",
2352
                                                      "tls_inspect_handshake_msg_certificate_verify",
2353
                                                      "tls_inspect_handshake_msg_finished"});
2354
                  }),
1✔
2355

2356
            CHECK("Verify server's generated handshake messages",
2357
                  [&](Test::Result& result) {
1✔
2358
                     result.require("ctx is available", ctx != nullptr);
1✔
2359
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2360

2361
                     result.test_bin_eq("Server Hello",
2✔
2362
                                        msgs.at("server_hello")[0],
1✔
2363
                                        strip_message_header(vars.get_opt_bin("Message_ServerHello")));
2✔
2364
                     result.test_bin_eq("Encrypted Extensions",
2✔
2365
                                        msgs.at("encrypted_extensions")[0],
1✔
2366
                                        strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
2✔
2367
                     result.test_bin_eq("Certificate",
2✔
2368
                                        msgs.at("certificate")[0],
1✔
2369
                                        strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
2✔
2370
                     result.test_bin_eq("CertificateVerify",
2✔
2371
                                        msgs.at("certificate_verify")[0],
1✔
2372
                                        strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
2✔
2373
                     result.test_bin_eq("Finished",
2✔
2374
                                        msgs.at("finished")[0],
1✔
2375
                                        strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
2✔
2376

2377
                     // Those records contain the required Change Cipher Spec message the server must produce for compatibility mode compliance
2378
                     result.test_bin_eq("Server's entire first flight",
1✔
2379
                                        ctx->pull_send_buffer(),
1✔
2380
                                        concat(vars.get_req_bin("Record_ServerHello"),
3✔
2381
                                               vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2382

2383
                     result.test_is_true("Server could now send application data", ctx->server.is_active());
1✔
2384
                     result.test_is_true("handshake is not yet complete",
1✔
2385
                                         !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2386
                  }),
1✔
2387

2388
            CHECK("Receive Client Finished",
2389
                  [&](Test::Result& result) {
1✔
2390
                     result.require("ctx is available", ctx != nullptr);
1✔
2391
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
1✔
2392

2393
                     ctx->check_callback_invocations(result,
2✔
2394
                                                     "client finished received",
2395
                                                     {"tls_inspect_handshake_msg_finished",
2396
                                                      "tls_current_timestamp",
2397
                                                      "tls_session_established",
2398
                                                      "tls_session_activated"});
2399

2400
                     result.test_is_true("TLS handshake fully finished", ctx->server.is_active());
1✔
2401
                     result.test_is_true("handshake is complete", ctx->server.is_handshake_complete());
1✔
2402
                  }),
1✔
2403

2404
            CHECK("Receive Client close_notify",
2405
                  [&](Test::Result& result) {
1✔
2406
                     result.require("ctx is available", ctx != nullptr);
1✔
2407
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
1✔
2408

2409
                     ctx->check_callback_invocations(
2✔
2410
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2411

2412
                     result.test_is_true("connection is not yet closed", !ctx->server.is_closed());
1✔
2413
                     result.test_is_true("connection is still active", ctx->server.is_active());
1✔
2414
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2415
                  }),
1✔
2416

2417
            CHECK("Expect Server close_notify",
2418
                  [&](Test::Result& result) {
1✔
2419
                     result.require("ctx is available", ctx != nullptr);
1✔
2420
                     ctx->server.close();
1✔
2421

2422
                     result.test_is_true("connection is now inactive", !ctx->server.is_active());
1✔
2423
                     result.test_is_true("connection is now closed", ctx->server.is_closed());
1✔
2424
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2425
                     result.test_bin_eq("Server's close notify",
1✔
2426
                                        ctx->pull_send_buffer(),
1✔
2427
                                        vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2428
                  }),
1✔
2429

2430
         };
6✔
2431
      }
2✔
2432

2433
      std::vector<Test::Result> externally_provided_psk_with_ephemeral_key(const VarMap& vars) override {
1✔
2434
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
2435

2436
         // 32 - for server hello random
2437
         // 32 - for KeyShare (eph. x25519 key pair)
2438
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
1✔
2439

2440
         std::unique_ptr<Server_Context> ctx;
1✔
2441

2442
         return {
1✔
2443
            CHECK("Send Client Hello",
2444
                  [&](Test::Result& result) {
1✔
2445
                     auto sort_our_extensions = [&](Botan::TLS::Extensions& exts,
3✔
2446
                                                    Botan::TLS::Connection_Side /* side */,
2447
                                                    Botan::TLS::Handshake_Type type) {
2448
                        // This is the order of extensions when we first introduced the PSK
2449
                        // implementation and generated the transcript. To stay compatible
2450
                        // with the now hard-coded transcript, we pin the extension order.
2451
                        if(type == Botan::TLS::Handshake_Type::EncryptedExtensions) {
2✔
2452
                           exts.reorder(std::array{
1✔
2453
                              Botan::TLS::Extension_Code::SupportedGroups,
2454
                              Botan::TLS::Extension_Code::RecordSizeLimit,
2455
                              Botan::TLS::Extension_Code::ServerNameIndication,
2456
                           });
2457
                        } else if(type == Botan::TLS::Handshake_Type::ServerHello) {
1✔
2458
                           exts.reorder(std::array{
1✔
2459
                              Botan::TLS::Extension_Code::SupportedVersions,
2460
                              Botan::TLS::Extension_Code::KeyShare,
2461
                              Botan::TLS::Extension_Code::PresharedKey,
2462
                           });
2463
                        }
2464
                     };
2✔
2465

2466
                     ctx = std::make_unique<Server_Context>(std::move(rng),
1✔
2467
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_psk_dhe"),
1✔
2468
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
2469
                                                            sort_our_extensions,
2470
                                                            make_mock_signatures(vars),
1✔
2471
                                                            false,
1✔
2472
                                                            std::nullopt,
2473
                                                            ExternalPSK(vars.get_req_str("PskIdentity"),
2✔
2474
                                                                        vars.get_req_str("PskPRF"),
1✔
2475
                                                                        lock(vars.get_req_bin("PskSecret"))));
4✔
2476
                     result.test_is_true("server not closed", !ctx->server.is_closed());
1✔
2477

2478
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
1✔
2479

2480
                     ctx->check_callback_invocations(result,
2✔
2481
                                                     "client hello received",
2482
                                                     {"tls_emit_data",
2483
                                                      "tls_examine_extensions_client_hello",
2484
                                                      "tls_modify_extensions_server_hello",
2485
                                                      "tls_modify_extensions_encrypted_extensions",
2486
                                                      "tls_generate_ephemeral_key",
2487
                                                      "tls_ephemeral_key_agreement",
2488
                                                      "tls_inspect_handshake_msg_client_hello",
2489
                                                      "tls_inspect_handshake_msg_server_hello",
2490
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2491
                                                      "tls_inspect_handshake_msg_finished"});
2492
                  }),
1✔
2493

2494
            CHECK("Verify generated messages in server's first flight",
2495
                  [&](Test::Result& result) {
1✔
2496
                     result.require("ctx is available", ctx != nullptr);
1✔
2497
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2498

2499
                     result.test_bin_eq("Server Hello",
2✔
2500
                                        msgs.at("server_hello")[0],
1✔
2501
                                        strip_message_header(vars.get_opt_bin("Message_ServerHello")));
2✔
2502
                     result.test_bin_eq("Encrypted Extensions",
2✔
2503
                                        msgs.at("encrypted_extensions")[0],
1✔
2504
                                        strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
2✔
2505
                     result.test_bin_eq("Server Finished",
2✔
2506
                                        msgs.at("finished")[0],
1✔
2507
                                        strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
2✔
2508

2509
                     result.test_bin_eq("Server's entire first flight",
1✔
2510
                                        ctx->pull_send_buffer(),
1✔
2511
                                        concat(vars.get_req_bin("Record_ServerHello"),
3✔
2512
                                               vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2513

2514
                     result.test_is_true("Server can now send application data", ctx->server.is_active());
1✔
2515
                     result.test_is_true("handshake is not yet complete",
1✔
2516
                                         !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2517
                  }),
1✔
2518

2519
            CHECK("Send Client Finished",
2520
                  [&](Test::Result& result) {
1✔
2521
                     result.require("ctx is available", ctx != nullptr);
1✔
2522
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
1✔
2523
                     result.require("PSK negotiated",
1✔
2524
                                    ctx->psk_identity_negotiated() == vars.get_req_str("PskIdentity"));
1✔
2525

2526
                     ctx->check_callback_invocations(result,
2✔
2527
                                                     "client finished received",
2528
                                                     {"tls_inspect_handshake_msg_finished",
2529
                                                      "tls_current_timestamp",
2530
                                                      "tls_session_established",
2531
                                                      "tls_session_activated"});
2532
                  }),
1✔
2533

2534
            CHECK("Exchange Application Data",
2535
                  [&](Test::Result& result) {
1✔
2536
                     result.require("ctx is available", ctx != nullptr);
1✔
2537
                     ctx->server.received_data(vars.get_req_bin("Record_Client_AppData"));
1✔
2538
                     ctx->check_callback_invocations(result, "application data received", {"tls_record_received"});
2✔
2539

2540
                     const auto rcvd = ctx->pull_receive_buffer();
1✔
2541
                     result.test_bin_eq("decrypted application traffic", rcvd, vars.get_req_bin("Client_AppData"));
1✔
2542
                     result.test_u64_eq("sequence number", ctx->last_received_seq_no(), uint64_t(0));
1✔
2543

2544
                     ctx->send(vars.get_req_bin("Server_AppData"));
2✔
2545
                     ctx->check_callback_invocations(result, "application data sent", {"tls_emit_data"});
2✔
2546
                     result.test_bin_eq("correct server application data",
1✔
2547
                                        ctx->pull_send_buffer(),
1✔
2548
                                        vars.get_req_bin("Record_Server_AppData"));
2✔
2549
                  }),
1✔
2550

2551
            CHECK("Terminate Connection",
2552
                  [&](Test::Result& result) {
1✔
2553
                     result.require("ctx is available", ctx != nullptr);
1✔
2554
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
1✔
2555

2556
                     ctx->check_callback_invocations(
2✔
2557
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2558

2559
                     result.test_is_true("connection is not yet closed", !ctx->server.is_closed());
1✔
2560
                     result.test_is_true("connection is still active", ctx->server.is_active());
1✔
2561
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2562

2563
                     ctx->server.close();
1✔
2564

2565
                     result.test_is_true("connection is now inactive", !ctx->server.is_active());
1✔
2566
                     result.test_is_true("connection is now closed", ctx->server.is_closed());
1✔
2567
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2568
                     result.test_bin_eq("Server's close notify",
1✔
2569
                                        ctx->pull_send_buffer(),
1✔
2570
                                        vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2571
                  }),
1✔
2572
         };
6✔
2573
      }
2✔
2574

2575
      std::vector<Test::Result> raw_public_key_with_client_authentication(const VarMap& vars) override {
1✔
2576
         auto rng = std::make_unique<Fixed_Output_RNG>("");
1✔
2577

2578
         // 32 - for server hello random
2579
         // 32 - for KeyShare (eph. x25519 key pair)
2580
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
1✔
2581

2582
         auto sort_our_extensions =
1✔
2583
            [&](Botan::TLS::Extensions& exts, Botan::TLS::Connection_Side /* side */, Botan::TLS::Handshake_Type type) {
4✔
2584
               // This is the order of extensions when we first introduced the raw
2585
               // public key authentication implementation and generated the transcript.
2586
               // To stay compatible with the now hard-coded transcript, we pin the
2587
               // extension order.
2588
               if(type == Botan::TLS::Handshake_Type::EncryptedExtensions) {
4✔
2589
                  exts.reorder(std::array{
1✔
2590
                     Botan::TLS::Extension_Code::ClientCertificateType,
2591
                     Botan::TLS::Extension_Code::ServerCertificateType,
2592
                     Botan::TLS::Extension_Code::SupportedGroups,
2593
                     Botan::TLS::Extension_Code::RecordSizeLimit,
2594
                     Botan::TLS::Extension_Code::ServerNameIndication,
2595
                  });
2596
               } else if(type == Botan::TLS::Handshake_Type::ServerHello) {
3✔
2597
                  exts.reorder(std::array{
1✔
2598
                     Botan::TLS::Extension_Code::KeyShare,
2599
                     Botan::TLS::Extension_Code::SupportedVersions,
2600
                  });
2601
               }
2602
            };
4✔
2603

2604
         std::unique_ptr<Server_Context> ctx;
1✔
2605

2606
         return {
1✔
2607
            CHECK("Receive Client Hello",
2608
                  [&](Test::Result& result) {
1✔
2609
                     ctx = std::make_unique<Server_Context>(std::move(rng),
1✔
2610
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_rawpubkey"),
1✔
2611
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
2612
                                                            sort_our_extensions,
2613
                                                            make_mock_signatures(vars));
2✔
2614
                     result.test_is_true("server not closed", !ctx->server.is_closed());
1✔
2615

2616
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
1✔
2617

2618
                     ctx->check_callback_invocations(result,
2✔
2619
                                                     "client hello received",
2620
                                                     {"tls_emit_data",
2621
                                                      "tls_examine_extensions_client_hello",
2622
                                                      "tls_modify_extensions_server_hello",
2623
                                                      "tls_modify_extensions_encrypted_extensions",
2624
                                                      "tls_modify_extensions_certificate_request",
2625
                                                      "tls_modify_extensions_certificate",
2626
                                                      "tls_sign_message",
2627
                                                      "tls_generate_ephemeral_key",
2628
                                                      "tls_ephemeral_key_agreement",
2629
                                                      "tls_inspect_handshake_msg_client_hello",
2630
                                                      "tls_inspect_handshake_msg_server_hello",
2631
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2632
                                                      "tls_inspect_handshake_msg_certificate_request",
2633
                                                      "tls_inspect_handshake_msg_certificate",
2634
                                                      "tls_inspect_handshake_msg_certificate_verify",
2635
                                                      "tls_inspect_handshake_msg_finished"});
2636
                  }),
1✔
2637

2638
            CHECK("Verify server's generated handshake messages",
2639
                  [&](Test::Result& result) {
1✔
2640
                     result.require("ctx is available", ctx != nullptr);
1✔
2641
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2642

2643
                     result.test_bin_eq("Server Hello",
2✔
2644
                                        msgs.at("server_hello")[0],
1✔
2645
                                        strip_message_header(vars.get_opt_bin("Message_ServerHello")));
2✔
2646
                     result.test_bin_eq("Encrypted Extensions",
2✔
2647
                                        msgs.at("encrypted_extensions")[0],
1✔
2648
                                        strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
2✔
2649
                     result.test_bin_eq("Certificate Request",
2✔
2650
                                        msgs.at("certificate_request")[0],
1✔
2651
                                        strip_message_header(vars.get_opt_bin("Message_CertificateRequest")));
2✔
2652
                     result.test_bin_eq("Certificate",
2✔
2653
                                        msgs.at("certificate")[0],
1✔
2654
                                        strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
2✔
2655
                     result.test_bin_eq("CertificateVerify",
2✔
2656
                                        msgs.at("certificate_verify")[0],
1✔
2657
                                        strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
2✔
2658
                     result.test_bin_eq("Finished",
2✔
2659
                                        msgs.at("finished")[0],
1✔
2660
                                        strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
2✔
2661

2662
                     result.test_bin_eq("Server's entire first flight",
1✔
2663
                                        ctx->pull_send_buffer(),
1✔
2664
                                        concat(vars.get_req_bin("Record_ServerHello"),
3✔
2665
                                               vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2666

2667
                     result.test_is_true("Not yet aware of client's cert chain", ctx->server.peer_cert_chain().empty());
1✔
2668
                     result.test_is_true("Server could now send application data", ctx->server.is_active());
1✔
2669
                     result.test_is_true("handshake is not yet complete",
1✔
2670
                                         !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2671
                  }),
1✔
2672

2673
            CHECK("Receive Client's second flight",
2674
                  [&](Test::Result& result) {
1✔
2675
                     result.require("ctx is available", ctx != nullptr);
1✔
2676
                     // This encrypted message contains the following messages:
2677
                     // * client's Certificate message
2678
                     // * client's Certificate_Verify message
2679
                     // * client's Finished message
2680
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
1✔
2681

2682
                     ctx->check_callback_invocations(result,
2✔
2683
                                                     "client finished received",
2684
                                                     {"tls_inspect_handshake_msg_certificate",
2685
                                                      "tls_inspect_handshake_msg_certificate_verify",
2686
                                                      "tls_inspect_handshake_msg_finished",
2687
                                                      "tls_examine_extensions_certificate",
2688
                                                      "tls_verify_raw_public_key",
2689
                                                      "tls_verify_message",
2690
                                                      "tls_current_timestamp",
2691
                                                      "tls_session_established",
2692
                                                      "tls_session_activated"});
2693

2694
                     const auto raw_pk = ctx->server.peer_raw_public_key();
1✔
2695
                     result.test_is_true(
1✔
2696
                        "Received client's raw public key",
2697
                        raw_pk && raw_pk->fingerprint_public() == client_raw_public_key_pair()->fingerprint_public());
5✔
2698

2699
                     result.test_is_true("TLS handshake finished", ctx->server.is_active());
1✔
2700
                     result.test_is_true("handshake is complete", ctx->server.is_handshake_complete());
1✔
2701
                  }),
1✔
2702

2703
            CHECK("Receive Client close_notify",
2704
                  [&](Test::Result& result) {
1✔
2705
                     result.require("ctx is available", ctx != nullptr);
1✔
2706
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
1✔
2707

2708
                     ctx->check_callback_invocations(
2✔
2709
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2710

2711
                     result.test_is_true("connection is not yet closed", !ctx->server.is_closed());
1✔
2712
                     result.test_is_true("connection is still active", ctx->server.is_active());
1✔
2713
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2714
                  }),
1✔
2715

2716
            CHECK("Expect Server close_notify",
2717
                  [&](Test::Result& result) {
1✔
2718
                     result.require("ctx is available", ctx != nullptr);
1✔
2719
                     ctx->server.close();
1✔
2720

2721
                     result.test_is_true("connection is now inactive", !ctx->server.is_active());
1✔
2722
                     result.test_is_true("connection is now closed", ctx->server.is_closed());
1✔
2723
                     result.test_is_true("handshake is still complete", ctx->server.is_handshake_complete());
1✔
2724
                     result.test_bin_eq("Server's close notify",
1✔
2725
                                        ctx->pull_send_buffer(),
1✔
2726
                                        vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2727
                  }),
1✔
2728
         };
6✔
2729
      }
2✔
2730
};
2731

2732
BOTAN_REGISTER_TEST("tls", "tls_rfc8448_client", Test_TLS_RFC8448_Client);
2733
BOTAN_REGISTER_TEST("tls", "tls_rfc8448_server", Test_TLS_RFC8448_Server);
2734

2735
#endif
2736

2737
}  // namespace
2738

2739
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc