1 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
2 index 69e6067..1a1ace9 100644
3 --- a/third_party/tlslite/tlslite/constants.py
4 +++ b/third_party/tlslite/tlslite/constants.py
5 @@ -31,6 +31,7 @@ class HandshakeType:
6 certificate_verify = 15
7 client_key_exchange = 16
9 + certificate_status = 22
11 encrypted_extensions = 203
13 @@ -41,8 +42,12 @@ class ContentType:
17 +class CertificateStatusType:
20 class ExtensionType: # RFC 6066 / 4366
21 server_name = 0 # RFC 6066 / 4366
22 + status_request = 5 # RFC 6066 / 4366
24 cert_type = 9 # RFC 6091
25 signed_cert_timestamps = 18 # RFC 6962
26 diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
27 index 876b033..9a8e5f6 100644
28 --- a/third_party/tlslite/tlslite/messages.py
29 +++ b/third_party/tlslite/tlslite/messages.py
30 @@ -115,6 +115,7 @@ class ClientHello(HandshakeMsg):
31 self.server_name = bytearray(0)
32 self.channel_id = False
33 self.support_signed_cert_timestamps = False
34 + self.status_request = False
36 def create(self, version, random, session_id, cipher_suites,
37 certificate_types=None, srpUsername=None,
38 @@ -188,6 +189,19 @@ class ClientHello(HandshakeMsg):
41 self.support_signed_cert_timestamps = True
42 + elif extType == ExtensionType.status_request:
43 + # Extension contents are currently ignored.
44 + # According to RFC 6066, this is not strictly forbidden
45 + # (although it is suboptimal):
46 + # Servers that receive a client hello containing the
47 + # "status_request" extension MAY return a suitable
48 + # certificate status response to the client along with
49 + # their certificate. If OCSP is requested, they
50 + # SHOULD use the information contained in the extension
51 + # when selecting an OCSP responder and SHOULD include
52 + # request_extensions in the OCSP request.
53 + p.getFixBytes(extLength)
54 + self.status_request = True
56 _ = p.getFixBytes(extLength)
58 @@ -254,6 +268,7 @@ class ServerHello(HandshakeMsg):
59 self.next_protos = None
60 self.channel_id = False
61 self.signed_cert_timestamps = None
62 + self.status_request = False
64 def create(self, version, random, session_id, cipher_suite,
65 certificate_type, tackExt, next_protos_advertised):
66 @@ -346,6 +361,9 @@ class ServerHello(HandshakeMsg):
67 if self.signed_cert_timestamps:
68 w2.add(ExtensionType.signed_cert_timestamps, 2)
69 w2.addVarSeq(bytearray(self.signed_cert_timestamps), 1, 2)
70 + if self.status_request:
71 + w2.add(ExtensionType.status_request, 2)
74 w.add(len(w2.bytes), 2)
76 @@ -403,6 +421,37 @@ class Certificate(HandshakeMsg):
77 raise AssertionError()
78 return self.postWrite(w)
80 +class CertificateStatus(HandshakeMsg):
82 + HandshakeMsg.__init__(self, HandshakeType.certificate_status)
84 + def create(self, ocsp_response):
85 + self.ocsp_response = ocsp_response
88 + # Defined for the sake of completeness, even though we currently only
89 + # support sending the status message (server-side), not requesting
90 + # or receiving it (client-side).
92 + p.startLengthCheck(3)
93 + status_type = p.get(1)
94 + # Only one type is specified, so hardwire it.
95 + if status_type != CertificateStatusType.ocsp:
97 + ocsp_response = p.getVarBytes(3)
98 + if not ocsp_response:
100 + raise SyntaxError()
101 + self.ocsp_response = ocsp_response
102 + p.stopLengthCheck()
107 + w.add(CertificateStatusType.ocsp, 1)
108 + w.addVarSeq(bytearray(self.ocsp_response), 1, 3)
109 + return self.postWrite(w)
111 class CertificateRequest(HandshakeMsg):
112 def __init__(self, version):
113 HandshakeMsg.__init__(self, HandshakeType.certificate_request)
114 diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
115 index 0563fb5f..5d508ed 100644
116 --- a/third_party/tlslite/tlslite/tlsconnection.py
117 +++ b/third_party/tlslite/tlslite/tlsconnection.py
118 @@ -970,7 +970,7 @@ class TLSConnection(TLSRecordLayer):
119 tacks=None, activationFlags=0,
120 nextProtos=None, anon=False,
121 tlsIntolerant=None, signedCertTimestamps=None,
122 - fallbackSCSV=False):
123 + fallbackSCSV=False, ocspResponse=None):
124 """Perform a handshake in the role of server.
126 This function performs an SSL or TLS handshake. Depending on
127 @@ -1054,6 +1054,16 @@ class TLSConnection(TLSRecordLayer):
128 TLS_FALLBACK_SCSV and thus reject connections using less than the
129 server's maximum TLS version that include this cipher suite.
131 + @type ocspResponse: str
132 + @param ocspResponse: An OCSP response (as a binary 8-bit string) that
133 + will be sent stapled in the handshake whenever the client announces
134 + support for the status_request extension.
135 + Note that the response is sent independent of the ClientHello
136 + status_request extension contents, and is thus only meant for testing
137 + environments. Real OCSP stapling is more complicated as it requires
138 + choosing a suitable response based on the ClientHello status_request
139 + extension contents.
141 @raise socket.error: If a socket error occurs.
142 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
143 without a preceding alert.
144 @@ -1067,7 +1077,7 @@ class TLSConnection(TLSRecordLayer):
145 tacks=tacks, activationFlags=activationFlags,
146 nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
147 signedCertTimestamps=signedCertTimestamps,
148 - fallbackSCSV=fallbackSCSV):
149 + fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse):
153 @@ -1079,7 +1089,8 @@ class TLSConnection(TLSRecordLayer):
154 nextProtos=None, anon=False,
156 signedCertTimestamps=None,
158 + fallbackSCSV=False,
161 """Start a server handshake operation on the TLS connection.
163 @@ -1101,7 +1112,8 @@ class TLSConnection(TLSRecordLayer):
164 nextProtos=nextProtos, anon=anon,
165 tlsIntolerant=tlsIntolerant,
166 signedCertTimestamps=signedCertTimestamps,
167 - fallbackSCSV=fallbackSCSV)
168 + fallbackSCSV=fallbackSCSV,
169 + ocspResponse=ocspResponse)
170 for result in self._handshakeWrapperAsync(handshaker, checker):
173 @@ -1111,7 +1123,8 @@ class TLSConnection(TLSRecordLayer):
175 tacks, activationFlags,
177 - tlsIntolerant, signedCertTimestamps, fallbackSCSV):
178 + tlsIntolerant, signedCertTimestamps, fallbackSCSV,
181 self._handshakeStart(client=False)
183 @@ -1181,6 +1194,8 @@ class TLSConnection(TLSRecordLayer):
184 serverHello.channel_id = clientHello.channel_id
185 if clientHello.support_signed_cert_timestamps:
186 serverHello.signed_cert_timestamps = signedCertTimestamps
187 + if clientHello.status_request:
188 + serverHello.status_request = ocspResponse
190 # Perform the SRP key exchange
191 clientCertChain = None
192 @@ -1197,7 +1212,7 @@ class TLSConnection(TLSRecordLayer):
193 for result in self._serverCertKeyExchange(clientHello, serverHello,
194 certChain, privateKey,
195 reqCert, reqCAs, cipherSuite,
197 + settings, ocspResponse):
198 if result in (0,1): yield result
200 (premasterSecret, clientCertChain) = result
201 @@ -1475,7 +1490,7 @@ class TLSConnection(TLSRecordLayer):
202 def _serverCertKeyExchange(self, clientHello, serverHello,
203 serverCertChain, privateKey,
204 reqCert, reqCAs, cipherSuite,
206 + settings, ocspResponse):
207 #Send ServerHello, Certificate[, CertificateRequest],
210 @@ -1485,6 +1500,8 @@ class TLSConnection(TLSRecordLayer):
212 msgs.append(serverHello)
213 msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
214 + if serverHello.status_request:
215 + msgs.append(CertificateStatus().create(ocspResponse))
216 if reqCert and reqCAs:
217 msgs.append(CertificateRequest().create(\
218 [ClientCertificateType.rsa_sign], reqCAs))