From: Theo Buehler Subject: Re: rpki-client: cert_check_purpose tweaks To: tech@openbsd.org Date: Fri, 27 Jun 2025 06:30:44 +0200 On Thu, Jun 19, 2025 at 01:50:24PM +0200, Theo Buehler wrote: > I want the cert->purpose to be already available and valid when parsing > the extensions, so I can branch on that if needed. So hoist the call in > cert_parse_pre() above the extension checking proper and make sure > that cert_check_purpose() prints an error if we don't know what kind > of cert we have. The double warning in cert_parse_ee_cert() isn't new > except for the one warnx() that I added in the cert_check_purpose() > exit path. The meatier diffs will come soon and it will help not to have such relatively simple things mixed in. (also the double warning will disappear soon enough) Index: cert.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v diff -u -p -r1.171 cert.c --- cert.c 27 Jun 2025 04:01:04 -0000 1.171 +++ cert.c 27 Jun 2025 04:23:35 -0000 @@ -872,10 +872,13 @@ cert_check_purpose(const char *fn, X509 for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { if (OBJ_cmp(bgpsec_oid, sk_ASN1_OBJECT_value(eku, i)) == 0) { purpose = CERT_PURPOSE_BGPSEC_ROUTER; - break; + goto out; } } + warnx("%s: unknown certificate purpose", fn); + assert(purpose == CERT_PURPOSE_INVALID); + out: BASIC_CONSTRAINTS_free(bc); EXTENDED_KEY_USAGE_free(eku); @@ -913,6 +916,7 @@ cert_parse_ee_cert(const char *fn, int t * appropriate for an EE cert. Covers RFC 6487, 4.8.1, 4.8.4, 4.8.5. */ if ((cert->purpose = cert_check_purpose(fn, x)) != CERT_PURPOSE_EE) { + /* XXX - double warning */ warnx("%s: expected EE cert, got %s", fn, purpose2str(cert->purpose)); goto out; @@ -1022,6 +1026,13 @@ cert_parse_pre(const char *fn, const uns if (!cert_check_subject_and_issuer(fn, x)) goto out; + /* + * Check issuance, basic constraints and (extended) key usage bits are + * appropriate for a resource cert. Covers RFC 6487 4.8.1, 4.8.4, 4.8.5. + */ + if ((cert->purpose = cert_check_purpose(fn, x)) == CERT_PURPOSE_INVALID) + goto out; + /* Look for X509v3 extensions. */ if ((extsz = X509_get_ext_count(x)) <= 0) { warnx("%s: certificate without X.509v3 extensions", fn); @@ -1124,7 +1135,6 @@ cert_parse_pre(const char *fn, const uns goto out; /* Validation on required fields. */ - cert->purpose = cert_check_purpose(fn, x); switch (cert->purpose) { case CERT_PURPOSE_TA: /* XXX - caller should indicate if it expects TA or CA cert */