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.
This commit is contained in:
Martin Willi
2014-03-31 14:40:33 +02:00
parent a844b65890
commit 91d71abb16
3 changed files with 65 additions and 10 deletions
@@ -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;
}
@@ -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
@@ -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