blob: 460468b10060883dc2f0a9f201d2c46d46fb66e7 [file] [log] [blame]
diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
index 8720de6..69e6067 100644
--- a/third_party/tlslite/tlslite/constants.py
+++ b/third_party/tlslite/tlslite/constants.py
@@ -107,6 +107,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
@@ -118,6 +119,9 @@ class CipherSuite:
# We actually don't do any renegotiation, but this
# prevents renegotiation attacks
TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF
+
+ # draft-ietf-tls-downgrade-scsv-03
+ 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 100644
--- 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 4dedc5f..0563fb5f 100644
--- a/third_party/tlslite/tlslite/tlsconnection.py
+++ b/third_party/tlslite/tlslite/tlsconnection.py
@@ -969,7 +969,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
@@ -1048,6 +1049,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.
@@ -1060,7 +1066,8 @@ class TLSConnection(TLSRecordLayer):
checker, reqCAs,
tacks=tacks, activationFlags=activationFlags,
nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
- signedCertTimestamps=signedCertTimestamps):
+ signedCertTimestamps=signedCertTimestamps,
+ fallbackSCSV=fallbackSCSV):
pass
@@ -1071,7 +1078,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.
@@ -1092,7 +1100,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
@@ -1102,7 +1111,7 @@ class TLSConnection(TLSRecordLayer):
settings, reqCAs,
tacks, activationFlags,
nextProtos, anon,
- tlsIntolerant, signedCertTimestamps):
+ tlsIntolerant, signedCertTimestamps, fallbackSCSV):
self._handshakeStart(client=False)
@@ -1137,7 +1146,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)
@@ -1237,7 +1246,7 @@ class TLSConnection(TLSRecordLayer):
def _serverGetClientHello(self, settings, certChain, verifierDB,
- sessionCache, anon, tlsIntolerant):
+ sessionCache, anon, tlsIntolerant, fallbackSCSV):
#Initialize acceptable cipher suites
cipherSuites = []
if verifierDB:
@@ -1283,6 +1292,14 @@ 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:
+ self.version = clientHello.client_version
+ 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