1 /** 2 * Hooks for application level policies on TLS connections 3 * 4 * Copyright: 5 * (C) 2004-2006,2013 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.tls.policy; 12 13 import botan.constants; 14 static if (BOTAN_HAS_TLS): 15 16 import botan.tls.version_; 17 import botan.tls.ciphersuite; 18 import botan.cert.x509.x509cert; 19 import botan.pubkey.algo.dl_group; 20 import botan.tls.ciphersuite; 21 import botan.tls.magic; 22 import botan.tls.exceptn; 23 import memutils.dictionarylist; 24 import std.datetime; 25 import std.algorithm : uniq, sort; 26 import std.array : array, Appender; 27 import std.conv : to; 28 import botan.utils.types; 29 public import botan.tls.extensions; 30 31 /** 32 * TLSPolicy Base Class 33 * Inherit and overload as desired to suit local policy concerns 34 */ 35 class TLSPolicy 36 { 37 public: 38 Vector!HandshakeExtensionType enabledExtensions() const { 39 return Vector!HandshakeExtensionType([TLSEXT_SAFE_RENEGOTIATION, 40 TLSEXT_SERVER_NAME_INDICATION, 41 TLSEXT_EC_POINT_FORMATS, 42 TLSEXT_USABLE_ELLIPTIC_CURVES, 43 TLSEXT_EXTENDED_MASTER_SECRET, 44 TLSEXT_SESSION_TICKET, 45 TLSEXT_SIGNATURE_ALGORITHMS, 46 //TLSEXT_STATUS_REQUEST, 47 //TLSEXT_NPN, 48 //TLSEXT_SIGNED_CERT_TIMESTAMP, 49 TLSEXT_ALPN, 50 TLSEXT_CHANNEL_ID, 51 TLSEXT_SRP_IDENTIFIER, 52 TLSEXT_HEARTBEAT_SUPPORT, 53 TLSEXT_MAX_FRAGMENT_LENGTH]); 54 } 55 56 /** 57 * Returns a list of ciphers we are willing to negotiate, in 58 * order of preference. 59 */ 60 Vector!string allowedCiphers() const 61 { 62 return Vector!string([ 63 "AES-128/GCM", 64 "AES-256/GCM", 65 "ChaCha20Poly1305", 66 "AES-256/CCM", 67 "AES-128/CCM", 68 "AES-256/CCM-8", 69 "AES-128/CCM-8", 70 "Camellia-256/GCM", 71 "Camellia-128/GCM", 72 "AES-256", 73 "AES-128", 74 "Camellia-256", 75 "Camellia-128", 76 "SEED", 77 "3DES", 78 "RC4", 79 ]); 80 } 81 82 /** 83 * Returns a list of hash algorithms we are willing to use for 84 * signatures, in order of preference. 85 */ 86 Vector!string allowedSignatureHashes() const 87 { 88 return Vector!string([ 89 "SHA-256", 90 "SHA-512", 91 "SHA-384", 92 "SHA-224", 93 "SHA-1", 94 "MD5", 95 ]); 96 } 97 98 99 /** 100 * Returns a list of MAC algorithms we are willing to use. 101 */ 102 Vector!string allowedMacs() const 103 { 104 return Vector!string([ 105 "AEAD", 106 "SHA-384", 107 "SHA-256", 108 "SHA-1", 109 "MD5", 110 ]); 111 } 112 113 /** 114 * Returns a list of key exchange algorithms we are willing to 115 * use, in order of preference. Allowed values: DH, empty string 116 * (representing RSA using server certificate key) 117 */ 118 Vector!string allowedKeyExchangeMethods() const 119 { 120 return Vector!string([ 121 //"SRP_SHA", 122 //"ECDHE_PSK", 123 //"DHE_PSK", 124 //"PSK", 125 "RSA", 126 "ECDH", 127 "DH", 128 ]); 129 } 130 131 /** 132 * Returns a list of signature algorithms we are willing to 133 * use, in order of preference. Allowed values RSA and DSA. 134 */ 135 Vector!string allowedSignatureMethods() const 136 { 137 return Vector!string([ 138 "RSA", 139 "ECDSA", 140 "DSA", 141 //"" 142 ]); 143 } 144 145 /** 146 * Return list of ECC curves we are willing to use in order of preference 147 */ 148 Vector!string allowedEccCurves() const 149 { 150 return Vector!string([ 151 "x25519", 152 "brainpool512r1", 153 "brainpool384r1", 154 "brainpool256r1", 155 "secp521r1", 156 "secp384r1", 157 "secp256r1", 158 "secp256k1", 159 "secp224r1", 160 "secp224k1", 161 "secp192r1", 162 "secp192k1", 163 "secp160r2", 164 "secp160r1", 165 "secp160k1", 166 ]); 167 } 168 169 /** 170 * Returns a list of compression algorithms we are willing to use, 171 * in order of preference. Allowed values any value of 172 * Compression_Method. 173 * 174 * @note Compression is not currently supported 175 */ 176 Vector!ubyte compression() const 177 { 178 return Vector!ubyte([NO_COMPRESSION]); 179 } 180 181 182 /** 183 * Choose an elliptic curve to use 184 */ 185 string chooseCurve(in Vector!string curve_names) const 186 { 187 const Vector!string our_curves = allowedEccCurves(); 188 for (size_t i = 0; i != our_curves.length; ++i) 189 if (valueExists(curve_names, our_curves[i])) 190 return our_curves[i]; 191 192 return ""; // no shared curve 193 } 194 195 /** 196 * Attempt to negotiate the use of the heartbeat extension 197 */ 198 bool negotiateHeartbeatSupport() const 199 { 200 return false; 201 } 202 203 /** 204 * Allow renegotiation even if the counterparty doesn't 205 * support the secure renegotiation extension. 206 * 207 * Notes: 208 * Changing this to true exposes you to injected plaintext attacks. 209 * Read RFC 5746 for background. 210 */ 211 bool allowInsecureRenegotiation() const { return false; } 212 213 /** 214 * The protocol dictates that the first 32 bits of the random 215 * field are the current time in seconds. However this allows 216 * client fingerprinting attacks. Set to false to disable, in 217 * which case random bytes will be used instead. 218 */ 219 bool includeTimeInHelloRandom() const { return false; } 220 221 /** 222 * Allow servers to initiate a new handshake 223 */ 224 bool allowServerInitiatedRenegotiation() const 225 { 226 return true; 227 } 228 229 /** 230 * Return the group to use for ephemeral Diffie-Hellman key agreement 231 */ 232 DLGroup dhGroup() const 233 { 234 return DLGroup("modp/ietf/2048"); 235 } 236 237 /** 238 * Return the minimum DH group size we're willing to use 239 */ 240 size_t minimumDhGroupSize() const 241 { 242 return 1024; 243 } 244 245 /** 246 * If this function returns false, unknown SRP/PSK identifiers 247 * will be rejected with an unknown_psk_identifier alert as soon 248 * as the non-existence is identified. Otherwise, a false 249 * identifier value will be used and the protocol allowed to 250 * proceed, causing the handshake to eventually fail without 251 * revealing that the username does not exist on this system. 252 */ 253 bool hideUnknownUsers() const { return false; } 254 255 /** 256 * Return the allowed lifetime of a session ticket. If 0, session 257 * tickets do not expire until the session ticket key rolls over. 258 * Expired session tickets cannot be used to resume a session. 259 */ 260 Duration sessionTicketLifetime() const 261 { 262 return 24.hours; // 1 day 263 } 264 265 /** 266 * Returns: true if and only if we are willing to accept this version 267 * Default accepts only TLS, so if you want to enable DTLS override 268 * in your application. 269 */ 270 bool acceptableProtocolVersion(TLSProtocolVersion _version) const 271 { 272 if (_version.isDatagramProtocol()) 273 return (_version >= TLSProtocolVersion.DTLS_V12); 274 275 return (_version >= TLSProtocolVersion.TLS_V10); 276 } 277 /** 278 * Returns the more recent protocol version we are willing to 279 * use, for either TLS or DTLS depending on datagram param. 280 * Shouldn't ever need to override this unless you want to allow 281 * a user to disable use of TLS v1.2 (which is *not recommended*) 282 */ 283 TLSProtocolVersion latestSupportedVersion(bool datagram) const 284 { 285 if (datagram) 286 return TLSProtocolVersion.latestDtlsVersion(); 287 else 288 return TLSProtocolVersion.latestTlsVersion(); 289 } 290 291 /** 292 * When offering this version, should we send a fallback SCSV? 293 * Default returns true iff version is the latest version the 294 * policy allows, exists to allow override in case of interop problems. 295 */ 296 bool sendFallbackSCSV(in TLSProtocolVersion _version) const 297 { 298 return _version == latestSupportedVersion(_version.isDatagramProtocol()); 299 } 300 301 /** 302 * Allows policy to reject any ciphersuites which are undesirable 303 * for whatever reason without having to reimplement ciphersuite_list 304 */ 305 bool acceptableCiphersuite(in TLSCiphersuite) const 306 { 307 return true; 308 } 309 310 /** 311 * Returns: true if servers should choose the ciphersuite matching 312 * their highest preference, rather than the clients. 313 * Has no effect on client side. 314 */ 315 bool serverUsesOwnCiphersuitePreferences() const { return true; } 316 317 /** 318 * Return allowed ciphersuites, in order of preference 319 */ 320 Vector!ushort ciphersuiteList(TLSProtocolVersion _version, bool have_srp) const 321 { 322 Vector!string ciphers = allowedCiphers(); 323 Vector!string macs = allowedMacs(); 324 Vector!string kex = allowedKeyExchangeMethods(); 325 Vector!string sigs = allowedSignatureMethods(); 326 327 CiphersuitePreferenceOrdering order = CiphersuitePreferenceOrdering(ciphers, macs, kex, sigs); 328 329 Vector!(TLSCiphersuite) ciphersuites; 330 ciphersuites.reserve(64); 331 auto cipher_suites = TLSCiphersuite.allKnownCiphersuites(); 332 foreach (const ref TLSCiphersuite suite; cipher_suites) 333 { 334 if (!acceptableCiphersuite(suite)) 335 continue; 336 337 if (!have_srp && suite.kexAlgo() == "SRP_SHA") 338 continue; 339 340 if (_version.isDatagramProtocol() && suite.cipherAlgo() == "RC4") 341 continue; 342 343 if (!_version.supportsAeadModes() && suite.macAlgo() == "AEAD") 344 continue; 345 346 if (!valueExists(kex, suite.kexAlgo())) 347 continue; // unsupported key exchange 348 349 if (!valueExists(ciphers, suite.cipherAlgo())) 350 continue; // unsupported cipher 351 352 if (!valueExists(macs, suite.macAlgo())) 353 continue; // unsupported MAC algo 354 355 if (!valueExists(sigs, suite.sigAlgo())) 356 { 357 // allow if it's an empty sig algo and we want to use PSK 358 if (suite.sigAlgo() != "" || !suite.pskCiphersuite()) 359 continue; 360 } 361 362 // OK, allow it: 363 ciphersuites ~= suite; 364 } 365 366 if (ciphersuites.length == 0) 367 throw new LogicError("TLSPolicy does not allow any available cipher suite"); 368 Vector!ushort ciphersuite_codes; 369 auto ciphersuites_ordered = ciphersuites[].uniq.array.sort!((a,b){ return order.compare(a, b); }).array.to!(TLSCiphersuite[]); 370 foreach (TLSCiphersuite i; ciphersuites_ordered) 371 ciphersuite_codes.pushBack(i.ciphersuiteCode()); 372 return ciphersuite_codes; 373 } 374 375 ~this() {} 376 } 377 378 /** 379 * NSA Suite B 128-bit security level (see @rfc 6460) 380 */ 381 class NSASuiteB128 : TLSPolicy 382 { 383 public: 384 override Vector!string allowedCiphers() const 385 { return Vector!string(["AES-128/GCM"]); } 386 387 override Vector!string allowedSignatureHashes() const 388 { return Vector!string(["SHA-256"]); } 389 390 override Vector!string allowedMacs() const 391 { return Vector!string(["AEAD"]); } 392 393 override Vector!string allowedKeyExchangeMethods() const 394 { return Vector!string(["ECDH"]); } 395 396 override Vector!string allowedSignatureMethods() const 397 { return Vector!string(["ECDSA"]); } 398 399 override Vector!string allowedEccCurves() const 400 { return Vector!string(["secp256r1"]); } 401 402 override bool acceptableProtocolVersion(TLSProtocolVersion _version) const 403 { return _version == TLSProtocolVersion.TLS_V12; } 404 } 405 406 /** 407 * TLSPolicy for DTLS. We require DTLS v1.2 and an AEAD mode 408 */ 409 class DatagramPolicy : TLSPolicy 410 { 411 public: 412 override Vector!string allowedMacs() const 413 { return Vector!string(["AEAD"]); } 414 415 override bool acceptableProtocolVersion(TLSProtocolVersion _version) const 416 { return _version == TLSProtocolVersion.DTLS_V12; } 417 } 418 419 420 private: 421 422 struct CiphersuitePreferenceOrdering 423 { 424 public: 425 this(ref Vector!string ciphers, ref Vector!string macs, ref Vector!string kex, ref Vector!string sigs) 426 { 427 m_ciphers = ciphers.dup(); 428 m_macs = macs.dup(); 429 m_kex = kex.dup(); 430 m_sigs = sigs.dup(); 431 } 432 433 bool compare(U : TLSCiphersuite)(in TLSCiphersuite a, auto ref U b) const 434 { 435 if (a.kexAlgo() != b.kexAlgo()) 436 { 437 for (size_t i = 0; i != m_kex.length; ++i) 438 { 439 if (a.kexAlgo() == m_kex[i]) 440 return true; 441 if (b.kexAlgo() == m_kex[i]) 442 return false; 443 } 444 } 445 446 if (a.cipherAlgo() != b.cipherAlgo()) 447 { 448 for (size_t i = 0; i != m_ciphers.length; ++i) 449 { 450 if (a.cipherAlgo() == m_ciphers[i]) 451 return true; 452 if (b.cipherAlgo() == m_ciphers[i]) 453 return false; 454 } 455 } 456 457 if (a.cipherKeylen() != b.cipherKeylen()) 458 { 459 if (a.cipherKeylen() < b.cipherKeylen()) 460 return false; 461 if (a.cipherKeylen() > b.cipherKeylen()) 462 return true; 463 } 464 465 if (a.sigAlgo() != b.sigAlgo()) 466 { 467 for (size_t i = 0; i != m_sigs.length; ++i) 468 { 469 if (a.sigAlgo() == m_sigs[i]) 470 return true; 471 if (b.sigAlgo() == m_sigs[i]) 472 return false; 473 } 474 } 475 476 if (a.macAlgo() != b.macAlgo()) 477 { 478 for (size_t i = 0; i != m_macs.length; ++i) 479 { 480 if (a.macAlgo() == m_macs[i]) 481 return true; 482 if (b.macAlgo() == m_macs[i]) 483 return false; 484 } 485 } 486 487 return false; // equal (?!?) 488 } 489 private: 490 Vector!string m_ciphers, m_macs, m_kex, m_sigs; 491 }