Index | Thread | Search

From:
Theo Buehler <tb@theobuehler.org>
Subject:
rpki-client: some signed object boiler plate
To:
tech@openbsd.org
Date:
Mon, 22 Jun 2026 14:59:56 +0200

Download raw body.

Thread
This diff adds new/free/obj functions and introduces struct signed_obj
containing the handlers. For now I pass der_len and time_t into the
new function, this isn't particularly safe since the compiler won't
complain if we call sobj->new(signtime, der_len) in the future. We can
switch to a different approach in a later step.

For now only _new() is used in the _parse() functions. More wiring
up will happen in a later step.

Index: aspa.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/aspa.c,v
diff -u -p -r1.43 aspa.c
--- aspa.c	17 Jun 2026 08:22:21 -0000	1.43
+++ aspa.c	22 Jun 2026 12:47:49 -0000
@@ -179,6 +179,39 @@ aspa_validate(const char *fn, void *obj,
 	return 1; /* XXX */
 }
 
+static void *
+aspa_obj_new(size_t der_len, time_t signtime)
+{
+	struct aspa *aspa;
+
+	if ((aspa = calloc(1, sizeof(*aspa))) == NULL)
+		err(1, NULL);
+	aspa->signtime = signtime;
+
+	return aspa;
+}
+
+static void
+aspa_obj_free(void *obj)
+{
+	aspa_free(obj);
+}
+
+static const struct signed_obj aspa_signed_obj = {
+	.rtype = RTYPE_ASPA,
+	.new = aspa_obj_new,
+	.free = aspa_obj_free,
+	.cert_info = aspa_cert_info,
+	.parse_econtent = aspa_parse_econtent,
+	.validate = aspa_validate,
+};
+
+const struct signed_obj *
+aspa_obj(void)
+{
+	return &aspa_signed_obj;
+}
+
 /*
  * Parse a full ASPA file.
  * Returns the payload or NULL if the file was malformed.
@@ -201,10 +234,7 @@ aspa_parse(struct cert **out_cert, const
 	if (cms == NULL)
 		return NULL;
 
-	if ((aspa = calloc(1, sizeof(*aspa))) == NULL)
-		err(1, NULL);
-	aspa->signtime = signtime;
-
+	aspa = aspa_obj_new(len, signtime);
 	if (!aspa_cert_info(fn, aspa, cert))
 		goto out;
 	if (!aspa_parse_econtent(fn, aspa, cms, cmsz))
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
diff -u -p -r1.283 extern.h
--- extern.h	22 Jun 2026 08:08:03 -0000	1.283
+++ extern.h	22 Jun 2026 12:47:49 -0000
@@ -212,6 +212,17 @@ enum location {
 	DIR_VALID,
 };
 
+struct signed_obj {
+	enum rtype rtype;
+	void *(*new)(size_t, time_t);
+	void (*free)(void *);
+	int (*cert_info)(const char *, void *, const struct cert *);
+	int (*parse_econtent)(const char *, void *, const uint8_t *, size_t);
+	int (*parse_detached)(const char *, void *, BIO *, char *, size_t,
+	    uint8_t **, size_t *);
+	int (*validate)(const char *, void *, struct cert *);
+};
+
 /*
  * Files specified in an MFT have their bodies hashed with SHA256.
  */
@@ -732,6 +743,7 @@ void		 mft_buffer(struct ibuf *, const s
 void		 mft_free(struct mft *);
 struct mft	*mft_parse(struct cert **, const char *, int,
 		    const unsigned char *, size_t);
+const struct signed_obj *mft_obj(void);
 struct mft	*mft_read(struct ibuf *);
 int		 mft_compare_issued(const struct mft *, const struct mft *);
 int		 mft_compare_seqnum(const struct mft *, const struct mft *);
@@ -742,6 +754,7 @@ void		 roa_buffer(struct ibuf *, const s
 void		 roa_free(struct roa *);
 struct roa	*roa_parse(struct cert **, const char *, int,
 		    const unsigned char *, size_t);
+const struct signed_obj *roa_obj(void);
 struct roa	*roa_read(struct ibuf *);
 void		 roa_insert_vrps(struct vrp_tree *, struct roa *,
 		    struct repo *);
@@ -750,6 +763,7 @@ void		 spl_buffer(struct ibuf *, const s
 void		 spl_free(struct spl *);
 struct spl	*spl_parse(struct cert **, const char *, int,
 		    const unsigned char *, size_t);
+const struct signed_obj *spl_obj(void);
 struct spl	*spl_read(struct ibuf *);
 void		 spl_insert_vsps(struct vsp_tree *, struct spl *,
 		    struct repo *);
@@ -757,11 +771,13 @@ void		 spl_insert_vsps(struct vsp_tree *
 void		 rsc_free(struct rsc *);
 struct rsc	*rsc_parse(struct cert **, const char *, int,
 		    const unsigned char *, size_t);
+const struct signed_obj *rsc_obj(void);
 
 void		 takey_free(struct takey *);
 void		 tak_free(struct tak *);
 struct tak	*tak_parse(struct cert **, const char *, int,
 		    const unsigned char *, size_t);
+const struct signed_obj *tak_obj(void);
 
 void		 aspa_buffer(struct ibuf *, const struct aspa *);
 void		 aspa_free(struct aspa *);
@@ -769,6 +785,7 @@ void		 aspa_insert_vaps(char *, struct v
 		    struct repo *);
 struct aspa	*aspa_parse(struct cert **, const char *, int,
 		    const unsigned char *, size_t);
+const struct signed_obj *aspa_obj(void);
 struct aspa	*aspa_read(struct ibuf *);
 
 /* crl.c */
Index: mft.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
diff -u -p -r1.140 mft.c
--- mft.c	17 Jun 2026 08:47:28 -0000	1.140
+++ mft.c	22 Jun 2026 12:47:49 -0000
@@ -424,6 +424,40 @@ mft_validate(const char *fn, void *obj, 
 	return 1;
 }
 
+static void *
+mft_obj_new(size_t der_len, time_t signtime)
+{
+	struct mft *mft;
+
+	if ((mft = calloc(1, sizeof(*mft))) == NULL)
+		err(1, NULL);
+	mft->mftsize = der_len;
+	mft->signtime = signtime;
+
+	return mft;
+}
+
+static void
+mft_obj_free(void *obj)
+{
+	mft_free(obj);
+}
+
+static const struct signed_obj mft_signed_obj = {
+	.rtype = RTYPE_MFT,
+	.new = mft_obj_new,
+	.free = mft_obj_free,
+	.cert_info = mft_cert_info,
+	.parse_econtent = mft_parse_econtent,
+	.validate = mft_validate,
+};
+
+const struct signed_obj *
+mft_obj(void)
+{
+	return &mft_signed_obj;
+}
+
 /*
  * Parse the objects that have been published in the manifest.
  * Return mft if it conforms to RFC 9286, otherwise NULL.
@@ -446,11 +480,7 @@ mft_parse(struct cert **out_cert, const 
 	if (cms == NULL)
 		return NULL;
 
-	if ((mft = calloc(1, sizeof(*mft))) == NULL)
-		err(1, NULL);
-	mft->signtime = signtime;
-	mft->mftsize = len;
-
+	mft = mft_obj_new(len, signtime);
 	if (!mft_cert_info(fn, mft, cert))
 		goto out;
 	if (!mft_parse_econtent(fn, mft, cms, cmsz))
Index: roa.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
diff -u -p -r1.89 roa.c
--- roa.c	17 Jun 2026 08:47:28 -0000	1.89
+++ roa.c	22 Jun 2026 12:47:49 -0000
@@ -236,6 +236,39 @@ roa_validate(const char *fn, void *obj, 
 	return 1; /* XXX */
 }
 
+static void *
+roa_obj_new(size_t der_len, time_t signtime)
+{
+	struct roa *roa;
+
+	if ((roa = calloc(1, sizeof(*roa))) == NULL)
+		err(1, NULL);
+	roa->signtime = signtime;
+
+	return roa;
+}
+
+static void
+roa_obj_free(void *obj)
+{
+	roa_free(obj);
+}
+
+static const struct signed_obj roa_signed_obj = {
+	.rtype = RTYPE_ROA,
+	.new = roa_obj_new,
+	.free = roa_obj_free,
+	.cert_info = roa_cert_info,
+	.parse_econtent = roa_parse_econtent,
+	.validate = roa_validate,
+};
+
+const struct signed_obj *
+roa_obj(void)
+{
+	return &roa_signed_obj;
+}
+
 /*
  * Parse a full RFC 9582 file.
  * Returns the ROA or NULL if the document was malformed.
@@ -258,10 +291,7 @@ roa_parse(struct cert **out_cert, const 
 	if (cms == NULL)
 		return NULL;
 
-	if ((roa = calloc(1, sizeof(struct roa))) == NULL)
-		err(1, NULL);
-	roa->signtime = signtime;
-
+	roa = roa_obj_new(len, signtime);
 	if (!roa_cert_info(fn, roa, cert))
 		goto out;
 	if (!roa_parse_econtent(fn, roa, cms, cmsz))
Index: rsc.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/rsc.c,v
diff -u -p -r1.45 rsc.c
--- rsc.c	17 Jun 2026 08:22:21 -0000	1.45
+++ rsc.c	22 Jun 2026 12:47:49 -0000
@@ -361,6 +361,39 @@ rsc_validate(const char *fn, void *obj, 
 	return 1; /* XXX */
 }
 
+static void *
+rsc_obj_new(size_t der_len, time_t signtime)
+{
+	struct rsc *rsc;
+
+	if ((rsc = calloc(1, sizeof(*rsc))) == NULL)
+		err(1, NULL);
+	rsc->signtime = signtime;
+
+	return rsc;
+}
+
+static void
+rsc_obj_free(void *obj)
+{
+	rsc_free(obj);
+}
+
+static const struct signed_obj rsc_signed_obj = {
+	.rtype = RTYPE_RSC,
+	.new = rsc_obj_new,
+	.free = rsc_obj_free,
+	.cert_info = rsc_cert_info,
+	.parse_econtent = rsc_parse_econtent,
+	.validate = rsc_validate,
+};
+
+const struct signed_obj *
+rsc_obj(void)
+{
+	return &rsc_signed_obj;
+}
+
 /*
  * Parse a full RFC 9323 file.
  * Returns the RSC or NULL if the object was malformed.
@@ -383,10 +416,7 @@ rsc_parse(struct cert **out_cert, const 
 	if (cms == NULL)
 		return NULL;
 
-	if ((rsc = calloc(1, sizeof(struct rsc))) == NULL)
-		err(1, NULL);
-	rsc->signtime = signtime;
-
+	rsc = rsc_obj_new(len, signtime);
 	if (!rsc_cert_info(fn, rsc, cert))
 		goto out;
 	if (!rsc_parse_econtent(fn, rsc, cms, cmsz))
Index: spl.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/spl.c,v
diff -u -p -r1.17 spl.c
--- spl.c	17 Jun 2026 08:22:21 -0000	1.17
+++ spl.c	22 Jun 2026 12:47:49 -0000
@@ -241,6 +241,39 @@ spl_validate(const char *fn, void *obj, 
 	return 1; /* XXX */
 }
 
+static void *
+spl_obj_new(size_t der_len, time_t signtime)
+{
+	struct spl *spl;
+
+	if ((spl = calloc(1, sizeof(*spl))) == NULL)
+		err(1, NULL);
+	spl->signtime = signtime;
+
+	return spl;
+}
+
+static void
+spl_obj_free(void *obj)
+{
+	spl_free(obj);
+}
+
+static const struct signed_obj spl_signed_obj = {
+	.rtype = RTYPE_SPL,
+	.new = spl_obj_new,
+	.free = spl_obj_free,
+	.cert_info = spl_cert_info,
+	.parse_econtent = spl_parse_econtent,
+	.validate = spl_validate,
+};
+
+const struct signed_obj *
+spl_obj(void)
+{
+	return &spl_signed_obj;
+}
+
 /*
  * Parse a full Signed Prefix List file.
  * Returns the SPL, or NULL if the object was malformed.
@@ -263,10 +296,7 @@ spl_parse(struct cert **out_cert, const 
 	if (cms == NULL)
 		return NULL;
 
-	if ((spl = calloc(1, sizeof(*spl))) == NULL)
-		err(1, NULL);
-	spl->signtime = signtime;
-
+	spl = spl_obj_new(len, signtime);
 	if (!spl_cert_info(fn, spl, cert))
 		goto out;
 	if (!spl_parse_econtent(fn, spl, cms, cmsz))
Index: tak.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/tak.c,v
diff -u -p -r1.30 tak.c
--- tak.c	17 Jun 2026 08:22:21 -0000	1.30
+++ tak.c	22 Jun 2026 12:47:49 -0000
@@ -208,6 +208,39 @@ tak_validate(const char *fn, void *obj, 
 	return 1;
 }
 
+static void *
+tak_obj_new(size_t der_len, time_t signtime)
+{
+	struct tak *tak;
+
+	if ((tak = calloc(1, sizeof(*tak))) == NULL)
+		err(1, NULL);
+	tak->signtime = signtime;
+
+	return tak;
+}
+
+static void
+tak_obj_free(void *obj)
+{
+	tak_free(obj);
+}
+
+static const struct signed_obj tak_signed_obj = {
+	.rtype = RTYPE_SPL,
+	.new = tak_obj_new,
+	.free = tak_obj_free,
+	.cert_info = tak_cert_info,
+	.parse_econtent = tak_parse_econtent,
+	.validate = tak_validate,
+};
+
+const struct signed_obj *
+tak_obj(void)
+{
+	return &tak_signed_obj;
+}
+
 /*
  * Parse a full RFC 9691 Trust Anchor Key file.
  * Returns the TAK or NULL if the object was malformed.
@@ -230,10 +263,7 @@ tak_parse(struct cert **out_cert, const 
 	if (cms == NULL)
 		return NULL;
 
-	if ((tak = calloc(1, sizeof(struct tak))) == NULL)
-		err(1, NULL);
-	tak->signtime = signtime;
-
+	tak = tak_obj_new(len, signtime);
 	if (!tak_cert_info(fn, tak, cert))
 		goto out;
 	if (!tak_parse_econtent(fn, tak, cms, cmsz))