OLD | NEW |
(Empty) | |
| 1 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlsl
ite/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/tlsl
ite/tlslite/handshakesettings.py |
| 111 index 7a38ee2..35c8b0e 100644 |
| 112 --- a/third_party/tlslite/tlslite/handshakesettings.py |
| 113 +++ b/third_party/tlslite/tlslite/handshakesettings.py |
| 114 @@ -14,6 +14,7 @@ from .utils import cipherfactory |
| 115 # issues such as timing attacks |
| 116 CIPHER_NAMES = ["rc4", "aes256", "aes128", "3des"] |
| 117 MAC_NAMES = ["sha"] # "md5" is allowed |
| 118 +KEY_EXCHANGE_NAMES = ["rsa", "dhe_rsa", "srp_sha", "srp_sha_rsa", "dh_anon"] |
| 119 CIPHER_IMPLEMENTATIONS = ["openssl", "pycrypto", "python"] |
| 120 CERTIFICATE_TYPES = ["x509"] |
| 121 |
| 122 @@ -100,6 +101,7 @@ class HandshakeSettings(object): |
| 123 def __init__(self): |
| 124 self.minKeySize = 1023 |
| 125 self.maxKeySize = 8193 |
| 126 + self.keyExchangeNames = KEY_EXCHANGE_NAMES |
| 127 self.cipherNames = CIPHER_NAMES |
| 128 self.macNames = MAC_NAMES |
| 129 self.cipherImplementations = CIPHER_IMPLEMENTATIONS |
| 130 @@ -114,6 +116,7 @@ class HandshakeSettings(object): |
| 131 other = HandshakeSettings() |
| 132 other.minKeySize = self.minKeySize |
| 133 other.maxKeySize = self.maxKeySize |
| 134 + other.keyExchangeNames = self.keyExchangeNames |
| 135 other.cipherNames = self.cipherNames |
| 136 other.macNames = self.macNames |
| 137 other.cipherImplementations = self.cipherImplementations |
| 138 @@ -145,6 +148,9 @@ class HandshakeSettings(object): |
| 139 raise ValueError("maxKeySize too small") |
| 140 if other.maxKeySize>16384: |
| 141 raise ValueError("maxKeySize too large") |
| 142 + for s in other.keyExchangeNames: |
| 143 + if s not in KEY_EXCHANGE_NAMES: |
| 144 + raise ValueError("Unknown key exchange name: '%s'" % s) |
| 145 for s in other.cipherNames: |
| 146 if s not in CIPHER_NAMES: |
| 147 raise ValueError("Unknown cipher name: '%s'" % s) |
| 148 diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlsli
te/messages.py |
| 149 index 532d86b..550b387 100644 |
| 150 --- a/third_party/tlslite/tlslite/messages.py |
| 151 +++ b/third_party/tlslite/tlslite/messages.py |
| 152 @@ -533,31 +533,31 @@ class ServerKeyExchange(HandshakeMsg): |
| 153 p.stopLengthCheck() |
| 154 return self |
| 155 |
| 156 - def write(self): |
| 157 + def write_params(self): |
| 158 w = Writer() |
| 159 if self.cipherSuite in CipherSuite.srpAllSuites: |
| 160 w.addVarSeq(numberToByteArray(self.srp_N), 1, 2) |
| 161 w.addVarSeq(numberToByteArray(self.srp_g), 1, 2) |
| 162 w.addVarSeq(self.srp_s, 1, 1) |
| 163 w.addVarSeq(numberToByteArray(self.srp_B), 1, 2) |
| 164 - if self.cipherSuite in CipherSuite.srpCertSuites: |
| 165 - w.addVarSeq(self.signature, 1, 2) |
| 166 - elif self.cipherSuite in CipherSuite.anonSuites: |
| 167 + elif self.cipherSuite in CipherSuite.dhAllSuites: |
| 168 w.addVarSeq(numberToByteArray(self.dh_p), 1, 2) |
| 169 w.addVarSeq(numberToByteArray(self.dh_g), 1, 2) |
| 170 w.addVarSeq(numberToByteArray(self.dh_Ys), 1, 2) |
| 171 - if self.cipherSuite in []: # TODO support for signed_params |
| 172 - w.addVarSeq(self.signature, 1, 2) |
| 173 + else: |
| 174 + assert(False) |
| 175 + return w.bytes |
| 176 + |
| 177 + def write(self): |
| 178 + w = Writer() |
| 179 + w.bytes += self.write_params() |
| 180 + if self.cipherSuite in CipherSuite.certAllSuites: |
| 181 + w.addVarSeq(self.signature, 1, 2) |
| 182 return self.postWrite(w) |
| 183 |
| 184 def hash(self, clientRandom, serverRandom): |
| 185 - oldCipherSuite = self.cipherSuite |
| 186 - self.cipherSuite = None |
| 187 - try: |
| 188 - bytes = clientRandom + serverRandom + self.write()[4:] |
| 189 - return MD5(bytes) + SHA1(bytes) |
| 190 - finally: |
| 191 - self.cipherSuite = oldCipherSuite |
| 192 + bytes = clientRandom + serverRandom + self.write_params() |
| 193 + return MD5(bytes) + SHA1(bytes) |
| 194 |
| 195 class ServerHelloDone(HandshakeMsg): |
| 196 def __init__(self): |
| 197 @@ -607,7 +607,7 @@ class ClientKeyExchange(HandshakeMsg): |
| 198 p.getFixBytes(len(p.bytes)-p.index) |
| 199 else: |
| 200 raise AssertionError() |
| 201 - elif self.cipherSuite in CipherSuite.anonSuites: |
| 202 + elif self.cipherSuite in CipherSuite.dhAllSuites: |
| 203 self.dh_Yc = bytesToNumber(p.getVarBytes(2)) |
| 204 else: |
| 205 raise AssertionError() |
| 206 diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/
tlslite/tlsconnection.py |
| 207 index 20cd85b..07ee862 100644 |
| 208 --- a/third_party/tlslite/tlslite/tlsconnection.py |
| 209 +++ b/third_party/tlslite/tlslite/tlsconnection.py |
| 210 @@ -24,6 +24,78 @@ from .handshakesettings import HandshakeSettings |
| 211 from .utils.tackwrapper import * |
| 212 |
| 213 |
| 214 +class KeyExchange(object): |
| 215 + def __init__(self, cipherSuite, clientHello, serverHello, privateKey): |
| 216 + self.cipherSuite = cipherSuite |
| 217 + self.clientHello = clientHello |
| 218 + self.serverHello = serverHello |
| 219 + self.privateKey = privateKey |
| 220 + |
| 221 + def makeServerKeyExchange(): |
| 222 + raise NotImplementedError() |
| 223 + def processClientKeyExchange(clientKeyExchange): |
| 224 + raise NotImplementedError() |
| 225 + |
| 226 + |
| 227 +class RSAKeyExchange(KeyExchange): |
| 228 + def makeServerKeyExchange(self): |
| 229 + return None |
| 230 + |
| 231 + def processClientKeyExchange(self, clientKeyExchange): |
| 232 + premasterSecret = self.privateKey.decrypt(\ |
| 233 + clientKeyExchange.encryptedPreMasterSecret) |
| 234 + |
| 235 + # On decryption failure randomize premaster secret to avoid |
| 236 + # Bleichenbacher's "million message" attack |
| 237 + randomPreMasterSecret = getRandomBytes(48) |
| 238 + versionCheck = (premasterSecret[0], premasterSecret[1]) |
| 239 + if not premasterSecret: |
| 240 + premasterSecret = randomPreMasterSecret |
| 241 + elif len(premasterSecret)!=48: |
| 242 + premasterSecret = randomPreMasterSecret |
| 243 + elif versionCheck != self.clientHello.client_version: |
| 244 + #Tolerate buggy IE clients |
| 245 + if versionCheck != self.serverHello.server_version: |
| 246 + premasterSecret = randomPreMasterSecret |
| 247 + return premasterSecret |
| 248 + |
| 249 +class DHE_RSAKeyExchange(KeyExchange): |
| 250 + # Generated with openssl dhparam 1024 -text. Generating a new one each time |
| 251 + # in Python is far far far too slow. |
| 252 + dh_p = bytesToNumber( |
| 253 + bytearray( |
| 254 + "\x00\x88\xc4\xdc\x2a\xd9\xba\x8d\x24\x69\x7f\xe4\xd4\xeb\x62" |
| 255 + "\x04\x43\xe8\x31\x08\x30\xa8\xe4\x24\x0f\xa7\xc3\xff\x84\x52" |
| 256 + "\x44\x4a\x1b\x8c\x88\x16\xa6\x17\x90\xac\x21\x34\xfb\xc5\xff" |
| 257 + "\x90\x46\x32\x29\xfa\x9d\xd3\x36\x05\xc2\x86\xcf\xde\x77\x68" |
| 258 + "\x4c\xe3\xb0\x34\x55\xce\x27\x85\x46\x94\xad\x0c\xef\x11\x53" |
| 259 + "\x61\x50\x0c\x3e\x7b\x8a\x3c\xa0\x52\x6c\xb2\xa5\x84\xf7\xa9" |
| 260 + "\xdc\x9d\x57\x60\xd0\x89\xc6\x14\x39\x54\xce\x20\xcc\x2d\xe9" |
| 261 + "\x90\xeb\xe7\x42\xf1\x03\x60\x5b\x06\x2f\x51\x97\x01\xc2\x1d" |
| 262 + "\xfa\xb3\xfe\x02\x4b\xee\xd1\x65\xcb")) |
| 263 + dh_g = 2 |
| 264 + |
| 265 + def makeServerKeyExchange(self): |
| 266 + self.dh_Xs = bytesToNumber(getRandomBytes(1024 / 8)) |
| 267 + dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p) |
| 268 + |
| 269 + serverKeyExchange = ServerKeyExchange(self.cipherSuite) |
| 270 + serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys) |
| 271 + serverKeyExchange.signature = self.privateKey.sign( |
| 272 + serverKeyExchange.hash(self.clientHello.random, |
| 273 + self.serverHello.random)) |
| 274 + return serverKeyExchange |
| 275 + |
| 276 + def processClientKeyExchange(self, clientKeyExchange): |
| 277 + dh_Yc = clientKeyExchange.dh_Yc |
| 278 + |
| 279 + if dh_Yc % self.dh_p == 0: |
| 280 + raise TLSLocalAlert(AlertDescription.illegal_parameter, |
| 281 + "Suspicious dh_Yc value") |
| 282 + |
| 283 + S = powMod(dh_Yc, self.dh_Xs, self.dh_p) |
| 284 + return numberToByteArray(S) |
| 285 + |
| 286 class TLSConnection(TLSRecordLayer): |
| 287 """ |
| 288 This class wraps a socket and provides TLS handshaking and data |
| 289 @@ -500,6 +572,8 @@ class TLSConnection(TLSRecordLayer): |
| 290 cipherSuites += CipherSuite.getSrpAllSuites(settings) |
| 291 elif certParams: |
| 292 cipherSuites += CipherSuite.getCertSuites(settings) |
| 293 + # Client DHE_RSA not supported. |
| 294 + # cipherSuites += CipherSuite.getDheCertSuites(settings) |
| 295 elif anonParams: |
| 296 cipherSuites += CipherSuite.getAnonSuites(settings) |
| 297 else: |
| 298 @@ -1205,9 +1279,22 @@ class TLSConnection(TLSRecordLayer): |
| 299 premasterSecret = result |
| 300 |
| 301 # Perform the RSA key exchange |
| 302 - elif cipherSuite in CipherSuite.certSuites: |
| 303 + elif (cipherSuite in CipherSuite.certSuites or |
| 304 + cipherSuite in CipherSuite.dheCertSuites): |
| 305 + if cipherSuite in CipherSuite.certSuites: |
| 306 + keyExchange = RSAKeyExchange(cipherSuite, |
| 307 + clientHello, |
| 308 + serverHello, |
| 309 + privateKey) |
| 310 + elif cipherSuite in CipherSuite.dheCertSuites: |
| 311 + keyExchange = DHE_RSAKeyExchange(cipherSuite, |
| 312 + clientHello, |
| 313 + serverHello, |
| 314 + privateKey) |
| 315 + else: |
| 316 + assert(False) |
| 317 for result in self._serverCertKeyExchange(clientHello, serverHello,
|
| 318 - certChain, privateKey, |
| 319 + certChain, keyExchange, |
| 320 reqCert, reqCAs, cipherSuite, |
| 321 settings, ocspResponse): |
| 322 if result in (0,1): yield result |
| 323 @@ -1268,6 +1355,7 @@ class TLSConnection(TLSRecordLayer): |
| 324 cipherSuites += CipherSuite.getSrpSuites(settings) |
| 325 elif certChain: |
| 326 cipherSuites += CipherSuite.getCertSuites(settings) |
| 327 + cipherSuites += CipherSuite.getDheCertSuites(settings) |
| 328 elif anon: |
| 329 cipherSuites += CipherSuite.getAnonSuites(settings) |
| 330 else: |
| 331 @@ -1483,7 +1571,7 @@ class TLSConnection(TLSRecordLayer): |
| 332 |
| 333 |
| 334 def _serverCertKeyExchange(self, clientHello, serverHello, |
| 335 - serverCertChain, privateKey, |
| 336 + serverCertChain, keyExchange, |
| 337 reqCert, reqCAs, cipherSuite, |
| 338 settings, ocspResponse): |
| 339 #Send ServerHello, Certificate[, CertificateRequest], |
| 340 @@ -1497,6 +1585,9 @@ class TLSConnection(TLSRecordLayer): |
| 341 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) |
| 342 if serverHello.status_request: |
| 343 msgs.append(CertificateStatus().create(ocspResponse)) |
| 344 + serverKeyExchange = keyExchange.makeServerKeyExchange() |
| 345 + if serverKeyExchange is not None: |
| 346 + msgs.append(serverKeyExchange) |
| 347 if reqCert and reqCAs: |
| 348 msgs.append(CertificateRequest().create(\ |
| 349 [ClientCertificateType.rsa_sign], reqCAs)) |
| 350 @@ -1555,21 +1646,13 @@ class TLSConnection(TLSRecordLayer): |
| 351 else: break |
| 352 clientKeyExchange = result |
| 353 |
| 354 - #Decrypt ClientKeyExchange |
| 355 - premasterSecret = privateKey.decrypt(\ |
| 356 - clientKeyExchange.encryptedPreMasterSecret) |
| 357 - |
| 358 - # On decryption failure randomize premaster secret to avoid |
| 359 - # Bleichenbacher's "million message" attack |
| 360 - randomPreMasterSecret = getRandomBytes(48) |
| 361 - versionCheck = (premasterSecret[0], premasterSecret[1]) |
| 362 - if not premasterSecret: |
| 363 - premasterSecret = randomPreMasterSecret |
| 364 - elif len(premasterSecret)!=48: |
| 365 - premasterSecret = randomPreMasterSecret |
| 366 - elif versionCheck != clientHello.client_version: |
| 367 - if versionCheck != self.version: #Tolerate buggy IE clients |
| 368 - premasterSecret = randomPreMasterSecret |
| 369 + #Process ClientKeyExchange |
| 370 + try: |
| 371 + premasterSecret = \ |
| 372 + keyExchange.processClientKeyExchange(clientKeyExchange) |
| 373 + except TLSLocalAlert, e: |
| 374 + for result in self._sendError(alert.description, alert.message): |
| 375 + yield result |
| 376 |
| 377 #Get and check CertificateVerify, if relevant |
| 378 if clientCertChain: |
OLD | NEW |