1# Authors: 2# Trevor Perrin 3# Dave Baggett (Arcode Corporation) - cleanup handling of constants 4# 5# See the LICENSE file for legal information regarding use of this file. 6 7"""Class for setting handshake parameters.""" 8 9from .constants import CertificateType 10from .utils import cryptomath 11from .utils import cipherfactory 12 13# RC4 is preferred as faster in Python, works in SSL3, and immune to CBC 14# issues such as timing attacks 15CIPHER_NAMES = ["rc4", "aes256", "aes128", "3des"] 16MAC_NAMES = ["sha"] # Don't allow "md5" by default. 17ALL_MAC_NAMES = ["sha", "md5"] 18KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"] 19CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"] 20CERTIFICATE_TYPES = ["x509"] 21TLS_INTOLERANCE_TYPES = ["alert", "close", "reset"] 22 23class HandshakeSettings(object): 24 """This class encapsulates various parameters that can be used with 25 a TLS handshake. 26 @sort: minKeySize, maxKeySize, cipherNames, macNames, certificateTypes, 27 minVersion, maxVersion 28 29 @type minKeySize: int 30 @ivar minKeySize: The minimum bit length for asymmetric keys. 31 32 If the other party tries to use SRP, RSA, or Diffie-Hellman 33 parameters smaller than this length, an alert will be 34 signalled. The default is 1023. 35 36 @type maxKeySize: int 37 @ivar maxKeySize: The maximum bit length for asymmetric keys. 38 39 If the other party tries to use SRP, RSA, or Diffie-Hellman 40 parameters larger than this length, an alert will be signalled. 41 The default is 8193. 42 43 @type cipherNames: list 44 @ivar cipherNames: The allowed ciphers, in order of preference. 45 46 The allowed values in this list are 'aes256', 'aes128', '3des', and 47 'rc4'. If these settings are used with a client handshake, they 48 determine the order of the ciphersuites offered in the ClientHello 49 message. 50 51 If these settings are used with a server handshake, the server will 52 choose whichever ciphersuite matches the earliest entry in this 53 list. 54 55 NOTE: If '3des' is used in this list, but TLS Lite can't find an 56 add-on library that supports 3DES, then '3des' will be silently 57 removed. 58 59 The default value is ['rc4', 'aes256', 'aes128', '3des']. 60 61 @type macNames: list 62 @ivar macNames: The allowed MAC algorithms. 63 64 The allowed values in this list are 'sha' and 'md5'. 65 66 The default value is ['sha']. 67 68 69 @type certificateTypes: list 70 @ivar certificateTypes: The allowed certificate types, in order of 71 preference. 72 73 The only allowed certificate type is 'x509'. This list is only used with a 74 client handshake. The client will advertise to the server which certificate 75 types are supported, and will check that the server uses one of the 76 appropriate types. 77 78 79 @type minVersion: tuple 80 @ivar minVersion: The minimum allowed SSL/TLS version. 81 82 This variable can be set to (3,0) for SSL 3.0, (3,1) for 83 TLS 1.0, or (3,2) for TLS 1.1. If the other party wishes to 84 use a lower version, a protocol_version alert will be signalled. 85 The default is (3,0). 86 87 @type maxVersion: tuple 88 @ivar maxVersion: The maximum allowed SSL/TLS version. 89 90 This variable can be set to (3,0) for SSL 3.0, (3,1) for 91 TLS 1.0, or (3,2) for TLS 1.1. If the other party wishes to 92 use a higher version, a protocol_version alert will be signalled. 93 The default is (3,2). (WARNING: Some servers may (improperly) 94 reject clients which offer support for TLS 1.1. In this case, 95 try lowering maxVersion to (3,1)). 96 97 @type tlsIntolerant: tuple 98 @ivar tlsIntolerant: The TLS ClientHello version which the server 99 simulates intolerance of. 100 101 If tlsIntolerant is not None, the server will simulate TLS version 102 intolerance by aborting the handshake in response to all TLS versions 103 tlsIntolerant or higher. 104 105 @type tlsIntoleranceType: str 106 @ivar tlsIntoleranceType: How the server should react when simulating TLS 107 intolerance. 108 109 The allowed values are "alert" (return a fatal handshake_failure alert), 110 "close" (abruptly close the connection), and "reset" (send a TCP reset). 111 112 @type useExperimentalTackExtension: bool 113 @ivar useExperimentalTackExtension: Whether to enabled TACK support. 114 115 Note that TACK support is not standardized by IETF and uses a temporary 116 TLS Extension number, so should NOT be used in production software. 117 """ 118 def __init__(self): 119 self.minKeySize = 1023 120 self.maxKeySize = 8193 121 self.cipherNames = CIPHER_NAMES 122 self.macNames = MAC_NAMES 123 self.keyExchangeNames = KEY_EXCHANGE_NAMES 124 self.cipherImplementations = CIPHER_IMPLEMENTATIONS 125 self.certificateTypes = CERTIFICATE_TYPES 126 self.minVersion = (3,0) 127 self.maxVersion = (3,2) 128 self.tlsIntolerant = None 129 self.tlsIntoleranceType = 'alert' 130 self.useExperimentalTackExtension = False 131 132 # Validates the min/max fields, and certificateTypes 133 # Filters out unsupported cipherNames and cipherImplementations 134 def _filter(self): 135 other = HandshakeSettings() 136 other.minKeySize = self.minKeySize 137 other.maxKeySize = self.maxKeySize 138 other.cipherNames = self.cipherNames 139 other.macNames = self.macNames 140 other.keyExchangeNames = self.keyExchangeNames 141 other.cipherImplementations = self.cipherImplementations 142 other.certificateTypes = self.certificateTypes 143 other.minVersion = self.minVersion 144 other.maxVersion = self.maxVersion 145 other.tlsIntolerant = self.tlsIntolerant 146 other.tlsIntoleranceType = self.tlsIntoleranceType 147 148 if not cipherfactory.tripleDESPresent: 149 other.cipherNames = [e for e in self.cipherNames if e != "3des"] 150 if len(other.cipherNames)==0: 151 raise ValueError("No supported ciphers") 152 if len(other.certificateTypes)==0: 153 raise ValueError("No supported certificate types") 154 155 if not cryptomath.m2cryptoLoaded: 156 other.cipherImplementations = \ 157 [e for e in other.cipherImplementations if e != "openssl"] 158 if not cryptomath.pycryptoLoaded: 159 other.cipherImplementations = \ 160 [e for e in other.cipherImplementations if e != "pycrypto"] 161 if len(other.cipherImplementations)==0: 162 raise ValueError("No supported cipher implementations") 163 164 if other.minKeySize<512: 165 raise ValueError("minKeySize too small") 166 if other.minKeySize>16384: 167 raise ValueError("minKeySize too large") 168 if other.maxKeySize<512: 169 raise ValueError("maxKeySize too small") 170 if other.maxKeySize>16384: 171 raise ValueError("maxKeySize too large") 172 for s in other.cipherNames: 173 if s not in CIPHER_NAMES: 174 raise ValueError("Unknown cipher name: '%s'" % s) 175 for s in other.macNames: 176 if s not in ALL_MAC_NAMES: 177 raise ValueError("Unknown MAC name: '%s'" % s) 178 for s in other.keyExchangeNames: 179 if s not in KEY_EXCHANGE_NAMES: 180 raise ValueError("Unknown key exchange name: '%s'" % s) 181 for s in other.cipherImplementations: 182 if s not in CIPHER_IMPLEMENTATIONS: 183 raise ValueError("Unknown cipher implementation: '%s'" % s) 184 for s in other.certificateTypes: 185 if s not in CERTIFICATE_TYPES: 186 raise ValueError("Unknown certificate type: '%s'" % s) 187 188 if other.tlsIntoleranceType not in TLS_INTOLERANCE_TYPES: 189 raise ValueError( 190 "Unknown TLS intolerance type: '%s'" % other.tlsIntoleranceType) 191 192 if other.minVersion > other.maxVersion: 193 raise ValueError("Versions set incorrectly") 194 195 if not other.minVersion in ((3,0), (3,1), (3,2)): 196 raise ValueError("minVersion set incorrectly") 197 198 if not other.maxVersion in ((3,0), (3,1), (3,2)): 199 raise ValueError("maxVersion set incorrectly") 200 201 return other 202 203 def _getCertificateTypes(self): 204 l = [] 205 for ct in self.certificateTypes: 206 if ct == "x509": 207 l.append(CertificateType.x509) 208 else: 209 raise AssertionError() 210 return l 211