Coverage Report

Created: 2021-05-04 09:02

/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
11.5k
   {
22
11.5k
   switch(m_nonce_format)
23
11.5k
      {
24
6.43k
      case Nonce_Format::CBC_MODE:
25
6.43k
         {
26
6.43k
         if(cipher_algo() == "3DES")
27
428
            return 8;
28
6.00k
         else
29
6.00k
            return 16;
30
0
         }
31
900
      case Nonce_Format::AEAD_IMPLICIT_4:
32
900
         return 4;
33
4.24k
      case Nonce_Format::AEAD_XOR_12:
34
4.24k
         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
1.34k
   {
42
1.34k
   BOTAN_UNUSED(version);
43
1.34k
   switch(m_nonce_format)
44
1.34k
      {
45
564
      case Nonce_Format::CBC_MODE:
46
422
         return cipher_algo() == "3DES" ? 8 : 16;
47
495
      case Nonce_Format::AEAD_IMPLICIT_4:
48
495
         return 8;
49
288
      case Nonce_Format::AEAD_XOR_12:
50
288
         return 0;
51
0
      }
52
53
0
   throw Invalid_State("In Ciphersuite::nonce_bytes_from_handshake invalid enum value");
54
0
   }
55
56
bool Ciphersuite::is_scsv(uint16_t suite)
57
0
   {
58
   // TODO: derive from IANA file in script
59
0
   return (suite == 0x00FF || suite == 0x5600);
60
0
   }
61
62
bool Ciphersuite::psk_ciphersuite() const
63
0
   {
64
0
   return kex_method() == Kex_Algo::PSK ||
65
0
          kex_method() == Kex_Algo::ECDHE_PSK;
66
0
   }
67
68
bool Ciphersuite::ecc_ciphersuite() const
69
22.9k
   {
70
22.9k
   return kex_method() == Kex_Algo::ECDH ||
71
22.9k
          kex_method() == Kex_Algo::ECDHE_PSK ||
72
1.24k
          auth_method() == Auth_Method::ECDSA;
73
22.9k
   }
74
75
bool Ciphersuite::usable_in_version(Protocol_Version version) const
76
0
   {
77
0
   BOTAN_UNUSED(version);
78
0
   return true;
79
0
   }
80
81
bool Ciphersuite::cbc_ciphersuite() const
82
22.3k
   {
83
22.3k
   return (mac_algo() != "AEAD");
84
22.3k
   }
85
86
bool Ciphersuite::signature_used() const
87
67.1k
   {
88
67.1k
   return auth_method() != Auth_Method::IMPLICIT;
89
67.1k
   }
90
91
Ciphersuite Ciphersuite::by_id(uint16_t suite)
92
67.2k
   {
93
67.2k
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
94
67.2k
   auto s = std::lower_bound(all_suites.begin(), all_suites.end(), suite);
95
96
67.2k
   if(s != all_suites.end() && s->ciphersuite_code() == suite)
97
67.1k
      {
98
67.1k
      return *s;
99
67.1k
      }
100
101
57
   return Ciphersuite(); // some unknown ciphersuite
102
57
   }
103
104
Ciphersuite Ciphersuite::from_name(const std::string& name)
105
0
   {
106
0
   const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
107
108
0
   for(auto suite : all_suites)
109
0
      {
110
0
      if(suite.to_string() == name)
111
0
         return suite;
112
0
      }
113
114
0
   return Ciphersuite(); // some unknown ciphersuite
115
0
   }
116
117
namespace {
118
119
bool have_hash(const std::string& prf)
120
250
   {
121
250
   return (HashFunction::providers(prf).size() > 0);
122
250
   }
123
124
bool have_cipher(const std::string& cipher)
125
176
   {
126
176
   return (BlockCipher::providers(cipher).size() > 0) ||
127
0
      (StreamCipher::providers(cipher).size() > 0);
128
176
   }
129
130
}
131
132
bool Ciphersuite::is_usable() const
133
190
   {
134
190
   if(!m_cipher_keylen) // uninitialized object
135
0
      return false;
136
137
190
   if(!have_hash(prf_algo()))
138
0
      return false;
139
140
#if !defined(BOTAN_HAS_TLS_CBC)
141
   if(cbc_ciphersuite())
142
      return false;
143
#endif
144
145
190
   if(mac_algo() == "AEAD")
146
130
      {
147
130
      if(cipher_algo() == "ChaCha20Poly1305")
148
14
         {
149
#if !defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
150
         return false;
151
#endif
152
14
         }
153
116
      else
154
116
         {
155
116
         auto cipher_and_mode = split_on(cipher_algo(), '/');
156
116
         BOTAN_ASSERT(cipher_and_mode.size() == 2, "Expected format for AEAD algo");
157
116
         if(!have_cipher(cipher_and_mode[0]))
158
0
            return false;
159
160
116
         const auto mode = cipher_and_mode[1];
161
162
#if !defined(BOTAN_HAS_AEAD_CCM)
163
         if(mode == "CCM" || mode == "CCM-8")
164
            return false;
165
#endif
166
167
#if !defined(BOTAN_HAS_AEAD_GCM)
168
         if(mode == "GCM")
169
            return false;
170
#endif
171
172
#if !defined(BOTAN_HAS_AEAD_OCB)
173
         if(mode == "OCB(12)" || mode == "OCB")
174
            return false;
175
#endif
176
116
         }
177
130
      }
178
60
   else
179
60
      {
180
      // Old non-AEAD schemes
181
60
      if(!have_cipher(cipher_algo()))
182
0
         return false;
183
60
      if(!have_hash(mac_algo())) // HMAC
184
0
         return false;
185
190
      }
186
187
190
   if(kex_method() == Kex_Algo::ECDH || kex_method() == Kex_Algo::ECDHE_PSK)
188
82
      {
189
#if !defined(BOTAN_HAS_ECDH)
190
      return false;
191
#endif
192
82
      }
193
108
   else if(kex_method() == Kex_Algo::DH)
194
32
      {
195
#if !defined(BOTAN_HAS_DIFFIE_HELLMAN)
196
      return false;
197
#endif
198
32
      }
199
76
   else if(kex_method() == Kex_Algo::CECPQ1)
200
12
      {
201
#if !defined(BOTAN_HAS_CECPQ1)
202
      return false;
203
#endif
204
12
      }
205
206
190
   if(auth_method() == Auth_Method::ECDSA)
207
40
      {
208
#if !defined(BOTAN_HAS_ECDSA)
209
      return false;
210
#endif
211
40
      }
212
150
   else if(auth_method() == Auth_Method::RSA)
213
64
      {
214
#if !defined(BOTAN_HAS_RSA)
215
      return false;
216
#endif
217
64
      }
218
219
190
   return true;
220
190
   }
221
222
}
223
224
}
225