1 diff --git a/third_party/tlslite/tlslite/TLSConnection.py b/third_party/tlslite/tlslite/TLSConnection.py
2 index e6ce187..94ee5eb 100644
3 --- a/third_party/tlslite/tlslite/TLSConnection.py
4 +++ b/third_party/tlslite/tlslite/TLSConnection.py
5 @@ -937,8 +937,8 @@ class TLSConnection(TLSRecordLayer):
6 certChain=None, privateKey=None, reqCert=False,
7 sessionCache=None, settings=None, checker=None,
8 reqCAs=None, tlsIntolerant=0,
9 - signedCertTimestamps=None,
10 - fallbackSCSV=False):
11 + signedCertTimestamps=None, fallbackSCSV=False,
13 """Perform a handshake in the role of server.
15 This function performs an SSL or TLS handshake. Depending on
16 @@ -1014,6 +1014,16 @@ class TLSConnection(TLSRecordLayer):
17 binary 8-bit string) that will be sent as a TLS extension whenever
18 the client announces support for the extension.
20 + @type ocspResponse: str
21 + @param ocspResponse: An OCSP response (as a binary 8-bit string) that
22 + will be sent stapled in the handshake whenever the client announces
23 + support for the status_request extension.
24 + Note that the response is sent independent of the ClientHello
25 + status_request extension contents, and is thus only meant for testing
26 + environments. Real OCSP stapling is more complicated as it requires
27 + choosing a suitable response based on the ClientHello status_request
30 @raise socket.error: If a socket error occurs.
31 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
32 without a preceding alert.
33 @@ -1024,7 +1034,7 @@ class TLSConnection(TLSRecordLayer):
34 for result in self.handshakeServerAsync(sharedKeyDB, verifierDB,
35 certChain, privateKey, reqCert, sessionCache, settings,
36 checker, reqCAs, tlsIntolerant, signedCertTimestamps,
38 + fallbackSCSV, ocspResponse):
42 @@ -1033,7 +1043,7 @@ class TLSConnection(TLSRecordLayer):
43 sessionCache=None, settings=None, checker=None,
44 reqCAs=None, tlsIntolerant=0,
45 signedCertTimestamps=None,
46 - fallbackSCSV=False):
47 + fallbackSCSV=False, ocspResponse=None):
48 """Start a server handshake operation on the TLS connection.
50 This function returns a generator which behaves similarly to
51 @@ -1053,7 +1063,8 @@ class TLSConnection(TLSRecordLayer):
53 tlsIntolerant=tlsIntolerant,
54 signedCertTimestamps=signedCertTimestamps,
55 - fallbackSCSV=fallbackSCSV)
56 + fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse)
58 for result in self._handshakeWrapperAsync(handshaker, checker):
61 @@ -1062,7 +1073,7 @@ class TLSConnection(TLSRecordLayer):
62 certChain, privateKey, reqCert,
63 sessionCache, settings, reqCAs,
64 tlsIntolerant, signedCertTimestamps,
66 + fallbackSCSV, ocspResponse):
68 self._handshakeStart(client=False)
70 @@ -1439,10 +1450,14 @@ class TLSConnection(TLSRecordLayer):
71 sessionID, cipherSuite, certificateType)
72 serverHello.channel_id = clientHello.channel_id
73 if clientHello.support_signed_cert_timestamps:
74 - serverHello.signed_cert_timestamps = signedCertTimestamps
75 + serverHello.signed_cert_timestamps = signedCertTimestamps
76 + serverHello.status_request = (clientHello.status_request and
78 doingChannelID = clientHello.channel_id
79 msgs.append(serverHello)
80 msgs.append(Certificate(certificateType).create(serverCertChain))
81 + if serverHello.status_request:
82 + msgs.append(CertificateStatus().create(ocspResponse))
83 if reqCert and reqCAs:
84 msgs.append(CertificateRequest().create([], reqCAs))
86 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
87 index 23e3dcb..d027ef5 100644
88 --- a/third_party/tlslite/tlslite/constants.py
89 +++ b/third_party/tlslite/tlslite/constants.py
90 @@ -22,6 +22,7 @@ class HandshakeType:
91 certificate_verify = 15
92 client_key_exchange = 16
94 + certificate_status = 22
95 encrypted_extensions = 203
98 @@ -31,7 +32,11 @@ class ContentType:
102 +class CertificateStatusType:
106 + status_request = 5 # OCSP stapling
107 signed_cert_timestamps = 18 # signed_certificate_timestamp in RFC 6962
110 diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
111 index 296f422..497ef60 100644
112 --- a/third_party/tlslite/tlslite/messages.py
113 +++ b/third_party/tlslite/tlslite/messages.py
114 @@ -132,6 +132,7 @@ class ClientHello(HandshakeMsg):
115 self.srp_username = None # a string
116 self.channel_id = False
117 self.support_signed_cert_timestamps = False
118 + self.status_request = False
120 def create(self, version, random, session_id, cipher_suites,
121 certificate_types=None, srp_username=None):
122 @@ -182,6 +183,19 @@ class ClientHello(HandshakeMsg):
125 self.support_signed_cert_timestamps = True
126 + elif extType == ExtensionType.status_request:
127 + # Extension contents are currently ignored.
128 + # According to RFC 6066, this is not strictly forbidden
129 + # (although it is suboptimal):
130 + # Servers that receive a client hello containing the
131 + # "status_request" extension MAY return a suitable
132 + # certificate status response to the client along with
133 + # their certificate. If OCSP is requested, they
134 + # SHOULD use the information contained in the extension
135 + # when selecting an OCSP responder and SHOULD include
136 + # request_extensions in the OCSP request.
137 + p.getFixBytes(extLength)
138 + self.status_request = True
140 p.getFixBytes(extLength)
141 soFar += 4 + extLength
142 @@ -230,6 +244,7 @@ class ServerHello(HandshakeMsg):
143 self.compression_method = 0
144 self.channel_id = False
145 self.signed_cert_timestamps = None
146 + self.status_request = False
148 def create(self, version, random, session_id, cipher_suite,
150 @@ -282,6 +297,9 @@ class ServerHello(HandshakeMsg):
151 if self.signed_cert_timestamps:
152 extLength += 4 + len(self.signed_cert_timestamps)
154 + if self.status_request:
160 @@ -299,6 +317,10 @@ class ServerHello(HandshakeMsg):
161 w.add(ExtensionType.signed_cert_timestamps, 2)
162 w.addVarSeq(stringToBytes(self.signed_cert_timestamps), 1, 2)
164 + if self.status_request:
165 + w.add(ExtensionType.status_request, 2)
168 return HandshakeMsg.postWrite(self, w, trial)
170 class Certificate(HandshakeMsg):
171 @@ -367,6 +389,37 @@ class Certificate(HandshakeMsg):
172 raise AssertionError()
173 return HandshakeMsg.postWrite(self, w, trial)
175 +class CertificateStatus(HandshakeMsg):
176 + def __init__(self):
177 + self.contentType = ContentType.handshake
179 + def create(self, ocsp_response):
180 + self.ocsp_response = ocsp_response
183 + # Defined for the sake of completeness, even though we currently only
184 + # support sending the status message (server-side), not requesting
185 + # or receiving it (client-side).
186 + def parse(self, p):
187 + p.startLengthCheck(3)
188 + status_type = p.get(1)
189 + # Only one type is specified, so hardwire it.
190 + if status_type != CertificateStatusType.ocsp:
191 + raise SyntaxError()
192 + ocsp_response = p.getVarBytes(3)
193 + if not ocsp_response:
195 + raise SyntaxError()
196 + self.ocsp_response = ocsp_response
199 + def write(self, trial=False):
200 + w = HandshakeMsg.preWrite(self, HandshakeType.certificate_status,
202 + w.add(CertificateStatusType.ocsp, 1)
203 + w.addVarSeq(stringToBytes(self.ocsp_response), 1, 3)
204 + return HandshakeMsg.postWrite(self, w, trial)
206 class CertificateRequest(HandshakeMsg):
208 self.contentType = ContentType.handshake