From: Remi Tricot-Le Breton Date: Tue, 20 Dec 2022 10:11:06 +0000 (+0100) Subject: MINOR: ssl: Add helper function that checks the validity of an OCSP response X-Git-Tag: v2.8-dev1~91 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c0b4058e7e9fa6a83f3ec0e771f5469b362d02b6;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/haproxy/ssl_sock.h b/include/haproxy/ssl_sock.h index 1c48c1474f..16428e86cd 100644 --- a/include/haproxy/ssl_sock.h +++ b/include/haproxy/ssl_sock.h @@ -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, diff --git a/src/ssl_sock.c b/src/ssl_sock.c index c9de250281..44f515c39d 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -1248,6 +1248,72 @@ end: return errcode; } +/* + * Parse an OCSP_RESPONSE contained in and check its validity in + * regard to the contents of or the 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 */ /*