On Sun, Feb 14, 2021 at 05:41:55PM +0000, Job Snijders wrote:
> Make the AIA more easily available for debugging purposes & future
> changesets
> 
> In the context of the RPKI, the AIA extension identifies the publication
> point of the certificate of the issuer of the certificate in which the
> extension appears. A single reference to the publication point of the
> immediate superior certificate MUST be present, except for a
> "self-signed" certificate.
> 
> OK?

I'm not against this going in but I think there is some improvements that
should be made. Some of it inline.

The extra data stored increases the memory usage by 16MB or 3.5% which is ok.
Also the data is already kind of known via the AKI / SKI stack but for
individual files it is much easier to to walk backup up the tree via AIA.

> Index: regress/usr.sbin/rpki-client/test-cert.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-cert.c,v
> retrieving revision 1.8
> diff -u -p -r1.8 test-cert.c
> --- regress/usr.sbin/rpki-client/test-cert.c  8 Feb 2021 09:28:58 -0000       
> 1.8
> +++ regress/usr.sbin/rpki-client/test-cert.c  14 Feb 2021 17:29:17 -0000
> @@ -52,6 +52,8 @@ cert_print(const struct cert *p)
>       printf("Subject key identifier: %s\n", p->ski);
>       if (p->aki != NULL)
>               printf("Authority key identifier: %s\n", p->aki);
> +     if (p->aia != NULL)
> +             printf("Authority info access: %s\n", p->aia);
>  
>       for (i = 0; i < p->asz; i++)
>               switch (p->as[i].type) {
> Index: regress/usr.sbin/rpki-client/test-gbr.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-gbr.c,v
> retrieving revision 1.1
> diff -u -p -r1.1 test-gbr.c
> --- regress/usr.sbin/rpki-client/test-gbr.c   9 Dec 2020 11:30:44 -0000       
> 1.1
> +++ regress/usr.sbin/rpki-client/test-gbr.c   14 Feb 2021 17:29:17 -0000
> @@ -42,6 +42,7 @@ gbr_print(const struct gbr *p)
>  
>       printf("Subject key identifier: %s\n", p->ski);
>       printf("Authority key identifier: %s\n", p->aki);
> +     printf("Authority info access: %s\n", p->aia);
>       printf("vcard:\n%s", p->vcard);
>  }
>  
> Index: regress/usr.sbin/rpki-client/test-mft.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-mft.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 test-mft.c
> --- regress/usr.sbin/rpki-client/test-mft.c   9 Nov 2020 16:13:02 -0000       
> 1.10
> +++ regress/usr.sbin/rpki-client/test-mft.c   14 Feb 2021 17:29:17 -0000
> @@ -54,6 +54,7 @@ mft_print(const struct mft *p)
>  
>       printf("Subject key identifier: %s\n", p->ski);
>       printf("Authority key identifier: %s\n", p->aki);
> +     printf("Authority info access: %s\n", p->aia);
>       for (i = 0; i < p->filesz; i++) {
>               b64_ntop(p->files[i].hash, sizeof(p->files[i].hash),
>                   hash, sizeof(hash));
> Index: regress/usr.sbin/rpki-client/test-roa.c
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-roa.c,v
> retrieving revision 1.8
> diff -u -p -r1.8 test-roa.c
> --- regress/usr.sbin/rpki-client/test-roa.c   29 Jan 2021 10:15:42 -0000      
> 1.8
> +++ regress/usr.sbin/rpki-client/test-roa.c   14 Feb 2021 17:29:17 -0000
> @@ -42,6 +42,7 @@ roa_print(const struct roa *p)
>  
>       printf("Subject key identifier: %s\n", p->ski);
>       printf("Authority key identifier: %s\n", p->aki);
> +     printf("Authority info access: %s\n", p->aia);
>       printf("asID: %" PRIu32 "\n", p->asid);
>       for (i = 0; i < p->ipsz; i++) {
>               ip_addr_print(&p->ips[i].addr,
> Index: regress/usr.sbin/rpki-client/Makefile.inc
> ===================================================================
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/Makefile.inc,v
> retrieving revision 1.6
> diff -u -p -r1.6 Makefile.inc
> --- regress/usr.sbin/rpki-client/Makefile.inc 3 Feb 2021 10:45:12 -0000       
> 1.6
> +++ regress/usr.sbin/rpki-client/Makefile.inc 14 Feb 2021 17:29:17 -0000
> @@ -4,9 +4,9 @@
>  
>  PROGS += test-ip
>  PROGS += test-cert
> +PROGS += test-gbr
>  PROGS += test-mft
>  PROGS += test-roa
> -PROGS += test-gbr
>  PROGS += test-tal
>  
>  .for p in ${PROGS}

Regress tests are OK.

> Index: usr.sbin/rpki-client/cert.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 cert.c
> --- usr.sbin/rpki-client/cert.c       8 Feb 2021 09:22:53 -0000       1.25
> +++ usr.sbin/rpki-client/cert.c       14 Feb 2021 17:29:18 -0000
> @@ -1079,6 +1079,11 @@ cert_parse_inner(X509 **xp, const char *
>               case NID_crl_distribution_points:
>                       /* ignored here, handled later */
>                       break;
> +             case NID_info_access:
> +                     free(p.res->aia);
> +                     p.res->aia = x509_get_aia(x, p.fn);
> +                     c = (p.res->aia != NULL);
> +                     break;
>               case NID_authority_key_identifier:
>                       free(p.res->aki);
>                       p.res->aki = x509_get_aki_ext(ext, p.fn);

See x509.c comments

> Index: usr.sbin/rpki-client/gbr.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/gbr.c,v
> retrieving revision 1.4
> diff -u -p -r1.4 gbr.c
> --- usr.sbin/rpki-client/gbr.c        4 Feb 2021 08:58:19 -0000       1.4
> +++ usr.sbin/rpki-client/gbr.c        14 Feb 2021 17:29:18 -0000
> @@ -62,7 +62,7 @@ gbr_parse(X509 **x509, const char *fn)
>               err(1, NULL);
>       if ((p.res->vcard = strndup(cms, cmsz)) == NULL)
>               err(1, NULL);
> -     if (!x509_get_ski_aki(*x509, fn, &p.res->ski, &p.res->aki)) {
> +     if (!x509_get_exts(*x509, fn, &p.res->ski, &p.res->aki, &p.res->aia)) {
>               gbr_free(p.res);
>               X509_free(*x509);
>               *x509 = NULL;
> Index: usr.sbin/rpki-client/mft.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 mft.c
> --- usr.sbin/rpki-client/mft.c        4 Feb 2021 08:58:19 -0000       1.25
> +++ usr.sbin/rpki-client/mft.c        14 Feb 2021 17:29:18 -0000
> @@ -395,7 +395,7 @@ mft_parse(X509 **x509, const char *fn)
>               err(1, NULL);
>       if ((p.res->file = strdup(fn)) == NULL)
>               err(1, NULL);
> -     if (!x509_get_ski_aki(*x509, fn, &p.res->ski, &p.res->aki))
> +     if (!x509_get_exts(*x509, fn, &p.res->ski, &p.res->aki, &p.res->aia))
>               goto out;
>  
>       /*
> Index: usr.sbin/rpki-client/roa.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
> retrieving revision 1.13
> diff -u -p -r1.13 roa.c
> --- usr.sbin/rpki-client/roa.c        4 Feb 2021 08:58:19 -0000       1.13
> +++ usr.sbin/rpki-client/roa.c        14 Feb 2021 17:29:18 -0000
> @@ -349,7 +349,7 @@ roa_parse(X509 **x509, const char *fn)
>  
>       if ((p.res = calloc(1, sizeof(struct roa))) == NULL)
>               err(1, NULL);
> -     if (!x509_get_ski_aki(*x509, fn, &p.res->ski, &p.res->aki))
> +     if (!x509_get_exts(*x509, fn, &p.res->ski, &p.res->aki, &p.res->aia))
>               goto out;
>       if (!roa_parse_econtent(cms, cmsz, &p))
>               goto out;
> Index: usr.sbin/rpki-client/x509.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/x509.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 x509.c
> --- usr.sbin/rpki-client/x509.c       12 Sep 2020 15:46:48 -0000      1.14
> +++ usr.sbin/rpki-client/x509.c       14 Feb 2021 17:29:18 -0000
> @@ -169,12 +169,57 @@ out:
>  }
>  
>  /*
> - * Wraps around x509_get_ski_ext and x509_get_aki_ext.
> + * Parse the Authority Information Access (AIA) extension
> + * See RFC 6487, section 4.8.7 for details.
> + * Returns NULL on failure, on success returns the AIA URI
> + * (which has to be freed after use).
> + */
> +char *
> +x509_get_aia(X509 *x, const char *fn)
> +{
> +     AUTHORITY_INFO_ACCESS           *info;
> +     char                            *aia = NULL;
> +
> +     info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
> +     if (!info) {
> +             warnx("%s: RFC 6487 section 4.8.7: AIA: extension missing", fn);
> +             return NULL;
> +     }
> +     if (sk_ACCESS_DESCRIPTION_num(info) != 1) {
> +             warnx("%s: RFC 6487 section 4.8.7: AIA: "
> +                 "want 1 element, have %d", fn,
> +                 sk_ACCESS_DESCRIPTION_num(info));
> +             return NULL;
> +     }
> +
> +     ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, 0);

Please do not define variables in the middle of functions. Add
        ACCESS_DESCRIPTION *ad;
at the top.

> +     if (OBJ_obj2nid(ad->method) != NID_ad_ca_issuers) {
> +             warnx("%s: RFC 6487 section 4.8.7: AIA: "
> +                 "expected caIssuers, have %d", fn, OBJ_obj2nid(ad->method));
> +             return NULL;
> +     }
> +     if (ad->location->type != GEN_URI) {
> +             warnx("%s: RFC 6487 section 4.8.7: AIA: "
> +                 "want GEN_URI type, have %d", fn, ad->location->type);
> +             return NULL;
> +     }
> +
> +     aia = strndup(
> +         ASN1_STRING_get0_data(ad->location->d.uniformResourceIdentifier),
> +         ASN1_STRING_length(ad->location->d.uniformResourceIdentifier));
> +
> +     AUTHORITY_INFO_ACCESS_free(info);
> +
> +     return aia;
> +}

I really don't like the way x509_get_aia() is different to
x509_get_ski_ext and x509_get_aki_ext. The way the x509 extensions are
handled in rpki-client is strange. In x509_get_exts() the code walks over
all extensions and looks for the NID we're interested in.
x509_get_aia() makes this approach even more strange by actually not using
the ext but instead do a lookup from the x509 object directly. So why call
it in the for loop at all. Just do it directly.

Also the way the code is written in x509_get_exts() implies that x509
allows the same extension to be added more then once. Is that really true?
Wouldn't that be an error regarding RFC6487.

Anyway I would prefer if x509_get_ski_ext(), x509_get_aki_ext() and
x509_get_aia() all work the same way.

> +
> +/*
> + * Wraps around x509_get_ski_ext, x509_get_aki_ext, and x509_get_aia.
>   * Returns zero on failure (out pointers are NULL) or non-zero on
>   * success (out pointers must be freed).
>   */
>  int
> -x509_get_ski_aki(X509 *x, const char *fn, char **ski, char **aki)
> +x509_get_exts(X509 *x, const char *fn, char **ski, char **aki, char **aia)
>  {
>       X509_EXTENSION          *ext = NULL;
>       const ASN1_OBJECT       *obj;

You forgot to add *aia to at the start where *ski = *aki = NULL;

> @@ -199,21 +244,38 @@ x509_get_ski_aki(X509 *x, const char *fn
>                       free(*aki);
>                       *aki = x509_get_aki_ext(ext, fn);
>                       break;
> +             case NID_info_access:
> +                     free(*aia);

Since you did not initially NULL aia this free call may be bad.

> +                     *aia = x509_get_aia(x, fn);
> +                     break;
>               }
>       }

As mentioned above this function feels not quite right to me.

>  
> +     if (*aia == NULL) {
> +             cryptowarnx("%s: RFC 6487 section 4.8.7: AIA: "
> +                 "missing AIA X509 extension", fn);
> +             free(*ski);
> +             free(*aki);
> +             *ski = NULL;
> +             *aki = NULL;
> +             return 0;
> +     }
>       if (*aki == NULL) {
>               cryptowarnx("%s: RFC 6487 section 4.8.3: AKI: "
>                   "missing AKI X509 extension", fn);
>               free(*ski);
> +             free(*aia);
>               *ski = NULL;
> +             *aia = NULL;
>               return 0;
>       }
>       if (*ski == NULL) {
> -             cryptowarnx("%s: RFC 6487 section 4.8.2: AKI: "
> +             cryptowarnx("%s: RFC 6487 section 4.8.2: SKI: "
>                   "missing SKI X509 extension", fn);
>               free(*aki);
> +             free(*aia);
>               *aki = NULL;
> +             *aia = NULL;
>               return 0;
>       }
>  
> Index: usr.sbin/rpki-client/extern.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.42
> diff -u -p -r1.42 extern.h
> --- usr.sbin/rpki-client/extern.h     8 Feb 2021 09:22:53 -0000       1.42
> +++ usr.sbin/rpki-client/extern.h     14 Feb 2021 17:29:18 -0000
> @@ -116,6 +116,7 @@ struct cert {
>       char            *mft; /* manifest (rsync:// uri) */
>       char            *notify; /* RRDP notify (https:// uri) */
>       char            *crl; /* CRL location (rsync:// or NULL) */
> +     char            *aia; /* AIA (or NULL, for trust anchor) */
>       char            *aki; /* AKI (or NULL, for trust anchor) */
>       char            *ski; /* SKI */
>       int              valid; /* validated resources */
> @@ -157,6 +158,7 @@ struct mft {
>       int              stale; /* if a stale manifest */
>       char            *ski; /* SKI */
>       char            *aki; /* AKI */
> +     char            *aia; /* AIA */
>  };
>  
>  /*
> @@ -183,6 +185,7 @@ struct roa {
>       int              valid; /* validated resources */
>       char            *ski; /* SKI */
>       char            *aki; /* AKI */
> +     char            *aia; /* AIA */
>       char            *tal; /* basename of TAL for this cert */
>  };
>  
> @@ -193,6 +196,7 @@ struct gbr {
>       char            *vcard;
>       char            *ski; /* SKI */
>       char            *aki; /* AKI */
> +     char            *aia; /* AIA */
>  };
>  
>  /*
> @@ -248,7 +252,7 @@ struct auth *auth_find(struct auth_tree 
>  
>  /*
>   * Resource types specified by the RPKI profiles.
> - * There are others (e.g., gbr) that we don't consider.
> + * There might be others we don't consider.
>   */
>  enum rtype {
>       RTYPE_EOF = 0,
> @@ -418,9 +422,10 @@ void              io_str_read(int, char **);
>  
>  /* X509 helpers. */
>  
> +char         *x509_get_aia(X509 *, const char *);
>  char         *x509_get_aki_ext(X509_EXTENSION *, const char *);
>  char         *x509_get_ski_ext(X509_EXTENSION *, const char *);
> -int           x509_get_ski_aki(X509 *, const char *, char **, char **);
> +int           x509_get_exts(X509 *, const char *, char **, char **, char **);
>  char         *x509_get_crl(X509 *, const char *);
>  char         *x509_crl_get_aki(X509_CRL *);
>  
> 

With the style and initialisation issue fixed I think this can go in but
as mentioned more x509 cleanup needs to follow.

-- 
:wq Claudio

Reply via email to