On Tue, Apr 05, 2022 at 06:33:35PM +0200, Theo Buehler wrote: > Instead of manually unpacking the SIA extension with super low-level > ASN.1 fiddling, we can let the templated ASN.1 in libcrypto do this work > for us, which makes the code quite a bit simpler. This resolves one > FIXME and removes one use of the magic ASN1_frame(). > > I kept the current split of the functions to avoid noise and make the > diff easier to review. I'm going to undo this split in a follow-up. > > The relevant structs and typedefs are in x509/x509v3.h and the ASN.1 > templates are in x509/x509_info.c if you want to take a look at that. > > The main point is the X509V3_EXT_d2i() in sbgp_sia(), which deserializes > the extension based on its OID, which was checked in cert_parse_pre(). > We (ab)use the AUTHORITY_INFO_ACCESS type since there is unfortunately > no SUBJECT_INFO_ACCESS type (the extensions have the same syntax, see > RFC 5280, 4.2.2). This is documented in AUTHORITY_INFO_ACCESS_new(3). > A typedef might be appropriate here. > > AUTHORITY_INFO_ACCESS is a STACK_OF(ACCESS_DESCRIPTION), the unpacking > of which is done in sbgp_sia_resource().
I'm not too woried about this, an option could be to use STACK_OF(ACCESS_DESCRIPTION) directly but I'm totally fine with this. > ACCESS_DESCRIPTION has an oid (ASN1_OBJECT) called method and a > GENERAL_NAME called location. All three resources we currently care > about are of the URI type, the new GEN_URI check makes sure of that > (the discarded ptag argument of ASN1_frame() should have been checked > to be GEN_URI). > > Overall, I think the resulting code is a lot easier to follow and more > correct. This is a lot cleaner and indeed an improvement. I think some of the rc handling can also be simplified. The code in sbgp_sia_resource_entry() and sbgp_sia_resource() no longer require cleanup on error so we can just return 0 instead of goto out. It is OK to do this cleanup in a 2nd step (which you probably already planned). OK claudio@ > Index: cert.c > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v > retrieving revision 1.62 > diff -u -p -r1.62 cert.c > --- cert.c 5 Apr 2022 03:56:20 -0000 1.62 > +++ cert.c 5 Apr 2022 04:54:18 -0000 > @@ -214,63 +214,45 @@ sbgp_sia_resource_carepo(struct parse *p > * Returns zero on failure, non-zero on success. > */ > static int > -sbgp_sia_resource_entry(struct parse *p, > - const unsigned char *d, size_t dsz) > +sbgp_sia_resource_entry(struct parse *p, ACCESS_DESCRIPTION *ad) > { > - ASN1_SEQUENCE_ANY *seq; > ASN1_OBJECT *oid; > - const ASN1_TYPE *t; > - int rc = 0, ptag; > - long plen; > + ASN1_IA5STRING *uri = NULL; > + int rc = 0; > > - if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) { > - cryptowarnx("%s: RFC 6487 section 4.8.8: SIA: " > - "failed ASN.1 sequence parse", p->fn); > - goto out; > - } > - if (sk_ASN1_TYPE_num(seq) != 2) { > - warnx("%s: RFC 6487 section 4.8.8: SIA: " > - "want 2 elements, have %d", > - p->fn, sk_ASN1_TYPE_num(seq)); > - goto out; > - } > + if (ad->location->type == GEN_URI) > + uri = ad->location->d.uniformResourceIdentifier; > > - /* Composed of an OID and its continuation. */ > + oid = ad->method; > > - t = sk_ASN1_TYPE_value(seq, 0); > - if (t->type != V_ASN1_OBJECT) { > - warnx("%s: RFC 6487 section 4.8.8: SIA: " > - "want ASN.1 object, have %s (NID %d)", > - p->fn, ASN1_tag2str(t->type), t->type); > - goto out; > - } > - oid = t->value.object; > - > - t = sk_ASN1_TYPE_value(seq, 1); > - if (t->type != V_ASN1_OTHER) { > - warnx("%s: RFC 6487 section 4.8.8: SIA: " > - "want ASN.1 external, have %s (NID %d)", > - p->fn, ASN1_tag2str(t->type), t->type); > - goto out; > + if (OBJ_cmp(oid, carepo_oid) == 0) { > + if (uri == NULL) { > + warnx("%s: RFC 6487: 4.8.8.1 caRepository without URI", > + p->fn); > + goto out; > + } > + if (!sbgp_sia_resource_carepo(p, uri->data, uri->length)) > + goto out; > + } else if (OBJ_cmp(oid, manifest_oid) == 0) { > + if (uri == NULL) { > + warnx("%s: RFC 6487: 4.8.8 SIA manifest without URI", > + p->fn); > + goto out; > + } > + if (!sbgp_sia_resource_mft(p, uri->data, uri->length)) > + goto out; > + } else if (OBJ_cmp(oid, notify_oid) == 0) { > + if (uri == NULL) { > + warnx("%s: RFC 6487: 4.8.8 SIA resourceNnotify " > + "without URI", p->fn); > + goto out; > + } > + if (!sbgp_sia_resource_notify(p, uri->data, uri->length)) > + goto out; > } > > - /* FIXME: there must be a way to do this without ASN1_frame. */ > - > - d = t->value.asn1_string->data; > - dsz = t->value.asn1_string->length; > - if (!ASN1_frame(p->fn, dsz, &d, &plen, &ptag)) > - goto out; > - > - if (OBJ_cmp(oid, carepo_oid) == 0) > - rc = sbgp_sia_resource_carepo(p, d, plen); > - else if (OBJ_cmp(oid, manifest_oid) == 0) > - rc = sbgp_sia_resource_mft(p, d, plen); > - else if (OBJ_cmp(oid, notify_oid) == 0) > - rc = sbgp_sia_resource_notify(p, d, plen); > - else > - rc = 1; /* silently ignore */ > -out: > - sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free); > + rc = 1; > + out: > return rc; > } > > @@ -279,29 +261,14 @@ out: > * Returns zero on failure, non-zero on success. > */ > static int > -sbgp_sia_resource(struct parse *p, const unsigned char *d, size_t dsz) > +sbgp_sia_resource(struct parse *p, AUTHORITY_INFO_ACCESS *sia) > { > - ASN1_SEQUENCE_ANY *seq; > - const ASN1_TYPE *t; > - int rc = 0, i; > + ACCESS_DESCRIPTION *ad; > + int i, rc = 0; > > - if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) { > - cryptowarnx("%s: RFC 6487 section 4.8.8: SIA: " > - "failed ASN.1 sequence parse", p->fn); > - goto out; > - } > - > - for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) { > - t = sk_ASN1_TYPE_value(seq, i); > - if (t->type != V_ASN1_SEQUENCE) { > - warnx("%s: RFC 6487 section 4.8.8: SIA: " > - "want ASN.1 sequence, have %s (NID %d)", > - p->fn, ASN1_tag2str(t->type), t->type); > - goto out; > - } > - d = t->value.asn1_string->data; > - dsz = t->value.asn1_string->length; > - if (!sbgp_sia_resource_entry(p, d, dsz)) > + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(sia); i++) { > + ad = sk_ACCESS_DESCRIPTION_value(sia, i); > + if (!sbgp_sia_resource_entry(p, ad)) > goto out; > } > > @@ -317,9 +284,9 @@ sbgp_sia_resource(struct parse *p, const > p->fn); > goto out; > } > + > rc = 1; > -out: > - sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free); > + out: > return rc; > } > > @@ -330,11 +297,8 @@ out: > static int > sbgp_sia(struct parse *p, X509_EXTENSION *ext) > { > - unsigned char *sv = NULL; > - const unsigned char *d; > - ASN1_SEQUENCE_ANY *seq = NULL; > - const ASN1_TYPE *t; > - int dsz, rc = 0; > + AUTHORITY_INFO_ACCESS *sia = NULL; > + int rc = 0; > > if (X509_EXTENSION_get_critical(ext)) { > warnx("%s: RFC 6487 section 4.8.8: SIA: " > @@ -342,57 +306,17 @@ sbgp_sia(struct parse *p, X509_EXTENSION > goto out; > } > > - if ((dsz = i2d_X509_EXTENSION(ext, &sv)) < 0) { > + if ((sia = X509V3_EXT_d2i(ext)) == NULL) { > cryptowarnx("%s: RFC 6487 section 4.8.8: SIA: " > "failed extension parse", p->fn); > goto out; > } > - d = sv; > - > - if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) { > - cryptowarnx("%s: RFC 6487 section 4.8.8: SIA: " > - "failed ASN.1 sequence parse", p->fn); > - goto out; > - } > - if (sk_ASN1_TYPE_num(seq) != 2) { > - warnx("%s: RFC 6487 section 4.8.8: SIA: " > - "want 2 elements, have %d", p->fn, > - sk_ASN1_TYPE_num(seq)); > - goto out; > - } > - > - t = sk_ASN1_TYPE_value(seq, 0); > - if (t->type != V_ASN1_OBJECT) { > - warnx("%s: RFC 6487 section 4.8.8: SIA: " > - "want ASN.1 object, have %s (NID %d)", > - p->fn, ASN1_tag2str(t->type), t->type); > - goto out; > - } > - if (OBJ_obj2nid(t->value.object) != NID_sinfo_access) { > - warnx("%s: RFC 6487 section 4.8.8: SIA: " > - "incorrect OID, have %s (NID %d)", p->fn, > - ASN1_tag2str(OBJ_obj2nid(t->value.object)), > - OBJ_obj2nid(t->value.object)); > - goto out; > - } > - > - t = sk_ASN1_TYPE_value(seq, 1); > - if (t->type != V_ASN1_OCTET_STRING) { > - warnx("%s: RFC 6487 section 4.8.8: SIA: " > - "want ASN.1 octet string, have %s (NID %d)", > - p->fn, ASN1_tag2str(t->type), t->type); > - goto out; > - } > - > - d = t->value.octet_string->data; > - dsz = t->value.octet_string->length; > - if (!sbgp_sia_resource(p, d, dsz)) > + if (!sbgp_sia_resource(p, sia)) > goto out; > > rc = 1; > -out: > - sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free); > - free(sv); > + out: > + AUTHORITY_INFO_ACCESS_free(sia); > return rc; > } > > -- :wq Claudio