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

randombit / botan / 13274522654

11 Feb 2025 11:26PM UTC coverage: 91.645% (-0.007%) from 91.652%
13274522654

push

github

web-flow
Merge pull request #4647 from randombit/jack/internal-assert-and-mem-ops

Avoid using mem_ops.h or assert.h in public headers

94854 of 103501 relevant lines covered (91.65%)

11334975.77 hits per line

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

93.65
/src/lib/tls/tls_ciphersuite.cpp
1
/*
2
* TLS Cipher Suite
3
* (C) 2004-2010,2012,2013 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/tls_ciphersuite.h>
9

10
#include <botan/assert.h>
11
#include <botan/block_cipher.h>
12
#include <botan/exceptn.h>
13
#include <botan/hash.h>
14
#include <botan/stream_cipher.h>
15
#include <botan/internal/parsing.h>
16
#include <algorithm>
17

18
namespace Botan::TLS {
19

20
size_t Ciphersuite::nonce_bytes_from_handshake() const {
5,484✔
21
   switch(m_nonce_format) {
5,484✔
22
      case Nonce_Format::CBC_MODE: {
792✔
23
         if(cipher_algo() == "3DES") {
792✔
24
            return 8;
25
         } else {
26
            return 16;
660✔
27
         }
28
      }
29
      case Nonce_Format::AEAD_IMPLICIT_4:
30
         return 4;
31
      case Nonce_Format::AEAD_XOR_12:
3,627✔
32
         return 12;
3,627✔
33
   }
34

35
   throw Invalid_State("In Ciphersuite::nonce_bytes_from_handshake invalid enum value");
×
36
}
37

38
size_t Ciphersuite::nonce_bytes_from_record(Protocol_Version version) const {
3,591✔
39
   BOTAN_UNUSED(version);
3,591✔
40
   switch(m_nonce_format) {
3,591✔
41
      case Nonce_Format::CBC_MODE:
525✔
42
         return cipher_algo() == "3DES" ? 8 : 16;
962✔
43
      case Nonce_Format::AEAD_IMPLICIT_4:
44
         return 8;
45
      case Nonce_Format::AEAD_XOR_12:
2,356✔
46
         return 0;
2,356✔
47
   }
48

49
   throw Invalid_State("In Ciphersuite::nonce_bytes_from_handshake invalid enum value");
×
50
}
51

52
bool Ciphersuite::is_scsv(uint16_t suite) {
1,275✔
53
   // TODO: derive from IANA file in script
54
   return (suite == 0x00FF || suite == 0x5600);
1,275✔
55
}
56

57
bool Ciphersuite::psk_ciphersuite() const {
848✔
58
   return kex_method() == Kex_Algo::PSK || kex_method() == Kex_Algo::ECDHE_PSK;
848✔
59
}
60

61
bool Ciphersuite::ecc_ciphersuite() const {
1,005✔
62
   return kex_method() == Kex_Algo::ECDH || kex_method() == Kex_Algo::ECDHE_PSK || auth_method() == Auth_Method::ECDSA;
1,005✔
63
}
64

65
bool Ciphersuite::usable_in_version(Protocol_Version version) const {
364,543✔
66
   // RFC 8446 B.4.:
67
   //   Although TLS 1.3 uses the same cipher suite space as previous
68
   //   versions of TLS, TLS 1.3 cipher suites are defined differently, only
69
   //   specifying the symmetric ciphers, and cannot be used for TLS 1.2.
70
   //   Similarly, cipher suites for TLS 1.2 and lower cannot be used with
71
   //   TLS 1.3.
72
   //
73
   // Currently cipher suite codes {0x13,0x01} through {0x13,0x05} are
74
   // allowed for TLS 1.3. This may change in the future.
75
   const auto is_legacy_suite = (ciphersuite_code() & 0xFF00) != 0x1300;
364,543✔
76
   return version.is_pre_tls_13() == is_legacy_suite;
364,543✔
77
}
78

79
bool Ciphersuite::cbc_ciphersuite() const {
826✔
80
   return (mac_algo() != "AEAD");
826✔
81
}
82

83
bool Ciphersuite::aead_ciphersuite() const {
1,275✔
84
   return (mac_algo() == "AEAD");
1,275✔
85
}
86

87
bool Ciphersuite::signature_used() const {
6,193✔
88
   return auth_method() != Auth_Method::IMPLICIT;
6,193✔
89
}
90

91
std::optional<Ciphersuite> Ciphersuite::by_id(uint16_t suite) {
78,630✔
92
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
78,630✔
93
   auto s = std::lower_bound(all_suites.begin(), all_suites.end(), suite);
78,630✔
94

95
   if(s != all_suites.end() && s->ciphersuite_code() == suite) {
78,630✔
96
      return *s;
13,142✔
97
   }
98

99
   return std::nullopt;  // some unknown ciphersuite
65,488✔
100
}
101

102
std::optional<Ciphersuite> Ciphersuite::from_name(std::string_view name) {
89✔
103
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
89✔
104

105
   for(auto suite : all_suites) {
2,378✔
106
      if(suite.to_string() == name) {
7,134✔
107
         return suite;
89✔
108
      }
109
   }
110

111
   return std::nullopt;  // some unknown ciphersuite
×
112
}
113

114
namespace {
115

116
bool have_hash(std::string_view prf) {
259,036✔
117
   return (!HashFunction::providers(prf).empty());
259,036✔
118
}
119

120
bool have_cipher(std::string_view cipher) {
183,832✔
121
   return (!BlockCipher::providers(cipher).empty()) || (!StreamCipher::providers(cipher).empty());
183,832✔
122
}
123

124
}  // namespace
125

126
bool Ciphersuite::is_usable() const {
196,366✔
127
   if(!m_cipher_keylen) {  // uninitialized object
196,366✔
128
      return false;
129
   }
130

131
   if(!have_hash(prf_algo())) {
196,366✔
132
      return false;
133
   }
134

135
#if !defined(BOTAN_HAS_TLS_CBC)
136
   if(cbc_ciphersuite())
137
      return false;
138
#endif
139

140
   if(mac_algo() == "AEAD") {
196,366✔
141
      if(cipher_algo() == "ChaCha20Poly1305") {
133,696✔
142
#if !defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
143
         return false;
144
#endif
145
      } else {
146
         auto cipher_and_mode = split_on(cipher_algo(), '/');
121,162✔
147
         BOTAN_ASSERT(cipher_and_mode.size() == 2, "Expected format for AEAD algo");
121,162✔
148
         if(!have_cipher(cipher_and_mode[0])) {
121,162✔
149
            return false;
×
150
         }
151

152
         const auto& mode = cipher_and_mode[1];
121,162✔
153

154
#if !defined(BOTAN_HAS_AEAD_CCM)
155
         if(mode == "CCM" || mode == "CCM-8")
156
            return false;
157
#endif
158

159
#if !defined(BOTAN_HAS_AEAD_GCM)
160
         if(mode == "GCM")
161
            return false;
162
#endif
163

164
#if !defined(BOTAN_HAS_AEAD_OCB)
165
         if(mode == "OCB(12)" || mode == "OCB")
166
            return false;
167
#endif
168

169
         // Potentially unused if all AEADs are available
170
         BOTAN_UNUSED(mode);
121,162✔
171
      }
121,162✔
172
   } else {
173
      // Old non-AEAD schemes
174
      if(!have_cipher(cipher_algo())) {
62,670✔
175
         return false;
176
      }
177
      if(!have_hash(mac_algo())) {  // HMAC
62,670✔
178
         return false;
179
      }
180
   }
181

182
   if(kex_method() == Kex_Algo::ECDH || kex_method() == Kex_Algo::ECDHE_PSK) {
196,366✔
183
#if !defined(BOTAN_HAS_ECDH)
184
      return false;
185
#endif
186
   } else if(kex_method() == Kex_Algo::DH) {
187
#if !defined(BOTAN_HAS_DIFFIE_HELLMAN)
188
      return false;
189
#endif
190
   }
191

192
   if(auth_method() == Auth_Method::ECDSA) {
196,366✔
193
#if !defined(BOTAN_HAS_ECDSA)
194
      return false;
195
#endif
196
   } else if(auth_method() == Auth_Method::RSA) {
197
#if !defined(BOTAN_HAS_RSA)
198
      return false;
199
#endif
200
   }
201

202
   return true;
203
}
204

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