Botan 2.19.5 Crypto and TLS for C&

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