Download raw body.
rpki-client: fix handling of inherited resources in leaves
On Thu, Sep 10, 2026 at 12:07:52PM +0200, Theo Buehler wrote:
> It's been publicly known at least since Frank Denis's "security audit"
> dumps back in May that the RFC 3779 inheritance handling in libcrypto's
> path validation is broken. Namely, if the certificate to be validated
> inherits resources, X509v3_asid_validate_path(3) and friends can succeed
> even if one of the certs on the path does not have the corresponding
> resource delegation extension at all. RFC 3779's sections 2.3 and 3.3
> clearly require that every cert on the entire validating path have the
> relevant INR delegation extensions. Frank Denis flagged this ASIDs
> extension, but it is obvious that IP addresses have the same problem.
>
> For rpki-client, one of the very few (if not the only) consumers of this
> code in libcrypto, this doesn't matter all that much because it duplicates
> much of the work on INR validation. Per the specification, EE certs with
> inherit elements are only in MFTs, TAKs (of which there are none) and
> the no longer supported GBRs (of which there is one - malformed). Correct
> nesting and presence of RFC 3779 extensions is ensured by rpki-client
> except for the leaf.
>
> RFC 9286, section 5.1, says this for manifest EE certs:
>
> This EE certificate MUST describe its Internet Number Resources
> (INRs) using the "inherit" attribute, rather than an explicit
> description of a resource set (see [RFC3779]). (RPs are required
> to verify this.)
>
> which is the exact wording of RFC 6486 up to the last parenthesis. This
> does not explicitly say both resource extensions must be present. It
> could probably have been a bit more explicit that it does not do so and
> perhaps the following mistake would have been avoided.
>
> About 1/3 (~16k) of all manifest EE certs have both RFC 3779 extensions
> (with inherit element) despite the fact that their issuing certificate
> lacks one of the two. Blindly fixing this to be strictly RFC 3779
> compliant is therefore quite devastating for the RPKI: about 130,000
> validated ROA payloads (out of roughly one million) would disappear as
> well as 500 validated ASPA payloads (out of ~3,000).
>
> It turns out that rpki-client's valid_cert() has a similar bug as
> libcrypto. Given the above, we cannot be strictly RFC 3779 compliant,
> but we can get close: allow EE certs to inherit even if the parent does
> not have the required resource extension. There is no real downside to
> this. Subordinate objects (mostly ASPAs and ROAs will still need to
> have the subordinate resources covered with explicit extensions).
>
> valid_cert() is currently only called for CA and BGPsec certs, but I
> want to change this soon.
>
> Index: validate.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/validate.c,v
> diff -u -p -r1.84 validate.c
> --- validate.c 15 Jun 2026 14:30:53 -0000 1.84
> +++ validate.c 9 Sep 2026 21:58:57 -0000
> @@ -90,8 +90,22 @@ valid_cert(const char *fn, struct auth *
> uint32_t min, max;
>
> for (i = 0; i < cert->num_ases; i++) {
> - if (cert->ases[i].type == CERT_AS_INHERIT)
> - continue;
> + if (cert->ases[i].type == CERT_AS_INHERIT) {
> + /*
> + * Many MFTs are issued by a CA without AS resources.
> + * Accept this non-compliance with RFC 3779, 3.3.
> + * Apart from MFTs, this affects only TAKs and GBRs.
> + */
> + if (cert->purpose == CERT_PURPOSE_EE)
> + continue;
> +
> + if (a->cert->num_ases > 0)
> + continue;
> +
> + as_warn(fn, "parent without AS resources",
> + &cert->ases[i]);
> + return 0;
> + }
>
> if (cert->ases[i].type == CERT_AS_ID) {
> min = cert->ases[i].id;
> @@ -109,8 +123,22 @@ valid_cert(const char *fn, struct auth *
> }
>
> for (i = 0; i < cert->num_ips; i++) {
> - if (cert->ips[i].type == CERT_IP_INHERIT)
> - continue;
> + if (cert->ips[i].type == CERT_IP_INHERIT) {
> + /*
> + * Many MFTs are issued by a CA without IP resources.
> + * Accept this non-compliance with RFC 3779, 2.3.
> + * Apart from MFTs, this affects only TAKs and GBRs.
> + */
> + if (cert->purpose == CERT_PURPOSE_EE)
> + continue;
> +
> + if (a->cert->num_ips > 0)
> + continue;
> +
> + ip_warn(fn, "parent without IP resources",
> + &cert->ips[i]);
> + return 0;
> + }
>
> if (valid_ip(a, cert->ips[i].afi, cert->ips[i].min,
> cert->ips[i].max))
>
Yikes! We discussed a bit about the mini bikesheds around this but in
general this is OK claudio@
--
:wq Claudio
rpki-client: fix handling of inherited resources in leaves