MINOR: ssl: Add helper function that checks the validity of an OCSP response

This helper function will check that an OCSP response is valid, meaning
that the proper "Content-Type: application/ocsp-response" header is
present and the data itself is a proper OCSP_RESPONSE that can be
checked thanks to the issuer certificate.
This commit is contained in:
Remi Tricot-Le Breton 2022-12-20 11:11:06 +01:00 committed by William Lallemand
parent e09d2ae598
commit c0b4058e7e
2 changed files with 68 additions and 0 deletions

View File

@ -90,6 +90,8 @@ int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err);
int ssl_ocsp_get_uri_from_cert(X509 *cert, struct buffer *out, char **err);
int ssl_ocsp_create_request_details(const OCSP_CERTID *certid, struct buffer *req_url,
struct buffer *req_body, char **err);
int ssl_ocsp_check_response(STACK_OF(X509) *chain, X509 *issuer,
struct buffer *respbuf, char **err);
#endif
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,

View File

@ -1248,6 +1248,72 @@ int ssl_ocsp_create_request_details(const OCSP_CERTID *certid, struct buffer *re
return errcode;
}
/*
* Parse an OCSP_RESPONSE contained in <respbuf> and check its validity in
* regard to the contents of <ckch> or the <issuer> certificate.
* Certificate_ocsp structure does not keep a reference to the corresponding
* ckch_store so outside of a CLI context (see "send ssl ocsp-response"
* command), we only have an easy access to the issuer's certificate whose
* reference is held in the structure.
* Return 0 in case of success, 1 otherwise.
*/
int ssl_ocsp_check_response(STACK_OF(X509) *chain, X509 *issuer,
struct buffer *respbuf, char **err)
{
int ret = 1;
int n;
OCSP_RESPONSE *response = NULL;
OCSP_BASICRESP *basic = NULL;
X509_STORE *store = NULL;
const unsigned char *start = (const unsigned char*)b_orig(respbuf);
if (!chain && !issuer) {
memprintf(err, "check_ocsp_response needs a certificate validation chain or an issuer certificate");
goto end;
}
response = d2i_OCSP_RESPONSE(NULL, &start, b_data(respbuf));
if (!response) {
memprintf(err, "d2i_OCSP_RESPONSE() failed");
goto end;
}
n = OCSP_response_status(response);
if (n != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
memprintf(err, "OCSP response not successful (%d: %s)",
n, OCSP_response_status_str(n));
goto end;
}
basic = OCSP_response_get1_basic(response);
if (basic == NULL) {
memprintf(err, "OCSP_response_get1_basic() failed");
goto end;
}
/* Add ocsp issuer certificate to a store in order verify the ocsp
* response. */
store = X509_STORE_new();
if (!store) {
memprintf(err, "X509_STORE_new() failed");
goto end;
}
X509_STORE_add_cert(store, issuer);
if (OCSP_basic_verify(basic, chain, store, 0) != 1) {
memprintf(err, "OCSP_basic_verify() failed");
goto end;
}
ret = 0;
end:
X509_STORE_free(store);
OCSP_RESPONSE_free(response);
OCSP_BASICRESP_free(basic);
return ret;
}
#endif /* defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP */
/*