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

randombit / botan / 6449915476

08 Oct 2023 08:52PM UTC coverage: 91.697% (+0.005%) from 91.692%
6449915476

push

github

web-flow
Merge pull request #3729 from randombit/jack/enum-for-group-params

Wrap TLS::Group_Params enum in a class

79979 of 87221 relevant lines covered (91.7%)

8572940.26 hits per line

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

92.64
/src/lib/tls/tls_policy.cpp
1
/*
2
* Policies for TLS
3
* (C) 2004-2010,2012,2015,2016 Jack Lloyd
4
*     2016 Christian Mainka
5
*     2017 Harry Reimann, Rohde & Schwarz Cybersecurity
6
*     2022 René Meusel, Hannes Rantzsch - neXenio GmbH
7
*
8
* Botan is released under the Simplified BSD License (see license.txt)
9
*/
10

11
#include <botan/tls_policy.h>
12

13
#include <botan/pk_keys.h>
14
#include <botan/tls_algos.h>
15
#include <botan/tls_ciphersuite.h>
16
#include <botan/tls_exceptn.h>
17
#include <botan/internal/stl_util.h>
18
#include <optional>
19
#include <sstream>
20

21
namespace Botan::TLS {
22

23
std::vector<Signature_Scheme> Policy::allowed_signature_schemes() const {
5,247✔
24
   std::vector<Signature_Scheme> schemes;
5,247✔
25

26
   for(Signature_Scheme scheme : Signature_Scheme::all_available_schemes()) {
52,470✔
27
      const bool sig_allowed = allowed_signature_method(scheme.algorithm_name());
47,223✔
28
      const bool hash_allowed = allowed_signature_hash(scheme.hash_function_name());
47,223✔
29

30
      if(sig_allowed && hash_allowed) {
47,223✔
31
         schemes.push_back(scheme);
46,907✔
32
      }
33
   }
34

35
   return schemes;
5,247✔
36
}
×
37

38
std::vector<Signature_Scheme> Policy::acceptable_signature_schemes() const {
3,836✔
39
   return this->allowed_signature_schemes();
3,836✔
40
}
41

42
std::optional<std::vector<Signature_Scheme>> Policy::acceptable_certificate_signature_schemes() const {
3,705✔
43
   // the restrictions of ::acceptable_signature_schemes() shall apply
44
   return std::nullopt;
3,705✔
45
}
46

47
std::vector<std::string> Policy::allowed_ciphers() const {
26,995✔
48
   return {
26,995✔
49
      //"AES-256/OCB(12)",
50
      "ChaCha20Poly1305",
51
      "AES-256/GCM",
52
      "AES-128/GCM",
53
      //"AES-256/CCM",
54
      //"AES-128/CCM",
55
      //"AES-256/CCM(8)",
56
      //"AES-128/CCM(8)",
57
      //"Camellia-256/GCM",
58
      //"Camellia-128/GCM",
59
      //"ARIA-256/GCM",
60
      //"ARIA-128/GCM",
61
      //"AES-256",
62
      //"AES-128",
63
      //"3DES",
64
   };
107,980✔
65
}
66

67
std::vector<std::string> Policy::allowed_signature_hashes() const {
22,252✔
68
   return {
22,252✔
69
      "SHA-512",
70
      "SHA-384",
71
      "SHA-256",
72
   };
89,008✔
73
}
74

75
std::vector<std::string> Policy::allowed_macs() const {
3,705✔
76
   /*
77
   SHA-256 is preferred because the Lucky13 countermeasure works
78
   somewhat better for SHA-256 vs SHA-384:
79
   https://github.com/randombit/botan/pull/675
80
   */
81
   return {
3,705✔
82
      "AEAD",
83
      "SHA-256",
84
      "SHA-384",
85
      "SHA-1",
86
   };
18,525✔
87
}
88

89
std::vector<std::string> Policy::allowed_key_exchange_methods() const {
354✔
90
   return {
354✔
91
      //"ECDHE_PSK",
92
      //"PSK",
93
      "ECDH",
94
      "DH",
95
      //"RSA",
96
   };
1,062✔
97
}
98

99
std::vector<std::string> Policy::allowed_signature_methods() const {
22,301✔
100
   return {
22,301✔
101
      "ECDSA", "RSA",
102
      //"IMPLICIT",
103
   };
66,903✔
104
}
105

106
bool Policy::allowed_signature_method(std::string_view sig_method) const {
48,450✔
107
   return value_exists(allowed_signature_methods(), sig_method);
48,450✔
108
}
109

110
bool Policy::allowed_signature_hash(std::string_view sig_hash) const {
50,458✔
111
   return value_exists(allowed_signature_hashes(), sig_hash);
50,458✔
112
}
113

114
bool Policy::use_ecc_point_compression() const {
2,225✔
115
   return false;
2,225✔
116
}
117

118
Group_Params Policy::choose_key_exchange_group(const std::vector<Group_Params>& supported_by_peer,
512✔
119
                                               const std::vector<Group_Params>& offered_by_peer) const {
120
   if(supported_by_peer.empty()) {
512✔
121
      return Group_Params::NONE;
23✔
122
   }
123

124
   const std::vector<Group_Params> our_groups = key_exchange_groups();
489✔
125

126
   // Prefer groups that were offered by the peer for the sake of saving
127
   // an additional round trip. For TLS 1.2, this won't be used.
128
   for(auto g : offered_by_peer) {
489✔
129
      if(value_exists(our_groups, g)) {
38✔
130
         return g;
19✔
131
      }
132
   }
133

134
   // If no pre-offered groups fit our supported set, we prioritize our
135
   // own preference.
136
   for(auto g : our_groups) {
1,342✔
137
      if(value_exists(supported_by_peer, g)) {
2,684✔
138
         return g;
470✔
139
      }
140
   }
141

142
   return Group_Params::NONE;
×
143
}
512✔
144

145
Group_Params Policy::default_dh_group() const {
×
146
   /*
147
   * Return the first listed or just default to 2048
148
   */
149
   for(auto g : key_exchange_groups()) {
×
150
      if(g.is_dh_named_group()) {
×
151
         return g;
×
152
      }
153
   }
×
154

155
   return Group_Params::FFDHE_2048;
×
156
}
157

158
std::vector<Group_Params> Policy::key_exchange_groups() const {
8,763✔
159
   // Default list is ordered by performance
160
   return {
8,763✔
161
#if defined(BOTAN_HAS_CURVE_25519)
162
      Group_Params::X25519,
163
#endif
164

165
         Group_Params::SECP256R1, Group_Params::BRAINPOOL256R1, Group_Params::SECP384R1, Group_Params::BRAINPOOL384R1,
166
         Group_Params::SECP521R1, Group_Params::BRAINPOOL512R1,
167

168
         Group_Params::FFDHE_2048, Group_Params::FFDHE_3072, Group_Params::FFDHE_4096, Group_Params::FFDHE_6144,
169
         Group_Params::FFDHE_8192,
170
   };
8,763✔
171
}
172

173
std::vector<Group_Params> Policy::key_exchange_groups_to_offer() const {
971✔
174
   // by default, we offer a key share for the most-preferred group, only
175
   std::vector<Group_Params> groups_to_offer;
971✔
176
   const auto supported_groups = key_exchange_groups();
971✔
177
   if(!supported_groups.empty()) {
971✔
178
      groups_to_offer.push_back(supported_groups.front());
971✔
179
   }
180
   return groups_to_offer;
971✔
181
}
971✔
182

183
size_t Policy::minimum_dh_group_size() const {
20✔
184
   return 2048;
20✔
185
}
186

187
size_t Policy::minimum_ecdsa_group_size() const {
73✔
188
   // Here we are at the mercy of whatever the CA signed, but most certs should be 256 bit by now
189
   return 256;
73✔
190
}
191

192
size_t Policy::minimum_ecdh_group_size() const {
256✔
193
   // x25519 is smallest curve currently supported for TLS key exchange
194
   return 255;
256✔
195
}
196

197
size_t Policy::minimum_signature_strength() const {
17✔
198
   return 110;
17✔
199
}
200

201
bool Policy::require_cert_revocation_info() const {
98✔
202
   return true;
98✔
203
}
204

205
size_t Policy::minimum_rsa_bits() const {
1,046✔
206
   /* Default assumption is all end-entity certificates should
207
      be at least 2048 bits these days.
208

209
      If you are connecting to arbitrary servers on the Internet
210
      (ie as a web browser or SMTP client) you'll probably have to reduce this
211
      to 1024 bits, or perhaps even lower.
212
   */
213
   return 2048;
1,046✔
214
}
215

216
void Policy::check_peer_key_acceptable(const Public_Key& public_key) const {
3,221✔
217
   const std::string algo_name = public_key.algo_name();
3,221✔
218

219
   const size_t keylength = public_key.key_length();
3,221✔
220
   size_t expected_keylength = 0;
3,221✔
221

222
   if(algo_name == "RSA") {
3,221✔
223
      expected_keylength = minimum_rsa_bits();
1,046✔
224
   } else if(algo_name == "DH") {
2,175✔
225
      expected_keylength = minimum_dh_group_size();
9✔
226
   } else if(algo_name == "ECDH" || algo_name == "Curve25519") {
2,166✔
227
      expected_keylength = minimum_ecdh_group_size();
1,974✔
228
   } else if(algo_name == "ECDSA") {
192✔
229
      expected_keylength = minimum_ecdsa_group_size();
192✔
230
   }
231
   // else some other algo, so leave expected_keylength as zero and the check is a no-op
232

233
   if(keylength < expected_keylength) {
3,221✔
234
      throw TLS_Exception(Alert::InsufficientSecurity,
11✔
235
                          "Peer sent " + std::to_string(keylength) + " bit " + algo_name +
22✔
236
                             " key"
237
                             ", policy requires at least " +
22✔
238
                             std::to_string(expected_keylength));
22✔
239
   }
240
}
3,210✔
241

242
size_t Policy::maximum_session_tickets_per_client_hello() const {
7,118✔
243
   return 1;
7,118✔
244
}
245

246
std::chrono::seconds Policy::session_ticket_lifetime() const {
8,463✔
247
   return std::chrono::days(1);
8,463✔
248
}
249

250
bool Policy::reuse_session_tickets() const {
3,565✔
251
   return false;
3,565✔
252
}
253

254
size_t Policy::new_session_tickets_upon_handshake_success() const {
36✔
255
   return 1;
36✔
256
}
257

258
bool Policy::acceptable_protocol_version(Protocol_Version version) const {
12,618✔
259
#if defined(BOTAN_HAS_TLS_13)
260
   if(version == Protocol_Version::TLS_V13 && allow_tls13()) {
12,618✔
261
      return true;
262
   }
263
#endif
264

265
#if defined(BOTAN_HAS_TLS_12)
266
   if(version == Protocol_Version::TLS_V12 && allow_tls12()) {
9,184✔
267
      return true;
268
   }
269

270
   if(version == Protocol_Version::DTLS_V12 && allow_dtls12()) {
2,998✔
271
      return true;
1,837✔
272
   }
273
#endif
274

275
   return false;
276
}
277

278
Protocol_Version Policy::latest_supported_version(bool datagram) const {
3,962✔
279
   if(datagram) {
3,962✔
280
      if(acceptable_protocol_version(Protocol_Version::DTLS_V12)) {
776✔
281
         return Protocol_Version::DTLS_V12;
775✔
282
      }
283
      throw Invalid_State("Policy forbids all available DTLS version");
1✔
284
   } else {
285
#if defined(BOTAN_HAS_TLS_13)
286
      if(acceptable_protocol_version(Protocol_Version::TLS_V13)) {
3,186✔
287
         return Protocol_Version::TLS_V13;
1,967✔
288
      }
289
#endif
290
      if(acceptable_protocol_version(Protocol_Version::TLS_V12)) {
1,219✔
291
         return Protocol_Version::TLS_V12;
1,218✔
292
      }
293
      throw Invalid_State("Policy forbids all available TLS version");
1✔
294
   }
295
}
296

297
bool Policy::acceptable_ciphersuite(const Ciphersuite& ciphersuite) const {
27,907✔
298
   return value_exists(allowed_ciphers(), ciphersuite.cipher_algo()) &&
55,814✔
299
          value_exists(allowed_macs(), ciphersuite.mac_algo());
59,390✔
300
}
301

302
bool Policy::allow_client_initiated_renegotiation() const {
×
303
   return false;
×
304
}
305

306
bool Policy::allow_server_initiated_renegotiation() const {
11✔
307
   return false;
11✔
308
}
309

310
bool Policy::allow_insecure_renegotiation() const {
237✔
311
   return false;
237✔
312
}
313

314
bool Policy::allow_tls12() const {
9,932✔
315
#if defined(BOTAN_HAS_TLS_12)
316
   return true;
9,932✔
317
#else
318
   return false;
319
#endif
320
}
321

322
bool Policy::allow_tls13() const {
326✔
323
#if defined(BOTAN_HAS_TLS_13)
324
   return true;
326✔
325
#else
326
   return false;
327
#endif
328
}
329

330
bool Policy::allow_dtls12() const {
242✔
331
#if defined(BOTAN_HAS_TLS_12)
332
   return true;
242✔
333
#else
334
   return false;
335
#endif
336
}
337

338
bool Policy::include_time_in_hello_random() const {
6,728✔
339
   return true;
6,728✔
340
}
341

342
bool Policy::hide_unknown_users() const {
12✔
343
   return false;
12✔
344
}
345

346
bool Policy::server_uses_own_ciphersuite_preferences() const {
1,114✔
347
   return true;
1,114✔
348
}
349

350
bool Policy::negotiate_encrypt_then_mac() const {
3,386✔
351
   return true;
3,386✔
352
}
353

354
std::optional<uint16_t> Policy::record_size_limit() const {
1,275✔
355
   return std::nullopt;
1,275✔
356
}
357

358
bool Policy::support_cert_status_message() const {
2,285✔
359
   return true;
2,285✔
360
}
361

362
bool Policy::allow_resumption_for_renegotiation() const {
×
363
   return true;
×
364
}
365

366
bool Policy::tls_13_middlebox_compatibility_mode() const {
104✔
367
   return true;
104✔
368
}
369

370
bool Policy::hash_hello_random() const {
6,728✔
371
   return true;
6,728✔
372
}
373

374
bool Policy::only_resume_with_exact_version() const {
111✔
375
   return true;
111✔
376
}
377

378
bool Policy::require_client_certificate_authentication() const {
124✔
379
   return false;
124✔
380
}
381

382
bool Policy::request_client_certificate_authentication() const {
56✔
383
   return require_client_certificate_authentication();
56✔
384
}
385

386
bool Policy::abort_connection_on_undesired_renegotiation() const {
×
387
   return false;
×
388
}
389

390
bool Policy::allow_dtls_epoch0_restart() const {
55,417✔
391
   return false;
55,417✔
392
}
393

394
size_t Policy::maximum_certificate_chain_size() const {
217✔
395
   return 0;
217✔
396
}
397

398
// 1 second initial timeout, 60 second max - see RFC 6347 sec 4.2.4.1
399
size_t Policy::dtls_initial_timeout() const {
697✔
400
   return 1 * 1000;
697✔
401
}
402

403
size_t Policy::dtls_maximum_timeout() const {
697✔
404
   return 60 * 1000;
697✔
405
}
406

407
size_t Policy::dtls_default_mtu() const {
128✔
408
   // default MTU is IPv6 min MTU minus UDP/IP headers
409
   return 1280 - 40 - 8;
128✔
410
}
411

412
std::vector<uint16_t> Policy::srtp_profiles() const {
4✔
413
   return std::vector<uint16_t>();
4✔
414
}
415

416
namespace {
417

418
class Ciphersuite_Preference_Ordering final {
419
   public:
420
      Ciphersuite_Preference_Ordering(const std::vector<std::string>& ciphers,
362✔
421
                                      const std::vector<std::string>& macs,
422
                                      const std::vector<std::string>& kex,
423
                                      const std::vector<std::string>& sigs) :
362✔
424
            m_ciphers(ciphers), m_macs(macs), m_kex(kex), m_sigs(sigs) {}
362✔
425

426
      bool operator()(const Ciphersuite& a, const Ciphersuite& b) const {
2,777✔
427
         if(a.kex_method() != b.kex_method()) {
2,777✔
428
            for(const auto& i : m_kex) {
1,315✔
429
               if(a.kex_algo() == i) {
1,315✔
430
                  return true;
2,777✔
431
               }
432
               if(b.kex_algo() == i) {
733✔
433
                  return false;
434
               }
435
            }
436
         }
437

438
         if(a.cipher_algo() != b.cipher_algo()) {
2,605✔
439
            for(const auto& m_cipher : m_ciphers) {
4,186✔
440
               if(a.cipher_algo() == m_cipher) {
4,964✔
441
                  return true;
2,777✔
442
               }
443
               if(b.cipher_algo() == m_cipher) {
3,582✔
444
                  return false;
445
               }
446
            }
447
         }
448

449
         if(a.cipher_keylen() != b.cipher_keylen()) {
687✔
450
            if(a.cipher_keylen() < b.cipher_keylen()) {
×
451
               return false;
452
            }
453
            if(a.cipher_keylen() > b.cipher_keylen()) {
×
454
               return true;
455
            }
456
         }
457

458
         if(a.auth_method() != b.auth_method()) {
687✔
459
            for(const auto& m_sig : m_sigs) {
624✔
460
               if(a.sig_algo() == m_sig) {
624✔
461
                  return true;
2,777✔
462
               }
463
               if(b.sig_algo() == m_sig) {
514✔
464
                  return false;
465
               }
466
            }
467
         }
468

469
         if(a.mac_algo() != b.mac_algo()) {
63✔
470
            for(const auto& m_mac : m_macs) {
88✔
471
               if(a.mac_algo() == m_mac) {
88✔
472
                  return true;
473
               }
474
               if(b.mac_algo() == m_mac) {
37✔
475
                  return false;
476
               }
477
            }
478
         }
479

480
         return false;  // equal (?!?)
481
      }
482

483
   private:
484
      std::vector<std::string> m_ciphers, m_macs, m_kex, m_sigs;
485
};
486

487
}  // namespace
488

489
std::vector<uint16_t> Policy::ciphersuite_list(Protocol_Version version) const {
362✔
490
   const std::vector<std::string> ciphers = allowed_ciphers();
362✔
491
   const std::vector<std::string> macs = allowed_macs();
362✔
492
   const std::vector<std::string> kex = allowed_key_exchange_methods();
362✔
493
   const std::vector<std::string> sigs = allowed_signature_methods();
362✔
494

495
   std::vector<Ciphersuite> ciphersuites;
362✔
496

497
   for(auto&& suite : Ciphersuite::all_known_ciphersuites()) {
34,390✔
498
      // Can we use it?
499
      if(!suite.valid()) {
34,028✔
500
         continue;
×
501
      }
502

503
      // Can we use it in this version?
504
      if(!suite.usable_in_version(version)) {
34,028✔
505
         continue;
6,430✔
506
      }
507

508
      // Is it acceptable to the policy?
509
      if(!this->acceptable_ciphersuite(suite)) {
27,598✔
510
         continue;
24,340✔
511
      }
512

513
      if(!value_exists(ciphers, suite.cipher_algo())) {
3,878✔
514
         continue;  // unsupported cipher
×
515
      }
516

517
      // these checks are irrelevant for TLS 1.3
518
      // TODO: consider making a method for this logic
519
      if(version.is_pre_tls_13()) {
3,258✔
520
         if(!value_exists(kex, suite.kex_algo())) {
3,093✔
521
            continue;  // unsupported key exchange
1,805✔
522
         }
523

524
         if(!value_exists(macs, suite.mac_algo())) {
1,288✔
525
            continue;  // unsupported MAC algo
×
526
         }
527

528
         if(!value_exists(sigs, suite.sig_algo())) {
1,288✔
529
            // allow if it's an empty sig algo and we want to use PSK
530
            if(suite.auth_method() != Auth_Method::IMPLICIT || !suite.psk_ciphersuite()) {
66✔
531
               continue;
14✔
532
            }
533
         }
534
      }
535

536
      // OK, consider it
537
      ciphersuites.push_back(suite);
1,439✔
538
   }
539

540
   if(ciphersuites.empty()) {
362✔
541
      throw Invalid_State("Policy does not allow any available cipher suite");
×
542
   }
543

544
   Ciphersuite_Preference_Ordering order(ciphers, macs, kex, sigs);
362✔
545
   std::sort(ciphersuites.begin(), ciphersuites.end(), order);
362✔
546

547
   std::vector<uint16_t> ciphersuite_codes;
362✔
548
   ciphersuite_codes.reserve(ciphersuites.size());
362✔
549
   for(auto i : ciphersuites) {
1,801✔
550
      ciphersuite_codes.push_back(i.ciphersuite_code());
1,439✔
551
   }
552
   return ciphersuite_codes;
362✔
553
}
724✔
554

555
namespace {
556

557
void print_vec(std::ostream& o, const char* key, const std::vector<std::string>& v) {
60✔
558
   o << key << " = ";
60✔
559
   for(size_t i = 0; i != v.size(); ++i) {
184✔
560
      o << v[i];
124✔
561
      if(i != v.size() - 1) {
124✔
562
         o << ' ';
64✔
563
      }
564
   }
565
   o << '\n';
60✔
566
}
60✔
567

568
void print_vec(std::ostream& o, const char* key, const std::vector<Group_Params>& params) {
24✔
569
   // first filter out any groups we don't have a name for:
570
   std::vector<std::string> names;
24✔
571
   for(auto p : params) {
128✔
572
      if(auto name = p.to_string()) {
104✔
573
         names.push_back(name.value());
104✔
574
      }
104✔
575
   }
576

577
   o << key << " = ";
24✔
578

579
   for(size_t i = 0; i != names.size(); ++i) {
128✔
580
      o << names[i];
104✔
581
      if(i != names.size() - 1) {
104✔
582
         o << " ";
80✔
583
      }
584
   }
585
   o << "\n";
24✔
586
}
24✔
587

588
void print_bool(std::ostream& o, const char* key, bool b) {
144✔
589
   o << key << " = " << (b ? "true" : "false") << '\n';
194✔
590
}
144✔
591

592
}  // namespace
593

594
void Policy::print(std::ostream& o) const {
12✔
595
   print_bool(o, "allow_tls12", allow_tls12());
12✔
596
   print_bool(o, "allow_tls13", allow_tls13());
12✔
597
   print_bool(o, "allow_dtls12", allow_dtls12());
12✔
598
   print_vec(o, "ciphers", allowed_ciphers());
12✔
599
   print_vec(o, "macs", allowed_macs());
12✔
600
   print_vec(o, "signature_hashes", allowed_signature_hashes());
12✔
601
   print_vec(o, "signature_methods", allowed_signature_methods());
12✔
602
   print_vec(o, "key_exchange_methods", allowed_key_exchange_methods());
12✔
603
   print_vec(o, "key_exchange_groups", key_exchange_groups());
12✔
604
   const auto groups_to_offer = key_exchange_groups_to_offer();
12✔
605
   if(groups_to_offer.empty()) {
12✔
606
      print_vec(o, "key_exchange_groups_to_offer", {std::string("none")});
×
607
   } else {
608
      print_vec(o, "key_exchange_groups_to_offer", groups_to_offer);
12✔
609
   }
610
   print_bool(o, "allow_insecure_renegotiation", allow_insecure_renegotiation());
12✔
611
   print_bool(o, "include_time_in_hello_random", include_time_in_hello_random());
12✔
612
   print_bool(o, "allow_server_initiated_renegotiation", allow_server_initiated_renegotiation());
12✔
613
   print_bool(o, "hide_unknown_users", hide_unknown_users());
12✔
614
   print_bool(o, "server_uses_own_ciphersuite_preferences", server_uses_own_ciphersuite_preferences());
12✔
615
   print_bool(o, "negotiate_encrypt_then_mac", negotiate_encrypt_then_mac());
12✔
616
   print_bool(o, "support_cert_status_message", support_cert_status_message());
12✔
617
   print_bool(o, "tls_13_middlebox_compatibility_mode", tls_13_middlebox_compatibility_mode());
12✔
618
   print_bool(o, "hash_hello_random", hash_hello_random());
12✔
619
   if(record_size_limit().has_value()) {
12✔
620
      o << "record_size_limit = " << record_size_limit().value() << '\n';
×
621
   }
622
   o << "maximum_session_tickets_per_client_hello = " << maximum_session_tickets_per_client_hello() << '\n';
12✔
623
   o << "session_ticket_lifetime = " << session_ticket_lifetime().count() << '\n';
12✔
624
   o << "reuse_session_tickets = " << reuse_session_tickets() << '\n';
12✔
625
   o << "new_session_tickets_upon_handshake_success = " << new_session_tickets_upon_handshake_success() << '\n';
12✔
626
   o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n';
12✔
627
   o << "minimum_ecdh_group_size = " << minimum_ecdh_group_size() << '\n';
12✔
628
   o << "minimum_rsa_bits = " << minimum_rsa_bits() << '\n';
12✔
629
   o << "minimum_signature_strength = " << minimum_signature_strength() << '\n';
12✔
630
}
12✔
631

632
std::string Policy::to_string() const {
12✔
633
   std::ostringstream oss;
12✔
634
   this->print(oss);
12✔
635
   return oss.str();
24✔
636
}
12✔
637

638
std::vector<std::string> Strict_Policy::allowed_ciphers() const {
453✔
639
   return {"ChaCha20Poly1305", "AES-256/GCM", "AES-128/GCM"};
1,812✔
640
}
641

642
std::vector<std::string> Strict_Policy::allowed_signature_hashes() const {
79✔
643
   return {"SHA-512", "SHA-384"};
237✔
644
}
645

646
std::vector<std::string> Strict_Policy::allowed_macs() const {
91✔
647
   return {"AEAD"};
182✔
648
}
649

650
std::vector<std::string> Strict_Policy::allowed_key_exchange_methods() const {
6✔
651
   return {"ECDH"};
12✔
652
}
653

654
}  // namespace Botan::TLS
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