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

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: spaces Created 6 years, 8 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):
wtc 2014/04/02 19:11:29 Nit: it would be nice to document what privateKey
wtc 2014/04/02 19:13:46 Sorry, I forgot to update this comment. I believe
davidben 2014/04/03 18:45:48 Done.
29 self.cipherSuite = cipherSuite
30 self.clientHello = clientHello
31 self.serverHello = serverHello
32 self.privateKey = privateKey
33
34 def makeServerKeyExchange():
wtc 2014/04/02 19:11:29 Nit: document what this method returns, and what i
davidben 2014/04/03 18:45:48 Done.
35 raise NotImplementedError()
36 def processClientKeyExchange(clientKeyExchange):
wtc 2014/04/02 19:11:29 Nit: document what this method returns (the premas
davidben 2014/04/03 18:45:48 Done.
37 raise NotImplementedError()
38
39
wtc 2014/04/02 19:11:29 Nit: use only one blank line here and before line
davidben 2014/04/03 18:45:48 Done. Although this code doesn't seem to be very c
40 class RSAKeyExchange(KeyExchange):
41 def makeServerKeyExchange(self):
42 return None
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
50 randomPreMasterSecret = getRandomBytes(48)
51 versionCheck = (premasterSecret[0], premasterSecret[1])
52 if not premasterSecret:
wtc 2014/04/02 19:11:29 Hmm... On line 51 we already dereferenced premaste
davidben 2014/04/03 18:45:48 Haha. I guess that code never actually worked then
53 premasterSecret = randomPreMasterSecret
54 elif len(premasterSecret)!=48:
55 premasterSecret = randomPreMasterSecret
56 elif versionCheck != self.clientHello.client_version:
57 #Tolerate buggy IE clients
58 if versionCheck != self.serverHello.server_version:
59 premasterSecret = randomPreMasterSecret
60 return premasterSecret
61
62 def _hexStringToNumber(s):
63 s = s.replace(" ", "").replace("\n", "")
64 if len(s) % 2 != 0:
65 raise ValueError("Length is not even")
66 return bytesToNumber(bytearray(s.decode("hex")))
67
68 class DHE_RSAKeyExchange(KeyExchange):
69 # 2048-bit MODP Group (RFC 3526, Section 3)
70 dh_p = _hexStringToNumber("""
71 FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
72 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
73 EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
74 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
75 EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
76 C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
77 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
78 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
79 E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
80 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
81 15728E5A 8AACAA68 FFFFFFFF FFFFFFFF""")
wtc 2014/04/02 19:11:29 Nit: should lines 71-81 be indented?
davidben 2014/04/03 18:45:48 *shrug* It does actually change what's in the stri
82 dh_g = 2
83
84 # RFC 3526, Section 8.
85 strength = 160
86
87 def makeServerKeyExchange(self):
88 # Per RFC 3526, Section 1, the exponent should have double the entropy
89 # of the strength of the curve.
90 self.dh_Xs = bytesToNumber(getRandomBytes(self.strength * 2 / 8))
91 dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p)
92
93 serverKeyExchange = ServerKeyExchange(self.cipherSuite)
94 serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
95 serverKeyExchange.signature = self.privateKey.sign(
96 serverKeyExchange.hash(self.clientHello.random,
97 self.serverHello.random))
98 return serverKeyExchange
99
100 def processClientKeyExchange(self, clientKeyExchange):
101 dh_Yc = clientKeyExchange.dh_Yc
102
103 # First half of RFC 2631, Section 2.1.5.
wtc 2014/04/02 19:11:29 Nit: Add "Validate the client's public key." This
davidben 2014/04/03 18:45:48 Done.
104 if not 2 <= dh_Yc <= self.dh_p - 1:
105 raise TLSLocalAlert(AlertDescription.illegal_parameter,
106 "Suspicious dh_Yc value")
wtc 2014/04/02 19:11:29 Nit: Suspicious => Invalid
davidben 2014/04/03 18:45:48 Done.
107
108 S = powMod(dh_Yc, self.dh_Xs, self.dh_p)
109 return numberToByteArray(S)
110
27 class TLSConnection(TLSRecordLayer): 111 class TLSConnection(TLSRecordLayer):
28 """ 112 """
29 This class wraps a socket and provides TLS handshaking and data 113 This class wraps a socket and provides TLS handshaking and data
30 transfer. 114 transfer.
31 115
32 To use this class, create a new instance, passing a connected 116 To use this class, create a new instance, passing a connected
33 socket into the constructor. Then call some handshake function. 117 socket into the constructor. Then call some handshake function.
34 If the handshake completes without raising an exception, then a TLS 118 If the handshake completes without raising an exception, then a TLS
35 connection has been negotiated. You can transfer data over this 119 connection has been negotiated. You can transfer data over this
36 connection as if it were a socket. 120 connection as if it were a socket.
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 577
494 def _clientSendClientHello(self, settings, session, srpUsername, 578 def _clientSendClientHello(self, settings, session, srpUsername,
495 srpParams, certParams, anonParams, 579 srpParams, certParams, anonParams,
496 serverName, nextProtos, reqTack): 580 serverName, nextProtos, reqTack):
497 #Initialize acceptable ciphersuites 581 #Initialize acceptable ciphersuites
498 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 582 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
499 if srpParams: 583 if srpParams:
500 cipherSuites += CipherSuite.getSrpAllSuites(settings) 584 cipherSuites += CipherSuite.getSrpAllSuites(settings)
501 elif certParams: 585 elif certParams:
502 cipherSuites += CipherSuite.getCertSuites(settings) 586 cipherSuites += CipherSuite.getCertSuites(settings)
587 # Client DHE_RSA not supported.
wtc 2014/04/02 19:11:29 Nit: Add "TODO" to this comment.
davidben 2014/04/03 18:45:48 Done.
588 # cipherSuites += CipherSuite.getDheCertSuites(settings)
503 elif anonParams: 589 elif anonParams:
504 cipherSuites += CipherSuite.getAnonSuites(settings) 590 cipherSuites += CipherSuite.getAnonSuites(settings)
505 else: 591 else:
506 assert(False) 592 assert(False)
507 593
508 #Initialize acceptable certificate types 594 #Initialize acceptable certificate types
509 certificateTypes = settings._getCertificateTypes() 595 certificateTypes = settings._getCertificateTypes()
510 596
511 #Either send ClientHello (with a resumable session)... 597 #Either send ClientHello (with a resumable session)...
512 if session and session.sessionID: 598 if session and session.sessionID:
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 # Perform the SRP key exchange 1283 # Perform the SRP key exchange
1198 clientCertChain = None 1284 clientCertChain = None
1199 if cipherSuite in CipherSuite.srpAllSuites: 1285 if cipherSuite in CipherSuite.srpAllSuites:
1200 for result in self._serverSRPKeyExchange(clientHello, serverHello, 1286 for result in self._serverSRPKeyExchange(clientHello, serverHello,
1201 verifierDB, cipherSuite, 1287 verifierDB, cipherSuite,
1202 privateKey, certChain): 1288 privateKey, certChain):
1203 if result in (0,1): yield result 1289 if result in (0,1): yield result
1204 else: break 1290 else: break
1205 premasterSecret = result 1291 premasterSecret = result
1206 1292
1207 # Perform the RSA key exchange 1293 # Perform the RSA or DHE_RSA key exchange
1208 elif cipherSuite in CipherSuite.certSuites: 1294 elif (cipherSuite in CipherSuite.certSuites or
1295 cipherSuite in CipherSuite.dheCertSuites):
1296 if cipherSuite in CipherSuite.certSuites:
1297 keyExchange = RSAKeyExchange(cipherSuite,
1298 clientHello,
1299 serverHello,
1300 privateKey)
1301 elif cipherSuite in CipherSuite.dheCertSuites:
1302 keyExchange = DHE_RSAKeyExchange(cipherSuite,
1303 clientHello,
1304 serverHello,
1305 privateKey)
1306 else:
1307 assert(False)
1209 for result in self._serverCertKeyExchange(clientHello, serverHello, 1308 for result in self._serverCertKeyExchange(clientHello, serverHello,
1210 certChain, privateKey, 1309 certChain, keyExchange,
1211 reqCert, reqCAs, cipherSuite, 1310 reqCert, reqCAs, cipherSuite,
1212 settings, ocspResponse): 1311 settings, ocspResponse):
1213 if result in (0,1): yield result 1312 if result in (0,1): yield result
1214 else: break 1313 else: break
1215 (premasterSecret, clientCertChain) = result 1314 (premasterSecret, clientCertChain) = result
1216 1315
1217 # Perform anonymous Diffie Hellman key exchange 1316 # Perform anonymous Diffie Hellman key exchange
1218 elif cipherSuite in CipherSuite.anonSuites: 1317 elif cipherSuite in CipherSuite.anonSuites:
1219 for result in self._serverAnonKeyExchange(clientHello, serverHello, 1318 for result in self._serverAnonKeyExchange(clientHello, serverHello,
1220 cipherSuite, settings): 1319 cipherSuite, settings):
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 sessionCache, anon, tlsIntolerant, fallbackSCSV) : 1360 sessionCache, anon, tlsIntolerant, fallbackSCSV) :
1262 #Initialize acceptable cipher suites 1361 #Initialize acceptable cipher suites
1263 cipherSuites = [] 1362 cipherSuites = []
1264 if verifierDB: 1363 if verifierDB:
1265 if certChain: 1364 if certChain:
1266 cipherSuites += \ 1365 cipherSuites += \
1267 CipherSuite.getSrpCertSuites(settings) 1366 CipherSuite.getSrpCertSuites(settings)
1268 cipherSuites += CipherSuite.getSrpSuites(settings) 1367 cipherSuites += CipherSuite.getSrpSuites(settings)
1269 elif certChain: 1368 elif certChain:
1270 cipherSuites += CipherSuite.getCertSuites(settings) 1369 cipherSuites += CipherSuite.getCertSuites(settings)
1370 cipherSuites += CipherSuite.getDheCertSuites(settings)
1271 elif anon: 1371 elif anon:
1272 cipherSuites += CipherSuite.getAnonSuites(settings) 1372 cipherSuites += CipherSuite.getAnonSuites(settings)
1273 else: 1373 else:
1274 assert(False) 1374 assert(False)
1275 1375
1276 #Tentatively set version to most-desirable version, so if an error 1376 #Tentatively set version to most-desirable version, so if an error
1277 #occurs parsing the ClientHello, this is what we'll use for the 1377 #occurs parsing the ClientHello, this is what we'll use for the
1278 #error alert 1378 #error alert
1279 self.version = settings.maxVersion 1379 self.version = settings.maxVersion
1280 1380
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1476 u = makeU(N, A, B) 1576 u = makeU(N, A, B)
1477 1577
1478 #Calculate premaster secret 1578 #Calculate premaster secret
1479 S = powMod((A * powMod(v,u,N)) % N, b, N) 1579 S = powMod((A * powMod(v,u,N)) % N, b, N)
1480 premasterSecret = numberToByteArray(S) 1580 premasterSecret = numberToByteArray(S)
1481 1581
1482 yield premasterSecret 1582 yield premasterSecret
1483 1583
1484 1584
1485 def _serverCertKeyExchange(self, clientHello, serverHello, 1585 def _serverCertKeyExchange(self, clientHello, serverHello,
1486 serverCertChain, privateKey, 1586 serverCertChain, keyExchange,
1487 reqCert, reqCAs, cipherSuite, 1587 reqCert, reqCAs, cipherSuite,
1488 settings, ocspResponse): 1588 settings, ocspResponse):
1489 #Send ServerHello, Certificate[, CertificateRequest], 1589 #Send ServerHello, Certificate[, ServerKeyExchange]
1490 #ServerHelloDone 1590 #[, CertificateRequest], ServerHelloDone
1491 msgs = [] 1591 msgs = []
1492 1592
1493 # If we verify a client cert chain, return it 1593 # If we verify a client cert chain, return it
1494 clientCertChain = None 1594 clientCertChain = None
1495 1595
1496 msgs.append(serverHello) 1596 msgs.append(serverHello)
1497 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) 1597 msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
1498 if serverHello.status_request: 1598 if serverHello.status_request:
1499 msgs.append(CertificateStatus().create(ocspResponse)) 1599 msgs.append(CertificateStatus().create(ocspResponse))
1600 serverKeyExchange = keyExchange.makeServerKeyExchange()
wtc 2014/04/02 19:11:29 Nit: the function call you use to create the Serve
davidben 2014/04/03 18:45:48 Hrm. Yeah, I'm not sure we can follow that pattern
1601 if serverKeyExchange is not None:
1602 msgs.append(serverKeyExchange)
1500 if reqCert and reqCAs: 1603 if reqCert and reqCAs:
1501 msgs.append(CertificateRequest().create(\ 1604 msgs.append(CertificateRequest().create(\
1502 [ClientCertificateType.rsa_sign], reqCAs)) 1605 [ClientCertificateType.rsa_sign], reqCAs))
1503 elif reqCert: 1606 elif reqCert:
1504 msgs.append(CertificateRequest()) 1607 msgs.append(CertificateRequest())
1505 msgs.append(ServerHelloDone()) 1608 msgs.append(ServerHelloDone())
1506 for result in self._sendMsgs(msgs): 1609 for result in self._sendMsgs(msgs):
1507 yield result 1610 yield result
1508 1611
1509 #From here on, the client's messages must have the right version 1612 #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() 1651 raise AssertionError()
1549 1652
1550 #Get ClientKeyExchange 1653 #Get ClientKeyExchange
1551 for result in self._getMsg(ContentType.handshake, 1654 for result in self._getMsg(ContentType.handshake,
1552 HandshakeType.client_key_exchange, 1655 HandshakeType.client_key_exchange,
1553 cipherSuite): 1656 cipherSuite):
1554 if result in (0,1): yield result 1657 if result in (0,1): yield result
1555 else: break 1658 else: break
1556 clientKeyExchange = result 1659 clientKeyExchange = result
1557 1660
1558 #Decrypt ClientKeyExchange 1661 #Process ClientKeyExchange
1559 premasterSecret = privateKey.decrypt(\ 1662 try:
1560 clientKeyExchange.encryptedPreMasterSecret) 1663 premasterSecret = \
1561 1664 keyExchange.processClientKeyExchange(clientKeyExchange)
1562 # On decryption failure randomize premaster secret to avoid 1665 except TLSLocalAlert, e:
1563 # Bleichenbacher's "million message" attack 1666 for result in self._sendError(e.description, e.message):
wtc 2014/04/02 19:11:29 Nit: rename |e| to |alert|?
davidben 2014/04/03 18:45:48 Done.
1564 randomPreMasterSecret = getRandomBytes(48) 1667 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 1668
1574 #Get and check CertificateVerify, if relevant 1669 #Get and check CertificateVerify, if relevant
1575 if clientCertChain: 1670 if clientCertChain:
1576 if self.version == (3,0): 1671 if self.version == (3,0):
1577 masterSecret = calcMasterSecret(self.version, premasterSecret, 1672 masterSecret = calcMasterSecret(self.version, premasterSecret,
1578 clientHello.random, serverHello.random) 1673 clientHello.random, serverHello.random)
1579 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"") 1674 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
1580 elif self.version in ((3,1), (3,2)): 1675 elif self.version in ((3,1), (3,2)):
1581 verifyBytes = self._handshake_md5.digest() + \ 1676 verifyBytes = self._handshake_md5.digest() + \
1582 self._handshake_sha.digest() 1677 self._handshake_sha.digest()
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
1810 except TLSAlert as alert: 1905 except TLSAlert as alert:
1811 if not self.fault: 1906 if not self.fault:
1812 raise 1907 raise
1813 if alert.description not in Fault.faultAlerts[self.fault]: 1908 if alert.description not in Fault.faultAlerts[self.fault]:
1814 raise TLSFaultError(str(alert)) 1909 raise TLSFaultError(str(alert))
1815 else: 1910 else:
1816 pass 1911 pass
1817 except: 1912 except:
1818 self._shutdown(False) 1913 self._shutdown(False)
1819 raise 1914 raise
OLDNEW
« third_party/tlslite/tlslite/handshakesettings.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