}
static int
- handle_ip_extension(X509_EXTENSION *ext, struct resources *resources, int flags)
+ handle_ip_extension(
+ #if OPENSSL_VERSION_MAJOR >= 4
+ X509_EXTENSION const *ext,
+ #else
+ X509_EXTENSION *ext,
+ #endif
- struct resources *resources)
++ struct resources *resources, int flags)
{
- ASN1_OCTET_STRING *string;
+ ASN1_OCTET_STRING const *string;
struct IPAddrBlocks *blocks;
OCTET_STRING_t *family;
int i;
int error;
+ if (!X509_EXTENSION_get_critical(ext))
+ return pr_val_err("IP extension is not marked critical.");
+
string = X509_EXTENSION_get_data(ext);
- error = asn1_decode(string->data, string->length, &asn_DEF_IPAddrBlocks,
+ error = asn1_decode(ASN1_STRING_get0_data(string),
+ ASN1_STRING_length(string), &asn_DEF_IPAddrBlocks,
(void **) &blocks, true);
if (error)
return error;
}
static int
- handle_asn_extension(X509_EXTENSION *ext, struct resources *resources,
- int flags)
+ handle_asn_extension(
+ #if OPENSSL_VERSION_MAJOR >= 4
+ X509_EXTENSION const *ext,
+ #else
+ X509_EXTENSION *ext,
+ #endif
- struct resources *resources, bool allow_inherit)
++ struct resources *resources, int flags)
{
- ASN1_OCTET_STRING *string;
+ ASN1_OCTET_STRING const *string;
struct ASIdentifiers *ids;
int error;
return error;
}
-static int
-__certificate_get_resources(X509 *cert, struct resources *resources,
- int addr_nid, int asn_nid, int bad_addr_nid, int bad_asn_nid,
- char const *policy_rfc, char const *bad_ext_rfc, bool allow_asn_inherit)
+/**
+ * Copies the resources from @cert to @resources.
+ */
+int
+certificate_get_resources(X509 *cert, struct resources *resources,
+ enum cert_type type, enum ee_type eet)
{
+ int allowed_ip_nid = NID_undef;
+ int allowed_as_nid = NID_undef;
+ int flags = RF_ALLOW_ALL;
+
+ int nid_ip1 = NID_sbgp_ipAddrBlock;
+ int nid_ip2 = nid_ipAddrBlocksv2();
+ int nid_as1 = NID_sbgp_autonomousSysNum;
+ int nid_as2 = nid_autonomousSysIdsv2();
+
+ #if OPENSSL_VERSION_MAJOR >= 4
+ X509_EXTENSION const *ext;
+ #else
X509_EXTENSION *ext;
- int nid;
- int i;
+ #endif
+ int extnid;
+ int e;
int error;
- bool ip_ext_found = false;
- bool asn_ext_found = false;
-
- /* Reference: X509_get_ext_d2i */
- /* rfc6487#section-2 */
- for (i = 0; i < X509_get_ext_count(cert); i++) {
- ext = X509_get_ext(cert, i);
- nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
+ switch (type) {
+ case CERTYPE_TA:
+ case CERTYPE_CA:
+ case CERTYPE_BGPSEC:
+ switch (resources_get_policy(resources)) {
+ case RPKI_POLICY_RFC6484:
+ allowed_ip_nid = nid_ip1;
+ allowed_as_nid = nid_as1;
+ break;
+ case RPKI_POLICY_RFC8360:
+ allowed_ip_nid = nid_ip2;
+ allowed_as_nid = nid_as2;
+ }
+ break;
+ case CERTYPE_EE:
+ switch (eet) {
+ case EET_ROA:
+ switch (resources_get_policy(resources)) {
+ case RPKI_POLICY_RFC6484:
+ allowed_ip_nid = nid_ip1; break;
+ case RPKI_POLICY_RFC8360:
+ allowed_ip_nid = nid_ip2;
+ }
+ flags &= ~RF_ALLOW_INHERIT;
+ break;
+ case EET_ASPA:
+ switch (resources_get_policy(resources)) {
+ case RPKI_POLICY_RFC6484:
+ allowed_as_nid = nid_as1; break;
+ case RPKI_POLICY_RFC8360:
+ allowed_as_nid = nid_as2;
+ }
+ flags = 0;
+ break;
+ case EET_MFT:
+ case EET_GBR:
+ /*
+ * RFC6487:
+ *
+ * > Either the IP Resources extension, or the AS
+ * > Resources extension, or both, MUST be present in
+ * > all RPKI certificates
+ *
+ * This requirement seems counterproductive,
+ * but I guess it's too late to fix it.
+ */
+ switch (resources_get_policy(resources)) {
+ case RPKI_POLICY_RFC6484:
+ allowed_ip_nid = nid_ip1;
+ allowed_as_nid = nid_as1;
+ break;
+ case RPKI_POLICY_RFC8360:
+ allowed_ip_nid = nid_ip2;
+ allowed_as_nid = nid_as2;
+ }
+ break;
+ }
+ break;
+ }
- if (nid == addr_nid) {
- if (ip_ext_found)
- return pr_val_err("Multiple IP extensions found.");
- if (!X509_EXTENSION_get_critical(ext))
- return pr_val_err("The IP extension is not marked as critical.");
+ for (e = 0; e < X509_get_ext_count(cert); e++) {
+ ext = X509_get_ext(cert, e);
+ extnid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
- pr_val_debug("IP {");
- error = handle_ip_extension(ext, resources);
- pr_val_debug("}");
- ip_ext_found = true;
+ if (extnid == nid_ip1 || extnid == nid_ip2) {
+ if (extnid != allowed_ip_nid)
+ return pr_val_err("Found an unexpected IP Resources extension.");
+ error = handle_ip_extension(ext, resources, flags);
if (error)
return error;
+ allowed_ip_nid = NID_undef;
- } else if (nid == asn_nid) {
- if (asn_ext_found)
- return pr_val_err("Multiple AS extensions found.");
- if (!X509_EXTENSION_get_critical(ext))
- return pr_val_err("The AS extension is not marked as critical.");
-
- pr_val_debug("ASN {");
- error = handle_asn_extension(ext, resources,
- allow_asn_inherit);
- pr_val_debug("}");
- asn_ext_found = true;
+ } else if (extnid == nid_as1 || extnid == nid_as2) {
+ if (extnid != allowed_as_nid)
+ return pr_val_err("Found an unexpected AS Resources extension.");
+ error = handle_asn_extension(ext, resources, flags);
if (error)
return error;
-
- } else if (nid == bad_addr_nid) {
- return pr_val_err("Certificate has an RFC%s policy, but contains an RFC%s IP extension.",
- policy_rfc, bad_ext_rfc);
- } else if (nid == bad_asn_nid) {
- return pr_val_err("Certificate has an RFC%s policy, but contains an RFC%s ASN extension.",
- policy_rfc, bad_ext_rfc);
+ allowed_as_nid = NID_undef;
}
}