aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/tls_policy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls/tls_policy.cpp')
-rw-r--r--src/tls/tls_policy.cpp232
1 files changed, 151 insertions, 81 deletions
diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp
index b510c3d4b..bc0cd53f5 100644
--- a/src/tls/tls_policy.cpp
+++ b/src/tls/tls_policy.cpp
@@ -1,95 +1,166 @@
/*
* Policies for TLS
-* (C) 2004-2010 Jack Lloyd
+* (C) 2004-2010,2012 Jack Lloyd
*
* Released under the terms of the Botan license
*/
#include <botan/tls_policy.h>
+#include <botan/tls_suites.h>
#include <botan/tls_exceptn.h>
+#include <botan/internal/stl_util.h>
namespace Botan {
-/*
-* Return allowed ciphersuites
-*/
-std::vector<u16bit> TLS_Policy::ciphersuites(bool have_srp) const
+std::vector<std::string> TLS_Policy::allowed_ciphers() const
{
- return suite_list(allow_static_rsa(), allow_edh_rsa(), allow_edh_dsa(),
- allow_srp() && have_srp);
+ std::vector<std::string> allowed;
+ allowed.push_back("AES-256");
+ allowed.push_back("AES-128");
+ allowed.push_back("TripleDES");
+ allowed.push_back("ARC4");
+ // Note that SEED is not included by default
+ return allowed;
}
-/*
-* Return allowed ciphersuites
-*/
-std::vector<u16bit> TLS_Policy::suite_list(bool use_rsa,
- bool use_edh_rsa,
- bool use_edh_dsa,
- bool use_srp) const
+std::vector<std::string> TLS_Policy::allowed_hashes() const
{
- std::vector<u16bit> suites;
+ std::vector<std::string> allowed;
+ allowed.push_back("SHA-256");
+ allowed.push_back("SHA-1");
+ // Note that MD5 is not included by default
+ return allowed;
+ }
- if(use_srp)
- {
- if(use_edh_rsa)
- {
- suites.push_back(TLS_SRP_SHA_DSS_WITH_AES_256_SHA);
- suites.push_back(TLS_SRP_SHA_DSS_WITH_AES_128_SHA);
- suites.push_back(TLS_SRP_SHA_DSS_WITH_3DES_EDE_SHA);
- }
+std::vector<std::string> TLS_Policy::allowed_key_exchange_methods() const
+ {
+ std::vector<std::string> allowed;
+ //allowed.push_back("ECDH");
+ //allowed.push_back("SRP");
+ allowed.push_back("DH");
+ allowed.push_back(""); // means RSA via server cert
+ return allowed;
+ }
- if(use_edh_dsa)
+std::vector<std::string> TLS_Policy::allowed_signature_methods() const
+ {
+ std::vector<std::string> allowed;
+ //allowed.push_back("ECDSA");
+ allowed.push_back("RSA");
+ allowed.push_back("DSA");
+ return allowed;
+ }
+
+namespace {
+
+class Ciphersuite_Preference_Ordering
+ {
+ public:
+ Ciphersuite_Preference_Ordering(const std::vector<std::string>& ciphers,
+ const std::vector<std::string>& hashes,
+ const std::vector<std::string>& kex,
+ const std::vector<std::string>& sigs) :
+ m_ciphers(ciphers), m_hashes(hashes), m_kex(kex), m_sigs(sigs) {}
+
+ bool operator()(const TLS_Ciphersuite& a, const TLS_Ciphersuite& b) const
{
- suites.push_back(TLS_SRP_SHA_RSA_WITH_AES_256_SHA);
- suites.push_back(TLS_SRP_SHA_RSA_WITH_AES_128_SHA);
- suites.push_back(TLS_SRP_SHA_RSA_WITH_3DES_EDE_SHA);
+ if(a.kex_algo() != b.kex_algo())
+ {
+ for(size_t i = 0; i != m_kex.size(); ++i)
+ {
+ if(a.kex_algo() == m_kex[i])
+ return true;
+ if(b.kex_algo() == m_kex[i])
+ return false;
+ }
+ }
+
+ if(a.cipher_algo() != b.cipher_algo())
+ {
+ for(size_t i = 0; i != m_ciphers.size(); ++i)
+ {
+ if(a.cipher_algo() == m_ciphers[i])
+ return true;
+ if(b.cipher_algo() == m_ciphers[i])
+ return false;
+ }
+ }
+
+ if(a.sig_algo() != b.sig_algo())
+ {
+ for(size_t i = 0; i != m_sigs.size(); ++i)
+ {
+ if(a.sig_algo() == m_sigs[i])
+ return true;
+ if(b.sig_algo() == m_sigs[i])
+ return false;
+ }
+ }
+
+ if(a.mac_algo() != b.mac_algo())
+ {
+ for(size_t i = 0; i != m_hashes.size(); ++i)
+ {
+ if(a.mac_algo() == m_hashes[i])
+ return true;
+ if(b.mac_algo() == m_hashes[i])
+ return false;
+ }
+ }
+
+ return false; // equal (?!?)
}
- }
+ private:
+ std::vector<std::string> m_ciphers, m_hashes, m_kex, m_sigs;
- if(use_edh_dsa)
- {
- suites.push_back(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256);
- suites.push_back(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256);
+ };
- suites.push_back(TLS_DHE_DSS_WITH_AES_256_CBC_SHA);
- suites.push_back(TLS_DHE_DSS_WITH_AES_128_CBC_SHA);
+}
- suites.push_back(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
- suites.push_back(TLS_DHE_DSS_WITH_SEED_CBC_SHA);
- }
+std::vector<u16bit> TLS_Policy::ciphersuite_list(bool have_srp) const
+ {
+ std::vector<std::string> ciphers = allowed_ciphers();
+ std::vector<std::string> hashes = allowed_hashes();
+ std::vector<std::string> kex = allowed_key_exchange_methods();
+ std::vector<std::string> sigs = allowed_signature_methods();
- if(use_edh_rsa)
+ if(!have_srp)
{
- suites.push_back(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256);
- suites.push_back(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256);
-
- suites.push_back(TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
- suites.push_back(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
+ std::vector<std::string>::iterator i = std::find(kex.begin(), kex.end(), "SRP");
- suites.push_back(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
- suites.push_back(TLS_DHE_RSA_WITH_SEED_CBC_SHA);
+ if(i != kex.end())
+ kex.erase(i);
}
- if(use_rsa)
- {
- suites.push_back(TLS_RSA_WITH_AES_256_CBC_SHA256);
- suites.push_back(TLS_RSA_WITH_AES_128_CBC_SHA256);
+ Ciphersuite_Preference_Ordering order(ciphers, hashes, kex, sigs);
- suites.push_back(TLS_RSA_WITH_AES_256_CBC_SHA);
- suites.push_back(TLS_RSA_WITH_AES_128_CBC_SHA);
+ std::map<TLS_Ciphersuite, u16bit, Ciphersuite_Preference_Ordering> ciphersuites(order);
- suites.push_back(TLS_RSA_WITH_3DES_EDE_CBC_SHA);
- suites.push_back(TLS_RSA_WITH_SEED_CBC_SHA);
-
- suites.push_back(TLS_RSA_WITH_RC4_128_SHA);
- suites.push_back(TLS_RSA_WITH_RC4_128_MD5);
+ // When in doubt use brute force :)
+ for(u32bit i = 0; i != 65536; ++i)
+ {
+ TLS_Ciphersuite suite = TLS_Ciphersuite::lookup_ciphersuite(i);
+ if(suite.cipher_keylen() == 0)
+ continue; // not a ciphersuite we know
+
+ if(value_exists(ciphers, suite.cipher_algo()) &&
+ value_exists(hashes, suite.mac_algo()) &&
+ value_exists(kex, suite.kex_algo()) &&
+ value_exists(sigs, suite.sig_algo()))
+ {
+ ciphersuites[suite] = i;
+ }
}
- if(suites.size() == 0)
- throw TLS_Exception(INTERNAL_ERROR,
- "TLS_Policy error: All ciphersuites disabled");
+ std::vector<u16bit> ciphersuite_codes;
+
+ for(std::map<TLS_Ciphersuite, u16bit, Ciphersuite_Preference_Ordering>::iterator i = ciphersuites.begin();
+ i != ciphersuites.end(); ++i)
+ {
+ ciphersuite_codes.push_back(i->second);
+ }
- return suites;
+ return ciphersuite_codes;
}
/*
@@ -105,23 +176,30 @@ std::vector<byte> TLS_Policy::compression() const
/*
* Choose which ciphersuite to use
*/
-u16bit TLS_Policy::choose_suite(const std::vector<u16bit>& c_suites,
+u16bit TLS_Policy::choose_suite(const std::vector<u16bit>& client_suites,
bool have_rsa,
bool have_dsa,
bool have_srp) const
{
- const bool use_static_rsa = allow_static_rsa() && have_rsa;
- const bool use_edh_rsa = allow_edh_rsa() && have_rsa;
- const bool use_edh_dsa = allow_edh_dsa() && have_dsa;
- const bool use_srp = allow_srp() && have_srp;
-
- std::vector<u16bit> s_suites = suite_list(use_static_rsa, use_edh_rsa,
- use_edh_dsa, use_srp);
-
- for(size_t i = 0; i != s_suites.size(); ++i)
- for(size_t j = 0; j != c_suites.size(); ++j)
- if(s_suites[i] == c_suites[j])
- return s_suites[i];
+ for(size_t i = 0; i != client_suites.size(); ++i)
+ {
+ u16bit suite_id = client_suites[i];
+ TLS_Ciphersuite suite = TLS_Ciphersuite::lookup_ciphersuite(suite_id);
+ if(suite.cipher_keylen() == 0)
+ continue; // not a ciphersuite we know
+
+ if(!have_srp && suite.kex_algo() == "SRP")
+ continue;
+
+ if(suite.sig_algo() == "RSA" && have_rsa)
+ return suite_id;
+ else if(suite.sig_algo() == "DSA" && have_dsa)
+ return suite_id;
+#if 0
+ else if(suite.sig_algo() == "") // anonymous server
+ return suite_id;
+#endif
+ }
return 0;
}
@@ -141,12 +219,4 @@ byte TLS_Policy::choose_compression(const std::vector<byte>& c_comp) const
return NO_COMPRESSION;
}
-/*
-* Return the group to use for empheral DH
-*/
-DL_Group TLS_Policy::dh_group() const
- {
- return DL_Group("modp/ietf/1024");
- }
-
}