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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

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

90.22
/src/tests/test_tls_messages.cpp
1
/*
2
* (C) 2016 Juraj Somorovsky
3
* (C) 2021 Elektrobit Automotive GmbH
4
* (C) 2022 Hannes Rantzsch, René Meusel - neXenio GmbH
5
* (C) 2022 René Meusel - Rohde & Schwarz Cybersecurity
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9

10
#include "tests.h"
11

12
#if defined(BOTAN_HAS_TLS)
13
   #include <botan/hex.h>
14
   #include <botan/mac.h>
15
   #include <botan/ocsp.h>
16
   #include <botan/tls_alert.h>
17
   #include <botan/tls_callbacks.h>
18
   #include <botan/tls_ciphersuite.h>
19
   #include <botan/tls_handshake_msg.h>
20
   #include <botan/tls_messages.h>
21
   #include <botan/tls_version.h>
22
   #include <botan/internal/loadstor.h>
23
   #include <exception>
24
   #if defined(BOTAN_HAS_TLS_13)
25
      #include "test_rng.h"
26

27
      #include <botan/internal/tls_reader.h>
28
   #endif
29
#endif
30

31
namespace Botan_Tests {
32

33
namespace {
34

35
#if defined(BOTAN_HAS_TLS)
36
Test::Result test_hello_verify_request() {
2✔
37
   Test::Result result("hello_verify_request construction");
2✔
38

39
   std::vector<uint8_t> test_data;
2✔
40
   std::vector<uint8_t> key_data(32);
2✔
41
   Botan::SymmetricKey sk(key_data);
2✔
42

43
   // Compute cookie over an empty string with an empty test data
44
   Botan::TLS::Hello_Verify_Request hfr(test_data, "", sk);
2✔
45

46
   // Compute HMAC
47
   auto hmac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)");
2✔
48
   hmac->set_key(sk);
2✔
49
   hmac->update_be(uint64_t(0));  // length of client hello
2✔
50
   hmac->update_be(uint64_t(0));  // length of client identity
2✔
51
   std::vector<uint8_t> test = unlock(hmac->final());
4✔
52

53
   result.test_eq("Cookie comparison", hfr.cookie(), test);
2✔
54
   return result;
2✔
55
}
10✔
56

57
class Test_Callbacks : public Botan::TLS::Callbacks {
×
58
   public:
59
      Test_Callbacks(Test::Result& result) : m_result(result) {}
11✔
60

61
   public:
62
      void tls_emit_data(std::span<const uint8_t>) override {
×
63
         m_result.test_failure("unsolicited call to tls_emit_data");
×
64
      }
×
65

66
      void tls_record_received(uint64_t, std::span<const uint8_t>) override {
×
67
         m_result.test_failure("unsolicited call to tls_record_received");
×
68
      }
×
69

70
      void tls_alert(Botan::TLS::Alert) override { m_result.test_failure("unsolicited call to tls_alert"); }
×
71

72
      void tls_session_established(const Botan::TLS::Session_Summary&) override {
×
73
         m_result.test_failure("unsolicited call to tls_session_established");
×
74
      }
×
75

76
   private:
77
      Test::Result& m_result;
78
};
79

80
class TLS_Message_Parsing_Test final : public Text_Based_Test {
×
81
   public:
82
      TLS_Message_Parsing_Test() :
1✔
83
            Text_Based_Test("tls", "Buffer,Exception", "Protocol,AdditionalData,Ciphersuite,Name") {}
4✔
84

85
      Test::Result run_one_test(const std::string& algo, const VarMap& vars) override {
46✔
86
         const std::vector<uint8_t> buffer = vars.get_req_bin("Buffer");
46✔
87
         const std::vector<uint8_t> protocol = vars.get_opt_bin("Protocol");
46✔
88
         const std::vector<uint8_t> ciphersuite = vars.get_opt_bin("Ciphersuite");
46✔
89
         const std::string exception = vars.get_req_str("Exception");
46✔
90
         const std::string expected_name = vars.get_opt_str("Name", "");
92✔
91
         const bool is_positive_test = exception.empty();
46✔
92

93
         Test::Result result(algo + " parsing");
46✔
94

95
         if(is_positive_test) {
46✔
96
            try {
17✔
97
               if(algo == "cert_verify") {
17✔
98
                  Botan::TLS::Certificate_Verify message(buffer);
2✔
99
               } else if(algo == "client_hello") {
17✔
100
                  const std::string extensions = vars.get_req_str("AdditionalData");
4✔
101
                  Botan::TLS::Protocol_Version pv(protocol[0], protocol[1]);
4✔
102
                  Botan::TLS::Client_Hello_12 message(buffer);
4✔
103
                  result.test_eq("Protocol version", message.legacy_version().to_string(), pv.to_string());
8✔
104
                  std::vector<uint8_t> buf;
4✔
105
                  for(const Botan::TLS::Extension_Code& type : message.extension_types()) {
28✔
106
                     uint16_t u16type = static_cast<uint16_t>(type);
24✔
107
                     buf.push_back(Botan::get_byte<0>(u16type));
24✔
108
                     buf.push_back(Botan::get_byte<1>(u16type));
24✔
109
                  }
×
110
                  result.test_eq("Hello extensions", Botan::hex_encode(buf), extensions);
11✔
111
               } else if(algo == "hello_verify") {
18✔
112
                  Botan::TLS::Hello_Verify_Request message(buffer);
1✔
113
               } else if(algo == "hello_request") {
11✔
114
                  Botan::TLS::Hello_Request message(buffer);
1✔
115
               } else if(algo == "new_session_ticket") {
10✔
116
                  Botan::TLS::New_Session_Ticket_12 message(buffer);
3✔
117
               } else if(algo == "server_hello") {
9✔
118
                  const std::string extensions = vars.get_req_str("AdditionalData");
2✔
119
                  Botan::TLS::Protocol_Version pv(protocol[0], protocol[1]);
2✔
120
                  Botan::TLS::Ciphersuite cs =
2✔
121
                     Botan::TLS::Ciphersuite::by_id(Botan::make_uint16(ciphersuite[0], ciphersuite[1])).value();
2✔
122
                  Botan::TLS::Server_Hello_12 message(buffer);
2✔
123
                  result.test_eq("Protocol version", message.legacy_version().to_string(), pv.to_string());
4✔
124
                  result.confirm("Ciphersuite", (message.ciphersuite() == cs.ciphersuite_code()));
4✔
125
                  std::vector<uint8_t> buf;
2✔
126
                  for(const Botan::TLS::Extension_Code& type : message.extension_types()) {
11✔
127
                     uint16_t u16type = static_cast<uint16_t>(type);
9✔
128
                     buf.push_back(Botan::get_byte<0>(u16type));
9✔
129
                     buf.push_back(Botan::get_byte<1>(u16type));
9✔
130
                  }
×
131
                  result.test_eq("Hello extensions", Botan::hex_encode(buf), extensions);
6✔
132
               } else if(algo == "alert") {
8✔
133
                  Botan::secure_vector<uint8_t> sb(buffer.begin(), buffer.end());
3✔
134
                  Botan::TLS::Alert message(sb);
3✔
135
                  result.test_lt("Alert type vectors result to UNKNOWN_CA or ACCESS_DENIED, which is shorter than 15",
6✔
136
                                 message.type_string().size(),
6✔
137
                                 15);
138
               } else if(algo == "cert_status") {
4✔
139
                  Botan::TLS::Certificate_Status message(buffer, Botan::TLS::Connection_Side::Server);
1✔
140

141
                  Botan::OCSP::Response resp(message.response());
1✔
142

143
                  const std::vector<std::string> CNs = resp.signer_name().get_attribute("CN");
1✔
144

145
                  // This is not requird by OCSP protocol, we are just using it as a test here
146
                  if(result.test_eq("OCSP response has signer name", CNs.size(), 1)) {
2✔
147
                     result.test_eq("Expected name", CNs[0], expected_name);
2✔
148
                  }
149
               } else {
2✔
150
                  throw Test_Error("Unknown message type " + algo + " in TLS parsing tests");
×
151
               }
152
               result.test_success("Correct parsing");
34✔
153
            } catch(std::exception& e) { result.test_failure(e.what()); }
×
154
         } else {
155
            if(algo == "cert_verify") {
29✔
156
               result.test_throws("invalid cert_verify input", exception, [&buffer]() {
6✔
157
                  Botan::TLS::Certificate_Verify message(buffer);
2✔
158
               });
×
159
            } else if(algo == "client_hello") {
27✔
160
               result.test_throws("invalid client_hello input", exception, [&buffer]() {
27✔
161
                  Botan::TLS::Client_Hello_12 message(buffer);
9✔
162
               });
×
163
            } else if(algo == "hello_verify") {
18✔
164
               result.test_throws("invalid hello_verify input", exception, [&buffer]() {
12✔
165
                  Botan::TLS::Hello_Verify_Request message(buffer);
4✔
166
               });
×
167
            } else if(algo == "hello_request") {
14✔
168
               result.test_throws(
3✔
169
                  "invalid hello_request input", exception, [&buffer]() { Botan::TLS::Hello_Request message(buffer); });
1✔
170
            } else if(algo == "cert_status") {
13✔
171
               result.test_throws("invalid cert_status input", exception, [&buffer]() {
12✔
172
                  Botan::TLS::Certificate_Status message(buffer, Botan::TLS::Connection_Side::Server);
4✔
173
               });
×
174
            } else if(algo == "new_session_ticket") {
9✔
175
               result.test_throws("invalid new_session_ticket input", exception, [&buffer]() {
6✔
176
                  Botan::TLS::New_Session_Ticket_12 message(buffer);
2✔
177
               });
×
178
            } else if(algo == "server_hello") {
7✔
179
               result.test_throws("invalid server_hello input", exception, [&buffer]() {
12✔
180
                  Botan::TLS::Server_Hello_12 message(buffer);
4✔
181
               });
×
182
            } else if(algo == "alert") {
3✔
183
               result.test_throws("invalid alert input", exception, [&buffer]() {
9✔
184
                  Botan::secure_vector<uint8_t> sb(buffer.begin(), buffer.end());
3✔
185
                  Botan::TLS::Alert message(sb);
3✔
186
               });
×
187
            } else {
188
               throw Test_Error("Unknown message type " + algo + " in TLS parsing tests");
×
189
            }
190
         }
191

192
         return result;
46✔
193
      }
147✔
194

195
      std::vector<Test::Result> run_final_tests() override {
1✔
196
         std::vector<Test::Result> results;
1✔
197

198
         results.push_back(test_hello_verify_request());
2✔
199

200
         return results;
1✔
201
      }
×
202
};
203

204
BOTAN_REGISTER_TEST("tls", "tls_messages", TLS_Message_Parsing_Test);
205

206
   #if defined(BOTAN_HAS_TLS_13)
207
class TLS_Key_Share_CH_Generation_Test final : public Text_Based_Test {
×
208
   public:
209
      TLS_Key_Share_CH_Generation_Test() :
1✔
210
            Text_Based_Test("tls_extensions/generation/key_share_CH_offers.vec",
211
                            "Groups,Rng_Data,Expected_Content",
212
                            "Offered_Groups") {}
3✔
213

214
      Test::Result run_one_test(const std::string& extension, const VarMap& vars) override {
11✔
215
         Test::Result result(extension + " generation");
11✔
216

217
         const auto rng_data = vars.get_req_bin("Rng_Data");
11✔
218
         const auto groups = vars.get_req_str("Groups");
11✔
219
         const auto offered_groups = vars.get_opt_str("Offered_Groups", groups);
11✔
220
         const auto expected_key_share = vars.get_req_bin("Expected_Content");
11✔
221

222
         Test_Callbacks cb(result);
11✔
223
         Botan::TLS::Text_Policy policy("key_exchange_groups = " + groups +
22✔
224
                                        "\n"
225
                                        "key_exchange_groups_to_offer = " +
22✔
226
                                        offered_groups);
11✔
227
         Botan_Tests::Fixed_Output_RNG rng;
11✔
228
         rng.add_entropy(rng_data.data(), rng_data.size());
11✔
229

230
         Botan::TLS::Key_Share share(policy, cb, rng);
11✔
231
         const auto serialized_buffer = share.serialize(Botan::TLS::Connection_Side::Client);
11✔
232

233
         result.test_eq("key_share_CH_offers test", serialized_buffer, expected_key_share);
11✔
234

235
         return result;
11✔
236
      }
44✔
237
};
238

239
class TLS_Extension_Parsing_Test final : public Text_Based_Test {
×
240
   public:
241
      TLS_Extension_Parsing_Test() :
1✔
242
            Text_Based_Test("tls_extensions/parsing",
243
                            "Buffer,Exception",
244
                            "Protocol,Ciphersuite,AdditionalData,Name,Expected_Content") {}
4✔
245

246
      Test::Result run_one_test(const std::string& extension, const VarMap& vars) override {
23✔
247
         const std::vector<uint8_t> buffer = vars.get_req_bin("Buffer");
23✔
248
         const std::vector<uint8_t> protocol = vars.get_opt_bin("Protocol");
23✔
249
         const std::vector<uint8_t> ciphersuite = vars.get_opt_bin("Ciphersuite");
23✔
250
         const std::string exception = vars.get_req_str("Exception");
23✔
251
         const std::string expected_name = vars.get_opt_str("Name", "");
46✔
252
         const bool is_positive_test = exception.empty();
23✔
253

254
         Test::Result result(extension + " parsing");
23✔
255

256
         if(is_positive_test) {
23✔
257
            try {
12✔
258
               if(extension == "supported_version") {
12✔
259
                  const std::string expected_buffer = Botan::hex_encode(buffer);
2✔
260
                  Botan::TLS::TLS_Data_Reader tls_data_reader("ClientHello", buffer);
2✔
261
                  Botan::TLS::Supported_Versions supported_versions(
2✔
262
                     tls_data_reader, static_cast<uint16_t>(buffer.size()), Botan::TLS::Connection_Side::Client);
2✔
263
                  const auto serialized_buffer = supported_versions.serialize(Botan::TLS::Connection_Side::Client);
2✔
264

265
                  const std::vector<std::vector<uint8_t>> expected_versions = vars.get_req_bin_list("Expected_Content");
2✔
266
                  for(const auto& expected_version : expected_versions) {
5✔
267
                     result.confirm("Expected_Content",
6✔
268
                                    supported_versions.supports(
3✔
269
                                       Botan::TLS::Protocol_Version(expected_version[0], expected_version[1])));
3✔
270
                  }
271

272
                  result.test_eq("supported_version test 1", Botan::hex_encode(serialized_buffer), expected_buffer);
4✔
273
               } else if(extension == "supported_groups") {
14✔
274
                  Botan::TLS::TLS_Data_Reader tls_data_reader("ClientHello", buffer);
2✔
275
                  Botan::TLS::Supported_Groups supp_groups_ext(tls_data_reader, static_cast<uint16_t>(buffer.size()));
2✔
276

277
                  const auto serialized_buffer = supp_groups_ext.serialize(Botan::TLS::Connection_Side::Client);
2✔
278
                  const auto expected_content = vars.get_req_bin("Expected_Content");
2✔
279

280
                  const auto dh_groups = supp_groups_ext.dh_groups();
2✔
281
                  const auto ec_groups = supp_groups_ext.ec_groups();
2✔
282

283
                  std::vector<Botan::TLS::Named_Group> named_groupes;
2✔
284
                  std::merge(dh_groups.begin(),
2✔
285
                             dh_groups.end(),
286
                             ec_groups.begin(),
287
                             ec_groups.end(),
288
                             std::back_inserter(named_groupes));
289

290
                  result.confirm("supported_groups extension - size check",
4✔
291
                                 (named_groupes.size() * 2) == expected_content.size());
2✔
292

293
                  for(size_t i = 0; i < expected_content.size(); i += 2) {
12✔
294
                     const auto expected_named_group =
10✔
295
                        Botan::make_uint16(expected_content.at(i), expected_content.at(i + 1));
10✔
296

297
                     result.confirm("signature_algorithms_cert extension - named group check",
20✔
298
                                    std::any_of(named_groupes.cbegin(),
10✔
299
                                                named_groupes.cend(),
300
                                                [&expected_named_group](const Botan::TLS::Named_Group& named_group) {
46✔
301
                                                   return static_cast<Botan::TLS::Named_Group>(expected_named_group) ==
16✔
302
                                                          named_group;
303
                                                }));
304
                  }
305

306
                  result.test_eq("supported_groups extension - serialization test", serialized_buffer, buffer);
4✔
307
               } else if(extension == "signature_algorithms_cert") {
17✔
308
                  Botan::TLS::TLS_Data_Reader tls_data_reader("ClientHello", buffer);
2✔
309
                  Botan::TLS::Signature_Algorithms_Cert sig_algo_cert(tls_data_reader,
2✔
310
                                                                      static_cast<uint16_t>(buffer.size()));
2✔
311

312
                  const auto serialized_buffer = sig_algo_cert.serialize(Botan::TLS::Connection_Side::Client);
2✔
313
                  const auto expected_content = vars.get_req_bin("Expected_Content");
2✔
314

315
                  result.confirm("signature_algorithms_cert extension - size check",
2✔
316
                                 sig_algo_cert.supported_schemes().size() * 2 == expected_content.size());
2✔
317

318
                  size_t offset = 0;
2✔
319
                  for(const auto& sig_scheme : sig_algo_cert.supported_schemes()) {
10✔
320
                     const auto expected_sig_scheme =
8✔
321
                        Botan::make_uint16(expected_content.at(offset), expected_content.at(offset + 1));
8✔
322

323
                     result.confirm("signature_algorithms_cert extension - sig scheme check",
8✔
324
                                    Botan::TLS::Signature_Scheme(expected_sig_scheme) == sig_scheme);
8✔
325

326
                     offset += 2;
8✔
327
                  }
328

329
                  result.test_eq("signature_algorithms_cert extension - serialization test", serialized_buffer, buffer);
4✔
330
               } else if(extension == "cookie") {
10✔
331
                  Botan::TLS::TLS_Data_Reader tls_data_reader("HelloRetryRequest", buffer);
2✔
332
                  Botan::TLS::Cookie cookie(tls_data_reader, static_cast<uint16_t>(buffer.size()));
2✔
333

334
                  const auto serialized_buffer = cookie.serialize(Botan::TLS::Connection_Side::Server);
2✔
335
                  const auto expected_cookie = vars.get_req_bin("Expected_Content");
2✔
336

337
                  result.test_eq("Cookie extension test",
4✔
338
                                 Botan::hex_encode(expected_cookie),
4✔
339
                                 Botan::hex_encode(cookie.get_cookie()));
4✔
340
               } else if(extension == "key_share_HRR") {
10✔
341
                  Botan::TLS::TLS_Data_Reader tls_data_reader("HelloRetryRequest", buffer);
1✔
342
                  Botan::TLS::Key_Share key_share(tls_data_reader,
1✔
343
                                                  static_cast<uint16_t>(buffer.size()),
1✔
344
                                                  Botan::TLS::Handshake_Type::HelloRetryRequest);
1✔
345

346
                  const auto serialized_buffer = key_share.serialize(Botan::TLS::Connection_Side::Client);
1✔
347
                  const auto expected_key_share = vars.get_req_bin("Expected_Content");
1✔
348

349
                  result.test_eq(
3✔
350
                     "key_share_HRR test", Botan::hex_encode(serialized_buffer), Botan::hex_encode(expected_key_share));
2✔
351
               } else if(extension == "key_share_SH") {
5✔
352
                  Botan::TLS::TLS_Data_Reader tls_data_reader("ServerHello", buffer);
1✔
353
                  Botan::TLS::Key_Share key_share(
1✔
354
                     tls_data_reader, static_cast<uint16_t>(buffer.size()), Botan::TLS::Handshake_Type::ServerHello);
1✔
355

356
                  const auto serialized_buffer = key_share.serialize(Botan::TLS::Connection_Side::Client);
1✔
357
                  const auto expected_key_share = vars.get_req_bin("Expected_Content");
1✔
358

359
                  result.test_eq(
3✔
360
                     "key_share_SH test", Botan::hex_encode(serialized_buffer), Botan::hex_encode(expected_key_share));
3✔
361
               } else if(extension == "key_share_CH") {
4✔
362
                  Botan::TLS::TLS_Data_Reader tls_data_reader("ClientHello", buffer);
2✔
363
                  Botan::TLS::Key_Share key_share(
2✔
364
                     tls_data_reader, static_cast<uint16_t>(buffer.size()), Botan::TLS::Handshake_Type::ClientHello);
2✔
365

366
                  const auto serialized_buffer = key_share.serialize(Botan::TLS::Connection_Side::Server);
2✔
367
                  const auto expected_key_share = vars.get_req_bin("Expected_Content");
2✔
368

369
                  result.test_eq(
6✔
370
                     "key_share_CH test", Botan::hex_encode(serialized_buffer), Botan::hex_encode(expected_key_share));
6✔
371
               } else {
4✔
372
                  throw Test_Error("Unknown extension type " + extension + " in TLS parsing tests");
×
373
               }
374
               result.test_success("Correct parsing");
24✔
375
            } catch(std::exception& e) { result.test_failure(e.what()); }
×
376
         } else {
377
         }
378

379
         return result;
23✔
380
      }
57✔
381

382
      std::vector<Test::Result> run_final_tests() override {
1✔
383
         std::vector<Test::Result> results;
1✔
384

385
         results.push_back(test_hello_verify_request());
2✔
386

387
         return results;
1✔
388
      }
×
389
};
390

391
BOTAN_REGISTER_TEST("tls_extensions", "tls_extensions_parsing", TLS_Extension_Parsing_Test);
392
BOTAN_REGISTER_TEST("tls_extensions", "tls_extensions_key_share_client_hello", TLS_Key_Share_CH_Generation_Test);
393

394
class TLS_13_Message_Parsing_Test final : public Text_Based_Test {
×
395
   public:
396
      TLS_13_Message_Parsing_Test() :
1✔
397
            Text_Based_Test("tls_13", "Buffer,Exception", "Protocol,Message_Type,AdditionalData,Ciphersuite,Name") {}
4✔
398

399
      Test::Result run_one_test(const std::string& algo, const VarMap& vars) override {
24✔
400
         const std::vector<uint8_t> buffer = vars.get_req_bin("Buffer");
24✔
401
         const std::vector<uint8_t> protocol = vars.get_opt_bin("Protocol");
24✔
402
         const std::string msg_type = vars.get_opt_str("Message_Type", "");
48✔
403
         const std::vector<uint8_t> ciphersuite = vars.get_opt_bin("Ciphersuite");
24✔
404
         const std::string exception = vars.get_req_str("Exception");
24✔
405
         const bool is_positive_test = exception.empty();
24✔
406

407
         Test::Result result("TLS 1.3 " + algo + " parsing");
24✔
408

409
         if(algo == "client_hello") {
24✔
410
            try {
16✔
411
               std::visit(
4✔
412
                  [&](auto ch) {
4✔
413
                     if constexpr(std::is_same_v<Botan::TLS::Client_Hello_12, decltype(ch)>) {
414
                        result.confirm("expected Client_Hello_12", msg_type == "client_hello_12");
7✔
415
                     }
416
                     if constexpr(std::is_same_v<Botan::TLS::Client_Hello_13, decltype(ch)>) {
417
                        result.confirm("expected Client_Hello_13", msg_type == "client_hello_13");
2✔
418
                     }
419

420
                     const std::string extensions = vars.get_req_str("AdditionalData");
8✔
421
                     std::vector<uint8_t> exts_buffer;
4✔
422
                     for(Botan::TLS::Extension_Code const& type : ch.extensions().extension_types()) {
32✔
423
                        uint16_t u16type = static_cast<uint16_t>(type);
24✔
424
                        exts_buffer.push_back(Botan::get_byte<0>(u16type));
24✔
425
                        exts_buffer.push_back(Botan::get_byte<1>(u16type));
24✔
426
                     }
427
                     result.test_eq("Hello extensions", Botan::hex_encode(exts_buffer), extensions);
11✔
428

429
                     std::vector<uint8_t> ciphersuites_buffer;
4✔
430
                     for(const auto& cs : ch.ciphersuites()) {
290✔
431
                        ciphersuites_buffer.push_back(Botan::get_byte<0>(cs));
286✔
432
                        ciphersuites_buffer.push_back(Botan::get_byte<1>(cs));
286✔
433
                     }
434
                     result.test_eq("Supported ciphersuites", ciphersuites_buffer, ciphersuite);
4✔
435

436
                     result.confirm("this is a positive test that should not have failed yet", is_positive_test);
12✔
437
                  },
11✔
438
                  Botan::TLS::Client_Hello_13::parse(buffer));
20✔
439
            } catch(const std::exception& ex) {
12✔
440
               result.test_eq("correct error produced", ex.what(), exception);
24✔
441
               result.confirm("negative test", !is_positive_test);
24✔
442
            }
12✔
443
         }
444

445
         if(algo == "server_hello") {
24✔
446
            const std::string extensions = vars.get_req_str("AdditionalData");
8✔
447
            const Botan::TLS::Ciphersuite cs =
8✔
448
               Botan::TLS::Ciphersuite::by_id(Botan::make_uint16(ciphersuite[0], ciphersuite[1])).value();
8✔
449
            const Botan::TLS::Protocol_Version pv(protocol[0], protocol[1]);
8✔
450

451
            try {
8✔
452
               std::visit(
4✔
453
                  [&](auto msg) {
4✔
454
                     if constexpr(std::is_same_v<Botan::TLS::Server_Hello_12, decltype(msg)>) {
455
                        result.confirm("expected Server_Hello_12", msg_type == "server_hello_12");
6✔
456
                        result.confirm("expected pre TLS 1.3 message", pv == msg.legacy_version());
4✔
457
                     } else if constexpr(std::is_same_v<Botan::TLS::Server_Hello_13, decltype(msg)>) {
458
                        result.confirm("expected Server_Hello_13", msg_type == "server_hello_13");
2✔
459
                     } else if constexpr(std::is_same_v<Botan::TLS::Hello_Retry_Request, decltype(msg)>) {
460
                        result.confirm("expected Hello_Retry_Request", msg_type == "hello_retry_request");
2✔
461
                     }
462

463
                     result.confirm("Ciphersuite", (msg.ciphersuite() == cs.ciphersuite_code()));
8✔
464

465
                     std::vector<uint8_t> buf;
4✔
466
                     for(Botan::TLS::Extension_Code const& type : msg.extensions().extension_types()) {
18✔
467
                        uint16_t u16type = static_cast<uint16_t>(type);
14✔
468
                        buf.push_back(Botan::get_byte<0>(u16type));
14✔
469
                        buf.push_back(Botan::get_byte<1>(u16type));
14✔
470
                     }
471
                     result.test_eq("Hello extensions", Botan::hex_encode(buf), extensions);
10✔
472
                  },
4✔
473
                  Botan::TLS::Server_Hello_13::parse(buffer));
12✔
474
            } catch(const std::exception& ex) {
4✔
475
               result.test_eq("correct error produced", ex.what(), exception);
8✔
476
               result.confirm("negative test", !is_positive_test);
8✔
477
            }
4✔
478
         }
8✔
479

480
         return result;
24✔
481
      }
88✔
482
};
483

484
BOTAN_REGISTER_TEST("tls", "tls_13_messages", TLS_13_Message_Parsing_Test);
485

486
   #endif
487

488
#endif
489

490
}
491

492
}
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