OLD | NEW |
---|---|
1 # Authors: | 1 # Authors: |
2 # Trevor Perrin | 2 # Trevor Perrin |
3 # Google - added reqCAs parameter | 3 # Google - added reqCAs parameter |
4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support | 4 # Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support |
5 # Dimitris Moraitis - Anon ciphersuites | 5 # Dimitris Moraitis - Anon ciphersuites |
6 # Martin von Loewis - python 3 port | 6 # Martin von Loewis - python 3 port |
7 # | 7 # |
8 # See the LICENSE file for legal information regarding use of this file. | 8 # See the LICENSE file for legal information regarding use of this file. |
9 | 9 |
10 """ | 10 """ |
11 MAIN CLASS FOR TLS LITE (START HERE!). | 11 MAIN CLASS FOR TLS LITE (START HERE!). |
12 """ | 12 """ |
13 | 13 |
14 import socket | 14 import socket |
15 from .utils.compat import formatExceptionTrace | 15 from .utils.compat import formatExceptionTrace |
16 from .tlsrecordlayer import TLSRecordLayer | 16 from .tlsrecordlayer import TLSRecordLayer |
17 from .session import Session | 17 from .session import Session |
18 from .constants import * | 18 from .constants import * |
19 from .utils.cryptomath import getRandomBytes | 19 from .utils.cryptomath import getRandomBytes |
20 from .errors import * | 20 from .errors import * |
21 from .messages import * | 21 from .messages import * |
22 from .mathtls import * | 22 from .mathtls import * |
23 from .handshakesettings import HandshakeSettings | 23 from .handshakesettings import HandshakeSettings |
24 from .utils.tackwrapper import * | 24 from .utils.tackwrapper import * |
25 | 25 |
26 | 26 |
27 class KeyExchange(object): | |
28 def __init__(self, cipherSuite, clientHello, serverHello, privateKey): | |
29 self.cipherSuite = cipherSuite | |
30 self.clientHello = clientHello | |
31 self.serverHello = serverHello | |
32 self.privateKey = privateKey | |
33 | |
34 def makeServerKeyExchange(): | |
35 raise NotImplementedError() | |
36 def processClientKeyExchange(clientKeyExchange): | |
37 raise NotImplementedError() | |
38 | |
39 | |
40 class RSAKeyExchange(KeyExchange): | |
41 def makeServerKeyExchange(self): | |
42 return None | |
Ryan Sleevi
2014/03/31 20:43:57
is None right? Should it be NotImplemented?
davidben
2014/03/31 20:58:20
RSA doesn't send a ServerKeyExchange. This method
| |
43 | |
44 def processClientKeyExchange(self, clientKeyExchange): | |
45 premasterSecret = self.privateKey.decrypt(\ | |
46 clientKeyExchange.encryptedPreMasterSecret) | |
47 | |
48 # On decryption failure randomize premaster secret to avoid | |
49 # Bleichenbacher's "million message" attack | |
Ryan Sleevi
2014/03/31 20:43:57
heheheh.
This doesn't really do that, but ok [Yes
davidben
2014/03/31 20:58:20
:-P I make no claims as to whether that comment wa
wtc
2014/04/02 03:34:20
If self.privateKey.decrypt does RSA blinding, then
| |
50 randomPreMasterSecret = getRandomBytes(48) | |
51 versionCheck = (premasterSecret[0], premasterSecret[1]) | |
52 if not premasterSecret: | |
53 premasterSecret = randomPreMasterSecret | |
54 elif len(premasterSecret)!=48: | |
55 premasterSecret = randomPreMasterSecret | |
56 elif versionCheck != self.clientHello.client_version: | |
57 #Tolerate buggy IE clients | |
wtc
2014/04/01 22:00:01
This is a very old bug of IE. I suspect this bug h
davidben
2014/04/01 23:25:18
Yeah, this block was just moved over. I can also j
wtc
2014/04/02 03:34:20
It's fine to keep this. We should only drop this i
| |
58 if versionCheck != self.serverHello.server_version: | |
wtc
2014/04/01 22:00:01
Is self.serverHello.server_version correct? The or
davidben
2014/04/01 23:25:18
Should be. I made sure it passed all tlslite's ori
| |
59 premasterSecret = randomPreMasterSecret | |
60 return premasterSecret | |
61 | |
62 class DHE_RSAKeyExchange(KeyExchange): | |
63 # Generated with openssl dhparam 1024 -text. Generating a new one each time | |
64 # in Python is far far far too slow. | |
wtc
2014/04/01 22:00:01
IMPORTANT: please use one of the well-known DH gro
davidben
2014/04/01 23:25:18
Done.
| |
65 dh_p = bytesToNumber( | |
66 bytearray( | |
67 "\x00\x88\xc4\xdc\x2a\xd9\xba\x8d\x24\x69\x7f\xe4\xd4\xeb\x62" | |
68 "\x04\x43\xe8\x31\x08\x30\xa8\xe4\x24\x0f\xa7\xc3\xff\x84\x52" | |
69 "\x44\x4a\x1b\x8c\x88\x16\xa6\x17\x90\xac\x21\x34\xfb\xc5\xff" | |
70 "\x90\x46\x32\x29\xfa\x9d\xd3\x36\x05\xc2\x86\xcf\xde\x77\x68" | |
71 "\x4c\xe3\xb0\x34\x55\xce\x27\x85\x46\x94\xad\x0c\xef\x11\x53" | |
72 "\x61\x50\x0c\x3e\x7b\x8a\x3c\xa0\x52\x6c\xb2\xa5\x84\xf7\xa9" | |
73 "\xdc\x9d\x57\x60\xd0\x89\xc6\x14\x39\x54\xce\x20\xcc\x2d\xe9" | |
74 "\x90\xeb\xe7\x42\xf1\x03\x60\x5b\x06\x2f\x51\x97\x01\xc2\x1d" | |
75 "\xfa\xb3\xfe\x02\x4b\xee\xd1\x65\xcb")) | |
76 dh_g = 2 | |
77 | |
78 def makeServerKeyExchange(self): | |
79 self.dh_Xs = bytesToNumber(getRandomBytes(1024 / 8)) | |
80 dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p) | |
81 | |
82 serverKeyExchange = ServerKeyExchange(self.cipherSuite) | |
83 serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys) | |
84 serverKeyExchange.signature = self.privateKey.sign( | |
85 serverKeyExchange.hash(self.clientHello.random, | |
86 self.serverHello.random)) | |
87 return serverKeyExchange | |
88 | |
89 def processClientKeyExchange(self, clientKeyExchange): | |
90 dh_Yc = clientKeyExchange.dh_Yc | |
91 | |
92 if dh_Yc % self.dh_p == 0: | |
wtc
2014/04/01 22:00:01
Is this check recommended by RFC 5246? I'm just cu
davidben
2014/04/01 23:25:18
I just copied the DH code from _serverAnonKeyExcha
| |
93 raise TLSLocalAlert(AlertDescription.illegal_parameter, | |
94 "Suspicious dh_Yc value") | |
95 | |
96 S = powMod(dh_Yc, self.dh_Xs, self.dh_p) | |
97 return numberToByteArray(S) | |
98 | |
27 class TLSConnection(TLSRecordLayer): | 99 class TLSConnection(TLSRecordLayer): |
28 """ | 100 """ |
29 This class wraps a socket and provides TLS handshaking and data | 101 This class wraps a socket and provides TLS handshaking and data |
30 transfer. | 102 transfer. |
31 | 103 |
32 To use this class, create a new instance, passing a connected | 104 To use this class, create a new instance, passing a connected |
33 socket into the constructor. Then call some handshake function. | 105 socket into the constructor. Then call some handshake function. |
34 If the handshake completes without raising an exception, then a TLS | 106 If the handshake completes without raising an exception, then a TLS |
35 connection has been negotiated. You can transfer data over this | 107 connection has been negotiated. You can transfer data over this |
36 connection as if it were a socket. | 108 connection as if it were a socket. |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
493 | 565 |
494 def _clientSendClientHello(self, settings, session, srpUsername, | 566 def _clientSendClientHello(self, settings, session, srpUsername, |
495 srpParams, certParams, anonParams, | 567 srpParams, certParams, anonParams, |
496 serverName, nextProtos, reqTack): | 568 serverName, nextProtos, reqTack): |
497 #Initialize acceptable ciphersuites | 569 #Initialize acceptable ciphersuites |
498 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] | 570 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] |
499 if srpParams: | 571 if srpParams: |
500 cipherSuites += CipherSuite.getSrpAllSuites(settings) | 572 cipherSuites += CipherSuite.getSrpAllSuites(settings) |
501 elif certParams: | 573 elif certParams: |
502 cipherSuites += CipherSuite.getCertSuites(settings) | 574 cipherSuites += CipherSuite.getCertSuites(settings) |
575 # Client DHE_RSA not supported. | |
576 # cipherSuites += CipherSuite.getDheCertSuites(settings) | |
503 elif anonParams: | 577 elif anonParams: |
504 cipherSuites += CipherSuite.getAnonSuites(settings) | 578 cipherSuites += CipherSuite.getAnonSuites(settings) |
505 else: | 579 else: |
506 assert(False) | 580 assert(False) |
507 | 581 |
508 #Initialize acceptable certificate types | 582 #Initialize acceptable certificate types |
509 certificateTypes = settings._getCertificateTypes() | 583 certificateTypes = settings._getCertificateTypes() |
510 | 584 |
511 #Either send ClientHello (with a resumable session)... | 585 #Either send ClientHello (with a resumable session)... |
512 if session and session.sessionID: | 586 if session and session.sessionID: |
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1197 # Perform the SRP key exchange | 1271 # Perform the SRP key exchange |
1198 clientCertChain = None | 1272 clientCertChain = None |
1199 if cipherSuite in CipherSuite.srpAllSuites: | 1273 if cipherSuite in CipherSuite.srpAllSuites: |
1200 for result in self._serverSRPKeyExchange(clientHello, serverHello, | 1274 for result in self._serverSRPKeyExchange(clientHello, serverHello, |
1201 verifierDB, cipherSuite, | 1275 verifierDB, cipherSuite, |
1202 privateKey, certChain): | 1276 privateKey, certChain): |
1203 if result in (0,1): yield result | 1277 if result in (0,1): yield result |
1204 else: break | 1278 else: break |
1205 premasterSecret = result | 1279 premasterSecret = result |
1206 | 1280 |
1207 # Perform the RSA key exchange | 1281 # Perform the RSA key exchange |
wtc
2014/04/01 22:00:01
Nit: this comment should say "Perform the RSA or D
davidben
2014/04/01 23:25:18
Done.
| |
1208 elif cipherSuite in CipherSuite.certSuites: | 1282 elif (cipherSuite in CipherSuite.certSuites or |
1283 cipherSuite in CipherSuite.dheCertSuites): | |
1284 if cipherSuite in CipherSuite.certSuites: | |
1285 keyExchange = RSAKeyExchange(cipherSuite, | |
1286 clientHello, | |
1287 serverHello, | |
1288 privateKey) | |
1289 elif cipherSuite in CipherSuite.dheCertSuites: | |
1290 keyExchange = DHE_RSAKeyExchange(cipherSuite, | |
1291 clientHello, | |
1292 serverHello, | |
1293 privateKey) | |
1294 else: | |
1295 assert(False) | |
1209 for result in self._serverCertKeyExchange(clientHello, serverHello, | 1296 for result in self._serverCertKeyExchange(clientHello, serverHello, |
1210 certChain, privateKey, | 1297 certChain, keyExchange, |
1211 reqCert, reqCAs, cipherSuite, | 1298 reqCert, reqCAs, cipherSuite, |
1212 settings, ocspResponse): | 1299 settings, ocspResponse): |
1213 if result in (0,1): yield result | 1300 if result in (0,1): yield result |
1214 else: break | 1301 else: break |
1215 (premasterSecret, clientCertChain) = result | 1302 (premasterSecret, clientCertChain) = result |
1216 | 1303 |
1217 # Perform anonymous Diffie Hellman key exchange | 1304 # Perform anonymous Diffie Hellman key exchange |
1218 elif cipherSuite in CipherSuite.anonSuites: | 1305 elif cipherSuite in CipherSuite.anonSuites: |
1219 for result in self._serverAnonKeyExchange(clientHello, serverHello, | 1306 for result in self._serverAnonKeyExchange(clientHello, serverHello, |
1220 cipherSuite, settings): | 1307 cipherSuite, settings): |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1261 sessionCache, anon, tlsIntolerant, fallbackSCSV) : | 1348 sessionCache, anon, tlsIntolerant, fallbackSCSV) : |
1262 #Initialize acceptable cipher suites | 1349 #Initialize acceptable cipher suites |
1263 cipherSuites = [] | 1350 cipherSuites = [] |
1264 if verifierDB: | 1351 if verifierDB: |
1265 if certChain: | 1352 if certChain: |
1266 cipherSuites += \ | 1353 cipherSuites += \ |
1267 CipherSuite.getSrpCertSuites(settings) | 1354 CipherSuite.getSrpCertSuites(settings) |
1268 cipherSuites += CipherSuite.getSrpSuites(settings) | 1355 cipherSuites += CipherSuite.getSrpSuites(settings) |
1269 elif certChain: | 1356 elif certChain: |
1270 cipherSuites += CipherSuite.getCertSuites(settings) | 1357 cipherSuites += CipherSuite.getCertSuites(settings) |
1358 cipherSuites += CipherSuite.getDheCertSuites(settings) | |
1271 elif anon: | 1359 elif anon: |
1272 cipherSuites += CipherSuite.getAnonSuites(settings) | 1360 cipherSuites += CipherSuite.getAnonSuites(settings) |
1273 else: | 1361 else: |
1274 assert(False) | 1362 assert(False) |
1275 | 1363 |
1276 #Tentatively set version to most-desirable version, so if an error | 1364 #Tentatively set version to most-desirable version, so if an error |
1277 #occurs parsing the ClientHello, this is what we'll use for the | 1365 #occurs parsing the ClientHello, this is what we'll use for the |
1278 #error alert | 1366 #error alert |
1279 self.version = settings.maxVersion | 1367 self.version = settings.maxVersion |
1280 | 1368 |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1476 u = makeU(N, A, B) | 1564 u = makeU(N, A, B) |
1477 | 1565 |
1478 #Calculate premaster secret | 1566 #Calculate premaster secret |
1479 S = powMod((A * powMod(v,u,N)) % N, b, N) | 1567 S = powMod((A * powMod(v,u,N)) % N, b, N) |
1480 premasterSecret = numberToByteArray(S) | 1568 premasterSecret = numberToByteArray(S) |
1481 | 1569 |
1482 yield premasterSecret | 1570 yield premasterSecret |
1483 | 1571 |
1484 | 1572 |
1485 def _serverCertKeyExchange(self, clientHello, serverHello, | 1573 def _serverCertKeyExchange(self, clientHello, serverHello, |
1486 serverCertChain, privateKey, | 1574 serverCertChain, keyExchange, |
1487 reqCert, reqCAs, cipherSuite, | 1575 reqCert, reqCAs, cipherSuite, |
1488 settings, ocspResponse): | 1576 settings, ocspResponse): |
1489 #Send ServerHello, Certificate[, CertificateRequest], | 1577 #Send ServerHello, Certificate[, CertificateRequest], |
wtc
2014/04/01 22:00:01
Nit: add the optional ServerKeyExchange method to
davidben
2014/04/01 23:25:18
Done.
| |
1490 #ServerHelloDone | 1578 #ServerHelloDone |
1491 msgs = [] | 1579 msgs = [] |
1492 | 1580 |
1493 # If we verify a client cert chain, return it | 1581 # If we verify a client cert chain, return it |
1494 clientCertChain = None | 1582 clientCertChain = None |
1495 | 1583 |
1496 msgs.append(serverHello) | 1584 msgs.append(serverHello) |
1497 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) | 1585 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) |
1498 if serverHello.status_request: | 1586 if serverHello.status_request: |
1499 msgs.append(CertificateStatus().create(ocspResponse)) | 1587 msgs.append(CertificateStatus().create(ocspResponse)) |
1588 serverKeyExchange = keyExchange.makeServerKeyExchange() | |
1589 if serverKeyExchange is not None: | |
1590 msgs.append(serverKeyExchange) | |
1500 if reqCert and reqCAs: | 1591 if reqCert and reqCAs: |
1501 msgs.append(CertificateRequest().create(\ | 1592 msgs.append(CertificateRequest().create(\ |
1502 [ClientCertificateType.rsa_sign], reqCAs)) | 1593 [ClientCertificateType.rsa_sign], reqCAs)) |
1503 elif reqCert: | 1594 elif reqCert: |
1504 msgs.append(CertificateRequest()) | 1595 msgs.append(CertificateRequest()) |
1505 msgs.append(ServerHelloDone()) | 1596 msgs.append(ServerHelloDone()) |
1506 for result in self._sendMsgs(msgs): | 1597 for result in self._sendMsgs(msgs): |
1507 yield result | 1598 yield result |
1508 | 1599 |
1509 #From here on, the client's messages must have the right version | 1600 #From here on, the client's messages must have the right version |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1548 raise AssertionError() | 1639 raise AssertionError() |
1549 | 1640 |
1550 #Get ClientKeyExchange | 1641 #Get ClientKeyExchange |
1551 for result in self._getMsg(ContentType.handshake, | 1642 for result in self._getMsg(ContentType.handshake, |
1552 HandshakeType.client_key_exchange, | 1643 HandshakeType.client_key_exchange, |
1553 cipherSuite): | 1644 cipherSuite): |
1554 if result in (0,1): yield result | 1645 if result in (0,1): yield result |
1555 else: break | 1646 else: break |
1556 clientKeyExchange = result | 1647 clientKeyExchange = result |
1557 | 1648 |
1558 #Decrypt ClientKeyExchange | 1649 #Process ClientKeyExchange |
1559 premasterSecret = privateKey.decrypt(\ | 1650 try: |
1560 clientKeyExchange.encryptedPreMasterSecret) | 1651 premasterSecret = \ |
1561 | 1652 keyExchange.processClientKeyExchange(clientKeyExchange) |
1562 # On decryption failure randomize premaster secret to avoid | 1653 except TLSLocalAlert, e: |
1563 # Bleichenbacher's "million message" attack | 1654 for result in self._sendError(alert.description, alert.message): |
wtc
2014/04/01 22:00:01
IMPORTANT: Should |alert| be |e|?
davidben
2014/04/01 23:25:18
Oops. Done.
| |
1564 randomPreMasterSecret = getRandomBytes(48) | 1655 yield result |
1565 versionCheck = (premasterSecret[0], premasterSecret[1]) | |
1566 if not premasterSecret: | |
1567 premasterSecret = randomPreMasterSecret | |
1568 elif len(premasterSecret)!=48: | |
1569 premasterSecret = randomPreMasterSecret | |
1570 elif versionCheck != clientHello.client_version: | |
1571 if versionCheck != self.version: #Tolerate buggy IE clients | |
1572 premasterSecret = randomPreMasterSecret | |
1573 | 1656 |
1574 #Get and check CertificateVerify, if relevant | 1657 #Get and check CertificateVerify, if relevant |
1575 if clientCertChain: | 1658 if clientCertChain: |
1576 if self.version == (3,0): | 1659 if self.version == (3,0): |
1577 masterSecret = calcMasterSecret(self.version, premasterSecret, | 1660 masterSecret = calcMasterSecret(self.version, premasterSecret, |
1578 clientHello.random, serverHello.random) | 1661 clientHello.random, serverHello.random) |
1579 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"") | 1662 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"") |
1580 elif self.version in ((3,1), (3,2)): | 1663 elif self.version in ((3,1), (3,2)): |
1581 verifyBytes = self._handshake_md5.digest() + \ | 1664 verifyBytes = self._handshake_md5.digest() + \ |
1582 self._handshake_sha.digest() | 1665 self._handshake_sha.digest() |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1810 except TLSAlert as alert: | 1893 except TLSAlert as alert: |
1811 if not self.fault: | 1894 if not self.fault: |
1812 raise | 1895 raise |
1813 if alert.description not in Fault.faultAlerts[self.fault]: | 1896 if alert.description not in Fault.faultAlerts[self.fault]: |
1814 raise TLSFaultError(str(alert)) | 1897 raise TLSFaultError(str(alert)) |
1815 else: | 1898 else: |
1816 pass | 1899 pass |
1817 except: | 1900 except: |
1818 self._shutdown(False) | 1901 self._shutdown(False) |
1819 raise | 1902 raise |
OLD | NEW |