]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
x509: fix OCSP BasicResponse leak in in-verify check
authorMounir IDRASSI <mounir.idrassi@idrix.fr>
Mon, 29 Jun 2026 07:00:00 +0000 (16:00 +0900)
committerNorbert Pocs <norbertp@openssl.org>
Mon, 3 Aug 2026 07:02:26 +0000 (09:02 +0200)
In check_cert_ocsp_resp(), OCSP_response_get1_basic() returns an owning
OCSP_BASICRESP. The combined-condition early return on
OCSP_resp_count(bs) < 1 bypassed the end: cleanup label, leaking bs when
a stapled OCSP response decoded to a BasicResponse with no single
responses.

Separate the count check from the acquisition and route the empty case
through end: (ret = X509_V_ERR_OCSP_NO_RESPONSE; goto end;) so bs is
freed while preserving the previous return value. Reachable only with
the non-default X509_V_FLAG_OCSP_RESP_CHECK with peer-supplied (e.g.
TLS 1.3 stapled) responses.

Reported-by: geeknik (https://github.com/geeknik)
Suggested-by: geeknik (https://github.com/geeknik)
Fixes #31759

Reviewed-by: Andrew Dinh <andrewd@openssl.org>
Reviewed-by: Daniel Kubec <kubec@openssl.foundation>
MergeDate: Mon Aug  3 07:02:30 2026
(Merged from https://github.com/openssl/openssl/pull/31764)

crypto/x509/x509_vfy.c

index 977672d8fcaa911fc94218adc91122f90a0bb9a1..ff06e402dc4adf17b770a384e50bab381347ae19 100644 (file)
@@ -1307,10 +1307,20 @@ static int check_cert_ocsp_resp(X509_STORE_CTX *ctx)
         return X509_V_ERR_OCSP_NO_RESPONSE;
 
     if ((resp = sk_OCSP_RESPONSE_value(ctx->ocsp_resp, ctx->error_depth)) == NULL
-        || (bs = OCSP_response_get1_basic(resp)) == NULL
-        || (num = OCSP_resp_count(bs)) < 1)
+        || (bs = OCSP_response_get1_basic(resp)) == NULL)
         return X509_V_ERR_OCSP_NO_RESPONSE;
 
+    /*
+     * OCSP_response_get1_basic() returns an owning reference, so once bs is
+     * non-NULL it must be released via the end: cleanup label. Route an empty
+     * BasicResponse (no single responses) through end: rather than returning
+     * directly, otherwise bs leaks.
+     */
+    if ((num = OCSP_resp_count(bs)) < 1) {
+        ret = X509_V_ERR_OCSP_NO_RESPONSE;
+        goto end;
+    }
+
     if (OCSP_response_status(resp) != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
         OCSP_BASICRESP_free(bs);
         bs = NULL;