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