From: Claudio Jeker Subject: Re: rpki-client: fix handling of inherited resources in leaves To: Theo Buehler Cc: tech@openbsd.org Date: Thu, 10 Sep 2026 13:44:04 +0200 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