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

Reply via email to