aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2014-03-25 14:34:58 +0100
committerMartin Willi <martin@revosec.ch>2014-03-31 14:40:33 +0200
commit91d71abb16a9b15bbcd7f6cbefb806408be3b92d (patch)
tree78316a3926aeef1358ad770fee3401fc56af7fa7
parenta844b6589034ff53e845fb9013d69dac02385453 (diff)
downloadstrongswan-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.c70
-rw-r--r--testing/tests/ikev2/ocsp-no-signer-cert/evaltest.dat2
-rw-r--r--testing/tests/ikev2/ocsp-untrusted-cert/evaltest.dat3
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