Coverage Report

Created: 2020-11-21 08:34

/src/botan/src/lib/tls/tls_ciphersuite.cpp
Line
Count
Source (jump to first uncovered line)
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
#include <botan/exceptn.h>
10
#include <botan/internal/parsing.h>
11
#include <botan/block_cipher.h>
12
#include <botan/stream_cipher.h>
13
#include <botan/hash.h>
14
#include <algorithm>
15
16
namespace Botan {
17
18
namespace TLS {
19
20
size_t Ciphersuite::nonce_bytes_from_handshake() const
21
18.4k
   {
22
18.4k
   switch(m_nonce_format)
23
18.4k
      {
24
9.25k
      case Nonce_Format::CBC_MODE:
25
9.25k
         {
26
9.25k
         if(cipher_algo() == "3DES")
27
2.89k
            return 8;
28
6.36k
         else
29
6.36k
            return 16;
30
0
         }
31
8.07k
      case Nonce_Format::AEAD_IMPLICIT_4:
32
8.07k
         return 4;
33
1.12k
      case Nonce_Format::AEAD_XOR_12:
34
1.12k
         return 12;
35
0
      }
36
37
0
   throw Invalid_State("In Ciphersuite::nonce_bytes_from_handshake invalid enum value");
38
0
   }
39
40
size_t Ciphersuite::nonce_bytes_from_record(Protocol_Version version) const
41
2.98k
   {
42
2.98k
   switch(m_nonce_format)
43
2.98k
      {
44
1.40k
      case Nonce_Format::CBC_MODE:
45
1.40k
         {
46
1.40k
         if(version.supports_explicit_cbc_ivs())
47
1.40k
            {
48
834
            return cipher_algo() == "3DES" ? 8 : 16;
49
1.40k
            }
50
0
         else
51
0
            {
52
0
            return 0;
53
0
            }
54
0
         }
55
872
      case Nonce_Format::AEAD_IMPLICIT_4:
56
872
         return 8;
57
711
      case Nonce_Format::AEAD_XOR_12:
58
711
         return 0;
59
0
      }
60
61
0
   throw Invalid_State("In Ciphersuite::nonce_bytes_from_handshake invalid enum value");
62
0
   }
63
64
bool Ciphersuite::is_scsv(uint16_t suite)
65
4.68k
   {
66
   // TODO: derive from IANA file in script
67
4.68k
   return (suite == 0x00FF || suite == 0x5600);
68
4.68k
   }
69
70
bool Ciphersuite::psk_ciphersuite() const
71
1.17k
   {
72
1.17k
   return kex_method() == Kex_Algo::PSK ||
73
1.17k
          kex_method() == Kex_Algo::DHE_PSK ||
74
1.16k
          kex_method() == Kex_Algo::ECDHE_PSK;
75
1.17k
   }
76
77
bool Ciphersuite::ecc_ciphersuite() const
78
32.9k
   {
79
32.9k
   return kex_method() == Kex_Algo::ECDH ||
80
32.8k
          kex_method() == Kex_Algo::ECDHE_PSK ||
81
14.3k
          auth_method() == Auth_Method::ECDSA;
82
32.9k
   }
83
84
bool Ciphersuite::usable_in_version(Protocol_Version version) const
85
4.68k
   {
86
4.68k
   if(!version.supports_aead_modes())
87
8
      {
88
      // Old versions do not support AEAD, or any MAC but SHA-1
89
8
      if(mac_algo() != "SHA-1")
90
1
         return false;
91
4.68k
      }
92
93
4.68k
   return true;
94
4.68k
   }
95
96
bool Ciphersuite::cbc_ciphersuite() const
97
25.6k
   {
98
25.6k
   return (mac_algo() != "AEAD");
99
25.6k
   }
100
101
bool Ciphersuite::signature_used() const
102
84.3k
   {
103
84.3k
   return auth_method() != Auth_Method::ANONYMOUS &&
104
71.9k
          auth_method() != Auth_Method::IMPLICIT;
105
84.3k
   }
106
107
Ciphersuite Ciphersuite::by_id(uint16_t suite)
108
87.4k
   {
109
87.4k
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
110
87.4k
   auto s = std::lower_bound(all_suites.begin(), all_suites.end(), suite);
111
112
87.4k
   if(s != all_suites.end() && s->ciphersuite_code() == suite)
113
87.3k
      {
114
87.3k
      return *s;
115
87.3k
      }
116
117
42
   return Ciphersuite(); // some unknown ciphersuite
118
42
   }
119
120
Ciphersuite Ciphersuite::from_name(const std::string& name)
121
0
   {
122
0
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
123
124
0
   for(auto suite : all_suites)
125
0
      {
126
0
      if(suite.to_string() == name)
127
0
         return suite;
128
0
      }
129
130
0
   return Ciphersuite(); // some unknown ciphersuite
131
0
   }
132
133
namespace {
134
135
bool have_hash(const std::string& prf)
136
540
   {
137
540
   return (HashFunction::providers(prf).size() > 0);
138
540
   }
139
140
bool have_cipher(const std::string& cipher)
141
350
   {
142
350
   return (BlockCipher::providers(cipher).size() > 0) ||
143
0
      (StreamCipher::providers(cipher).size() > 0);
144
350
   }
145
146
}
147
148
bool Ciphersuite::is_usable() const
149
366
   {
150
366
   if(!m_cipher_keylen) // uninitialized object
151
0
      return false;
152
153
366
   if(!have_hash(prf_algo()))
154
0
      return false;
155
156
#if !defined(BOTAN_HAS_TLS_CBC)
157
   if(cbc_ciphersuite())
158
      return false;
159
#endif
160
161
366
   if(mac_algo() == "AEAD")
162
192
      {
163
192
      if(cipher_algo() == "ChaCha20Poly1305")
164
16
         {
165
#if !defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
166
         return false;
167
#endif
168
16
         }
169
176
      else
170
176
         {
171
176
         auto cipher_and_mode = split_on(cipher_algo(), '/');
172
176
         BOTAN_ASSERT(cipher_and_mode.size() == 2, "Expected format for AEAD algo");
173
176
         if(!have_cipher(cipher_and_mode[0]))
174
0
            return false;
175
176
176
         const auto mode = cipher_and_mode[1];
177
178
#if !defined(BOTAN_HAS_AEAD_CCM)
179
         if(mode == "CCM" || mode == "CCM-8")
180
            return false;
181
#endif
182
183
#if !defined(BOTAN_HAS_AEAD_GCM)
184
         if(mode == "GCM")
185
            return false;
186
#endif
187
188
#if !defined(BOTAN_HAS_AEAD_OCB)
189
         if(mode == "OCB(12)" || mode == "OCB")
190
            return false;
191
#endif
192
176
         }
193
192
      }
194
174
   else
195
174
      {
196
      // Old non-AEAD schemes
197
174
      if(!have_cipher(cipher_algo()))
198
0
         return false;
199
174
      if(!have_hash(mac_algo())) // HMAC
200
0
         return false;
201
366
      }
202
203
366
   if(kex_method() == Kex_Algo::SRP_SHA)
204
18
      {
205
#if !defined(BOTAN_HAS_SRP6)
206
      return false;
207
#endif
208
18
      }
209
348
   else if(kex_method() == Kex_Algo::ECDH || kex_method() == Kex_Algo::ECDHE_PSK)
210
106
      {
211
#if !defined(BOTAN_HAS_ECDH)
212
      return false;
213
#endif
214
106
      }
215
242
   else if(kex_method() == Kex_Algo::DH || kex_method() == Kex_Algo::DHE_PSK)
216
150
      {
217
#if !defined(BOTAN_HAS_DIFFIE_HELLMAN)
218
      return false;
219
#endif
220
150
      }
221
92
   else if(kex_method() == Kex_Algo::CECPQ1)
222
12
      {
223
#if !defined(BOTAN_HAS_CECPQ1)
224
      return false;
225
#endif
226
12
      }
227
228
366
   if(auth_method() == Auth_Method::DSA)
229
38
      {
230
#if !defined(BOTAN_HAS_DSA)
231
      return false;
232
#endif
233
38
      }
234
328
   else if(auth_method() == Auth_Method::ECDSA)
235
46
      {
236
#if !defined(BOTAN_HAS_ECDSA)
237
      return false;
238
#endif
239
46
      }
240
282
   else if(auth_method() == Auth_Method::RSA)
241
90
      {
242
#if !defined(BOTAN_HAS_RSA)
243
      return false;
244
#endif
245
90
      }
246
247
366
   return true;
248
366
   }
249
250
}
251
252
}
253