Coverage Report

Created: 2020-02-14 15:38

/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/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
17.6k
   {
22
17.6k
   switch(m_nonce_format)
23
17.6k
      {
24
17.6k
      case Nonce_Format::CBC_MODE:
25
5.96k
         {
26
5.96k
         if(cipher_algo() == "3DES")
27
2.86k
            return 8;
28
3.10k
         else
29
3.10k
            return 16;
30
0
         }
31
10.6k
      case Nonce_Format::AEAD_IMPLICIT_4:
32
10.6k
         return 4;
33
1.01k
      case Nonce_Format::AEAD_XOR_12:
34
1.01k
         return 12;
35
0
      }
36
0
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.66k
   {
42
2.66k
   switch(m_nonce_format)
43
2.66k
      {
44
2.66k
      case Nonce_Format::CBC_MODE:
45
1.00k
         {
46
1.00k
         if(version.supports_explicit_cbc_ivs())
47
1.00k
            {
48
1.00k
            return cipher_algo() == "3DES" ? 8 : 16;
49
1.00k
            }
50
0
         else
51
0
            {
52
0
            return 0;
53
0
            }
54
0
         }
55
1.01k
      case Nonce_Format::AEAD_IMPLICIT_4:
56
1.01k
         return 8;
57
647
      case Nonce_Format::AEAD_XOR_12:
58
647
         return 0;
59
0
      }
60
0
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.54k
   {
66
4.54k
   // TODO: derive from IANA file in script
67
4.54k
   return (suite == 0x00FF || suite == 0x5600);
68
4.54k
   }
69
70
bool Ciphersuite::psk_ciphersuite() const
71
710
   {
72
710
   return kex_method() == Kex_Algo::PSK ||
73
710
          kex_method() == Kex_Algo::DHE_PSK ||
74
710
          kex_method() == Kex_Algo::ECDHE_PSK;
75
710
   }
76
77
bool Ciphersuite::ecc_ciphersuite() const
78
30.7k
   {
79
30.7k
   return kex_method() == Kex_Algo::ECDH ||
80
30.7k
          kex_method() == Kex_Algo::ECDHE_PSK ||
81
30.7k
          auth_method() == Auth_Method::ECDSA;
82
30.7k
   }
83
84
bool Ciphersuite::usable_in_version(Protocol_Version version) const
85
4.54k
   {
86
4.54k
   if(!version.supports_aead_modes())
87
4
      {
88
4
      // Old versions do not support AEAD, or any MAC but SHA-1
89
4
      if(mac_algo() != "SHA-1")
90
1
         return false;
91
4.54k
      }
92
4.54k
93
4.54k
   return true;
94
4.54k
   }
95
96
bool Ciphersuite::cbc_ciphersuite() const
97
23.3k
   {
98
23.3k
   return (mac_algo() != "AEAD");
99
23.3k
   }
100
101
bool Ciphersuite::signature_used() const
102
76.8k
   {
103
76.8k
   return auth_method() != Auth_Method::ANONYMOUS &&
104
76.8k
          auth_method() != Auth_Method::IMPLICIT;
105
76.8k
   }
106
107
Ciphersuite Ciphersuite::by_id(uint16_t suite)
108
79.9k
   {
109
79.9k
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
110
79.9k
   auto s = std::lower_bound(all_suites.begin(), all_suites.end(), suite);
111
79.9k
112
79.9k
   if(s != all_suites.end() && s->ciphersuite_code() == suite)
113
79.9k
      {
114
79.9k
      return *s;
115
79.9k
      }
116
33
117
33
   return Ciphersuite(); // some unknown ciphersuite
118
33
   }
119
120
Ciphersuite Ciphersuite::from_name(const std::string& name)
121
0
   {
122
0
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
123
0
124
0
   for(auto suite : all_suites)
125
0
      {
126
0
      if(suite.to_string() == name)
127
0
         return suite;
128
0
      }
129
0
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
350
      (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
366
153
366
   if(!have_hash(prf_algo()))
154
0
      return false;
155
366
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
         }
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
176
         const auto mode = cipher_and_mode[1];
177
176
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
         }
193
192
      }
194
174
   else
195
174
      {
196
174
      // 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
366
203
366
   if(kex_method() == Kex_Algo::SRP_SHA)
204
18
      {
205
#if !defined(BOTAN_HAS_SRP6)
206
      return false;
207
#endif
208
      }
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
      }
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
      }
221
92
   else if(kex_method() == Kex_Algo::CECPQ1)
222
12
      {
223
#if !defined(BOTAN_HAS_CECPQ1)
224
      return false;
225
#endif
226
      }
227
366
228
366
   if(auth_method() == Auth_Method::DSA)
229
38
      {
230
#if !defined(BOTAN_HAS_DSA)
231
      return false;
232
#endif
233
      }
234
328
   else if(auth_method() == Auth_Method::ECDSA)
235
46
      {
236
#if !defined(BOTAN_HAS_ECDSA)
237
      return false;
238
#endif
239
      }
240
282
   else if(auth_method() == Auth_Method::RSA)
241
90
      {
242
#if !defined(BOTAN_HAS_RSA)
243
      return false;
244
#endif
245
      }
246
366
247
366
   return true;
248
366
   }
249
250
}
251
252
}
253