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

randombit / botan / 4892192195

05 May 2023 10:32AM UTC coverage: 91.732% (+0.008%) from 91.724%
4892192195

push

github

77631 of 84628 relevant lines covered (91.73%)

11913034.27 hits per line

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

94.03
/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/exceptn.h>
11
#include <botan/internal/parsing.h>
12
#include <botan/block_cipher.h>
13
#include <botan/stream_cipher.h>
14
#include <botan/hash.h>
15
#include <algorithm>
16

17
namespace Botan::TLS {
18

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

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

39
size_t Ciphersuite::nonce_bytes_from_record(Protocol_Version version) const
3,503✔
40
   {
41
   BOTAN_UNUSED(version);
3,503✔
42
   switch(m_nonce_format)
3,503✔
43
      {
44
      case Nonce_Format::CBC_MODE:
499✔
45
         return cipher_algo() == "3DES" ? 8 : 16;
898✔
46
      case Nonce_Format::AEAD_IMPLICIT_4:
47
         return 8;
48
      case Nonce_Format::AEAD_XOR_12:
2,302✔
49
         return 0;
2,302✔
50
      }
51

52
   throw Invalid_State("In Ciphersuite::nonce_bytes_from_handshake invalid enum value");
×
53
   }
54

55
bool Ciphersuite::is_scsv(uint16_t suite)
1,199✔
56
   {
57
   // TODO: derive from IANA file in script
58
   return (suite == 0x00FF || suite == 0x5600);
1,199✔
59
   }
60

61
bool Ciphersuite::psk_ciphersuite() const
2,516✔
62
   {
63
   return kex_method() == Kex_Algo::PSK ||
2,516✔
64
          kex_method() == Kex_Algo::ECDHE_PSK;
2,370✔
65
   }
66

67
bool Ciphersuite::ecc_ciphersuite() const
944✔
68
   {
69
   return kex_method() == Kex_Algo::ECDH ||
944✔
70
          kex_method() == Kex_Algo::ECDHE_PSK ||
944✔
71
          auth_method() == Auth_Method::ECDSA;
122✔
72
   }
73

74
bool Ciphersuite::usable_in_version(Protocol_Version version) const
345,831✔
75
   {
76
   // RFC 8446 B.4.:
77
   //   Although TLS 1.3 uses the same cipher suite space as previous
78
   //   versions of TLS, TLS 1.3 cipher suites are defined differently, only
79
   //   specifying the symmetric ciphers, and cannot be used for TLS 1.2.
80
   //   Similarly, cipher suites for TLS 1.2 and lower cannot be used with
81
   //   TLS 1.3.
82
   //
83
   // Currently cipher suite codes {0x13,0x01} through {0x13,0x05} are
84
   // allowed for TLS 1.3. This may change in the future.
85
   const auto is_legacy_suite = (ciphersuite_code() & 0xFF00) != 0x1300;
345,831✔
86
   return version.is_pre_tls_13() == is_legacy_suite;
345,831✔
87
   }
88

89
bool Ciphersuite::cbc_ciphersuite() const
775✔
90
   {
91
   return (mac_algo() != "AEAD");
775✔
92
   }
93

94
bool Ciphersuite::aead_ciphersuite() const
1,199✔
95
   {
96
   return (mac_algo() == "AEAD");
1,199✔
97
   }
98

99
bool Ciphersuite::signature_used() const
5,722✔
100
   {
101
   return auth_method() != Auth_Method::IMPLICIT;
5,722✔
102
   }
103

104
std::optional<Ciphersuite> Ciphersuite::by_id(uint16_t suite)
78,061✔
105
   {
106
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
78,061✔
107
   auto s = std::lower_bound(all_suites.begin(), all_suites.end(), suite);
78,061✔
108

109
   if(s != all_suites.end() && s->ciphersuite_code() == suite)
78,061✔
110
      {
111
      return *s;
12,573✔
112
      }
113

114
   return std::nullopt; // some unknown ciphersuite
65,488✔
115
   }
116

117
std::optional<Ciphersuite> Ciphersuite::from_name(std::string_view name)
89✔
118
   {
119
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
89✔
120

121
   for(auto suite : all_suites)
2,378✔
122
      {
123
      if(suite.to_string() == name)
7,326✔
124
         return suite;
89✔
125
      }
126

127
   return std::nullopt; // some unknown ciphersuite
×
128
   }
129

130
namespace {
131

132
bool have_hash(std::string_view prf)
241,552✔
133
   {
134
   return (!HashFunction::providers(prf).empty());
241,552✔
135
   }
136

137
bool have_cipher(std::string_view cipher)
171,424✔
138
   {
139
   return (!BlockCipher::providers(cipher).empty()) ||
171,424✔
140
      (!StreamCipher::providers(cipher).empty());
171,424✔
141
   }
142

143
}
144

145
bool Ciphersuite::is_usable() const
183,112✔
146
   {
147
   if(!m_cipher_keylen) // uninitialized object
183,112✔
148
      return false;
149

150
   if(!have_hash(prf_algo()))
183,112✔
151
      return false;
152

153
#if !defined(BOTAN_HAS_TLS_CBC)
154
   if(cbc_ciphersuite())
155
      return false;
156
#endif
157

158
   if(mac_algo() == "AEAD")
183,112✔
159
      {
160
      if(cipher_algo() == "ChaCha20Poly1305")
155,840✔
161
         {
162
#if !defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
163
         return false;
164
#endif
165
         }
166
      else
167
         {
168
         auto cipher_and_mode = split_on(cipher_algo(), '/');
112,984✔
169
         BOTAN_ASSERT(cipher_and_mode.size() == 2, "Expected format for AEAD algo");
112,984✔
170
         if(!have_cipher(cipher_and_mode[0]))
112,984✔
171
            return false;
×
172

173
         const auto mode = cipher_and_mode[1];
225,968✔
174

175
#if !defined(BOTAN_HAS_AEAD_CCM)
176
         if(mode == "CCM" || mode == "CCM-8")
177
            return false;
178
#endif
179

180
#if !defined(BOTAN_HAS_AEAD_GCM)
181
         if(mode == "GCM")
182
            return false;
183
#endif
184

185
#if !defined(BOTAN_HAS_AEAD_OCB)
186
         if(mode == "OCB(12)" || mode == "OCB")
187
            return false;
188
#endif
189
         }
112,984✔
190
      }
191
   else
192
      {
193
      // Old non-AEAD schemes
194
      if(!have_cipher(cipher_algo()))
58,440✔
195
         return false;
196
      if(!have_hash(mac_algo())) // HMAC
58,440✔
197
         return false;
198
      }
199

200
   if(kex_method() == Kex_Algo::ECDH || kex_method() == Kex_Algo::ECDHE_PSK)
183,112✔
201
      {
202
#if !defined(BOTAN_HAS_ECDH)
203
      return false;
204
#endif
205
      }
206
   else if(kex_method() == Kex_Algo::DH)
207
      {
208
#if !defined(BOTAN_HAS_DIFFIE_HELLMAN)
209
      return false;
210
#endif
211
      }
212

213
   if(auth_method() == Auth_Method::ECDSA)
183,112✔
214
      {
215
#if !defined(BOTAN_HAS_ECDSA)
216
      return false;
217
#endif
218
      }
219
   else if(auth_method() == Auth_Method::RSA)
220
      {
221
#if !defined(BOTAN_HAS_RSA)
222
      return false;
223
#endif
224
      }
225

226
   return true;
227
   }
228

229
}
230

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