The OpenSSL function 'X509_STORE_CTX_set0_crls' wasn't taking into consideration the CRL stack; the simple way to check revocation was doing it manually.
Pay special attention to manifests, the CRL stack that's received when its EE is validated, is grandparent's CRL; so, in this case, validate manifests on its own CRLDP.
signed_object_args_init(struct signed_object_args *args,
struct rpki_uri *uri,
STACK_OF(X509_CRL) *crls,
- bool force_inherit)
+ bool force_inherit,
+ bool use_crldp)
{
args->res = resources_create(force_inherit);
if (args->res == NULL)
args->uri = uri;
args->crls = crls;
+ args->use_crldp = use_crldp;
memset(&args->refs, 0, sizeof(args->refs));
return 0;
}
handle_sdata_certificate(ANY_t *cert_encoded, struct signed_object_args *args,
OCTET_STRING_t *sid, ANY_t *signedData, SignatureValue_t *signature)
{
+ STACK_OF(X509_CRL) *crls;
const unsigned char *tmp;
X509 *cert;
enum rpki_policy policy;
goto end1;
}
- error = certificate_validate_chain(cert, args->crls);
+ crls = args->crls;
+ if (args->use_crldp) {
+ crls = sk_X509_CRL_new_null();
+ if (crls == NULL) {
+ error = pr_enomem();
+ goto end2;
+ }
+ }
+
+ error = certificate_validate_chain(cert, crls);
if (error)
- goto end2;
+ goto end3;
error = certificate_validate_rfc6487(cert, false);
if (error)
- goto end2;
+ goto end3;
error = certificate_validate_extensions_ee(cert, sid, &args->refs,
&policy);
if (error)
- goto end2;
+ goto end3;
error = certificate_validate_signature(cert, signedData, signature);
if (error)
- goto end2;
+ goto end3;
+
+ /* Validate in CRL at CRLDP */
+ if (args->use_crldp) {
+ error = certificate_revoked_at_crldp(cert, &args->refs);
+ if (error)
+ goto end3;
+ }
resources_set_policy(args->res, policy);
error = certificate_get_resources(cert, args->res);
if (error)
- goto end2;
+ goto end3;
+end3:
+ if (args->use_crldp)
+ sk_X509_CRL_free(crls);
end2:
X509_free(cert);
end1:
STACK_OF(X509_CRL) *crls;
/** A copy of the resources carried by the embedded certificate. */
struct resources *res;
+ /** Check if the certificate is revoked at CRLDP, not at crls stack */
+ bool use_crldp;
/**
* A bunch of URLs found in the embedded certificate's extensions,
* recorded for future validation.
};
int signed_object_args_init(struct signed_object_args *, struct rpki_uri *,
- STACK_OF(X509_CRL) *, bool);
+ STACK_OF(X509_CRL) *, bool, bool);
void signed_object_args_cleanup(struct signed_object_args *);
int signed_data_decode(ANY_t *, struct signed_object_args *args,
#include "asn1/oid.h"
#include "asn1/asn1c/IPAddrBlocks.h"
#include "crypto/hash.h"
+#include "object/crl.h"
#include "object/name.h"
#include "object/manifest.h"
#include "rsync/rsync.h"
return error;
}
+static bool
+cert_revoked(ASN1_INTEGER *serialNumber, X509_CRL *crl)
+{
+ STACK_OF(X509_REVOKED) *revoked;
+ X509_REVOKED *item;
+ int index;
+
+ revoked = X509_CRL_get_REVOKED(crl);
+ for (index = 0; index < sk_X509_REVOKED_num(revoked); index++) {
+ item = sk_X509_REVOKED_value(revoked, index);
+ if (ASN1_INTEGER_cmp(X509_REVOKED_get0_serialNumber(item),
+ serialNumber) == 0)
+ return true;
+ }
+
+ return false;
+}
+
int
certificate_validate_chain(X509 *cert, STACK_OF(X509_CRL) *crls)
{
X509_STORE_CTX_trusted_stack(ctx,
certstack_get_x509s(validation_certstack(state)));
- X509_STORE_CTX_set0_crls(ctx, crls);
+
+ /*
+ * The function 'X509_STORE_CTX_set0_crls' could be used with a
+ * 'X509_VERIFY_PARAM' of 'X509_V_FLAG_CRL_CHECK', but this didn't
+ * worked as expected.
+ *
+ * Instead of that, fetch the last CRL (father's) and check revoked
+ * serials "manually".
+ */
+ if (sk_X509_CRL_num(crls) > 0 &&
+ cert_revoked(X509_get_serialNumber(cert),
+ sk_X509_CRL_value(crls, sk_X509_CRL_num(crls) - 1))) {
+ pr_err("Certificate validation failed: certificate is revoked");
+ goto abort;
+ }
/*
* HERE'S THE MEAT OF LIBCRYPTO'S VALIDATION.
return -EINVAL;
}
+/*
+ * Load the CRL at CRLDP @refs and check if @cert is revoked there
+ */
+int
+certificate_revoked_at_crldp(X509 *cert, struct certificate_refs *refs)
+{
+ X509_CRL *crl;
+ struct rpki_uri *uri;
+ int error;
+
+ error = uri_create_str(&uri, refs->crldp, strlen(refs->crldp));
+ if (error)
+ return error;
+
+ error = crl_load(uri, &crl);
+ if (error)
+ goto release_uri;
+
+ /* Everything OK so far, error 0 is valid */
+ if (cert_revoked(X509_get_serialNumber(cert), crl)) {
+ error = pr_err("Certificate validation failed: certificate is revoked at CRL");
+ }
+
+ X509_CRL_free(crl);
+release_uri:
+ uri_refput(uri);
+ return error;
+}
+
static int
handle_ip_extension(X509_EXTENSION *ext, struct resources *resources)
{
int certificate_validate_extensions_ee(X509 *, OCTET_STRING_t *,
struct certificate_refs *, enum rpki_policy *);
+int certificate_revoked_at_crldp(X509 *cert, struct certificate_refs *refs);
+
int certificate_traverse(struct rpp *, struct rpki_uri *);
#endif /* SRC_OBJECT_CERTIFICATE_H_ */
if (error)
goto end1;
- error = signed_object_args_init(&sobj_args, uri, crl, true);
+ error = signed_object_args_init(&sobj_args, uri, crl, true, false);
if (error)
goto end1;
pr_debug_add("Manifest '%s' {", uri_get_printable(uri));
fnstack_push_uri(uri);
- error = signed_object_args_init(&sobj_args, uri, crls, false);
+ error = signed_object_args_init(&sobj_args, uri, crls, false, true);
if (error)
goto end1;
if (error)
goto revert_fnstack;
- error = signed_object_args_init(&sobj_args, uri, crl, false);
+ error = signed_object_args_init(&sobj_args, uri, crl, false, false);
if (error)
goto revert_fnstack;