diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py index b3bad2d..d132b78 100755 --- a/third_party/tlslite/tlslite/constants.py +++ b/third_party/tlslite/tlslite/constants.py @@ -106,6 +106,7 @@ class AlertDescription: protocol_version = 70 insufficient_security = 71 internal_error = 80 + inappropriate_fallback = 86 user_canceled = 90 no_renegotiation = 100 unknown_psk_identity = 115 @@ -117,6 +118,9 @@ class CipherSuite: # We actually don't do any renegotiation, but this # prevents renegotiation attacks TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF + + # draft-bmoeller-tls-downgrade-scsv-01 + TLS_FALLBACK_SCSV = 0x5600 TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D diff --git a/third_party/tlslite/tlslite/errors.py b/third_party/tlslite/tlslite/errors.py index 22c298c..001ef33 100755 --- a/third_party/tlslite/tlslite/errors.py +++ b/third_party/tlslite/tlslite/errors.py @@ -63,6 +63,7 @@ class TLSAlert(TLSError): AlertDescription.protocol_version: "protocol_version",\ AlertDescription.insufficient_security: "insufficient_security",\ AlertDescription.internal_error: "internal_error",\ + AlertDescription.inappropriate_fallback: "inappropriate_fallback",\ AlertDescription.user_canceled: "user_canceled",\ AlertDescription.no_renegotiation: "no_renegotiation",\ AlertDescription.unknown_psk_identity: "unknown_psk_identity"} diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py index 45b0bbb..bd92161 100755 --- a/third_party/tlslite/tlslite/tlsconnection.py +++ b/third_party/tlslite/tlslite/tlsconnection.py @@ -966,7 +966,8 @@ class TLSConnection(TLSRecordLayer): reqCAs = None, tacks=None, activationFlags=0, nextProtos=None, anon=False, - tlsIntolerant=None, signedCertTimestamps=None): + tlsIntolerant=None, signedCertTimestamps=None, + fallbackSCSV=False): """Perform a handshake in the role of server. This function performs an SSL or TLS handshake. Depending on @@ -1045,6 +1046,11 @@ class TLSConnection(TLSRecordLayer): binary 8-bit string) that will be sent as a TLS extension whenever the client announces support for the extension. + @type fallbackSCSV: bool + @param fallbackSCSV: if true, the server will implement + TLS_FALLBACK_SCSV and thus reject connections using less than the + server's maximum TLS version that include this cipher suite. + @raise socket.error: If a socket error occurs. @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed without a preceding alert. @@ -1057,7 +1063,8 @@ class TLSConnection(TLSRecordLayer): checker, reqCAs, tacks=tacks, activationFlags=activationFlags, nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant, - signedCertTimestamps=signedCertTimestamps): + signedCertTimestamps=signedCertTimestamps, + fallbackSCSV=fallbackSCSV): pass @@ -1068,7 +1075,8 @@ class TLSConnection(TLSRecordLayer): tacks=None, activationFlags=0, nextProtos=None, anon=False, tlsIntolerant=None, - signedCertTimestamps=None + signedCertTimestamps=None, + fallbackSCSV=False ): """Start a server handshake operation on the TLS connection. @@ -1089,7 +1097,8 @@ class TLSConnection(TLSRecordLayer): tacks=tacks, activationFlags=activationFlags, nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant, - signedCertTimestamps=signedCertTimestamps) + signedCertTimestamps=signedCertTimestamps, + fallbackSCSV=fallbackSCSV) for result in self._handshakeWrapperAsync(handshaker, checker): yield result @@ -1099,7 +1108,7 @@ class TLSConnection(TLSRecordLayer): settings, reqCAs, tacks, activationFlags, nextProtos, anon, - tlsIntolerant, signedCertTimestamps): + tlsIntolerant, signedCertTimestamps, fallbackSCSV): self._handshakeStart(client=False) @@ -1134,7 +1143,7 @@ class TLSConnection(TLSRecordLayer): # Handle ClientHello and resumption for result in self._serverGetClientHello(settings, certChain,\ verifierDB, sessionCache, - anon, tlsIntolerant): + anon, tlsIntolerant, fallbackSCSV): if result in (0,1): yield result elif result == None: self._handshakeDone(resumed=True) @@ -1234,7 +1243,7 @@ class TLSConnection(TLSRecordLayer): def _serverGetClientHello(self, settings, certChain, verifierDB, - sessionCache, anon, tlsIntolerant): + sessionCache, anon, tlsIntolerant, fallbackSCSV): #Initialize acceptable cipher suites cipherSuites = [] if verifierDB: @@ -1280,6 +1289,13 @@ class TLSConnection(TLSRecordLayer): elif clientHello.client_version > settings.maxVersion: self.version = settings.maxVersion + #Detect if the client performed an inappropriate fallback. + elif fallbackSCSV and clientHello.client_version < settings.maxVersion: + if CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites: + for result in self._sendError(\ + AlertDescription.inappropriate_fallback): + yield result + else: #Set the version to the client's version self.version = clientHello.client_version