diff options
Diffstat (limited to 'third_party')
-rw-r--r-- | third_party/boringssl/boringssl.gypi | 2 | ||||
-rw-r--r-- | third_party/boringssl/boringssl_tests.gypi | 34 | ||||
-rw-r--r-- | third_party/boringssl/boringssl_unittest.cc | 8 | ||||
-rw-r--r-- | third_party/boringssl/update_gypi_and_asm.py | 6 | ||||
-rw-r--r-- | third_party/tlslite/README.chromium | 3 | ||||
-rw-r--r-- | third_party/tlslite/patches/ecdhe_rsa.patch | 428 | ||||
-rw-r--r-- | third_party/tlslite/tlslite/constants.py | 45 | ||||
-rw-r--r-- | third_party/tlslite/tlslite/handshakesettings.py | 2 | ||||
-rw-r--r-- | third_party/tlslite/tlslite/messages.py | 18 | ||||
-rw-r--r-- | third_party/tlslite/tlslite/tlsconnection.py | 31 | ||||
-rw-r--r-- | third_party/tlslite/tlslite/utils/p256.py | 162 |
11 files changed, 717 insertions, 22 deletions
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi index d2fc5d4..01a4230 100644 --- a/third_party/boringssl/boringssl.gypi +++ b/third_party/boringssl/boringssl.gypi @@ -182,6 +182,8 @@ 'src/crypto/sha/sha512.c', 'src/crypto/stack/stack.c', 'src/crypto/thread.c', + 'src/crypto/thread_pthread.c', + 'src/crypto/thread_win.c', 'src/crypto/time_support.c', 'src/crypto/x509/a_digest.c', 'src/crypto/x509/a_sign.c', diff --git a/third_party/boringssl/boringssl_tests.gypi b/third_party/boringssl/boringssl_tests.gypi index 0373742..e1b606a 100644 --- a/third_party/boringssl/boringssl_tests.gypi +++ b/third_party/boringssl/boringssl_tests.gypi @@ -13,7 +13,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/base64/base64_test.c', + 'src/crypto/base64/base64_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -26,7 +26,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/bio/bio_test.c', + 'src/crypto/bio/bio_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -39,7 +39,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/bn/bn_test.c', + 'src/crypto/bn/bn_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -52,7 +52,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/bytestring/bytestring_test.c', + 'src/crypto/bytestring/bytestring_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -117,7 +117,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/digest/digest_test.c', + 'src/crypto/digest/digest_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -182,7 +182,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/err/err_test.c', + 'src/crypto/err/err_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -195,7 +195,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/evp/evp_test.c', + 'src/crypto/evp/evp_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -208,7 +208,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/evp/pbkdf_test.c', + 'src/crypto/evp/pbkdf_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -234,7 +234,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/crypto/hmac/hmac_test.c', + 'src/crypto/hmac/hmac_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -293,6 +293,19 @@ 'msvs_disabled_warnings': [ 4267, ], }, { + 'target_name': 'boringssl_thread_test', + 'type': 'executable', + 'dependencies': [ + 'boringssl.gyp:boringssl', + ], + 'sources': [ + 'src/crypto/thread_test.c', + ], + # TODO(davidben): Fix size_t truncations in BoringSSL. + # https://crbug.com/429039 + 'msvs_disabled_warnings': [ 4267, ], + }, + { 'target_name': 'boringssl_pkcs7_test', 'type': 'executable', 'dependencies': [ @@ -325,7 +338,7 @@ 'boringssl.gyp:boringssl', ], 'sources': [ - 'src/ssl/ssl_test.c', + 'src/ssl/ssl_test.cc', ], # TODO(davidben): Fix size_t truncations in BoringSSL. # https://crbug.com/429039 @@ -359,6 +372,7 @@ 'boringssl_pqueue_test', 'boringssl_rsa_test', 'boringssl_ssl_test', + 'boringssl_thread_test', ], } } diff --git a/third_party/boringssl/boringssl_unittest.cc b/third_party/boringssl/boringssl_unittest.cc index d568e33..52bac99 100644 --- a/third_party/boringssl/boringssl_unittest.cc +++ b/third_party/boringssl/boringssl_unittest.cc @@ -237,9 +237,13 @@ TEST(BoringSSL, PQueue) { } TEST(BoringSSL, HKDF) { - TestSimple("hkdf_test"); + TestSimple("hkdf_test"); } TEST(BoringSSL, PBKDF) { - TestSimple("pbkdf_test"); + TestSimple("pbkdf_test"); +} + +TEST(BoringSSL, Thread) { + TestSimple("thread_test"); } diff --git a/third_party/boringssl/update_gypi_and_asm.py b/third_party/boringssl/update_gypi_and_asm.py index 4112c4d..3c6b524 100644 --- a/third_party/boringssl/update_gypi_and_asm.py +++ b/third_party/boringssl/update_gypi_and_asm.py @@ -77,9 +77,11 @@ def FindCFiles(directory, filter_func): for (path, dirnames, filenames) in os.walk(directory): for filename in filenames: - if filename.endswith('.c') and filter_func(filename, False): - cfiles.append(os.path.join(path, filename)) + if not filename.endswith('.c') and not filename.endswith('.cc'): continue + if not filter_func(filename, False): + continue + cfiles.append(os.path.join(path, filename)) for (i, dirname) in enumerate(dirnames): if not filter_func(dirname, True): diff --git a/third_party/tlslite/README.chromium b/third_party/tlslite/README.chromium index c2084cd..4468a08 100644 --- a/third_party/tlslite/README.chromium +++ b/third_party/tlslite/README.chromium @@ -24,7 +24,7 @@ Local Modifications: - patches/ssl3_padding.patch: SSL3 requires minimal padding in CBC mode. - patches/fix_test_file.patch: Fix #! line in random test file to appease our presubmit checks. -- patches/dhe_rsa.patch: Implement DHE_RSA-based cipher suites. +- patches/dhe_rsa.patch: Implement DHE_RSA-based cipher suites on the server. - patches/req_cert_types.patch: Add a reqCertTypes parameter to populate the certificate_types field of CertificateRequest. Also fixes type errors. - patches/ignore_write_failure.patch: Don't invalidate sessions on write @@ -38,3 +38,4 @@ Local Modifications: unless >= TLS 1.2 is negotiated. - patches/alert_after_handshake.patch: Add an option to send a fatal alert immediately after the handshake completes. +- patches/ecdhe_rsa.patch: Implement ECDHE_RSA-based ciper suites on the server.
\ No newline at end of file diff --git a/third_party/tlslite/patches/ecdhe_rsa.patch b/third_party/tlslite/patches/ecdhe_rsa.patch new file mode 100644 index 0000000..054a07a0 --- /dev/null +++ b/third_party/tlslite/patches/ecdhe_rsa.patch @@ -0,0 +1,428 @@ +diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py +index e5b88af..6d78a20 100644 +--- a/third_party/tlslite/tlslite/constants.py ++++ b/third_party/tlslite/tlslite/constants.py +@@ -76,6 +76,14 @@ class SignatureAlgorithm: + class NameType: + host_name = 0 + ++class ECCurveType: ++ explicit_prime = 1 ++ explicit_char2 = 2 ++ named_curve = 3 ++ ++class NamedCurve: ++ secp256r1 = 23 ++ + class AlertLevel: + warning = 1 + fatal = 2 +@@ -178,11 +186,19 @@ class CipherSuite: + TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E + ++ TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xc011 ++ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xc012 ++ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xc013 ++ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xc014 ++ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xc027 ++ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f ++ + 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) ++ tripleDESSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) + + aes128Suites = [] + aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA) +@@ -192,6 +208,8 @@ class CipherSuite: + 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) ++ aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ++ aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) + + aes256Suites = [] + aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA) +@@ -201,14 +219,17 @@ class CipherSuite: + 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) ++ aes256Suites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) + + aes128GcmSuites = [] + aes128GcmSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256) + aes128GcmSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ++ aes128GcmSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) + + rc4Suites = [] + rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA) + rc4Suites.append(TLS_RSA_WITH_RC4_128_MD5) ++ rc4Suites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA) + + shaSuites = [] + shaSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) +@@ -226,6 +247,10 @@ class CipherSuite: + 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) ++ shaSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA) ++ shaSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ++ shaSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ++ shaSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) + + sha256Suites = [] + sha256Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256) +@@ -234,6 +259,9 @@ class CipherSuite: + sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) + sha256Suites.append(TLS_RSA_WITH_AES_128_GCM_SHA256) + sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ++ sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ++ sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ++ + + aeadSuites = aes128GcmSuites + +@@ -275,6 +303,8 @@ class CipherSuite: + keyExchangeSuites += CipherSuite.certSuites + if "dhe_rsa" in keyExchangeNames: + keyExchangeSuites += CipherSuite.dheCertSuites ++ if "ecdhe_rsa" in keyExchangeNames: ++ keyExchangeSuites += CipherSuite.ecdheCertSuites + if "srp_sha" in keyExchangeNames: + keyExchangeSuites += CipherSuite.srpSuites + if "srp_sha_rsa" in keyExchangeNames: +@@ -335,7 +365,19 @@ class CipherSuite: + def getDheCertSuites(settings, version=None): + return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings, version) + +- certAllSuites = srpCertSuites + certSuites + dheCertSuites ++ ecdheCertSuites = [] ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ++ ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA) ++ ++ @staticmethod ++ def getEcdheCertSuites(settings, version=None): ++ return CipherSuite._filterSuites(CipherSuite.ecdheCertSuites, settings, version) ++ ++ certAllSuites = srpCertSuites + certSuites + dheCertSuites + ecdheCertSuites + + anonSuites = [] + anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA) +@@ -346,6 +388,7 @@ class CipherSuite: + return CipherSuite._filterSuites(CipherSuite.anonSuites, settings, version) + + dhAllSuites = dheCertSuites + anonSuites ++ ecdhAllSuites = ecdheCertSuites + + @staticmethod + def canonicalCipherName(ciphersuite): +diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py +index e752834..605ed42 100644 +--- a/third_party/tlslite/tlslite/handshakesettings.py ++++ b/third_party/tlslite/tlslite/handshakesettings.py +@@ -14,7 +14,7 @@ from .utils import cipherfactory + CIPHER_NAMES = ["aes128gcm", "rc4", "aes256", "aes128", "3des"] + MAC_NAMES = ["sha", "sha256", "aead"] # Don't allow "md5" by default. + ALL_MAC_NAMES = MAC_NAMES + ["md5"] +-KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"] ++KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "ecdhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"] + CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"] + CERTIFICATE_TYPES = ["x509"] + TLS_INTOLERANCE_TYPES = ["alert", "close", "reset"] +diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py +index f2e2cfc..9aeff6d 100644 +--- a/third_party/tlslite/tlslite/messages.py ++++ b/third_party/tlslite/tlslite/messages.py +@@ -509,10 +509,13 @@ class ServerKeyExchange(HandshakeMsg): + self.srp_g = 0 + self.srp_s = bytearray(0) + self.srp_B = 0 +- # Anon DH params: ++ # DH params: + self.dh_p = 0 + self.dh_g = 0 + self.dh_Ys = 0 ++ # ECDH params: ++ self.ecdhCurve = 0 ++ self.ecdhPublic = bytearray(0) + self.signature = bytearray(0) + + def createSRP(self, srp_N, srp_g, srp_s, srp_B): +@@ -528,6 +531,11 @@ class ServerKeyExchange(HandshakeMsg): + self.dh_Ys = dh_Ys + return self + ++ def createECDH(self, ecdhCurve, ecdhPublic): ++ self.ecdhCurve = ecdhCurve ++ self.ecdhPublic = ecdhPublic ++ return self ++ + def parse(self, p): + p.startLengthCheck(3) + if self.cipherSuite in CipherSuite.srpAllSuites: +@@ -555,6 +563,10 @@ class ServerKeyExchange(HandshakeMsg): + w.addVarSeq(numberToByteArray(self.dh_p), 1, 2) + w.addVarSeq(numberToByteArray(self.dh_g), 1, 2) + w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2) ++ elif self.cipherSuite in CipherSuite.ecdhAllSuites: ++ w.add(ECCurveType.named_curve, 1) ++ w.add(self.ecdhCurve, 2) ++ w.addVarSeq(self.ecdhPublic, 1, 1) + else: + assert(False) + return w.bytes +@@ -626,7 +638,9 @@ class ClientKeyExchange(HandshakeMsg): + else: + raise AssertionError() + elif self.cipherSuite in CipherSuite.dhAllSuites: +- self.dh_Yc = bytesToNumber(p.getVarBytes(2)) ++ self.dh_Yc = bytesToNumber(p.getVarBytes(2)) ++ elif self.cipherSuite in CipherSuite.ecdhAllSuites: ++ self.ecdh_Yc = p.getVarBytes(1) + else: + raise AssertionError() + p.stopLengthCheck() +diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py +index 0a85d3c..dfac274 100644 +--- a/third_party/tlslite/tlslite/tlsconnection.py ++++ b/third_party/tlslite/tlslite/tlsconnection.py +@@ -24,6 +24,7 @@ from .mathtls import * + from .handshakesettings import HandshakeSettings + from .utils.tackwrapper import * + from .utils.rsakey import RSAKey ++from .utils import p256 + + class KeyExchange(object): + def __init__(self, cipherSuite, clientHello, serverHello, privateKey): +@@ -127,6 +128,25 @@ DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 + S = powMod(dh_Yc, self.dh_Xs, self.dh_p) + return numberToByteArray(S) + ++class ECDHE_RSAKeyExchange(KeyExchange): ++ def makeServerKeyExchange(self): ++ public, self.private = p256.generatePublicPrivate() ++ ++ version = self.serverHello.server_version ++ serverKeyExchange = ServerKeyExchange(self.cipherSuite, version) ++ serverKeyExchange.createECDH(NamedCurve.secp256r1, bytearray(public)) ++ 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): ++ ecdh_Yc = clientKeyExchange.ecdh_Yc ++ return bytearray(p256.generateSharedValue(bytes(ecdh_Yc), self.private)) ++ + class TLSConnection(TLSRecordLayer): + """ + This class wraps a socket and provides TLS handshaking and data +@@ -1321,9 +1341,8 @@ class TLSConnection(TLSRecordLayer): + else: break + premasterSecret = result + +- # Perform the RSA or DHE_RSA key exchange +- elif (cipherSuite in CipherSuite.certSuites or +- cipherSuite in CipherSuite.dheCertSuites): ++ # Perform a certificate-based key exchange ++ elif cipherSuite in CipherSuite.certAllSuites: + if cipherSuite in CipherSuite.certSuites: + keyExchange = RSAKeyExchange(cipherSuite, + clientHello, +@@ -1334,6 +1353,11 @@ class TLSConnection(TLSRecordLayer): + clientHello, + serverHello, + privateKey) ++ elif cipherSuite in CipherSuite.ecdheCertSuites: ++ keyExchange = ECDHE_RSAKeyExchange(cipherSuite, ++ clientHello, ++ serverHello, ++ privateKey) + else: + assert(False) + for result in self._serverCertKeyExchange(clientHello, serverHello, +@@ -1450,6 +1474,7 @@ class TLSConnection(TLSRecordLayer): + CipherSuite.getSrpCertSuites(settings, self.version) + cipherSuites += CipherSuite.getSrpSuites(settings, self.version) + elif certChain: ++ cipherSuites += CipherSuite.getEcdheCertSuites(settings, self.version) + cipherSuites += CipherSuite.getDheCertSuites(settings, self.version) + cipherSuites += CipherSuite.getCertSuites(settings, self.version) + elif anon: +diff --git a/third_party/tlslite/tlslite/utils/p256.py b/third_party/tlslite/tlslite/utils/p256.py +index e69de29..6eb9a77 100644 +--- a/third_party/tlslite/tlslite/utils/p256.py ++++ b/third_party/tlslite/tlslite/utils/p256.py +@@ -0,0 +1,162 @@ ++# Author: Google ++# See the LICENSE file for legal information regarding use of this file. ++ ++import os ++ ++p = ( ++ 115792089210356248762697446949407573530086143415290314195533631308867097853951) ++order = ( ++ 115792089210356248762697446949407573529996955224135760342422259061068512044369) ++p256B = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b ++ ++baseX = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 ++baseY = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 ++basePoint = (baseX, baseY) ++ ++ ++def _pointAdd(a, b): ++ Z1Z1 = (a[2] * a[2]) % p ++ Z2Z2 = (b[2] * b[2]) % p ++ U1 = (a[0] * Z2Z2) % p ++ U2 = (b[0] * Z1Z1) % p ++ S1 = (a[1] * b[2] * Z2Z2) % p ++ S2 = (b[1] * a[2] * Z1Z1) % p ++ if U1 == U2 and S1 == S2: ++ return pointDouble(a) ++ H = (U2 - U1) % p ++ I = (4 * H * H) % p ++ J = (H * I) % p ++ r = (2 * (S2 - S1)) % p ++ V = (U1 * I) % p ++ X3 = (r * r - J - 2 * V) % p ++ Y3 = (r * (V - X3) - 2 * S1 * J) % p ++ Z3 = (((a[2] + b[2]) * (a[2] + b[2]) - Z1Z1 - Z2Z2) * H) % p ++ ++ return (X3, Y3, Z3) ++ ++ ++def _pointDouble(a): ++ delta = (a[2] * a[2]) % p ++ gamma = (a[1] * a[1]) % p ++ beta = (a[0] * gamma) % p ++ alpha = (3 * (a[0] - delta) * (a[0] + delta)) % p ++ X3 = (alpha * alpha - 8 * beta) % p ++ Z3 = ((a[1] + a[2]) * (a[1] + a[2]) - gamma - delta) % p ++ Y3 = (alpha * (4 * beta - X3) - 8 * gamma * gamma) % p ++ ++ return (X3, Y3, Z3) ++ ++ ++def _square(n): ++ return (n * n) ++ ++ ++def _modpow(a, n, p): ++ if n == 0: ++ return 1 ++ if n == 1: ++ return a ++ r = _square(_modpow(a, n >> 1, p)) % p ++ if n & 1 == 1: ++ r = (r * a) % p ++ return r ++ ++ ++def _scalarMult(k, point): ++ accum = (0, 0, 0) ++ accumIsInfinity = True ++ jacobianPoint = (point[0], point[1], 1) ++ ++ for bit in range(255, -1, -1): ++ if not accumIsInfinity: ++ accum = _pointDouble(accum) ++ ++ if (k >> bit) & 1 == 1: ++ if accumIsInfinity: ++ accum = jacobianPoint ++ accumIsInfinity = False ++ else: ++ accum = _pointAdd(accum, jacobianPoint) ++ ++ if accumIsInfinity: ++ return (0, 0) ++ ++ zInv = _modpow(accum[2], p - 2, p) ++ return ((accum[0] * zInv * zInv) % p, (accum[1] * zInv * zInv * zInv) % p) ++ ++ ++def _scalarBaseMult(k): ++ return _scalarMult(k, basePoint) ++ ++ ++def _decodeBigEndian(b): ++ return sum([ord(b[len(b) - i - 1]) << 8 * i for i in range(len(b))]) ++ ++ ++def _encodeBigEndian(n): ++ b = [] ++ while n != 0: ++ b.append(chr(n & 0xff)) ++ n >>= 8 ++ ++ if len(b) == 0: ++ b.append(0) ++ b.reverse() ++ ++ return "".join(b) ++ ++ ++def _zeroPad(b, length): ++ if len(b) < length: ++ return ("\x00" * (length - len(b))) + b ++ return b ++ ++ ++def _encodePoint(point): ++ x = point[0] ++ y = point[1] ++ if (y * y) % p != (x * x * x - 3 * x + p256B) % p: ++ raise "point not on curve" ++ return "\x04" + _zeroPad(_encodeBigEndian(point[0]), 32) + _zeroPad( ++ _encodeBigEndian(point[1]), 32) ++ ++ ++def _decodePoint(b): ++ if len(b) != 1 + 32 + 32 or ord(b[0]) != 4: ++ raise "invalid encoded ec point" ++ x = _decodeBigEndian(b[1:33]) ++ y = _decodeBigEndian(b[33:65]) ++ if (y * y) % p != (x * x * x - 3 * x + p256B) % p: ++ raise "point not on curve" ++ return (x, y) ++ ++ ++def generatePublicPrivate(): ++ """generatePublicPrivate returns a tuple of (X9.62 encoded public point, ++ private value), where the private value is generated from os.urandom.""" ++ private = _decodeBigEndian(os.urandom(40)) % order ++ return _encodePoint(_scalarBaseMult(private)), private ++ ++ ++def generateSharedValue(theirPublic, private): ++ """generateSharedValue returns the encoded x-coordinate of the ++ multiplication of a peer's X9.62 encoded point and a private value.""" ++ return _zeroPad( ++ _encodeBigEndian(_scalarMult(private, _decodePoint(theirPublic))[0]), ++ 32) ++ ++if __name__ == "__main__": ++ alice, alicePrivate = generatePublicPrivate() ++ bob, bobPrivate = generatePublicPrivate() ++ ++ if generateSharedValue(alice, bobPrivate) != generateSharedValue( ++ bob, alicePrivate): ++ raise "simple DH test failed" ++ ++ (x, _) = _scalarBaseMult(1) ++ ++ for i in range(1000): ++ (x, _) = _scalarBaseMult(x) ++ ++ if x != 2428281965257598569040586318034812501729437946720808289049534492833635302706: ++ raise "loop test failed" diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py index e5b88af..6d78a20 100644 --- a/third_party/tlslite/tlslite/constants.py +++ b/third_party/tlslite/tlslite/constants.py @@ -76,6 +76,14 @@ class SignatureAlgorithm: class NameType: host_name = 0 +class ECCurveType: + explicit_prime = 1 + explicit_char2 = 2 + named_curve = 3 + +class NamedCurve: + secp256r1 = 23 + class AlertLevel: warning = 1 fatal = 2 @@ -178,11 +186,19 @@ class CipherSuite: TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E + TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xc011 + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xc012 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xc013 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xc014 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xc027 + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02f + 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) + tripleDESSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) aes128Suites = [] aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA) @@ -192,6 +208,8 @@ class CipherSuite: 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) + aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) + aes128Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) aes256Suites = [] aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA) @@ -201,14 +219,17 @@ class CipherSuite: 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) + aes256Suites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) aes128GcmSuites = [] aes128GcmSuites.append(TLS_RSA_WITH_AES_128_GCM_SHA256) aes128GcmSuites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) + aes128GcmSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) rc4Suites = [] rc4Suites.append(TLS_RSA_WITH_RC4_128_SHA) rc4Suites.append(TLS_RSA_WITH_RC4_128_MD5) + rc4Suites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA) shaSuites = [] shaSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) @@ -226,6 +247,10 @@ class CipherSuite: 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) + shaSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA) + shaSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) + shaSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) + shaSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) sha256Suites = [] sha256Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA256) @@ -234,6 +259,9 @@ class CipherSuite: sha256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) sha256Suites.append(TLS_RSA_WITH_AES_128_GCM_SHA256) sha256Suites.append(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) + sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) + sha256Suites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) + aeadSuites = aes128GcmSuites @@ -275,6 +303,8 @@ class CipherSuite: keyExchangeSuites += CipherSuite.certSuites if "dhe_rsa" in keyExchangeNames: keyExchangeSuites += CipherSuite.dheCertSuites + if "ecdhe_rsa" in keyExchangeNames: + keyExchangeSuites += CipherSuite.ecdheCertSuites if "srp_sha" in keyExchangeNames: keyExchangeSuites += CipherSuite.srpSuites if "srp_sha_rsa" in keyExchangeNames: @@ -335,7 +365,19 @@ class CipherSuite: def getDheCertSuites(settings, version=None): return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings, version) - certAllSuites = srpCertSuites + certSuites + dheCertSuites + ecdheCertSuites = [] + ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) + ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) + ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) + ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) + ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) + ecdheCertSuites.append(TLS_ECDHE_RSA_WITH_RC4_128_SHA) + + @staticmethod + def getEcdheCertSuites(settings, version=None): + return CipherSuite._filterSuites(CipherSuite.ecdheCertSuites, settings, version) + + certAllSuites = srpCertSuites + certSuites + dheCertSuites + ecdheCertSuites anonSuites = [] anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA) @@ -346,6 +388,7 @@ class CipherSuite: return CipherSuite._filterSuites(CipherSuite.anonSuites, settings, version) dhAllSuites = dheCertSuites + anonSuites + ecdhAllSuites = ecdheCertSuites @staticmethod def canonicalCipherName(ciphersuite): diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py index e752834..605ed42 100644 --- a/third_party/tlslite/tlslite/handshakesettings.py +++ b/third_party/tlslite/tlslite/handshakesettings.py @@ -14,7 +14,7 @@ from .utils import cipherfactory CIPHER_NAMES = ["aes128gcm", "rc4", "aes256", "aes128", "3des"] MAC_NAMES = ["sha", "sha256", "aead"] # Don't allow "md5" by default. ALL_MAC_NAMES = MAC_NAMES + ["md5"] -KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"] +KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "ecdhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"] CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"] CERTIFICATE_TYPES = ["x509"] TLS_INTOLERANCE_TYPES = ["alert", "close", "reset"] diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py index f2e2cfc..9aeff6d 100644 --- a/third_party/tlslite/tlslite/messages.py +++ b/third_party/tlslite/tlslite/messages.py @@ -509,10 +509,13 @@ class ServerKeyExchange(HandshakeMsg): self.srp_g = 0 self.srp_s = bytearray(0) self.srp_B = 0 - # Anon DH params: + # DH params: self.dh_p = 0 self.dh_g = 0 self.dh_Ys = 0 + # ECDH params: + self.ecdhCurve = 0 + self.ecdhPublic = bytearray(0) self.signature = bytearray(0) def createSRP(self, srp_N, srp_g, srp_s, srp_B): @@ -528,6 +531,11 @@ class ServerKeyExchange(HandshakeMsg): self.dh_Ys = dh_Ys return self + def createECDH(self, ecdhCurve, ecdhPublic): + self.ecdhCurve = ecdhCurve + self.ecdhPublic = ecdhPublic + return self + def parse(self, p): p.startLengthCheck(3) if self.cipherSuite in CipherSuite.srpAllSuites: @@ -555,6 +563,10 @@ class ServerKeyExchange(HandshakeMsg): w.addVarSeq(numberToByteArray(self.dh_p), 1, 2) w.addVarSeq(numberToByteArray(self.dh_g), 1, 2) w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2) + elif self.cipherSuite in CipherSuite.ecdhAllSuites: + w.add(ECCurveType.named_curve, 1) + w.add(self.ecdhCurve, 2) + w.addVarSeq(self.ecdhPublic, 1, 1) else: assert(False) return w.bytes @@ -626,7 +638,9 @@ class ClientKeyExchange(HandshakeMsg): else: raise AssertionError() elif self.cipherSuite in CipherSuite.dhAllSuites: - self.dh_Yc = bytesToNumber(p.getVarBytes(2)) + self.dh_Yc = bytesToNumber(p.getVarBytes(2)) + elif self.cipherSuite in CipherSuite.ecdhAllSuites: + self.ecdh_Yc = p.getVarBytes(1) else: raise AssertionError() p.stopLengthCheck() diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py index 0a85d3c..dfac274 100644 --- a/third_party/tlslite/tlslite/tlsconnection.py +++ b/third_party/tlslite/tlslite/tlsconnection.py @@ -24,6 +24,7 @@ from .mathtls import * from .handshakesettings import HandshakeSettings from .utils.tackwrapper import * from .utils.rsakey import RSAKey +from .utils import p256 class KeyExchange(object): def __init__(self, cipherSuite, clientHello, serverHello, privateKey): @@ -127,6 +128,25 @@ DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 S = powMod(dh_Yc, self.dh_Xs, self.dh_p) return numberToByteArray(S) +class ECDHE_RSAKeyExchange(KeyExchange): + def makeServerKeyExchange(self): + public, self.private = p256.generatePublicPrivate() + + version = self.serverHello.server_version + serverKeyExchange = ServerKeyExchange(self.cipherSuite, version) + serverKeyExchange.createECDH(NamedCurve.secp256r1, bytearray(public)) + 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): + ecdh_Yc = clientKeyExchange.ecdh_Yc + return bytearray(p256.generateSharedValue(bytes(ecdh_Yc), self.private)) + class TLSConnection(TLSRecordLayer): """ This class wraps a socket and provides TLS handshaking and data @@ -1321,9 +1341,8 @@ class TLSConnection(TLSRecordLayer): else: break premasterSecret = result - # Perform the RSA or DHE_RSA key exchange - elif (cipherSuite in CipherSuite.certSuites or - cipherSuite in CipherSuite.dheCertSuites): + # Perform a certificate-based key exchange + elif cipherSuite in CipherSuite.certAllSuites: if cipherSuite in CipherSuite.certSuites: keyExchange = RSAKeyExchange(cipherSuite, clientHello, @@ -1334,6 +1353,11 @@ class TLSConnection(TLSRecordLayer): clientHello, serverHello, privateKey) + elif cipherSuite in CipherSuite.ecdheCertSuites: + keyExchange = ECDHE_RSAKeyExchange(cipherSuite, + clientHello, + serverHello, + privateKey) else: assert(False) for result in self._serverCertKeyExchange(clientHello, serverHello, @@ -1450,6 +1474,7 @@ class TLSConnection(TLSRecordLayer): CipherSuite.getSrpCertSuites(settings, self.version) cipherSuites += CipherSuite.getSrpSuites(settings, self.version) elif certChain: + cipherSuites += CipherSuite.getEcdheCertSuites(settings, self.version) cipherSuites += CipherSuite.getDheCertSuites(settings, self.version) cipherSuites += CipherSuite.getCertSuites(settings, self.version) elif anon: diff --git a/third_party/tlslite/tlslite/utils/p256.py b/third_party/tlslite/tlslite/utils/p256.py new file mode 100644 index 0000000..6eb9a77 --- /dev/null +++ b/third_party/tlslite/tlslite/utils/p256.py @@ -0,0 +1,162 @@ +# Author: Google +# See the LICENSE file for legal information regarding use of this file. + +import os + +p = ( + 115792089210356248762697446949407573530086143415290314195533631308867097853951) +order = ( + 115792089210356248762697446949407573529996955224135760342422259061068512044369) +p256B = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b + +baseX = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 +baseY = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 +basePoint = (baseX, baseY) + + +def _pointAdd(a, b): + Z1Z1 = (a[2] * a[2]) % p + Z2Z2 = (b[2] * b[2]) % p + U1 = (a[0] * Z2Z2) % p + U2 = (b[0] * Z1Z1) % p + S1 = (a[1] * b[2] * Z2Z2) % p + S2 = (b[1] * a[2] * Z1Z1) % p + if U1 == U2 and S1 == S2: + return pointDouble(a) + H = (U2 - U1) % p + I = (4 * H * H) % p + J = (H * I) % p + r = (2 * (S2 - S1)) % p + V = (U1 * I) % p + X3 = (r * r - J - 2 * V) % p + Y3 = (r * (V - X3) - 2 * S1 * J) % p + Z3 = (((a[2] + b[2]) * (a[2] + b[2]) - Z1Z1 - Z2Z2) * H) % p + + return (X3, Y3, Z3) + + +def _pointDouble(a): + delta = (a[2] * a[2]) % p + gamma = (a[1] * a[1]) % p + beta = (a[0] * gamma) % p + alpha = (3 * (a[0] - delta) * (a[0] + delta)) % p + X3 = (alpha * alpha - 8 * beta) % p + Z3 = ((a[1] + a[2]) * (a[1] + a[2]) - gamma - delta) % p + Y3 = (alpha * (4 * beta - X3) - 8 * gamma * gamma) % p + + return (X3, Y3, Z3) + + +def _square(n): + return (n * n) + + +def _modpow(a, n, p): + if n == 0: + return 1 + if n == 1: + return a + r = _square(_modpow(a, n >> 1, p)) % p + if n & 1 == 1: + r = (r * a) % p + return r + + +def _scalarMult(k, point): + accum = (0, 0, 0) + accumIsInfinity = True + jacobianPoint = (point[0], point[1], 1) + + for bit in range(255, -1, -1): + if not accumIsInfinity: + accum = _pointDouble(accum) + + if (k >> bit) & 1 == 1: + if accumIsInfinity: + accum = jacobianPoint + accumIsInfinity = False + else: + accum = _pointAdd(accum, jacobianPoint) + + if accumIsInfinity: + return (0, 0) + + zInv = _modpow(accum[2], p - 2, p) + return ((accum[0] * zInv * zInv) % p, (accum[1] * zInv * zInv * zInv) % p) + + +def _scalarBaseMult(k): + return _scalarMult(k, basePoint) + + +def _decodeBigEndian(b): + return sum([ord(b[len(b) - i - 1]) << 8 * i for i in range(len(b))]) + + +def _encodeBigEndian(n): + b = [] + while n != 0: + b.append(chr(n & 0xff)) + n >>= 8 + + if len(b) == 0: + b.append(0) + b.reverse() + + return "".join(b) + + +def _zeroPad(b, length): + if len(b) < length: + return ("\x00" * (length - len(b))) + b + return b + + +def _encodePoint(point): + x = point[0] + y = point[1] + if (y * y) % p != (x * x * x - 3 * x + p256B) % p: + raise "point not on curve" + return "\x04" + _zeroPad(_encodeBigEndian(point[0]), 32) + _zeroPad( + _encodeBigEndian(point[1]), 32) + + +def _decodePoint(b): + if len(b) != 1 + 32 + 32 or ord(b[0]) != 4: + raise "invalid encoded ec point" + x = _decodeBigEndian(b[1:33]) + y = _decodeBigEndian(b[33:65]) + if (y * y) % p != (x * x * x - 3 * x + p256B) % p: + raise "point not on curve" + return (x, y) + + +def generatePublicPrivate(): + """generatePublicPrivate returns a tuple of (X9.62 encoded public point, + private value), where the private value is generated from os.urandom.""" + private = _decodeBigEndian(os.urandom(40)) % order + return _encodePoint(_scalarBaseMult(private)), private + + +def generateSharedValue(theirPublic, private): + """generateSharedValue returns the encoded x-coordinate of the + multiplication of a peer's X9.62 encoded point and a private value.""" + return _zeroPad( + _encodeBigEndian(_scalarMult(private, _decodePoint(theirPublic))[0]), + 32) + +if __name__ == "__main__": + alice, alicePrivate = generatePublicPrivate() + bob, bobPrivate = generatePublicPrivate() + + if generateSharedValue(alice, bobPrivate) != generateSharedValue( + bob, alicePrivate): + raise "simple DH test failed" + + (x, _) = _scalarBaseMult(1) + + for i in range(1000): + (x, _) = _scalarBaseMult(x) + + if x != 2428281965257598569040586318034812501729437946720808289049534492833635302706: + raise "loop test failed" |