The ASIdentifiers code is a bit strangely factored presumably due to
constraints of the low-level shoveling. I kept the coarse structure
of the code and left some house keeping for later. The changes in
sbgp_asrange() and sbgp_asid() should be easy.

The in-tree sbgp_assysnum() is tricky to follow. The main thing to
note is that the for loop at the end really only inspects asnum (and
ignores rdi). Since RDI is forbidden in RFC 6487, I added a check
and error. All the complicated gymnastics can be dropped and what
remains is a bit stricter and what it does should be rather obvious.

With this diff, ASN1_TYPE and ASN1_frame() uses are gone from cert.c.

Index: cert.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.74
diff -u -p -r1.74 cert.c
--- cert.c      10 May 2022 16:43:53 -0000      1.74
+++ cert.c      10 May 2022 18:13:02 -0000
@@ -34,13 +34,6 @@
 #include "extern.h"
 
 /*
- * Type of ASIdentifier (RFC 3779, 3.2.3).
- */
-#define        ASID_TYPE_ASNUM 0x00
-#define ASID_TYPE_RDI  0x01
-#define ASID_TYPE_MAX  ASID_TYPE_RDI
-
-/*
  * A parsing sequence of a file (which may just be <stdin>).
  */
 struct parse {
@@ -128,70 +121,36 @@ sbgp_addr(struct parse *p, struct cert_i
  * Returns zero on failure, non-zero on success.
  */
 static int
-sbgp_asrange(struct parse *p, const unsigned char *d, size_t dsz)
+sbgp_asrange(struct parse *p, const ASRange *range)
 {
        struct cert_as           as;
-       ASN1_SEQUENCE_ANY       *seq;
-       const ASN1_TYPE         *t;
-       int                      rc = 0;
-
-       if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
-               cryptowarnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
-                   "failed ASN.1 sequence parse", p->fn);
-               goto out;
-       }
-       if (sk_ASN1_TYPE_num(seq) != 2) {
-               warnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
-                   "want 2 elements, have %d", p->fn,
-                   sk_ASN1_TYPE_num(seq));
-               goto out;
-       }
 
        memset(&as, 0, sizeof(struct cert_as));
        as.type = CERT_AS_RANGE;
 
-       t = sk_ASN1_TYPE_value(seq, 0);
-       if (t->type != V_ASN1_INTEGER) {
-               warnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
-                   "want ASN.1 integer, have %s (NID %d)",
-                   p->fn, ASN1_tag2str(t->type), t->type);
-               goto out;
-       }
-       if (!as_id_parse(t->value.integer, &as.range.min)) {
+       if (!as_id_parse(range->min, &as.range.min)) {
                warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
                    "malformed AS identifier", p->fn);
-               goto out;
+               return 0;
        }
 
-       t = sk_ASN1_TYPE_value(seq, 1);
-       if (t->type != V_ASN1_INTEGER) {
-               warnx("%s: RFC 3779 section 3.2.3.8: ASRange: "
-                   "want ASN.1 integer, have %s (NID %d)",
-                   p->fn, ASN1_tag2str(t->type), t->type);
-               goto out;
-       }
-       if (!as_id_parse(t->value.integer, &as.range.max)) {
+       if (!as_id_parse(range->max, &as.range.max)) {
                warnx("%s: RFC 3779 section 3.2.3.8 (via RFC 1930): "
                    "malformed AS identifier", p->fn);
-               goto out;
+               return 0;
        }
 
        if (as.range.max == as.range.min) {
                warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
                    "range is singular", p->fn);
-               goto out;
+               return 0;
        } else if (as.range.max < as.range.min) {
                warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
                    "range is out of order", p->fn);
-               goto out;
+               return 0;
        }
 
-       if (!append_as(p, &as))
-               goto out;
-       rc = 1;
-out:
-       sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
-       return rc;
+       return append_as(p, &as);
 }
 
 /*
@@ -224,80 +183,46 @@ sbgp_asid(struct parse *p, const ASN1_IN
  * Returns zero on failure, non-zero on success.
  */
 static int
-sbgp_asnum(struct parse *p, const unsigned char *d, size_t dsz)
+sbgp_asnum(struct parse *p, const ASIdentifierChoice *aic)
 {
        struct cert_as           as;
-       ASN1_TYPE               *t, *tt;
-       ASN1_SEQUENCE_ANY       *seq = NULL;
-       int                      i, rc = 0;
-       const unsigned char     *sv = d;
-
-       /* We can either be a null (inherit) or sequence. */
-
-       if ((t = d2i_ASN1_TYPE(NULL, &d, dsz)) == NULL) {
-               cryptowarnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
-                   "failed ASN.1 type parse", p->fn);
-               goto out;
-       }
-
-       /*
-        * Section 3779 3.2.3.3 is to inherit with an ASN.1 NULL type,
-        * which is the easy case.
-        */
+       const ASIdOrRanges      *aors = NULL;
+       const ASIdOrRange       *aor;
+       int                      i;
 
-       switch (t->type) {
-       case V_ASN1_NULL:
+       switch (aic->type) {
+       case ASIdentifierChoice_inherit:
                memset(&as, 0, sizeof(struct cert_as));
                as.type = CERT_AS_INHERIT;
-               if (!append_as(p, &as))
-                       goto out;
-               rc = 1;
-               goto out;
-       case V_ASN1_SEQUENCE:
+               return append_as(p, &as);
+       case ASIdentifierChoice_asIdsOrRanges:
+               aors = aic->u.asIdsOrRanges;
                break;
        default:
                warnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
-                   "want ASN.1 sequence or null, have %s (NID %d)",
-                   p->fn, ASN1_tag2str(t->type), t->type);
-               goto out;
-       }
-
-       /* This is RFC 3779 3.2.3.4. */
-
-       if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &sv, dsz)) == NULL) {
-               cryptowarnx("%s: RFC 3779 section 3.2.3.2: ASIdentifierChoice: "
-                   "failed ASN.1 sequence parse", p->fn);
-               goto out;
+                   "unknown type %d", p->fn, aic->type);
+               return 0;
        }
 
-       /* Accepts RFC 3779 3.2.3.6 or 3.2.3.7 (sequence). */
-
-       for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
-               tt = sk_ASN1_TYPE_value(seq, i);
-               switch (tt->type) {
-               case V_ASN1_INTEGER:
-                       if (!sbgp_asid(p, tt->value.integer))
-                               goto out;
+       for (i = 0; i < sk_ASIdOrRange_num(aors); i++) {
+               aor = sk_ASIdOrRange_value(aors, i);
+               switch (aor->type) {
+               case ASIdOrRange_id:
+                       if (!sbgp_asid(p, aor->u.id))
+                               return 0;
                        break;
-               case V_ASN1_SEQUENCE:
-                       d = tt->value.asn1_string->data;
-                       dsz = tt->value.asn1_string->length;
-                       if (!sbgp_asrange(p, d, dsz))
-                               goto out;
+               case ASIdOrRange_range:
+                       if (!sbgp_asrange(p, aor->u.range))
+                               return 0;
                        break;
                default:
                        warnx("%s: RFC 3779 section 3.2.3.5: ASIdOrRange: "
-                           "want ASN.1 sequence or integer, have %s (NID %d)",
-                           p->fn, ASN1_tag2str(tt->type), tt->type);
-                       goto out;
+                           "unknown type %d", p->fn, aor->type);
+                       return 0;
                }
        }
 
-       rc = 1;
-out:
-       ASN1_TYPE_free(t);
-       sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
-       return rc;
+       return 1;
 }
 
 /*
@@ -308,12 +233,8 @@ out:
 static int
 sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
 {
-       unsigned char           *sv = NULL;
-       const unsigned char     *d;
-       ASN1_SEQUENCE_ANY       *seq = NULL, *sseq = NULL;
-       const ASN1_TYPE         *t;
-       int                      dsz, rc = 0, i, ptag;
-       long                     plen;
+       ASIdentifiers           *asidentifiers = NULL;
+       int                      rc = 0;
 
        if (!X509_EXTENSION_get_critical(ext)) {
                cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
@@ -321,98 +242,30 @@ sbgp_assysnum(struct parse *p, X509_EXTE
                goto out;
        }
 
-       if ((dsz = i2d_X509_EXTENSION(ext, &sv)) < 0) {
+       if ((asidentifiers = X509V3_EXT_d2i(ext)) == NULL) {
                cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
                    "failed extension parse", p->fn);
                goto out;
        }
 
-       /* Start with RFC 3779, section 3.2 top-level. */
-
-       d = sv;
-       if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
-               cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
-                   "failed ASN.1 sequence parse", p->fn);
-               goto out;
-       }
-       if (sk_ASN1_TYPE_num(seq) != 3) {
-               warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
-                   "want 3 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.11: autonomousSysNum: "
-                   "want ASN.1 object, have %s (NID %d)",
-                   p->fn, ASN1_tag2str(t->type), t->type);
-               goto out;
-       }
-
-       t = sk_ASN1_TYPE_value(seq, 1);
-       if (t->type != V_ASN1_BOOLEAN) {
+       if (asidentifiers->rdi != NULL) {
                warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
-                   "want ASN.1 boolean, have %s (NID %d)",
-                   p->fn, ASN1_tag2str(t->type), t->type);
+                   "should not have RDI values", p->fn);
                goto out;
        }
 
-       t = sk_ASN1_TYPE_value(seq, 2);
-       if (t->type != V_ASN1_OCTET_STRING) {
+       if (asidentifiers->asnum == NULL) {
                warnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
-                   "want ASN.1 octet string, have %s (NID %d)",
-                   p->fn, ASN1_tag2str(t->type), t->type);
+                   "no AS number resource set", p->fn);
                goto out;
        }
 
-       /* Within RFC 3779 3.2.3, check 3.2.3.1. */
-
-       d = t->value.octet_string->data;
-       dsz = t->value.octet_string->length;
-
-       if ((sseq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
-               cryptowarnx("%s: RFC 3779 section 3.2.3.1: ASIdentifiers: "
-                   "failed ASN.1 sequence parse", p->fn);
+       if (!sbgp_asnum(p, asidentifiers->asnum))
                goto out;
-       }
-
-       /* Scan through for private 3.2.3.2 classes. */
-
-       for (i = 0; i < sk_ASN1_TYPE_num(sseq); i++) {
-               t = sk_ASN1_TYPE_value(sseq, i);
-               if (t->type != V_ASN1_OTHER) {
-                       warnx("%s: RFC 3779 section 3.2.3.1: ASIdentifiers: "
-                           "want ASN.1 explicit, have %s (NID %d)", p->fn,
-                           ASN1_tag2str(t->type), t->type);
-                       goto out;
-               }
-
-               /* Use the low-level 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;
-
-               /* Ignore bad AS identifiers and RDI entries. */
-
-               if (ptag > ASID_TYPE_MAX) {
-                       warnx("%s: RFC 3779 section 3.2.3.1: ASIdentifiers: "
-                           "unknown explicit tag 0x%02x", p->fn, ptag);
-                       goto out;
-               } else if (ptag == ASID_TYPE_RDI)
-                       continue;
-
-               if (!sbgp_asnum(p, d, plen))
-                       goto out;
-       }
 
        rc = 1;
-out:
-       sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
-       sk_ASN1_TYPE_pop_free(sseq, ASN1_TYPE_free);
-       free(sv);
+ out:
+       ASIdentifiers_free(asidentifiers);
        return rc;
 }
 

Reply via email to