For some reason libcrypto doesn't check this part of RFC 5280, 4.2: A certificate MUST NOT include more than one instance of a particular extension.
With the badCertSIA2x.cer from Ties's test artefacts, I get this warning: rpki-client: badCertSIA2x.cer: RFC 5280 section 4.2: duplicate subjectInfoAccess extension https://github.com/ties/rpki-commons-object-scan/tree/main/app/src/test/resources/bbn-conformance/root The diff below is straightforward. It does not help EE certs. That could be done similarly. Index: cert.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v retrieving revision 1.109 diff -u -p -r1.109 cert.c --- cert.c 20 Jun 2023 12:28:08 -0000 1.109 +++ cert.c 20 Jun 2023 18:46:22 -0000 @@ -648,7 +648,6 @@ cert_parse_pre(const char *fn, const uns { const unsigned char *oder; int extsz; - int sia_present = 0; size_t i; X509 *x = NULL; X509_EXTENSION *ext = NULL; @@ -658,7 +657,10 @@ cert_parse_pre(const char *fn, const uns ASN1_OBJECT *obj; EVP_PKEY *pkey; struct parse p; - int nid; + int nid, ip, as, sia, cp, crldp, aia, aki, ski, + eku, bc, ku; + + nid = ip = as = sia = cp = crldp = aia = aki = ski = eku = bc = ku = 0; /* just fail for empty buffers, the warning was printed elsewhere */ if (der == NULL) @@ -721,38 +723,58 @@ cert_parse_pre(const char *fn, const uns obj = X509_EXTENSION_get_object(ext); assert(obj != NULL); - switch (OBJ_obj2nid(obj)) { + switch ((nid = OBJ_obj2nid(obj))) { case NID_sbgp_ipAddrBlock: + if (ip++ >= 1) + goto dup; if (!sbgp_ipaddrblk(&p, ext)) goto out; break; case NID_sbgp_autonomousSysNum: + if (as++ > 0) + goto dup; if (!sbgp_assysnum(&p, ext)) goto out; break; case NID_sinfo_access: - sia_present = 1; + if (sia++ > 0) + goto dup; if (!sbgp_sia(&p, ext)) goto out; break; case NID_certificate_policies: + if (cp++ > 0) + goto dup; if (!certificate_policies(&p, ext)) goto out; break; case NID_crl_distribution_points: - /* ignored here, handled later */ + if (crldp++ > 0) + goto dup; break; case NID_info_access: + if (aia++ > 0) + goto dup; break; case NID_authority_key_identifier: + if (aki++ > 0) + goto dup; break; case NID_subject_key_identifier: + if (ski++ > 0) + goto dup; break; case NID_ext_key_usage: + if (eku++ > 0) + goto dup; break; case NID_basic_constraints: + if (bc++ > 0) + goto dup; break; case NID_key_usage: + if (ku++ > 0) + goto dup; break; default: /* unexpected extensions warrant investigation */ @@ -831,7 +853,7 @@ cert_parse_pre(const char *fn, const uns goto out; } } - if (sia_present) { + if (sia) { warnx("%s: unexpected SIA extension in BGPsec cert", p.fn); goto out; @@ -850,7 +872,10 @@ cert_parse_pre(const char *fn, const uns p.res->x509 = x; return p.res; -out: + dup: + warnx("%s: RFC 5280 section 4.2: duplicate %s extension", fn, + OBJ_nid2sn(nid)); + out: cert_free(p.res); X509_free(x); return NULL;