Index | Thread | Search

From:
Theo Buehler <tb@theobuehler.org>
Subject:
rpki-client: merge cert_parse() and cert_parse_pre()
To:
tech@openbsd.org
Date:
Mon, 14 Jul 2025 09:46:30 +0200

Download raw body.

Thread
  • Theo Buehler:

    rpki-client: merge cert_parse() and cert_parse_pre()

The split between cert_parse_pre() and cert_parse() is no longer
meaningful, really.

cert_parse_pre() has checks depending on the purpose which are now
all part of cert_parse_extensions() except for the check that a cert
coming through here is not supposed to be an EE cert, which I kept.

cert_parse() itself only has some checks on extensions which are done
as part of cert_parse_extensions() already.

For TA certs we could not call cert_parse() previously because of
AIA, CRLDP and SKI vs AKI, which we now handle depending on purpose
in cert_parse_extensions().

We could consider making ta_parse() call cert_parse() directly, but
it would add some complications to this diff and especially filemode
is a bit messy (we don't know if a .cer is a TA, CA or BGPsec cert)
and it doesn't really seem to help a lot.

Index: regress/usr.sbin/rpki-client/test-cert.c
===================================================================
RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-cert.c,v
diff -u -p -r1.25 test-cert.c
--- regress/usr.sbin/rpki-client/test-cert.c	7 Jul 2025 17:57:16 -0000	1.25
+++ regress/usr.sbin/rpki-client/test-cert.c	14 Jul 2025 07:17:19 -0000
@@ -84,7 +84,7 @@ main(int argc, char *argv[])
 				break;
 
 			buf = load_file(cert_path, &len);
-			p = cert_parse_pre(cert_path, buf, len);
+			p = cert_parse(cert_path, buf, len);
 			free(buf);
 			if (p == NULL)
 				break;
@@ -103,11 +103,8 @@ main(int argc, char *argv[])
 			size_t		 len;
 
 			buf = load_file(argv[i], &len);
-			p = cert_parse_pre(argv[i], buf, len);
+			p = cert_parse(argv[i], buf, len);
 			free(buf);
-			if (p == NULL)
-				break;
-			p = cert_parse(argv[i], p);
 			if (p == NULL)
 				break;
 			if (verb)
Index: usr.sbin/rpki-client/cert.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
diff -u -p -r1.193 cert.c
--- usr.sbin/rpki-client/cert.c	14 Jul 2025 06:03:17 -0000	1.193
+++ usr.sbin/rpki-client/cert.c	14 Jul 2025 07:17:19 -0000
@@ -1875,7 +1875,7 @@ cert_parse_ee_cert(const char *fn, int t
  * Returns the parse results or NULL on failure.
  */
 struct cert *
-cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
+cert_parse(const char *fn, const unsigned char *der, size_t len)
 {
 	struct cert		*cert = NULL;
 	const unsigned char	*oder;
@@ -1902,37 +1902,9 @@ cert_parse_pre(const char *fn, const uns
 	if ((cert = cert_parse_internal(fn, x)) == NULL)
 		goto out;
 
-	/* Validation on required fields. */
-	switch (cert->purpose) {
-	case CERT_PURPOSE_TA:
-		/* XXX - caller should indicate if it expects TA or CA cert */
-	case CERT_PURPOSE_CA:
-		if (cert->mft == NULL) {
-			warnx("%s: RFC 6487 section 4.8.8: missing SIA", fn);
-			goto out;
-		}
-		if (cert->num_ases == 0 && cert->num_ips == 0) {
-			warnx("%s: missing IP or AS resources", fn);
-			goto out;
-		}
-		break;
-	case CERT_PURPOSE_BGPSEC_ROUTER:
-		if (cert->num_ips > 0) {
-			warnx("%s: unexpected IP resources in BGPsec cert", fn);
-			goto out;
-		}
-		break;
-	case CERT_PURPOSE_EE:
+	if (cert->purpose == CERT_PURPOSE_EE) {
 		warnx("%s: unexpected EE cert", fn);
 		goto out;
-	default:
-		warnx("%s: x509_get_purpose failed in %s", fn, __func__);
-		goto out;
-	}
-
-	if (cert->ski == NULL) {
-		warnx("%s: RFC 6487 section 8.4.2: missing SKI", fn);
-		goto out;
 	}
 
 	X509_free(x);
@@ -1945,38 +1917,6 @@ cert_parse_pre(const char *fn, const uns
 }
 
 struct cert *
-cert_parse(const char *fn, struct cert *p)
-{
-	if (p == NULL)
-		return NULL;
-
-	if (p->aki == NULL) {
-		warnx("%s: RFC 6487 section 8.4.2: "
-		    "non-trust anchor missing AKI", fn);
-		goto badcert;
-	}
-	if (strcmp(p->aki, p->ski) == 0) {
-		warnx("%s: RFC 6487 section 8.4.2: "
-		    "non-trust anchor AKI may not match SKI", fn);
-		goto badcert;
-	}
-	if (p->aia == NULL) {
-		warnx("%s: RFC 6487 section 8.4.7: AIA: extension missing", fn);
-		goto badcert;
-	}
-	if (p->crl == NULL) {
-		warnx("%s: RFC 6487 section 4.8.6: CRL: "
-		    "no CRL distribution point extension", fn);
-		goto badcert;
-	}
-	return p;
-
- badcert:
-	cert_free(p);
-	return NULL;
-}
-
-struct cert *
 ta_parse(const char *fn, struct cert *p, const unsigned char *pkey,
     size_t pkeysz)
 {
@@ -2008,21 +1948,6 @@ ta_parse(const char *fn, struct cert *p,
 	}
 	if (p->notafter < now) {
 		warnx("%s: certificate has expired", fn);
-		goto badcert;
-	}
-	if (p->aki != NULL && strcmp(p->aki, p->ski)) {
-		warnx("%s: RFC 6487 section 4.8.3: "
-		    "trust anchor AKI, if specified, must match SKI", fn);
-		goto badcert;
-	}
-	if (p->aia != NULL) {
-		warnx("%s: RFC 6487 section 4.8.7: "
-		    "trust anchor must not have AIA", fn);
-		goto badcert;
-	}
-	if (p->crl != NULL) {
-		warnx("%s: RFC 6487 section 4.8.6: "
-		    "trust anchor may not specify CRL resource", fn);
 		goto badcert;
 	}
 	if (p->purpose != CERT_PURPOSE_TA) {
Index: usr.sbin/rpki-client/extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
diff -u -p -r1.247 extern.h
--- usr.sbin/rpki-client/extern.h	11 Jul 2025 09:20:23 -0000	1.247
+++ usr.sbin/rpki-client/extern.h	14 Jul 2025 07:17:19 -0000
@@ -716,8 +716,7 @@ void		 cert_buffer(struct ibuf *, const 
 void		 cert_free(struct cert *);
 void		 auth_tree_free(struct auth_tree *);
 struct cert	*cert_parse_ee_cert(const char *, int, X509 *);
-struct cert	*cert_parse_pre(const char *, const unsigned char *, size_t);
-struct cert	*cert_parse(const char *, struct cert *);
+struct cert	*cert_parse(const char *, const unsigned char *, size_t);
 struct cert	*ta_parse(const char *, struct cert *, const unsigned char *,
 		    size_t);
 struct cert	*cert_read(struct ibuf *);
Index: usr.sbin/rpki-client/filemode.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/filemode.c,v
diff -u -p -r1.62 filemode.c
--- usr.sbin/rpki-client/filemode.c	25 Jun 2025 16:24:44 -0000	1.62
+++ usr.sbin/rpki-client/filemode.c	14 Jul 2025 07:17:19 -0000
@@ -151,7 +151,7 @@ parse_load_cert(char *uri)
 		goto done;
 	}
 
-	cert = cert_parse_pre(uri, f, flen);
+	cert = cert_parse(uri, f, flen);
 	free(f);
 
 	if (cert == NULL)
@@ -260,7 +260,7 @@ parse_load_ta(struct tal *tal)
 	}
 
 	/* Extract certificate data. */
-	cert = cert_parse_pre(file, f, flen);
+	cert = cert_parse(file, f, flen);
 	cert = ta_parse(file, cert, tal->pkey, tal->pkeysz);
 	if (cert == NULL)
 		goto out;
@@ -408,14 +408,10 @@ proc_parser_file(char *file, unsigned ch
 		notafter = &aspa->notafter;
 		break;
 	case RTYPE_CER:
-		cert = cert_parse_pre(file, buf, len);
+		cert = cert_parse(file, buf, len);
 		if (cert == NULL)
 			break;
 		is_ta = (cert->purpose == CERT_PURPOSE_TA);
-		if (!is_ta)
-			cert = cert_parse(file, cert);
-		if (cert == NULL)
-			break;
 		aia = cert->aia;
 		x509 = cert->x509;
 		if (X509_up_ref(x509) == 0)
Index: usr.sbin/rpki-client/parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
diff -u -p -r1.162 parser.c
--- usr.sbin/rpki-client/parser.c	25 Jun 2025 16:24:44 -0000	1.162
+++ usr.sbin/rpki-client/parser.c	14 Jul 2025 07:17:19 -0000
@@ -588,8 +588,7 @@ proc_parser_cert(char *file, const unsig
 
 	/* Extract certificate data. */
 
-	cert = cert_parse_pre(file, der, len);
-	cert = cert_parse(file, cert);
+	cert = cert_parse(file, der, len);
 	if (cert == NULL)
 		goto out;
 
@@ -693,7 +692,7 @@ proc_parser_root_cert(struct entity *ent
 
 	file2 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_VALID);
 	der = load_file(file2, &der_len);
-	cert2 = cert_parse_pre(file2, der, der_len);
+	cert2 = cert_parse(file2, der, der_len);
 	free(der);
 	cert2 = ta_parse(file2, cert2, pkey, pkeysz);
 
@@ -701,7 +700,7 @@ proc_parser_root_cert(struct entity *ent
 		file1 = parse_filepath(entp->repoid, entp->path, entp->file,
 		    DIR_TEMP);
 		der = load_file(file1, &der_len);
-		cert1 = cert_parse_pre(file1, der, der_len);
+		cert1 = cert_parse(file1, der, der_len);
 		free(der);
 		cert1 = ta_parse(file1, cert1, pkey, pkeysz);
 	}