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

randombit / botan / 14191488263

01 Apr 2025 07:17AM UTC coverage: 91.364% (+0.002%) from 91.362%
14191488263

push

github

web-flow
Merge pull request #4811 from KaganCanSit/feature-android-NDK-and-XCode-TODO-messages

Fixed the use of C++20 functions with updated Android NDK and XCode versions.

95237 of 104239 relevant lines covered (91.36%)

11724846.79 hits per line

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

97.35
/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_13) && defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305) && defined(BOTAN_HAS_AEAD_GCM) &&          \
17
   defined(BOTAN_HAS_AES) && defined(BOTAN_HAS_X25519) && defined(BOTAN_HAS_SHA2_32) && defined(BOTAN_HAS_SHA2_64) && \
18
   defined(BOTAN_HAS_ECDSA)
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/ecdsa.h>
29
   #include <botan/hash.h>
30
   #include <botan/pk_algs.h>
31
   #include <botan/pkcs8.h>
32
   #include <botan/rsa.h>
33
   #include <botan/tls.h>
34
   #include <botan/tls_extensions.h>
35
   #include <botan/tls_messages.h>
36
   #include <botan/x509_key.h>
37
   #include <botan/internal/fmt.h>
38
   #include <botan/internal/stl_util.h>
39
#endif
40

41
namespace Botan_Tests {
42

43
#if defined(BOTAN_CAN_RUN_TEST_TLS_RFC8448)
44

45
namespace {
46

47
void add_entropy(Fixed_Output_RNG& rng, const std::vector<uint8_t>& bin) {
14✔
48
   rng.add_entropy(bin.data(), bin.size());
28✔
49
}
50

51
Botan::X509_Certificate server_certificate() {
4✔
52
   // self-signed certificate with an RSA1024 public key valid until:
53
   //   Jul 30 01:23:59 2026 GMT
54
   Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/server_certificate.pem"));
8✔
55
   return Botan::X509_Certificate(in);
4✔
56
}
4✔
57

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

68
Botan::X509_Certificate client_certificate() {
2✔
69
   // self-signed certificate with an RSA1024 public key valid until:
70
   //   Jul 30 01:23:59 2026 GMT
71
   Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/client_certificate.pem"));
4✔
72
   return Botan::X509_Certificate(in);
2✔
73
}
2✔
74

75
std::unique_ptr<Botan::Private_Key> client_raw_public_key_pair() {
4✔
76
   // P-256 private key (independently generated)
77
   Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/client_raw_public_keypair.pem"));
8✔
78
   return Botan::PKCS8::load_key(in);
4✔
79
}
4✔
80

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

87
/**
88
* Simple version of the Padding extension (RFC 7685) to reproduce the
89
* 2nd Client_Hello in RFC8448 Section 5 (HelloRetryRequest)
90
*/
91
class Padding final : public Botan::TLS::Extension {
92
   public:
93
      static Botan::TLS::Extension_Code static_type() {
94
         // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
95
         return Botan::TLS::Extension_Code(21);
96
      }
97

98
      Botan::TLS::Extension_Code type() const override { return static_type(); }
46✔
99

100
      explicit Padding(const size_t padding_bytes) : m_padding_bytes(padding_bytes) {}
2✔
101

102
      std::vector<uint8_t> serialize(Botan::TLS::Connection_Side) const override {
5✔
103
         return std::vector<uint8_t>(m_padding_bytes, 0x00);
5✔
104
      }
105

106
      bool empty() const override { return m_padding_bytes == 0; }
5✔
107

108
   private:
109
      size_t m_padding_bytes;
110
};
111

112
using namespace Botan;
113
using namespace Botan::TLS;
114

115
std::chrono::system_clock::time_point from_milliseconds_since_epoch(uint64_t msecs) {
14✔
116
   const int64_t secs_since_epoch = msecs / 1000;
14✔
117
   const uint32_t additional_millis = msecs % 1000;
14✔
118

119
   BOTAN_ASSERT_NOMSG(secs_since_epoch <= std::numeric_limits<time_t>::max());
14✔
120
   return std::chrono::system_clock::from_time_t(static_cast<time_t>(secs_since_epoch)) +
14✔
121
          std::chrono::milliseconds(additional_millis);
14✔
122
}
123

124
using Modify_Exts_Fn =
125
   std::function<void(Botan::TLS::Extensions&, Botan::TLS::Connection_Side, Botan::TLS::Handshake_Type)>;
126

127
/**
128
 * We cannot actually reproduce the signatures stated in RFC 8448 as their
129
 * signature scheme is probabilistic and we're lacking the correct RNG
130
 * input. Hence, signatures are know beforehand and just reproduced by the
131
 * TLS callback when requested.
132
 */
133
struct MockSignature {
15✔
134
      std::vector<uint8_t> message_to_sign;
135
      std::vector<uint8_t> signature_to_produce;
136
};
137

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

154
      void tls_emit_data(std::span<const uint8_t> data) override {
47✔
155
         count_callback_invocation("tls_emit_data");
47✔
156
         send_buffer.insert(send_buffer.end(), data.begin(), data.end());
47✔
157
      }
47✔
158

159
      void tls_record_received(uint64_t seq_no, std::span<const uint8_t> data) override {
4✔
160
         count_callback_invocation("tls_record_received");
4✔
161
         received_seq_no = seq_no;
4✔
162
         receive_buffer.insert(receive_buffer.end(), data.begin(), data.end());
4✔
163
      }
4✔
164

165
      void tls_alert(Botan::TLS::Alert alert) override {
12✔
166
         count_callback_invocation("tls_alert");
12✔
167
         BOTAN_UNUSED(alert);
12✔
168
         // handle a tls alert received from the tls server
169
      }
12✔
170

171
      bool tls_peer_closed_connection() override {
12✔
172
         count_callback_invocation("tls_peer_closed_connection");
12✔
173
         // we want to handle the closure ourselves
174
         return false;
12✔
175
      }
176

177
      void tls_session_established(const Botan::TLS::Session_Summary& summary) override {
12✔
178
         if(summary.psk_used()) {
12✔
179
            negotiated_psk_identity = summary.external_psk_identity().value();
2✔
180
         }
181
         count_callback_invocation("tls_session_established");
12✔
182
      }
12✔
183

184
      void tls_session_activated() override {
12✔
185
         count_callback_invocation("tls_session_activated");
12✔
186
         session_activated_called = true;
12✔
187
      }
12✔
188

189
      bool tls_should_persist_resumption_information(const Session&) override {
2✔
190
         count_callback_invocation("tls_should_persist_resumption_information");
2✔
191
         return true;  // should always store the session
2✔
192
      }
193

194
      void tls_verify_cert_chain(const std::vector<Botan::X509_Certificate>& cert_chain,
5✔
195
                                 const std::vector<std::optional<Botan::OCSP::Response>>&,
196
                                 const std::vector<Botan::Certificate_Store*>&,
197
                                 Botan::Usage_Type,
198
                                 std::string_view,
199
                                 const Botan::TLS::Policy&) override {
200
         count_callback_invocation("tls_verify_cert_chain");
5✔
201
         certificate_chain = cert_chain;
5✔
202
      }
5✔
203

204
      void tls_verify_raw_public_key(const Public_Key& raw_pk,
2✔
205
                                     Usage_Type,
206
                                     std::string_view,
207
                                     const TLS::Policy&) override {
208
         count_callback_invocation("tls_verify_raw_public_key");
2✔
209
         // TODO: is there a better way to copy a generic public key?
210
         raw_public_key = Botan::X509::load_key(raw_pk.subject_public_key());
2✔
211
      }
2✔
212

213
      std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const override {
×
214
         count_callback_invocation("tls_verify_cert_chain");
×
215
         return std::chrono::milliseconds(0);
×
216
      }
217

218
      std::vector<uint8_t> tls_provide_cert_status(const std::vector<X509_Certificate>& chain,
×
219
                                                   const Certificate_Status_Request& csr) override {
220
         count_callback_invocation("tls_provide_cert_status");
×
221
         return Callbacks::tls_provide_cert_status(chain, csr);
×
222
      }
223

224
      std::vector<uint8_t> tls_sign_message(const Private_Key& key,
7✔
225
                                            RandomNumberGenerator& rng,
226
                                            std::string_view padding,
227
                                            Signature_Format format,
228
                                            const std::vector<uint8_t>& msg) override {
229
         BOTAN_UNUSED(key, rng);
7✔
230
         count_callback_invocation("tls_sign_message");
7✔
231

232
         if(key.algo_name() == "RSA") {
7✔
233
            if(format != Signature_Format::Standard) {
4✔
234
               throw Test_Error("TLS implementation selected unexpected signature format for RSA");
×
235
            }
236

237
            if(padding != "PSS(SHA-256,MGF1,32)") {
8✔
238
               throw Test_Error("TLS implementation selected unexpected padding for RSA: " + std::string(padding));
×
239
            }
240
         } else if(key.algo_name() == "ECDSA") {
3✔
241
            if(format != Signature_Format::DerSequence) {
3✔
242
               throw Test_Error("TLS implementation selected unexpected signature format for ECDSA");
×
243
            }
244

245
            if(padding != "SHA-256") {
6✔
246
               throw Test_Error("TLS implementation selected unexpected padding for ECDSA: " + std::string(padding));
×
247
            }
248
         } else {
249
            throw Test_Error("TLS implementation trying to sign with unexpected algorithm (" + key.algo_name() + ")");
×
250
         }
251

252
         for(const auto& mock : m_mock_signatures) {
9✔
253
            if(mock.message_to_sign == msg) {
9✔
254
               return mock.signature_to_produce;
7✔
255
            }
256
         }
257

258
         throw Test_Error("TLS implementation produced an unexpected message to be signed: " + Botan::hex_encode(msg));
×
259
      }
260

261
      bool tls_verify_message(const Public_Key& key,
7✔
262
                              std::string_view padding,
263
                              Signature_Format format,
264
                              const std::vector<uint8_t>& msg,
265
                              const std::vector<uint8_t>& sig) override {
266
         count_callback_invocation("tls_verify_message");
7✔
267
         return Callbacks::tls_verify_message(key, padding, format, msg, sig);
7✔
268
      }
269

270
      std::unique_ptr<PK_Key_Agreement_Key> tls_generate_ephemeral_key(
15✔
271
         const std::variant<TLS::Group_Params, DL_Group>& group, RandomNumberGenerator& rng) override {
272
         count_callback_invocation("tls_generate_ephemeral_key");
15✔
273
         return Callbacks::tls_generate_ephemeral_key(group, rng);
15✔
274
      }
275

276
      secure_vector<uint8_t> tls_ephemeral_key_agreement(const std::variant<TLS::Group_Params, DL_Group>& group,
13✔
277
                                                         const PK_Key_Agreement_Key& private_key,
278
                                                         const std::vector<uint8_t>& public_value,
279
                                                         RandomNumberGenerator& rng,
280
                                                         const Policy& policy) override {
281
         count_callback_invocation("tls_ephemeral_key_agreement");
13✔
282
         return Callbacks::tls_ephemeral_key_agreement(group, private_key, public_value, rng, policy);
13✔
283
      }
284

285
      void tls_inspect_handshake_msg(const Handshake_Message& message) override {
102✔
286
         count_callback_invocation("tls_inspect_handshake_msg_" + message.type_string());
306✔
287

288
         try {
102✔
289
            auto serialized_message = message.serialize();
102✔
290

291
            serialized_messages.try_emplace(message.type_string())
204✔
292
               .first->second.emplace_back(std::move(serialized_message));
102✔
293
         } catch(const Not_Implemented&) {
102✔
294
            // TODO: Once the server implementation is finished, this crutch
295
            //       can likely be removed, as all message types will have a
296
            //       serialization method with actual business logic. :o)
297
         }
×
298

299
         return Callbacks::tls_inspect_handshake_msg(message);
102✔
300
      }
301

302
      std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos) override {
×
303
         count_callback_invocation("tls_server_choose_app_protocol");
×
304
         return Callbacks::tls_server_choose_app_protocol(client_protos);
×
305
      }
306

307
      void tls_modify_extensions(Botan::TLS::Extensions& exts,
33✔
308
                                 Botan::TLS::Connection_Side side,
309
                                 Botan::TLS::Handshake_Type which_message) override {
310
         count_callback_invocation(std::string("tls_modify_extensions_") + handshake_type_to_string(which_message));
99✔
311
         m_modify_exts(exts, side, which_message);
33✔
312
         Callbacks::tls_modify_extensions(exts, side, which_message);
33✔
313
      }
33✔
314

315
      void tls_examine_extensions(const Botan::TLS::Extensions& extn,
31✔
316
                                  Connection_Side which_side,
317
                                  Botan::TLS::Handshake_Type which_message) override {
318
         count_callback_invocation(std::string("tls_examine_extensions_") + handshake_type_to_string(which_message));
93✔
319
         return Callbacks::tls_examine_extensions(extn, which_side, which_message);
31✔
320
      }
321

322
      std::string tls_peer_network_identity() override {
×
323
         count_callback_invocation("tls_peer_network_identity");
×
324
         return Callbacks::tls_peer_network_identity();
×
325
      }
326

327
      std::chrono::system_clock::time_point tls_current_timestamp() override {
23✔
328
         count_callback_invocation("tls_current_timestamp");
23✔
329
         return m_timestamp;
23✔
330
      }
331

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

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

336
      uint64_t last_received_seq_no() const { return received_seq_no; }
4✔
337

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

340
      void reset_callback_invocation_counters() { m_callback_invocations.clear(); }
60✔
341

342
   private:
343
      void count_callback_invocation(const std::string& callback_name) const {
339✔
344
         if(!m_callback_invocations.contains(callback_name)) {
339✔
345
            m_callback_invocations[callback_name] = 0;
320✔
346
         }
347

348
         m_callback_invocations[callback_name]++;
339✔
349
      }
339✔
350

351
   public:
352
      bool session_activated_called;                           // NOLINT(*-non-private-member-variables-in-classes)
353
      std::vector<Botan::X509_Certificate> certificate_chain;  // NOLINT(*-non-private-member-variables-in-classes)
354
      std::unique_ptr<Botan::Public_Key> raw_public_key;       // NOLINT(*-non-private-member-variables-in-classes)
355
      std::string negotiated_psk_identity;                     // NOLINT(*-non-private-member-variables-in-classes)
356
      std::map<std::string, std::vector<std::vector<uint8_t>>>
357
         serialized_messages;  // NOLINT(*-non-private-member-variables-in-classes)
358

359
   private:
360
      std::vector<uint8_t> send_buffer;
361
      std::vector<uint8_t> receive_buffer;
362
      uint64_t received_seq_no;
363
      Modify_Exts_Fn m_modify_exts;
364
      std::vector<MockSignature> m_mock_signatures;
365
      std::chrono::system_clock::time_point m_timestamp;
366

367
      mutable std::map<std::string, unsigned int> m_callback_invocations;
368
};
369

370
class Test_Credentials : public Botan::Credentials_Manager {
371
   public:
372
      explicit Test_Credentials(bool use_alternative_server_certificate, std::optional<ExternalPSK> external_psk) :
14✔
373
            m_alternative_server_certificate(use_alternative_server_certificate),
14✔
374
            m_external_psk(std::move(external_psk)) {
16✔
375
         Botan::DataSource_Memory in(Test::read_data_file("tls_13_rfc8448/server_key.pem"));
28✔
376
         m_server_private_key.reset(Botan::PKCS8::load_key(in).release());
14✔
377

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

385
         m_client_private_key.reset(create_private_key("RSA", *rng, "1024").release());
28✔
386
      }
28✔
387

388
      std::vector<Botan::X509_Certificate> cert_chain(const std::vector<std::string>& cert_key_types,
5✔
389
                                                      const std::vector<AlgorithmIdentifier>& cert_signature_schemes,
390
                                                      const std::string& type,
391
                                                      const std::string& context) override {
392
         BOTAN_UNUSED(cert_key_types, cert_signature_schemes, context);
5✔
393
         if(type == "tls-client") {
5✔
394
            return {client_certificate()};
2✔
395
         } else if(m_alternative_server_certificate) {
4✔
396
            return {alternative_server_certificate()};
2✔
397
         } else {
398
            return {server_certificate()};
6✔
399
         }
400
      }
5✔
401

402
      std::shared_ptr<Public_Key> find_raw_public_key(const std::vector<std::string>& key_types,
2✔
403
                                                      const std::string& type,
404
                                                      const std::string& context) override {
405
         BOTAN_UNUSED(key_types, type, context);
2✔
406
         return (type == "tls-client") ? client_raw_public_key_pair()->public_key()
3✔
407
                                       : server_raw_public_key_pair()->public_key();
5✔
408
      }
409

410
      std::shared_ptr<Botan::Private_Key> private_key_for(const Botan::X509_Certificate& cert,
5✔
411
                                                          const std::string& type,
412
                                                          const std::string& context) override {
413
         BOTAN_UNUSED(cert, context);
5✔
414

415
         if(type == "tls-client") {
5✔
416
            return m_client_private_key;
1✔
417
         }
418

419
         if(m_alternative_server_certificate) {
4✔
420
            return m_bogus_alternative_server_private_key;
1✔
421
         }
422

423
         return m_server_private_key;
3✔
424
      }
425

426
      std::shared_ptr<Botan::Private_Key> private_key_for(const Public_Key& raw_public_key,
2✔
427
                                                          const std::string& type,
428
                                                          const std::string& context) override {
429
         BOTAN_UNUSED(type, context);
2✔
430
         std::vector<std::unique_ptr<Botan::Private_Key>> keys;
2✔
431
         keys.emplace_back(client_raw_public_key_pair());
2✔
432
         keys.emplace_back(server_raw_public_key_pair());
2✔
433
         for(auto& key : keys) {
3✔
434
            if(key->fingerprint_public() == raw_public_key.fingerprint_public()) {
3✔
435
               return std::move(key);
2✔
436
            }
437
         }
438
         return nullptr;
×
439
      }
2✔
440

441
      std::vector<TLS::ExternalPSK> find_preshared_keys(std::string_view /* host */,
8✔
442
                                                        TLS::Connection_Side /* whoami */,
443
                                                        const std::vector<std::string>& identities,
444
                                                        const std::optional<std::string>& prf) override {
445
         if(!m_external_psk.has_value()) {
8✔
446
            return {};
6✔
447
         }
448

449
         ExternalPSK& epsk = m_external_psk.value();
2✔
450
         const auto found = std::find(identities.begin(), identities.end(), epsk.identity());
2✔
451
         if(!identities.empty() && found == identities.end()) {
2✔
452
            return {};
×
453
         }
454

455
         if(prf && prf != epsk.prf_algo()) {
2✔
456
            return {};
×
457
         }
458

459
         // ExternalPSK has a deleted copy constructor. We need to do some gymnastics
460
         // to copy it and leave the data in m_external_psk intact
461
         const auto secret = epsk.extract_master_secret();
2✔
462
         m_external_psk = ExternalPSK(epsk.identity(), epsk.prf_algo(), secret);
2✔
463
         std::vector<ExternalPSK> psks;
2✔
464
         psks.emplace_back(epsk.identity(), epsk.prf_algo(), secret);
2✔
465
         return psks;
2✔
466
      }
4✔
467

468
   private:
469
      bool m_alternative_server_certificate;
470
      std::optional<ExternalPSK> m_external_psk;
471
      std::shared_ptr<Private_Key> m_client_private_key;
472
      std::shared_ptr<Private_Key> m_bogus_alternative_server_private_key;
473
      std::shared_ptr<Private_Key> m_server_private_key;
474
};
475

476
class RFC8448_Text_Policy : public Botan::TLS::Text_Policy {
14✔
477
   private:
478
      Botan::TLS::Text_Policy read_policy(const std::string& policy_file) {
14✔
479
         const std::string fspath = Test::data_file("tls-policy/" + policy_file + ".txt");
42✔
480

481
         std::ifstream is(fspath.c_str());
14✔
482
         if(!is.good()) {
14✔
483
            throw Test_Error("Missing policy file " + fspath);
×
484
         }
485

486
         return Botan::TLS::Text_Policy(is);
14✔
487
      }
14✔
488

489
   public:
490
      RFC8448_Text_Policy(const std::string& policy_file, bool rfc8448 = true) :
14✔
491
            Botan::TLS::Text_Policy(read_policy(policy_file)), m_rfc8448(rfc8448) {}
14✔
492

493
      std::vector<Botan::TLS::Signature_Scheme> allowed_signature_schemes() const override {
16✔
494
         if(!m_rfc8448) {
16✔
495
            return Botan::TLS::Text_Policy::allowed_signature_schemes();
1✔
496
         }
497

498
         // We extend the allowed signature schemes with algorithms that we don't
499
         // actually support. The nature of the RFC 8448 test forces us to generate
500
         // bit-compatible TLS messages. Unfortunately, the test data offers all
501
         // those algorithms in its Client Hellos.
502
         return {
15✔
503
            Botan::TLS::Signature_Scheme::ECDSA_SHA256,
504
            Botan::TLS::Signature_Scheme::ECDSA_SHA384,
505
            Botan::TLS::Signature_Scheme::ECDSA_SHA512,
506
            Botan::TLS::Signature_Scheme::ECDSA_SHA1,  // not actually supported
507
            Botan::TLS::Signature_Scheme::RSA_PSS_SHA256,
508
            Botan::TLS::Signature_Scheme::RSA_PSS_SHA384,
509
            Botan::TLS::Signature_Scheme::RSA_PSS_SHA512,
510
            Botan::TLS::Signature_Scheme::RSA_PKCS1_SHA256,
511
            Botan::TLS::Signature_Scheme::RSA_PKCS1_SHA384,
512
            Botan::TLS::Signature_Scheme::RSA_PKCS1_SHA512,
513
            Botan::TLS::Signature_Scheme::RSA_PKCS1_SHA1,  // not actually supported
514
            Botan::TLS::Signature_Scheme(0x0402),          // DSA_SHA256, not actually supported
515
            Botan::TLS::Signature_Scheme(0x0502),          // DSA_SHA384, not actually supported
516
            Botan::TLS::Signature_Scheme(0x0602),          // DSA_SHA512, not actually supported
517
            Botan::TLS::Signature_Scheme(0x0202),          // DSA_SHA1, not actually supported
518
         };
15✔
519
      }
520

521
      // Overriding the key exchange group selection to favour the server's key
522
      // exchange group preference. This is required to enforce a Hello Retry Request
523
      // when testing RFC 8448 5. from the server side.
524
      Named_Group choose_key_exchange_group(const std::vector<Group_Params>& supported_by_peer,
8✔
525
                                            const std::vector<Group_Params>& offered_by_peer) const override {
526
         BOTAN_UNUSED(offered_by_peer);
8✔
527

528
         const auto supported_by_us = key_exchange_groups();
8✔
529
         const auto selected_group =
8✔
530
            std::find_if(supported_by_us.begin(), supported_by_us.end(), [&](const auto group) {
8✔
531
               return value_exists(supported_by_peer, group);
16✔
532
            });
533

534
         return selected_group != supported_by_us.end() ? *selected_group : Named_Group::NONE;
8✔
535
      }
8✔
536

537
   private:
538
      bool m_rfc8448;
539
};
540

541
/**
542
 * In-Memory Session Manager that stores sessions verbatim, without encryption.
543
 * Therefor it is not dependent on a random number generator and can easily be
544
 * instrumented for test inspection.
545
 */
546
class RFC8448_Session_Manager : public Botan::TLS::Session_Manager {
547
   private:
548
      decltype(auto) find_by_handle(const Session_Handle& handle) {
3✔
549
         return [=](const Session_with_Handle& session) {
18✔
550
            if(session.handle.id().has_value() && handle.id().has_value() &&
4✔
551
               session.handle.id().value() == handle.id().value()) {
2✔
552
               return true;
553
            }
554
            if(session.handle.ticket().has_value() && handle.ticket().has_value() &&
8✔
555
               session.handle.ticket().value() == handle.ticket().value()) {
10✔
556
               return true;
557
            }
558
            return false;
559
         };
6✔
560
      }
561

562
   public:
563
      RFC8448_Session_Manager() : Session_Manager(std::make_shared<Botan::Null_RNG>()) {}
28✔
564

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

567
      void store(const Session& session, const Session_Handle& handle) override {
4✔
568
         m_sessions.push_back({session, handle});
4✔
569
      }
12✔
570

571
      std::optional<Session_Handle> establish(const Session& session, const std::optional<Session_ID>&, bool) override {
1✔
572
         // we assume that the 'mocked' session is already stored in the manager,
573
         // verify that it is equivalent to the one created by the testee and
574
         // return the associated handle stored with it
575

576
         if(m_sessions.size() != 1) {
1✔
577
            throw Test_Error("No mocked session handle available; Test bug?");
×
578
         }
579

580
         const auto& [mocked_session, handle] = m_sessions.front();
1✔
581
         if(mocked_session.master_secret() != session.master_secret()) {
1✔
582
            throw Test_Error("Generated session object does not match the expected mock");
×
583
         }
584

585
         return handle;
1✔
586
      }
587

588
      std::optional<Session> retrieve_one(const Session_Handle& handle) override {
2✔
589
         auto itr = std::find_if(m_sessions.begin(), m_sessions.end(), find_by_handle(handle));
2✔
590
         if(itr == m_sessions.end()) {
2✔
591
            return std::nullopt;
1✔
592
         } else {
593
            return itr->session;
1✔
594
         }
595
      }
596

597
      std::vector<Session_with_Handle> find_some(const Server_Information& info, const size_t) override {
7✔
598
         std::vector<Session_with_Handle> found_sessions;
7✔
599
         for(const auto& [session, handle] : m_sessions) {
8✔
600
            if(session.server_info() == info) {
1✔
601
               found_sessions.emplace_back(Session_with_Handle{session, handle});
2✔
602
            }
603
         }
604

605
         return found_sessions;
7✔
606
      }
×
607

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

610
      size_t remove_all() override {
×
611
         const auto sessions = m_sessions.size();
×
612
         m_sessions.clear();
×
613
         return sessions;
×
614
      }
615

616
   private:
617
      std::vector<Session_with_Handle> m_sessions;
618
};
619

620
/**
621
 * This steers the TLS client handle and is the central entry point for the
622
 * test cases to interact with the TLS 1.3 implementation.
623
 *
624
 * Note: This class is abstract to be subclassed for both client and server tests.
625
 */
626
class TLS_Context {
627
   protected:
628
      TLS_Context(std::shared_ptr<Botan::RandomNumberGenerator> rng_in,
14✔
629
                  std::shared_ptr<const RFC8448_Text_Policy> policy,
630
                  Modify_Exts_Fn modify_exts_cb,
631
                  std::vector<MockSignature> mock_signatures,
632
                  uint64_t timestamp,
633
                  std::optional<std::pair<Session, Session_Ticket>> session_and_ticket,
634
                  std::optional<ExternalPSK> external_psk,
635
                  bool use_alternative_server_certificate) :
14✔
636
            m_callbacks(std::make_shared<Test_TLS_13_Callbacks>(
14✔
637
               std::move(modify_exts_cb), std::move(mock_signatures), timestamp)),
638
            m_creds(std::make_shared<Test_Credentials>(use_alternative_server_certificate, std::move(external_psk))),
14✔
639
            m_rng(std::move(rng_in)),
14✔
640
            m_session_mgr(std::make_shared<RFC8448_Session_Manager>()),
641
            m_policy(std::move(policy)) {
28✔
642
         if(session_and_ticket.has_value()) {
14✔
643
            m_session_mgr->store(std::get<Session>(session_and_ticket.value()),
12✔
644
                                 std::get<Session_Ticket>(session_and_ticket.value()));
3✔
645
         }
646
      }
14✔
647

648
   public:
649
      virtual ~TLS_Context() = default;
70✔
650

651
      TLS_Context(TLS_Context&) = delete;
652
      TLS_Context& operator=(const TLS_Context&) = delete;
653

654
      TLS_Context(TLS_Context&&) = delete;
655
      TLS_Context& operator=(TLS_Context&&) = delete;
656

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

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

661
      uint64_t last_received_seq_no() const { return m_callbacks->last_received_seq_no(); }
4✔
662

663
      /**
664
       * Checks that all of the listed callbacks were called at least once, no other
665
       * callbacks were called in addition to the expected ones. After the checks are
666
       * done, the callback invocation counters are reset.
667
       */
668
      void check_callback_invocations(Test::Result& result,
60✔
669
                                      const std::string& context,
670
                                      const std::vector<std::string>& callback_names) {
671
         const auto& invokes = m_callbacks->callback_invocations();
60✔
672
         for(const auto& cbn : callback_names) {
371✔
673
            result.confirm(Botan::fmt("{} was invoked (Context: {})", cbn, context),
933✔
674
                           invokes.contains(cbn) && invokes.at(cbn) > 0);
311✔
675
         }
676

677
         for(const auto& invoke : invokes) {
371✔
678
            if(invoke.second == 0) {
311✔
679
               continue;
×
680
            }
681
            result.confirm(
622✔
682
               invoke.first + " was expected (Context: " + context + ")",
1,244✔
683
               std::find(callback_names.cbegin(), callback_names.cend(), invoke.first) != callback_names.cend());
622✔
684
         }
685

686
         m_callbacks->reset_callback_invocation_counters();
60✔
687
      }
60✔
688

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

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

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

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

697
      /**
698
       * Send application data through the secure channel
699
       */
700
      virtual void send(const std::vector<uint8_t>& data) = 0;
701

702
   protected:
703
      std::shared_ptr<Test_TLS_13_Callbacks> m_callbacks;  // NOLINT(*-non-private-member-variables-in-classes)
704
      std::shared_ptr<Test_Credentials> m_creds;           // NOLINT(*-non-private-member-variables-in-classes)
705

706
      std::shared_ptr<Botan::RandomNumberGenerator> m_rng;     // NOLINT(*-non-private-member-variables-in-classes)
707
      std::shared_ptr<RFC8448_Session_Manager> m_session_mgr;  // NOLINT(*-non-private-member-variables-in-classes)
708
      std::shared_ptr<const RFC8448_Text_Policy> m_policy;     // NOLINT(*-non-private-member-variables-in-classes)
709
};
710

711
class Client_Context : public TLS_Context {
712
   public:
713
      Client_Context(std::shared_ptr<Botan::RandomNumberGenerator> rng_in,
7✔
714
                     std::shared_ptr<const RFC8448_Text_Policy> policy,
715
                     uint64_t timestamp,
716
                     Modify_Exts_Fn modify_exts_cb,
717
                     std::optional<std::pair<Session, Session_Ticket>> session_and_ticket = std::nullopt,
718
                     std::optional<ExternalPSK> external_psk = std::nullopt,
719
                     std::vector<MockSignature> mock_signatures = {}) :
7✔
720
            TLS_Context(std::move(rng_in),
721
                        std::move(policy),
722
                        std::move(modify_exts_cb),
723
                        std::move(mock_signatures),
724
                        timestamp,
725
                        std::move(session_and_ticket),
726
                        std::move(external_psk),
727
                        false),
728
            client(m_callbacks,
35✔
729
                   m_session_mgr,
7✔
730
                   m_creds,
7✔
731
                   m_policy,
7✔
732
                   m_rng,
7✔
733
                   Botan::TLS::Server_Information("server"),
14✔
734
                   Botan::TLS::Protocol_Version::TLS_V13) {}
31✔
735

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

738
      Botan::TLS::Client client;  // NOLINT(*-non-private-member-variables-in-classes)
739
};
740

741
class Server_Context : public TLS_Context {
742
   public:
743
      Server_Context(std::shared_ptr<Botan::RandomNumberGenerator> rng,
7✔
744
                     std::shared_ptr<const RFC8448_Text_Policy> policy,
745
                     uint64_t timestamp,
746
                     Modify_Exts_Fn modify_exts_cb,
747
                     std::vector<MockSignature> mock_signatures,
748
                     bool use_alternative_server_certificate = false,
749
                     std::optional<std::pair<Session, Session_Ticket>> session_and_ticket = std::nullopt,
750
                     std::optional<ExternalPSK> external_psk = std::nullopt) :
7✔
751
            TLS_Context(std::move(rng),
752
                        std::move(policy),
753
                        std::move(modify_exts_cb),
754
                        std::move(mock_signatures),
755
                        timestamp,
756
                        std::move(session_and_ticket),
757
                        std::move(external_psk),
758
                        use_alternative_server_certificate),
759
            server(m_callbacks, m_session_mgr, m_creds, m_policy, m_rng, false /* DTLS NYI */) {}
53✔
760

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

763
      Botan::TLS::Server server;  // NOLINT(*-non-private-member-variables-in-classes)
764
};
765

766
void sort_extensions(Botan::TLS::Extensions& exts, const std::vector<Botan::TLS::Extension_Code>& expected_order) {
30✔
767
   for(const auto ext_type : expected_order) {
283✔
768
      auto ext = exts.take(ext_type);
253✔
769
      if(ext != nullptr) {
253✔
770
         exts.add(std::move(ext));
230✔
771
      }
772
   }
253✔
773
}
30✔
774

775
/**
776
 * Because of the nature of the RFC 8448 test data we need to produce bit-compatible
777
 * TLS messages. Hence we sort the generated TLS extensions exactly as expected.
778
 */
779
void sort_rfc8448_extensions(Botan::TLS::Extensions& exts,
23✔
780
                             Botan::TLS::Connection_Side side,
781
                             Botan::TLS::Handshake_Type = Botan::TLS::Handshake_Type::ClientHello) {
782
   if(side == Botan::TLS::Connection_Side::Client) {
23✔
783
      sort_extensions(exts,
12✔
784
                      {
785
                         Botan::TLS::Extension_Code::ServerNameIndication,
786
                         Botan::TLS::Extension_Code::SafeRenegotiation,
787
                         Botan::TLS::Extension_Code::SupportedGroups,
788
                         Botan::TLS::Extension_Code::SessionTicket,
789
                         Botan::TLS::Extension_Code::KeyShare,
790
                         Botan::TLS::Extension_Code::EarlyData,
791
                         Botan::TLS::Extension_Code::SupportedVersions,
792
                         Botan::TLS::Extension_Code::SignatureAlgorithms,
793
                         Botan::TLS::Extension_Code::Cookie,
794
                         Botan::TLS::Extension_Code::PskKeyExchangeModes,
795
                         Botan::TLS::Extension_Code::RecordSizeLimit,
796
                         Padding::static_type(),
797
                         Botan::TLS::Extension_Code::PresharedKey,
798
                      });
799
   } else {
800
      sort_extensions(exts,
34✔
801
                      {
802
                         Botan::TLS::Extension_Code::SupportedGroups,
803
                         Botan::TLS::Extension_Code::KeyShare,
804
                         Botan::TLS::Extension_Code::Cookie,
805
                         Botan::TLS::Extension_Code::SupportedVersions,
806
                         Botan::TLS::Extension_Code::SignatureAlgorithms,
807
                         Botan::TLS::Extension_Code::RecordSizeLimit,
808
                         Botan::TLS::Extension_Code::ServerNameIndication,
809
                         Botan::TLS::Extension_Code::EarlyData,
810
                      });
811
   }
812
}
23✔
813

814
void add_renegotiation_extension(Botan::TLS::Extensions& exts) {
5✔
815
   // Renegotiation is not possible in TLS 1.3. Nevertheless, RFC 8448 requires
816
   // to add this to the Client Hello for reasons.
817
   exts.add(new Renegotiation_Extension());
5✔
818
}
5✔
819

820
void add_early_data_indication(Botan::TLS::Extensions& exts) {
1✔
821
   exts.add(new Botan::TLS::EarlyDataIndication());
1✔
822
}
1✔
823

824
std::vector<uint8_t> strip_message_header(const std::vector<uint8_t>& msg) {
31✔
825
   BOTAN_ASSERT_NOMSG(msg.size() >= 4);
31✔
826
   return {msg.begin() + 4, msg.end()};
31✔
827
}
828

829
std::vector<MockSignature> make_mock_signatures(const VarMap& vars) {
9✔
830
   std::vector<MockSignature> result;
9✔
831

832
   auto mock = [&](const std::string& msg, const std::string& sig) {
27✔
833
      if(vars.has_key(msg) && vars.has_key(sig)) {
36✔
834
         result.push_back({vars.get_opt_bin(msg), vars.get_opt_bin(sig)});
11✔
835
      }
836
   };
29✔
837

838
   mock("Server_MessageToSign", "Server_MessageSignature");
18✔
839
   mock("Client_MessageToSign", "Client_MessageSignature");
18✔
840

841
   return result;
9✔
842
}
×
843

844
}  // namespace
845

846
/**
847
 * Traffic transcripts and supporting data for the TLS RFC 8448 and TLS policy
848
 * configuration is kept in data files (accessible via `Test:::data_file()`).
849
 *
850
 * tls_13_rfc8448/transcripts.vec
851
 *   The record transcripts and RNG outputs as defined/required in RFC 8448 in
852
 *   Botan's Text_Based_Test vector format. Data from each RFC 8448 section is
853
 *   placed in a sub-section of the *.vec file. Each of those sections needs a
854
 *   specific test case implementation that is dispatched in `run_one_test()`.
855
 *
856
 * tls_13_rfc8448/client_certificate.pem
857
 *   The client certificate provided in RFC 8448 used to perform client auth.
858
 *   Note that RFC 8448 _does not_ provide the associated private key but only
859
 *   the resulting signature in the client's CertificateVerify message.
860
 *
861
 * tls_13_rfc8448/server_certificate.pem
862
 * tls_13_rfc8448/server_key.pem
863
 *   The server certificate and its associated private key.
864
 *
865
 * tls_13_rfc8448/server_certificate_client_auth.pem
866
 *   The server certificate used in the Client Authentication test case.
867
 *
868
 * tls_13_rfc8448/client_raw_public_keypair.pem
869
 * tls_13_rfc8448/server_raw_public_keypair.pem
870
 *   The raw public key pairs for client and server authentication in the
871
 *   equally named test cases.
872
 *
873
 * tls-policy/rfc8448_*.txt
874
 *   Each RFC 8448 section test required a slightly adapted Botan TLS policy
875
 *   to enable/disable certain features under test.
876
 *
877
 * While the test cases are split into Client-side and Server-side tests, the
878
 * transcript data is reused. See the concrete implementations of the abstract
879
 * Test_TLS_RFC8448 test class.
880
 */
881
class Test_TLS_RFC8448 : public Text_Based_Test {
882
   protected:
883
      // Those tests are based on the test vectors in RFC8448.
884
      virtual std::vector<Test::Result> simple_1_rtt(const VarMap& vars) = 0;
885
      virtual std::vector<Test::Result> resumed_handshake_with_0_rtt(const VarMap& vars) = 0;
886
      virtual std::vector<Test::Result> hello_retry_request(const VarMap& vars) = 0;
887
      virtual std::vector<Test::Result> client_authentication(const VarMap& vars) = 0;
888
      virtual std::vector<Test::Result> middlebox_compatibility(const VarMap& vars) = 0;
889

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

895
      virtual std::string side() const = 0;
896

897
   public:
898
      Test_TLS_RFC8448() :
2✔
899
            Text_Based_Test("tls_13_rfc8448/transcripts.vec",
900
                            // mandatory data fields
901
                            "Client_RNG_Pool,"
902
                            "Server_RNG_Pool,"
903
                            "CurrentTimestamp,"
904
                            "Record_ClientHello_1,"
905
                            "Record_ServerHello,"
906
                            "Record_ServerHandshakeMessages,"
907
                            "Record_ClientFinished,"
908
                            "Record_Client_CloseNotify,"
909
                            "Record_Server_CloseNotify",
910
                            // optional data fields
911
                            "Message_ServerHello,"
912
                            "Message_EncryptedExtensions,"
913
                            "Message_CertificateRequest,"
914
                            "Message_Server_Certificate,"
915
                            "Message_Server_CertificateVerify,"
916
                            "Message_Server_Finished,"
917
                            "Record_HelloRetryRequest,"
918
                            "Record_ClientHello_2,"
919
                            "Record_NewSessionTicket,"
920
                            "Client_AppData,"
921
                            "Record_Client_AppData,"
922
                            "Server_AppData,"
923
                            "Record_Server_AppData,"
924
                            "Client_EarlyAppData,"
925
                            "Record_Client_EarlyAppData,"
926
                            "SessionTicket,"
927
                            "Client_SessionData,"
928
                            "Server_MessageToSign,"
929
                            "Server_MessageSignature,"
930
                            "Client_MessageToSign,"
931
                            "Client_MessageSignature,"
932
                            "HelloRetryRequest_Cookie,"
933
                            "PskIdentity,"
934
                            "PskPRF,"
935
                            "PskSecret") {}
4✔
936

937
      Test::Result run_one_test(const std::string& header, const VarMap& vars) override {
14✔
938
         if(header == "Simple_1RTT_Handshake") {
14✔
939
            return Test::Result("Simple 1-RTT (" + side() + " side)", simple_1_rtt(vars));
8✔
940
         } else if(header == "Resumed_0RTT_Handshake") {
12✔
941
            return Test::Result("Resumption with 0-RTT data (" + side() + " side)", resumed_handshake_with_0_rtt(vars));
8✔
942
         } else if(header == "HelloRetryRequest_Handshake") {
10✔
943
            return Test::Result("Handshake involving Hello Retry Request (" + side() + " side)",
6✔
944
                                hello_retry_request(vars));
6✔
945
         } else if(header == "Client_Authentication_Handshake") {
8✔
946
            return Test::Result("Client Authentication (" + side() + " side)", client_authentication(vars));
8✔
947
         } else if(header == "Middlebox_Compatibility_Mode") {
6✔
948
            return Test::Result("Middlebox Compatibility Mode (" + side() + " side)", middlebox_compatibility(vars));
8✔
949
         } else if(header == "Externally_Provided_PSK_with_Ephemeral_Key") {
4✔
950
            return Test::Result("Externally Provided PSK with ephemeral key (" + side() + " side)",
6✔
951
                                externally_provided_psk_with_ephemeral_key(vars));
6✔
952
         } else if(header == "RawPublicKey_With_Client_Authentication") {
2✔
953
            return Test::Result("RawPublicKey with Client Authentication (" + side() + " side)",
6✔
954
                                raw_public_key_with_client_authentication(vars));
6✔
955
         } else {
956
            return Test::Result::Failure("test dispatcher", "unknown sub-test: " + header);
×
957
         }
958
      }
959
};
960

961
class Test_TLS_RFC8448_Client : public Test_TLS_RFC8448 {
1✔
962
   private:
963
      std::string side() const override { return "Client"; }
7✔
964

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

968
         // 32 - for client hello random
969
         // 32 - for KeyShare (eph. x25519 key pair)
970
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
2✔
971

972
         auto add_extensions_and_sort = [](Botan::TLS::Extensions& exts,
2✔
973
                                           Botan::TLS::Connection_Side side,
974
                                           Botan::TLS::Handshake_Type which_message) {
975
            if(which_message == Handshake_Type::ClientHello) {
1✔
976
               // For some reason, presumably checking compatibility, the RFC 8448 Client
977
               // Hello includes a (TLS 1.2) Session_Ticket extension. We don't normally add
978
               // this obsoleted extension in a TLS 1.3 client.
979
               exts.add(new Botan::TLS::Session_Ticket_Extension());
1✔
980

981
               add_renegotiation_extension(exts);
1✔
982
               sort_rfc8448_extensions(exts, side);
1✔
983
            }
984
         };
1✔
985

986
         std::unique_ptr<Client_Context> ctx;
1✔
987

988
         return {
1✔
989
            CHECK("Client Hello",
990
                  [&](Test::Result& result) {
1✔
991
                     ctx = std::make_unique<Client_Context>(rng,
1✔
992
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
2✔
993
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
994
                                                            add_extensions_and_sort);
1✔
995

996
                     result.confirm("client not closed", !ctx->client.is_closed());
2✔
997
                     ctx->check_callback_invocations(result,
2✔
998
                                                     "client hello prepared",
999
                                                     {
1000
                                                        "tls_emit_data",
1001
                                                        "tls_inspect_handshake_msg_client_hello",
1002
                                                        "tls_modify_extensions_client_hello",
1003
                                                        "tls_generate_ephemeral_key",
1004
                                                        "tls_current_timestamp",
1005
                                                     });
1006

1007
                     result.test_eq(
2✔
1008
                        "TLS client hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
3✔
1009
                  }),
1✔
1010

1011
            CHECK("Server Hello",
1012
                  [&](Test::Result& result) {
1✔
1013
                     result.require("ctx is available", ctx != nullptr);
1✔
1014
                     const auto server_hello = vars.get_req_bin("Record_ServerHello");
1✔
1015
                     // splitting the input data to test partial reads
1016
                     const std::vector<uint8_t> server_hello_a(server_hello.begin(), server_hello.begin() + 20);
1✔
1017
                     const std::vector<uint8_t> server_hello_b(server_hello.begin() + 20, server_hello.end());
1✔
1018

1019
                     ctx->client.received_data(server_hello_a);
1✔
1020
                     ctx->check_callback_invocations(result, "server hello partially received", {});
2✔
1021

1022
                     ctx->client.received_data(server_hello_b);
1✔
1023
                     ctx->check_callback_invocations(result,
2✔
1024
                                                     "server hello received",
1025
                                                     {"tls_inspect_handshake_msg_server_hello",
1026
                                                      "tls_examine_extensions_server_hello",
1027
                                                      "tls_ephemeral_key_agreement"});
1028

1029
                     result.confirm("client is not yet active", !ctx->client.is_active());
2✔
1030
                     result.confirm("handshake is not yet complete", !ctx->client.is_handshake_complete());
2✔
1031
                  }),
3✔
1032

1033
            CHECK("Server HS messages .. Client Finished",
1034
                  [&](Test::Result& result) {
1✔
1035
                     result.require("ctx is available", ctx != nullptr);
1✔
1036
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
2✔
1037

1038
                     ctx->check_callback_invocations(result,
2✔
1039
                                                     "encrypted handshake messages received",
1040
                                                     {"tls_inspect_handshake_msg_encrypted_extensions",
1041
                                                      "tls_inspect_handshake_msg_certificate",
1042
                                                      "tls_inspect_handshake_msg_certificate_verify",
1043
                                                      "tls_inspect_handshake_msg_finished",
1044
                                                      "tls_examine_extensions_encrypted_extensions",
1045
                                                      "tls_examine_extensions_certificate",
1046
                                                      "tls_emit_data",
1047
                                                      "tls_current_timestamp",
1048
                                                      "tls_session_established",
1049
                                                      "tls_session_activated",
1050
                                                      "tls_verify_cert_chain",
1051
                                                      "tls_verify_message"});
1052
                     result.require("certificate exists", !ctx->certs_verified().empty());
1✔
1053
                     result.require("correct certificate", ctx->certs_verified().front() == server_certificate());
2✔
1054
                     result.require("client is active", ctx->client.is_active());
1✔
1055
                     result.confirm("handshake is complete", ctx->client.is_handshake_complete());
2✔
1056

1057
                     result.test_eq("correct handshake finished",
2✔
1058
                                    ctx->pull_send_buffer(),
2✔
1059
                                    vars.get_req_bin("Record_ClientFinished"));
2✔
1060
                  }),
1✔
1061

1062
            CHECK("Post-Handshake: NewSessionTicket",
1063
                  [&](Test::Result& result) {
1✔
1064
                     result.require("ctx is available", ctx != nullptr);
1✔
1065
                     result.require("no sessions so far", ctx->stored_sessions().empty());
1✔
1066
                     ctx->client.received_data(vars.get_req_bin("Record_NewSessionTicket"));
2✔
1067

1068
                     ctx->check_callback_invocations(result,
2✔
1069
                                                     "new session ticket received",
1070
                                                     {"tls_examine_extensions_new_session_ticket",
1071
                                                      "tls_should_persist_resumption_information",
1072
                                                      "tls_current_timestamp"});
1073
                     if(result.test_eq("session was stored", ctx->stored_sessions().size(), 1)) {
1✔
1074
                        const auto& [stored_session, stored_handle] = ctx->stored_sessions().front();
1✔
1075
                        result.require("session handle contains a ticket", stored_handle.ticket().has_value());
2✔
1076
                        result.test_is_eq("session was serialized as expected",
2✔
1077
                                          Botan::unlock(stored_session.DER_encode()),
4✔
1078
                                          vars.get_req_bin("Client_SessionData"));
2✔
1079
                     }
1080
                  }),
1✔
1081

1082
            CHECK("Send Application Data",
1083
                  [&](Test::Result& result) {
1✔
1084
                     result.require("ctx is available", ctx != nullptr);
1✔
1085
                     ctx->send(vars.get_req_bin("Client_AppData"));
3✔
1086

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

1089
                     result.test_eq("correct client application data",
2✔
1090
                                    ctx->pull_send_buffer(),
2✔
1091
                                    vars.get_req_bin("Record_Client_AppData"));
2✔
1092
                  }),
1✔
1093

1094
            CHECK("Receive Application Data",
1095
                  [&](Test::Result& result) {
1✔
1096
                     result.require("ctx is available", ctx != nullptr);
1✔
1097
                     ctx->client.received_data(vars.get_req_bin("Record_Server_AppData"));
2✔
1098

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

1101
                     const auto rcvd = ctx->pull_receive_buffer();
1✔
1102
                     result.test_eq("decrypted application traffic", rcvd, vars.get_req_bin("Server_AppData"));
3✔
1103
                     result.test_is_eq("sequence number", ctx->last_received_seq_no(), uint64_t(1));
2✔
1104
                  }),
1✔
1105

1106
            CHECK("Close Connection",
1107
                  [&](Test::Result& result) {
1✔
1108
                     result.require("ctx is available", ctx != nullptr);
1✔
1109
                     ctx->client.close();
1✔
1110

1111
                     result.test_eq(
2✔
1112
                        "close payload", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
3✔
1113
                     ctx->check_callback_invocations(result, "CLOSE_NOTIFY sent", {"tls_emit_data"});
2✔
1114

1115
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
2✔
1116
                     ctx->check_callback_invocations(
2✔
1117
                        result, "CLOSE_NOTIFY received", {"tls_alert", "tls_peer_closed_connection"});
1118

1119
                     result.confirm("connection is closed", ctx->client.is_closed());
2✔
1120
                  }),
1✔
1121
         };
8✔
1122
      }
3✔
1123

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

1127
         // 32 - for client hello random
1128
         // 32 - for KeyShare (eph. x25519 key pair)
1129
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
2✔
1130

1131
         auto add_extensions_and_sort = [](Botan::TLS::Extensions& exts,
2✔
1132
                                           Botan::TLS::Connection_Side side,
1133
                                           Botan::TLS::Handshake_Type which_message) {
1134
            if(which_message == Handshake_Type::ClientHello) {
1✔
1135
               exts.add(new Padding(87));
1✔
1136

1137
               add_renegotiation_extension(exts);
1✔
1138

1139
               // TODO: Implement early data support and remove this 'hack'.
1140
               //
1141
               // Currently, the production implementation will never add this
1142
               // extension even if the resumed session would allow early data.
1143
               add_early_data_indication(exts);
1✔
1144
               sort_rfc8448_extensions(exts, side);
1✔
1145
            }
1146
         };
1✔
1147

1148
         std::unique_ptr<Client_Context> ctx;
1✔
1149

1150
         return {
1✔
1151
            CHECK("Client Hello",
1152
                  [&](Test::Result& result) {
1✔
1153
                     ctx = std::make_unique<Client_Context>(
1✔
1154
                        std::move(rng),
1155
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
2✔
1156
                        vars.get_req_u64("CurrentTimestamp"),
1✔
1157
                        add_extensions_and_sort,
1158
                        std::pair{Botan::TLS::Session(vars.get_req_bin("Client_SessionData")),
5✔
1159
                                  Botan::TLS::Session_Ticket(vars.get_req_bin("SessionTicket"))});
3✔
1160

1161
                     result.confirm("client not closed", !ctx->client.is_closed());
2✔
1162
                     ctx->check_callback_invocations(result,
2✔
1163
                                                     "client hello prepared",
1164
                                                     {
1165
                                                        "tls_emit_data",
1166
                                                        "tls_inspect_handshake_msg_client_hello",
1167
                                                        "tls_modify_extensions_client_hello",
1168
                                                        "tls_current_timestamp",
1169
                                                        "tls_generate_ephemeral_key",
1170
                                                     });
1171

1172
                     result.test_eq(
2✔
1173
                        "TLS client hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
3✔
1174
                  })
1✔
1175

1176
            // TODO: The rest of this test vector requires 0-RTT which is not
1177
            //       yet implemented. For now we can only test the client's
1178
            //       ability to offer a session resumption via PSK.
1179
         };
2✔
1180
      }
2✔
1181

1182
      std::vector<Test::Result> hello_retry_request(const VarMap& vars) override {
1✔
1183
         auto add_extensions_and_sort = [flights = 0](Botan::TLS::Extensions& exts,
3✔
1184
                                                      Botan::TLS::Connection_Side side,
1185
                                                      Botan::TLS::Handshake_Type which_message) mutable {
1186
            if(which_message == Handshake_Type::ClientHello) {
2✔
1187
               ++flights;
2✔
1188

1189
               if(flights == 1) {
2✔
1190
                  add_renegotiation_extension(exts);
1✔
1191
               }
1192

1193
               // For some reason RFC8448 decided to require this (fairly obscure) extension
1194
               // in the second flight of the Client_Hello.
1195
               if(flights == 2) {
2✔
1196
                  exts.add(new Padding(175));
1✔
1197
               }
1198

1199
               sort_rfc8448_extensions(exts, side);
2✔
1200
            }
1201
         };
2✔
1202

1203
         // Fallback RNG is required to for blinding in ECDH with P-256
1204
         auto& fallback_rng = this->rng();
1✔
1205
         auto rng = std::make_unique<Fixed_Output_RNG>(fallback_rng);
1✔
1206

1207
         // 32 - client hello random
1208
         // 32 - eph. x25519 key pair
1209
         // 32 - eph. P-256 key pair
1210
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
2✔
1211

1212
         std::unique_ptr<Client_Context> ctx;
1✔
1213

1214
         return {
1✔
1215
            CHECK("Client Hello",
1216
                  [&](Test::Result& result) {
1✔
1217
                     ctx = std::make_unique<Client_Context>(std::move(rng),
1✔
1218
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_hrr_client"),
2✔
1219
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
1220
                                                            add_extensions_and_sort);
1✔
1221
                     result.confirm("client not closed", !ctx->client.is_closed());
2✔
1222

1223
                     ctx->check_callback_invocations(result,
2✔
1224
                                                     "client hello prepared",
1225
                                                     {
1226
                                                        "tls_emit_data",
1227
                                                        "tls_inspect_handshake_msg_client_hello",
1228
                                                        "tls_modify_extensions_client_hello",
1229
                                                        "tls_generate_ephemeral_key",
1230
                                                        "tls_current_timestamp",
1231
                                                     });
1232

1233
                     result.test_eq(
2✔
1234
                        "TLS client hello (1)", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
3✔
1235
                  }),
1✔
1236

1237
            CHECK("Hello Retry Request .. second Client Hello",
1238
                  [&](Test::Result& result) {
1✔
1239
                     result.require("ctx is available", ctx != nullptr);
1✔
1240
                     ctx->client.received_data(vars.get_req_bin("Record_HelloRetryRequest"));
2✔
1241

1242
                     ctx->check_callback_invocations(result,
2✔
1243
                                                     "hello retry request received",
1244
                                                     {
1245
                                                        "tls_emit_data",
1246
                                                        "tls_inspect_handshake_msg_hello_retry_request",
1247
                                                        "tls_examine_extensions_hello_retry_request",
1248
                                                        "tls_inspect_handshake_msg_client_hello",
1249
                                                        "tls_modify_extensions_client_hello",
1250
                                                        "tls_generate_ephemeral_key",
1251
                                                     });
1252

1253
                     result.test_eq(
2✔
1254
                        "TLS client hello (2)", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_2"));
3✔
1255
                  }),
1✔
1256

1257
            CHECK("Server Hello",
1258
                  [&](Test::Result& result) {
1✔
1259
                     result.require("ctx is available", ctx != nullptr);
1✔
1260
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHello"));
2✔
1261

1262
                     ctx->check_callback_invocations(result,
2✔
1263
                                                     "server hello received",
1264
                                                     {
1265
                                                        "tls_inspect_handshake_msg_server_hello",
1266
                                                        "tls_examine_extensions_server_hello",
1267
                                                        "tls_ephemeral_key_agreement",
1268
                                                     });
1269
                  }),
1✔
1270

1271
            CHECK("Server HS Messages .. Client Finished",
1272
                  [&](Test::Result& result) {
1✔
1273
                     result.require("ctx is available", ctx != nullptr);
1✔
1274
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
2✔
1275

1276
                     ctx->check_callback_invocations(result,
2✔
1277
                                                     "encrypted handshake messages received",
1278
                                                     {"tls_inspect_handshake_msg_encrypted_extensions",
1279
                                                      "tls_inspect_handshake_msg_certificate",
1280
                                                      "tls_inspect_handshake_msg_certificate_verify",
1281
                                                      "tls_inspect_handshake_msg_finished",
1282
                                                      "tls_examine_extensions_encrypted_extensions",
1283
                                                      "tls_examine_extensions_certificate",
1284
                                                      "tls_emit_data",
1285
                                                      "tls_current_timestamp",
1286
                                                      "tls_session_established",
1287
                                                      "tls_session_activated",
1288
                                                      "tls_verify_cert_chain",
1289
                                                      "tls_verify_message"});
1290

1291
                     result.test_eq(
2✔
1292
                        "client finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished"));
3✔
1293
                  }),
1✔
1294

1295
            CHECK("Close Connection",
1296
                  [&](Test::Result& result) {
1✔
1297
                     result.require("ctx is available", ctx != nullptr);
1✔
1298
                     ctx->client.close();
1✔
1299
                     ctx->check_callback_invocations(
2✔
1300
                        result, "encrypted handshake messages received", {"tls_emit_data"});
1301
                     result.test_eq(
2✔
1302
                        "client close notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
3✔
1303

1304
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
2✔
1305
                     ctx->check_callback_invocations(
2✔
1306
                        result, "encrypted handshake messages received", {"tls_alert", "tls_peer_closed_connection"});
1307

1308
                     result.confirm("connection is closed", ctx->client.is_closed());
2✔
1309
                  }),
1✔
1310
         };
6✔
1311
      }
2✔
1312

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

1316
         // 32 - for client hello random
1317
         // 32 - for eph. x25519 key pair
1318
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
2✔
1319

1320
         auto add_extensions_and_sort = [&](Botan::TLS::Extensions& exts,
3✔
1321
                                            Botan::TLS::Connection_Side side,
1322
                                            Botan::TLS::Handshake_Type which_message) {
1323
            if(which_message == Handshake_Type::ClientHello) {
2✔
1324
               add_renegotiation_extension(exts);
1✔
1325
               sort_rfc8448_extensions(exts, side);
1✔
1326
            }
1327
         };
1328

1329
         std::unique_ptr<Client_Context> ctx;
1✔
1330

1331
         return {
1✔
1332
            CHECK("Client Hello",
1333
                  [&](Test::Result& result) {
1✔
1334
                     ctx = std::make_unique<Client_Context>(std::move(rng),
1✔
1335
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
2✔
1336
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
1337
                                                            add_extensions_and_sort,
1338
                                                            std::nullopt,
1339
                                                            std::nullopt,
1340
                                                            make_mock_signatures(vars));
3✔
1341

1342
                     ctx->check_callback_invocations(result,
2✔
1343
                                                     "initial callbacks",
1344
                                                     {
1345
                                                        "tls_emit_data",
1346
                                                        "tls_inspect_handshake_msg_client_hello",
1347
                                                        "tls_modify_extensions_client_hello",
1348
                                                        "tls_generate_ephemeral_key",
1349
                                                        "tls_current_timestamp",
1350
                                                     });
1351

1352
                     result.test_eq("Client Hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
4✔
1353
                  }),
1✔
1354

1355
            CHECK("Server Hello",
1356
                  [&](auto& result) {
1✔
1357
                     result.require("ctx is available", ctx != nullptr);
1✔
1358
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHello"));
2✔
1359

1360
                     ctx->check_callback_invocations(result,
2✔
1361
                                                     "callbacks after server hello",
1362
                                                     {
1363
                                                        "tls_examine_extensions_server_hello",
1364
                                                        "tls_inspect_handshake_msg_server_hello",
1365
                                                        "tls_ephemeral_key_agreement",
1366
                                                     });
1367
                  }),
1✔
1368

1369
            CHECK("other handshake messages and client auth",
1370
                  [&](Test::Result& result) {
1✔
1371
                     result.require("ctx is available", ctx != nullptr);
1✔
1372
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
2✔
1373

1374
                     ctx->check_callback_invocations(result,
2✔
1375
                                                     "signing callbacks invoked",
1376
                                                     {
1377
                                                        "tls_sign_message",
1378
                                                        "tls_emit_data",
1379
                                                        "tls_examine_extensions_encrypted_extensions",
1380
                                                        "tls_examine_extensions_certificate",
1381
                                                        "tls_examine_extensions_certificate_request",
1382
                                                        "tls_modify_extensions_certificate",
1383
                                                        "tls_inspect_handshake_msg_certificate",
1384
                                                        "tls_inspect_handshake_msg_certificate_request",
1385
                                                        "tls_inspect_handshake_msg_certificate_verify",
1386
                                                        "tls_inspect_handshake_msg_encrypted_extensions",
1387
                                                        "tls_inspect_handshake_msg_finished",
1388
                                                        "tls_current_timestamp",
1389
                                                        "tls_session_established",
1390
                                                        "tls_session_activated",
1391
                                                        "tls_verify_cert_chain",
1392
                                                        "tls_verify_message",
1393
                                                     });
1394

1395
                     // ClientFinished contains the entire coalesced client authentication flight
1396
                     // Messages: Certificate, CertificateVerify, Finished
1397
                     result.test_eq(
2✔
1398
                        "Client Auth and Finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished"));
3✔
1399
                  }),
1✔
1400

1401
            CHECK("Close Connection",
1402
                  [&](Test::Result& result) {
1✔
1403
                     result.require("ctx is available", ctx != nullptr);
1✔
1404
                     ctx->client.close();
1✔
1405
                     result.test_eq(
2✔
1406
                        "Client close_notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
3✔
1407

1408
                     ctx->check_callback_invocations(result,
2✔
1409
                                                     "after sending close notify",
1410
                                                     {
1411
                                                        "tls_emit_data",
1412
                                                     });
1413

1414
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
2✔
1415
                     result.confirm("connection closed", ctx->client.is_closed());
2✔
1416

1417
                     ctx->check_callback_invocations(
2✔
1418
                        result, "after receiving close notify", {"tls_alert", "tls_peer_closed_connection"});
1419
                  }),
1✔
1420
         };
5✔
1421
      }
2✔
1422

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

1426
         // 32 - client hello random
1427
         // 32 - legacy session ID
1428
         // 32 - eph. x25519 key pair
1429
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
2✔
1430

1431
         auto add_extensions_and_sort = [&](Botan::TLS::Extensions& exts,
2✔
1432
                                            Botan::TLS::Connection_Side side,
1433
                                            Botan::TLS::Handshake_Type which_message) {
1434
            if(which_message == Handshake_Type::ClientHello) {
1✔
1435
               add_renegotiation_extension(exts);
1✔
1436
               sort_rfc8448_extensions(exts, side);
1✔
1437
            }
1438
         };
1439

1440
         std::unique_ptr<Client_Context> ctx;
1✔
1441

1442
         return {
1✔
1443
            CHECK("Client Hello",
1444
                  [&](Test::Result& result) {
1✔
1445
                     ctx =
1✔
1446
                        std::make_unique<Client_Context>(std::move(rng),
1✔
1447
                                                         std::make_shared<RFC8448_Text_Policy>("rfc8448_compat_client"),
2✔
1448
                                                         vars.get_req_u64("CurrentTimestamp"),
1✔
1449
                                                         add_extensions_and_sort);
1✔
1450

1451
                     result.test_eq("Client Hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
4✔
1452

1453
                     ctx->check_callback_invocations(result,
2✔
1454
                                                     "client hello prepared",
1455
                                                     {
1456
                                                        "tls_emit_data",
1457
                                                        "tls_inspect_handshake_msg_client_hello",
1458
                                                        "tls_modify_extensions_client_hello",
1459
                                                        "tls_generate_ephemeral_key",
1460
                                                        "tls_current_timestamp",
1461
                                                     });
1462
                  }),
1✔
1463

1464
            CHECK("Server Hello + other handshake messages",
1465
                  [&](Test::Result& result) {
1✔
1466
                     result.require("ctx is available", ctx != nullptr);
1✔
1467
                     ctx->client.received_data(
2✔
1468
                        Botan::concat(vars.get_req_bin("Record_ServerHello"),
4✔
1469
                                      // ServerHandshakeMessages contains the expected ChangeCipherSpec record
1470
                                      vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
1471

1472
                     ctx->check_callback_invocations(result,
2✔
1473
                                                     "callbacks after server's first flight",
1474
                                                     {
1475
                                                        "tls_inspect_handshake_msg_server_hello",
1476
                                                        "tls_inspect_handshake_msg_encrypted_extensions",
1477
                                                        "tls_inspect_handshake_msg_certificate",
1478
                                                        "tls_inspect_handshake_msg_certificate_verify",
1479
                                                        "tls_inspect_handshake_msg_finished",
1480
                                                        "tls_examine_extensions_server_hello",
1481
                                                        "tls_examine_extensions_encrypted_extensions",
1482
                                                        "tls_examine_extensions_certificate",
1483
                                                        "tls_emit_data",
1484
                                                        "tls_current_timestamp",
1485
                                                        "tls_session_established",
1486
                                                        "tls_session_activated",
1487
                                                        "tls_verify_cert_chain",
1488
                                                        "tls_verify_message",
1489
                                                        "tls_ephemeral_key_agreement",
1490
                                                     });
1491

1492
                     result.test_eq("CCS + Client Finished",
2✔
1493
                                    ctx->pull_send_buffer(),
2✔
1494
                                    // ClientFinished contains the expected ChangeCipherSpec record
1495
                                    vars.get_req_bin("Record_ClientFinished"));
2✔
1496

1497
                     result.confirm("client is ready to send application traffic", ctx->client.is_active());
2✔
1498
                     result.confirm("handshake is complete", ctx->client.is_handshake_complete());
2✔
1499
                  }),
1✔
1500

1501
            CHECK("Close connection",
1502
                  [&](Test::Result& result) {
1✔
1503
                     result.require("ctx is available", ctx != nullptr);
1✔
1504
                     ctx->client.close();
1✔
1505

1506
                     result.test_eq(
2✔
1507
                        "Client close_notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
3✔
1508

1509
                     result.require("client cannot send application traffic anymore", !ctx->client.is_active());
1✔
1510
                     result.require("client is not fully closed yet", !ctx->client.is_closed());
1✔
1511
                     result.confirm("handshake stays completed", ctx->client.is_handshake_complete());
2✔
1512

1513
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
2✔
1514

1515
                     result.confirm("client connection was terminated", ctx->client.is_closed());
2✔
1516
                  }),
1✔
1517
         };
4✔
1518
      }
2✔
1519

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

1523
         // 32 - for client hello random
1524
         // 32 - for KeyShare (eph. x25519 key pair)
1525
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
2✔
1526

1527
         auto sort_our_extensions = [](Botan::TLS::Extensions& exts,
2✔
1528
                                       Botan::TLS::Connection_Side /* side */,
1529
                                       Botan::TLS::Handshake_Type /* which_message */) {
1530
            // This is the order of extensions when we first introduced the PSK
1531
            // implementation and generated the transcript. To stay compatible
1532
            // with the now hard-coded transcript, we pin the extension order.
1533
            sort_extensions(exts,
1✔
1534
                            {
1535
                               Botan::TLS::Extension_Code::ServerNameIndication,
1536
                               Botan::TLS::Extension_Code::SupportedGroups,
1537
                               Botan::TLS::Extension_Code::KeyShare,
1538
                               Botan::TLS::Extension_Code::SupportedVersions,
1539
                               Botan::TLS::Extension_Code::SignatureAlgorithms,
1540
                               Botan::TLS::Extension_Code::PskKeyExchangeModes,
1541
                               Botan::TLS::Extension_Code::RecordSizeLimit,
1542
                               Botan::TLS::Extension_Code::PresharedKey,
1543
                            });
1544
         };
1✔
1545

1546
         std::unique_ptr<Client_Context> ctx;
1✔
1547

1548
         return {
1✔
1549
            CHECK("Client Hello",
1550
                  [&](Test::Result& result) {
1✔
1551
                     ctx = std::make_unique<Client_Context>(
1✔
1552
                        std::move(rng),
1553
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_psk_dhe", false /* no rfc8448 */),
2✔
1554
                        vars.get_req_u64("CurrentTimestamp"),
1✔
1555
                        sort_our_extensions,
1556
                        std::nullopt,
1557
                        ExternalPSK(vars.get_req_str("PskIdentity"),
2✔
1558
                                    vars.get_req_str("PskPRF"),
2✔
1559
                                    lock(vars.get_req_bin("PskSecret"))));
5✔
1560

1561
                     result.confirm("client not closed", !ctx->client.is_closed());
2✔
1562
                     ctx->check_callback_invocations(result,
2✔
1563
                                                     "client hello prepared",
1564
                                                     {
1565
                                                        "tls_emit_data",
1566
                                                        "tls_inspect_handshake_msg_client_hello",
1567
                                                        "tls_modify_extensions_client_hello",
1568
                                                        "tls_current_timestamp",
1569
                                                        "tls_generate_ephemeral_key",
1570
                                                     });
1571

1572
                     result.test_eq(
2✔
1573
                        "TLS client hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
3✔
1574
                  }),
1✔
1575

1576
            CHECK("Server Hello",
1577
                  [&](Test::Result& result) {
1✔
1578
                     result.require("ctx is available", ctx != nullptr);
1✔
1579
                     const auto server_hello = vars.get_req_bin("Record_ServerHello");
1✔
1580
                     ctx->client.received_data(server_hello);
1✔
1581
                     ctx->check_callback_invocations(result,
2✔
1582
                                                     "server hello received",
1583
                                                     {"tls_inspect_handshake_msg_server_hello",
1584
                                                      "tls_examine_extensions_server_hello",
1585
                                                      "tls_ephemeral_key_agreement"});
1586

1587
                     result.confirm("client is not yet active", !ctx->client.is_active());
2✔
1588
                     result.confirm("handshake is not yet complete", !ctx->client.is_handshake_complete());
2✔
1589
                  }),
1✔
1590

1591
            CHECK(
1592
               "Server HS messages .. Client Finished",
1593
               [&](Test::Result& result) {
1✔
1594
                  result.require("ctx is available", ctx != nullptr);
1✔
1595
                  ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
2✔
1596

1597
                  ctx->check_callback_invocations(result,
2✔
1598
                                                  "encrypted handshake messages received",
1599
                                                  {"tls_inspect_handshake_msg_encrypted_extensions",
1600
                                                   "tls_inspect_handshake_msg_finished",
1601
                                                   "tls_examine_extensions_encrypted_extensions",
1602
                                                   "tls_emit_data",
1603
                                                   "tls_current_timestamp",
1604
                                                   "tls_session_established",
1605
                                                   "tls_session_activated"});
1606
                  result.require("PSK negotiated", ctx->psk_identity_negotiated() == vars.get_req_str("PskIdentity"));
2✔
1607
                  result.require("client is active", ctx->client.is_active());
1✔
1608
                  result.confirm("handshake is complete", ctx->client.is_handshake_complete());
2✔
1609

1610
                  result.test_eq(
2✔
1611
                     "correct handshake finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished"));
3✔
1612
               }),
1✔
1613

1614
            CHECK("Send Application Data",
1615
                  [&](Test::Result& result) {
1✔
1616
                     result.require("ctx is available", ctx != nullptr);
1✔
1617
                     ctx->send(vars.get_req_bin("Client_AppData"));
3✔
1618

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

1621
                     result.test_eq("correct client application data",
2✔
1622
                                    ctx->pull_send_buffer(),
2✔
1623
                                    vars.get_req_bin("Record_Client_AppData"));
2✔
1624
                  }),
1✔
1625

1626
            CHECK("Receive Application Data",
1627
                  [&](Test::Result& result) {
1✔
1628
                     result.require("ctx is available", ctx != nullptr);
1✔
1629
                     ctx->client.received_data(vars.get_req_bin("Record_Server_AppData"));
2✔
1630

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

1633
                     const auto rcvd = ctx->pull_receive_buffer();
1✔
1634
                     result.test_eq("decrypted application traffic", rcvd, vars.get_req_bin("Server_AppData"));
3✔
1635
                     result.test_is_eq("sequence number", ctx->last_received_seq_no(), uint64_t(0));
2✔
1636
                  }),
1✔
1637

1638
            CHECK("Close Connection",
1639
                  [&](Test::Result& result) {
1✔
1640
                     result.require("ctx is available", ctx != nullptr);
1✔
1641
                     ctx->client.close();
1✔
1642

1643
                     result.test_eq(
2✔
1644
                        "close payload", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
3✔
1645
                     ctx->check_callback_invocations(result, "CLOSE_NOTIFY sent", {"tls_emit_data"});
2✔
1646

1647
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
2✔
1648
                     ctx->check_callback_invocations(
2✔
1649
                        result, "CLOSE_NOTIFY received", {"tls_alert", "tls_peer_closed_connection"});
1650

1651
                     result.confirm("connection is closed", ctx->client.is_closed());
2✔
1652
                  }),
1✔
1653
         };
7✔
1654
      }
2✔
1655

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

1659
         // 32 - for client hello random
1660
         // 32 - for KeyShare (eph. x25519 key pair)
1661
         add_entropy(*rng, vars.get_req_bin("Client_RNG_Pool"));
2✔
1662

1663
         auto sort_our_extensions = [&](Botan::TLS::Extensions& exts,
3✔
1664
                                        Botan::TLS::Connection_Side /* side */,
1665
                                        Botan::TLS::Handshake_Type /* which_message */) {
1666
            // This is the order of extensions when we first introduced the raw
1667
            // public key authentication implementation and generated the transcript.
1668
            // To stay compatible with the now hard-coded transcript, we pin the
1669
            // extension order.
1670
            sort_extensions(exts,
2✔
1671
                            {
1672
                               Botan::TLS::Extension_Code::ServerNameIndication,
1673
                               Botan::TLS::Extension_Code::SupportedGroups,
1674
                               Botan::TLS::Extension_Code::KeyShare,
1675
                               Botan::TLS::Extension_Code::SupportedVersions,
1676
                               Botan::TLS::Extension_Code::SignatureAlgorithms,
1677
                               Botan::TLS::Extension_Code::PskKeyExchangeModes,
1678
                               Botan::TLS::Extension_Code::RecordSizeLimit,
1679
                               Botan::TLS::Extension_Code::ClientCertificateType,
1680
                               Botan::TLS::Extension_Code::ServerCertificateType,
1681
                            });
1682
         };
2✔
1683

1684
         std::unique_ptr<Client_Context> ctx;
1✔
1685

1686
         return {
1✔
1687
            CHECK("Client Hello",
1688
                  [&](Test::Result& result) {
1✔
1689
                     ctx = std::make_unique<Client_Context>(std::move(rng),
1✔
1690
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_rawpubkey"),
2✔
1691
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
1692
                                                            sort_our_extensions,
1693
                                                            std::nullopt,
1694
                                                            std::nullopt,
1695
                                                            make_mock_signatures(vars));
3✔
1696

1697
                     ctx->check_callback_invocations(result,
2✔
1698
                                                     "initial callbacks",
1699
                                                     {
1700
                                                        "tls_emit_data",
1701
                                                        "tls_inspect_handshake_msg_client_hello",
1702
                                                        "tls_modify_extensions_client_hello",
1703
                                                        "tls_generate_ephemeral_key",
1704
                                                        "tls_current_timestamp",
1705
                                                     });
1706

1707
                     result.test_eq("Client Hello", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientHello_1"));
4✔
1708
                  }),
1✔
1709

1710
            CHECK("Server Hello",
1711
                  [&](auto& result) {
1✔
1712
                     result.require("ctx is available", ctx != nullptr);
1✔
1713
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHello"));
2✔
1714

1715
                     ctx->check_callback_invocations(result,
2✔
1716
                                                     "callbacks after server hello",
1717
                                                     {
1718
                                                        "tls_examine_extensions_server_hello",
1719
                                                        "tls_inspect_handshake_msg_server_hello",
1720
                                                        "tls_ephemeral_key_agreement",
1721
                                                     });
1722
                  }),
1✔
1723

1724
            CHECK("other handshake messages and client auth",
1725
                  [&](Test::Result& result) {
1✔
1726
                     result.require("ctx is available", ctx != nullptr);
1✔
1727
                     ctx->client.received_data(vars.get_req_bin("Record_ServerHandshakeMessages"));
2✔
1728

1729
                     ctx->check_callback_invocations(result,
2✔
1730
                                                     "signing callbacks invoked",
1731
                                                     {
1732
                                                        "tls_sign_message",
1733
                                                        "tls_emit_data",
1734
                                                        "tls_examine_extensions_encrypted_extensions",
1735
                                                        "tls_examine_extensions_certificate",
1736
                                                        "tls_examine_extensions_certificate_request",
1737
                                                        "tls_modify_extensions_certificate",
1738
                                                        "tls_inspect_handshake_msg_certificate",
1739
                                                        "tls_inspect_handshake_msg_certificate_request",
1740
                                                        "tls_inspect_handshake_msg_certificate_verify",
1741
                                                        "tls_inspect_handshake_msg_encrypted_extensions",
1742
                                                        "tls_inspect_handshake_msg_finished",
1743
                                                        "tls_current_timestamp",
1744
                                                        "tls_session_established",
1745
                                                        "tls_session_activated",
1746
                                                        "tls_verify_raw_public_key",
1747
                                                        "tls_verify_message",
1748
                                                     });
1749

1750
                     const auto raw_pk = ctx->client.peer_raw_public_key();
1✔
1751
                     result.confirm(
2✔
1752
                        "Received server's raw public key",
1753
                        raw_pk && raw_pk->fingerprint_public() == server_raw_public_key_pair()->fingerprint_public());
5✔
1754

1755
                     // ClientFinished contains the entire coalesced client authentication flight
1756
                     // Messages: Certificate, CertificateVerify, Finished
1757
                     result.test_eq(
2✔
1758
                        "Client Auth and Finished", ctx->pull_send_buffer(), vars.get_req_bin("Record_ClientFinished"));
3✔
1759
                  }),
1✔
1760

1761
            CHECK("Close Connection",
1762
                  [&](Test::Result& result) {
1✔
1763
                     result.require("ctx is available", ctx != nullptr);
1✔
1764
                     ctx->client.close();
1✔
1765
                     result.test_eq(
2✔
1766
                        "Client close_notify", ctx->pull_send_buffer(), vars.get_req_bin("Record_Client_CloseNotify"));
3✔
1767

1768
                     ctx->check_callback_invocations(result,
2✔
1769
                                                     "after sending close notify",
1770
                                                     {
1771
                                                        "tls_emit_data",
1772
                                                     });
1773

1774
                     ctx->client.received_data(vars.get_req_bin("Record_Server_CloseNotify"));
2✔
1775
                     result.confirm("connection closed", ctx->client.is_closed());
2✔
1776

1777
                     ctx->check_callback_invocations(
2✔
1778
                        result, "after receiving close notify", {"tls_alert", "tls_peer_closed_connection"});
1779
                  }),
1✔
1780
         };
5✔
1781
      }
2✔
1782
};
1783

1784
class Test_TLS_RFC8448_Server : public Test_TLS_RFC8448 {
1✔
1785
   private:
1786
      std::string side() const override { return "Server"; }
7✔
1787

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

1791
         // 32 - for server hello random
1792
         // 32 - for KeyShare (eph. x25519 key pair)  --  I guess?
1793
         //  4 - for ticket_age_add (in New Session Ticket)
1794
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
2✔
1795

1796
         std::unique_ptr<Server_Context> ctx;
1✔
1797

1798
         return {
1✔
1799
            CHECK("Send Client Hello",
1800
                  [&](Test::Result& result) {
1✔
1801
                     auto add_early_data_and_sort = [&](Botan::TLS::Extensions& exts,
5✔
1802
                                                        Botan::TLS::Connection_Side side,
1803
                                                        Botan::TLS::Handshake_Type type) {
1804
                        if(type == Handshake_Type::NewSessionTicket) {
4✔
1805
                           exts.add(new EarlyDataIndication(1024));
1✔
1806
                        }
1807
                        sort_rfc8448_extensions(exts, side, type);
4✔
1808
                     };
4✔
1809

1810
                     ctx = std::make_unique<Server_Context>(
1✔
1811
                        std::move(rng),
1812
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
2✔
1813
                        vars.get_req_u64("CurrentTimestamp"),
1✔
1814
                        add_early_data_and_sort,
1815
                        make_mock_signatures(vars),
1✔
1816
                        false,
2✔
1817
                        std::pair{Botan::TLS::Session(vars.get_req_bin("Client_SessionData")),
5✔
1818
                                  Botan::TLS::Session_Ticket(vars.get_req_bin("SessionTicket"))});
3✔
1819
                     result.confirm("server not closed", !ctx->server.is_closed());
2✔
1820

1821
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
2✔
1822

1823
                     ctx->check_callback_invocations(result,
2✔
1824
                                                     "client hello received",
1825
                                                     {"tls_emit_data",
1826
                                                      "tls_examine_extensions_client_hello",
1827
                                                      "tls_modify_extensions_server_hello",
1828
                                                      "tls_modify_extensions_encrypted_extensions",
1829
                                                      "tls_modify_extensions_certificate",
1830
                                                      "tls_sign_message",
1831
                                                      "tls_generate_ephemeral_key",
1832
                                                      "tls_ephemeral_key_agreement",
1833
                                                      "tls_inspect_handshake_msg_client_hello",
1834
                                                      "tls_inspect_handshake_msg_server_hello",
1835
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
1836
                                                      "tls_inspect_handshake_msg_certificate",
1837
                                                      "tls_inspect_handshake_msg_certificate_verify",
1838
                                                      "tls_inspect_handshake_msg_finished"});
1839
                  }),
1✔
1840

1841
            CHECK("Verify generated messages in server's first flight",
1842
                  [&](Test::Result& result) {
1✔
1843
                     result.require("ctx is available", ctx != nullptr);
1✔
1844
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
1845

1846
                     result.test_eq("Server Hello",
3✔
1847
                                    msgs.at("server_hello")[0],
2✔
1848
                                    strip_message_header(vars.get_opt_bin("Message_ServerHello")));
3✔
1849
                     result.test_eq("Encrypted Extensions",
3✔
1850
                                    msgs.at("encrypted_extensions")[0],
2✔
1851
                                    strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
3✔
1852
                     result.test_eq("Certificate",
3✔
1853
                                    msgs.at("certificate")[0],
2✔
1854
                                    strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
3✔
1855
                     result.test_eq("CertificateVerify",
3✔
1856
                                    msgs.at("certificate_verify")[0],
2✔
1857
                                    strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
3✔
1858

1859
                     result.test_eq("Server's entire first flight",
2✔
1860
                                    ctx->pull_send_buffer(),
2✔
1861
                                    concat(vars.get_req_bin("Record_ServerHello"),
4✔
1862
                                           vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
1863

1864
                     // Note: is_active() defines that we can send application data.
1865
                     //       RFC 8446 Section 4.4.4 explicitly allows that for servers
1866
                     //       that did not receive the client's Finished message, yet.
1867
                     //       However, before receiving and validating this message,
1868
                     //       the handshake is not yet finished.
1869
                     result.confirm("Server can now send application data", ctx->server.is_active());
2✔
1870
                     result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete());
2✔
1871
                  }),
1✔
1872

1873
            CHECK("Send Client Finished",
1874
                  [&](Test::Result& result) {
1✔
1875
                     result.require("ctx is available", ctx != nullptr);
1✔
1876
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
2✔
1877

1878
                     ctx->check_callback_invocations(result,
2✔
1879
                                                     "client finished received",
1880
                                                     {"tls_inspect_handshake_msg_finished",
1881
                                                      "tls_current_timestamp",
1882
                                                      "tls_session_established",
1883
                                                      "tls_session_activated"});
1884
                  }),
1✔
1885

1886
            CHECK("Send Session Ticket",
1887
                  [&](Test::Result& result) {
1✔
1888
                     result.require("ctx is available", ctx != nullptr);
1✔
1889
                     const auto new_tickets = ctx->server.send_new_session_tickets(1);
1✔
1890

1891
                     result.test_eq("session ticket was sent", new_tickets, 1);
1✔
1892

1893
                     ctx->check_callback_invocations(result,
2✔
1894
                                                     "issued new session ticket",
1895
                                                     {"tls_inspect_handshake_msg_new_session_ticket",
1896
                                                      "tls_current_timestamp",
1897
                                                      "tls_emit_data",
1898
                                                      "tls_modify_extensions_new_session_ticket",
1899
                                                      "tls_should_persist_resumption_information"});
1900
                  }),
1✔
1901

1902
            CHECK("Verify generated new session ticket message",
1903
                  [&](Test::Result& result) {
1✔
1904
                     result.require("ctx is available", ctx != nullptr);
1✔
1905
                     result.test_eq(
2✔
1906
                        "New Session Ticket", ctx->pull_send_buffer(), vars.get_req_bin("Record_NewSessionTicket"));
3✔
1907
                  }),
1✔
1908

1909
            CHECK("Receive Application Data",
1910
                  [&](Test::Result& result) {
1✔
1911
                     result.require("ctx is available", ctx != nullptr);
1✔
1912
                     ctx->server.received_data(vars.get_req_bin("Record_Client_AppData"));
2✔
1913
                     ctx->check_callback_invocations(result, "application data received", {"tls_record_received"});
2✔
1914

1915
                     const auto rcvd = ctx->pull_receive_buffer();
1✔
1916
                     result.test_eq("decrypted application traffic", rcvd, vars.get_req_bin("Client_AppData"));
3✔
1917
                     result.test_is_eq("sequence number", ctx->last_received_seq_no(), uint64_t(0));
2✔
1918
                  }),
1✔
1919

1920
            CHECK("Send Application Data",
1921
                  [&](Test::Result& result) {
1✔
1922
                     result.require("ctx is available", ctx != nullptr);
1✔
1923
                     ctx->send(vars.get_req_bin("Server_AppData"));
3✔
1924

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

1927
                     result.test_eq("correct server application data",
2✔
1928
                                    ctx->pull_send_buffer(),
2✔
1929
                                    vars.get_req_bin("Record_Server_AppData"));
2✔
1930
                  }),
1✔
1931

1932
            CHECK("Receive Client's close_notify",
1933
                  [&](Test::Result& result) {
1✔
1934
                     result.require("ctx is available", ctx != nullptr);
1✔
1935
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
2✔
1936

1937
                     ctx->check_callback_invocations(
2✔
1938
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
1939

1940
                     result.confirm("connection is not yet closed", !ctx->server.is_closed());
2✔
1941
                     result.confirm("connection is still active", ctx->server.is_active());
2✔
1942
                     result.confirm("handshake is still finished", ctx->server.is_handshake_complete());
2✔
1943
                  }),
1✔
1944

1945
            CHECK("Expect Server close_notify",
1946
                  [&](Test::Result& result) {
1✔
1947
                     result.require("ctx is available", ctx != nullptr);
1✔
1948
                     ctx->server.close();
1✔
1949

1950
                     result.confirm("connection is now inactive", !ctx->server.is_active());
2✔
1951
                     result.confirm("connection is now closed", ctx->server.is_closed());
2✔
1952
                     result.confirm("handshake is still finished", ctx->server.is_handshake_complete());
2✔
1953
                     result.test_eq("Server's close notify",
2✔
1954
                                    ctx->pull_send_buffer(),
2✔
1955
                                    vars.get_req_bin("Record_Server_CloseNotify"));
2✔
1956
                  }),
1✔
1957
         };
10✔
1958
      }
2✔
1959

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

1963
         // 32 - for server hello random
1964
         // 32 - for KeyShare (eph. x25519 key pair)
1965
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
2✔
1966

1967
         std::unique_ptr<Server_Context> ctx;
1✔
1968

1969
         return {
1✔
1970
            CHECK("Receive Client Hello",
1971
                  [&](Test::Result& result) {
1✔
1972
                     auto add_cookie_and_sort = [&](Botan::TLS::Extensions& exts,
3✔
1973
                                                    Botan::TLS::Connection_Side side,
1974
                                                    Botan::TLS::Handshake_Type type) {
1975
                        if(type == Handshake_Type::EncryptedExtensions) {
2✔
1976
                           exts.add(new EarlyDataIndication());
1✔
1977
                        }
1978
                        sort_rfc8448_extensions(exts, side, type);
2✔
1979
                     };
2✔
1980

1981
                     ctx = std::make_unique<Server_Context>(
1✔
1982
                        std::move(rng),
1983
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_1rtt"),
2✔
1984
                        vars.get_req_u64("CurrentTimestamp"),
1✔
1985
                        add_cookie_and_sort,
1986
                        make_mock_signatures(vars),
1✔
1987
                        false,
2✔
1988
                        std::pair{Botan::TLS::Session(vars.get_req_bin("Client_SessionData")),
5✔
1989
                                  Botan::TLS::Session_Ticket(vars.get_req_bin("SessionTicket"))});
3✔
1990
                     result.confirm("server not closed", !ctx->server.is_closed());
2✔
1991

1992
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
2✔
1993

1994
                     ctx->check_callback_invocations(result,
2✔
1995
                                                     "client hello received",
1996
                                                     {
1997
                                                        "tls_emit_data",
1998
                                                        "tls_current_timestamp",
1999
                                                        "tls_generate_ephemeral_key",
2000
                                                        "tls_ephemeral_key_agreement",
2001
                                                        "tls_examine_extensions_client_hello",
2002
                                                        "tls_modify_extensions_server_hello",
2003
                                                        "tls_modify_extensions_encrypted_extensions",
2004
                                                        "tls_inspect_handshake_msg_client_hello",
2005
                                                        "tls_inspect_handshake_msg_server_hello",
2006
                                                        "tls_inspect_handshake_msg_encrypted_extensions",
2007
                                                        "tls_inspect_handshake_msg_finished",
2008
                                                     });
2009
                  }),
1✔
2010

2011
            CHECK("Verify generated messages in server's first flight",
2012
                  [&](Test::Result& result) {
1✔
2013
                     result.require("ctx is available", ctx != nullptr);
1✔
2014
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2015

2016
                     result.test_eq("Server Hello",
3✔
2017
                                    msgs.at("server_hello")[0],
2✔
2018
                                    strip_message_header(vars.get_opt_bin("Message_ServerHello")));
3✔
2019
                     result.test_eq("Encrypted Extensions",
3✔
2020
                                    msgs.at("encrypted_extensions")[0],
2✔
2021
                                    strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
3✔
2022

2023
                     result.test_eq("Server's entire first flight",
2✔
2024
                                    ctx->pull_send_buffer(),
2✔
2025
                                    concat(vars.get_req_bin("Record_ServerHello"),
4✔
2026
                                           vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2027

2028
                     // Note: is_active() defines that we can send application data.
2029
                     //       RFC 8446 Section 4.4.4 explicitly allows that for servers
2030
                     //       that did not receive the client's Finished message, yet.
2031
                     //       However, before receiving and validating this message,
2032
                     //       the handshake is not yet finished.
2033
                     result.confirm("Server can now send application data", ctx->server.is_active());
2✔
2034
                     result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete());
2✔
2035
                  }),
1✔
2036

2037
            // TODO: The rest of this test vector requires 0-RTT which is not
2038
            //       yet implemented. For now we can only test the server's
2039
            //       ability to acknowledge a session resumption via PSK.
2040
         };
3✔
2041
      }
2✔
2042

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

2048
         // 32 - for server hello random
2049
         // 32 - for KeyShare (eph. P-256 key pair)
2050
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
2✔
2051

2052
         std::unique_ptr<Server_Context> ctx;
1✔
2053

2054
         return {
1✔
2055
            CHECK("Receive Client Hello",
2056
                  [&](Test::Result& result) {
1✔
2057
                     auto add_cookie_and_sort = [&](Botan::TLS::Extensions& exts,
5✔
2058
                                                    Botan::TLS::Connection_Side side,
2059
                                                    Botan::TLS::Handshake_Type type) {
2060
                        if(type == Handshake_Type::HelloRetryRequest) {
4✔
2061
                           // This cookie needs to be mocked into the HRR since RFC 8448 contains it.
2062
                           exts.add(new Cookie(vars.get_opt_bin("HelloRetryRequest_Cookie")));
2✔
2063
                        }
2064
                        sort_rfc8448_extensions(exts, side, type);
4✔
2065
                     };
4✔
2066

2067
                     ctx = std::make_unique<Server_Context>(std::move(rng),
1✔
2068
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_hrr_server"),
2✔
2069
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
2070
                                                            add_cookie_and_sort,
2071
                                                            make_mock_signatures(vars));
3✔
2072
                     result.confirm("server not closed", !ctx->server.is_closed());
2✔
2073

2074
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
2✔
2075

2076
                     ctx->check_callback_invocations(result,
2✔
2077
                                                     "client hello received",
2078
                                                     {"tls_emit_data",
2079
                                                      "tls_examine_extensions_client_hello",
2080
                                                      "tls_modify_extensions_hello_retry_request",
2081
                                                      "tls_inspect_handshake_msg_client_hello",
2082
                                                      "tls_inspect_handshake_msg_hello_retry_request"});
2083
                  }),
1✔
2084

2085
            CHECK("Verify generated Hello Retry Request message",
2086
                  [&](Test::Result& result) {
1✔
2087
                     result.require("ctx is available", ctx != nullptr);
1✔
2088
                     result.test_eq("Server's Hello Retry Request record",
2✔
2089
                                    ctx->pull_send_buffer(),
2✔
2090
                                    vars.get_req_bin("Record_HelloRetryRequest"));
2✔
2091
                     result.confirm("TLS handshake not yet finished", !ctx->server.is_active());
2✔
2092
                     result.confirm("handshake is not yet complete", !ctx->server.is_handshake_complete());
2✔
2093
                  }),
1✔
2094

2095
            CHECK("Receive updated Client Hello message",
2096
                  [&](Test::Result& result) {
1✔
2097
                     result.require("ctx is available", ctx != nullptr);
1✔
2098
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_2"));
2✔
2099

2100
                     ctx->check_callback_invocations(result,
2✔
2101
                                                     "updated client hello received",
2102
                                                     {"tls_emit_data",
2103
                                                      "tls_examine_extensions_client_hello",
2104
                                                      "tls_modify_extensions_server_hello",
2105
                                                      "tls_modify_extensions_encrypted_extensions",
2106
                                                      "tls_modify_extensions_certificate",
2107
                                                      "tls_sign_message",
2108
                                                      "tls_generate_ephemeral_key",
2109
                                                      "tls_ephemeral_key_agreement",
2110
                                                      "tls_inspect_handshake_msg_client_hello",
2111
                                                      "tls_inspect_handshake_msg_server_hello",
2112
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2113
                                                      "tls_inspect_handshake_msg_certificate",
2114
                                                      "tls_inspect_handshake_msg_certificate_verify",
2115
                                                      "tls_inspect_handshake_msg_finished"});
2116
                  }),
1✔
2117

2118
            CHECK("Verify generated messages in server's second flight",
2119
                  [&](Test::Result& result) {
1✔
2120
                     result.require("ctx is available", ctx != nullptr);
1✔
2121
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2122

2123
                     result.test_eq("Server Hello",
3✔
2124
                                    msgs.at("server_hello")[0],
2✔
2125
                                    strip_message_header(vars.get_opt_bin("Message_ServerHello")));
3✔
2126
                     result.test_eq("Encrypted Extensions",
3✔
2127
                                    msgs.at("encrypted_extensions")[0],
2✔
2128
                                    strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
3✔
2129
                     result.test_eq("Certificate",
3✔
2130
                                    msgs.at("certificate")[0],
2✔
2131
                                    strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
3✔
2132
                     result.test_eq("CertificateVerify",
3✔
2133
                                    msgs.at("certificate_verify")[0],
2✔
2134
                                    strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
3✔
2135
                     result.test_eq("Finished",
3✔
2136
                                    msgs.at("finished")[0],
2✔
2137
                                    strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
3✔
2138

2139
                     result.test_eq("Server's entire second flight",
2✔
2140
                                    ctx->pull_send_buffer(),
2✔
2141
                                    concat(vars.get_req_bin("Record_ServerHello"),
4✔
2142
                                           vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2143
                     result.confirm("Server could now send application data", ctx->server.is_active());
2✔
2144
                     result.confirm("handshake is not yet complete",
1✔
2145
                                    !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2146
                  }),
1✔
2147

2148
            CHECK("Receive Client Finished",
2149
                  [&](Test::Result& result) {
1✔
2150
                     result.require("ctx is available", ctx != nullptr);
1✔
2151
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
2✔
2152

2153
                     ctx->check_callback_invocations(result,
2✔
2154
                                                     "client finished received",
2155
                                                     {"tls_inspect_handshake_msg_finished",
2156
                                                      "tls_current_timestamp",
2157
                                                      "tls_session_established",
2158
                                                      "tls_session_activated"});
2159

2160
                     result.confirm("TLS handshake finished", ctx->server.is_active());
2✔
2161
                     result.confirm("handshake is complete", ctx->server.is_handshake_complete());
2✔
2162
                  }),
1✔
2163

2164
            CHECK("Receive Client close_notify",
2165
                  [&](Test::Result& result) {
1✔
2166
                     result.require("ctx is available", ctx != nullptr);
1✔
2167
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
2✔
2168

2169
                     ctx->check_callback_invocations(
2✔
2170
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2171

2172
                     result.confirm("connection is not yet closed", !ctx->server.is_closed());
2✔
2173
                     result.confirm("connection is still active", ctx->server.is_active());
2✔
2174
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2175
                  }),
1✔
2176

2177
            CHECK("Expect Server close_notify",
2178
                  [&](Test::Result& result) {
1✔
2179
                     result.require("ctx is available", ctx != nullptr);
1✔
2180
                     ctx->server.close();
1✔
2181

2182
                     result.confirm("connection is now inactive", !ctx->server.is_active());
2✔
2183
                     result.confirm("connection is now closed", ctx->server.is_closed());
2✔
2184
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2185
                     result.test_eq("Server's close notify",
2✔
2186
                                    ctx->pull_send_buffer(),
2✔
2187
                                    vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2188
                  }),
1✔
2189

2190
         };
8✔
2191
      }
2✔
2192

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

2196
         // 32 - for server hello random
2197
         // 32 - for KeyShare (eph. x25519 pair)
2198
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
2✔
2199

2200
         std::unique_ptr<Server_Context> ctx;
1✔
2201

2202
         return {
1✔
2203
            CHECK("Receive Client Hello",
2204
                  [&](Test::Result& result) {
1✔
2205
                     ctx = std::make_unique<Server_Context>(
1✔
2206
                        std::move(rng),
2207
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_client_auth_server"),
2✔
2208
                        vars.get_req_u64("CurrentTimestamp"),
1✔
2209
                        sort_rfc8448_extensions,
2210
                        make_mock_signatures(vars),
1✔
2211
                        true /* use alternative certificate */);
2✔
2212
                     result.confirm("server not closed", !ctx->server.is_closed());
2✔
2213

2214
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
2✔
2215

2216
                     ctx->check_callback_invocations(result,
2✔
2217
                                                     "client hello received",
2218
                                                     {"tls_emit_data",
2219
                                                      "tls_examine_extensions_client_hello",
2220
                                                      "tls_modify_extensions_server_hello",
2221
                                                      "tls_modify_extensions_encrypted_extensions",
2222
                                                      "tls_modify_extensions_certificate_request",
2223
                                                      "tls_modify_extensions_certificate",
2224
                                                      "tls_sign_message",
2225
                                                      "tls_generate_ephemeral_key",
2226
                                                      "tls_ephemeral_key_agreement",
2227
                                                      "tls_inspect_handshake_msg_client_hello",
2228
                                                      "tls_inspect_handshake_msg_server_hello",
2229
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2230
                                                      "tls_inspect_handshake_msg_certificate_request",
2231
                                                      "tls_inspect_handshake_msg_certificate",
2232
                                                      "tls_inspect_handshake_msg_certificate_verify",
2233
                                                      "tls_inspect_handshake_msg_finished"});
2234
                  }),
1✔
2235

2236
            CHECK("Verify server's generated handshake messages",
2237
                  [&](Test::Result& result) {
1✔
2238
                     result.require("ctx is available", ctx != nullptr);
1✔
2239
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2240

2241
                     result.test_eq("Server Hello",
3✔
2242
                                    msgs.at("server_hello")[0],
2✔
2243
                                    strip_message_header(vars.get_opt_bin("Message_ServerHello")));
3✔
2244
                     result.test_eq("Encrypted Extensions",
3✔
2245
                                    msgs.at("encrypted_extensions")[0],
2✔
2246
                                    strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
3✔
2247
                     result.test_eq("Certificate Request",
3✔
2248
                                    msgs.at("certificate_request")[0],
2✔
2249
                                    strip_message_header(vars.get_opt_bin("Message_CertificateRequest")));
3✔
2250
                     result.test_eq("Certificate",
3✔
2251
                                    msgs.at("certificate")[0],
2✔
2252
                                    strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
3✔
2253
                     result.test_eq("CertificateVerify",
3✔
2254
                                    msgs.at("certificate_verify")[0],
2✔
2255
                                    strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
3✔
2256
                     result.test_eq("Finished",
3✔
2257
                                    msgs.at("finished")[0],
2✔
2258
                                    strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
3✔
2259

2260
                     result.test_eq("Server's entire first flight",
2✔
2261
                                    ctx->pull_send_buffer(),
2✔
2262
                                    concat(vars.get_req_bin("Record_ServerHello"),
4✔
2263
                                           vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2264

2265
                     result.confirm("Not yet aware of client's cert chain", ctx->server.peer_cert_chain().empty());
2✔
2266
                     result.confirm("Server could now send application data", ctx->server.is_active());
2✔
2267
                     result.confirm("handshake is not yet complete",
1✔
2268
                                    !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2269
                  }),
1✔
2270

2271
            CHECK("Receive Client's second flight",
2272
                  [&](Test::Result& result) {
1✔
2273
                     result.require("ctx is available", ctx != nullptr);
1✔
2274
                     // This encrypted message contains the following messages:
2275
                     // * client's Certificate message
2276
                     // * client's Certificate_Verify message
2277
                     // * client's Finished message
2278
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
2✔
2279

2280
                     ctx->check_callback_invocations(result,
2✔
2281
                                                     "client finished received",
2282
                                                     {"tls_inspect_handshake_msg_certificate",
2283
                                                      "tls_inspect_handshake_msg_certificate_verify",
2284
                                                      "tls_inspect_handshake_msg_finished",
2285
                                                      "tls_examine_extensions_certificate",
2286
                                                      "tls_verify_cert_chain",
2287
                                                      "tls_verify_message",
2288
                                                      "tls_current_timestamp",
2289
                                                      "tls_session_established",
2290
                                                      "tls_session_activated"});
2291

2292
                     const auto cert_chain = ctx->server.peer_cert_chain();
1✔
2293
                     result.confirm("Received client's cert chain",
2✔
2294
                                    !cert_chain.empty() && cert_chain.front() == client_certificate());
2✔
2295

2296
                     result.confirm("TLS handshake finished", ctx->server.is_active());
2✔
2297
                     result.confirm("handshake is complete", ctx->server.is_handshake_complete());
2✔
2298
                  }),
1✔
2299

2300
            CHECK("Receive Client close_notify",
2301
                  [&](Test::Result& result) {
1✔
2302
                     result.require("ctx is available", ctx != nullptr);
1✔
2303
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
2✔
2304

2305
                     ctx->check_callback_invocations(
2✔
2306
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2307

2308
                     result.confirm("connection is not yet closed", !ctx->server.is_closed());
2✔
2309
                     result.confirm("connection is still active", ctx->server.is_active());
2✔
2310
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2311
                  }),
1✔
2312

2313
            CHECK("Expect Server close_notify",
2314
                  [&](Test::Result& result) {
1✔
2315
                     result.require("ctx is available", ctx != nullptr);
1✔
2316
                     ctx->server.close();
1✔
2317

2318
                     result.confirm("connection is now inactive", !ctx->server.is_active());
2✔
2319
                     result.confirm("connection is now closed", ctx->server.is_closed());
2✔
2320
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2321
                     result.test_eq("Server's close notify",
2✔
2322
                                    ctx->pull_send_buffer(),
2✔
2323
                                    vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2324
                  }),
1✔
2325

2326
         };
6✔
2327
      }
2✔
2328

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

2332
         // 32 - for server hello random
2333
         // 32 - for KeyShare (eph. x25519 pair)
2334
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
2✔
2335

2336
         std::unique_ptr<Server_Context> ctx;
1✔
2337

2338
         return {
1✔
2339
            CHECK("Receive Client Hello",
2340
                  [&](Test::Result& result) {
1✔
2341
                     ctx =
1✔
2342
                        std::make_unique<Server_Context>(std::move(rng),
1✔
2343
                                                         std::make_shared<RFC8448_Text_Policy>("rfc8448_compat_server"),
2✔
2344
                                                         vars.get_req_u64("CurrentTimestamp"),
1✔
2345
                                                         sort_rfc8448_extensions,
2346
                                                         make_mock_signatures(vars));
3✔
2347
                     result.confirm("server not closed", !ctx->server.is_closed());
2✔
2348

2349
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
2✔
2350

2351
                     ctx->check_callback_invocations(result,
2✔
2352
                                                     "client hello received",
2353
                                                     {"tls_emit_data",
2354
                                                      "tls_examine_extensions_client_hello",
2355
                                                      "tls_modify_extensions_server_hello",
2356
                                                      "tls_modify_extensions_encrypted_extensions",
2357
                                                      "tls_modify_extensions_certificate",
2358
                                                      "tls_sign_message",
2359
                                                      "tls_generate_ephemeral_key",
2360
                                                      "tls_ephemeral_key_agreement",
2361
                                                      "tls_inspect_handshake_msg_client_hello",
2362
                                                      "tls_inspect_handshake_msg_server_hello",
2363
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2364
                                                      "tls_inspect_handshake_msg_certificate",
2365
                                                      "tls_inspect_handshake_msg_certificate_verify",
2366
                                                      "tls_inspect_handshake_msg_finished"});
2367
                  }),
1✔
2368

2369
            CHECK("Verify server's generated handshake messages",
2370
                  [&](Test::Result& result) {
1✔
2371
                     result.require("ctx is available", ctx != nullptr);
1✔
2372
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2373

2374
                     result.test_eq("Server Hello",
3✔
2375
                                    msgs.at("server_hello")[0],
2✔
2376
                                    strip_message_header(vars.get_opt_bin("Message_ServerHello")));
3✔
2377
                     result.test_eq("Encrypted Extensions",
3✔
2378
                                    msgs.at("encrypted_extensions")[0],
2✔
2379
                                    strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
3✔
2380
                     result.test_eq("Certificate",
3✔
2381
                                    msgs.at("certificate")[0],
2✔
2382
                                    strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
3✔
2383
                     result.test_eq("CertificateVerify",
3✔
2384
                                    msgs.at("certificate_verify")[0],
2✔
2385
                                    strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
3✔
2386
                     result.test_eq("Finished",
3✔
2387
                                    msgs.at("finished")[0],
2✔
2388
                                    strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
3✔
2389

2390
                     // Those records contain the required Change Cipher Spec message the server must produce for compatibility mode compliance
2391
                     result.test_eq("Server's entire first flight",
2✔
2392
                                    ctx->pull_send_buffer(),
2✔
2393
                                    concat(vars.get_req_bin("Record_ServerHello"),
4✔
2394
                                           vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2395

2396
                     result.confirm("Server could now send application data", ctx->server.is_active());
2✔
2397
                     result.confirm("handshake is not yet complete",
1✔
2398
                                    !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2399
                  }),
1✔
2400

2401
            CHECK("Receive Client Finished",
2402
                  [&](Test::Result& result) {
1✔
2403
                     result.require("ctx is available", ctx != nullptr);
1✔
2404
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
2✔
2405

2406
                     ctx->check_callback_invocations(result,
2✔
2407
                                                     "client finished received",
2408
                                                     {"tls_inspect_handshake_msg_finished",
2409
                                                      "tls_current_timestamp",
2410
                                                      "tls_session_established",
2411
                                                      "tls_session_activated"});
2412

2413
                     result.confirm("TLS handshake fully finished", ctx->server.is_active());
2✔
2414
                     result.confirm("handshake is complete", ctx->server.is_handshake_complete());
2✔
2415
                  }),
1✔
2416

2417
            CHECK("Receive Client close_notify",
2418
                  [&](Test::Result& result) {
1✔
2419
                     result.require("ctx is available", ctx != nullptr);
1✔
2420
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
2✔
2421

2422
                     ctx->check_callback_invocations(
2✔
2423
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2424

2425
                     result.confirm("connection is not yet closed", !ctx->server.is_closed());
2✔
2426
                     result.confirm("connection is still active", ctx->server.is_active());
2✔
2427
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2428
                  }),
1✔
2429

2430
            CHECK("Expect Server close_notify",
2431
                  [&](Test::Result& result) {
1✔
2432
                     result.require("ctx is available", ctx != nullptr);
1✔
2433
                     ctx->server.close();
1✔
2434

2435
                     result.confirm("connection is now inactive", !ctx->server.is_active());
2✔
2436
                     result.confirm("connection is now closed", ctx->server.is_closed());
2✔
2437
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2438
                     result.test_eq("Server's close notify",
2✔
2439
                                    ctx->pull_send_buffer(),
2✔
2440
                                    vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2441
                  }),
1✔
2442

2443
         };
6✔
2444
      }
2✔
2445

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

2449
         // 32 - for server hello random
2450
         // 32 - for KeyShare (eph. x25519 key pair)
2451
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
2✔
2452

2453
         std::unique_ptr<Server_Context> ctx;
1✔
2454

2455
         return {
1✔
2456
            CHECK("Send Client Hello",
2457
                  [&](Test::Result& result) {
1✔
2458
                     auto sort_our_extensions = [&](Botan::TLS::Extensions& exts,
3✔
2459
                                                    Botan::TLS::Connection_Side /* side */,
2460
                                                    Botan::TLS::Handshake_Type type) {
2461
                        // This is the order of extensions when we first introduced the PSK
2462
                        // implementation and generated the transcript. To stay compatible
2463
                        // with the now hard-coded transcript, we pin the extension order.
2464
                        if(type == Botan::TLS::Handshake_Type::EncryptedExtensions) {
2✔
2465
                           sort_extensions(exts,
2✔
2466
                                           {
2467
                                              Botan::TLS::Extension_Code::SupportedGroups,
2468
                                              Botan::TLS::Extension_Code::RecordSizeLimit,
2469
                                              Botan::TLS::Extension_Code::ServerNameIndication,
2470
                                           });
2471
                        } else if(type == Botan::TLS::Handshake_Type::ServerHello) {
1✔
2472
                           sort_extensions(exts,
2✔
2473
                                           {
2474
                                              Botan::TLS::Extension_Code::SupportedVersions,
2475
                                              Botan::TLS::Extension_Code::KeyShare,
2476
                                              Botan::TLS::Extension_Code::PresharedKey,
2477
                                           });
2478
                        }
2479
                     };
2✔
2480

2481
                     ctx = std::make_unique<Server_Context>(
1✔
2482
                        std::move(rng),
2483
                        std::make_shared<RFC8448_Text_Policy>("rfc8448_psk_dhe", false /* no rfc8448 */),
2✔
2484
                        vars.get_req_u64("CurrentTimestamp"),
1✔
2485
                        sort_our_extensions,
2486
                        make_mock_signatures(vars),
1✔
2487
                        false,
1✔
2488
                        std::nullopt,
2489
                        ExternalPSK(vars.get_req_str("PskIdentity"),
2✔
2490
                                    vars.get_req_str("PskPRF"),
2✔
2491
                                    lock(vars.get_req_bin("PskSecret"))));
5✔
2492
                     result.confirm("server not closed", !ctx->server.is_closed());
2✔
2493

2494
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
2✔
2495

2496
                     ctx->check_callback_invocations(result,
2✔
2497
                                                     "client hello received",
2498
                                                     {"tls_emit_data",
2499
                                                      "tls_examine_extensions_client_hello",
2500
                                                      "tls_modify_extensions_server_hello",
2501
                                                      "tls_modify_extensions_encrypted_extensions",
2502
                                                      "tls_generate_ephemeral_key",
2503
                                                      "tls_ephemeral_key_agreement",
2504
                                                      "tls_inspect_handshake_msg_client_hello",
2505
                                                      "tls_inspect_handshake_msg_server_hello",
2506
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2507
                                                      "tls_inspect_handshake_msg_finished"});
2508
                  }),
1✔
2509

2510
            CHECK("Verify generated messages in server's first flight",
2511
                  [&](Test::Result& result) {
1✔
2512
                     result.require("ctx is available", ctx != nullptr);
1✔
2513
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2514

2515
                     result.test_eq("Server Hello",
3✔
2516
                                    msgs.at("server_hello")[0],
2✔
2517
                                    strip_message_header(vars.get_opt_bin("Message_ServerHello")));
3✔
2518
                     result.test_eq("Encrypted Extensions",
3✔
2519
                                    msgs.at("encrypted_extensions")[0],
2✔
2520
                                    strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
3✔
2521
                     result.test_eq("Server Finished",
3✔
2522
                                    msgs.at("finished")[0],
2✔
2523
                                    strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
3✔
2524

2525
                     result.test_eq("Server's entire first flight",
2✔
2526
                                    ctx->pull_send_buffer(),
2✔
2527
                                    concat(vars.get_req_bin("Record_ServerHello"),
4✔
2528
                                           vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2529

2530
                     result.confirm("Server can now send application data", ctx->server.is_active());
2✔
2531
                     result.confirm("handshake is not yet complete",
1✔
2532
                                    !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2533
                  }),
1✔
2534

2535
            CHECK("Send Client Finished",
2536
                  [&](Test::Result& result) {
1✔
2537
                     result.require("ctx is available", ctx != nullptr);
1✔
2538
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
2✔
2539
                     result.require("PSK negotiated",
2✔
2540
                                    ctx->psk_identity_negotiated() == vars.get_req_str("PskIdentity"));
2✔
2541

2542
                     ctx->check_callback_invocations(result,
2✔
2543
                                                     "client finished received",
2544
                                                     {"tls_inspect_handshake_msg_finished",
2545
                                                      "tls_current_timestamp",
2546
                                                      "tls_session_established",
2547
                                                      "tls_session_activated"});
2548
                  }),
1✔
2549

2550
            CHECK("Exchange Application Data",
2551
                  [&](Test::Result& result) {
1✔
2552
                     result.require("ctx is available", ctx != nullptr);
1✔
2553
                     ctx->server.received_data(vars.get_req_bin("Record_Client_AppData"));
2✔
2554
                     ctx->check_callback_invocations(result, "application data received", {"tls_record_received"});
2✔
2555

2556
                     const auto rcvd = ctx->pull_receive_buffer();
1✔
2557
                     result.test_eq("decrypted application traffic", rcvd, vars.get_req_bin("Client_AppData"));
3✔
2558
                     result.test_is_eq("sequence number", ctx->last_received_seq_no(), uint64_t(0));
1✔
2559

2560
                     ctx->send(vars.get_req_bin("Server_AppData"));
3✔
2561
                     ctx->check_callback_invocations(result, "application data sent", {"tls_emit_data"});
2✔
2562
                     result.test_eq("correct server application data",
2✔
2563
                                    ctx->pull_send_buffer(),
2✔
2564
                                    vars.get_req_bin("Record_Server_AppData"));
2✔
2565
                  }),
1✔
2566

2567
            CHECK("Terminate Connection",
2568
                  [&](Test::Result& result) {
1✔
2569
                     result.require("ctx is available", ctx != nullptr);
1✔
2570
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
2✔
2571

2572
                     ctx->check_callback_invocations(
2✔
2573
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2574

2575
                     result.confirm("connection is not yet closed", !ctx->server.is_closed());
2✔
2576
                     result.confirm("connection is still active", ctx->server.is_active());
2✔
2577
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2578

2579
                     ctx->server.close();
1✔
2580

2581
                     result.confirm("connection is now inactive", !ctx->server.is_active());
2✔
2582
                     result.confirm("connection is now closed", ctx->server.is_closed());
2✔
2583
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2584
                     result.test_eq("Server's close notify",
2✔
2585
                                    ctx->pull_send_buffer(),
2✔
2586
                                    vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2587
                  }),
1✔
2588
         };
6✔
2589
      }
2✔
2590

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

2594
         // 32 - for server hello random
2595
         // 32 - for KeyShare (eph. x25519 key pair)
2596
         add_entropy(*rng, vars.get_req_bin("Server_RNG_Pool"));
2✔
2597

2598
         auto sort_our_extensions =
1✔
2599
            [&](Botan::TLS::Extensions& exts, Botan::TLS::Connection_Side /* side */, Botan::TLS::Handshake_Type type) {
4✔
2600
               // This is the order of extensions when we first introduced the raw
2601
               // public key authentication implementation and generated the transcript.
2602
               // To stay compatible with the now hard-coded transcript, we pin the
2603
               // extension order.
2604
               if(type == Botan::TLS::Handshake_Type::EncryptedExtensions) {
4✔
2605
                  sort_extensions(exts,
2✔
2606
                                  {
2607
                                     Botan::TLS::Extension_Code::ClientCertificateType,
2608
                                     Botan::TLS::Extension_Code::ServerCertificateType,
2609
                                     Botan::TLS::Extension_Code::SupportedGroups,
2610
                                     Botan::TLS::Extension_Code::RecordSizeLimit,
2611
                                     Botan::TLS::Extension_Code::ServerNameIndication,
2612
                                  });
2613
               } else if(type == Botan::TLS::Handshake_Type::ServerHello) {
3✔
2614
                  sort_extensions(exts,
2✔
2615
                                  {
2616
                                     Botan::TLS::Extension_Code::KeyShare,
2617
                                     Botan::TLS::Extension_Code::SupportedVersions,
2618
                                  });
2619
               }
2620
            };
4✔
2621

2622
         std::unique_ptr<Server_Context> ctx;
1✔
2623

2624
         return {
1✔
2625
            CHECK("Receive Client Hello",
2626
                  [&](Test::Result& result) {
1✔
2627
                     ctx = std::make_unique<Server_Context>(std::move(rng),
1✔
2628
                                                            std::make_shared<RFC8448_Text_Policy>("rfc8448_rawpubkey"),
2✔
2629
                                                            vars.get_req_u64("CurrentTimestamp"),
1✔
2630
                                                            sort_our_extensions,
2631
                                                            make_mock_signatures(vars));
3✔
2632
                     result.confirm("server not closed", !ctx->server.is_closed());
2✔
2633

2634
                     ctx->server.received_data(vars.get_req_bin("Record_ClientHello_1"));
2✔
2635

2636
                     ctx->check_callback_invocations(result,
2✔
2637
                                                     "client hello received",
2638
                                                     {"tls_emit_data",
2639
                                                      "tls_examine_extensions_client_hello",
2640
                                                      "tls_modify_extensions_server_hello",
2641
                                                      "tls_modify_extensions_encrypted_extensions",
2642
                                                      "tls_modify_extensions_certificate_request",
2643
                                                      "tls_modify_extensions_certificate",
2644
                                                      "tls_sign_message",
2645
                                                      "tls_generate_ephemeral_key",
2646
                                                      "tls_ephemeral_key_agreement",
2647
                                                      "tls_inspect_handshake_msg_client_hello",
2648
                                                      "tls_inspect_handshake_msg_server_hello",
2649
                                                      "tls_inspect_handshake_msg_encrypted_extensions",
2650
                                                      "tls_inspect_handshake_msg_certificate_request",
2651
                                                      "tls_inspect_handshake_msg_certificate",
2652
                                                      "tls_inspect_handshake_msg_certificate_verify",
2653
                                                      "tls_inspect_handshake_msg_finished"});
2654
                  }),
1✔
2655

2656
            CHECK("Verify server's generated handshake messages",
2657
                  [&](Test::Result& result) {
1✔
2658
                     result.require("ctx is available", ctx != nullptr);
1✔
2659
                     const auto& msgs = ctx->observed_handshake_messages();
1✔
2660

2661
                     result.test_eq("Server Hello",
3✔
2662
                                    msgs.at("server_hello")[0],
2✔
2663
                                    strip_message_header(vars.get_opt_bin("Message_ServerHello")));
3✔
2664
                     result.test_eq("Encrypted Extensions",
3✔
2665
                                    msgs.at("encrypted_extensions")[0],
2✔
2666
                                    strip_message_header(vars.get_opt_bin("Message_EncryptedExtensions")));
3✔
2667
                     result.test_eq("Certificate Request",
3✔
2668
                                    msgs.at("certificate_request")[0],
2✔
2669
                                    strip_message_header(vars.get_opt_bin("Message_CertificateRequest")));
3✔
2670
                     result.test_eq("Certificate",
3✔
2671
                                    msgs.at("certificate")[0],
2✔
2672
                                    strip_message_header(vars.get_opt_bin("Message_Server_Certificate")));
3✔
2673
                     result.test_eq("CertificateVerify",
3✔
2674
                                    msgs.at("certificate_verify")[0],
2✔
2675
                                    strip_message_header(vars.get_opt_bin("Message_Server_CertificateVerify")));
3✔
2676
                     result.test_eq("Finished",
3✔
2677
                                    msgs.at("finished")[0],
2✔
2678
                                    strip_message_header(vars.get_opt_bin("Message_Server_Finished")));
3✔
2679

2680
                     result.test_eq("Server's entire first flight",
2✔
2681
                                    ctx->pull_send_buffer(),
2✔
2682
                                    concat(vars.get_req_bin("Record_ServerHello"),
4✔
2683
                                           vars.get_req_bin("Record_ServerHandshakeMessages")));
2✔
2684

2685
                     result.confirm("Not yet aware of client's cert chain", ctx->server.peer_cert_chain().empty());
2✔
2686
                     result.confirm("Server could now send application data", ctx->server.is_active());
2✔
2687
                     result.confirm("handshake is not yet complete",
1✔
2688
                                    !ctx->server.is_handshake_complete());  // See RFC 8446 4.4.4
1✔
2689
                  }),
1✔
2690

2691
            CHECK("Receive Client's second flight",
2692
                  [&](Test::Result& result) {
1✔
2693
                     result.require("ctx is available", ctx != nullptr);
1✔
2694
                     // This encrypted message contains the following messages:
2695
                     // * client's Certificate message
2696
                     // * client's Certificate_Verify message
2697
                     // * client's Finished message
2698
                     ctx->server.received_data(vars.get_req_bin("Record_ClientFinished"));
2✔
2699

2700
                     ctx->check_callback_invocations(result,
2✔
2701
                                                     "client finished received",
2702
                                                     {"tls_inspect_handshake_msg_certificate",
2703
                                                      "tls_inspect_handshake_msg_certificate_verify",
2704
                                                      "tls_inspect_handshake_msg_finished",
2705
                                                      "tls_examine_extensions_certificate",
2706
                                                      "tls_verify_raw_public_key",
2707
                                                      "tls_verify_message",
2708
                                                      "tls_current_timestamp",
2709
                                                      "tls_session_established",
2710
                                                      "tls_session_activated"});
2711

2712
                     const auto raw_pk = ctx->server.peer_raw_public_key();
1✔
2713
                     result.confirm(
2✔
2714
                        "Received client's raw public key",
2715
                        raw_pk && raw_pk->fingerprint_public() == client_raw_public_key_pair()->fingerprint_public());
5✔
2716

2717
                     result.confirm("TLS handshake finished", ctx->server.is_active());
2✔
2718
                     result.confirm("handshake is complete", ctx->server.is_handshake_complete());
2✔
2719
                  }),
1✔
2720

2721
            CHECK("Receive Client close_notify",
2722
                  [&](Test::Result& result) {
1✔
2723
                     result.require("ctx is available", ctx != nullptr);
1✔
2724
                     ctx->server.received_data(vars.get_req_bin("Record_Client_CloseNotify"));
2✔
2725

2726
                     ctx->check_callback_invocations(
2✔
2727
                        result, "client finished received", {"tls_alert", "tls_peer_closed_connection"});
2728

2729
                     result.confirm("connection is not yet closed", !ctx->server.is_closed());
2✔
2730
                     result.confirm("connection is still active", ctx->server.is_active());
2✔
2731
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2732
                  }),
1✔
2733

2734
            CHECK("Expect Server close_notify",
2735
                  [&](Test::Result& result) {
1✔
2736
                     result.require("ctx is available", ctx != nullptr);
1✔
2737
                     ctx->server.close();
1✔
2738

2739
                     result.confirm("connection is now inactive", !ctx->server.is_active());
2✔
2740
                     result.confirm("connection is now closed", ctx->server.is_closed());
2✔
2741
                     result.confirm("handshake is still complete", ctx->server.is_handshake_complete());
2✔
2742
                     result.test_eq("Server's close notify",
2✔
2743
                                    ctx->pull_send_buffer(),
2✔
2744
                                    vars.get_req_bin("Record_Server_CloseNotify"));
2✔
2745
                  }),
1✔
2746
         };
6✔
2747
      }
2✔
2748
};
2749

2750
BOTAN_REGISTER_TEST("tls", "tls_rfc8448_client", Test_TLS_RFC8448_Client);
2751
BOTAN_REGISTER_TEST("tls", "tls_rfc8448_server", Test_TLS_RFC8448_Server);
2752

2753
#endif
2754

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

© 2026 Coveralls, Inc