Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
Re: rpki-client: fix handling of inherited resources in leaves
To:
Theo Buehler <tb@theobuehler.org>
Cc:
tech@openbsd.org
Date:
Thu, 10 Sep 2026 13:44:04 +0200

Download raw body.

Thread
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