Home | History | Annotate | Download | only in patches
      1 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
      2 index 52c20ac..feca423 100644
      3 --- a/third_party/tlslite/tlslite/constants.py
      4 +++ b/third_party/tlslite/tlslite/constants.py
      5 @@ -143,6 +143,10 @@ class CipherSuite:
      6      
      7      TLS_RSA_WITH_RC4_128_MD5 = 0x0004
      8  
      9 +    TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016
     10 +    TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033
     11 +    TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039
     12 +
     13      TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x0034
     14      TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x003A
     15  
     16 @@ -150,17 +154,20 @@ class CipherSuite:
     17      tripleDESSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
     18      tripleDESSuites.append(TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA)
     19      tripleDESSuites.append(TLS_RSA_WITH_3DES_EDE_CBC_SHA)
     20 +    tripleDESSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
     21  
     22      aes128Suites = []
     23      aes128Suites.append(TLS_SRP_SHA_WITH_AES_128_CBC_SHA)
     24      aes128Suites.append(TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA)
     25      aes128Suites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
     26 +    aes128Suites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
     27      aes128Suites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
     28  
     29      aes256Suites = []
     30      aes256Suites.append(TLS_SRP_SHA_WITH_AES_256_CBC_SHA)
     31      aes256Suites.append(TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA)
     32      aes256Suites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
     33 +    aes256Suites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
     34      aes256Suites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
     35  
     36      rc4Suites = []
     37 @@ -178,6 +185,9 @@ class CipherSuite:
     38      shaSuites.append(TLS_RSA_WITH_AES_128_CBC_SHA)
     39      shaSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
     40      shaSuites.append(TLS_RSA_WITH_RC4_128_SHA)
     41 +    shaSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
     42 +    shaSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
     43 +    shaSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
     44      shaSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
     45      shaSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
     46      
     47 @@ -188,6 +198,7 @@ class CipherSuite:
     48      def _filterSuites(suites, settings):
     49          macNames = settings.macNames
     50          cipherNames = settings.cipherNames
     51 +        keyExchangeNames = settings.keyExchangeNames
     52          macSuites = []
     53          if "sha" in macNames:
     54              macSuites += CipherSuite.shaSuites
     55 @@ -204,7 +215,20 @@ class CipherSuite:
     56          if "rc4" in cipherNames:
     57              cipherSuites += CipherSuite.rc4Suites
     58  
     59 -        return [s for s in suites if s in macSuites and s in cipherSuites]
     60 +        keyExchangeSuites = []
     61 +        if "rsa" in keyExchangeNames:
     62 +            keyExchangeSuites += CipherSuite.certSuites
     63 +        if "dhe_rsa" in keyExchangeNames:
     64 +            keyExchangeSuites += CipherSuite.dheCertSuites
     65 +        if "srp_sha" in keyExchangeNames:
     66 +            keyExchangeSuites += CipherSuite.srpSuites
     67 +        if "srp_sha_rsa" in keyExchangeNames:
     68 +            keyExchangeSuites += CipherSuite.srpCertSuites
     69 +        if "dh_anon" in keyExchangeNames:
     70 +            keyExchangeSuites += CipherSuite.anonSuites
     71 +
     72 +        return [s for s in suites if s in macSuites and
     73 +                s in cipherSuites and s in keyExchangeSuites]
     74  
     75      srpSuites = []
     76      srpSuites.append(TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA)
     77 @@ -236,12 +260,22 @@ class CipherSuite:
     78      certSuites.append(TLS_RSA_WITH_AES_256_CBC_SHA)
     79      certSuites.append(TLS_RSA_WITH_RC4_128_SHA)
     80      certSuites.append(TLS_RSA_WITH_RC4_128_MD5)
     81 -    certAllSuites = srpCertSuites + certSuites
     82      
     83      @staticmethod
     84      def getCertSuites(settings):
     85          return CipherSuite._filterSuites(CipherSuite.certSuites, settings)
     86  
     87 +    dheCertSuites = []
     88 +    dheCertSuites.append(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA)
     89 +    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
     90 +    dheCertSuites.append(TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
     91 +
     92 +    @staticmethod
     93 +    def getDheCertSuites(settings):
     94 +        return CipherSuite._filterSuites(CipherSuite.dheCertSuites, settings)
     95 +
     96 +    certAllSuites = srpCertSuites + certSuites + dheCertSuites
     97 +
     98      anonSuites = []
     99      anonSuites.append(TLS_DH_ANON_WITH_AES_128_CBC_SHA)
    100      anonSuites.append(TLS_DH_ANON_WITH_AES_256_CBC_SHA)
    101 @@ -250,6 +284,8 @@ class CipherSuite:
    102      def getAnonSuites(settings):
    103          return CipherSuite._filterSuites(CipherSuite.anonSuites, settings)
    104  
    105 +    dhAllSuites = dheCertSuites + anonSuites
    106 +
    107      @staticmethod
    108      def canonicalCipherName(ciphersuite):
    109          "Return the canonical name of the cipher whose number is provided."
    110 diff --git a/third_party/tlslite/tlslite/handshakesettings.py b/third_party/tlslite/tlslite/handshakesettings.py
    111 index 7a38ee2..e0bc0e6 100644
    112 --- a/third_party/tlslite/tlslite/handshakesettings.py
    113 +++ b/third_party/tlslite/tlslite/handshakesettings.py
    114 @@ -13,7 +13,9 @@ from .utils import cipherfactory
    115  # RC4 is preferred as faster in Python, works in SSL3, and immune to CBC
    116  # issues such as timing attacks
    117  CIPHER_NAMES = ["rc4", "aes256", "aes128", "3des"]
    118 -MAC_NAMES = ["sha"] # "md5" is allowed
    119 +MAC_NAMES = ["sha"] # Don't allow "md5" by default.
    120 +ALL_MAC_NAMES = ["sha", "md5"]
    121 +KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"]
    122  CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"]
    123  CERTIFICATE_TYPES = ["x509"]
    124  
    125 @@ -102,6 +104,7 @@ class HandshakeSettings(object):
    126          self.maxKeySize = 8193
    127          self.cipherNames = CIPHER_NAMES
    128          self.macNames = MAC_NAMES
    129 +        self.keyExchangeNames = KEY_EXCHANGE_NAMES
    130          self.cipherImplementations = CIPHER_IMPLEMENTATIONS
    131          self.certificateTypes = CERTIFICATE_TYPES
    132          self.minVersion = (3,0)
    133 @@ -116,6 +119,7 @@ class HandshakeSettings(object):
    134          other.maxKeySize = self.maxKeySize
    135          other.cipherNames = self.cipherNames
    136          other.macNames = self.macNames
    137 +        other.keyExchangeNames = self.keyExchangeNames
    138          other.cipherImplementations = self.cipherImplementations
    139          other.certificateTypes = self.certificateTypes
    140          other.minVersion = self.minVersion
    141 @@ -148,6 +152,12 @@ class HandshakeSettings(object):
    142          for s in other.cipherNames:
    143              if s not in CIPHER_NAMES:
    144                  raise ValueError("Unknown cipher name: '%s'" % s)
    145 +        for s in other.macNames:
    146 +            if s not in ALL_MAC_NAMES:
    147 +                raise ValueError("Unknown MAC name: '%s'" % s)
    148 +        for s in other.keyExchangeNames:
    149 +            if s not in KEY_EXCHANGE_NAMES:
    150 +                raise ValueError("Unknown key exchange name: '%s'" % s)
    151          for s in other.cipherImplementations:
    152              if s not in CIPHER_IMPLEMENTATIONS:
    153                  raise ValueError("Unknown cipher implementation: '%s'" % s)
    154 diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
    155 index 532d86b..550b387 100644
    156 --- a/third_party/tlslite/tlslite/messages.py
    157 +++ b/third_party/tlslite/tlslite/messages.py
    158 @@ -533,31 +533,31 @@ class ServerKeyExchange(HandshakeMsg):
    159          p.stopLengthCheck()
    160          return self
    161  
    162 -    def write(self):
    163 +    def write_params(self):
    164          w = Writer()
    165          if self.cipherSuite in CipherSuite.srpAllSuites:
    166              w.addVarSeq(numberToByteArray(self.srp_N), 1, 2)
    167              w.addVarSeq(numberToByteArray(self.srp_g), 1, 2)
    168              w.addVarSeq(self.srp_s, 1, 1)
    169              w.addVarSeq(numberToByteArray(self.srp_B), 1, 2)
    170 -            if self.cipherSuite in CipherSuite.srpCertSuites:
    171 -                w.addVarSeq(self.signature, 1, 2)
    172 -        elif self.cipherSuite in CipherSuite.anonSuites:
    173 +        elif self.cipherSuite in CipherSuite.dhAllSuites:
    174              w.addVarSeq(numberToByteArray(self.dh_p), 1, 2)
    175              w.addVarSeq(numberToByteArray(self.dh_g), 1, 2)
    176              w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2)
    177 -            if self.cipherSuite in []: # TODO support for signed_params
    178 -                w.addVarSeq(self.signature, 1, 2)
    179 +        else:
    180 +            assert(False)
    181 +        return w.bytes
    182 +
    183 +    def write(self):
    184 +        w = Writer()
    185 +        w.bytes += self.write_params()
    186 +        if self.cipherSuite in CipherSuite.certAllSuites:
    187 +            w.addVarSeq(self.signature, 1, 2)
    188          return self.postWrite(w)
    189  
    190      def hash(self, clientRandom, serverRandom):
    191 -        oldCipherSuite = self.cipherSuite
    192 -        self.cipherSuite = None
    193 -        try:
    194 -            bytes = clientRandom + serverRandom + self.write()[4:]
    195 -            return MD5(bytes) + SHA1(bytes)
    196 -        finally:
    197 -            self.cipherSuite = oldCipherSuite
    198 +        bytes = clientRandom + serverRandom + self.write_params()
    199 +        return MD5(bytes) + SHA1(bytes)
    200  
    201  class ServerHelloDone(HandshakeMsg):
    202      def __init__(self):
    203 @@ -607,7 +607,7 @@ class ClientKeyExchange(HandshakeMsg):
    204                      p.getFixBytes(len(p.bytes)-p.index)
    205              else:
    206                  raise AssertionError()
    207 -        elif self.cipherSuite in CipherSuite.anonSuites:
    208 +        elif self.cipherSuite in CipherSuite.dhAllSuites:
    209              self.dh_Yc = bytesToNumber(p.getVarBytes(2))            
    210          else:
    211              raise AssertionError()
    212 diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
    213 index 20cd85b..e6f7820 100644
    214 --- a/third_party/tlslite/tlslite/tlsconnection.py
    215 +++ b/third_party/tlslite/tlslite/tlsconnection.py
    216 @@ -23,6 +23,103 @@ from .mathtls import *
    217  from .handshakesettings import HandshakeSettings
    218  from .utils.tackwrapper import *
    219  
    220 +class KeyExchange(object):
    221 +    def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
    222 +        """
    223 +        Initializes the KeyExchange. privateKey is the signing private key.
    224 +        """
    225 +        self.cipherSuite = cipherSuite
    226 +        self.clientHello = clientHello
    227 +        self.serverHello = serverHello
    228 +        self.privateKey = privateKey
    229 +
    230 +    def makeServerKeyExchange():
    231 +        """
    232 +        Returns a ServerKeyExchange object for the server's initial leg in the
    233 +        handshake. If the key exchange method does not send ServerKeyExchange
    234 +        (e.g. RSA), it returns None.
    235 +        """
    236 +        raise NotImplementedError()
    237 +
    238 +    def processClientKeyExchange(clientKeyExchange):
    239 +        """
    240 +        Processes the client's ClientKeyExchange message and returns the
    241 +        premaster secret. Raises TLSLocalAlert on error.
    242 +        """
    243 +        raise NotImplementedError()
    244 +
    245 +class RSAKeyExchange(KeyExchange):
    246 +    def makeServerKeyExchange(self):
    247 +        return None
    248 +
    249 +    def processClientKeyExchange(self, clientKeyExchange):
    250 +        premasterSecret = self.privateKey.decrypt(\
    251 +            clientKeyExchange.encryptedPreMasterSecret)
    252 +
    253 +        # On decryption failure randomize premaster secret to avoid
    254 +        # Bleichenbacher's "million message" attack
    255 +        randomPreMasterSecret = getRandomBytes(48)
    256 +        if not premasterSecret:
    257 +            premasterSecret = randomPreMasterSecret
    258 +        elif len(premasterSecret)!=48:
    259 +            premasterSecret = randomPreMasterSecret
    260 +        else:
    261 +            versionCheck = (premasterSecret[0], premasterSecret[1])
    262 +            if versionCheck != self.clientHello.client_version:
    263 +                #Tolerate buggy IE clients
    264 +                if versionCheck != self.serverHello.server_version:
    265 +                    premasterSecret = randomPreMasterSecret
    266 +        return premasterSecret
    267 +
    268 +def _hexStringToNumber(s):
    269 +    s = s.replace(" ", "").replace("\n", "")
    270 +    if len(s) % 2 != 0:
    271 +        raise ValueError("Length is not even")
    272 +    return bytesToNumber(bytearray(s.decode("hex")))
    273 +
    274 +class DHE_RSAKeyExchange(KeyExchange):
    275 +    # 2048-bit MODP Group (RFC 3526, Section 3)
    276 +    dh_p = _hexStringToNumber("""
    277 +FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
    278 +29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
    279 +EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
    280 +E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
    281 +EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
    282 +C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
    283 +83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
    284 +670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
    285 +E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
    286 +DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
    287 +15728E5A 8AACAA68 FFFFFFFF FFFFFFFF""")
    288 +    dh_g = 2
    289 +
    290 +    # RFC 3526, Section 8.
    291 +    strength = 160
    292 +
    293 +    def makeServerKeyExchange(self):
    294 +        # Per RFC 3526, Section 1, the exponent should have double the entropy
    295 +        # of the strength of the curve.
    296 +        self.dh_Xs = bytesToNumber(getRandomBytes(self.strength * 2 / 8))
    297 +        dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p)
    298 +
    299 +        serverKeyExchange = ServerKeyExchange(self.cipherSuite)
    300 +        serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
    301 +        serverKeyExchange.signature = self.privateKey.sign(
    302 +            serverKeyExchange.hash(self.clientHello.random,
    303 +                                   self.serverHello.random))
    304 +        return serverKeyExchange
    305 +
    306 +    def processClientKeyExchange(self, clientKeyExchange):
    307 +        dh_Yc = clientKeyExchange.dh_Yc
    308 +
    309 +        # First half of RFC 2631, Section 2.1.5. Validate the client's public
    310 +        # key.
    311 +        if not 2 <= dh_Yc <= self.dh_p - 1:
    312 +            raise TLSLocalAlert(AlertDescription.illegal_parameter,
    313 +                                "Invalid dh_Yc value")
    314 +
    315 +        S = powMod(dh_Yc, self.dh_Xs, self.dh_p)
    316 +        return numberToByteArray(S)
    317  
    318  class TLSConnection(TLSRecordLayer):
    319      """
    320 @@ -500,6 +597,8 @@ class TLSConnection(TLSRecordLayer):
    321              cipherSuites += CipherSuite.getSrpAllSuites(settings)
    322          elif certParams:
    323              cipherSuites += CipherSuite.getCertSuites(settings)
    324 +            # TODO: Client DHE_RSA not supported.
    325 +            # cipherSuites += CipherSuite.getDheCertSuites(settings)
    326          elif anonParams:
    327              cipherSuites += CipherSuite.getAnonSuites(settings)
    328          else:
    329 @@ -1204,10 +1303,23 @@ class TLSConnection(TLSRecordLayer):
    330                  else: break
    331              premasterSecret = result
    332  
    333 -        # Perform the RSA key exchange
    334 -        elif cipherSuite in CipherSuite.certSuites:
    335 +        # Perform the RSA or DHE_RSA key exchange
    336 +        elif (cipherSuite in CipherSuite.certSuites or
    337 +              cipherSuite in CipherSuite.dheCertSuites):
    338 +            if cipherSuite in CipherSuite.certSuites:
    339 +                keyExchange = RSAKeyExchange(cipherSuite,
    340 +                                             clientHello,
    341 +                                             serverHello,
    342 +                                             privateKey)
    343 +            elif cipherSuite in CipherSuite.dheCertSuites:
    344 +                keyExchange = DHE_RSAKeyExchange(cipherSuite,
    345 +                                                 clientHello,
    346 +                                                 serverHello,
    347 +                                                 privateKey)
    348 +            else:
    349 +                assert(False)
    350              for result in self._serverCertKeyExchange(clientHello, serverHello, 
    351 -                                        certChain, privateKey,
    352 +                                        certChain, keyExchange,
    353                                          reqCert, reqCAs, cipherSuite,
    354                                          settings, ocspResponse):
    355                  if result in (0,1): yield result
    356 @@ -1268,6 +1380,7 @@ class TLSConnection(TLSRecordLayer):
    357              cipherSuites += CipherSuite.getSrpSuites(settings)
    358          elif certChain:
    359              cipherSuites += CipherSuite.getCertSuites(settings)
    360 +            cipherSuites += CipherSuite.getDheCertSuites(settings)
    361          elif anon:
    362              cipherSuites += CipherSuite.getAnonSuites(settings)
    363          else:
    364 @@ -1483,11 +1596,11 @@ class TLSConnection(TLSRecordLayer):
    365  
    366  
    367      def _serverCertKeyExchange(self, clientHello, serverHello, 
    368 -                                serverCertChain, privateKey,
    369 +                                serverCertChain, keyExchange,
    370                                  reqCert, reqCAs, cipherSuite,
    371                                  settings, ocspResponse):
    372 -        #Send ServerHello, Certificate[, CertificateRequest],
    373 -        #ServerHelloDone
    374 +        #Send ServerHello, Certificate[, ServerKeyExchange]
    375 +        #[, CertificateRequest], ServerHelloDone
    376          msgs = []
    377  
    378          # If we verify a client cert chain, return it
    379 @@ -1497,6 +1610,9 @@ class TLSConnection(TLSRecordLayer):
    380          msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
    381          if serverHello.status_request:
    382              msgs.append(CertificateStatus().create(ocspResponse))
    383 +        serverKeyExchange = keyExchange.makeServerKeyExchange()
    384 +        if serverKeyExchange is not None:
    385 +            msgs.append(serverKeyExchange)
    386          if reqCert and reqCAs:
    387              msgs.append(CertificateRequest().create(\
    388                  [ClientCertificateType.rsa_sign], reqCAs))
    389 @@ -1555,21 +1671,13 @@ class TLSConnection(TLSRecordLayer):
    390              else: break
    391          clientKeyExchange = result
    392  
    393 -        #Decrypt ClientKeyExchange
    394 -        premasterSecret = privateKey.decrypt(\
    395 -            clientKeyExchange.encryptedPreMasterSecret)
    396 -
    397 -        # On decryption failure randomize premaster secret to avoid
    398 -        # Bleichenbacher's "million message" attack
    399 -        randomPreMasterSecret = getRandomBytes(48)
    400 -        versionCheck = (premasterSecret[0], premasterSecret[1])
    401 -        if not premasterSecret:
    402 -            premasterSecret = randomPreMasterSecret
    403 -        elif len(premasterSecret)!=48:
    404 -            premasterSecret = randomPreMasterSecret
    405 -        elif versionCheck != clientHello.client_version:
    406 -            if versionCheck != self.version: #Tolerate buggy IE clients
    407 -                premasterSecret = randomPreMasterSecret
    408 +        #Process ClientKeyExchange
    409 +        try:
    410 +            premasterSecret = \
    411 +                keyExchange.processClientKeyExchange(clientKeyExchange)
    412 +        except TLSLocalAlert, alert:
    413 +            for result in self._sendError(alert.description, alert.message):
    414 +                yield result
    415  
    416          #Get and check CertificateVerify, if relevant
    417          if clientCertChain:
    418