• 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

93.0
/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,243✔
24
   std::vector<Signature_Scheme> schemes;
5,243✔
25

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

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

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

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

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

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

65
std::vector<std::string> Policy::allowed_signature_hashes() const {
22,418✔
66
   return {
22,418✔
67
      "SHA-512",
68
      "SHA-384",
69
      "SHA-256",
70
   };
89,672✔
71
}
72

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

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

97
std::vector<std::string> Policy::allowed_signature_methods() const {
22,436✔
98
   return {
22,436✔
99
      "ECDSA", "RSA",
100
      //"IMPLICIT",
101
   };
67,308✔
102
}
103

104
bool Policy::allowed_signature_method(std::string_view sig_method) const {
48,409✔
105
   return value_exists(allowed_signature_methods(), sig_method);
48,409✔
106
}
107

108
bool Policy::allowed_signature_hash(std::string_view sig_hash) const {
49,173✔
109
   return value_exists(allowed_signature_hashes(), sig_hash);
49,173✔
110
}
111

112
bool Policy::use_ecc_point_compression() const { return false; }
2,233✔
113

114
Group_Params Policy::choose_key_exchange_group(const std::vector<Group_Params>& supported_by_peer,
382✔
115
                                               const std::vector<Group_Params>& offered_by_peer) const {
116
   if(supported_by_peer.empty())
382✔
117
      return Group_Params::NONE;
118

119
   const std::vector<Group_Params> our_groups = key_exchange_groups();
379✔
120

121
   // Prefer groups that were offered by the peer for the sake of saving
122
   // an additional round trip. For TLS 1.2, this won't be used.
123
   for(auto g : offered_by_peer) {
379✔
124
      if(value_exists(our_groups, g))
32✔
125
         return g;
16✔
126
   }
127

128
   // If no pre-offered groups fit our supported set, we prioritize our
129
   // own preference.
130
   for(auto g : our_groups) {
377✔
131
      if(value_exists(supported_by_peer, g))
754✔
132
         return g;
363✔
133
   }
134

135
   return Group_Params::NONE;
136
}
382✔
137

138
Group_Params Policy::default_dh_group() const {
×
139
   /*
140
   * Return the first listed or just default to 2048
141
   */
142
   for(auto g : key_exchange_groups()) {
×
143
      if(group_param_is_dh(g))
×
144
         return g;
×
145
   }
×
146

147
   return Group_Params::FFDHE_2048;
×
148
}
149

150
std::vector<Group_Params> Policy::key_exchange_groups() const {
8,488✔
151
   // Default list is ordered by performance
152
   return {
8,488✔
153
#if defined(BOTAN_HAS_CURVE_25519)
154
      Group_Params::X25519,
155
#endif
156

157
         Group_Params::SECP256R1, Group_Params::BRAINPOOL256R1, Group_Params::SECP384R1, Group_Params::BRAINPOOL384R1,
158
         Group_Params::SECP521R1, Group_Params::BRAINPOOL512R1,
159

160
         Group_Params::FFDHE_2048, Group_Params::FFDHE_3072, Group_Params::FFDHE_4096, Group_Params::FFDHE_6144,
161
         Group_Params::FFDHE_8192,
162
   };
8,488✔
163
}
164

165
std::vector<Group_Params> Policy::key_exchange_groups_to_offer() const {
961✔
166
   // by default, we offer a key share for the most-preferred group, only
167
   std::vector<Group_Params> groups_to_offer;
961✔
168
   const auto supported_groups = key_exchange_groups();
961✔
169
   if(!supported_groups.empty())
961✔
170
      groups_to_offer.push_back(supported_groups.front());
961✔
171
   return groups_to_offer;
961✔
172
}
961✔
173

174
size_t Policy::minimum_dh_group_size() const { return 2048; }
22✔
175

176
size_t Policy::minimum_ecdsa_group_size() const {
77✔
177
   // Here we are at the mercy of whatever the CA signed, but most certs should be 256 bit by now
178
   return 256;
77✔
179
}
180

181
size_t Policy::minimum_ecdh_group_size() const {
256✔
182
   // x25519 is smallest curve currently supported for TLS key exchange
183
   return 255;
256✔
184
}
185

186
size_t Policy::minimum_signature_strength() const { return 110; }
15✔
187

188
bool Policy::require_cert_revocation_info() const { return true; }
102✔
189

190
size_t Policy::minimum_rsa_bits() const {
1,036✔
191
   /* Default assumption is all end-entity certificates should
192
      be at least 2048 bits these days.
193

194
      If you are connecting to arbitrary servers on the Internet
195
      (ie as a web browser or SMTP client) you'll probably have to reduce this
196
      to 1024 bits, or perhaps even lower.
197
   */
198
   return 2048;
1,036✔
199
}
200

201
void Policy::check_peer_key_acceptable(const Public_Key& public_key) const {
3,204✔
202
   const std::string algo_name = public_key.algo_name();
3,204✔
203

204
   const size_t keylength = public_key.key_length();
3,204✔
205
   size_t expected_keylength = 0;
3,204✔
206

207
   if(algo_name == "RSA") {
3,204✔
208
      expected_keylength = minimum_rsa_bits();
1,037✔
209
   } else if(algo_name == "DH") {
2,167✔
210
      expected_keylength = minimum_dh_group_size();
11✔
211
   } else if(algo_name == "ECDH" || algo_name == "Curve25519") {
2,156✔
212
      expected_keylength = minimum_ecdh_group_size();
1,960✔
213
   } else if(algo_name == "ECDSA") {
196✔
214
      expected_keylength = minimum_ecdsa_group_size();
196✔
215
   }
216
   // else some other algo, so leave expected_keylength as zero and the check is a no-op
217

218
   if(keylength < expected_keylength)
3,204✔
219
      throw TLS_Exception(Alert::InsufficientSecurity,
11✔
220
                          "Peer sent " + std::to_string(keylength) + " bit " + algo_name +
22✔
221
                             " key"
222
                             ", policy requires at least " +
22✔
223
                             std::to_string(expected_keylength));
22✔
224
}
3,193✔
225

226
size_t Policy::maximum_session_tickets_per_client_hello() const { return 1; }
7,084✔
227

228
std::chrono::seconds Policy::session_ticket_lifetime() const { return std::chrono::days(1); }
8,412✔
229

230
bool Policy::reuse_session_tickets() const { return false; }
3,548✔
231

232
size_t Policy::new_session_tickets_upon_handshake_success() const { return 1; }
32✔
233

234
bool Policy::acceptable_protocol_version(Protocol_Version version) const {
12,547✔
235
#if defined(BOTAN_HAS_TLS_13)
236
   if(version == Protocol_Version::TLS_V13 && allow_tls13())
12,547✔
237
      return true;
238
#endif
239

240
#if defined(BOTAN_HAS_TLS_12)
241
   if(version == Protocol_Version::TLS_V12 && allow_tls12())
9,150✔
242
      return true;
243

244
   if(version == Protocol_Version::DTLS_V12 && allow_dtls12())
2,978✔
245
      return true;
1,819✔
246
#endif
247

248
   return false;
249
}
250

251
Protocol_Version Policy::latest_supported_version(bool datagram) const {
3,935✔
252
   if(datagram) {
3,935✔
253
      if(acceptable_protocol_version(Protocol_Version::DTLS_V12))
770✔
254
         return Protocol_Version::DTLS_V12;
769✔
255
      throw Invalid_State("Policy forbids all available DTLS version");
1✔
256
   } else {
257
#if defined(BOTAN_HAS_TLS_13)
258
      if(acceptable_protocol_version(Protocol_Version::TLS_V13))
3,165✔
259
         return Protocol_Version::TLS_V13;
1,948✔
260
#endif
261
      if(acceptable_protocol_version(Protocol_Version::TLS_V12))
1,217✔
262
         return Protocol_Version::TLS_V12;
1,216✔
263
      throw Invalid_State("Policy forbids all available TLS version");
1✔
264
   }
265
}
266

267
bool Policy::acceptable_ciphersuite(const Ciphersuite& ciphersuite) const {
28,132✔
268
   return value_exists(allowed_ciphers(), ciphersuite.cipher_algo()) &&
56,264✔
269
          value_exists(allowed_macs(), ciphersuite.mac_algo());
59,805✔
270
}
271

272
bool Policy::allow_client_initiated_renegotiation() const { return false; }
×
273

274
bool Policy::allow_server_initiated_renegotiation() const { return false; }
11✔
275

276
bool Policy::allow_insecure_renegotiation() const { return false; }
237✔
277

278
bool Policy::allow_tls12() const {
9,912✔
279
#if defined(BOTAN_HAS_TLS_12)
280
   return true;
9,912✔
281
#else
282
   return false;
283
#endif
284
}
285

286
bool Policy::allow_tls13() const {
314✔
287
#if defined(BOTAN_HAS_TLS_13)
288
   return true;
314✔
289
#else
290
   return false;
291
#endif
292
}
293

294
bool Policy::allow_dtls12() const {
237✔
295
#if defined(BOTAN_HAS_TLS_12)
296
   return true;
237✔
297
#else
298
   return false;
299
#endif
300
}
301

302
bool Policy::include_time_in_hello_random() const { return true; }
6,694✔
303

304
bool Policy::hide_unknown_users() const { return false; }
12✔
305

306
bool Policy::server_uses_own_ciphersuite_preferences() const { return true; }
1,107✔
307

308
bool Policy::negotiate_encrypt_then_mac() const { return true; }
3,382✔
309

310
std::optional<uint16_t> Policy::record_size_limit() const { return std::nullopt; }
1,267✔
311

312
bool Policy::support_cert_status_message() const { return true; }
2,288✔
313

314
bool Policy::allow_resumption_for_renegotiation() const { return true; }
×
315

316
bool Policy::tls_13_middlebox_compatibility_mode() const { return true; }
92✔
317

318
bool Policy::hash_hello_random() const { return true; }
6,694✔
319

320
bool Policy::only_resume_with_exact_version() const { return true; }
111✔
321

322
bool Policy::require_client_certificate_authentication() const { return false; }
129✔
323

324
bool Policy::request_client_certificate_authentication() const { return require_client_certificate_authentication(); }
54✔
325

326
bool Policy::abort_connection_on_undesired_renegotiation() const { return false; }
×
327

328
bool Policy::allow_dtls_epoch0_restart() const { return false; }
53,861✔
329

330
size_t Policy::maximum_certificate_chain_size() const { return 0; }
228✔
331

332
// 1 second initial timeout, 60 second max - see RFC 6347 sec 4.2.4.1
333
size_t Policy::dtls_initial_timeout() const { return 1 * 1000; }
691✔
334

335
size_t Policy::dtls_maximum_timeout() const { return 60 * 1000; }
691✔
336

337
size_t Policy::dtls_default_mtu() const {
128✔
338
   // default MTU is IPv6 min MTU minus UDP/IP headers
339
   return 1280 - 40 - 8;
128✔
340
}
341

342
std::vector<uint16_t> Policy::srtp_profiles() const { return std::vector<uint16_t>(); }
4✔
343

344
namespace {
345

346
class Ciphersuite_Preference_Ordering final {
347
   public:
348
      Ciphersuite_Preference_Ordering(const std::vector<std::string>& ciphers,
357✔
349
                                      const std::vector<std::string>& macs,
350
                                      const std::vector<std::string>& kex,
351
                                      const std::vector<std::string>& sigs) :
357✔
352
            m_ciphers(ciphers), m_macs(macs), m_kex(kex), m_sigs(sigs) {}
357✔
353

354
      bool operator()(const Ciphersuite& a, const Ciphersuite& b) const {
2,750✔
355
         if(a.kex_method() != b.kex_method()) {
2,750✔
356
            for(const auto& i : m_kex) {
1,315✔
357
               if(a.kex_algo() == i)
1,315✔
358
                  return true;
2,750✔
359
               if(b.kex_algo() == i)
733✔
360
                  return false;
361
            }
362
         }
363

364
         if(a.cipher_algo() != b.cipher_algo()) {
2,566✔
365
            for(const auto& m_cipher : m_ciphers) {
4,156✔
366
               if(a.cipher_algo() == m_cipher)
4,920✔
367
                  return true;
2,750✔
368
               if(b.cipher_algo() == m_cipher)
3,566✔
369
                  return false;
370
            }
371
         }
372

373
         if(a.cipher_keylen() != b.cipher_keylen()) {
682✔
374
            if(a.cipher_keylen() < b.cipher_keylen())
×
375
               return false;
376
            if(a.cipher_keylen() > b.cipher_keylen())
×
377
               return true;
378
         }
379

380
         if(a.auth_method() != b.auth_method()) {
682✔
381
            for(const auto& m_sig : m_sigs) {
624✔
382
               if(a.sig_algo() == m_sig)
624✔
383
                  return true;
2,750✔
384
               if(b.sig_algo() == m_sig)
514✔
385
                  return false;
386
            }
387
         }
388

389
         if(a.mac_algo() != b.mac_algo()) {
58✔
390
            for(const auto& m_mac : m_macs) {
83✔
391
               if(a.mac_algo() == m_mac)
83✔
392
                  return true;
393
               if(b.mac_algo() == m_mac)
37✔
394
                  return false;
395
            }
396
         }
397

398
         return false;  // equal (?!?)
399
      }
400

401
   private:
402
      std::vector<std::string> m_ciphers, m_macs, m_kex, m_sigs;
403
};
404

405
}
406

407
std::vector<uint16_t> Policy::ciphersuite_list(Protocol_Version version) const {
357✔
408
   const std::vector<std::string> ciphers = allowed_ciphers();
357✔
409
   const std::vector<std::string> macs = allowed_macs();
357✔
410
   const std::vector<std::string> kex = allowed_key_exchange_methods();
357✔
411
   const std::vector<std::string> sigs = allowed_signature_methods();
357✔
412

413
   std::vector<Ciphersuite> ciphersuites;
357✔
414

415
   for(auto&& suite : Ciphersuite::all_known_ciphersuites()) {
33,915✔
416
      // Can we use it?
417
      if(!suite.valid())
33,558✔
418
         continue;
×
419

420
      // Can we use it in this version?
421
      if(!suite.usable_in_version(version))
33,558✔
422
         continue;
5,733✔
423

424
      // Is it acceptable to the policy?
425
      if(!this->acceptable_ciphersuite(suite))
27,825✔
426
         continue;
24,591✔
427

428
      if(!value_exists(ciphers, suite.cipher_algo()))
3,846✔
429
         continue;  // unsupported cipher
×
430

431
      // these checks are irrelevant for TLS 1.3
432
      // TODO: consider making a method for this logic
433
      if(version.is_pre_tls_13()) {
3,234✔
434
         if(!value_exists(kex, suite.kex_algo()))
3,093✔
435
            continue;  // unsupported key exchange
1,805✔
436

437
         if(!value_exists(macs, suite.mac_algo()))
1,288✔
438
            continue;  // unsupported MAC algo
×
439

440
         if(!value_exists(sigs, suite.sig_algo())) {
1,288✔
441
            // allow if it's an empty sig algo and we want to use PSK
442
            if(suite.auth_method() != Auth_Method::IMPLICIT || !suite.psk_ciphersuite())
67✔
443
               continue;
14✔
444
         }
445
      }
446

447
      // OK, consider it
448
      ciphersuites.push_back(suite);
1,415✔
449
   }
450

451
   if(ciphersuites.empty()) {
357✔
452
      throw Invalid_State("Policy does not allow any available cipher suite");
×
453
   }
454

455
   Ciphersuite_Preference_Ordering order(ciphers, macs, kex, sigs);
357✔
456
   std::sort(ciphersuites.begin(), ciphersuites.end(), order);
357✔
457

458
   std::vector<uint16_t> ciphersuite_codes;
357✔
459
   ciphersuite_codes.reserve(ciphersuites.size());
357✔
460
   for(auto i : ciphersuites)
1,772✔
461
      ciphersuite_codes.push_back(i.ciphersuite_code());
1,415✔
462
   return ciphersuite_codes;
357✔
463
}
714✔
464

465
namespace {
466

467
void print_vec(std::ostream& o, const char* key, const std::vector<std::string>& v) {
60✔
468
   o << key << " = ";
60✔
469
   for(size_t i = 0; i != v.size(); ++i) {
184✔
470
      o << v[i];
124✔
471
      if(i != v.size() - 1)
124✔
472
         o << ' ';
64✔
473
   }
474
   o << '\n';
60✔
475
}
60✔
476

477
void print_vec(std::ostream& o, const char* key, const std::vector<Group_Params>& v) {
24✔
478
   o << key << " = ";
24✔
479
   for(size_t i = 0; i != v.size(); ++i) {
128✔
480
      o << group_param_to_string(v[i]);
104✔
481
      if(i != v.size() - 1)
104✔
482
         o << ' ';
80✔
483
   }
484
   o << '\n';
24✔
485
}
24✔
486

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

489
}
490

491
void Policy::print(std::ostream& o) const {
12✔
492
   print_bool(o, "allow_tls12", allow_tls12());
12✔
493
   print_bool(o, "allow_tls13", allow_tls13());
12✔
494
   print_bool(o, "allow_dtls12", allow_dtls12());
12✔
495
   print_vec(o, "ciphers", allowed_ciphers());
12✔
496
   print_vec(o, "macs", allowed_macs());
12✔
497
   print_vec(o, "signature_hashes", allowed_signature_hashes());
12✔
498
   print_vec(o, "signature_methods", allowed_signature_methods());
12✔
499
   print_vec(o, "key_exchange_methods", allowed_key_exchange_methods());
12✔
500
   print_vec(o, "key_exchange_groups", key_exchange_groups());
12✔
501
   const auto groups_to_offer = key_exchange_groups_to_offer();
12✔
502
   if(groups_to_offer.empty()) {
12✔
503
      print_vec(o, "key_exchange_groups_to_offer", {std::string("none")});
×
504
   } else {
505
      print_vec(o, "key_exchange_groups_to_offer", groups_to_offer);
12✔
506
   }
507
   print_bool(o, "allow_insecure_renegotiation", allow_insecure_renegotiation());
12✔
508
   print_bool(o, "include_time_in_hello_random", include_time_in_hello_random());
12✔
509
   print_bool(o, "allow_server_initiated_renegotiation", allow_server_initiated_renegotiation());
12✔
510
   print_bool(o, "hide_unknown_users", hide_unknown_users());
12✔
511
   print_bool(o, "server_uses_own_ciphersuite_preferences", server_uses_own_ciphersuite_preferences());
12✔
512
   print_bool(o, "negotiate_encrypt_then_mac", negotiate_encrypt_then_mac());
12✔
513
   print_bool(o, "support_cert_status_message", support_cert_status_message());
12✔
514
   print_bool(o, "tls_13_middlebox_compatibility_mode", tls_13_middlebox_compatibility_mode());
12✔
515
   print_bool(o, "hash_hello_random", hash_hello_random());
12✔
516
   if(record_size_limit().has_value()) {
12✔
517
      o << "record_size_limit = " << record_size_limit().value() << '\n';
×
518
   }
519
   o << "maximum_session_tickets_per_client_hello = " << maximum_session_tickets_per_client_hello() << '\n';
12✔
520
   o << "session_ticket_lifetime = " << session_ticket_lifetime().count() << '\n';
12✔
521
   o << "reuse_session_tickets = " << reuse_session_tickets() << '\n';
12✔
522
   o << "new_session_tickets_upon_handshake_success = " << new_session_tickets_upon_handshake_success() << '\n';
12✔
523
   o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n';
12✔
524
   o << "minimum_ecdh_group_size = " << minimum_ecdh_group_size() << '\n';
12✔
525
   o << "minimum_rsa_bits = " << minimum_rsa_bits() << '\n';
12✔
526
   o << "minimum_signature_strength = " << minimum_signature_strength() << '\n';
12✔
527
}
12✔
528

529
std::string Policy::to_string() const {
12✔
530
   std::ostringstream oss;
12✔
531
   this->print(oss);
12✔
532
   return oss.str();
24✔
533
}
12✔
534

535
std::vector<std::string> Strict_Policy::allowed_ciphers() const {
453✔
536
   return {"ChaCha20Poly1305", "AES-256/GCM", "AES-128/GCM"};
1,812✔
537
}
538

539
std::vector<std::string> Strict_Policy::allowed_signature_hashes() const { return {"SHA-512", "SHA-384"}; }
237✔
540

541
std::vector<std::string> Strict_Policy::allowed_macs() const { return {"AEAD"}; }
182✔
542

543
std::vector<std::string> Strict_Policy::allowed_key_exchange_methods() const { return {"ECDH"}; }
12✔
544

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