LIBRESSL-SSL_CTX_SET_TLSEXT_STATUS_CB(3)

πŸ“¦ version 4.4.0, in alpine 3.24, arch rolling

πŸ’… SSL_CTX_SET_TLSEXT_STATUS_CB β€” OCSP Certificate Status Request functions ✨

okay so bestie, this is one of those libssl / libcrypto pages β€” like, the actual manual name is SSL_CTX_SET_TLSEXT_STATU(3) (Library Functions Manual, yes the header is slightly abbreviated, we love that for her) β€” and it's all about OCSP Certificate Status Request. It's giving "my certificate has receipts" energy. Let's get into it πŸŽ€


🌸 NAME 🌸

SSL_CTX_set_tlsext_status_cb, SSL_CTX_get_tlsext_status_cb, SSL_CTX_set_tlsext_status_arg, SSL_CTX_get_tlsext_status_arg, SSL_set_tlsext_status_type, SSL_get_tlsext_status_type, SSL_get_tlsext_status_ocsp_resp, SSL_set_tlsext_status_ocsp_resp β€” OCSP Certificate Status Request functions. That's the whole squad, and yes, every single one of them is here. πŸ’–


✨ SYNOPSIS ✨

Library: libssl libcrypto β€” and you're gonna want:

#include <openssl/tls1.h>

Then the whole lineup, character for character:

long
SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx,
    int (*callback)(SSL *, void *));

long
SSL_CTX_get_tlsext_status_cb(SSL_CTX *ctx,
    int (*callback)(SSL *, void *));

long
SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);

long
SSL_CTX_get_tlsext_status_arg(SSL_CTX *ctx, void **arg);

long
SSL_set_tlsext_status_type(SSL *s, int type);

long
SSL_get_tlsext_status_type(SSL *s);

long
SSL_get_tlsext_status_ocsp_resp(ssl, unsigned char **resp);

long
SSL_set_tlsext_status_ocsp_resp(ssl, unsigned char *resp, int len);

πŸ¦‹ DESCRIPTION πŸ¦‹

So a client app can be like "hey server, bestie, send me back an OCSP status response" β€” this is also known as OCSP stapling (iconic name, no notes). To do it, the client calls SSL_set_tlsext_status_type() on an individual SSL object, and it has to happen before the handshake kicks off. Currently the only supported type is TLSEXT_STATUSTYPE_ocsp, and that's the value you pass in the type argument. Periodt.

The client should also provide a callback function, so it can decide what to do with the returned OCSP response β€” that's what SSL_CTX_set_tlsext_status_cb() is for. The callback's whole job is to determine whether the returned OCSP response is acceptable or not. The callback gets passed, as an argument, the value you previously set by calling SSL_CTX_set_tlsext_status_arg(). 🫢

⚠️ Heads up, and this is important: the callback will not be called in the event of a handshake where session resumption occurs β€” because there are, like, no Certificates exchanged in that kind of handshake. It's a whole vibe, just accept it. 😭

You can get the callback you previously set via SSL_CTX_set_tlsext_status_cb() back by calling SSL_CTX_get_tlsext_status_cb(), and the argument by calling SSL_CTX_get_tlsext_status_arg(). Retrieval queen behavior. πŸ’…

On the client side, SSL_get_tlsext_status_type() can be used to figure out whether the client has previously called SSL_set_tlsext_status_type(). It returns TLSEXT_STATUSTYPE_ocsp if it has been called, or -1 otherwise.

On the server side, SSL_get_tlsext_status_type() can be used to figure out whether the client requested OCSP stapling. If the client requested it, this function returns TLSEXT_STATUSTYPE_ocsp, or -1 otherwise. Same function, different side of the story, we love a versatile icon. 🌈

The response the server sent back can be gotten via a call to SSL_get_tlsext_status_ocsp_resp(). *resp gets updated to point to the OCSP response data, and the return value is the length of that data. If the server didn't provide any response data, then *resp will be NULL and the return value from SSL_get_tlsext_status_ocsp_resp() will be -1.

A server application must also call the SSL_CTX_set_tlsext_status_cb() function if it wants to be able to provide clients with OCSP Certificate Status responses. Typically the server callback would:

  • obtain the server certificate that's being sent back to the client, via a call to SSL_get_certificate(3) πŸ“œ
  • obtain the OCSP response to be sent back
  • then set that response data by calling SSL_set_tlsext_status_ocsp_resp()

A pointer to the response data should be provided in the resp argument, and the length of that data should be in the len argument. Slay.


πŸ”₯ RETURN VALUES πŸ”₯

Client-side callback behavior:

  • returns a negative value on error πŸ’€
  • returns 0 if the response is not acceptable β€” in which case the handshake will fail 😬
  • returns a positive value if it's acceptable βœ…

Server-side callback should return one of these:

  • SSL_TLSEXT_ERR_OK β€” meaning the OCSP response that has been set should be returned
  • SSL_TLSEXT_ERR_NOACK β€” meaning an OCSP response should not be returned
  • SSL_TLSEXT_ERR_ALERT_FATAL β€” meaning a fatal error has occurred πŸ’€

As for the rest:

  • SSL_CTX_set_tlsext_status_cb(), SSL_CTX_get_tlsext_status_cb(), SSL_CTX_set_tlsext_status_arg(), SSL_CTX_get_tlsext_status_arg(), SSL_set_tlsext_status_type(), and SSL_set_tlsext_status_ocsp_resp() always return 1, indicating success. Always. Success queens. πŸ‘‘
  • SSL_get_tlsext_status_type() returns TLSEXT_STATUSTYPE_ocsp on the client side if SSL_set_tlsext_status_type() was previously called, or on the server side if the client requested OCSP stapling. Otherwise -1 is returned.
  • SSL_get_tlsext_status_ocsp_resp() returns the length of the OCSP response data, or -1 if there's no OCSP response data.

🧚 SEE ALSO 🧚


⭐ HISTORY ⭐

  • SSL_CTX_set_tlsext_status_cb(), SSL_CTX_set_tlsext_status_arg(), SSL_set_tlsext_status_type(), SSL_get_tlsext_status_ocsp_resp(), and SSL_set_tlsext_status_ocsp_resp() first appeared in OpenSSL 0.9.8h and have been available since OpenBSD 4.5. Ancient. Iconic. OG vibes.
  • SSL_CTX_get_tlsext_status_cb() and SSL_CTX_get_tlsext_status_arg() first appeared in OpenSSL 1.1.0 and have been available since OpenBSD 6.3.
  • SSL_get_tlsext_status_type() first appeared in OpenSSL 1.1.0 and has been available since OpenBSD 7.0. The newest baby of the family 🌱

πŸ’Œ and that's the page bestie! This lil doc? Debian, dated June 8, 2025. Go staple some OCSP, you absolute legend πŸ“πŸ’œ
πŸ“¦ where this page comes from