Botan
1.11.15
|
00001 /* 00002 * Hooks for application level policies on TLS connections 00003 * (C) 2004-2006,2013 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #ifndef BOTAN_TLS_POLICY_H__ 00009 #define BOTAN_TLS_POLICY_H__ 00010 00011 #include <botan/tls_version.h> 00012 #include <botan/tls_ciphersuite.h> 00013 #include <botan/x509cert.h> 00014 #include <botan/dl_group.h> 00015 #include <vector> 00016 00017 namespace Botan { 00018 00019 namespace TLS { 00020 00021 /** 00022 * TLS Policy Base Class 00023 * Inherit and overload as desired to suit local policy concerns 00024 */ 00025 class BOTAN_DLL Policy 00026 { 00027 public: 00028 00029 /** 00030 * Returns a list of ciphers we are willing to negotiate, in 00031 * order of preference. 00032 */ 00033 virtual std::vector<std::string> allowed_ciphers() const; 00034 00035 /** 00036 * Returns a list of hash algorithms we are willing to use for 00037 * signatures, in order of preference. 00038 */ 00039 virtual std::vector<std::string> allowed_signature_hashes() const; 00040 00041 /** 00042 * Returns a list of MAC algorithms we are willing to use. 00043 */ 00044 virtual std::vector<std::string> allowed_macs() const; 00045 00046 /** 00047 * Returns a list of key exchange algorithms we are willing to 00048 * use, in order of preference. Allowed values: DH, empty string 00049 * (representing RSA using server certificate key) 00050 */ 00051 virtual std::vector<std::string> allowed_key_exchange_methods() const; 00052 00053 /** 00054 * Returns a list of signature algorithms we are willing to 00055 * use, in order of preference. Allowed values RSA and DSA. 00056 */ 00057 virtual std::vector<std::string> allowed_signature_methods() const; 00058 00059 /** 00060 * Return list of ECC curves we are willing to use in order of preference 00061 */ 00062 virtual std::vector<std::string> allowed_ecc_curves() const; 00063 00064 /** 00065 * Returns a list of compression algorithms we are willing to use, 00066 * in order of preference. Allowed values any value of 00067 * Compression_Method. 00068 * 00069 * @note Compression is not currently supported 00070 */ 00071 virtual std::vector<byte> compression() const; 00072 00073 /** 00074 * Choose an elliptic curve to use 00075 */ 00076 virtual std::string choose_curve(const std::vector<std::string>& curve_names) const; 00077 00078 /** 00079 * Attempt to negotiate the use of the heartbeat extension 00080 */ 00081 virtual bool negotiate_heartbeat_support() const; 00082 00083 /** 00084 * Allow renegotiation even if the counterparty doesn't 00085 * support the secure renegotiation extension. 00086 * 00087 * @warning Changing this to true exposes you to injected 00088 * plaintext attacks. Read RFC 5746 for background. 00089 */ 00090 virtual bool allow_insecure_renegotiation() const; 00091 00092 /** 00093 * The protocol dictates that the first 32 bits of the random 00094 * field are the current time in seconds. However this allows 00095 * client fingerprinting attacks. Set to false to disable, in 00096 * which case random bytes will be used instead. 00097 */ 00098 virtual bool include_time_in_hello_random() const; 00099 00100 /** 00101 * Allow servers to initiate a new handshake 00102 */ 00103 virtual bool allow_server_initiated_renegotiation() const; 00104 00105 virtual std::string dh_group() const; 00106 00107 /** 00108 * Return the minimum DH group size we're willing to use 00109 */ 00110 virtual size_t minimum_dh_group_size() const; 00111 00112 /** 00113 * If this function returns false, unknown SRP/PSK identifiers 00114 * will be rejected with an unknown_psk_identifier alert as soon 00115 * as the non-existence is identified. Otherwise, a false 00116 * identifier value will be used and the protocol allowed to 00117 * proceed, causing the handshake to eventually fail without 00118 * revealing that the username does not exist on this system. 00119 */ 00120 virtual bool hide_unknown_users() const; 00121 00122 /** 00123 * Return the allowed lifetime of a session ticket. If 0, session 00124 * tickets do not expire until the session ticket key rolls over. 00125 * Expired session tickets cannot be used to resume a session. 00126 */ 00127 virtual u32bit session_ticket_lifetime() const; 00128 00129 /** 00130 * If this returns a non-empty vector, and DTLS is negotiated, 00131 * then we will also attempt to negotiate the SRTP extension from 00132 * RFC 5764 using the returned values as the profile ids. 00133 */ 00134 virtual std::vector<u16bit> srtp_profiles() const; 00135 00136 /** 00137 * @return true if and only if we are willing to accept this version 00138 * Default accepts TLS v1.0 and later or DTLS v1.2 or later. 00139 */ 00140 virtual bool acceptable_protocol_version(Protocol_Version version) const; 00141 00142 /** 00143 * Returns the more recent protocol version we are willing to 00144 * use, for either TLS or DTLS depending on datagram param. 00145 * Shouldn't ever need to override this unless you want to allow 00146 * a user to disable use of TLS v1.2 (which is *not recommended*) 00147 */ 00148 virtual Protocol_Version latest_supported_version(bool datagram) const; 00149 00150 /** 00151 * When offering this version, should we send a fallback SCSV? 00152 * Default returns true iff version is not the latest version the 00153 * policy allows, exists to allow override in case of interop problems. 00154 */ 00155 virtual bool send_fallback_scsv(Protocol_Version version) const; 00156 00157 /** 00158 * Allows policy to reject any ciphersuites which are undesirable 00159 * for whatever reason without having to reimplement ciphersuite_list 00160 */ 00161 virtual bool acceptable_ciphersuite(const Ciphersuite& suite) const; 00162 00163 /** 00164 * @return true if servers should choose the ciphersuite matching 00165 * their highest preference, rather than the clients. 00166 * Has no effect on client side. 00167 */ 00168 virtual bool server_uses_own_ciphersuite_preferences() const; 00169 00170 /** 00171 * Return allowed ciphersuites, in order of preference 00172 */ 00173 virtual std::vector<u16bit> ciphersuite_list(Protocol_Version version, 00174 bool have_srp) const; 00175 00176 virtual void print(std::ostream& o) const; 00177 00178 virtual ~Policy() {} 00179 }; 00180 00181 /** 00182 * NSA Suite B 128-bit security level (see @rfc 6460) 00183 */ 00184 class BOTAN_DLL NSA_Suite_B_128 : public Policy 00185 { 00186 public: 00187 std::vector<std::string> allowed_ciphers() const override 00188 { return std::vector<std::string>({"AES-128/GCM"}); } 00189 00190 std::vector<std::string> allowed_signature_hashes() const override 00191 { return std::vector<std::string>({"SHA-256"}); } 00192 00193 std::vector<std::string> allowed_macs() const override 00194 { return std::vector<std::string>({"AEAD"}); } 00195 00196 std::vector<std::string> allowed_key_exchange_methods() const override 00197 { return std::vector<std::string>({"ECDH"}); } 00198 00199 std::vector<std::string> allowed_signature_methods() const override 00200 { return std::vector<std::string>({"ECDSA"}); } 00201 00202 std::vector<std::string> allowed_ecc_curves() const override 00203 { return std::vector<std::string>({"secp256r1"}); } 00204 00205 bool acceptable_protocol_version(Protocol_Version version) const override 00206 { return version == Protocol_Version::TLS_V12; } 00207 }; 00208 00209 /** 00210 * Policy for DTLS. We require DTLS v1.2 and an AEAD mode 00211 */ 00212 class BOTAN_DLL Datagram_Policy : public Policy 00213 { 00214 public: 00215 std::vector<std::string> allowed_macs() const override 00216 { return std::vector<std::string>({"AEAD"}); } 00217 00218 bool acceptable_protocol_version(Protocol_Version version) const override 00219 { return version == Protocol_Version::DTLS_V12; } 00220 }; 00221 00222 /* 00223 * This policy requires a secure version of TLS and disables all insecure 00224 * algorithms. It is compatible with other botan TLSes (including those using the 00225 * default policy) and with many other recent implementations. It is a great idea 00226 * to use if you control both sides of the protocol and don't have to worry 00227 * about ancient and/or bizarre TLS implementations. 00228 */ 00229 class BOTAN_DLL Strict_Policy : public Policy 00230 { 00231 public: 00232 std::vector<std::string> allowed_ciphers() const override; 00233 00234 std::vector<std::string> allowed_signature_hashes() const override; 00235 00236 std::vector<std::string> allowed_macs() const override; 00237 00238 std::vector<std::string> allowed_key_exchange_methods() const override; 00239 00240 bool acceptable_protocol_version(Protocol_Version version) const override; 00241 }; 00242 00243 class BOTAN_DLL Text_Policy : public Policy 00244 { 00245 public: 00246 00247 std::vector<std::string> allowed_ciphers() const override 00248 { return get_list("ciphers", Policy::allowed_ciphers()); } 00249 00250 std::vector<std::string> allowed_signature_hashes() const override 00251 { return get_list("signature_hashes", Policy::allowed_signature_hashes()); } 00252 00253 std::vector<std::string> allowed_macs() const override 00254 { return get_list("macs", Policy::allowed_macs()); } 00255 00256 std::vector<std::string> allowed_key_exchange_methods() const override 00257 { return get_list("key_exchange_methods", Policy::allowed_key_exchange_methods()); } 00258 00259 std::vector<std::string> allowed_signature_methods() const override 00260 { return get_list("signature_methods", Policy::allowed_signature_methods()); } 00261 00262 std::vector<std::string> allowed_ecc_curves() const override 00263 { return get_list("ecc_curves", Policy::allowed_ecc_curves()); } 00264 00265 bool negotiate_heartbeat_support() const override 00266 { return get_bool("negotiate_heartbeat_support", Policy::negotiate_heartbeat_support()); } 00267 00268 bool allow_insecure_renegotiation() const override 00269 { return get_bool("allow_insecure_renegotiation", Policy::allow_insecure_renegotiation()); } 00270 00271 bool include_time_in_hello_random() const override 00272 { return get_bool("include_time_in_hello_random", Policy::include_time_in_hello_random()); } 00273 00274 bool allow_server_initiated_renegotiation() const override 00275 { return get_bool("allow_server_initiated_renegotiation", Policy::allow_server_initiated_renegotiation()); } 00276 00277 bool server_uses_own_ciphersuite_preferences() const override 00278 { return get_bool("server_uses_own_ciphersuite_preferences", Policy::server_uses_own_ciphersuite_preferences()); } 00279 00280 std::string dh_group() const override 00281 { return get_str("dh_group", Policy::dh_group()); } 00282 00283 size_t minimum_dh_group_size() const override 00284 { return get_len("minimum_dh_group_size", Policy::minimum_dh_group_size()); } 00285 00286 bool hide_unknown_users() const override 00287 { return get_bool("hide_unknown_users", Policy::hide_unknown_users()); } 00288 00289 u32bit session_ticket_lifetime() const override 00290 { return get_len("session_ticket_lifetime", Policy::session_ticket_lifetime()); } 00291 00292 std::vector<u16bit> srtp_profiles() const override 00293 { 00294 std::vector<u16bit> r; 00295 for(auto&& p : get_list("srtp_profiles", std::vector<std::string>())) 00296 { 00297 r.push_back(to_u32bit(p)); 00298 } 00299 return r; 00300 } 00301 00302 Text_Policy(std::istream& in) 00303 { 00304 m_kv = read_cfg(in); 00305 } 00306 00307 private: 00308 00309 std::vector<std::string> get_list(const std::string& key, 00310 const std::vector<std::string>& def) const 00311 { 00312 const std::string v = get_str(key); 00313 00314 if(v == "") 00315 return def; 00316 00317 return split_on(v, ' '); 00318 } 00319 00320 size_t get_len(const std::string& key, size_t def) const 00321 { 00322 const std::string v = get_str(key); 00323 00324 if(v == "") 00325 return def; 00326 00327 return to_u32bit(v); 00328 } 00329 00330 bool get_bool(const std::string& key, bool def) const 00331 { 00332 const std::string v = get_str(key); 00333 00334 if(v == "") 00335 return def; 00336 00337 if(v == "true" || v == "True") 00338 return true; 00339 else if(v == "false" || v == "False") 00340 return false; 00341 else 00342 throw std::runtime_error("Invalid boolean '" + v + "'"); 00343 } 00344 00345 std::string get_str(const std::string& key, const std::string& def = "") const 00346 { 00347 auto i = m_kv.find(key); 00348 if(i == m_kv.end()) 00349 return def; 00350 00351 return i->second; 00352 } 00353 00354 std::map<std::string, std::string> m_kv; 00355 }; 00356 00357 } 00358 00359 } 00360 00361 #endif