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

Unified Diff: third_party/tlslite/patches/dhe_rsa.patch

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 side-by-side diff with in-line comments
Download patch
Index: third_party/tlslite/patches/dhe_rsa.patch
diff --git a/third_party/tlslite/patches/dhe_rsa.patch b/third_party/tlslite/patches/dhe_rsa.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4521e8b302fe3f219acb5b114a00f6a1b54af7ef
--- /dev/null
+++ b/third_party/tlslite/patches/dhe_rsa.patch
@@ -0,0 +1,378 @@
+diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
+index 52c20ac..feca423 100644
+--- a/third_party/tlslite/tlslite/constants.py
++++ b/third_party/tlslite/tlslite/constants.py
+@@ -143,6 +143,10 @@ class CipherSuite:
+
+ TLS_RSA_WITH_RC4_128_MD5 = 0x0004
+
++ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016
++ TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033
++ TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039
++
+ TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x0034
+ TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x003A
+
+@@ -150,17 +154,20 @@ class CipherSuite:
+ tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
+ tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
+ tripleDESSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
++ tripleDESSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
+
+ aes128Suites = []
+ aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
+ aes128Suites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA)
+ aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
++ aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
+ aes128Suites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
+
+ aes256Suites = []
+ aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
+ aes256Suites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA)
+ aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
++ aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
+ aes256Suites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
+
+ rc4Suites = []
+@@ -178,6 +185,9 @@ class CipherSuite:
+ shaSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
+ shaSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
+ shaSuites.append(TLS_RSA_WITH_RC4_128_SHA)
++ shaSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
++ shaSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
++ shaSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
+ shaSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
+ shaSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
+
+@@ -188,6 +198,7 @@ class CipherSuite:
+ def _filterSuites(suites, settings):
+ macNames = settings.macNames
+ cipherNames = settings.cipherNames
++ keyExchangeNames = settings.keyExchangeNames
+ macSuites = []
+ if "sha" in macNames:
+ macSuites += CipherSuite.shaSuites
+@@ -204,7 +215,20 @@ class CipherSuite:
+ if "rc4" in cipherNames:
+ cipherSuites += CipherSuite.rc4Suites
+
+- return [s for s in suites if s in macSuites and s in cipherSuites]
++ keyExchangeSuites = []
++ if "rsa" in keyExchangeNames:
++ keyExchangeSuites += CipherSuite.certSuites
++ if "dhe_rsa" in keyExchangeNames:
++ keyExchangeSuites += CipherSuite.dheCertSuites
++ if "srp_sha" in keyExchangeNames:
++ keyExchangeSuites += CipherSuite.srpSuites
++ if "srp_sha_rsa" in keyExchangeNames:
++ keyExchangeSuites += CipherSuite.srpCertSuites
++ if "dh_anon" in keyExchangeNames:
++ keyExchangeSuites += CipherSuite.anonSuites
++
++ return [s for s in suites if s in macSuites and
++ s in cipherSuites and s in keyExchangeSuites]
+
+ srpSuites = []
+ srpSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
+@@ -236,12 +260,22 @@ class CipherSuite:
+ certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
+ certSuites.append(TLS_RSA_WITH_RC4_128_SHA)
+ certSuites.append(TLS_RSA_WITH_RC4_128_MD5)
+- certAllSuites = srpCertSuites + certSuites
+
+ @staticmethod
+ def getCertSuites(settings):
+ return CipherSuite._filterSuites(CipherSuite.certSuites, settings)
+
++ dheCertSuites = []
++ dheCertSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
++ dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
++ dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
++
++ @staticmethod
++ def getDheCertSuites(settings):
++ return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings)
++
++ certAllSuites = srpCertSuites + certSuites + dheCertSuites
++
+ anonSuites = []
+ anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
+ anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
+@@ -250,6 +284,8 @@ class CipherSuite:
+ def getAnonSuites(settings):
+ return CipherSuite._filterSuites(CipherSuite.anonSuites, settings)
+
++ dhAllSuites = dheCertSuites + anonSuites
++
+ @staticmethod
+ def canonicalCipherName(ciphersuite):
+ "Return the canonical name of the cipher whose number is provided."
+diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
+index 7a38ee2..35c8b0e 100644
+--- a/third_party/tlslite/tlslite/handshakesettings.py
++++ b/third_party/tlslite/tlslite/handshakesettings.py
+@@ -14,6 +14,7 @@ from .utils import cipherfactory
+ # issues such as timing attacks
+ CIPHER_NAMES = ["rc4", "aes256", "aes128", "3des"]
+ MAC_NAMES = ["sha"] # "md5" is allowed
++KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
+ CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
+ CERTIFICATE_TYPES = ["x509"]
+
+@@ -100,6 +101,7 @@ class HandshakeSettings(object):
+ def __init__(self):
+ self.minKeySize = 1023
+ self.maxKeySize = 8193
++ self.keyExchangeNames = KEY_EXCHANGE_NAMES
+ self.cipherNames = CIPHER_NAMES
+ self.macNames = MAC_NAMES
+ self.cipherImplementations = CIPHER_IMPLEMENTATIONS
+@@ -114,6 +116,7 @@ class HandshakeSettings(object):
+ other = HandshakeSettings()
+ other.minKeySize = self.minKeySize
+ other.maxKeySize = self.maxKeySize
++ other.keyExchangeNames = self.keyExchangeNames
+ other.cipherNames = self.cipherNames
+ other.macNames = self.macNames
+ other.cipherImplementations = self.cipherImplementations
+@@ -145,6 +148,9 @@ class HandshakeSettings(object):
+ raise ValueError("maxKeySize too small")
+ if other.maxKeySize>16384:
+ raise ValueError("maxKeySize too large")
++ for s in other.keyExchangeNames:
++ if s not in KEY_EXCHANGE_NAMES:
++ raise ValueError("Unknown key exchange name: '%s'" % s)
+ for s in other.cipherNames:
+ if s not in CIPHER_NAMES:
+ raise ValueError("Unknown cipher name: '%s'" % s)
+diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
+index 532d86b..550b387 100644
+--- a/third_party/tlslite/tlslite/messages.py
++++ b/third_party/tlslite/tlslite/messages.py
+@@ -533,31 +533,31 @@ class ServerKeyExchange(HandshakeMsg):
+ p.stopLengthCheck()
+ return self
+
+- def write(self):
++ def write_params(self):
+ w = Writer()
+ if self.cipherSuite in CipherSuite.srpAllSuites:
+ w.addVarSeq(numberToByteArray(self.srp_N), 1, 2)
+ w.addVarSeq(numberToByteArray(self.srp_g), 1, 2)
+ w.addVarSeq(self.srp_s, 1, 1)
+ w.addVarSeq(numberToByteArray(self.srp_B), 1, 2)
+- if self.cipherSuite in CipherSuite.srpCertSuites:
+- w.addVarSeq(self.signature, 1, 2)
+- elif self.cipherSuite in CipherSuite.anonSuites:
++ elif self.cipherSuite in CipherSuite.dhAllSuites:
+ w.addVarSeq(numberToByteArray(self.dh_p), 1, 2)
+ w.addVarSeq(numberToByteArray(self.dh_g), 1, 2)
+ w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2)
+- if self.cipherSuite in []: # TODO support for signed_params
+- w.addVarSeq(self.signature, 1, 2)
++ else:
++ assert(False)
++ return w.bytes
++
++ def write(self):
++ w = Writer()
++ w.bytes += self.write_params()
++ if self.cipherSuite in CipherSuite.certAllSuites:
++ w.addVarSeq(self.signature, 1, 2)
+ return self.postWrite(w)
+
+ def hash(self, clientRandom, serverRandom):
+- oldCipherSuite = self.cipherSuite
+- self.cipherSuite = None
+- try:
+- bytes = clientRandom + serverRandom + self.write()[4:]
+- return MD5(bytes) + SHA1(bytes)
+- finally:
+- self.cipherSuite = oldCipherSuite
++ bytes = clientRandom + serverRandom + self.write_params()
++ return MD5(bytes) + SHA1(bytes)
+
+ class ServerHelloDone(HandshakeMsg):
+ def __init__(self):
+@@ -607,7 +607,7 @@ class ClientKeyExchange(HandshakeMsg):
+ p.getFixBytes(len(p.bytes)-p.index)
+ else:
+ raise AssertionError()
+- elif self.cipherSuite in CipherSuite.anonSuites:
++ elif self.cipherSuite in CipherSuite.dhAllSuites:
+ self.dh_Yc = bytesToNumber(p.getVarBytes(2))
+ else:
+ raise AssertionError()
+diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
+index 20cd85b..07ee862 100644
+--- a/third_party/tlslite/tlslite/tlsconnection.py
++++ b/third_party/tlslite/tlslite/tlsconnection.py
+@@ -24,6 +24,78 @@ from .handshakesettings import HandshakeSettings
+ from .utils.tackwrapper import *
+
+
++class KeyExchange(object):
++ def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
++ self.cipherSuite = cipherSuite
++ self.clientHello = clientHello
++ self.serverHello = serverHello
++ self.privateKey = privateKey
++
++ def makeServerKeyExchange():
++ raise NotImplementedError()
++ def processClientKeyExchange(clientKeyExchange):
++ raise NotImplementedError()
++
++
++class RSAKeyExchange(KeyExchange):
++ def makeServerKeyExchange(self):
++ return None
++
++ def processClientKeyExchange(self, clientKeyExchange):
++ premasterSecret = self.privateKey.decrypt(\
++ clientKeyExchange.encryptedPreMasterSecret)
++
++ # On decryption failure randomize premaster secret to avoid
++ # Bleichenbacher's "million message" attack
++ randomPreMasterSecret = getRandomBytes(48)
++ versionCheck = (premasterSecret[0], premasterSecret[1])
++ if not premasterSecret:
++ premasterSecret = randomPreMasterSecret
++ elif len(premasterSecret)!=48:
++ premasterSecret = randomPreMasterSecret
++ elif versionCheck != self.clientHello.client_version:
++ #Tolerate buggy IE clients
++ if versionCheck != self.serverHello.server_version:
++ premasterSecret = randomPreMasterSecret
++ return premasterSecret
++
++class DHE_RSAKeyExchange(KeyExchange):
++ # Generated with openssl dhparam 1024 -text. Generating a new one each time
++ # in Python is far far far too slow.
++ dh_p = bytesToNumber(
++ bytearray(
++ "\x00\x88\xc4\xdc\x2a\xd9\xba\x8d\x24\x69\x7f\xe4\xd4\xeb\x62"
++ "\x04\x43\xe8\x31\x08\x30\xa8\xe4\x24\x0f\xa7\xc3\xff\x84\x52"
++ "\x44\x4a\x1b\x8c\x88\x16\xa6\x17\x90\xac\x21\x34\xfb\xc5\xff"
++ "\x90\x46\x32\x29\xfa\x9d\xd3\x36\x05\xc2\x86\xcf\xde\x77\x68"
++ "\x4c\xe3\xb0\x34\x55\xce\x27\x85\x46\x94\xad\x0c\xef\x11\x53"
++ "\x61\x50\x0c\x3e\x7b\x8a\x3c\xa0\x52\x6c\xb2\xa5\x84\xf7\xa9"
++ "\xdc\x9d\x57\x60\xd0\x89\xc6\x14\x39\x54\xce\x20\xcc\x2d\xe9"
++ "\x90\xeb\xe7\x42\xf1\x03\x60\x5b\x06\x2f\x51\x97\x01\xc2\x1d"
++ "\xfa\xb3\xfe\x02\x4b\xee\xd1\x65\xcb"))
++ dh_g = 2
++
++ def makeServerKeyExchange(self):
++ self.dh_Xs = bytesToNumber(getRandomBytes(1024 / 8))
++ dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p)
++
++ serverKeyExchange = ServerKeyExchange(self.cipherSuite)
++ serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
++ serverKeyExchange.signature = self.privateKey.sign(
++ serverKeyExchange.hash(self.clientHello.random,
++ self.serverHello.random))
++ return serverKeyExchange
++
++ def processClientKeyExchange(self, clientKeyExchange):
++ dh_Yc = clientKeyExchange.dh_Yc
++
++ if dh_Yc % self.dh_p == 0:
++ raise TLSLocalAlert(AlertDescription.illegal_parameter,
++ "Suspicious dh_Yc value")
++
++ S = powMod(dh_Yc, self.dh_Xs, self.dh_p)
++ return numberToByteArray(S)
++
+ class TLSConnection(TLSRecordLayer):
+ """
+ This class wraps a socket and provides TLS handshaking and data
+@@ -500,6 +572,8 @@ class TLSConnection(TLSRecordLayer):
+ cipherSuites += CipherSuite.getSrpAllSuites(settings)
+ elif certParams:
+ cipherSuites += CipherSuite.getCertSuites(settings)
++ # Client DHE_RSA not supported.
++ # cipherSuites += CipherSuite.getDheCertSuites(settings)
+ elif anonParams:
+ cipherSuites += CipherSuite.getAnonSuites(settings)
+ else:
+@@ -1205,9 +1279,22 @@ class TLSConnection(TLSRecordLayer):
+ premasterSecret = result
+
+ # Perform the RSA key exchange
+- elif cipherSuite in CipherSuite.certSuites:
++ elif (cipherSuite in CipherSuite.certSuites or
++ cipherSuite in CipherSuite.dheCertSuites):
++ if cipherSuite in CipherSuite.certSuites:
++ keyExchange = RSAKeyExchange(cipherSuite,
++ clientHello,
++ serverHello,
++ privateKey)
++ elif cipherSuite in CipherSuite.dheCertSuites:
++ keyExchange = DHE_RSAKeyExchange(cipherSuite,
++ clientHello,
++ serverHello,
++ privateKey)
++ else:
++ assert(False)
+ for result in self._serverCertKeyExchange(clientHello, serverHello,
+- certChain, privateKey,
++ certChain, keyExchange,
+ reqCert, reqCAs, cipherSuite,
+ settings, ocspResponse):
+ if result in (0,1): yield result
+@@ -1268,6 +1355,7 @@ class TLSConnection(TLSRecordLayer):
+ cipherSuites += CipherSuite.getSrpSuites(settings)
+ elif certChain:
+ cipherSuites += CipherSuite.getCertSuites(settings)
++ cipherSuites += CipherSuite.getDheCertSuites(settings)
+ elif anon:
+ cipherSuites += CipherSuite.getAnonSuites(settings)
+ else:
+@@ -1483,7 +1571,7 @@ class TLSConnection(TLSRecordLayer):
+
+
+ def _serverCertKeyExchange(self, clientHello, serverHello,
+- serverCertChain, privateKey,
++ serverCertChain, keyExchange,
+ reqCert, reqCAs, cipherSuite,
+ settings, ocspResponse):
+ #Send ServerHello, Certificate[, CertificateRequest],
+@@ -1497,6 +1585,9 @@ class TLSConnection(TLSRecordLayer):
+ msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
+ if serverHello.status_request:
+ msgs.append(CertificateStatus().create(ocspResponse))
++ serverKeyExchange = keyExchange.makeServerKeyExchange()
++ if serverKeyExchange is not None:
++ msgs.append(serverKeyExchange)
+ if reqCert and reqCAs:
+ msgs.append(CertificateRequest().create(\
+ [ClientCertificateType.rsa_sign], reqCAs))
+@@ -1555,21 +1646,13 @@ class TLSConnection(TLSRecordLayer):
+ else: break
+ clientKeyExchange = result
+
+- #Decrypt ClientKeyExchange
+- premasterSecret = privateKey.decrypt(\
+- clientKeyExchange.encryptedPreMasterSecret)
+-
+- # On decryption failure randomize premaster secret to avoid
+- # Bleichenbacher's "million message" attack
+- randomPreMasterSecret = getRandomBytes(48)
+- versionCheck = (premasterSecret[0], premasterSecret[1])
+- if not premasterSecret:
+- premasterSecret = randomPreMasterSecret
+- elif len(premasterSecret)!=48:
+- premasterSecret = randomPreMasterSecret
+- elif versionCheck != clientHello.client_version:
+- if versionCheck != self.version: #Tolerate buggy IE clients
+- premasterSecret = randomPreMasterSecret
++ #Process ClientKeyExchange
++ try:
++ premasterSecret = \
++ keyExchange.processClientKeyExchange(clientKeyExchange)
++ except TLSLocalAlert, e:
++ for result in self._sendError(alert.description, alert.message):
++ yield result
+
+ #Get and check CertificateVerify, if relevant
+ if clientCertChain:

Powered by Google App Engine
This is Rietveld 408576698