fallback_scsv.patch revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
2index 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
23diff --git a/third_party/tlslite/tlslite/errors.py b/third_party/tlslite/tlslite/errors.py
24index 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"}
35diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
36index 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