On Tue, May 31, 2022 at 01:16:19PM +0200, Theo Buehler wrote:
> I chose to implement the constrained versions of the RFC 3779 types from
> the draft because the OpenSSL RFC 3779 code has static IPAddrBlocks_it,
> so we have to work around that anyway. This isn't quite minimal, but it
> avoids asymmetry between ASIdentifiers and IPAddrBlocks and it's cleaner
> than reusing as many of the available RFC 3779 types as possible (which
> also means additional checks either when walking the structs or after).
> 
> The diff has three parts that build on top of each other. There is no
> overlap outside of extern.h, so it should not make the review harder.
> 
> The mechanical cert.c diff adjusts some sbgp_addr_*() and sbgp_as_*() to
> remove the struct parse argument so that we can use them from rsc.c.
> 
> The rsc.c diff is the tricky part: it switches to templates and uses the
> cert.c functions. rsc_parse_aslist() and rsc_parse_iplist() are similar
> to sbgp_assysnum() and sbgp_ipaddrblk(), but somewhat easier. We get
> rid of the copy-paste XXXs and the last bit of low level ASN.1 fiddling. 
> 
> Remove the unused ASN1_frame() and cms_econtent_version() from cms.c.

I checked the changes outside of rsc.c and am OK with those.
I also looked at the new version of rsc.c and think it is much nicer code.
I did not test the rsc.c changes with an RSC file though.
 
OK claudio@

> Index: cert.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
> retrieving revision 1.82
> diff -u -p -r1.82 cert.c
> --- cert.c    15 May 2022 15:00:53 -0000      1.82
> +++ cert.c    31 May 2022 10:46:00 -0000
> @@ -58,11 +58,12 @@ extern ASN1_OBJECT        *notify_oid;    /* 1.3.6
>   * Returns zero on failure (IP overlap) non-zero on success.
>   */
>  static int
> -append_ip(struct parse *p, const struct cert_ip *ip)
> +append_ip(const char *fn, struct cert_ip *ips, size_t *ipsz,
> +    const struct cert_ip *ip)
>  {
> -     if (!ip_addr_check_overlap(ip, p->fn, p->res->ips, p->res->ipsz))
> +     if (!ip_addr_check_overlap(ip, fn, ips, *ipsz))
>               return 0;
> -     p->res->ips[p->res->ipsz++] = *ip;
> +     ips[(*ipsz)++] = *ip;
>       return 1;
>  }
>  
> @@ -72,11 +73,12 @@ append_ip(struct parse *p, const struct 
>   * as defined by RFC 3779 section 3.3.
>   */
>  static int
> -append_as(struct parse *p, const struct cert_as *as)
> +append_as(const char *fn, struct cert_as *ases, size_t *asz,
> +    const struct cert_as *as)
>  {
> -     if (!as_check_overlap(as, p->fn, p->res->as, p->res->asz))
> +     if (!as_check_overlap(as, fn, ases, *asz))
>               return 0;
> -     p->res->as[p->res->asz++] = *as;
> +     ases[(*asz)++] = *as;
>       return 1;
>  }
>  
> @@ -84,8 +86,9 @@ append_as(struct parse *p, const struct 
>   * Parse a range of AS identifiers as in 3.2.3.8.
>   * Returns zero on failure, non-zero on success.
>   */
> -static int
> -sbgp_asrange(struct parse *p, const ASRange *range)
> +int
> +sbgp_as_range(const char *fn, struct cert_as *ases, size_t *asz,
> +    const ASRange *range)
>  {
>       struct cert_as           as;
>  
> @@ -94,34 +97,35 @@ sbgp_asrange(struct parse *p, const ASRa
>  
>       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);
> +                 "malformed AS identifier", fn);
>               return 0;
>       }
>  
>       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);
> +                 "malformed AS identifier", fn);
>               return 0;
>       }
>  
>       if (as.range.max == as.range.min) {
>               warnx("%s: RFC 3379 section 3.2.3.8: ASRange: "
> -                 "range is singular", p->fn);
> +                 "range is singular", fn);
>               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);
> +                 "range is out of order", fn);
>               return 0;
>       }
>  
> -     return append_as(p, &as);
> +     return append_as(fn, ases, asz, &as);
>  }
>  
>  /*
>   * Parse an entire 3.2.3.10 integer type.
>   */
> -static int
> -sbgp_asid(struct parse *p, const ASN1_INTEGER *i)
> +int
> +sbgp_as_id(const char *fn, struct cert_as *ases, size_t *asz,
> +    const ASN1_INTEGER *i)
>  {
>       struct cert_as   as;
>  
> @@ -130,27 +134,27 @@ sbgp_asid(struct parse *p, const ASN1_IN
>  
>       if (!as_id_parse(i, &as.id)) {
>               warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): "
> -                 "malformed AS identifier", p->fn);
> +                 "malformed AS identifier", fn);
>               return 0;
>       }
>       if (as.id == 0) {
>               warnx("%s: RFC 3779 section 3.2.3.10 (via RFC 1930): "
> -                 "AS identifier zero is reserved", p->fn);
> +                 "AS identifier zero is reserved", fn);
>               return 0;
>       }
>  
> -     return append_as(p, &as);
> +     return append_as(fn, ases, asz, &as);
>  }
>  
>  static int
> -sbgp_asinherit(struct parse *p)
> +sbgp_as_inherit(const char *fn, struct cert_as *ases, size_t *asz)
>  {
>       struct cert_as as;
>  
>       memset(&as, 0, sizeof(struct cert_as));
>       as.type = CERT_AS_INHERIT;
>  
> -     return append_as(p, &as);
> +     return append_as(fn, ases, asz, &as);
>  }
>  
>  /*
> @@ -214,7 +218,7 @@ sbgp_assysnum(struct parse *p, X509_EXTE
>               err(1, NULL);
>  
>       if (aors == NULL) {
> -             if (!sbgp_asinherit(p))
> +             if (!sbgp_as_inherit(p->fn, p->res->as, &p->res->asz))
>                       goto out;
>       }
>  
> @@ -224,11 +228,13 @@ sbgp_assysnum(struct parse *p, X509_EXTE
>               aor = sk_ASIdOrRange_value(aors, i);
>               switch (aor->type) {
>               case ASIdOrRange_id:
> -                     if (!sbgp_asid(p, aor->u.id))
> +                     if (!sbgp_as_id(p->fn, p->res->as, &p->res->asz,
> +                         aor->u.id))
>                               goto out;
>                       break;
>               case ASIdOrRange_range:
> -                     if (!sbgp_asrange(p, aor->u.range))
> +                     if (!sbgp_as_range(p->fn, p->res->as, &p->res->asz,
> +                         aor->u.range))
>                               goto out;
>                       break;
>               default:
> @@ -248,8 +254,9 @@ sbgp_assysnum(struct parse *p, X509_EXTE
>   * Construct a RFC 3779 2.2.3.8 range from its bit string.
>   * Returns zero on failure, non-zero on success.
>   */
> -static int
> -sbgp_addr(struct parse *p, enum afi afi, const ASN1_BIT_STRING *bs)
> +int
> +sbgp_addr(const char *fn, struct cert_ip *ips, size_t *ipsz, enum afi afi,
> +    const ASN1_BIT_STRING *bs)
>  {
>       struct cert_ip  ip;
>  
> @@ -258,27 +265,28 @@ sbgp_addr(struct parse *p, enum afi afi,
>       ip.afi = afi;
>       ip.type = CERT_IP_ADDR;
>  
> -     if (!ip_addr_parse(bs, afi, p->fn, &ip.ip)) {
> +     if (!ip_addr_parse(bs, afi, fn, &ip.ip)) {
>               warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
> -                 "invalid IP address", p->fn);
> +                 "invalid IP address", fn);
>               return 0;
>       }
>  
>       if (!ip_cert_compose_ranges(&ip)) {
>               warnx("%s: RFC 3779 section 2.2.3.8: IPAddress: "
> -                 "IP address range reversed", p->fn);
> +                 "IP address range reversed", fn);
>               return 0;
>       }
>  
> -     return append_ip(p, &ip);
> +     return append_ip(fn, ips, ipsz, &ip);
>  }
>  
>  /*
>   * Parse RFC 3779 2.2.3.9 range of addresses.
>   * Returns zero on failure, non-zero on success.
>   */
> -static int
> -sbgp_addr_range(struct parse *p, enum afi afi, const IPAddressRange *range)
> +int
> +sbgp_addr_range(const char *fn, struct cert_ip *ips, size_t *ipsz,
> +    enum afi afi, const IPAddressRange *range)
>  {
>       struct cert_ip  ip;
>  
> @@ -287,29 +295,30 @@ sbgp_addr_range(struct parse *p, enum af
>       ip.afi = afi;
>       ip.type = CERT_IP_RANGE;
>  
> -     if (!ip_addr_parse(range->min, afi, p->fn, &ip.range.min)) {
> +     if (!ip_addr_parse(range->min, afi, fn, &ip.range.min)) {
>               warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
> -                 "invalid IP address", p->fn);
> +                 "invalid IP address", fn);
>               return 0;
>       }
>  
> -     if (!ip_addr_parse(range->max, afi, p->fn, &ip.range.max)) {
> +     if (!ip_addr_parse(range->max, afi, fn, &ip.range.max)) {
>               warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
> -                 "invalid IP address", p->fn);
> +                 "invalid IP address", fn);
>               return 0;
>       }
>  
>       if (!ip_cert_compose_ranges(&ip)) {
>               warnx("%s: RFC 3779 section 2.2.3.9: IPAddressRange: "
> -                 "IP address range reversed", p->fn);
> +                 "IP address range reversed", fn);
>               return 0;
>       }
>  
> -     return append_ip(p, &ip);
> +     return append_ip(fn, ips, ipsz, &ip);
>  }
>  
>  static int
> -sbgp_addr_inherit(struct parse *p, enum afi afi)
> +sbgp_addr_inherit(const char *fn, struct cert_ip *ips, size_t *ipsz,
> +    enum afi afi)
>  {
>       struct cert_ip  ip;
>  
> @@ -318,7 +327,7 @@ sbgp_addr_inherit(struct parse *p, enum 
>       ip.afi = afi;
>       ip.type = CERT_IP_INHERIT;
>  
> -     return append_ip(p, &ip);
> +     return append_ip(fn, ips, ipsz, &ip);
>  }
>  
>  /*
> @@ -380,7 +389,8 @@ sbgp_ipaddrblk(struct parse *p, X509_EXT
>               }
>  
>               if (aors == NULL) {
> -                     if (!sbgp_addr_inherit(p, afi))
> +                     if (!sbgp_addr_inherit(p->fn, p->res->ips,
> +                         &p->res->ipsz, afi))
>                               goto out;
>                       continue;
>               }
> @@ -389,12 +399,13 @@ sbgp_ipaddrblk(struct parse *p, X509_EXT
>                       aor = sk_IPAddressOrRange_value(aors, j);
>                       switch (aor->type) {
>                       case IPAddressOrRange_addressPrefix:
> -                             if (!sbgp_addr(p, afi, aor->u.addressPrefix))
> +                             if (!sbgp_addr(p->fn, p->res->ips,
> +                                 &p->res->ipsz, afi, aor->u.addressPrefix))
>                                       goto out;
>                               break;
>                       case IPAddressOrRange_addressRange:
> -                             if (!sbgp_addr_range(p, afi,
> -                                 aor->u.addressRange))
> +                             if (!sbgp_addr_range(p->fn, p->res->ips,
> +                                 &p->res->ipsz, afi, aor->u.addressRange))
>                                       goto out;
>                               break;
>                       default:
> Index: cms.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/cms.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 cms.c
> --- cms.c     15 May 2022 16:43:34 -0000      1.19
> +++ cms.c     28 May 2022 09:04:10 -0000
> @@ -272,61 +272,3 @@ out:
>  
>       return res;
>  }
> -
> -/*
> - * Wrapper around ASN1_get_object() that preserves the current start
> - * state and returns a more meaningful value.
> - * Return zero on failure, non-zero on success.
> - */
> -int
> -ASN1_frame(const char *fn, size_t sz,
> -    const unsigned char **cnt, long *cntsz, int *tag)
> -{
> -     int      ret, pcls;
> -
> -     ret = ASN1_get_object(cnt, cntsz, tag, &pcls, sz);
> -     if ((ret & 0x80)) {
> -             cryptowarnx("%s: ASN1_get_object", fn);
> -             return 0;
> -     }
> -     return ASN1_object_size((ret & 0x01) ? 2 : 0, *cntsz, *tag);
> -}
> -
> -/*
> - * Check the version field in eContent.
> - * Returns -1 on failure, zero on success.
> - */
> -int
> -cms_econtent_version(const char *fn, const unsigned char **d, size_t dsz,
> -    long *version)
> -{
> -     ASN1_INTEGER    *aint = NULL;
> -     long             plen;
> -     int              ptag, rc = -1;
> -
> -     if (!ASN1_frame(fn, dsz, d, &plen, &ptag))
> -             goto out;
> -     if (ptag != 0) {
> -             warnx("%s: eContent version: expected explicit tag [0]", fn);
> -             goto out;
> -     }
> -
> -     aint = d2i_ASN1_INTEGER(NULL, d, plen);
> -     if (aint == NULL) {
> -             cryptowarnx("%s: eContent version: failed d2i_ASN1_INTEGER",
> -                 fn);
> -             goto out;
> -     }
> -
> -     *version = ASN1_INTEGER_get(aint);
> -     if (*version < 0) {
> -             warnx("%s: eContent version: expected positive integer, got:"
> -                 " %ld", fn, *version);
> -             goto out;
> -     }
> -
> -     rc = 0;
> -out:
> -     ASN1_INTEGER_free(aint);
> -     return rc;
> -}
> Index: extern.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.138
> diff -u -p -r1.138 extern.h
> --- extern.h  24 May 2022 09:20:49 -0000      1.138
> +++ extern.h  29 May 2022 21:05:03 -0000
> @@ -513,11 +513,6 @@ int               valid_rsc(const char *, struct aut
>  unsigned char        *cms_parse_validate(X509 **, const char *,
>                   const unsigned char *, size_t,
>                   const ASN1_OBJECT *, size_t *);
> -int           cms_econtent_version(const char *, const unsigned char **,
> -                 size_t, long *);
> -/* Helper for ASN1 parsing */
> -int           ASN1_frame(const char *, size_t,
> -                     const unsigned char **, long *, int *);
>  
>  /* Work with RFC 3779 IP addresses, prefixes, ranges. */
>  
> @@ -535,6 +530,11 @@ int               ip_addr_check_covered(enum afi, co
>  int           ip_cert_compose_ranges(struct cert_ip *);
>  void          ip_roa_compose_ranges(struct roa_ip *);
>  
> +int           sbgp_addr(const char *, struct cert_ip *, size_t *,
> +                 enum afi, const ASN1_BIT_STRING *);
> +int           sbgp_addr_range(const char *, struct cert_ip *, size_t *,
> +                 enum afi, const IPAddressRange *);
> +
>  /* Work with RFC 3779 AS numbers, ranges. */
>  
>  int           as_id_parse(const ASN1_INTEGER *, uint32_t *);
> @@ -542,6 +542,11 @@ int               as_check_overlap(const struct cert
>                       const struct cert_as *, size_t);
>  int           as_check_covered(uint32_t, uint32_t,
>                       const struct cert_as *, size_t);
> +
> +int           sbgp_as_id(const char *, struct cert_as *, size_t *,
> +                 const ASN1_INTEGER *);
> +int           sbgp_as_range(const char *, struct cert_as *, size_t *,
> +                 const ASRange *);
>  
>  /* Parser-specific */
>  void          entity_free(struct entity *);
> Index: rpki-client.8
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/rpki-client.8,v
> retrieving revision 1.64
> diff -u -p -r1.64 rpki-client.8
> --- rpki-client.8     20 May 2022 10:38:39 -0000      1.64
> +++ rpki-client.8     28 May 2022 09:04:10 -0000
> @@ -271,7 +271,7 @@ A Profile for BGPsec Router Certificates
>  Certification Requests.
>  .It RFC 8630
>  Resource Public Key Infrastructure (RPKI) Trust Anchor Locator.
> -.It draft-ietf-sidrops-rpki-rsc-06
> +.It draft-ietf-sidrops-rpki-rsc-08
>  A profile for Resource Public Key Infrastructure (RPKI) Signed Checklists 
> (RSC).
>  .El
>  .Sh HISTORY
> Index: rsc.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/rsc.c,v
> retrieving revision 1.4
> diff -u -p -r1.4 rsc.c
> --- rsc.c     15 May 2022 16:43:35 -0000      1.4
> +++ rsc.c     31 May 2022 11:09:26 -0000
> @@ -16,16 +16,17 @@
>   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>   */
>  
> -#include <assert.h>
>  #include <err.h>
> -#include <stdarg.h>
> -#include <stdint.h>
>  #include <stdlib.h>
>  #include <string.h>
>  #include <unistd.h>
>  
>  #include <openssl/asn1.h>
> +#include <openssl/asn1t.h>
> +#include <openssl/safestack.h>
> +#include <openssl/stack.h>
>  #include <openssl/x509.h>
> +#include <openssl/x509v3.h>
>  
>  #include "extern.h"
>  
> @@ -40,520 +41,273 @@ struct  parse {
>  extern ASN1_OBJECT   *rsc_oid;
>  
>  /*
> - * Append an AS identifier structure to our list of results.
> - * Return zero on failure.
> - * XXX: merge with append_as() in cert.c
> + * Types and templates for RSC eContent draft-ietf-sidrops-rpki-rsc-08
>   */
> -static int
> -append_as(struct parse *p, const struct cert_as *as)
> -{
> -     if (!as_check_overlap(as, p->fn, p->res->as, p->res->asz))
> -             return 0;
> -     if (p->res->asz >= MAX_AS_SIZE)
> -             return 0;
> -     p->res->as = reallocarray(p->res->as, p->res->asz + 1,
> -         sizeof(struct cert_as));
> -     if (p->res->as == NULL)
> -             err(1, NULL);
> -     p->res->as[p->res->asz++] = *as;
> -     return 1;
> -}
>  
> -/*
> - * Append an IP address structure to our list of results.
> - * return zero on failure.
> - * XXX: merge with append_ip() in cert.c
> - */
> -static int
> -append_ip(struct parse *p, const struct cert_ip *ip)
> -{
> -     struct rsc      *res = p->res;
> +typedef struct {
> +     ASIdOrRanges            *asnum;
> +} ConstrainedASIdentifiers;
> +
> +ASN1_SEQUENCE(ConstrainedASIdentifiers) = {
> +     ASN1_EXP_SEQUENCE_OF(ConstrainedASIdentifiers, asnum, ASIdOrRange, 0),
> +} ASN1_SEQUENCE_END(ConstrainedASIdentifiers);
> +
> +typedef struct {
> +     ASN1_OCTET_STRING               *addressFamily;
> +     STACK_OF(IPAddressOrRange)      *addressesOrRanges;
> +} ConstrainedIPAddressFamily;
> +
> +ASN1_SEQUENCE(ConstrainedIPAddressFamily) = {
> +     ASN1_SIMPLE(ConstrainedIPAddressFamily, addressFamily,
> +         ASN1_OCTET_STRING),
> +     ASN1_SEQUENCE_OF(ConstrainedIPAddressFamily, addressesOrRanges,
> +         IPAddressOrRange),
> +} ASN1_SEQUENCE_END(ConstrainedIPAddressFamily);
> +
> +typedef STACK_OF(ConstrainedIPAddressFamily) ConstrainedIPAddrBlocks;
> +DECLARE_STACK_OF(ConstrainedIPAddressFamily);
> +
> +ASN1_ITEM_TEMPLATE(ConstrainedIPAddrBlocks) =
> +     ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ConstrainedIPAddrBlocks,
> +         ConstrainedIPAddressFamily)
> +ASN1_ITEM_TEMPLATE_END(ConstrainedIPAddrBlocks);
> +
> +typedef struct {
> +     ConstrainedASIdentifiers        *asID;
> +     ConstrainedIPAddrBlocks         *ipAddrBlocks;
> +} ResourceBlock;
> +
> +ASN1_SEQUENCE(ResourceBlock) = {
> +     ASN1_EXP_OPT(ResourceBlock, asID, ConstrainedASIdentifiers, 0),
> +     ASN1_EXP_SEQUENCE_OF_OPT(ResourceBlock, ipAddrBlocks,
> +         ConstrainedIPAddressFamily, 1)
> +} ASN1_SEQUENCE_END(ResourceBlock);
> +
> +typedef struct {
> +     ASN1_IA5STRING          *fileName;
> +     ASN1_OCTET_STRING       *hash;
> +} FileNameAndHash;
> +
> +DECLARE_STACK_OF(FileNameAndHash);
> +
> +#ifndef DEFINE_STACK_OF
> +#define sk_ConstrainedIPAddressFamily_num(sk) \
> +    SKM_sk_num(ConstrainedIPAddressFamily, (sk))
> +#define sk_ConstrainedIPAddressFamily_value(sk, i) \
> +    SKM_sk_value(ConstrainedIPAddressFamily, (sk), (i))
> +
> +#define sk_FileNameAndHash_num(sk)   SKM_sk_num(FileNameAndHash, (sk))
> +#define sk_FileNameAndHash_value(sk, i)      SKM_sk_value(FileNameAndHash, 
> (sk), (i))
> +#endif
> +
> +ASN1_SEQUENCE(FileNameAndHash) = {
> +     ASN1_OPT(FileNameAndHash, fileName, ASN1_IA5STRING),
> +     ASN1_SIMPLE(FileNameAndHash, hash, ASN1_OCTET_STRING),
> +} ASN1_SEQUENCE_END(FileNameAndHash);
> +
> +typedef struct {
> +     ASN1_INTEGER                    *version;
> +     ResourceBlock                   *resources;
> +     X509_ALGOR                      *digestAlgorithm;
> +     STACK_OF(FileNameAndHash)       *checkList;
> +} RpkiSignedChecklist;
> +
> +ASN1_SEQUENCE(RpkiSignedChecklist) = {
> +     ASN1_IMP_OPT(RpkiSignedChecklist, version, ASN1_INTEGER, 0),
> +     ASN1_SIMPLE(RpkiSignedChecklist, resources, ResourceBlock),
> +     ASN1_SIMPLE(RpkiSignedChecklist, digestAlgorithm, X509_ALGOR),
> +     ASN1_SEQUENCE_OF(RpkiSignedChecklist, checkList, FileNameAndHash),
> +} ASN1_SEQUENCE_END(RpkiSignedChecklist);
>  
> -     if (!ip_addr_check_overlap(ip, p->fn, p->res->ips, p->res->ipsz))
> -             return 0;
> -     if (res->ipsz >= MAX_IP_SIZE)
> -             return 0;
> -
> -     res->ips = reallocarray(res->ips, res->ipsz + 1,
> -         sizeof(struct cert_ip));
> -     if (res->ips == NULL)
> -             err(1, NULL);
> -
> -     res->ips[res->ipsz++] = *ip;
> -     return 1;
> -}
> +DECLARE_ASN1_FUNCTIONS(RpkiSignedChecklist);
> +IMPLEMENT_ASN1_FUNCTIONS(RpkiSignedChecklist);
>  
>  static int
> -rsc_check_digesttype(struct parse *p, const unsigned char *d, size_t dsz)
> +rsc_check_digesttype(struct parse *p, const X509_ALGOR *alg)
>  {
> -     X509_ALGOR              *alg;
>       const ASN1_OBJECT       *obj;
>       int                      type, nid;
> -     int                      rc = 0;
> -
> -     if ((alg = d2i_X509_ALGOR(NULL, &d, dsz)) == NULL) {
> -             cryptowarnx("%s: RSC DigestAlgorithmIdentifier faild to parse",
> -                 p->fn);
> -             goto out;
> -     }
>  
>       X509_ALGOR_get0(&obj, &type, NULL, alg);
>  
>       if (type != V_ASN1_UNDEF) {
>               warnx("%s: RSC DigestAlgorithmIdentifier unexpected parameters:"
>                   " %d", p->fn, type);
> -             goto out;
> +             return 0;
>       }
>  
>       if ((nid = OBJ_obj2nid(obj)) != NID_sha256) {
>               warnx("%s: RSC DigestAlgorithmIdentifier: want SHA256, have %s"
>                   " (NID %d)", p->fn, ASN1_tag2str(nid), nid);
> -             goto out;
> +             return 0;
>       }
>  
> -     rc = 1;
> - out:
> -     X509_ALGOR_free(alg);
> -     return rc;
> +     return 1;
>  }
>  
>  /*
> - * Parse and individual "FileNameAndHash", draft-ietf-sidrops-rpki-rsc
> - * section 4.1.
> + * Parse the FileNameAndHash sequence, draft-ietf-sidrops-rpki-rsc, section 
> 4.1
>   * Return zero on failure, non-zero on success.
>   */
>  static int
> -rsc_parse_filenamehash(struct parse *p, const ASN1_OCTET_STRING *os)
> +rsc_parse_checklist(struct parse *p, const STACK_OF(FileNameAndHash) 
> *checkList)
>  {
> -     ASN1_SEQUENCE_ANY       *seq;
> -     const ASN1_TYPE         *file, *hash;
> -     char                    *fn = NULL;
> -     const unsigned char     *d = os->data;
> -     size_t                   dsz = os->length;
> -     int                      i = 0, rc = 0, elemsz;
> -     struct rscfile          *rent;
> -
> -     if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> -             cryptowarnx("%s: RSC FileNameAndHash: failed ASN.1 sequence "
> -                 "parse", p->fn);
> -             goto out;
> -     }
> -
> -     elemsz = sk_ASN1_TYPE_num(seq);
> -     if (elemsz != 1 && elemsz != 2) {
> -             warnx("%s: RSC FileNameAndHash: want 1 or 2 elements, have %d",
> -                 p->fn, elemsz);
> -             goto out;
> -     }
> +     FileNameAndHash         *fh;
> +     ASN1_IA5STRING          *fn;
> +     struct rscfile          *file;
> +     size_t                   sz, i;
>  
> -     if (elemsz == 2) {
> -             ASN1_IA5STRING *filename;
> -
> -             file = sk_ASN1_TYPE_value(seq, i++);
> -             if (file->type != V_ASN1_IA5STRING) {
> -                     warnx("%s: RSC FileNameAndHash: want ASN.1 IA5 string,"
> -                         " have %s (NID %d)", p->fn,
> -                         ASN1_tag2str(file->type), file->type);
> -                     goto out;
> -             }
> -
> -             filename = file->value.ia5string;
> -
> -             if (!valid_filename(filename->data, filename->length)) {
> -                     warnx("%s: RSC FileNameAndHash: bad filename", p->fn);
> -                     goto out;
> -             }
> -
> -             fn = strndup(filename->data, filename->length);
> -             if (fn == NULL)
> -                     err(1, NULL);
> -     }
> -
> -     /* Now hash value. */
> -
> -     hash = sk_ASN1_TYPE_value(seq, i);
> -     if (hash->type != V_ASN1_OCTET_STRING) {
> -             warnx("%s: RSC FileNameAndHash: want ASN.1 OCTET string, have "
> -                 "%s (NID %d)", p->fn, ASN1_tag2str(hash->type), hash->type);
> -             goto out;
> -     }
> -
> -     if (hash->value.octet_string->length != SHA256_DIGEST_LENGTH) {
> -             warnx("%s: RSC Digest: invalid SHA256 length, have %d",
> -                 p->fn, hash->value.octet_string->length);
> -             goto out;
> +     if ((sz = sk_FileNameAndHash_num(checkList)) == 0) {
> +             warnx("%s: RSC checkList needs at least one entry", p->fn);
> +             return 0;
>       }
>  
> -     p->res->files = recallocarray(p->res->files, p->res->filesz,
> -         p->res->filesz + 1, sizeof(struct rscfile));
> +     p->res->files = calloc(sz, sizeof(struct rscfile));
>       if (p->res->files == NULL)
>               err(1, NULL);
> +     p->res->filesz = sz;
>  
> -     rent = &p->res->files[p->res->filesz++];
> -     rent->filename = fn;
> -     fn = NULL;
> -     memcpy(rent->hash, hash->value.octet_string->data,
> -         SHA256_DIGEST_LENGTH);
> -
> -     rc = 1;
> - out:
> -     free(fn);
> -     sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> -     return rc;
> -}
> -
> -/*
> - * Parse the FileNameAndHash sequence, draft-ietf-sidrops-rpki-rsc
> - * section 4.1
> - * Return zero on failure, non-zero on success.
> - */
> -static int
> -rsc_parse_checklist(struct parse *p, const ASN1_OCTET_STRING *os)
> -{
> -     ASN1_SEQUENCE_ANY       *seq;
> -     const ASN1_TYPE         *t;
> -     const unsigned char     *d = os->data;
> -     size_t                   dsz = os->length;
> -     int                      i, rc = 0;
> +     for (i = 0; i < sz; i++) {
> +             fh = sk_FileNameAndHash_value(checkList, i);
>  
> -     if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> -             cryptowarnx("%s: RSC checkList: failed ASN.1 sequence parse",
> -                 p->fn);
> -             goto out;
> -     }
> +             file = &p->res->files[i];
>  
> -     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: RSC checkList: want ASN.1 sequence, have %s"
> -                         " (NID %d)", p->fn, ASN1_tag2str(t->type), t->type);
> -                     goto out;
> +             if (fh->hash->length != SHA256_DIGEST_LENGTH) {
> +                     warnx("%s: RSC Digest: invalid SHA256 length", p->fn);
> +                     return 0;
>               }
> -             if (!rsc_parse_filenamehash(p, t->value.octet_string))
> -                     goto out;
> -     }
> +             memcpy(file->hash, fh->hash->data, SHA256_DIGEST_LENGTH);
>  
> -     rc = 1;
> - out:
> -     sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> -     return rc;
> -}
> -
> -/*
> - * Convert ASN1 INTEGER and add it to parse results
> - * Return zero on failure.
> - * XXX: merge with sbgp_asid() in cert.c
> - */
> -static int
> -rsc_parse_asid(struct parse *p, const ASN1_INTEGER *i)
> -{
> -     struct cert_as           as;
> +             if ((fn = fh->fileName) == NULL)
> +                     continue;
>  
> -     memset(&as, 0, sizeof(struct cert_as));
> -     as.type = CERT_AS_ID;
> +             if (!valid_filename(fn->data, fn->length)) {
> +                     warnx("%s: RSC FileNameAndHash: bad filename", p->fn);
> +                     return 0;
> +             }
>  
> -     if (!as_id_parse(i, &as.id)) {
> -             warnx("%s: RSC malformed AS identifier", p->fn);
> -             return 0;
> -     }
> -     if (as.id == 0) {
> -             warnx("%s: RSC AS identifier zero is reserved", p->fn);
> -             return 0;
> +             file->filename = strndup(fn->data, fn->length);
> +             if (file->filename == NULL)
> +                     err(1, NULL);
>       }
>  
> -     return append_as(p, &as);
> +     return 1;
>  }
>  
>  /*
> - * Parse AS Range and add it to parse result
> - * Return zero on failure.
> - * XXX: merge with sbgp_asrange() in cert.c
> + * parse AsList (inside ResourceBlock)
> + * Return 0 on failure.
>   */
>  static int
> -rsc_parse_asrange(struct parse *p, const unsigned char *d, size_t dsz)
> +rsc_parse_aslist(struct parse *p, const ConstrainedASIdentifiers *asids)
>  {
> -     struct cert_as           as;
> -     ASN1_SEQUENCE_ANY       *seq;
> -     const ASN1_TYPE         *t;
> -     int                      rc = 0;
> +     int      i, asz;
>  
> -     if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> -             cryptowarnx("%s: ASRange failed ASN.1 seq parse", p->fn);
> -             goto out;
> -     }
> -
> -     if (sk_ASN1_TYPE_num(seq) != 2) {
> -             warnx("%s: expected 2 elements in RSC ASRange, 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: RSC 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)) {
> -             warnx("%s: RSC malformed AS identifier", p->fn);
> -             goto out;
> -     }
> +     if (asids == NULL)
> +             return 1;
>  
> -     t = sk_ASN1_TYPE_value(seq, 1);
> -     if (t->type != V_ASN1_INTEGER) {
> -             warnx("%s: RSC 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)) {
> -             warnx("%s: RSC malformed AS identifier", p->fn);
> -             goto out;
> +     if ((asz = sk_ASIdOrRange_num(asids->asnum)) == 0) {
> +             warnx("%s: RSC asID empty", p->fn);
> +             return 0;
>       }
>  
> -     if (as.range.max == as.range.min) {
> -             warnx("%s: RSC ASRange error: range is singular", p->fn);
> -             goto out;
> -     }
> -     if (as.range.max < as.range.min) {
> -             warnx("%s: RSC ASRange: range is out of order", p->fn);
> -             goto out;
> +     if (asz >= MAX_AS_SIZE) {
> +             warnx("%s: too many AS number entries: limit %d",
> +                 p->fn, MAX_AS_SIZE);
> +             return 0;
>       }
>  
> -     if (!append_as(p, &as))
> -             goto out;
> -
> -     rc = 1;
> - out:
> -     sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> -     return rc;
> -}
> +     p->res->as = calloc(asz, sizeof(struct cert_as));
> +     if (p->res->as == NULL)
> +             err(1, NULL);
>  
> -/*
> - * parse AsList (inside ResourceBlock)
> - * Return 0 on failure.
> - */
> -static int
> -rsc_parse_aslist(struct parse *p, const unsigned char *d, size_t dsz)
> -{
> -     ASN1_SEQUENCE_ANY       *seq;
> -     const ASN1_TYPE         *t;
> -     int                      i, rc = 0;
> +     for (i = 0; i < asz; i++) {
> +             const ASIdOrRange *aor;
>  
> -     if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> -             cryptowarnx("%s: RSC AsList: failed ASN.1 sequence parse",
> -                 p->fn);
> -             goto out;
> -     }
> +             aor = sk_ASIdOrRange_value(asids->asnum, i);
>  
> -     for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
> -             t = sk_ASN1_TYPE_value(seq, i);
> -             switch (t->type) {
> -             case V_ASN1_INTEGER:
> -                     if (!rsc_parse_asid(p, t->value.integer))
> -                             goto out;
> +             switch (aor->type) {
> +             case ASIdOrRange_id:
> +                     if (!sbgp_as_id(p->fn, p->res->as, &p->res->asz,
> +                         aor->u.id))
> +                             return 0;
>                       break;
> -             case V_ASN1_SEQUENCE:
> -                     d = t->value.asn1_string->data;
> -                     dsz = t->value.asn1_string->length;
> -                     if (!rsc_parse_asrange(p, d, dsz))
> -                             goto out;
> +             case ASIdOrRange_range:
> +                     if (!sbgp_as_range(p->fn, p->res->as, &p->res->asz,
> +                         aor->u.range))
> +                             return 0;
>                       break;
>               default:
> -                     warnx("%s: RSC AsList expected INTEGER or SEQUENCE, "
> -                         "have %s (NID %d)", p->fn, ASN1_tag2str(t->type),
> -                         t->type);
> -                     goto out;
> +                     warnx("%s: RSC AsList: unknown type %d", p->fn,
> +                         aor->type);
> +                     return 0;
>               }
>       }
>  
> -     rc = 1;
> - out:
> -     sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> -     return rc;
> +     return 1;
>  }
>  
> -/*
> - * parse IPAddressFamilyItem (inside IPList, inside ResourceBlock)
> - * Return 0 on failure.
> - */
>  static int
> -rsc_parse_ipaddrfamitem(struct parse *p, const ASN1_OCTET_STRING *os)
> +rsc_parse_iplist(struct parse *p, const ConstrainedIPAddrBlocks 
> *ipAddrBlocks)
>  {
> -     ASN1_OCTET_STRING       *aos = NULL;
> -     IPAddressOrRange        *aor = NULL;
> -     int                      tag;
> -     const unsigned char     *cnt = os->data;
> -     long                     cntsz;
> -     const unsigned char     *d;
> -     struct cert_ip           ip;
> -     int                      rc = 0;
> -
> -     memset(&ip, 0, sizeof(struct cert_ip));
> -
> -     /*
> -      * IPAddressFamilyItem is a sequence containing an addressFamily and
> -      * an IPAddressOrRange.
> -      */
> -     if (!ASN1_frame(p->fn, os->length, &cnt, &cntsz, &tag)) {
> -             cryptowarnx("%s: ASN1_frame failed", p->fn);
> -             goto out;
> -     }
> -     if (tag != V_ASN1_SEQUENCE) {
> -             warnx("expected ASN.1 sequence, got %d", tag);
> -             goto out;
> -     }
> -
> -     d = cnt;
> -
> -     if ((aos = d2i_ASN1_OCTET_STRING(NULL, &cnt, cntsz)) == NULL) {
> -             cryptowarnx("%s: d2i_ASN1_OCTET_STRING failed", p->fn);
> -             goto out;
> -     }
> -
> -     cntsz -= cnt - d;
> -     assert(cntsz >= 0);
> -
> -     if (!ip_addr_afi_parse(p->fn, aos, &ip.afi)) {
> -             warnx("%s: RSC invalid addressFamily", p->fn);
> -             goto out;
> -     }
> -
> -     d = cnt;
> -
> -     if ((aor = d2i_IPAddressOrRange(NULL, &cnt, cntsz)) == NULL) {
> -             warnx("%s: d2i_IPAddressOrRange failed", p->fn);
> -             goto out;
> -     }
> -
> -     cntsz -= cnt - d;
> -     assert(cntsz >= 0);
> -
> -     if (cntsz > 0) {
> -             warnx("%s: trailing garbage in RSC IPAddressFamilyItem", p->fn);
> -             goto out;
> -     }
> -
> -     switch (aor->type) {
> -     case IPAddressOrRange_addressPrefix:
> -             ip.type = CERT_IP_ADDR;
> -             if (!ip_addr_parse(aor->u.addressPrefix, ip.afi, p->fn, &ip.ip))
> -                     goto out;
> -             break;
> -     case IPAddressOrRange_addressRange:
> -             ip.type = CERT_IP_RANGE;
> -             if (!ip_addr_parse(aor->u.addressRange->min, ip.afi, p->fn,
> -                 &ip.range.min))
> -                     goto out;
> -             if (!ip_addr_parse(aor->u.addressRange->max, ip.afi, p->fn,
> -                 &ip.range.max))
> -                     goto out;
> -             break;
> -     default:
> -             warnx("%s: unknown addressOrRange type %d\n", p->fn, aor->type);
> -             goto out;
> -     }
> -
> -     if (!ip_cert_compose_ranges(&ip)) {
> -             warnx("%s: RSC IP address range reversed", p->fn);
> -             goto out;
> -     }
> -
> -     if (!append_ip(p, &ip))
> -             goto out;
> -
> -     rc = 1;
> - out:
> -     ASN1_OCTET_STRING_free(aos);
> -     IPAddressOrRange_free(aor);
> -     return rc;
> -}
> +     const ConstrainedIPAddressFamily        *af;
> +     const IPAddressOrRanges                 *aors;
> +     const IPAddressOrRange                  *aor;
> +     size_t                                   ipsz;
> +     enum afi                                 afi;
> +     int                                      i, j;
>  
> -static int
> -rsc_parse_iplist(struct parse *p, const unsigned char *d, size_t dsz)
> -{
> -     ASN1_SEQUENCE_ANY       *seq;
> -     const ASN1_TYPE         *t;
> -     int                      i, rc = 0;
> +     if (ipAddrBlocks == NULL)
> +             return 1;
>  
> -     if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> -             cryptowarnx("%s: RSC IPList: failed ASN.1 sequence parse",
> -                 p->fn);
> -             goto out;
> +     if (sk_ConstrainedIPAddressFamily_num(ipAddrBlocks) == 0) {
> +             warnx("%s: RSC ipAddrBlocks empty", p->fn);
> +             return 0;
>       }
>  
> -     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: RSC IPList: want ASN.1 sequence, have %s"
> -                         " (NID %d)", p->fn, ASN1_tag2str(t->type), t->type);
> -                     goto out;
> +     for (i = 0; i < sk_ConstrainedIPAddressFamily_num(ipAddrBlocks); i++) {
> +             af = sk_ConstrainedIPAddressFamily_value(ipAddrBlocks, i);
> +             aors = af->addressesOrRanges;
> +
> +             ipsz = p->res->ipsz + sk_IPAddressOrRange_num(aors);
> +             if (ipsz >= MAX_IP_SIZE) {
> +                     warnx("%s: too many IP address entries: limit %d",
> +                         p->fn, MAX_IP_SIZE);
> +                     return 0;
>               }
> -             if (!rsc_parse_ipaddrfamitem(p, t->value.octet_string))
> -                     goto out;
> -     }
> -
> -     rc = 1;
> - out:
> -     sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> -     return rc;
> -}
>  
> -/*
> - * Parse a ResourceBlock, draft-ietf-sidrops-rpki-rsc section 4
> - * Returns zero on failure, non-zero on success.
> - */
> -static int
> -rsc_parse_resourceblock(const ASN1_OCTET_STRING *os, struct parse *p)
> -{
> -     ASN1_SEQUENCE_ANY       *seq;
> -     const unsigned char     *d = os->data;
> -     size_t                   dsz = os->length;
> -     int                      i, ptag, rc = 0;
> -     const ASN1_TYPE         *t;
> -     long                     plen;
> -
> -     if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> -             cryptowarnx("%s: RSC: ResourceBlock: failed ASN.1 sequence "
> -                 "parse", p->fn);
> -             goto out;
> -     }
> -
> -     if (sk_ASN1_TYPE_num(seq) == 0) {
> -             warnx("%s: ResourceBlock, there must be at least one of asID "
> -                 "or ipAddrBlocks", p->fn);
> -             goto out;
> -     }
> +             p->res->ips = recallocarray(p->res->ips, p->res->ipsz, ipsz,
> +                 sizeof(struct cert_ip));
> +             if (p->res->ips == NULL)
> +                     err(1, NULL);
>  
> -     for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
> -             t = sk_ASN1_TYPE_value(seq, i);
> +             if (!ip_addr_afi_parse(p->fn, af->addressFamily, &afi)) {
> +                     warnx("%s: RSC: invalid AFI", p->fn);
> +                     return 0;
> +             }
>  
> -             d = t->value.asn1_string->data;
> -             dsz = t->value.asn1_string->length;
> -             if (!ASN1_frame(p->fn, dsz, &d, &plen, &ptag))
> -                     goto out;
> -             switch (ptag) {
> -             case RSRCBLK_TYPE_ASID:
> -                     if (!rsc_parse_aslist(p, d, plen))
> -                             goto out;
> -                     break;
> -             case RSRCBLK_TYPE_IPADDRBLK:
> -                     if (!rsc_parse_iplist(p, d, plen))
> -                             goto out;
> -                     break;
> -             default:
> -                     warnx("%s: want ASN.1 context specific id, have %s"
> -                         " (NID %d)", p->fn, ASN1_tag2str(ptag), ptag);
> -                     goto out;
> +             for (j = 0; j < sk_IPAddressOrRange_num(aors); j++) {
> +                     aor = sk_IPAddressOrRange_value(aors, j);
> +                     switch (aor->type) {
> +                     case IPAddressOrRange_addressPrefix:
> +                             if (!sbgp_addr(p->fn, p->res->ips,
> +                                 &p->res->ipsz, afi, aor->u.addressPrefix))
> +                                     return 0;
> +                             break;
> +                     case IPAddressOrRange_addressRange:
> +                             if (!sbgp_addr_range(p->fn, p->res->ips,
> +                                 &p->res->ipsz, afi, aor->u.addressRange))
> +                                     return 0;
> +                             break;
> +                     default:
> +                             warnx("%s: RFC 3779: IPAddressOrRange: "
> +                                 "unknown type %d", p->fn, aor->type);
> +                             return 0;
> +                     }
>               }
>       }
>  
> -     rc = 1;
> - out:
> -     sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> -     return rc;
> +     return 1;
>  }
>  
>  /*
> @@ -564,88 +318,61 @@ rsc_parse_resourceblock(const ASN1_OCTET
>  static int
>  rsc_parse_econtent(const unsigned char *d, size_t dsz, struct parse *p)
>  {
> -     ASN1_SEQUENCE_ANY       *seq;
> -     const ASN1_TYPE         *t;
> -     int                      i = 0, rc = 0, sz;
> +     RpkiSignedChecklist     *rsc = NULL;
> +     ResourceBlock           *resources;
>       long                     rsc_version;
> +     int                      rc = 0;
>  
>       /*
>        * draft-ietf-sidrops-rpki-rsc section 4
>        */
>  
> -     if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, &d, dsz)) == NULL) {
> -             cryptowarnx("%s: RSC: RpkiSignedChecklist: failed ASN.1 "
> -                 "sequence parse", p->fn);
> +     if ((rsc = d2i_RpkiSignedChecklist(NULL, &d, dsz)) == NULL) {
> +             cryptowarnx("%s: RSC: failed ASN.1 decode", p->fn);
>               goto out;
>       }
>  
> -     if ((sz = sk_ASN1_TYPE_num(seq)) != 3 && sz != 4) {
> -             warnx("%s: RSC RpkiSignedChecklist: want 3 or 4 elements, have"
> -                 "%d", p->fn, sk_ASN1_TYPE_num(seq));
> -             goto out;
> -     }
> -
> -     /*
> -      * if there are 4 elements, a version should be present: check it.
> -      */
> -     if (sz == 4) {
> -             t = sk_ASN1_TYPE_value(seq, i++);
> -             d = t->value.asn1_string->data;
> -             dsz = t->value.asn1_string->length;
> -
> -             if (cms_econtent_version(p->fn, &d, dsz, &rsc_version) == -1)
> +     /* Validate the optional version field */
> +     if (rsc->version != NULL) {
> +             rsc_version = ASN1_INTEGER_get(rsc->version);
> +             if (rsc_version < 0) {
> +                     cryptowarnx("%s: RSC: ASN1_INTEGER_get failed", p->fn);
>                       goto out;
> +             }
>  
> -             switch (rsc_version) {
> +             switch(rsc_version) {
>               case 0:
> -                     warnx("%s: invalid encoding for version 0", p->fn);
> +                     warnx("%s: RSC: incorrect version encoding", p->fn);
>                       goto out;
>               default:
> -                     warnx("%s: version %ld not supported (yet)", p->fn,
> +                     warnx("%s: RSC: version %ld not supported (yet)", p->fn,
>                           rsc_version);
>                       goto out;
>               }
>       }
>  
> -     /*
> -      * The RSC's eContent ResourceBlock indicates which Internet Number
> -      * Resources are associated with the signature over the checkList.
> -      */
> -     t = sk_ASN1_TYPE_value(seq, i++);
> -     if (t->type != V_ASN1_SEQUENCE) {
> -             warnx("%s: RSC ResourceBlock: want ASN.1 sequence, have %s"
> -                 "(NID %d)", p->fn, ASN1_tag2str(t->type), t->type);
> +     resources = rsc->resources;
> +     if (resources->asID == NULL && resources->ipAddrBlocks == NULL) {
> +             warnx("%s: RSC: one of asID or ipAddrBlocks must be present",
> +                 p->fn);
>               goto out;
>       }
> -     if (!rsc_parse_resourceblock(t->value.octet_string, p))
> -             goto out;
>  
> -     /* digestAlgorithm */
> -     t = sk_ASN1_TYPE_value(seq, i++);
> -     if (t->type != V_ASN1_SEQUENCE) {
> -             warnx("%s: RSC DigestAlgorithmIdentifier: want ASN.1 sequence,"
> -                 " have %s (NID %d)", p->fn, ASN1_tag2str(t->type), t->type);
> +     if (!rsc_parse_aslist(p, resources->asID))
>               goto out;
> -     }
> -     if (!rsc_check_digesttype(p, t->value.asn1_string->data,
> -         t->value.asn1_string->length))
> +
> +     if (!rsc_parse_iplist(p, resources->ipAddrBlocks))
>               goto out;
>  
> -     /*
> -      * Now a sequence of FileNameAndHash
> -      */
> -     t = sk_ASN1_TYPE_value(seq, i++);
> -     if (t->type != V_ASN1_SEQUENCE) {
> -             warnx("%s: RSC checkList: want ASN.1 sequence, have %s "
> -                 "(NID %d)", p->fn, ASN1_tag2str(t->type), t->type);
> +     if (!rsc_check_digesttype(p, rsc->digestAlgorithm))
>               goto out;
> -     }
> -     if (!rsc_parse_checklist(p, t->value.octet_string))
> +
> +     if (!rsc_parse_checklist(p, rsc->checkList))
>               goto out;
>  
>       rc = 1;
>   out:
> -     sk_ASN1_TYPE_pop_free(seq, ASN1_TYPE_free);
> +     RpkiSignedChecklist_free(rsc);
>       return rc;
>  }
>  
> @@ -657,10 +384,10 @@ struct rsc *
>  rsc_parse(X509 **x509, const char *fn, const unsigned char *der, size_t len)
>  {
>       struct parse             p;
> -     size_t                   cmsz;
>       unsigned char           *cms;
> -     int                      rc = 0;
> +     size_t                   cmsz;
>       const ASN1_TIME         *at;
> +     int                      rc = 0;
>  
>       memset(&p, 0, sizeof(struct parse));
>       p.fn = fn;
> 

-- 
:wq Claudio

Reply via email to