1
2
3
4
5
6
7
8 """Class for setting handshake parameters."""
9
10 from .constants import CertificateType
11 from .utils import cryptomath
12 from .utils import cipherfactory
13 from .utils.compat import ecdsaAllCurves, int_types
14
15 CIPHER_NAMES = ["chacha20-poly1305",
16 "aes256gcm", "aes128gcm",
17 "aes256", "aes128",
18 "3des"]
19 ALL_CIPHER_NAMES = CIPHER_NAMES + ["chacha20-poly1305_draft00",
20 "rc4", "null"]
21 MAC_NAMES = ["sha", "sha256", "sha384", "aead"]
22 ALL_MAC_NAMES = MAC_NAMES + ["md5"]
23 KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "ecdhe_rsa", "srp_sha", "srp_sha_rsa",
24 "ecdh_anon", "dh_anon"]
25 CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
26 CERTIFICATE_TYPES = ["x509"]
27 RSA_SIGNATURE_HASHES = ["sha512", "sha384", "sha256", "sha224", "sha1"]
28 ALL_RSA_SIGNATURE_HASHES = RSA_SIGNATURE_HASHES + ["md5"]
29 RSA_SCHEMES = ["pss", "pkcs1"]
30
31
32 CURVE_NAMES = ["secp384r1", "secp256r1", "secp521r1"]
33 ALL_CURVE_NAMES = CURVE_NAMES + ["secp256k1"]
34 if ecdsaAllCurves:
35 ALL_CURVE_NAMES += ["secp224r1", "secp192r1"]
36 ALL_DH_GROUP_NAMES = ["ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144",
37 "ffdhe8192"]
40 """This class encapsulates various parameters that can be used with
41 a TLS handshake.
42 @sort: minKeySize, maxKeySize, cipherNames, macNames, certificateTypes,
43 minVersion, maxVersion
44
45 @type minKeySize: int
46 @ivar minKeySize: The minimum bit length for asymmetric keys.
47
48 If the other party tries to use SRP, RSA, or Diffie-Hellman
49 parameters smaller than this length, an alert will be
50 signalled. The default is 1023.
51
52 @type maxKeySize: int
53 @ivar maxKeySize: The maximum bit length for asymmetric keys.
54
55 If the other party tries to use SRP, RSA, or Diffie-Hellman
56 parameters larger than this length, an alert will be signalled.
57 The default is 8193.
58
59 @type cipherNames: list
60 @ivar cipherNames: The allowed ciphers.
61
62 The allowed values in this list are 'aes256', 'aes128', '3des', and
63 'rc4'. If these settings are used with a client handshake, they
64 determine the order of the ciphersuites offered in the ClientHello
65 message.
66
67 If these settings are used with a server handshake, the server will
68 choose whichever ciphersuite matches the earliest entry in this
69 list.
70
71 NOTE: If '3des' is used in this list, but TLS Lite can't find an
72 add-on library that supports 3DES, then '3des' will be silently
73 removed.
74
75 The default value is ['rc4', 'aes256', 'aes128', '3des'].
76
77 @type macNames: list
78 @ivar macNames: The allowed MAC algorithms.
79
80 The allowed values in this list are 'sha' and 'md5'.
81
82 The default value is ['sha'].
83
84
85 @type certificateTypes: list
86 @ivar certificateTypes: The allowed certificate types.
87
88 The only allowed certificate type is 'x509'. This list is only used with a
89 client handshake. The client will advertise to the server which certificate
90 types are supported, and will check that the server uses one of the
91 appropriate types.
92
93
94 @type minVersion: tuple
95 @ivar minVersion: The minimum allowed SSL/TLS version.
96
97 This variable can be set to (3,0) for SSL 3.0, (3,1) for TLS 1.0, (3,2) for
98 TLS 1.1, or (3,3) for TLS 1.2. If the other party wishes to use a lower
99 version, a protocol_version alert will be signalled. The default is (3,1).
100
101 @type maxVersion: tuple
102 @ivar maxVersion: The maximum allowed SSL/TLS version.
103
104 This variable can be set to (3,0) for SSL 3.0, (3,1) for TLS 1.0, (3,2) for
105 TLS 1.1, or (3,3) for TLS 1.2. If the other party wishes to use a higher
106 version, a protocol_version alert will be signalled. The default is (3,3).
107 (WARNING: Some servers may (improperly) reject clients which offer support
108 for TLS 1.1. In this case, try lowering maxVersion to (3,1)).
109
110 @type useExperimentalTackExtension: bool
111 @ivar useExperimentalTackExtension: Whether to enabled TACK support.
112
113 Note that TACK support is not standardized by IETF and uses a temporary
114 TLS Extension number, so should NOT be used in production software.
115
116 @type sendFallbackSCSV: bool
117 @ivar sendFallbackSCSV: Whether to, as a client, send FALLBACK_SCSV.
118
119 @type rsaSigHashes: list
120 @ivar rsaSigHashes: List of hashes supported (and advertised as such) for
121 TLS 1.2 signatures over Server Key Exchange or Certificate Verify with
122 RSA signature algorithm.
123
124 The list is sorted from most wanted to least wanted algorithm.
125
126 The allowed hashes are: "md5", "sha1", "sha224", "sha256",
127 "sha384" and "sha512". The default list does not include md5.
128
129 @type eccCurves: list
130 @ivar eccCurves: List of named curves that are to be supported
131
132 @type useEncryptThenMAC: bool
133 @ivar useEncryptThenMAC: whether to support the encrypt then MAC extension
134 from RFC 7366. True by default.
135
136 @type useExtendedMasterSecret: bool
137 @ivar useExtendedMasterSecret: whether to support the extended master
138 secret calculation from RFC 7627. True by default.
139
140 @type requireExtendedMasterSecret: bool
141 @ivar requireExtendedMasterSecret: whether to require negotiation of
142 extended master secret calculation for successful connection. Requires
143 useExtendedMasterSecret to be set to true. False by default.
144
145 @type defaultCurve: str
146 @ivar defaultCurve: curve that will be used by server in case the client
147 did not advertise support for any curves. It does not have to be the
148 first curve for eccCurves and may be distinct from curves from that list.
149 """
151 self.minKeySize = 1023
152 self.maxKeySize = 8193
153 self.cipherNames = list(CIPHER_NAMES)
154 self.macNames = list(MAC_NAMES)
155 self.keyExchangeNames = list(KEY_EXCHANGE_NAMES)
156 self.cipherImplementations = list(CIPHER_IMPLEMENTATIONS)
157 self.certificateTypes = list(CERTIFICATE_TYPES)
158 self.minVersion = (3, 1)
159 self.maxVersion = (3, 3)
160 self.useExperimentalTackExtension = False
161 self.sendFallbackSCSV = False
162 self.useEncryptThenMAC = True
163 self.rsaSigHashes = list(RSA_SIGNATURE_HASHES)
164 self.rsaSchemes = list(RSA_SCHEMES)
165 self.eccCurves = list(CURVE_NAMES)
166 self.usePaddingExtension = True
167 self.useExtendedMasterSecret = True
168 self.requireExtendedMasterSecret = False
169 self.dhParams = None
170 self.dhGroups = list(ALL_DH_GROUP_NAMES)
171 self.defaultCurve = "secp256r1"
172
173 @staticmethod
175 """Check if key size limits are sane"""
176 if other.minKeySize < 512:
177 raise ValueError("minKeySize too small")
178 if other.minKeySize > 16384:
179 raise ValueError("minKeySize too large")
180 if other.maxKeySize < 512:
181 raise ValueError("maxKeySize too small")
182 if other.maxKeySize > 16384:
183 raise ValueError("maxKeySize too large")
184 if other.maxKeySize < other.minKeySize:
185 raise ValueError("maxKeySize smaller than minKeySize")
186
187 @staticmethod
189 """Check if specified cryptographic primitive names are known"""
190 unknownCiphers = [val for val in other.cipherNames \
191 if val not in ALL_CIPHER_NAMES]
192 if unknownCiphers:
193 raise ValueError("Unknown cipher name: %s" % unknownCiphers)
194
195 unknownMacs = [val for val in other.macNames \
196 if val not in ALL_MAC_NAMES]
197 if unknownMacs:
198 raise ValueError("Unknown MAC name: %s" % unknownMacs)
199
200 unknownKex = [val for val in other.keyExchangeNames \
201 if val not in KEY_EXCHANGE_NAMES]
202 if unknownKex:
203 raise ValueError("Unknown key exchange name: %s" % unknownKex)
204
205 unknownImpl = [val for val in other.cipherImplementations \
206 if val not in CIPHER_IMPLEMENTATIONS]
207 if unknownImpl:
208 raise ValueError("Unknown cipher implementation: %s" % \
209 unknownImpl)
210
211 unknownType = [val for val in other.certificateTypes \
212 if val not in CERTIFICATE_TYPES]
213 if unknownType:
214 raise ValueError("Unknown certificate type: %s" % unknownType)
215
216 unknownCurve = [val for val in other.eccCurves \
217 if val not in ALL_CURVE_NAMES]
218 if unknownCurve:
219 raise ValueError("Unknown ECC Curve name: {0}".format(unknownCurve))
220
221 if other.defaultCurve not in ALL_CURVE_NAMES:
222 raise ValueError("Unknown default ECC Curve name: {0}"
223 .format(other.defaultCurve))
224
225 unknownSigHash = [val for val in other.rsaSigHashes \
226 if val not in ALL_RSA_SIGNATURE_HASHES]
227 if unknownSigHash:
228 raise ValueError("Unknown RSA signature hash: '{0}'".\
229 format(unknownSigHash))
230
231 unknownRSAPad = [val for val in other.rsaSchemes
232 if val not in RSA_SCHEMES]
233 if unknownRSAPad:
234 raise ValueError("Unknown RSA padding mode: '{0}'".\
235 format(unknownRSAPad))
236
237 unknownDHGroup = [val for val in other.dhGroups
238 if val not in ALL_DH_GROUP_NAMES]
239 if unknownDHGroup:
240 raise ValueError("Unknown FFDHE group name: '{0}'"
241 .format(unknownDHGroup))
242
243 @staticmethod
245 """Check if set protocol version are sane"""
246 if other.minVersion > other.maxVersion:
247 raise ValueError("Versions set incorrectly")
248 if other.minVersion not in ((3, 0), (3, 1), (3, 2), (3, 3)):
249 raise ValueError("minVersion set incorrectly")
250 if other.maxVersion not in ((3, 0), (3, 1), (3, 2), (3, 3)):
251 raise ValueError("maxVersion set incorrectly")
252
253 @staticmethod
255 """Check if set extension settings are sane"""
256 if other.useEncryptThenMAC not in (True, False):
257 raise ValueError("useEncryptThenMAC can only be True or False")
258
259 if other.useExtendedMasterSecret not in (True, False):
260 raise ValueError("useExtendedMasterSecret must be True or False")
261 if other.requireExtendedMasterSecret not in (True, False):
262 raise ValueError("requireExtendedMasterSecret must be True "
263 "or False")
264 if other.requireExtendedMasterSecret and \
265 not other.useExtendedMasterSecret:
266 raise ValueError("requireExtendedMasterSecret requires "
267 "useExtendedMasterSecret")
268
269 if other.usePaddingExtension not in (True, False):
270 raise ValueError("usePaddingExtension must be True or False")
271
273 """
274 Validate the settings, filter out unsupported ciphersuites and return
275 a copy of object. Does not modify the original object.
276
277 @rtype: HandshakeSettings
278 @return: a self-consistent copy of settings
279 @raise ValueError: when settings are invalid, insecure or unsupported.
280 """
281 other = HandshakeSettings()
282 other.minKeySize = self.minKeySize
283 other.maxKeySize = self.maxKeySize
284 other.cipherNames = self.cipherNames
285 other.macNames = self.macNames
286 other.keyExchangeNames = self.keyExchangeNames
287 other.cipherImplementations = self.cipherImplementations
288 other.certificateTypes = self.certificateTypes
289 other.minVersion = self.minVersion
290 other.maxVersion = self.maxVersion
291 other.sendFallbackSCSV = self.sendFallbackSCSV
292 other.useEncryptThenMAC = self.useEncryptThenMAC
293 other.usePaddingExtension = self.usePaddingExtension
294 other.rsaSigHashes = self.rsaSigHashes
295 other.rsaSchemes = self.rsaSchemes
296 other.eccCurves = self.eccCurves
297 other.useExtendedMasterSecret = self.useExtendedMasterSecret
298 other.requireExtendedMasterSecret = self.requireExtendedMasterSecret
299 other.dhParams = self.dhParams
300 other.dhGroups = self.dhGroups
301 other.defaultCurve = self.defaultCurve
302
303 if not cipherfactory.tripleDESPresent:
304 other.cipherNames = [i for i in self.cipherNames if i != "3des"]
305 if len(other.cipherNames) == 0:
306 raise ValueError("No supported ciphers")
307 if len(other.certificateTypes) == 0:
308 raise ValueError("No supported certificate types")
309
310 if not cryptomath.m2cryptoLoaded:
311 other.cipherImplementations = \
312 [e for e in other.cipherImplementations if e != "openssl"]
313 if not cryptomath.pycryptoLoaded:
314 other.cipherImplementations = \
315 [e for e in other.cipherImplementations if e != "pycrypto"]
316 if len(other.cipherImplementations) == 0:
317 raise ValueError("No supported cipher implementations")
318
319 self._sanityCheckKeySizes(other)
320
321 self._sanityCheckPrimitivesNames(other)
322
323 self._sanityCheckProtocolVersions(other)
324
325 self._sanityCheckExtensions(other)
326
327 if other.maxVersion < (3,3):
328
329 other.macNames = [e for e in self.macNames if \
330 e == "sha" or e == "md5"]
331
332 if len(other.rsaSigHashes) == 0 and other.maxVersion >= (3, 3):
333 raise ValueError("TLS 1.2 requires signature algorithms to be set")
334
335 if other.dhParams and (len(other.dhParams) != 2 or
336 not isinstance(other.dhParams[0], int_types) or
337 not isinstance(other.dhParams[1], int_types)):
338 raise ValueError("DH parameters need to be a tuple of integers")
339
340 return other
341
343 """Get list of certificate types as IDs"""
344 ret = []
345 for ct in self.certificateTypes:
346 if ct == "x509":
347 ret.append(CertificateType.x509)
348 else:
349 raise AssertionError()
350 return ret
351