pyopenssl icon indicating copy to clipboard operation
pyopenssl copied to clipboard

How to OCSP stapling?

Open ferfersan6 opened this issue 4 years ago • 1 comments

I have been looking for a python package which allows the use of OCSP stapling. Found PyOpenSSL but I am not sure if it covers everything needed for the OCSP stapling. I would like to wrap the TLS handshake extensions regarding to OCSP, defined in IETF RFC 6066. As far as I know, PyOpenSSL just let you wrap an OCSP request with "set_ocsp_server_callback", but no data from the request is passed to that callback function, so it would be more like a "blind" response (as you do not know what/how you are being requested) Am I using this package in a wrong way? Is it possible to get the extensions data (ResponderID, for example)?

If this package does not support this functionality, is there any available?.

Thanks.

ferfersan6 avatar May 31 '21 13:05 ferfersan6

It's not easy, and not well documented. You have to use cryptography's ocsp module to validate the stapled response. This is how we did it in PyMongo: https://github.com/mongodb/mongo-python-driver/blob/master/pymongo/ocsp_support.py https://github.com/mongodb/mongo-python-driver/blob/3.12.0/pymongo/pyopenssl_context.py#L183-L185

behackett avatar Sep 15 '21 16:09 behackett

While the above answer is a good example of how to validate a stapled OCSP response on the client side, I believe the original question was about how to implement the server side.

After a server receives an OCSP staple request (which can include a list of ResponderIDs to use), the callback set by set_ocsp_server_callback() will be called with the following params:

int (*callback)(SSL *, void *)

Note that none of these is the request to be processed. The void * param is arbitrary data that is passed by the user when first setting the callback using set_ocsp_server_callback().

Since this callback is called to provide an answer to the OCSP staple request sent by the client, it should have access to that request in order to inspect it and act accordingly. From the RFC (emphasis mine):

Servers that receive a client hello containing the "status_request" extension MAY return a suitable certificate status response to the client along with their certificate. If OCSP is requested, they SHOULD use the information contained in the extension when selecting an OCSP responder and SHOULD include request_extensions in the OCSP request.

After looking at the OpenSSL code, this can be done (in OpenSSL) by calling SSL_get_tlsext_status_ids(SSL*, void*), which will return the stack of OCSP_RESPID set by the last received OCSP stapling request (source). Unfortunately this function/macro is not documented in the OpenSSL docs, and more relevantly, pyOpenSSL does not provide a binding for it so inspecting the request is currently not possible using this library.

@woodruffw @mhils @reaperhulk I think this one can be closed now

facutuesca avatar Oct 04 '23 08:10 facutuesca