1 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py 2 index b3bad2d..d132b78 100755 3 --- a/third_party/tlslite/tlslite/constants.py 4 +++ b/third_party/tlslite/tlslite/constants.py 5 @@ -106,6 +106,7 @@ class AlertDescription: 6 protocol_version = 70 7 insufficient_security = 71 8 internal_error = 80 9 + inappropriate_fallback = 86 10 user_canceled = 90 11 no_renegotiation = 100 12 unknown_psk_identity = 115 13 @@ -117,6 +118,9 @@ class CipherSuite: 14 # We actually don't do any renegotiation, but this 15 # prevents renegotiation attacks 16 TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF 17 + 18 + # draft-bmoeller-tls-downgrade-scsv-01 19 + TLS_FALLBACK_SCSV = 0x5600 20 21 TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A 22 TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D 23 diff --git a/third_party/tlslite/tlslite/errors.py b/third_party/tlslite/tlslite/errors.py 24 index 22c298c..001ef33 100755 25 --- a/third_party/tlslite/tlslite/errors.py 26 +++ b/third_party/tlslite/tlslite/errors.py 27 @@ -63,6 +63,7 @@ class TLSAlert(TLSError): 28 AlertDescription.protocol_version: "protocol_version",\ 29 AlertDescription.insufficient_security: "insufficient_security",\ 30 AlertDescription.internal_error: "internal_error",\ 31 + AlertDescription.inappropriate_fallback: "inappropriate_fallback",\ 32 AlertDescription.user_canceled: "user_canceled",\ 33 AlertDescription.no_renegotiation: "no_renegotiation",\ 34 AlertDescription.unknown_psk_identity: "unknown_psk_identity"} 35 diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py 36 index 45b0bbb..bd92161 100755 37 --- a/third_party/tlslite/tlslite/tlsconnection.py 38 +++ b/third_party/tlslite/tlslite/tlsconnection.py 39 @@ -966,7 +966,8 @@ class TLSConnection(TLSRecordLayer): 40 reqCAs = None, 41 tacks=None, activationFlags=0, 42 nextProtos=None, anon=False, 43 - tlsIntolerant=None, signedCertTimestamps=None): 44 + tlsIntolerant=None, signedCertTimestamps=None, 45 + fallbackSCSV=False): 46 """Perform a handshake in the role of server. 47 48 This function performs an SSL or TLS handshake. Depending on 49 @@ -1045,6 +1046,11 @@ class TLSConnection(TLSRecordLayer): 50 binary 8-bit string) that will be sent as a TLS extension whenever 51 the client announces support for the extension. 52 53 + @type fallbackSCSV: bool 54 + @param fallbackSCSV: if true, the server will implement 55 + TLS_FALLBACK_SCSV and thus reject connections using less than the 56 + server's maximum TLS version that include this cipher suite. 57 + 58 @raise socket.error: If a socket error occurs. 59 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 60 without a preceding alert. 61 @@ -1057,7 +1063,8 @@ class TLSConnection(TLSRecordLayer): 62 checker, reqCAs, 63 tacks=tacks, activationFlags=activationFlags, 64 nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant, 65 - signedCertTimestamps=signedCertTimestamps): 66 + signedCertTimestamps=signedCertTimestamps, 67 + fallbackSCSV=fallbackSCSV): 68 pass 69 70 71 @@ -1068,7 +1075,8 @@ class TLSConnection(TLSRecordLayer): 72 tacks=None, activationFlags=0, 73 nextProtos=None, anon=False, 74 tlsIntolerant=None, 75 - signedCertTimestamps=None 76 + signedCertTimestamps=None, 77 + fallbackSCSV=False 78 ): 79 """Start a server handshake operation on the TLS connection. 80 81 @@ -1089,7 +1097,8 @@ class TLSConnection(TLSRecordLayer): 82 tacks=tacks, activationFlags=activationFlags, 83 nextProtos=nextProtos, anon=anon, 84 tlsIntolerant=tlsIntolerant, 85 - signedCertTimestamps=signedCertTimestamps) 86 + signedCertTimestamps=signedCertTimestamps, 87 + fallbackSCSV=fallbackSCSV) 88 for result in self._handshakeWrapperAsync(handshaker, checker): 89 yield result 90 91 @@ -1099,7 +1108,7 @@ class TLSConnection(TLSRecordLayer): 92 settings, reqCAs, 93 tacks, activationFlags, 94 nextProtos, anon, 95 - tlsIntolerant, signedCertTimestamps): 96 + tlsIntolerant, signedCertTimestamps, fallbackSCSV): 97 98 self._handshakeStart(client=False) 99 100 @@ -1134,7 +1143,7 @@ class TLSConnection(TLSRecordLayer): 101 # Handle ClientHello and resumption 102 for result in self._serverGetClientHello(settings, certChain,\ 103 verifierDB, sessionCache, 104 - anon, tlsIntolerant): 105 + anon, tlsIntolerant, fallbackSCSV): 106 if result in (0,1): yield result 107 elif result == None: 108 self._handshakeDone(resumed=True) 109 @@ -1234,7 +1243,7 @@ class TLSConnection(TLSRecordLayer): 110 111 112 def _serverGetClientHello(self, settings, certChain, verifierDB, 113 - sessionCache, anon, tlsIntolerant): 114 + sessionCache, anon, tlsIntolerant, fallbackSCSV): 115 #Initialize acceptable cipher suites 116 cipherSuites = [] 117 if verifierDB: 118 @@ -1280,6 +1289,14 @@ class TLSConnection(TLSRecordLayer): 119 elif clientHello.client_version > settings.maxVersion: 120 self.version = settings.maxVersion 121 122 + #Detect if the client performed an inappropriate fallback. 123 + elif fallbackSCSV and clientHello.client_version < settings.maxVersion: 124 + self.version = clientHello.client_version 125 + if CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites: 126 + for result in self._sendError(\ 127 + AlertDescription.inappropriate_fallback): 128 + yield result 129 + 130 else: 131 #Set the version to the client's version 132 self.version = clientHello.client_version 133