Botan  2.10.0
Crypto and TLS for C++11
tls_ciphersuite.cpp
Go to the documentation of this file.
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  {
22  switch(m_nonce_format)
23  {
25  {
26  if(cipher_algo() == "3DES")
27  return 8;
28  else
29  return 16;
30  }
32  return 4;
34  return 12;
35  }
36 
37  throw Invalid_State("In Ciphersuite::nonce_bytes_from_handshake invalid enum value");
38  }
39 
40 bool Ciphersuite::is_scsv(uint16_t suite)
41  {
42  // TODO: derive from IANA file in script
43  return (suite == 0x00FF || suite == 0x5600);
44  }
45 
46 bool Ciphersuite::psk_ciphersuite() const
47  {
48  return kex_method() == Kex_Algo::PSK ||
49  kex_method() == Kex_Algo::DHE_PSK ||
50  kex_method() == Kex_Algo::ECDHE_PSK;
51  }
52 
53 bool Ciphersuite::ecc_ciphersuite() const
54  {
55  return kex_method() == Kex_Algo::ECDH ||
56  kex_method() == Kex_Algo::ECDHE_PSK ||
57  auth_method() == Auth_Method::ECDSA;
58  }
59 
60 bool Ciphersuite::cbc_ciphersuite() const
61  {
62  return (mac_algo() != "AEAD");
63  }
64 
65 bool Ciphersuite::signature_used() const
66  {
67  return auth_method() != Auth_Method::ANONYMOUS &&
68  auth_method() != Auth_Method::IMPLICIT;
69  }
70 
71 Ciphersuite Ciphersuite::by_id(uint16_t suite)
72  {
73  const std::vector<Ciphersuite>& all_suites = all_known_ciphersuites();
74  auto s = std::lower_bound(all_suites.begin(), all_suites.end(), suite);
75 
76  if(s != all_suites.end() && s->ciphersuite_code() == suite)
77  {
78  return *s;
79  }
80 
81  return Ciphersuite(); // some unknown ciphersuite
82  }
83 
84 namespace {
85 
86 bool have_hash(const std::string& prf)
87  {
88  return (HashFunction::providers(prf).size() > 0);
89  }
90 
91 bool have_cipher(const std::string& cipher)
92  {
93  return (BlockCipher::providers(cipher).size() > 0) ||
94  (StreamCipher::providers(cipher).size() > 0);
95  }
96 
97 }
98 
99 bool Ciphersuite::is_usable() const
100  {
101  if(!m_cipher_keylen) // uninitialized object
102  return false;
103 
104  if(!have_hash(prf_algo()))
105  return false;
106 
107 #if !defined(BOTAN_HAS_TLS_CBC)
108  if(cbc_ciphersuite())
109  return false;
110 #endif
111 
112  if(mac_algo() == "AEAD")
113  {
114  if(cipher_algo() == "ChaCha20Poly1305")
115  {
116 #if !defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
117  return false;
118 #endif
119  }
120  else
121  {
122  auto cipher_and_mode = split_on(cipher_algo(), '/');
123  BOTAN_ASSERT(cipher_and_mode.size() == 2, "Expected format for AEAD algo");
124  if(!have_cipher(cipher_and_mode[0]))
125  return false;
126 
127  const auto mode = cipher_and_mode[1];
128 
129 #if !defined(BOTAN_HAS_AEAD_CCM)
130  if(mode == "CCM" || mode == "CCM-8")
131  return false;
132 #endif
133 
134 #if !defined(BOTAN_HAS_AEAD_GCM)
135  if(mode == "GCM")
136  return false;
137 #endif
138 
139 #if !defined(BOTAN_HAS_AEAD_OCB)
140  if(mode == "OCB(12)" || mode == "OCB")
141  return false;
142 #endif
143  }
144  }
145  else
146  {
147  // Old non-AEAD schemes
148  if(!have_cipher(cipher_algo()))
149  return false;
150  if(!have_hash(mac_algo())) // HMAC
151  return false;
152  }
153 
154  if(kex_method() == Kex_Algo::SRP_SHA)
155  {
156 #if !defined(BOTAN_HAS_SRP6)
157  return false;
158 #endif
159  }
160  else if(kex_method() == Kex_Algo::ECDH || kex_method() == Kex_Algo::ECDHE_PSK)
161  {
162 #if !defined(BOTAN_HAS_ECDH)
163  return false;
164 #endif
165  }
166  else if(kex_method() == Kex_Algo::DH || kex_method() == Kex_Algo::DHE_PSK)
167  {
168 #if !defined(BOTAN_HAS_DIFFIE_HELLMAN)
169  return false;
170 #endif
171  }
172  else if(kex_method() == Kex_Algo::CECPQ1)
173  {
174 #if !defined(BOTAN_HAS_CECPQ1)
175  return false;
176 #endif
177  }
178 
179  if(auth_method() == Auth_Method::DSA)
180  {
181 #if !defined(BOTAN_HAS_DSA)
182  return false;
183 #endif
184  }
185  else if(auth_method() == Auth_Method::ECDSA)
186  {
187 #if !defined(BOTAN_HAS_ECDSA)
188  return false;
189 #endif
190  }
191  else if(auth_method() == Auth_Method::RSA)
192  {
193 #if !defined(BOTAN_HAS_RSA)
194  return false;
195 #endif
196  }
197 
198  return true;
199  }
200 
201 }
202 
203 }
204 
botan_rng_t const botan_mp_t lower_bound
Definition: ffi.h:858
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:144
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
uint8_t size_t botan_rng_t const char uint32_t size_t const char * cipher_algo
Definition: ffi.h:1040
void BlockCipher * cipher
Definition: package.h:29
void uint8_t const uint8_t RandomNumberGenerator Newhope_Mode mode
Definition: newhope.h:75
Definition: alg_id.cpp:13