diff options
author | Martin Willi <martin@revosec.ch> | 2014-03-25 14:34:58 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2014-03-31 14:40:33 +0200 |
commit | 91d71abb16a9b15bbcd7f6cbefb806408be3b92d (patch) | |
tree | 78316a3926aeef1358ad770fee3401fc56af7fa7 | |
parent | a844b6589034ff53e845fb9013d69dac02385453 (diff) | |
download | strongswan-91d71abb16a9b15bbcd7f6cbefb806408be3b92d.tar.bz2 strongswan-91d71abb16a9b15bbcd7f6cbefb806408be3b92d.tar.xz |
revocation: Restrict OCSP signing to specific certificates
To avoid considering each cached OCSP response and evaluating its trustchain,
we limit the certificates considered for OCSP signing to:
- The issuing CA of the checked certificate
- A directly delegated signer by the same CA, having the OCSP signer constraint
- Any locally installed (trusted) certificate having the OCSP signer constraint
The first two options cover the requirements from RFC 6960 2.6. For
compatibility with non-conforming CAs, we allow the third option as exception,
but require the installation of such certificates locally.
-rw-r--r-- | src/libstrongswan/plugins/revocation/revocation_validator.c | 70 | ||||
-rw-r--r-- | testing/tests/ikev2/ocsp-no-signer-cert/evaltest.dat | 2 | ||||
-rw-r--r-- | testing/tests/ikev2/ocsp-untrusted-cert/evaltest.dat | 3 |
3 files changed, 65 insertions, 10 deletions
diff --git a/src/libstrongswan/plugins/revocation/revocation_validator.c b/src/libstrongswan/plugins/revocation/revocation_validator.c index 284bd1f7f..eb9065fb3 100644 --- a/src/libstrongswan/plugins/revocation/revocation_validator.c +++ b/src/libstrongswan/plugins/revocation/revocation_validator.c @@ -93,35 +93,92 @@ static certificate_t *fetch_ocsp(char *url, certificate_t *subject, /** * check the signature of an OCSP response */ -static bool verify_ocsp(ocsp_response_t *response) +static bool verify_ocsp(ocsp_response_t *response, certificate_t *ca) { certificate_t *issuer, *subject; identification_t *responder; ocsp_response_wrapper_t *wrapper; enumerator_t *enumerator; - bool verified = FALSE; + x509_t *x509; + bool verified = FALSE, found = FALSE; wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE); subject = &response->certificate; responder = subject->get_issuer(subject); - enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr, + + /* check OCSP response using CA or directly delegated OCSP signer */ + enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, CERT_X509, KEY_ANY, responder, FALSE); - while (enumerator->enumerate(enumerator, &issuer, NULL)) + while (enumerator->enumerate(enumerator, &issuer)) { + x509 = (x509_t*)issuer; + if (!issuer->get_validity(issuer, NULL, NULL, NULL)) + { /* OCSP signer currently invalid */ + continue; + } + found = TRUE; + if (!ca->equals(ca, issuer)) + { /* delegated OCSP signer? */ + if (!lib->credmgr->issued_by(lib->credmgr, issuer, ca, NULL)) + { /* OCSP response not signed by CA, nor delegated OCSP signer */ + continue; + } + if (!(x509->get_flags(x509) & X509_OCSP_SIGNER)) + { /* delegated OCSP signer does not have OCSP signer flag */ + continue; + } + } if (lib->credmgr->issued_by(lib->credmgr, subject, issuer, NULL)) { DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"", - issuer->get_subject(issuer)); + issuer->get_subject(issuer)); verified = TRUE; break; } + DBG1(DBG_CFG, "ocsp response verification failed, " + "invalid signature"); } enumerator->destroy(enumerator); + if (!verified) + { + /* as fallback, use any locally installed OCSP signer certificate */ + enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, + CERT_X509, KEY_ANY, responder, TRUE); + while (enumerator->enumerate(enumerator, &issuer)) + { + x509 = (x509_t*)issuer; + /* while issued_by() accepts both OCSP signer or CA basic + * constraint flags to verify OCSP responses, unrelated but trusted + * OCSP signers must explicitly have the OCSP signer flag set. */ + if ((x509->get_flags(x509) & X509_OCSP_SIGNER) && + issuer->get_validity(issuer, NULL, NULL, NULL)) + { + found = TRUE; + if (lib->credmgr->issued_by(lib->credmgr, subject, issuer, NULL)) + { + DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"", + issuer->get_subject(issuer)); + verified = TRUE; + break; + } + DBG1(DBG_CFG, "ocsp response verification failed, " + "invalid signature"); + } + } + enumerator->destroy(enumerator); + } + lib->credmgr->remove_local_set(lib->credmgr, &wrapper->set); wrapper->destroy(wrapper); + + if (!found) + { + DBG1(DBG_CFG, "ocsp response verification failed, " + "no signer certificate '%Y' found", responder); + } return verified; } @@ -140,9 +197,8 @@ static certificate_t *get_better_ocsp(certificate_t *cand, certificate_t *best, response = (ocsp_response_t*)cand; /* check ocsp signature */ - if (!verify_ocsp(response)) + if (!verify_ocsp(response, &issuer->interface)) { - DBG1(DBG_CFG, "ocsp response verification failed"); cand->destroy(cand); return best; } diff --git a/testing/tests/ikev2/ocsp-no-signer-cert/evaltest.dat b/testing/tests/ikev2/ocsp-no-signer-cert/evaltest.dat index a2ce5ad93..a6ae74fe3 100644 --- a/testing/tests/ikev2/ocsp-no-signer-cert/evaltest.dat +++ b/testing/tests/ikev2/ocsp-no-signer-cert/evaltest.dat @@ -1,5 +1,5 @@ moon:: cat /var/log/daemon.log::requesting ocsp status from::YES -moon:: cat /var/log/daemon.log::ocsp response verification failed::YES +moon:: cat /var/log/daemon.log::ocsp response verification failed, no signer::YES moon:: cat /var/log/daemon.log::certificate status is not available::YES moon:: cat /var/log/daemon.log::constraint check failed: RULE_CRL_VALIDATION is FAILED, but requires at least GOOD::YES moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED::NO diff --git a/testing/tests/ikev2/ocsp-untrusted-cert/evaltest.dat b/testing/tests/ikev2/ocsp-untrusted-cert/evaltest.dat index 6ba1be6b1..1eb84ca66 100644 --- a/testing/tests/ikev2/ocsp-untrusted-cert/evaltest.dat +++ b/testing/tests/ikev2/ocsp-untrusted-cert/evaltest.dat @@ -1,6 +1,5 @@ moon:: cat /var/log/daemon.log::requesting ocsp status from::YES -moon:: cat /var/log/daemon.log::self-signed certificate.*is not trusted::YES -moon:: cat /var/log/daemon.log::ocsp response verification failed::YES +moon:: cat /var/log/daemon.log::ocsp response verification failed, no signer::YES moon:: cat /var/log/daemon.log::certificate status is not available::YES moon:: cat /var/log/daemon.log::constraint check failed: RULE_CRL_VALIDATION is FAILED, but requires at least GOOD::YES moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED::NO |