Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/tlslite/tlslite/tlsconnection.py

Issue 212883008: Add DHE_RSA support to tlslite. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« third_party/tlslite/tlslite/messages.py ('K') | « third_party/tlslite/tlslite/messages.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698