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 """
146 self.minKeySize = 1023
147 self.maxKeySize = 8193
148 self.cipherNames = list(CIPHER_NAMES)
149 self.macNames = list(MAC_NAMES)
150 self.keyExchangeNames = list(KEY_EXCHANGE_NAMES)
151 self.cipherImplementations = list(CIPHER_IMPLEMENTATIONS)
152 self.certificateTypes = list(CERTIFICATE_TYPES)
153 self.minVersion = (3, 1)
154 self.maxVersion = (3, 3)
155 self.useExperimentalTackExtension = False
156 self.sendFallbackSCSV = False
157 self.useEncryptThenMAC = True
158 self.rsaSigHashes = list(RSA_SIGNATURE_HASHES)
159 self.rsaSchemes = list(RSA_SCHEMES)
160 self.eccCurves = list(CURVE_NAMES)
161 self.usePaddingExtension = True
162 self.useExtendedMasterSecret = True
163 self.requireExtendedMasterSecret = False
164 self.dhParams = None
165 self.dhGroups = list(ALL_DH_GROUP_NAMES)
166
167 @staticmethod
169 """Check if key size limits are sane"""
170 if other.minKeySize < 512:
171 raise ValueError("minKeySize too small")
172 if other.minKeySize > 16384:
173 raise ValueError("minKeySize too large")
174 if other.maxKeySize < 512:
175 raise ValueError("maxKeySize too small")
176 if other.maxKeySize > 16384:
177 raise ValueError("maxKeySize too large")
178 if other.maxKeySize < other.minKeySize:
179 raise ValueError("maxKeySize smaller than minKeySize")
180
181 @staticmethod
183 """Check if specified cryptographic primitive names are known"""
184 unknownCiphers = [val for val in other.cipherNames \
185 if val not in ALL_CIPHER_NAMES]
186 if unknownCiphers:
187 raise ValueError("Unknown cipher name: %s" % unknownCiphers)
188
189 unknownMacs = [val for val in other.macNames \
190 if val not in ALL_MAC_NAMES]
191 if unknownMacs:
192 raise ValueError("Unknown MAC name: %s" % unknownMacs)
193
194 unknownKex = [val for val in other.keyExchangeNames \
195 if val not in KEY_EXCHANGE_NAMES]
196 if unknownKex:
197 raise ValueError("Unknown key exchange name: %s" % unknownKex)
198
199 unknownImpl = [val for val in other.cipherImplementations \
200 if val not in CIPHER_IMPLEMENTATIONS]
201 if unknownImpl:
202 raise ValueError("Unknown cipher implementation: %s" % \
203 unknownImpl)
204
205 unknownType = [val for val in other.certificateTypes \
206 if val not in CERTIFICATE_TYPES]
207 if unknownType:
208 raise ValueError("Unknown certificate type: %s" % unknownType)
209
210 unknownCurve = [val for val in other.eccCurves \
211 if val not in ALL_CURVE_NAMES]
212 if unknownCurve:
213 raise ValueError("Unknown ECC Curve name: {0}".format(unknownCurve))
214
215 unknownSigHash = [val for val in other.rsaSigHashes \
216 if val not in ALL_RSA_SIGNATURE_HASHES]
217 if unknownSigHash:
218 raise ValueError("Unknown RSA signature hash: '{0}'".\
219 format(unknownSigHash))
220
221 unknownRSAPad = [val for val in other.rsaSchemes
222 if val not in RSA_SCHEMES]
223 if unknownRSAPad:
224 raise ValueError("Unknown RSA padding mode: '{0}'".\
225 format(unknownRSAPad))
226
227 unknownDHGroup = [val for val in other.dhGroups
228 if val not in ALL_DH_GROUP_NAMES]
229 if unknownDHGroup:
230 raise ValueError("Unknown FFDHE group name: '{0}'"
231 .format(unknownDHGroup))
232
233 @staticmethod
235 """Check if set protocol version are sane"""
236 if other.minVersion > other.maxVersion:
237 raise ValueError("Versions set incorrectly")
238 if other.minVersion not in ((3, 0), (3, 1), (3, 2), (3, 3)):
239 raise ValueError("minVersion set incorrectly")
240 if other.maxVersion not in ((3, 0), (3, 1), (3, 2), (3, 3)):
241 raise ValueError("maxVersion set incorrectly")
242
243 @staticmethod
245 """Check if set extension settings are sane"""
246 if other.useEncryptThenMAC not in (True, False):
247 raise ValueError("useEncryptThenMAC can only be True or False")
248
249 if other.useExtendedMasterSecret not in (True, False):
250 raise ValueError("useExtendedMasterSecret must be True or False")
251 if other.requireExtendedMasterSecret not in (True, False):
252 raise ValueError("requireExtendedMasterSecret must be True "
253 "or False")
254 if other.requireExtendedMasterSecret and \
255 not other.useExtendedMasterSecret:
256 raise ValueError("requireExtendedMasterSecret requires "
257 "useExtendedMasterSecret")
258
259 if other.usePaddingExtension not in (True, False):
260 raise ValueError("usePaddingExtension must be True or False")
261
263 """
264 Validate the settings, filter out unsupported ciphersuites and return
265 a copy of object. Does not modify the original object.
266
267 @rtype: HandshakeSettings
268 @return: a self-consistent copy of settings
269 @raise ValueError: when settings are invalid, insecure or unsupported.
270 """
271 other = HandshakeSettings()
272 other.minKeySize = self.minKeySize
273 other.maxKeySize = self.maxKeySize
274 other.cipherNames = self.cipherNames
275 other.macNames = self.macNames
276 other.keyExchangeNames = self.keyExchangeNames
277 other.cipherImplementations = self.cipherImplementations
278 other.certificateTypes = self.certificateTypes
279 other.minVersion = self.minVersion
280 other.maxVersion = self.maxVersion
281 other.sendFallbackSCSV = self.sendFallbackSCSV
282 other.useEncryptThenMAC = self.useEncryptThenMAC
283 other.usePaddingExtension = self.usePaddingExtension
284 other.rsaSigHashes = self.rsaSigHashes
285 other.rsaSchemes = self.rsaSchemes
286 other.eccCurves = self.eccCurves
287 other.useExtendedMasterSecret = self.useExtendedMasterSecret
288 other.requireExtendedMasterSecret = self.requireExtendedMasterSecret
289 other.dhParams = self.dhParams
290 other.dhGroups = self.dhGroups
291
292 if not cipherfactory.tripleDESPresent:
293 other.cipherNames = [i for i in self.cipherNames if i != "3des"]
294 if len(other.cipherNames) == 0:
295 raise ValueError("No supported ciphers")
296 if len(other.certificateTypes) == 0:
297 raise ValueError("No supported certificate types")
298
299 if not cryptomath.m2cryptoLoaded:
300 other.cipherImplementations = \
301 [e for e in other.cipherImplementations if e != "openssl"]
302 if not cryptomath.pycryptoLoaded:
303 other.cipherImplementations = \
304 [e for e in other.cipherImplementations if e != "pycrypto"]
305 if len(other.cipherImplementations) == 0:
306 raise ValueError("No supported cipher implementations")
307
308 self._sanityCheckKeySizes(other)
309
310 self._sanityCheckPrimitivesNames(other)
311
312 self._sanityCheckProtocolVersions(other)
313
314 self._sanityCheckExtensions(other)
315
316 if other.maxVersion < (3,3):
317
318 other.macNames = [e for e in self.macNames if \
319 e == "sha" or e == "md5"]
320
321 if len(other.rsaSigHashes) == 0 and other.maxVersion >= (3, 3):
322 raise ValueError("TLS 1.2 requires signature algorithms to be set")
323
324 if other.dhParams and (len(other.dhParams) != 2 or
325 not isinstance(other.dhParams[0], int_types) or
326 not isinstance(other.dhParams[1], int_types)):
327 raise ValueError("DH parameters need to be a tuple of integers")
328
329 return other
330
332 """Get list of certificate types as IDs"""
333 ret = []
334 for ct in self.certificateTypes:
335 if ct == "x509":
336 ret.append(CertificateType.x509)
337 else:
338 raise AssertionError()
339 return ret
340