Hi all,
RFC 6487 section 4.8.8.2 mandates that the SIA extension must be
present, and contain *at least* an instance of accessMethod
id-ad-signedObject. The below changeset enforces this requirement.
OK?
Index: aspa.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/aspa.c,v
retrieving revision 1.6
diff -u -p -r1.6 aspa.c
--- aspa.c 2 Nov 2022 10:04:41 -0000 1.6
+++ aspa.c 3 Nov 2022 15:12:26 -0000
@@ -207,11 +207,14 @@ aspa_parse(X509 **x509, const char *fn,
goto out;
if (!x509_get_aki(*x509, fn, &p.res->aki))
goto out;
+ if (!x509_get_sia(*x509, fn, &p.res->sia))
+ goto out;
if (!x509_get_ski(*x509, fn, &p.res->ski))
goto out;
- if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
+ if (p.res->aia == NULL || p.res->aki == NULL || p.res->sia == NULL
+ || p.res->ski == NULL) {
warnx("%s: RFC 6487 section 4.8: "
- "missing AIA, AKI or SKI X509 extension", fn);
+ "missing AIA, AKI, SIA, or SKI X509 extension", fn);
goto out;
}
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.157
diff -u -p -r1.157 extern.h
--- extern.h 2 Nov 2022 12:43:02 -0000 1.157
+++ extern.h 3 Nov 2022 15:12:27 -0000
@@ -213,6 +213,7 @@ struct mft {
char *seqnum; /* manifestNumber */
char *aia; /* AIA */
char *aki; /* AKI */
+ char *sia; /* SIA signedObject */
char *ski; /* SKI */
char *crl; /* CRL file name */
unsigned char crlhash[SHA256_DIGEST_LENGTH];
@@ -248,6 +249,7 @@ struct roa {
int valid; /* validated resources */
char *aia; /* AIA */
char *aki; /* AKI */
+ char *sia; /* SIA signedObject */
char *ski; /* SKI */
time_t expires; /* do not use after */
};
@@ -298,6 +300,7 @@ struct tak {
struct takey *successor;
char *aia; /* AIA */
char *aki; /* AKI */
+ char *sia; /* SIA signed Object */
char *ski; /* SKI */
time_t expires; /* Not After of the TAK EE */
};
@@ -309,6 +312,7 @@ struct gbr {
char *vcard;
char *aia; /* AIA */
char *aki; /* AKI */
+ char *sia; /* SIA signedObject */
char *ski; /* SKI */
};
@@ -325,6 +329,7 @@ struct aspa {
int talid; /* TAL the ASPA is chained up to */
char *aia; /* AIA */
char *aki; /* AKI */
+ char *sia; /* SIA signedObject */
char *ski; /* SKI */
uint32_t custasid; /* the customerASID */
struct aspa_provider *providers; /* the providers */
@@ -737,6 +742,7 @@ struct ibuf *io_buf_recvfd(int, struct i
void x509_init_oid(void);
int x509_get_aia(X509 *, const char *, char **);
int x509_get_aki(X509 *, const char *, char **);
+int x509_get_sia(X509 *, const char *, char **);
int x509_get_ski(X509 *, const char *, char **);
int x509_get_expire(X509 *, const char *, time_t *);
int x509_get_crl(X509 *, const char *, char **);
Index: gbr.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/gbr.c,v
retrieving revision 1.16
diff -u -p -r1.16 gbr.c
--- gbr.c 11 May 2022 21:19:06 -0000 1.16
+++ gbr.c 3 Nov 2022 15:12:27 -0000
@@ -67,11 +67,14 @@ gbr_parse(X509 **x509, const char *fn, c
goto out;
if (!x509_get_aki(*x509, fn, &p.res->aki))
goto out;
+ if (!x509_get_sia(*x509, fn, &p.res->sia))
+ goto out;
if (!x509_get_ski(*x509, fn, &p.res->ski))
goto out;
- if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
+ if (p.res->aia == NULL || p.res->aki == NULL || p.res->sia == NULL
+ || p.res->ski == NULL) {
warnx("%s: RFC 6487 section 4.8: "
- "missing AIA, AKI or SKI X509 extension", fn);
+ "missing AIA, AKI, SIA or SKI X509 extension", fn);
goto out;
}
Index: mft.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
retrieving revision 1.76
diff -u -p -r1.76 mft.c
--- mft.c 2 Nov 2022 12:43:02 -0000 1.76
+++ mft.c 3 Nov 2022 15:12:27 -0000
@@ -368,11 +368,14 @@ mft_parse(X509 **x509, const char *fn, c
goto out;
if (!x509_get_aki(*x509, fn, &p.res->aki))
goto out;
+ if (!x509_get_sia(*x509, fn, &p.res->sia))
+ goto out;
if (!x509_get_ski(*x509, fn, &p.res->ski))
goto out;
- if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
+ if (p.res->aia == NULL || p.res->aki == NULL || p.res->sia == NULL
+ || p.res->ski == NULL) {
warnx("%s: RFC 6487 section 4.8: "
- "missing AIA, AKI or SKI X509 extension", fn);
+ "missing AIA, AKI, SIA, or SKI X509 extension", fn);
goto out;
}
Index: print.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/print.c,v
retrieving revision 1.17
diff -u -p -r1.17 print.c
--- print.c 2 Nov 2022 12:43:02 -0000 1.17
+++ print.c 3 Nov 2022 15:12:27 -0000
@@ -337,6 +337,7 @@ mft_print(const X509 *x, const struct mf
x509_print(x);
printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
printf("\t\"aia\": \"%s\",\n", p->aia);
+ printf("\t\"sia\": \"%s\",\n", p->sia);
printf("\t\"manifest_number\": \"%s\",\n", p->seqnum);
printf("\t\"valid_since\": %lld,\n", (long long)p->valid_since);
printf("\t\"valid_until\": %lld,\n", (long long)p->valid_until);
@@ -345,6 +346,7 @@ mft_print(const X509 *x, const struct mf
printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
x509_print(x);
printf("Authority info access: %s\n", p->aia);
+ printf("Subject info access: %s\n", p->sia);
printf("Manifest Number: %s\n", p->seqnum);
printf("Manifest valid since: %s\n", time2str(p->valid_since));
printf("Manifest valid until: %s\n", time2str(p->valid_until));
@@ -388,12 +390,14 @@ roa_print(const X509 *x, const struct ro
x509_print(x);
printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
printf("\t\"aia\": \"%s\",\n", p->aia);
+ printf("\t\"sia\": \"%s\",\n", p->sia);
printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
} else {
printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
x509_print(x);
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);
printf("ROA valid until: %s\n", time2str(p->expires));
printf("asID: %u\n", p->asid);
}
@@ -432,6 +436,7 @@ gbr_print(const X509 *x, const struct gb
x509_print(x);
printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
printf("\t\"aia\": \"%s\",\n", p->aia);
+ printf("\t\"sia\": \"%s\",\n", p->sia);
printf("\t\"vcard\": \"");
for (i = 0; i < strlen(p->vcard); i++) {
if (p->vcard[i] == '"')
@@ -449,6 +454,7 @@ gbr_print(const X509 *x, const struct gb
x509_print(x);
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);
printf("vcard:\n%s", p->vcard);
}
}
@@ -580,6 +586,7 @@ aspa_print(const X509 *x, const struct a
x509_print(x);
printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
printf("\t\"aia\": \"%s\",\n", p->aia);
+ printf("\t\"sia\": \"%s\",\n", p->sia);
printf("\t\"customer_asid\": %u,\n", p->custasid);
printf("\t\"provider_set\": [\n");
for (i = 0; i < p->providersz; i++) {
@@ -599,6 +606,7 @@ aspa_print(const X509 *x, const struct a
x509_print(x);
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);
printf("Customer AS: %u\n", p->custasid);
printf("Provider Set:\n");
for (i = 0; i < p->providersz; i++) {
@@ -681,6 +689,7 @@ tak_print(const X509 *x, const struct ta
x509_print(x);
printf("\t\"aki\": \"%s\",\n", pretty_key_id(p->aki));
printf("\t\"aia\": \"%s\",\n", p->aia);
+ printf("\t\"sia\": \"%s\",\n", p->sia);
printf("\t\"valid_until\": %lld,\n", (long long)p->expires);
printf("\t\"takeys\": [\n");
} else {
@@ -689,6 +698,7 @@ tak_print(const X509 *x, const struct ta
x509_print(x);
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);
printf("TAK EE certificate valid until: %s\n", tbuf);
}
Index: roa.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
retrieving revision 1.54
diff -u -p -r1.54 roa.c
--- roa.c 2 Nov 2022 10:04:41 -0000 1.54
+++ roa.c 3 Nov 2022 15:12:27 -0000
@@ -222,11 +222,14 @@ roa_parse(X509 **x509, const char *fn, c
goto out;
if (!x509_get_aki(*x509, fn, &p.res->aki))
goto out;
+ if (!x509_get_sia(*x509, fn, &p.res->sia))
+ goto out;
if (!x509_get_ski(*x509, fn, &p.res->ski))
goto out;
- if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
+ if (p.res->aia == NULL || p.res->aki == NULL || p.res->sia == NULL
+ || p.res->ski == NULL) {
warnx("%s: RFC 6487 section 4.8: "
- "missing AIA, AKI or SKI X509 extension", fn);
+ "missing AIA, AKI, SIA, or SKI X509 extension", fn);
goto out;
}
Index: tak.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/tak.c,v
retrieving revision 1.1
diff -u -p -r1.1 tak.c
--- tak.c 2 Nov 2022 12:43:02 -0000 1.1
+++ tak.c 3 Nov 2022 15:12:27 -0000
@@ -247,11 +247,14 @@ tak_parse(X509 **x509, const char *fn, c
goto out;
if (!x509_get_aki(*x509, fn, &p.res->aki))
goto out;
+ if (!x509_get_sia(*x509, fn, &p.res->sia))
+ goto out;
if (!x509_get_ski(*x509, fn, &p.res->ski))
goto out;
- if (p.res->aia == NULL || p.res->aki == NULL || p.res->ski == NULL) {
+ if (p.res->aia == NULL || p.res->aki == NULL || p.res->sia == NULL
+ || p.res->ski == NULL) {
warnx("%s: RFC 6487 section 4.8: "
- "missing AIA, AKI or SKI X509 extension", fn);
+ "missing AIA, AKI, SIA, or SKI X509 extension", fn);
goto out;
}
Index: x509.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/x509.c,v
retrieving revision 1.53
diff -u -p -r1.53 x509.c
--- x509.c 2 Nov 2022 12:43:02 -0000 1.53
+++ x509.c 3 Nov 2022 15:12:27 -0000
@@ -34,6 +34,7 @@
ASN1_OBJECT *certpol_oid; /* id-cp-ipAddr-asNumber cert policy */
ASN1_OBJECT *carepo_oid; /* 1.3.6.1.5.5.7.48.5 (caRepository) */
ASN1_OBJECT *manifest_oid; /* 1.3.6.1.5.5.7.48.10 (rpkiManifest) */
+ASN1_OBJECT *signedobj_oid; /* 1.3.6.1.5.5.7.48.11 (signedObject) */
ASN1_OBJECT *notify_oid; /* 1.3.6.1.5.5.7.48.13 (rpkiNotify) */
ASN1_OBJECT *roa_oid; /* id-ct-routeOriginAuthz CMS content type */
ASN1_OBJECT *mft_oid; /* id-ct-rpkiManifest CMS content type */
@@ -64,6 +65,10 @@ static const struct {
.ptr = &manifest_oid,
},
{
+ .oid = "1.3.6.1.5.5.7.48.11",
+ .ptr = &signedobj_oid,
+ },
+ {
.oid = "1.3.6.1.5.5.7.48.13",
.ptr = ¬ify_oid,
},
@@ -368,6 +373,54 @@ out:
AUTHORITY_INFO_ACCESS_free(info);
return rc;
}
+
+/*
+ * Parse the Subject Information Access (SIA) extension
+ * See RFC 6487, section 4.8.8 for details.
+ * Returns NULL on failure, on success returns the SIA signedObject URI
+ * (which has to be freed after use).
+ */
+int
+x509_get_sia(X509 *x, const char *fn, char **sia)
+{
+ ACCESS_DESCRIPTION *ad;
+ AUTHORITY_INFO_ACCESS *info;
+ ASN1_OBJECT *oid;
+ int i, crit, rc = 0;
+
+ *sia = NULL;
+ info = X509_get_ext_d2i(x, NID_sinfo_access, &crit, NULL);
+ if (info == NULL)
+ return 1;
+
+ if (crit != 0) {
+ warnx("%s: RFC 6487 section 4.8.8: "
+ "SIA: extension not non-critical", fn);
+ goto out;
+ }
+
+ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
+ ad = sk_ACCESS_DESCRIPTION_value(info, i);
+ oid = ad->method;
+ if (OBJ_cmp(oid, signedobj_oid) == 0) {
+ if (!x509_location(fn, "SIA: signedObject", "rsync://",
+ ad->location, sia))
+ goto out;
+ }
+ }
+
+ if (sia == NULL) {
+ warnx("%s: RFC 6487 section 4.8.8: SIA: missing signedObject",
+ fn);
+ goto out;
+ }
+
+ rc = 1;
+ out:
+ AUTHORITY_INFO_ACCESS_free(info);
+ return rc;
+}
+
/*
* Extract the expire time (not-after) of a certificate.