1 diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py 2 index d132b78..ceaa903 100755 3 --- a/third_party/tlslite/tlslite/constants.py 4 +++ b/third_party/tlslite/tlslite/constants.py 5 @@ -30,6 +30,7 @@ class HandshakeType: 6 certificate_verify = 15 7 client_key_exchange = 16 8 finished = 20 9 + certificate_status = 22 10 next_protocol = 67 11 encrypted_extensions = 203 12 13 @@ -40,8 +41,12 @@ class ContentType: 14 application_data = 23 15 all = (20,21,22,23) 16 17 +class CertificateStatusType: 18 + ocsp = 1 19 + 20 class ExtensionType: # RFC 6066 / 4366 21 server_name = 0 # RFC 6066 / 4366 22 + status_request = 5 # RFC 6066 / 4366 23 srp = 12 # RFC 5054 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 5a2cd6c..532d86b 100755 28 --- a/third_party/tlslite/tlslite/messages.py 29 +++ b/third_party/tlslite/tlslite/messages.py 30 @@ -114,6 +114,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 35 36 def create(self, version, random, session_id, cipher_suites, 37 certificate_types=None, srpUsername=None, 38 @@ -187,6 +188,19 @@ class ClientHello(HandshakeMsg): 39 if extLength: 40 raise SyntaxError() 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 55 else: 56 _ = p.getFixBytes(extLength) 57 index2 = p.index 58 @@ -253,6 +267,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 63 64 def create(self, version, random, session_id, cipher_suite, 65 certificate_type, tackExt, next_protos_advertised): 66 @@ -345,6 +360,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) 72 + w2.add(0, 2) 73 if len(w2.bytes): 74 w.add(len(w2.bytes), 2) 75 w.bytes += w2.bytes 76 @@ -402,6 +420,37 @@ class Certificate(HandshakeMsg): 77 raise AssertionError() 78 return self.postWrite(w) 79 80 +class CertificateStatus(HandshakeMsg): 81 + def __init__(self): 82 + HandshakeMsg.__init__(self, HandshakeType.certificate_status) 83 + 84 + def create(self, ocsp_response): 85 + self.ocsp_response = ocsp_response 86 + return self 87 + 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). 91 + def parse(self, p): 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: 96 + raise SyntaxError() 97 + ocsp_response = p.getVarBytes(3) 98 + if not ocsp_response: 99 + # Can't be empty 100 + raise SyntaxError() 101 + self.ocsp_response = ocsp_response 102 + p.stopLengthCheck() 103 + return self 104 + 105 + def write(self): 106 + w = Writer() 107 + w.add(CertificateStatusType.ocsp, 1) 108 + w.addVarSeq(bytearray(self.ocsp_response), 1, 3) 109 + return self.postWrite(w) 110 + 111 class CertificateRequest(HandshakeMsg): 112 def __init__(self): 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 bd92161..b9797d2 100755 116 --- a/third_party/tlslite/tlslite/tlsconnection.py 117 +++ b/third_party/tlslite/tlslite/tlsconnection.py 118 @@ -967,7 +967,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. 125 126 This function performs an SSL or TLS handshake. Depending on 127 @@ -1051,6 +1051,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. 130 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. 140 + 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 @@ -1064,7 +1074,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): 150 pass 151 152 153 @@ -1076,7 +1086,8 @@ class TLSConnection(TLSRecordLayer): 154 nextProtos=None, anon=False, 155 tlsIntolerant=None, 156 signedCertTimestamps=None, 157 - fallbackSCSV=False 158 + fallbackSCSV=False, 159 + ocspResponse=None 160 ): 161 """Start a server handshake operation on the TLS connection. 162 163 @@ -1098,7 +1109,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): 171 yield result 172 173 @@ -1108,7 +1120,8 @@ class TLSConnection(TLSRecordLayer): 174 settings, reqCAs, 175 tacks, activationFlags, 176 nextProtos, anon, 177 - tlsIntolerant, signedCertTimestamps, fallbackSCSV): 178 + tlsIntolerant, signedCertTimestamps, fallbackSCSV, 179 + ocspResponse): 180 181 self._handshakeStart(client=False) 182 183 @@ -1178,6 +1191,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 189 190 # Perform the SRP key exchange 191 clientCertChain = None 192 @@ -1194,7 +1209,7 @@ class TLSConnection(TLSRecordLayer): 193 for result in self._serverCertKeyExchange(clientHello, serverHello, 194 certChain, privateKey, 195 reqCert, reqCAs, cipherSuite, 196 - settings): 197 + settings, ocspResponse): 198 if result in (0,1): yield result 199 else: break 200 (premasterSecret, clientCertChain) = result 201 @@ -1471,7 +1486,7 @@ class TLSConnection(TLSRecordLayer): 202 def _serverCertKeyExchange(self, clientHello, serverHello, 203 serverCertChain, privateKey, 204 reqCert, reqCAs, cipherSuite, 205 - settings): 206 + settings, ocspResponse): 207 #Send ServerHello, Certificate[, CertificateRequest], 208 #ServerHelloDone 209 msgs = [] 210 @@ -1481,6 +1496,8 @@ class TLSConnection(TLSRecordLayer): 211 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)) 219