Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
Re: rpki-client: introduce and use signed_object_parse()
To:
Theo Buehler <tb@theobuehler.org>
Cc:
tech@openbsd.org
Date:
Thu, 3 Sep 2026 15:47:27 +0200

Download raw body.

Thread
On Thu, Sep 03, 2026 at 03:39:41PM +0200, Theo Buehler wrote:
> This refactoring diff does two simple things:
> 
> Hang an ->oid() getter off struct signed obj. Since foo_oid is populated
> at runtime it's not a compile time constant, so we can't add it directly
> to the static structs.
> 
> The six copies of foo_parse() get replaced by signed_object_parse() and
> for now we pass in the rtype and use that to resolve the signed object
> handler which is only used in there. cms_parse_validate() can be made
> static and regress get a similar adjustment as well.
> 
> There is one subtle difference between the foo_parse() copies that
> I should call out: mft and tak check the result of *_validate()
> while aspa, roa, rsp, and spl do not. The latter always succeed, so
> the switch from (void)foo_validate() to !sobj->validate() does not
> change anything.
> 
> The .rtype member is currently unused. I chose to leave it there for now.

I like it a lot. OK claudio@

> Index: usr.sbin/rpki-client/aspa.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/aspa.c,v
> diff -u -p -r1.44 aspa.c
> --- usr.sbin/rpki-client/aspa.c	25 Jun 2026 07:51:58 -0000	1.44
> +++ usr.sbin/rpki-client/aspa.c	3 Sep 2026 12:46:09 -0000
> @@ -179,6 +179,12 @@ aspa_validate(const char *fn, void *obj,
>  	return 1; /* XXX */
>  }
>  
> +static const ASN1_OBJECT *
> +aspa_obj_oid(void)
> +{
> +	return aspa_oid;
> +}
> +
>  static void *
>  aspa_obj_new(size_t der_len, time_t signtime)
>  {
> @@ -199,60 +205,20 @@ aspa_obj_free(void *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,
> +
> +	.oid = aspa_obj_oid,
>  };
>  
>  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.
> - */
> -struct aspa *
> -aspa_parse(struct cert **out_cert, const char *fn, int talid,
> -    const unsigned char *der, size_t len)
> -{
> -	struct aspa	*aspa;
> -	struct cert	*cert = NULL;
> -	size_t		 cmsz;
> -	unsigned char	*cms;
> -	time_t		 signtime = 0;
> -	int		 rc = 0;
> -
> -	assert(*out_cert == NULL);
> -
> -	cms = cms_parse_validate(&cert, fn, talid, der, len, aspa_oid, &cmsz,
> -	    &signtime);
> -	if (cms == NULL)
> -		return NULL;
> -
> -	aspa = aspa_obj_new(len, signtime);
> -	if (!aspa_cert_info(fn, aspa, cert))
> -		goto out;
> -	if (!aspa_parse_econtent(fn, aspa, cms, cmsz))
> -		goto out;
> -	(void)aspa_validate(fn, aspa, cert);
> -
> -	*out_cert = cert;
> -	cert = NULL;
> -
> -	rc = 1;
> - out:
> -	if (rc == 0) {
> -		aspa_free(aspa);
> -		aspa = NULL;
> -	}
> -	cert_free(cert);
> -	free(cms);
> -	return aspa;
>  }
>  
>  /*
> Index: usr.sbin/rpki-client/cms.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/cms.c,v
> diff -u -p -r1.61 cms.c
> --- usr.sbin/rpki-client/cms.c	26 Aug 2026 05:57:47 -0000	1.61
> +++ usr.sbin/rpki-client/cms.c	3 Sep 2026 13:30:54 -0000
> @@ -401,7 +401,7 @@ cms_parse_validate_internal(struct cert 
>   * The eContentType of the message must be an oid object.
>   * Return the eContent as a string and set "rsz" to be its length.
>   */
> -unsigned char *
> +static unsigned char *
>  cms_parse_validate(struct cert **out_cert, const char *fn, int talid,
>      const unsigned char *der, size_t derlen, const ASN1_OBJECT *oid,
>      size_t *rsz, time_t *st)
> @@ -413,4 +413,71 @@ cms_parse_validate(struct cert **out_cer
>  		return NULL;
>  
>  	return res;
> +}
> +
> +static const struct signed_obj *
> +cms_object_from_rtype(const char *fn, enum rtype rtype)
> +{
> +	switch (rtype) {
> +	case RTYPE_ASPA:
> +		return aspa_obj();
> +	case RTYPE_MFT:
> +		return mft_obj();
> +	case RTYPE_ROA:
> +		return roa_obj();
> +	case RTYPE_RSC:
> +		return rsc_obj();
> +	case RTYPE_SPL:
> +		return spl_obj();
> +	case RTYPE_TAK:
> +		return tak_obj();
> +	default:
> +		errx(1, "%s: unsupported signed object", fn);
> +	}
> +}
> +
> +void *
> +signed_object_parse(struct cert **out_cert, const char *fn, enum rtype rtype,
> +    int talid, const unsigned char *der, size_t len)
> +{
> +	const struct signed_obj *sobj;
> +	const ASN1_OBJECT *oid;
> +	void *obj = NULL;
> +	struct cert *cert = NULL;
> +	size_t cmsz;
> +	unsigned char *cms;
> +	time_t signtime = 0;
> +	int rc = 0;
> +
> +	assert(*out_cert == NULL);
> +
> +	sobj = cms_object_from_rtype(fn, rtype);
> +	oid = sobj->oid();
> +
> +	cms = cms_parse_validate(&cert, fn, talid, der, len, oid, &cmsz,
> +	    &signtime);
> +	if (cms == NULL)
> +		return NULL;
> +
> +	obj = sobj->new(len, signtime);
> +	if (!sobj->cert_info(fn, obj, cert))
> +		goto out;
> +	if (!sobj->parse_econtent(fn, obj, cms, cmsz))
> +		goto out;
> +	if (!sobj->validate(fn, obj, cert))
> +		goto out;
> +
> +	*out_cert = cert;
> +	cert = NULL;
> +
> +	rc = 1;
> +
> + out:
> +	if (rc == 0) {
> +		sobj->free(obj);
> +		obj = NULL;
> +	}
> +	cert_free(cert);
> +	free(cms);
> +	return obj;
>  }
> Index: usr.sbin/rpki-client/extern.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> diff -u -p -r1.291 extern.h
> --- usr.sbin/rpki-client/extern.h	25 Aug 2026 08:41:14 -0000	1.291
> +++ usr.sbin/rpki-client/extern.h	3 Sep 2026 13:04:51 -0000
> @@ -244,6 +244,7 @@ enum location {
>  
>  struct signed_obj {
>  	enum rtype rtype;
> +
>  	void *(*new)(size_t, time_t);
>  	void (*free)(void *);
>  	int (*cert_info)(const char *, void *, const struct cert *);
> @@ -251,6 +252,8 @@ struct signed_obj {
>  	int (*parse_detached)(const char *, void *, BIO *, char *, size_t,
>  	    uint8_t **, size_t *);
>  	int (*validate)(const char *, void *, struct cert *);
> +
> +	const ASN1_OBJECT *(*oid)(void);
>  };
>  
>  /*
> @@ -776,8 +779,6 @@ void		 nca_tree_remove_cert(struct nca_t
>  enum rtype	 rtype_from_file_extension(const char *);
>  void		 mft_buffer(struct ibuf *, const struct mft *);
>  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 *);
> @@ -787,8 +788,6 @@ int		 mft_seqnum_gap_present(const struc
>  
>  void		 roa_buffer(struct ibuf *, const struct roa *);
>  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 *,
> @@ -796,30 +795,22 @@ void		 roa_insert_vrps(struct vrp_tree *
>  
>  void		 spl_buffer(struct ibuf *, const struct spl *);
>  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 *);
>  
>  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 *);
>  void		 aspa_insert_vaps(char *, struct vap_tree *, struct aspa *,
>  		    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 *);
>  
> @@ -849,9 +840,8 @@ int		 valid_uuid(const char *);
>  int		 valid_spl(const char *, struct cert *, struct spl *);
>  
>  /* Working with CMS. */
> -unsigned char	*cms_parse_validate(struct cert **, const char *, int,
> -		    const unsigned char *, size_t, const ASN1_OBJECT *,
> -		    size_t *, time_t *);
> +void		*signed_object_parse(struct cert **, const char *, enum rtype,
> +		 int, const unsigned char *, size_t);
>  
>  /* Work with RFC 3779 IP addresses, prefixes, ranges. */
>  
> Index: usr.sbin/rpki-client/filemode.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/filemode.c,v
> diff -u -p -r1.86 filemode.c
> --- usr.sbin/rpki-client/filemode.c	9 Jul 2026 11:39:19 -0000	1.86
> +++ usr.sbin/rpki-client/filemode.c	3 Sep 2026 12:46:09 -0000
> @@ -500,7 +500,7 @@ proc_parser_file(char *file, unsigned ch
>  
>  	switch (type) {
>  	case RTYPE_ASPA:
> -		aspa = aspa_parse(&cert, file, -1, buf, len);
> +		aspa = signed_object_parse(&cert, file, type, -1, buf, len);
>  		if (aspa == NULL)
>  			break;
>  		aia = cert->aia;
> @@ -531,7 +531,7 @@ proc_parser_file(char *file, unsigned ch
>  		crl_print(crl);
>  		break;
>  	case RTYPE_MFT:
> -		mft = mft_parse(&cert, file, -1, buf, len);
> +		mft = signed_object_parse(&cert, file, type, -1, buf, len);
>  		if (mft == NULL)
>  			break;
>  		aia = cert->aia;
> @@ -540,7 +540,7 @@ proc_parser_file(char *file, unsigned ch
>  		notafter = &mft->nextupdate;
>  		break;
>  	case RTYPE_ROA:
> -		roa = roa_parse(&cert, file, -1, buf, len);
> +		roa = signed_object_parse(&cert, file, type, -1, buf, len);
>  		if (roa == NULL)
>  			break;
>  		aia = cert->aia;
> @@ -549,7 +549,7 @@ proc_parser_file(char *file, unsigned ch
>  		notafter = &cert->notafter;
>  		break;
>  	case RTYPE_RSC:
> -		rsc = rsc_parse(&cert, file, -1, buf, len);
> +		rsc = signed_object_parse(&cert, file, type, -1, buf, len);
>  		if (rsc == NULL)
>  			break;
>  		aia = cert->aia;
> @@ -558,7 +558,7 @@ proc_parser_file(char *file, unsigned ch
>  		notafter = &cert->notafter;
>  		break;
>  	case RTYPE_SPL:
> -		spl = spl_parse(&cert, file, -1, buf, len);
> +		spl = signed_object_parse(&cert, file, type, -1, buf, len);
>  		if (spl == NULL)
>  			break;
>  		aia = cert->aia;
> @@ -567,7 +567,7 @@ proc_parser_file(char *file, unsigned ch
>  		notafter = &cert->notafter;
>  		break;
>  	case RTYPE_TAK:
> -		tak = tak_parse(&cert, file, -1, buf, len);
> +		tak = signed_object_parse(&cert, file, type, -1, buf, len);
>  		if (tak == NULL)
>  			break;
>  		aia = cert->aia;
> Index: usr.sbin/rpki-client/mft.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
> diff -u -p -r1.141 mft.c
> --- usr.sbin/rpki-client/mft.c	25 Jun 2026 07:51:58 -0000	1.141
> +++ usr.sbin/rpki-client/mft.c	3 Sep 2026 12:46:09 -0000
> @@ -424,6 +424,12 @@ mft_validate(const char *fn, void *obj, 
>  	return 1;
>  }
>  
> +static const ASN1_OBJECT *
> +mft_obj_oid(void)
> +{
> +	return mft_oid;
> +}
> +
>  static void *
>  mft_obj_new(size_t der_len, time_t signtime)
>  {
> @@ -445,61 +451,20 @@ mft_obj_free(void *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,
> +
> +	.oid = mft_obj_oid,
>  };
>  
>  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.
> - */
> -struct mft *
> -mft_parse(struct cert **out_cert, const char *fn, int talid,
> -    const unsigned char *der, size_t len)
> -{
> -	struct mft	*mft;
> -	struct cert	*cert = NULL;
> -	int		 rc = 0;
> -	size_t		 cmsz;
> -	unsigned char	*cms;
> -	time_t		 signtime = 0;
> -
> -	assert(*out_cert == NULL);
> -
> -	cms = cms_parse_validate(&cert, fn, talid, der, len, mft_oid, &cmsz,
> -	    &signtime);
> -	if (cms == NULL)
> -		return NULL;
> -
> -	mft = mft_obj_new(len, signtime);
> -	if (!mft_cert_info(fn, mft, cert))
> -		goto out;
> -	if (!mft_parse_econtent(fn, mft, cms, cmsz))
> -		goto out;
> -	if (!mft_validate(fn, mft, cert))
> -		goto out;
> -
> -	*out_cert = cert;
> -	cert = NULL;
> -
> -	rc = 1;
> - out:
> -	if (rc == 0) {
> -		mft_free(mft);
> -		mft = NULL;
> -	}
> -	cert_free(cert);
> -	free(cms);
> -	return mft;
>  }
>  
>  /*
> Index: usr.sbin/rpki-client/parser.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
> diff -u -p -r1.183 parser.c
> --- usr.sbin/rpki-client/parser.c	21 Jul 2026 12:21:42 -0000	1.183
> +++ usr.sbin/rpki-client/parser.c	3 Sep 2026 12:56:08 -0000
> @@ -211,7 +211,8 @@ proc_parser_roa(char *file, const unsign
>  	struct crl		*crl;
>  	const char		*errstr;
>  
> -	if ((roa = roa_parse(&cert, file, entp->talid, der, len)) == NULL)
> +	if ((roa = signed_object_parse(&cert, file, RTYPE_ROA, entp->talid,
> +	    der, len)) == NULL)
>  		goto out;
>  
>  	a = find_issuer(file, entp->certid, cert->aki, entp->mftaki);
> @@ -252,7 +253,8 @@ proc_parser_spl(char *file, const unsign
>  	struct crl		*crl;
>  	const char		*errstr;
>  
> -	if ((spl = spl_parse(&cert, file, entp->talid, der, len)) == NULL)
> +	if ((spl = signed_object_parse(&cert, file, RTYPE_SPL, entp->talid,
> +	    der, len)) == NULL)
>  		goto out;
>  
>  	a = find_issuer(file, entp->certid, cert->aki, entp->mftaki);
> @@ -412,7 +414,8 @@ proc_parser_mft_pre(struct entity *entp,
>  	if (der == NULL && errno != ENOENT)
>  		warn("parse file %s", file);
>  
> -	if ((mft = mft_parse(&cert, file, entp->talid, der, len)) == NULL) {
> +	if ((mft = signed_object_parse(&cert, file, RTYPE_MFT, entp->talid,
> +	    der, len)) == NULL) {
>  		free(der);
>  		return NULL;
>  	}
> @@ -772,7 +775,8 @@ proc_parser_aspa(char *file, const unsig
>  	struct crl	*crl;
>  	const char	*errstr;
>  
> -	if ((aspa = aspa_parse(&cert, file, entp->talid, der, len)) == NULL)
> +	if ((aspa = signed_object_parse(&cert, file, RTYPE_ASPA, entp->talid,
> +	    der, len)) == NULL)
>  		goto out;
>  
>  	a = find_issuer(file, entp->certid, cert->aki, entp->mftaki);
> @@ -812,7 +816,8 @@ proc_parser_tak(char *file, const unsign
>  	struct auth	*a;
>  	const char	*errstr;
>  
> -	if ((tak = tak_parse(&cert, file, entp->talid, der, len)) == NULL)
> +	if ((tak = signed_object_parse(&cert, file, RTYPE_TAK, entp->talid,
> +	    der, len)) == NULL)
>  		goto out;
>  
>  	a = find_issuer(file, entp->certid, cert->aki, entp->mftaki);
> Index: usr.sbin/rpki-client/roa.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
> diff -u -p -r1.90 roa.c
> --- usr.sbin/rpki-client/roa.c	25 Jun 2026 07:51:58 -0000	1.90
> +++ usr.sbin/rpki-client/roa.c	3 Sep 2026 12:46:09 -0000
> @@ -236,6 +236,12 @@ roa_validate(const char *fn, void *obj, 
>  	return 1; /* XXX */
>  }
>  
> +static const ASN1_OBJECT *
> +roa_obj_oid(void)
> +{
> +	return roa_oid;
> +}
> +
>  static void *
>  roa_obj_new(size_t der_len, time_t signtime)
>  {
> @@ -256,60 +262,20 @@ roa_obj_free(void *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,
> +
> +	.oid = roa_obj_oid,
>  };
>  
>  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.
> - */
> -struct roa *
> -roa_parse(struct cert **out_cert, const char *fn, int talid,
> -    const unsigned char *der, size_t len)
> -{
> -	struct roa	*roa;
> -	struct cert	*cert = NULL;
> -	size_t		 cmsz;
> -	unsigned char	*cms;
> -	time_t		 signtime = 0;
> -	int		 rc = 0;
> -
> -	assert(*out_cert == NULL);
> -
> -	cms = cms_parse_validate(&cert, fn, talid, der, len, roa_oid, &cmsz,
> -	    &signtime);
> -	if (cms == NULL)
> -		return NULL;
> -
> -	roa = roa_obj_new(len, signtime);
> -	if (!roa_cert_info(fn, roa, cert))
> -		goto out;
> -	if (!roa_parse_econtent(fn, roa, cms, cmsz))
> -		goto out;
> -	(void)roa_validate(fn, roa, cert);
> -
> -	*out_cert = cert;
> -	cert = NULL;
> -
> -	rc = 1;
> - out:
> -	if (rc == 0) {
> -		roa_free(roa);
> -		roa = NULL;
> -	}
> -	cert_free(cert);
> -	free(cms);
> -	return roa;
>  }
>  
>  /*
> Index: usr.sbin/rpki-client/rsc.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/rsc.c,v
> diff -u -p -r1.47 rsc.c
> --- usr.sbin/rpki-client/rsc.c	9 Jul 2026 12:13:56 -0000	1.47
> +++ usr.sbin/rpki-client/rsc.c	3 Sep 2026 12:46:09 -0000
> @@ -366,6 +366,12 @@ rsc_validate(const char *fn, void *obj, 
>  	return 1; /* XXX */
>  }
>  
> +static const ASN1_OBJECT *
> +rsc_obj_oid(void)
> +{
> +	return rsc_oid;
> +}
> +
>  static void *
>  rsc_obj_new(size_t der_len, time_t signtime)
>  {
> @@ -386,60 +392,20 @@ rsc_obj_free(void *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,
> +
> +	.oid = rsc_obj_oid,
>  };
>  
>  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.
> - */
> -struct rsc *
> -rsc_parse(struct cert **out_cert, const char *fn, int talid,
> -    const unsigned char *der, size_t len)
> -{
> -	struct rsc		*rsc;
> -	struct cert		*cert = NULL;
> -	unsigned char		*cms;
> -	size_t			 cmsz;
> -	time_t			 signtime = 0;
> -	int			 rc = 0;
> -
> -	assert(*out_cert == NULL);
> -
> -	cms = cms_parse_validate(&cert, fn, talid, der, len, rsc_oid, &cmsz,
> -	    &signtime);
> -	if (cms == NULL)
> -		return NULL;
> -
> -	rsc = rsc_obj_new(len, signtime);
> -	if (!rsc_cert_info(fn, rsc, cert))
> -		goto out;
> -	if (!rsc_parse_econtent(fn, rsc, cms, cmsz))
> -		goto out;
> -	(void)rsc_validate(fn, rsc, cert);
> -
> -	*out_cert = cert;
> -	cert = NULL;
> -
> -	rc = 1;
> - out:
> -	if (rc == 0) {
> -		rsc_free(rsc);
> -		rsc = NULL;
> -	}
> -	cert_free(cert);
> -	free(cms);
> -	return rsc;
>  }
>  
>  /*
> Index: usr.sbin/rpki-client/spl.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/spl.c,v
> diff -u -p -r1.18 spl.c
> --- usr.sbin/rpki-client/spl.c	25 Jun 2026 07:51:58 -0000	1.18
> +++ usr.sbin/rpki-client/spl.c	3 Sep 2026 12:46:09 -0000
> @@ -241,6 +241,12 @@ spl_validate(const char *fn, void *obj, 
>  	return 1; /* XXX */
>  }
>  
> +static const ASN1_OBJECT *
> +spl_obj_oid(void)
> +{
> +	return spl_oid;
> +}
> +
>  static void *
>  spl_obj_new(size_t der_len, time_t signtime)
>  {
> @@ -261,60 +267,20 @@ spl_obj_free(void *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,
> +
> +	.oid = spl_obj_oid,
>  };
>  
>  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.
> - */
> -struct spl *
> -spl_parse(struct cert **out_cert, const char *fn, int talid,
> -    const unsigned char *der, size_t len)
> -{
> -	struct spl	*spl;
> -	struct cert	*cert = NULL;
> -	size_t		 cmsz;
> -	unsigned char	*cms;
> -	time_t		 signtime = 0;
> -	int		 rc = 0;
> -
> -	assert(*out_cert == NULL);
> -
> -	cms = cms_parse_validate(&cert, fn, talid, der, len, spl_oid, &cmsz,
> -	    &signtime);
> -	if (cms == NULL)
> -		return NULL;
> -
> -	spl = spl_obj_new(len, signtime);
> -	if (!spl_cert_info(fn, spl, cert))
> -		goto out;
> -	if (!spl_parse_econtent(fn, spl, cms, cmsz))
> -		goto out;
> -	(void)spl_validate(fn, spl, cert);
> -
> -	*out_cert = cert;
> -	cert = NULL;
> -
> -	rc = 1;
> - out:
> -	if (rc == 0) {
> -		spl_free(spl);
> -		spl = NULL;
> -	}
> -	cert_free(cert);
> -	free(cms);
> -	return spl;
>  }
>  
>  void
> Index: usr.sbin/rpki-client/tak.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/tak.c,v
> diff -u -p -r1.32 tak.c
> --- usr.sbin/rpki-client/tak.c	7 Jul 2026 13:45:59 -0000	1.32
> +++ usr.sbin/rpki-client/tak.c	3 Sep 2026 12:46:09 -0000
> @@ -208,6 +208,12 @@ tak_validate(const char *fn, void *obj, 
>  	return 1;
>  }
>  
> +static const ASN1_OBJECT *
> +tak_obj_oid(void)
> +{
> +	return tak_oid;
> +}
> +
>  static void *
>  tak_obj_new(size_t der_len, time_t signtime)
>  {
> @@ -228,61 +234,20 @@ tak_obj_free(void *obj)
>  
>  static const struct signed_obj tak_signed_obj = {
>  	.rtype = RTYPE_TAK,
> +
>  	.new = tak_obj_new,
>  	.free = tak_obj_free,
>  	.cert_info = tak_cert_info,
>  	.parse_econtent = tak_parse_econtent,
>  	.validate = tak_validate,
> +
> +	.oid = tak_obj_oid,
>  };
>  
>  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.
> - */
> -struct tak *
> -tak_parse(struct cert **out_cert, const char *fn, int talid,
> -    const unsigned char *der, size_t len)
> -{
> -	struct tak		*tak;
> -	struct cert		*cert = NULL;
> -	unsigned char		*cms;
> -	size_t			 cmsz;
> -	time_t			 signtime = 0;
> -	int			 rc = 0;
> -
> -	assert(*out_cert == NULL);
> -
> -	cms = cms_parse_validate(&cert, fn, talid, der, len, tak_oid, &cmsz,
> -	    &signtime);
> -	if (cms == NULL)
> -		return NULL;
> -
> -	tak = tak_obj_new(len, signtime);
> -	if (!tak_cert_info(fn, tak, cert))
> -		goto out;
> -	if (!tak_parse_econtent(fn, tak, cms, cmsz))
> -		goto out;
> -	if (!tak_validate(fn, tak, cert))
> -		goto out;
> -
> -	*out_cert = cert;
> -	cert = NULL;
> -
> -	rc = 1;
> - out:
> -	if (rc == 0) {
> -		tak_free(tak);
> -		tak = NULL;
> -	}
> -	cert_free(cert);
> -	free(cms);
> -	return tak;
>  }
>  
>  /*
> Index: regress/usr.sbin/rpki-client/test-aspa.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-aspa.c,v
> diff -u -p -r1.12 test-aspa.c
> --- regress/usr.sbin/rpki-client/test-aspa.c	23 Oct 2025 05:35:46 -0000	1.12
> +++ regress/usr.sbin/rpki-client/test-aspa.c	3 Sep 2026 12:46:09 -0000
> @@ -63,7 +63,8 @@ main(int argc, char *argv[])
>  
>  	for (i = 0; i < argc; i++) {
>  		buf = load_file(argv[i], &len);
> -		if ((p = aspa_parse(&cert, argv[i], -1, buf, len)) == NULL) {
> +		if ((p = signed_object_parse(&cert, argv[i], RTYPE_ASPA, -1,
> +		    buf, len)) == NULL) {
>  			free(buf);
>  			break;
>  		}
> Index: regress/usr.sbin/rpki-client/test-mft.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-mft.c,v
> diff -u -p -r1.33 test-mft.c
> --- regress/usr.sbin/rpki-client/test-mft.c	23 Oct 2025 05:35:46 -0000	1.33
> +++ regress/usr.sbin/rpki-client/test-mft.c	3 Sep 2026 12:46:09 -0000
> @@ -65,7 +65,8 @@ main(int argc, char *argv[])
>  
>  	for (i = 0; i < argc; i++) {
>  		buf = load_file(argv[i], &len);
> -		if ((p = mft_parse(&cert, argv[i], -1, buf, len)) == NULL) {
> +		if ((p = signed_object_parse(&cert, argv[i], RTYPE_MFT, -1,
> +		    buf, len)) == NULL) {
>  			free(buf);
>  			break;
>  		}
> Index: regress/usr.sbin/rpki-client/test-roa.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-roa.c,v
> diff -u -p -r1.30 test-roa.c
> --- regress/usr.sbin/rpki-client/test-roa.c	23 Oct 2025 05:35:46 -0000	1.30
> +++ regress/usr.sbin/rpki-client/test-roa.c	3 Sep 2026 12:46:09 -0000
> @@ -62,7 +62,8 @@ main(int argc, char *argv[])
>  
>  	for (i = 0; i < argc; i++) {
>  		buf = load_file(argv[i], &len);
> -		if ((p = roa_parse(&cert, argv[i], -1, buf, len)) == NULL) {
> +		if ((p = signed_object_parse(&cert, argv[i], RTYPE_ROA, -1,
> +		    buf, len)) == NULL) {
>  			free(buf);
>  			break;
>  		}
> Index: regress/usr.sbin/rpki-client/test-rsc.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-rsc.c,v
> diff -u -p -r1.15 test-rsc.c
> --- regress/usr.sbin/rpki-client/test-rsc.c	23 Oct 2025 05:35:46 -0000	1.15
> +++ regress/usr.sbin/rpki-client/test-rsc.c	3 Sep 2026 12:46:09 -0000
> @@ -65,7 +65,8 @@ main(int argc, char *argv[])
>  
>  	for (i = 0; i < argc; i++) {
>  		buf = load_file(argv[i], &len);
> -		if ((p = rsc_parse(&cert, argv[i], -1, buf, len)) == NULL) {
> +		if ((p = signed_object_parse(&cert, argv[i], RTYPE_RSC, -1,
> +		    buf, len)) == NULL) {
>  			free(buf);
>  			break;
>  		}
> Index: regress/usr.sbin/rpki-client/test-spl.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-spl.c,v
> diff -u -p -r1.7 test-spl.c
> --- regress/usr.sbin/rpki-client/test-spl.c	23 Oct 2025 05:35:46 -0000	1.7
> +++ regress/usr.sbin/rpki-client/test-spl.c	3 Sep 2026 12:46:09 -0000
> @@ -63,7 +63,8 @@ main(int argc, char *argv[])
>  
>  	for (i = 0; i < argc; i++) {
>  		buf = load_file(argv[i], &len);
> -		if ((p = spl_parse(&cert, argv[i], -1, buf, len)) == NULL) {
> +		if ((p = signed_object_parse(&cert, argv[i], RTYPE_SPL,
> +		    -1, buf, len)) == NULL) {
>  			free(buf);
>  			break;
>  		}
> Index: regress/usr.sbin/rpki-client/test-tak.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-tak.c,v
> diff -u -p -r1.12 test-tak.c
> --- regress/usr.sbin/rpki-client/test-tak.c	23 Oct 2025 05:35:46 -0000	1.12
> +++ regress/usr.sbin/rpki-client/test-tak.c	3 Sep 2026 12:46:09 -0000
> @@ -63,7 +63,8 @@ main(int argc, char *argv[])
>  
>  	for (i = 0; i < argc; i++) {
>  		buf = load_file(argv[i], &len);
> -		if ((p = tak_parse(&cert, argv[i], -1, buf, len)) == NULL) {
> +		if ((p = signed_object_parse(&cert, argv[i], RTYPE_TAK, -1,
> +		    buf, len)) == NULL) {
>  			free(buf);
>  			break;
>  		}
> 

-- 
:wq Claudio