|
| 1 | +From 731861b9de8dccaf7d3b0c1446833051e48670c2 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Alexander Sosedkin <asosedkin@redhat.com> |
| 3 | +Date: Thu, 12 Mar 2026 09:48:57 +0100 |
| 4 | +Subject: [PATCH] cert-session: fix multi-entry OCSP revocation bypass |
| 5 | + |
| 6 | +In check_ocsp_response(), the code first searched |
| 7 | +for the SingleResponse that matches the certificate being validated. |
| 8 | +But later, the status was retrieved from entry 0 unconditionally, |
| 9 | +rather than from the matched resp_indx. |
| 10 | +As a result, if entry 0 corresponded to a different certificate and was good, |
| 11 | +while the matched entry for the peer certificate is revoked, |
| 12 | +the revocation check could've mistakenly accept the certificate. |
| 13 | + |
| 14 | +Reported-by: Oleh Konko (1seal) <security@1seal.org> |
| 15 | +Reported-by: Joshua Rogers of AISLE Research Team <joshua@joshua.hu> |
| 16 | +Fixes: #1801 |
| 17 | +Fixes: #1812 |
| 18 | +Fixes: CVE-2026-3832 |
| 19 | +Fixes: GNUTLS-SA-2026-04-29-12 |
| 20 | +CVSS: 3.7 Low CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N |
| 21 | +Introduced-in: ae404fe8488dee424876b5963c00d7e041672415 3.8.9 |
| 22 | +Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com> |
| 23 | + |
| 24 | +Upstream Patch Reference: https://gitlab.com/gnutls/gnutls/-/commit/731861b9de8dccaf7d3b0c1446833051e48670c2.patch |
| 25 | +--- |
| 26 | + lib/cert-session.c | 14 +++++++++----- |
| 27 | + 1 file changed, 9 insertions(+), 5 deletions(-) |
| 28 | + |
| 29 | +diff --git a/lib/cert-session.c b/lib/cert-session.c |
| 30 | +index 5a4b997..53de6f1 100644 |
| 31 | +--- a/lib/cert-session.c |
| 32 | ++++ b/lib/cert-session.c |
| 33 | +@@ -236,7 +236,7 @@ static int check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert, |
| 34 | + { |
| 35 | + gnutls_ocsp_resp_t resp; |
| 36 | + int ret; |
| 37 | +- unsigned int status, cert_status; |
| 38 | ++ unsigned int status, cert_status, resp_indx; |
| 39 | + time_t rtime, vtime, ntime, now; |
| 40 | + int check_failed = 0; |
| 41 | + |
| 42 | +@@ -277,7 +277,11 @@ static int check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert, |
| 43 | + goto cleanup; |
| 44 | + } |
| 45 | + |
| 46 | +- ret = gnutls_ocsp_resp_check_crt(resp, 0, cert); |
| 47 | ++ for (resp_indx = 0;; resp_indx++) { |
| 48 | ++ ret = gnutls_ocsp_resp_check_crt(resp, resp_indx, cert); |
| 49 | ++ if (ret == 0 || ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) |
| 50 | ++ break; |
| 51 | ++ } |
| 52 | + if (ret < 0) { |
| 53 | + ret = gnutls_assert_val(0); |
| 54 | + _gnutls_audit_log( |
| 55 | +@@ -339,9 +343,9 @@ static int check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert, |
| 56 | + goto cleanup; |
| 57 | + } |
| 58 | + |
| 59 | +- ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL, |
| 60 | +- &cert_status, &vtime, &ntime, &rtime, |
| 61 | +- NULL); |
| 62 | ++ ret = gnutls_ocsp_resp_get_single(resp, resp_indx, NULL, NULL, NULL, |
| 63 | ++ NULL, &cert_status, &vtime, &ntime, |
| 64 | ++ &rtime, NULL); |
| 65 | + if (ret < 0) { |
| 66 | + _gnutls_audit_log( |
| 67 | + session, |
| 68 | +-- |
| 69 | +2.45.4 |
| 70 | + |
0 commit comments