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

randombit / botan / 15356506686

30 May 2025 06:24PM UTC coverage: 90.978% (+0.003%) from 90.975%
15356506686

push

github

web-flow
Merge pull request #4894 from reneme/test/kat_for_tls_cbc_aead

98082 of 107808 relevant lines covered (90.98%)

12507195.62 hits per line

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

85.03
/src/tests/test_tls.cpp
1
/*
2
* (C) 2014,2015,2017,2018 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8
#include <fstream>
9
#include <memory>
10

11
#if defined(BOTAN_HAS_TLS)
12
   #include "test_rng.h"
13

14
   #include <botan/tls_alert.h>
15
   #include <botan/tls_policy.h>
16
   #include <botan/tls_session.h>
17
   #include <botan/tls_version.h>
18
   #include <botan/internal/fmt.h>
19

20
   #if defined(BOTAN_HAS_TLS_CBC)
21
      #include <botan/internal/tls_cbc.h>
22
   #endif
23

24
#endif
25

26
namespace Botan_Tests {
27

28
#if defined(BOTAN_HAS_TLS)
29

30
class TLS_Session_Tests final : public Test {
×
31
   public:
32
      std::vector<Test::Result> run() override {
1✔
33
         Test::Result result("TLS::Session");
1✔
34

35
         Botan::TLS::Session session(Botan::secure_vector<uint8_t>{0xCC, 0xDD},
1✔
36
                                     Botan::TLS::Protocol_Version::TLS_V12,
37
                                     0xC02F,
38
                                     Botan::TLS::Connection_Side::Client,
39
                                     true,
40
                                     false,
41
                                     std::vector<Botan::X509_Certificate>(),
1✔
42
                                     Botan::TLS::Server_Information("server"),
1✔
43
                                     0x0000,
44
                                     std::chrono::system_clock::now());
2✔
45

46
         const std::string pem = session.PEM_encode();
1✔
47
         Botan::TLS::Session session_from_pem(pem);
1✔
48
         result.test_eq("Roundtrip from pem", session.DER_encode(), session_from_pem.DER_encode());
3✔
49

50
         const auto der = session.DER_encode();
1✔
51
         Botan::TLS::Session session_from_der(der);
1✔
52
         result.test_eq("Roundtrip from der", session.DER_encode(), session_from_der.DER_encode());
3✔
53

54
         const Botan::SymmetricKey key("ABCDEF");
1✔
55
         const std::vector<uint8_t> ctext1 = session.encrypt(key, this->rng());
1✔
56
         const std::vector<uint8_t> ctext2 = session.encrypt(key, this->rng());
1✔
57

58
         result.test_ne(
1✔
59
            "TLS session encryption is non-determinsitic", ctext1.data(), ctext1.size(), ctext2.data(), ctext2.size());
60

61
         const std::vector<uint8_t> expected_hdr = Botan::hex_decode("068B5A9D396C0000F2322CAE");
1✔
62

63
         result.test_eq("tls", "TLS session encryption same header", ctext1.data(), 12, expected_hdr.data(), 12);
1✔
64
         result.test_eq("tls", "TLS session encryption same header", ctext2.data(), 12, expected_hdr.data(), 12);
1✔
65

66
         Botan::TLS::Session dsession = Botan::TLS::Session::decrypt(ctext1.data(), ctext1.size(), key);
1✔
67

68
         Fixed_Output_RNG frng1("00112233445566778899AABBCCDDEEFF802802802802802802802802");
1✔
69
         const std::vector<uint8_t> ctextf1 = session.encrypt(key, frng1);
1✔
70
         Fixed_Output_RNG frng2("00112233445566778899AABBCCDDEEFF802802802802802802802802");
1✔
71
         const std::vector<uint8_t> ctextf2 = session.encrypt(key, frng2);
1✔
72

73
         result.test_eq("Only randomness comes from RNG", ctextf1, ctextf2);
2✔
74

75
         Botan::TLS::Session session2(Botan::secure_vector<uint8_t>{0xCC, 0xEE},
1✔
76
                                      Botan::TLS::Protocol_Version::TLS_V12,
77
                                      0xBAAD,  // cipher suite does not exist
78
                                      Botan::TLS::Connection_Side::Client,
79
                                      true,
80
                                      false,
81
                                      std::vector<Botan::X509_Certificate>(),
1✔
82
                                      Botan::TLS::Server_Information("server"),
1✔
83
                                      0x0000,
84
                                      std::chrono::system_clock::now());
2✔
85
         const std::string pem_with_unknown_ciphersuite = session2.PEM_encode();
1✔
86

87
         result.test_throws("unknown ciphersuite during session parsing",
2✔
88
                            "Serialized TLS session contains unknown cipher suite (47789)",
89
                            [&] { Botan::TLS::Session{pem_with_unknown_ciphersuite}; });
2✔
90

91
         return {result};
3✔
92
      }
9✔
93
};
94

95
BOTAN_REGISTER_TEST("tls", "tls_session", TLS_Session_Tests);
96

97
   #if defined(BOTAN_HAS_TLS_CBC)
98

99
class TLS_CBC_Padding_Tests final : public Text_Based_Test {
×
100
   public:
101
      TLS_CBC_Padding_Tests() : Text_Based_Test("tls_cbc_padding.vec", "Record,Output") {}
2✔
102

103
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
22✔
104
         const std::vector<uint8_t> record = vars.get_req_bin("Record");
22✔
105
         const size_t output = vars.get_req_sz("Output");
22✔
106

107
         uint16_t res = Botan::TLS::check_tls_cbc_padding(record.data(), record.size());
22✔
108

109
         Test::Result result("TLS CBC padding check");
22✔
110
         result.test_eq("Expected", res, output);
22✔
111
         return result;
22✔
112
      }
22✔
113
};
114

115
BOTAN_REGISTER_TEST("tls", "tls_cbc_padding", TLS_CBC_Padding_Tests);
116

117
class TLS_CBC_Tests final : public Text_Based_Test {
×
118
   public:
119
      class ZeroMac : public Botan::MessageAuthenticationCode {
120
         public:
121
            explicit ZeroMac(size_t mac_len) : m_mac_len(mac_len) {}
10✔
122

123
            void clear() override {}
×
124

125
            std::string name() const override { return "ZeroMac"; }
16✔
126

127
            size_t output_length() const override { return m_mac_len; }
20✔
128

129
            void add_data(std::span<const uint8_t> /*input*/) override {}
26✔
130

131
            void final_result(std::span<uint8_t> out) override {
10✔
132
               for(size_t i = 0; i != m_mac_len; ++i) {
206✔
133
                  out[i] = 0;
196✔
134
               }
135
            }
10✔
136

137
            bool has_keying_material() const override { return true; }
×
138

139
            Botan::Key_Length_Specification key_spec() const override {
10✔
140
               return Botan::Key_Length_Specification(0, 0, 1);
10✔
141
            }
142

143
            std::unique_ptr<MessageAuthenticationCode> new_object() const override {
×
144
               return std::make_unique<ZeroMac>(m_mac_len);
×
145
            }
146

147
         private:
148
            void key_schedule(std::span<const uint8_t> /* key */) override {}
10✔
149

150
            size_t m_mac_len;
151
      };
152

153
      class Noop_Block_Cipher : public Botan::BlockCipher {
154
         public:
155
            explicit Noop_Block_Cipher(size_t bs) : m_bs(bs) {}
10✔
156

157
            void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override {
×
158
               Botan::copy_mem(out, in, blocks * m_bs);
×
159
            }
×
160

161
            void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override {
10✔
162
               Botan::copy_mem(out, in, blocks * m_bs);
10✔
163
            }
10✔
164

165
            size_t block_size() const override { return m_bs; }
40✔
166

167
            void clear() override {}
×
168

169
            std::string name() const override { return "noop"; }
10✔
170

171
            bool has_keying_material() const override { return true; }
×
172

173
            Botan::Key_Length_Specification key_spec() const override {
20✔
174
               return Botan::Key_Length_Specification(0, 0, 1);
20✔
175
            }
176

177
            std::unique_ptr<BlockCipher> new_object() const override {
×
178
               return std::make_unique<Noop_Block_Cipher>(m_bs);
×
179
            }
180

181
         private:
182
            void key_schedule(std::span<const uint8_t> /*key*/) override {}
10✔
183

184
            size_t m_bs;
185
      };
186

187
      TLS_CBC_Tests() : Text_Based_Test("tls_cbc.vec", "Blocksize,MACsize,Record,Valid") {}
2✔
188

189
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
10✔
190
         Test::Result result("TLS CBC");
10✔
191

192
         const size_t block_size = vars.get_req_sz("Blocksize");
10✔
193
         const size_t mac_len = vars.get_req_sz("MACsize");
10✔
194
         const std::vector<uint8_t> record = vars.get_req_bin("Record");
10✔
195
         const bool is_valid = vars.get_req_sz("Valid") == 1;
10✔
196

197
         // todo test permutations
198
         bool encrypt_then_mac = false;
10✔
199

200
         Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption tls_cbc(std::make_unique<Noop_Block_Cipher>(block_size),
20✔
201
                                                          std::make_unique<ZeroMac>(mac_len),
10✔
202
                                                          0,
203
                                                          0,
204
                                                          Botan::TLS::Protocol_Version::TLS_V12,
205
                                                          encrypt_then_mac);
20✔
206

207
         tls_cbc.set_key(std::vector<uint8_t>(0));
10✔
208
         std::vector<uint8_t> ad(13);
10✔
209
         tls_cbc.set_associated_data(ad.data(), ad.size());
10✔
210

211
         Botan::secure_vector<uint8_t> vec(record.begin(), record.end());
10✔
212

213
         try {
10✔
214
            tls_cbc.finish(vec, 0);
10✔
215
            if(is_valid) {
4✔
216
               result.test_success("Accepted valid TLS-CBC ciphertext");
8✔
217
            } else {
218
               result.test_failure("Accepted invalid TLS-CBC ciphertext");
×
219
            }
220
         } catch(std::exception&) {
6✔
221
            if(is_valid) {
6✔
222
               result.test_failure("Rejected valid TLS-CBC ciphertext");
×
223
            } else {
224
               result.test_success("Accepted invalid TLS-CBC ciphertext");
12✔
225
            }
226
         }
6✔
227

228
         return result;
10✔
229
      }
30✔
230
};
231

232
class TLS_CBC_KAT_Tests final : public Text_Based_Test {
×
233
   public:
234
      TLS_CBC_KAT_Tests() :
1✔
235
            Text_Based_Test(
236
               "tls_cbc_kat.vec",
237
               "BlockCipher,MAC,KeylenCipher,KeylenMAC,EncryptThenMAC,Protocol,Key,AssociatedData,Nonce,Plaintext,Ciphertext") {
2✔
238
      }
1✔
239

240
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
10✔
241
         Test::Result result("TLS CBC KAT");
10✔
242

243
         run_kat<Botan::TLS::TLS_CBC_HMAC_AEAD_Encryption>(result, vars);
10✔
244
         run_kat<Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption>(result, vars);
10✔
245

246
         return result;
10✔
247
      }
×
248

249
      bool skip_this_test(const std::string& /*header*/, const VarMap& vars) override {
10✔
250
         try {
10✔
251
            std::ignore = get_cipher_and_mac(vars);
10✔
252
            return false;
10✔
253
         } catch(const Botan::Lookup_Error&) {
×
254
            return true;
×
255
         }
×
256
      }
257

258
   private:
259
      [[nodiscard]] static std::pair<std::unique_ptr<Botan::BlockCipher>,
260
                                     std::unique_ptr<Botan::MessageAuthenticationCode>>
261
      get_cipher_and_mac(const VarMap& vars) {
30✔
262
         return {
30✔
263
            Botan::BlockCipher::create_or_throw(vars.get_req_str("BlockCipher")),
60✔
264
            Botan::MessageAuthenticationCode::create_or_throw(vars.get_req_str("MAC")),
30✔
265
         };
60✔
266
      }
267

268
      template <typename T>
269
         requires(std::same_as<T, Botan::TLS::TLS_CBC_HMAC_AEAD_Encryption> ||
270
                  std::same_as<T, Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption>)
271
      static void run_kat(Test::Result& result, const VarMap& vars) {
20✔
272
         constexpr bool encrypt = std::same_as<T, Botan::TLS::TLS_CBC_HMAC_AEAD_Encryption>;
20✔
273
         constexpr auto direction = [] {
20✔
274
            if constexpr(encrypt) {
275
               return "encryption";
276
            } else {
277
               return "decryption";
278
            }
279
         }();
280

281
         const auto keylen_cipher = vars.get_req_sz("KeylenCipher");
20✔
282
         const auto keylen_mac = vars.get_req_sz("KeylenMAC");
20✔
283
         const auto encrypt_then_mac = vars.get_req_bool("EncryptThenMAC");
20✔
284
         const auto protocol = [&] {
60✔
285
            const auto p = vars.get_req_str("Protocol");
20✔
286
            if(p == "TLS") {
20✔
287
               return Botan::TLS::Version_Code::TLS_V12;
288
            } else if(p == "DTLS") {
10✔
289
               return Botan::TLS::Version_Code::DTLS_V12;
290
            } else {
291
               throw Test_Error("unexpected protocol version");
×
292
            }
293
         }();
40✔
294

295
         const auto key = vars.get_req_bin("Key");
40✔
296
         const auto ad = vars.get_req_bin("AssociatedData");
40✔
297
         const auto nonce = vars.get_req_bin("Nonce");
40✔
298
         const auto pt = vars.get_req_bin("Plaintext");
40✔
299
         const auto ct = vars.get_req_bin("Ciphertext");
20✔
300

301
         auto [cipher, mac] = get_cipher_and_mac(vars);
20✔
302

303
         auto tls_cbc = T(std::move(cipher), std::move(mac), keylen_cipher, keylen_mac, protocol, encrypt_then_mac);
40✔
304

305
         tls_cbc.set_key(key);
20✔
306
         tls_cbc.set_associated_data(ad);
20✔
307

308
         std::vector<uint8_t> in(pt.begin(), pt.end());
20✔
309
         std::vector<uint8_t> out(ct.begin(), ct.end());
20✔
310

311
         if constexpr(!encrypt) {
312
            std::swap(in, out);
10✔
313
         }
314

315
         // Test 1: process the entire message at once
316
         std::vector<uint8_t> inout = in;
20✔
317
         tls_cbc.start(nonce);
20✔
318
         tls_cbc.finish(inout);  // in-place processing ('in' should now contain 'out')
20✔
319
         result.test_eq(std::string("expected output of ") + direction, inout, out);
40✔
320

321
         // Test 2: process the message in chunks
322
         auto in_span = std::span{in};
20✔
323
         tls_cbc.start(nonce);
20✔
324
         constexpr size_t chunk_size = 7;
325
         while(in_span.size() >= chunk_size && in_span.size() > tls_cbc.minimum_final_size() + chunk_size) {
2,047✔
326
            tls_cbc.process(in_span.first(chunk_size));
2,027✔
327
            in_span = in_span.subspan(chunk_size);
2,027✔
328
         }
329

330
         std::vector<uint8_t> chunked_out(in_span.begin(), in_span.end());
20✔
331
         tls_cbc.finish(chunked_out);
20✔
332
         result.test_eq(std::string("expected output with chunking of ") + direction, chunked_out, out);
40✔
333
      }
180✔
334
};
335

336
BOTAN_REGISTER_TEST("tls", "tls_cbc", TLS_CBC_Tests);
337
BOTAN_REGISTER_TEST("tls", "tls_cbc_kat", TLS_CBC_KAT_Tests);
338

339
   #endif
340

341
class Test_TLS_Alert_Strings : public Test {
1✔
342
   public:
343
      std::vector<Test::Result> run() override {
1✔
344
         Test::Result result("TLS::Alert::type_string");
1✔
345

346
         const std::vector<Botan::TLS::Alert::Type> alert_types = {
1✔
347
            Botan::TLS::Alert::CloseNotify,
348
            Botan::TLS::Alert::UnexpectedMessage,
349
            Botan::TLS::Alert::BadRecordMac,
350
            Botan::TLS::Alert::DecryptionFailed,
351
            Botan::TLS::Alert::RecordOverflow,
352
            Botan::TLS::Alert::DecompressionFailure,
353
            Botan::TLS::Alert::HandshakeFailure,
354
            Botan::TLS::Alert::NoCertificate,
355
            Botan::TLS::Alert::BadCertificate,
356
            Botan::TLS::Alert::UnsupportedCertificate,
357
            Botan::TLS::Alert::CertificateRevoked,
358
            Botan::TLS::Alert::CertificateExpired,
359
            Botan::TLS::Alert::CertificateUnknown,
360
            Botan::TLS::Alert::IllegalParameter,
361
            Botan::TLS::Alert::UnknownCA,
362
            Botan::TLS::Alert::AccessDenied,
363
            Botan::TLS::Alert::DecodeError,
364
            Botan::TLS::Alert::DecryptError,
365
            Botan::TLS::Alert::ExportRestriction,
366
            Botan::TLS::Alert::ProtocolVersion,
367
            Botan::TLS::Alert::InsufficientSecurity,
368
            Botan::TLS::Alert::InternalError,
369
            Botan::TLS::Alert::InappropriateFallback,
370
            Botan::TLS::Alert::UserCanceled,
371
            Botan::TLS::Alert::NoRenegotiation,
372
            Botan::TLS::Alert::MissingExtension,
373
            Botan::TLS::Alert::UnsupportedExtension,
374
            Botan::TLS::Alert::CertificateUnobtainable,
375
            Botan::TLS::Alert::UnrecognizedName,
376
            Botan::TLS::Alert::BadCertificateStatusResponse,
377
            Botan::TLS::Alert::BadCertificateHashValue,
378
            Botan::TLS::Alert::UnknownPSKIdentity,
379
            Botan::TLS::Alert::NoApplicationProtocol,
380
         };
1✔
381

382
         std::set<std::string> seen;
1✔
383

384
         for(auto alert : alert_types) {
34✔
385
            const std::string str = Botan::TLS::Alert(alert).type_string();
33✔
386
            result.test_eq("No duplicate strings", seen.count(str), 0);
33✔
387
            seen.insert(str);
33✔
388
         }
33✔
389

390
         Botan::TLS::Alert unknown_alert = Botan::TLS::Alert({01, 66});
1✔
391

392
         result.test_eq("Unknown alert str", unknown_alert.type_string(), "unrecognized_alert_66");
2✔
393

394
         return {result};
3✔
395
      }
2✔
396
};
397

398
BOTAN_REGISTER_TEST("tls", "tls_alert_strings", Test_TLS_Alert_Strings);
399

400
   #if defined(BOTAN_HAS_TLS_13) && defined(BOTAN_HAS_TLS_13_PQC) && defined(BOTAN_HAS_X25519) && \
401
      defined(BOTAN_HAS_X448)
402

403
class Test_TLS_Policy_Text : public Test {
1✔
404
   public:
405
      std::vector<Test::Result> run() override {
1✔
406
         Test::Result result("TLS Policy");
1✔
407

408
         const std::vector<std::string> policies = {"default", "suiteb_128", "suiteb_192", "strict", "datagram", "bsi"};
1✔
409

410
         for(const std::string& policy : policies) {
7✔
411
            const std::string from_policy_obj = tls_policy_string(policy);
6✔
412

413
            const std::string policy_file = policy + (policy == "default" || policy == "strict" ? "_tls13" : "");
8✔
414

415
            const std::string from_file = read_tls_policy(policy_file);
6✔
416

417
            if(from_policy_obj != from_file) {
6✔
418
               std::string d = diff(from_policy_obj, from_file);
×
419
               result.test_failure(Botan::fmt("Values for TLS policy from {} don't match (diff {})", policy_file, d));
×
420
            } else {
×
421
               result.test_success("Values from TLS policy from " + policy_file + " match");
18✔
422
            }
423
         }
6✔
424

425
         return {result};
3✔
426
      }
2✔
427

428
   private:
429
      static std::string diff(const std::string& a_str, const std::string& b_str) {
×
430
         std::istringstream a_ss(a_str);
×
431
         std::istringstream b_ss(b_str);
×
432

433
         std::ostringstream diff;
×
434

435
         for(;;) {
×
436
            if(!a_ss && !b_ss) {
×
437
               break;  // done
438
            }
439

440
            std::string a_line;
×
441
            std::getline(a_ss, a_line, '\n');
×
442

443
            std::string b_line;
×
444
            std::getline(b_ss, b_line, '\n');
×
445

446
            if(a_line != b_line) {
×
447
               diff << "- " << a_line << "\n"
×
448
                    << "+ " << b_line << "\n";
×
449
            }
450
         }
×
451

452
         return diff.str();
×
453
      }
×
454

455
      static std::string read_tls_policy(const std::string& policy_str) {
6✔
456
         const std::string fspath = Test::data_file("tls-policy/" + policy_str + ".txt");
18✔
457

458
         std::ifstream is(fspath.c_str());
6✔
459
         if(!is.good()) {
6✔
460
            throw Test_Error("Missing policy file " + fspath);
×
461
         }
462

463
         Botan::TLS::Text_Policy policy(is);
6✔
464
         return policy.to_string();
6✔
465
      }
6✔
466

467
      static std::string tls_policy_string(const std::string& policy_str) {
6✔
468
         std::unique_ptr<Botan::TLS::Policy> policy;
6✔
469
         if(policy_str == "default") {
6✔
470
            policy = std::make_unique<Botan::TLS::Policy>();
1✔
471
         } else if(policy_str == "suiteb_128") {
5✔
472
            policy = std::make_unique<Botan::TLS::NSA_Suite_B_128>();
1✔
473
         } else if(policy_str == "suiteb_192") {
4✔
474
            policy = std::make_unique<Botan::TLS::NSA_Suite_B_192>();
1✔
475
         } else if(policy_str == "bsi") {
3✔
476
            policy = std::make_unique<Botan::TLS::BSI_TR_02102_2>();
1✔
477
         } else if(policy_str == "strict") {
2✔
478
            policy = std::make_unique<Botan::TLS::Strict_Policy>();
1✔
479
         } else if(policy_str == "datagram") {
1✔
480
            policy = std::make_unique<Botan::TLS::Datagram_Policy>();
1✔
481
         } else {
482
            throw Test_Error("Unknown TLS policy type '" + policy_str + "'");
×
483
         }
484

485
         return policy->to_string();
6✔
486
      }
6✔
487
};
488

489
BOTAN_REGISTER_TEST("tls", "tls_policy_text", Test_TLS_Policy_Text);
490
   #endif
491

492
class Test_TLS_Ciphersuites : public Test {
1✔
493
   public:
494
      std::vector<Test::Result> run() override {
1✔
495
         Test::Result result("TLS::Ciphersuite");
1✔
496

497
         for(size_t csuite_id = 0; csuite_id <= 0xFFFF; ++csuite_id) {
65,537✔
498
            const uint16_t csuite_id16 = static_cast<uint16_t>(csuite_id);
65,536✔
499
            auto ciphersuite = Botan::TLS::Ciphersuite::by_id(csuite_id16);
65,536✔
500

501
            if(ciphersuite && ciphersuite->valid()) {
65,536✔
502
               result.test_eq("Valid Ciphersuite is not SCSV", Botan::TLS::Ciphersuite::is_scsv(csuite_id16), false);
94✔
503

504
               if(ciphersuite->cbc_ciphersuite() == false) {
94✔
505
                  result.test_eq("Expected AEAD ciphersuite", ciphersuite->aead_ciphersuite(), true);
64✔
506
                  result.test_eq("Expected MAC name for AEAD ciphersuites", ciphersuite->mac_algo(), "AEAD");
128✔
507
               } else {
508
                  result.test_eq("Did not expect AEAD ciphersuite", ciphersuite->aead_ciphersuite(), false);
30✔
509
                  result.test_eq(
90✔
510
                     "MAC algo and PRF algo same for CBC suites", ciphersuite->prf_algo(), ciphersuite->mac_algo());
60✔
511
               }
512

513
               // TODO more tests here
514
            }
515
         }
516

517
         return {result};
3✔
518
      }
2✔
519
};
520

521
BOTAN_REGISTER_TEST("tls", "tls_ciphersuites", Test_TLS_Ciphersuites);
522

523
class Test_TLS_Algo_Strings : public Test {
1✔
524
   public:
525
      std::vector<Test::Result> run() override {
1✔
526
         std::vector<Test::Result> results;
1✔
527

528
         results.push_back(test_auth_method_strings());
2✔
529
         results.push_back(test_kex_algo_strings());
2✔
530
         results.push_back(test_tls_sig_method_strings());
2✔
531

532
         return results;
1✔
533
      }
×
534

535
   private:
536
      static Test::Result test_tls_sig_method_strings() {
1✔
537
         Test::Result result("TLS::Signature_Scheme");
1✔
538

539
         std::vector<Botan::TLS::Signature_Scheme> schemes = Botan::TLS::Signature_Scheme::all_available_schemes();
1✔
540

541
         std::set<std::string> scheme_strs;
1✔
542
         for(auto scheme : schemes) {
10✔
543
            std::string scheme_str = scheme.to_string();
9✔
544

545
            result.test_eq("Scheme strings unique", scheme_strs.count(scheme_str), 0);
9✔
546

547
            scheme_strs.insert(scheme_str);
9✔
548
         }
9✔
549

550
         return result;
2✔
551
      }
1✔
552

553
      static Test::Result test_auth_method_strings() {
1✔
554
         Test::Result result("TLS::Auth_Method");
1✔
555

556
         const std::vector<Botan::TLS::Auth_Method> auth_methods({
1✔
557
            Botan::TLS::Auth_Method::RSA,
558
            Botan::TLS::Auth_Method::ECDSA,
559
            Botan::TLS::Auth_Method::IMPLICIT,
560
         });
1✔
561

562
         for(Botan::TLS::Auth_Method meth : auth_methods) {
4✔
563
            std::string meth_str = Botan::TLS::auth_method_to_string(meth);
3✔
564
            result.test_ne("Method string is not empty", meth_str, "");
6✔
565
            Botan::TLS::Auth_Method meth2 = Botan::TLS::auth_method_from_string(meth_str);
3✔
566
            result.confirm("Decoded method matches", meth == meth2);
6✔
567
         }
3✔
568

569
         return result;
1✔
570
      }
1✔
571

572
      static Test::Result test_kex_algo_strings() {
1✔
573
         Test::Result result("TLS::Kex_Algo");
1✔
574

575
         const std::vector<Botan::TLS::Kex_Algo> kex_algos({Botan::TLS::Kex_Algo::STATIC_RSA,
1✔
576
                                                            Botan::TLS::Kex_Algo::DH,
577
                                                            Botan::TLS::Kex_Algo::ECDH,
578
                                                            Botan::TLS::Kex_Algo::PSK,
579
                                                            Botan::TLS::Kex_Algo::ECDHE_PSK});
1✔
580

581
         for(Botan::TLS::Kex_Algo meth : kex_algos) {
6✔
582
            std::string meth_str = Botan::TLS::kex_method_to_string(meth);
5✔
583
            result.test_ne("Method string is not empty", meth_str, "");
10✔
584
            Botan::TLS::Kex_Algo meth2 = Botan::TLS::kex_method_from_string(meth_str);
5✔
585
            result.confirm("Decoded method matches", meth == meth2);
10✔
586
         }
5✔
587

588
         return result;
1✔
589
      }
1✔
590
};
591

592
BOTAN_REGISTER_TEST("tls", "tls_algo_strings", Test_TLS_Algo_Strings);
593

594
#endif
595

596
}  // 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