| 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:
|
|
|