From 1bb1e5098b739c68ade140881767ec199ce28a0b Mon Sep 17 00:00:00 2001 From: job Date: Thu, 9 Mar 2023 09:46:21 +0000 Subject: [PATCH] Show CMS signing-time signed attribute in filemode OK tb@ --- usr.sbin/rpki-client/aspa.c | 8 ++++-- usr.sbin/rpki-client/cms.c | 46 +++++++++++++++++++++++++++++----- usr.sbin/rpki-client/extern.h | 13 +++++++--- usr.sbin/rpki-client/gbr.c | 7 ++++-- usr.sbin/rpki-client/geofeed.c | 4 +-- usr.sbin/rpki-client/mft.c | 7 ++++-- usr.sbin/rpki-client/print.c | 44 +++++++++++++++++++++++++++++++- usr.sbin/rpki-client/roa.c | 7 ++++-- usr.sbin/rpki-client/rsc.c | 5 ++-- usr.sbin/rpki-client/tak.c | 5 ++-- 10 files changed, 122 insertions(+), 24 deletions(-) diff --git a/usr.sbin/rpki-client/aspa.c b/usr.sbin/rpki-client/aspa.c index 363288ad631..dc197d9e844 100644 --- a/usr.sbin/rpki-client/aspa.c +++ b/usr.sbin/rpki-client/aspa.c @@ -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 * Copyright (c) 2022 Theo Buehler @@ -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)) diff --git a/usr.sbin/rpki-client/cms.c b/usr.sbin/rpki-client/cms.c index 752c7d19337..cfc4b06af3c 100644 --- a/usr.sbin/rpki-client/cms.c +++ b/usr.sbin/rpki-client/cms.c @@ -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 * @@ -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); } diff --git a/usr.sbin/rpki-client/extern.h b/usr.sbin/rpki-client/extern.h index f331e5b2028..71158462650 100644 --- a/usr.sbin/rpki-client/extern.h +++ b/usr.sbin/rpki-client/extern.h @@ -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 * @@ -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. */ diff --git a/usr.sbin/rpki-client/gbr.c b/usr.sbin/rpki-client/gbr.c index a6eaedab69c..a2cd97ea4a7 100644 --- a/usr.sbin/rpki-client/gbr.c +++ b/usr.sbin/rpki-client/gbr.c @@ -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 * @@ -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); diff --git a/usr.sbin/rpki-client/geofeed.c b/usr.sbin/rpki-client/geofeed.c index d346f0652dd..452b3f72f30 100644 --- a/usr.sbin/rpki-client/geofeed.c +++ b/usr.sbin/rpki-client/geofeed.c @@ -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 * Copyright (c) 2019 Kristaps Dzonsons @@ -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)) diff --git a/usr.sbin/rpki-client/mft.c b/usr.sbin/rpki-client/mft.c index 486603645e5..1238e0b6a9c 100644 --- a/usr.sbin/rpki-client/mft.c +++ b/usr.sbin/rpki-client/mft.c @@ -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 * Copyright (c) 2019 Kristaps Dzonsons @@ -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; diff --git a/usr.sbin/rpki-client/print.c b/usr.sbin/rpki-client/print.c index 05bf8f0523f..6db8e10a336 100644 --- a/usr.sbin/rpki-client/print.c +++ b/usr.sbin/rpki-client/print.c @@ -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 * Copyright (c) 2019 Kristaps Dzonsons @@ -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"); } diff --git a/usr.sbin/rpki-client/roa.c b/usr.sbin/rpki-client/roa.c index a18daf187d7..751c33dd2b2 100644 --- a/usr.sbin/rpki-client/roa.c +++ b/usr.sbin/rpki-client/roa.c @@ -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 * Copyright (c) 2019 Kristaps Dzonsons @@ -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; diff --git a/usr.sbin/rpki-client/rsc.c b/usr.sbin/rpki-client/rsc.c index ff3bf5fb771..12c091f7f18 100644 --- a/usr.sbin/rpki-client/rsc.c +++ b/usr.sbin/rpki-client/rsc.c @@ -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 * Copyright (c) 2022 Job Snijders @@ -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; diff --git a/usr.sbin/rpki-client/tak.c b/usr.sbin/rpki-client/tak.c index cd1f643fc2b..24313d958fd 100644 --- a/usr.sbin/rpki-client/tak.c +++ b/usr.sbin/rpki-client/tak.c @@ -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 * Copyright (c) 2022 Theo Buehler @@ -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; -- 2.20.1