| diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py |
| index 1a1ace9..d2d50c5 100644 |
| --- a/third_party/tlslite/tlslite/constants.py |
| +++ b/third_party/tlslite/tlslite/constants.py |
| @@ -54,6 +54,20 @@ class ExtensionType: # RFC 6066 / 4366 |
| tack = 0xF300 |
| supports_npn = 13172 |
| channel_id = 30032 |
| + |
| +class HashAlgorithm: |
| + none = 0 |
| + md5 = 1 |
| + sha1 = 2 |
| + sha224 = 3 |
| + sha256 = 4 |
| + sha384 = 5 |
| + |
| +class SignatureAlgorithm: |
| + anonymous = 0 |
| + rsa = 1 |
| + dsa = 2 |
| + ecdsa = 3 |
| |
| class NameType: |
| host_name = 0 |
| @@ -144,30 +158,42 @@ 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 |
| |
| TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C |
| TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D |
| |
| + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067 |
| + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B |
| + |
| tripleDESSuites = [] |
| 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) |
| aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256) |
| + aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) |
| |
| 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_DH_ANON_WITH_AES_256_CBC_SHA) |
| + aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA) |
| aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256) |
| + aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) |
| |
| rc4Suites = [] |
| rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA) |
| @@ -184,12 +210,18 @@ 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) |
| |
| sha256Suites = [] |
| sha256Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256) |
| sha256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA256) |
| + sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) |
| + sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) |
| + |
| |
| md5Suites = [] |
| md5Suites.append(TLS_RSA_WITH_RC4_128_MD5) |
| @@ -198,6 +230,7 @@ class CipherSuite: |
| def _filterSuites(suites, settings): |
| macNames = settings.macNames |
| cipherNames = settings.cipherNames |
| + keyExchangeNames = settings.keyExchangeNames |
| macSuites = [] |
| if "sha" in macNames: |
| macSuites += CipherSuite.shaSuites |
| @@ -216,7 +249,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_AES_256_CBC_SHA) |
| @@ -250,12 +296,24 @@ class CipherSuite: |
| certSuites.append(TLS_RSA_WITH_3DES_EDE_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_AES_256_CBC_SHA256) |
| + dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) |
| + dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA) |
| + dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA) |
| + dheCertSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) |
| + |
| + @staticmethod |
| + def getDheCertSuites(settings): |
| + return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings) |
| + |
| + certAllSuites = srpCertSuites + certSuites + dheCertSuites |
| + |
| anonSuites = [] |
| anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA) |
| anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA) |
| @@ -264,6 +322,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 ee37c30..7998e2e 100644 |
| --- a/third_party/tlslite/tlslite/handshakesettings.py |
| +++ b/third_party/tlslite/tlslite/handshakesettings.py |
| @@ -14,7 +14,9 @@ from .utils import cipherfactory |
| # RC4 is preferred as faster in Python, works in SSL3, and immune to CBC |
| # issues such as timing attacks |
| CIPHER_NAMES = ["rc4", "aes256", "aes128", "3des"] |
| -MAC_NAMES = ["sha", "sha256"] # "md5" is allowed |
| +MAC_NAMES = ["sha", "sha256"] # Don't allow "md5" by default. |
| +ALL_MAC_NAMES = ["sha", "sha256", "md5"] |
| +KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"] |
| CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"] |
| CERTIFICATE_TYPES = ["x509"] |
| |
| @@ -101,6 +103,7 @@ class HandshakeSettings(object): |
| self.maxKeySize = 8193 |
| self.cipherNames = CIPHER_NAMES |
| self.macNames = MAC_NAMES |
| + self.keyExchangeNames = KEY_EXCHANGE_NAMES |
| self.cipherImplementations = CIPHER_IMPLEMENTATIONS |
| self.certificateTypes = CERTIFICATE_TYPES |
| self.minVersion = (3,1) |
| @@ -115,6 +118,7 @@ class HandshakeSettings(object): |
| other.maxKeySize = self.maxKeySize |
| other.cipherNames = self.cipherNames |
| other.macNames = self.macNames |
| + other.keyExchangeNames = self.keyExchangeNames |
| other.cipherImplementations = self.cipherImplementations |
| other.certificateTypes = self.certificateTypes |
| other.minVersion = self.minVersion |
| @@ -147,6 +151,12 @@ class HandshakeSettings(object): |
| for s in other.cipherNames: |
| if s not in CIPHER_NAMES: |
| raise ValueError("Unknown cipher name: '%s'" % s) |
| + for s in other.macNames: |
| + if s not in ALL_MAC_NAMES: |
| + raise ValueError("Unknown MAC name: '%s'" % s) |
| + for s in other.keyExchangeNames: |
| + if s not in KEY_EXCHANGE_NAMES: |
| + raise ValueError("Unknown key exchange name: '%s'" % s) |
| for s in other.cipherImplementations: |
| if s not in CIPHER_IMPLEMENTATIONS: |
| raise ValueError("Unknown cipher implementation: '%s'" % s) |
| diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py |
| index 9a8e5f6..8b77ee6 100644 |
| --- a/third_party/tlslite/tlslite/messages.py |
| +++ b/third_party/tlslite/tlslite/messages.py |
| @@ -500,9 +500,10 @@ class CertificateRequest(HandshakeMsg): |
| return self.postWrite(w) |
| |
| class ServerKeyExchange(HandshakeMsg): |
| - def __init__(self, cipherSuite): |
| + def __init__(self, cipherSuite, version): |
| HandshakeMsg.__init__(self, HandshakeType.server_key_exchange) |
| self.cipherSuite = cipherSuite |
| + self.version = version |
| self.srp_N = 0 |
| self.srp_g = 0 |
| self.srp_s = bytearray(0) |
| @@ -542,31 +543,38 @@ 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: |
| + if self.version >= (3,3): |
| + # TODO: Signature algorithm negotiation not supported. |
| + w.add(HashAlgorithm.sha1, 1) |
| + w.add(SignatureAlgorithm.rsa, 1) |
| + 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() |
| + if self.version >= (3,3): |
| + # TODO: Signature algorithm negotiation not supported. |
| + return SHA1(bytes) |
| + return MD5(bytes) + SHA1(bytes) |
| |
| class ServerHelloDone(HandshakeMsg): |
| def __init__(self): |
| @@ -616,7 +624,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 5d508ed..f6d13d4 100644 |
| --- a/third_party/tlslite/tlslite/tlsconnection.py |
| +++ b/third_party/tlslite/tlslite/tlsconnection.py |
| @@ -23,7 +23,109 @@ from .messages import * |
| from .mathtls import * |
| from .handshakesettings import HandshakeSettings |
| from .utils.tackwrapper import * |
| +from .utils.rsakey import RSAKey |
| |
| +class KeyExchange(object): |
| + def __init__(self, cipherSuite, clientHello, serverHello, privateKey): |
| + """ |
| + Initializes the KeyExchange. privateKey is the signing private key. |
| + """ |
| + self.cipherSuite = cipherSuite |
| + self.clientHello = clientHello |
| + self.serverHello = serverHello |
| + self.privateKey = privateKey |
| + |
| + def makeServerKeyExchange(): |
| + """ |
| + Returns a ServerKeyExchange object for the server's initial leg in the |
| + handshake. If the key exchange method does not send ServerKeyExchange |
| + (e.g. RSA), it returns None. |
| + """ |
| + raise NotImplementedError() |
| + |
| + def processClientKeyExchange(clientKeyExchange): |
| + """ |
| + Processes the client's ClientKeyExchange message and returns the |
| + premaster secret. Raises TLSLocalAlert on error. |
| + """ |
| + 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) |
| + if not premasterSecret: |
| + premasterSecret = randomPreMasterSecret |
| + elif len(premasterSecret)!=48: |
| + premasterSecret = randomPreMasterSecret |
| + else: |
| + versionCheck = (premasterSecret[0], premasterSecret[1]) |
| + if versionCheck != self.clientHello.client_version: |
| + #Tolerate buggy IE clients |
| + if versionCheck != self.serverHello.server_version: |
| + premasterSecret = randomPreMasterSecret |
| + return premasterSecret |
| + |
| +def _hexStringToNumber(s): |
| + s = s.replace(" ", "").replace("\n", "") |
| + if len(s) % 2 != 0: |
| + raise ValueError("Length is not even") |
| + return bytesToNumber(bytearray(s.decode("hex"))) |
| + |
| +class DHE_RSAKeyExchange(KeyExchange): |
| + # 2048-bit MODP Group (RFC 3526, Section 3) |
| + dh_p = _hexStringToNumber(""" |
| +FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 |
| +29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD |
| +EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 |
| +E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED |
| +EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D |
| +C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F |
| +83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D |
| +670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B |
| +E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 |
| +DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 |
| +15728E5A 8AACAA68 FFFFFFFF FFFFFFFF""") |
| + dh_g = 2 |
| + |
| + # RFC 3526, Section 8. |
| + strength = 160 |
| + |
| + def makeServerKeyExchange(self): |
| + # Per RFC 3526, Section 1, the exponent should have double the entropy |
| + # of the strength of the curve. |
| + self.dh_Xs = bytesToNumber(getRandomBytes(self.strength * 2 / 8)) |
| + dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p) |
| + |
| + version = self.serverHello.server_version |
| + serverKeyExchange = ServerKeyExchange(self.cipherSuite, version) |
| + serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys) |
| + hashBytes = serverKeyExchange.hash(self.clientHello.random, |
| + self.serverHello.random) |
| + if version >= (3,3): |
| + # TODO: Signature algorithm negotiation not supported. |
| + hashBytes = RSAKey.addPKCS1SHA1Prefix(hashBytes) |
| + serverKeyExchange.signature = self.privateKey.sign(hashBytes) |
| + return serverKeyExchange |
| + |
| + def processClientKeyExchange(self, clientKeyExchange): |
| + dh_Yc = clientKeyExchange.dh_Yc |
| + |
| + # First half of RFC 2631, Section 2.1.5. Validate the client's public |
| + # key. |
| + if not 2 <= dh_Yc <= self.dh_p - 1: |
| + raise TLSLocalAlert(AlertDescription.illegal_parameter, |
| + "Invalid dh_Yc value") |
| + |
| + S = powMod(dh_Yc, self.dh_Xs, self.dh_p) |
| + return numberToByteArray(S) |
| |
| class TLSConnection(TLSRecordLayer): |
| """ |
| @@ -500,6 +602,8 @@ class TLSConnection(TLSRecordLayer): |
| if srpParams: |
| cipherSuites += CipherSuite.getSrpAllSuites(settings) |
| elif certParams: |
| + # TODO: Client DHE_RSA not supported. |
| + # cipherSuites += CipherSuite.getDheCertSuites(settings) |
| cipherSuites += CipherSuite.getCertSuites(settings) |
| elif anonParams: |
| cipherSuites += CipherSuite.getAnonSuites(settings) |
| @@ -1207,10 +1311,23 @@ class TLSConnection(TLSRecordLayer): |
| else: break |
| premasterSecret = result |
| |
| - # Perform the RSA key exchange |
| - elif cipherSuite in CipherSuite.certSuites: |
| + # Perform the RSA or DHE_RSA key exchange |
| + 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 |
| @@ -1270,6 +1387,7 @@ class TLSConnection(TLSRecordLayer): |
| CipherSuite.getSrpCertSuites(settings) |
| cipherSuites += CipherSuite.getSrpSuites(settings) |
| elif certChain: |
| + cipherSuites += CipherSuite.getDheCertSuites(settings) |
| cipherSuites += CipherSuite.getCertSuites(settings) |
| elif anon: |
| cipherSuites += CipherSuite.getAnonSuites(settings) |
| @@ -1440,7 +1558,7 @@ class TLSConnection(TLSRecordLayer): |
| B = (powMod(g, b, N) + (k*v)) % N |
| |
| #Create ServerKeyExchange, signing it if necessary |
| - serverKeyExchange = ServerKeyExchange(cipherSuite) |
| + serverKeyExchange = ServerKeyExchange(cipherSuite, self.version) |
| serverKeyExchange.createSRP(N, g, s, B) |
| if cipherSuite in CipherSuite.srpCertSuites: |
| hashBytes = serverKeyExchange.hash(clientHello.random, |
| @@ -1488,11 +1606,11 @@ class TLSConnection(TLSRecordLayer): |
| |
| |
| def _serverCertKeyExchange(self, clientHello, serverHello, |
| - serverCertChain, privateKey, |
| + serverCertChain, keyExchange, |
| reqCert, reqCAs, cipherSuite, |
| settings, ocspResponse): |
| - #Send ServerHello, Certificate[, CertificateRequest], |
| - #ServerHelloDone |
| + #Send ServerHello, Certificate[, ServerKeyExchange] |
| + #[, CertificateRequest], ServerHelloDone |
| msgs = [] |
| |
| # If we verify a client cert chain, return it |
| @@ -1502,6 +1620,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)) |
| @@ -1560,21 +1681,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, alert: |
| + for result in self._sendError(alert.description, alert.message): |
| + yield result |
| |
| #Get and check CertificateVerify, if relevant |
| if clientCertChain: |
| @@ -1622,7 +1735,7 @@ class TLSConnection(TLSRecordLayer): |
| dh_Ys = powMod(dh_g, dh_Xs, dh_p) |
| |
| #Create ServerKeyExchange |
| - serverKeyExchange = ServerKeyExchange(cipherSuite) |
| + serverKeyExchange = ServerKeyExchange(cipherSuite, self.version) |
| serverKeyExchange.createDH(dh_p, dh_g, dh_Ys) |
| |
| #Send ServerHello[, Certificate], ServerKeyExchange, |
| diff --git a/third_party/tlslite/tlslite/tlsrecordlayer.py b/third_party/tlslite/tlslite/tlsrecordlayer.py |
| index 01ff3e9..6ef3895 100644 |
| --- a/third_party/tlslite/tlslite/tlsrecordlayer.py |
| +++ b/third_party/tlslite/tlslite/tlsrecordlayer.py |
| @@ -796,7 +796,8 @@ class TLSRecordLayer(object): |
| elif subType == HandshakeType.certificate_verify: |
| yield CertificateVerify().parse(p) |
| elif subType == HandshakeType.server_key_exchange: |
| - yield ServerKeyExchange(constructorType).parse(p) |
| + yield ServerKeyExchange(constructorType, |
| + self.version).parse(p) |
| elif subType == HandshakeType.server_hello_done: |
| yield ServerHelloDone().parse(p) |
| elif subType == HandshakeType.client_key_exchange: |
| diff --git a/third_party/tlslite/tlslite/utils/rsakey.py b/third_party/tlslite/tlslite/utils/rsakey.py |
| index 3f2100e..fb022cc 100644 |
| --- a/third_party/tlslite/tlslite/utils/rsakey.py |
| +++ b/third_party/tlslite/tlslite/utils/rsakey.py |
| @@ -60,7 +60,7 @@ class RSAKey(object): |
| @return: A PKCS1-SHA1 signature on the passed-in data. |
| """ |
| hashBytes = SHA1(bytearray(bytes)) |
| - prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes) |
| + prefixedHashBytes = self.addPKCS1SHA1Prefix(hashBytes) |
| sigBytes = self.sign(prefixedHashBytes) |
| return sigBytes |
| |
| @@ -81,8 +81,8 @@ class RSAKey(object): |
| hashBytes = SHA1(bytearray(bytes)) |
| |
| # Try it with/without the embedded NULL |
| - prefixedHashBytes1 = self._addPKCS1SHA1Prefix(hashBytes, False) |
| - prefixedHashBytes2 = self._addPKCS1SHA1Prefix(hashBytes, True) |
| + prefixedHashBytes1 = self.addPKCS1SHA1Prefix(hashBytes, False) |
| + prefixedHashBytes2 = self.addPKCS1SHA1Prefix(hashBytes, True) |
| result1 = self.verify(sigBytes, prefixedHashBytes1) |
| result2 = self.verify(sigBytes, prefixedHashBytes2) |
| return (result1 or result2) |
| @@ -221,7 +221,8 @@ class RSAKey(object): |
| # Helper Functions for RSA Keys |
| # ************************************************************************** |
| |
| - def _addPKCS1SHA1Prefix(self, bytes, withNULL=True): |
| + @staticmethod |
| + def addPKCS1SHA1Prefix(bytes, withNULL=True): |
| # There is a long history of confusion over whether the SHA1 |
| # algorithmIdentifier should be encoded with a NULL parameter or |
| # with the parameter omitted. While the original intention was |
| @@ -229,8 +230,7 @@ class RSAKey(object): |
| # specifies the NULL should be included, and this behavior is also |
| # mandated in recent versions of PKCS #1, and is what tlslite has |
| # always implemented. Anyways, verification code should probably |
| - # accept both. However, nothing uses this code yet, so this is |
| - # all fairly moot. |
| + # accept both. |
| if not withNULL: |
| prefixBytes = bytearray(\ |
| [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14]) |