Chromium Code Reviews| 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 |