Show CMS signing-time signed attribute in filemode
authorjob <job@openbsd.org>
Thu, 9 Mar 2023 09:46:21 +0000 (09:46 +0000)
committerjob <job@openbsd.org>
Thu, 9 Mar 2023 09:46:21 +0000 (09:46 +0000)
OK tb@

usr.sbin/rpki-client/aspa.c
usr.sbin/rpki-client/cms.c
usr.sbin/rpki-client/extern.h
usr.sbin/rpki-client/gbr.c
usr.sbin/rpki-client/geofeed.c
usr.sbin/rpki-client/mft.c
usr.sbin/rpki-client/print.c
usr.sbin/rpki-client/roa.c
usr.sbin/rpki-client/rsc.c
usr.sbin/rpki-client/tak.c

index 363288a..dc197d9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: aspa.c,v 1.11 2023/01/13 08:58:36 claudio Exp $ */
+/*     $OpenBSD: aspa.c,v 1.12 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2022 Job Snijders <job@fastly.com>
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
@@ -190,18 +190,22 @@ aspa_parse(X509 **x509, const char *fn, const unsigned char *der, size_t len)
        unsigned char   *cms;
        const ASN1_TIME *at;
        struct cert     *cert = NULL;
+       time_t           signtime;
        int              rc = 0;
 
        memset(&p, 0, sizeof(struct parse));
        p.fn = fn;
 
-       cms = cms_parse_validate(x509, fn, der, len, aspa_oid, &cmsz);
+       cms = cms_parse_validate(x509, fn, der, len, aspa_oid, &cmsz,
+           &signtime);
        if (cms == NULL)
                return NULL;
 
        if ((p.res = calloc(1, sizeof(*p.res))) == NULL)
                err(1, NULL);
 
+       p.res->signtime = signtime;
+
        if (!x509_get_aia(*x509, fn, &p.res->aia))
                goto out;
        if (!x509_get_aki(*x509, fn, &p.res->aki))
index 752c7d1..cfc4b06 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cms.c,v 1.29 2023/03/06 16:04:52 job Exp $ */
+/*     $OpenBSD: cms.c,v 1.30 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -62,10 +62,37 @@ cms_extract_econtent(const char *fn, CMS_ContentInfo *cms, unsigned char **res,
        return 1;
 }
 
+static int
+cms_get_signtime(const char *fn, X509_ATTRIBUTE *attr, time_t *signtime)
+{
+       const ASN1_TIME         *at;
+       const char              *time_str = "UTCtime";
+       int                      time_type = V_ASN1_UTCTIME;
+
+       at = X509_ATTRIBUTE_get0_data(attr, 0, time_type, NULL);
+       if (at == NULL) {
+               time_str = "GeneralizedTime";
+               time_type = V_ASN1_GENERALIZEDTIME;
+               at = X509_ATTRIBUTE_get0_data(attr, 0, time_type, NULL);
+               if (at == NULL) {
+                       warnx("%s: CMS signing-time issue", fn);
+                       return 0;
+               }
+               warnx("%s: GeneralizedTime instead of UTCtime", fn);
+       }
+
+       if (!x509_get_time(at, signtime)) {
+               warnx("%s: failed to convert %s", fn, time_str);
+               return 0;
+       }
+
+       return 1;
+}      
+
 static int
 cms_parse_validate_internal(X509 **xp, const char *fn, const unsigned char *der,
     size_t len, const ASN1_OBJECT *oid, BIO *bio, unsigned char **res,
-    size_t *rsz)
+    size_t *rsz, time_t *signtime)
 {
        const unsigned char             *oder;
        char                             buf[128], obuf[128];
@@ -160,6 +187,8 @@ cms_parse_validate_internal(X509 **xp, const char *fn, const unsigned char *der,
                                    "signed attribute", fn);
                                goto out;
                        }
+                       if (!cms_get_signtime(fn, attr, signtime))
+                               goto out;
                } else if (OBJ_cmp(obj, bin_sign_time_oid) == 0) {
                        if (has_bst++ != 0) {
                                cryptowarnx("%s: RFC 6488: duplicate "
@@ -174,11 +203,16 @@ cms_parse_validate_internal(X509 **xp, const char *fn, const unsigned char *der,
                        goto out;
                }
        }
+
        if (!has_ct || !has_md) {
                cryptowarnx("%s: RFC 6488: CMS missing required "
                    "signed attribute", fn);
                goto out;
        }
+
+       if (has_bst)
+               warnx("%s: unsupported CMS signing-time attribute", fn);
+
        if (CMS_unsigned_get_attr_count(si) != -1) {
                cryptowarnx("%s: RFC 6488: CMS has unsignedAttrs", fn);
                goto out;
@@ -299,12 +333,12 @@ cms_parse_validate_internal(X509 **xp, const char *fn, const unsigned char *der,
  */
 unsigned char *
 cms_parse_validate(X509 **xp, const char *fn, const unsigned char *der,
-    size_t derlen, const ASN1_OBJECT *oid, size_t *rsz)
+    size_t derlen, const ASN1_OBJECT *oid, size_t *rsz, time_t *st)
 {
        unsigned char *res = NULL;
 
        if (!cms_parse_validate_internal(xp, fn, der, derlen, oid, NULL, &res,
-           rsz))
+           rsz, st))
                return NULL;
 
        return res;
@@ -317,8 +351,8 @@ cms_parse_validate(X509 **xp, const char *fn, const unsigned char *der,
  */
 int
 cms_parse_validate_detached(X509 **xp, const char *fn, const unsigned char *der,
-    size_t derlen, const ASN1_OBJECT *oid, BIO *bio)
+    size_t derlen, const ASN1_OBJECT *oid, BIO *bio, time_t *st)
 {
        return cms_parse_validate_internal(xp, fn, der, derlen, oid, bio, NULL,
-           NULL);
+           NULL, st);
 }
index f331e5b..7115846 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extern.h,v 1.168 2023/03/06 16:04:52 job Exp $ */
+/*     $OpenBSD: extern.h,v 1.169 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -209,6 +209,7 @@ struct mft {
        char            *ski; /* SKI */
        char            *crl; /* CRL file name */
        unsigned char    crlhash[SHA256_DIGEST_LENGTH];
+       time_t           signtime; /* CMS signing-time attribute */
        time_t           valid_since;
        time_t           valid_until;
        size_t           filesz; /* number of filenames */
@@ -243,6 +244,7 @@ struct roa {
        char            *aki; /* AKI */
        char            *sia; /* SIA signedObject */
        char            *ski; /* SKI */
+       time_t           signtime; /* CMS signing-time attribute */
        time_t           expires; /* do not use after */
 };
 
@@ -266,6 +268,7 @@ struct rsc {
        char            *aia; /* AIA */
        char            *aki; /* AKI */
        char            *ski; /* SKI */
+       time_t           signtime; /* CMS signing-time attribute */
        time_t           expires; /* Not After of the RSC EE */
 };
 
@@ -294,6 +297,7 @@ struct tak {
        char            *aki; /* AKI */
        char            *sia; /* SIA signed Object */
        char            *ski; /* SKI */
+       time_t           signtime; /* CMS signing-time attribute */
        time_t           expires; /* Not After of the TAK EE */
 };
 
@@ -314,6 +318,7 @@ struct geofeed {
        char            *aia; /* AIA */
        char            *aki; /* AKI */
        char            *ski; /* SKI */
+       time_t           signtime; /* CMS signing-time attribute */
        time_t           expires; /* Not After of the Geofeed EE */
        int              valid; /* all resources covered */
 };
@@ -327,6 +332,7 @@ struct gbr {
        char            *aki; /* AKI */
        char            *sia; /* SIA signedObject */
        char            *ski; /* SKI */
+       time_t           signtime; /* CMS signing-time attribute */
 };
 
 struct aspa_provider {
@@ -347,6 +353,7 @@ struct aspa {
        uint32_t                 custasid; /* the customerASID */
        struct aspa_provider    *providers; /* the providers */
        size_t                   providersz; /* number of providers */
+       time_t                   signtime; /* CMS signing-time attribute */
        time_t                   expires; /* NotAfter of the ASPA EE cert */
 };
 
@@ -665,10 +672,10 @@ int                valid_ca_pkey(const char *, EVP_PKEY *);
 /* Working with CMS. */
 unsigned char  *cms_parse_validate(X509 **, const char *,
                    const unsigned char *, size_t,
-                   const ASN1_OBJECT *, size_t *);
+                   const ASN1_OBJECT *, size_t *, time_t *);
 int             cms_parse_validate_detached(X509 **, const char *,
                    const unsigned char *, size_t,
-                   const ASN1_OBJECT *, BIO *);
+                   const ASN1_OBJECT *, BIO *, time_t *);
 
 /* Work with RFC 3779 IP addresses, prefixes, ranges. */
 
index a6eaeda..a2cd97e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: gbr.c,v 1.20 2022/11/30 09:12:50 job Exp $ */
+/*     $OpenBSD: gbr.c,v 1.21 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org>
  *
@@ -45,16 +45,19 @@ gbr_parse(X509 **x509, const char *fn, const unsigned char *der, size_t len)
        struct parse     p;
        size_t           cmsz;
        unsigned char   *cms;
+       time_t           signtime;
 
        memset(&p, 0, sizeof(struct parse));
        p.fn = fn;
 
-       cms = cms_parse_validate(x509, fn, der, len, gbr_oid, &cmsz);
+       cms = cms_parse_validate(x509, fn, der, len, gbr_oid, &cmsz,
+           &signtime);
        if (cms == NULL)
                return NULL;
 
        if ((p.res = calloc(1, sizeof(*p.res))) == NULL)
                err(1, NULL);
+       p.res->signtime = signtime;
        if ((p.res->vcard = strndup(cms, cmsz)) == NULL)
                err(1, NULL);
        free(cms);
index d346f06..452b3f7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: geofeed.c,v 1.10 2022/12/28 13:21:11 tb Exp $ */
+/*     $OpenBSD: geofeed.c,v 1.11 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2022 Job Snijders <job@fastly.com>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -233,7 +233,7 @@ geofeed_parse(X509 **x509, const char *fn, char *buf, size_t len)
        }
 
        if (!cms_parse_validate_detached(x509, fn, der, dersz, geofeed_oid,
-           bio))
+           bio, &p.res->signtime))
                goto out;
 
        if (!x509_get_aia(*x509, fn, &p.res->aia))
index 4866036..1238e0b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mft.c,v 1.82 2022/12/01 10:24:28 claudio Exp $ */
+/*     $OpenBSD: mft.c,v 1.83 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -353,17 +353,20 @@ mft_parse(X509 **x509, const char *fn, const unsigned char *der, size_t len)
        size_t           cmsz;
        unsigned char   *cms;
        char            *crldp = NULL, *crlfile;
+       time_t           signtime;
 
        memset(&p, 0, sizeof(struct parse));
        p.fn = fn;
 
-       cms = cms_parse_validate(x509, fn, der, len, mft_oid, &cmsz);
+       cms = cms_parse_validate(x509, fn, der, len, mft_oid, &cmsz,
+           &signtime);
        if (cms == NULL)
                return NULL;
        assert(*x509 != NULL);
 
        if ((p.res = calloc(1, sizeof(struct mft))) == NULL)
                err(1, NULL);
+       p.res->signtime = signtime;
 
        if (!x509_get_aia(*x509, fn, &p.res->aia))
                goto out;
index 05bf8f0..6db8e10 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: print.c,v 1.27 2023/03/07 14:49:32 job Exp $ */
+/*     $OpenBSD: print.c,v 1.28 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -379,6 +379,9 @@ mft_print(const X509 *x, const struct mft *p)
                printf("\t\"aia\": \"%s\",\n", p->aia);
                printf("\t\"sia\": \"%s\",\n", p->sia);
                printf("\t\"manifest_number\": \"%s\",\n", p->seqnum);
+               if (p->signtime != 0)
+                       printf("\t\"signing_time\": %lld,\n",
+                           (long long)p->signtime);
                printf("\t\"valid_since\": %lld,\n", (long long)p->valid_since);
                printf("\t\"valid_until\": %lld,\n", (long long)p->valid_until);
        } else {
@@ -388,6 +391,9 @@ mft_print(const X509 *x, const struct mft *p)
                printf("Authority info access:    %s\n", p->aia);
                printf("Subject info access:      %s\n", p->sia);
                printf("Manifest Number:          %s\n", p->seqnum);
+               if (p->signtime != 0)
+                       printf("Signing time:             %s\n",
+                           time2str(p->signtime));
                printf("Manifest valid since:     %s\n", time2str(p->valid_since));
                printf("Manifest valid until:     %s\n", time2str(p->valid_until));
                printf("Files and hashes:         ");
@@ -434,6 +440,9 @@ roa_print(const X509 *x, const struct roa *p)
                printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
                printf("\t\"aia\": \"%s\",\n", p->aia);
                printf("\t\"sia\": \"%s\",\n", p->sia);
+               if (p->signtime != 0)
+                       printf("\t\"signing_time\": %lld,\n",
+                           (long long)p->signtime);
                printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
        } else {
                printf("Subject key identifier:   %s\n", pretty_key_id(p->ski));
@@ -441,6 +450,9 @@ roa_print(const X509 *x, const struct roa *p)
                printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
                printf("Authority info access:    %s\n", p->aia);
                printf("Subject info access:      %s\n", p->sia);
+               if (p->signtime != 0)
+                       printf("Signing time:             %s\n",
+                           time2str(p->signtime));
                printf("ROA valid until:          %s\n", time2str(p->expires));
                printf("asID:                     %u\n", p->asid);
                printf("IP address blocks:        ");
@@ -483,6 +495,9 @@ gbr_print(const X509 *x, const struct gbr *p)
                printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
                printf("\t\"aia\": \"%s\",\n", p->aia);
                printf("\t\"sia\": \"%s\",\n", p->sia);
+               if (p->signtime != 0)
+                       printf("\t\"signing_time\": %lld,\n",
+                           (long long)p->signtime);
                printf("\t\"vcard\": \"");
                for (i = 0; i < strlen(p->vcard); i++) {
                        if (p->vcard[i] == '"')
@@ -501,6 +516,9 @@ gbr_print(const X509 *x, const struct gbr *p)
                printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
                printf("Authority info access:    %s\n", p->aia);
                printf("Subject info access:      %s\n", p->sia);
+               if (p->signtime != 0)
+                       printf("Signing time:             %s\n",
+                           time2str(p->signtime));
                printf("vcard:\n%s", p->vcard);
        }
 }
@@ -518,6 +536,9 @@ rsc_print(const X509 *x, const struct rsc *p)
                printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
                x509_print(x);
                printf("\t\"aia\": \"%s\",\n", p->aia);
+               if (p->signtime != 0)
+                       printf("\t\"signing_time\": %lld,\n",
+                           (long long)p->signtime);
                printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
                printf("\t\"signed_with_resources\": [\n");
        } else {
@@ -525,6 +546,9 @@ rsc_print(const X509 *x, const struct rsc *p)
                printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
                x509_print(x);
                printf("Authority info access:    %s\n", p->aia);
+               if (p->signtime != 0)
+                       printf("Signing time:             %s\n",
+                           time2str(p->signtime));
                printf("RSC valid until:          %s\n", time2str(p->expires));
                printf("Signed with resources:    ");
        }
@@ -644,6 +668,9 @@ aspa_print(const X509 *x, const struct aspa *p)
                printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
                printf("\t\"aia\": \"%s\",\n", p->aia);
                printf("\t\"sia\": \"%s\",\n", p->sia);
+               if (p->signtime != 0)
+                       printf("\t\"signing_time\": %lld,\n",
+                           (long long)p->signtime);
                printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
                printf("\t\"customer_asid\": %u,\n", p->custasid);
                printf("\t\"provider_set\": [\n");
@@ -665,6 +692,9 @@ aspa_print(const X509 *x, const struct aspa *p)
                printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
                printf("Authority info access:    %s\n", p->aia);
                printf("Subject info access:      %s\n", p->sia);
+               if (p->signtime != 0)
+                       printf("Signing time:             %s\n",
+                           time2str(p->signtime));
                printf("ASPA valid until:         %s\n", time2str(p->expires));
                printf("Customer AS:              %u\n", p->custasid);
                printf("Provider Set:             ");
@@ -749,6 +779,9 @@ tak_print(const X509 *x, const struct tak *p)
                printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
                printf("\t\"aia\": \"%s\",\n", p->aia);
                printf("\t\"sia\": \"%s\",\n", p->sia);
+               if (p->signtime != 0)
+                       printf("\t\"signing_time\": %lld,\n",
+                           (long long)p->signtime);
                printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
                printf("\t\"takeys\": [\n");
        } else {
@@ -757,6 +790,9 @@ tak_print(const X509 *x, const struct tak *p)
                printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
                printf("Authority info access:    %s\n", p->aia);
                printf("Subject info access:      %s\n", p->sia);
+               if (p->signtime != 0)
+                       printf("Signing time:             %s\n",
+                           time2str(p->signtime));
                printf("TAK valid until:          %s\n", time2str(p->expires));
        }
 
@@ -790,6 +826,9 @@ geofeed_print(const X509 *x, const struct geofeed *p)
                x509_print(x);
                printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
                printf("\t\"aia\": \"%s\",\n", p->aia);
+               if (p->signtime != 0)
+                       printf("\t\"signing_time\": %lld,\n",
+                           (long long)p->signtime);
                printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
                printf("\t\"records\": [\n");
        } else {
@@ -797,6 +836,9 @@ geofeed_print(const X509 *x, const struct geofeed *p)
                x509_print(x);
                printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
                printf("Authority info access:    %s\n", p->aia);
+               if (p->signtime != 0)
+                       printf("Signing time:             %s\n",
+                           time2str(p->signtime));
                printf("Geofeed valid until:      %s\n", time2str(p->expires));
                printf("Geofeed CSV records:\n");
        }
index a18daf1..751c33d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: roa.c,v 1.59 2022/12/15 12:02:29 claudio Exp $ */
+/*     $OpenBSD: roa.c,v 1.60 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -213,17 +213,20 @@ roa_parse(X509 **x509, const char *fn, const unsigned char *der, size_t len)
        unsigned char   *cms;
        const ASN1_TIME *at;
        struct cert     *cert = NULL;
+       time_t           signtime;
        int              rc = 0;
 
        memset(&p, 0, sizeof(struct parse));
        p.fn = fn;
 
-       cms = cms_parse_validate(x509, fn, der, len, roa_oid, &cmsz);
+       cms = cms_parse_validate(x509, fn, der, len, roa_oid, &cmsz,
+           &signtime);
        if (cms == NULL)
                return NULL;
 
        if ((p.res = calloc(1, sizeof(struct roa))) == NULL)
                err(1, NULL);
+       p.res->signtime = signtime;
 
        if (!x509_get_aia(*x509, fn, &p.res->aia))
                goto out;
index ff3bf5f..12c091f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rsc.c,v 1.19 2022/11/26 17:14:40 job Exp $ */
+/*     $OpenBSD: rsc.c,v 1.20 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
  * Copyright (c) 2022 Job Snijders <job@fastly.com>
@@ -384,7 +384,8 @@ rsc_parse(X509 **x509, const char *fn, const unsigned char *der, size_t len)
        memset(&p, 0, sizeof(struct parse));
        p.fn = fn;
 
-       cms = cms_parse_validate(x509, fn, der, len, rsc_oid, &cmsz);
+       cms = cms_parse_validate(x509, fn, der, len, rsc_oid, &cmsz,
+           &p.res->signtime);
        if (cms == NULL)
                return NULL;
 
index cd1f643..24313d9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tak.c,v 1.2 2022/11/04 09:43:13 job Exp $ */
+/*     $OpenBSD: tak.c,v 1.3 2023/03/09 09:46:21 job Exp $ */
 /*
  * Copyright (c) 2022 Job Snijders <job@fastly.com>
  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
@@ -236,7 +236,8 @@ tak_parse(X509 **x509, const char *fn, const unsigned char *der, size_t len)
        memset(&p, 0, sizeof(struct parse));
        p.fn = fn;
 
-       cms = cms_parse_validate(x509, fn, der, len, tak_oid, &cmsz);
+       cms = cms_parse_validate(x509, fn, der, len, tak_oid, &cmsz,
+           &p.res->signtime);
        if (cms == NULL)
                return NULL;