diff --git a/PROTOCOL.krl b/PROTOCOL.krl index 115f80e5d..f4213156e 100644 --- a/PROTOCOL.krl +++ b/PROTOCOL.krl @@ -37,6 +37,7 @@ The available section types are: #define KRL_SECTION_FINGERPRINT_SHA1 3 #define KRL_SECTION_SIGNATURE 4 #define KRL_SECTION_FINGERPRINT_SHA256 5 +#define KRL_SECTION_EXTENSION 255 2. Certificate section @@ -64,6 +65,7 @@ The certificate section types are: #define KRL_SECTION_CERT_SERIAL_RANGE 0x21 #define KRL_SECTION_CERT_SERIAL_BITMAP 0x22 #define KRL_SECTION_CERT_KEY_ID 0x23 +#define KRL_SECTION_CERT_EXTENSION 0x39 2.1 Certificate serial list section @@ -114,6 +116,29 @@ associated with a particular identity, e.g. a host or a user. This section must contain at least one "key_id". This section may appear multiple times. +2.5. Certificate Extension subsections + +This subsection type provides a generic extension mechanism to the +certificates KRL section that may be used to provide optional or critical +data. + +Extensions are stored in subsections of type +KRL_SECTION_CERT_EXTENSION with the following contents: + + string extension_name + boolean is_critical + string extension_contents. + +Where "extension_name" describes the type of extension. It is +recommended that user extensions follow "cert-name@domain.org" naming. + +The "is_critical" indicates whether this extension is mandatory or +optional. If true, then any unsupported extension encountered should +result in KRL parsing failure. If false, then it may be safely be +ignored. + +The "extension_contents" contains the body of the extension. + 3. Explicit key sections These sections, identified as KRL_SECTION_EXPLICIT_KEY, revoke keys @@ -144,7 +169,29 @@ as a big-endian integer. This section may appear multiple times. -5. KRL signature sections +5. Extension sections + +This section type provides a generic extension mechanism to the KRL +format that may be used to provide optional or critical data. + +Extensions are recorded in sections of type KRL_SECTION_EXTENSION +with the following contents: + + string extension_name + boolean is_critical + string extension_contents. + +Where "extension_name" describes the type of extension. It is +recommended that user extensions follow "name@domain.org" naming. + +The "is_critical" indicates whether this extension is mandatory or +optional. If true, then any unsupported extension encountered should +result in KRL parsing failure. If false, then it may be safely be +ignored. + +The "extension_contents" contains the body of the extension. + +6. KRL signature sections The KRL_SECTION_SIGNATURE section serves a different purpose to the preceding ones: to provide cryptographic authentication of a KRL that @@ -168,4 +215,4 @@ Implementations that retrieve KRLs over untrusted channels must verify signatures. Signature sections are optional for KRLs distributed by trusted means. -$OpenBSD: PROTOCOL.krl,v 1.5 2018/09/12 01:21:34 djm Exp $ +$OpenBSD: PROTOCOL.krl,v 1.6 2023/07/17 03:57:21 djm Exp $ diff --git a/krl.c b/krl.c index 1fed42b22..f04ea27d7 100644 --- a/krl.c +++ b/krl.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.c,v 1.55 2023/03/14 07:28:47 dtucker Exp $ */ +/* $OpenBSD: krl.c,v 1.56 2023/07/17 03:57:21 djm Exp $ */ #include "includes.h" @@ -840,6 +840,45 @@ format_timestamp(u_int64_t timestamp, char *ts, size_t nts) } } +static int +cert_extension_subsection(struct sshbuf *subsect, struct ssh_krl *krl) +{ + int r = SSH_ERR_INTERNAL_ERROR; + u_char critical = 1; + struct sshbuf *value = NULL; + char *name = NULL; + + if ((r = sshbuf_get_cstring(subsect, &name, NULL)) != 0 || + (r = sshbuf_get_u8(subsect, &critical)) != 0 || + (r = sshbuf_froms(subsect, &value)) != 0) { + debug_fr(r, "parse"); + error("KRL has invalid certificate extension subsection"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_len(subsect) != 0) { + error("KRL has invalid certificate extension subsection: " + "trailing data"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + debug_f("cert extension %s critical %u len %zu", + name, critical, sshbuf_len(value)); + /* no extensions are currently supported */ + if (critical) { + error("KRL contains unsupported critical certificate " + "subsection \"%s\"", name); + r = SSH_ERR_FEATURE_UNSUPPORTED; + goto out; + } + /* success */ + r = 0; + out: + free(name); + sshbuf_free(value); + return r; +} + static int parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl) { @@ -931,6 +970,10 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl) key_id = NULL; } break; + case KRL_SECTION_CERT_EXTENSION: + if ((r = cert_extension_subsection(subsect, krl)) != 0) + goto out; + break; default: error("Unsupported KRL certificate section %u", type); r = SSH_ERR_INVALID_FORMAT; @@ -977,6 +1020,43 @@ blob_section(struct sshbuf *sect, struct revoked_blob_tree *target_tree, return 0; } +static int +extension_section(struct sshbuf *sect, struct ssh_krl *krl) +{ + int r = SSH_ERR_INTERNAL_ERROR; + u_char critical = 1; + struct sshbuf *value = NULL; + char *name = NULL; + + if ((r = sshbuf_get_cstring(sect, &name, NULL)) != 0 || + (r = sshbuf_get_u8(sect, &critical)) != 0 || + (r = sshbuf_froms(sect, &value)) != 0) { + debug_fr(r, "parse"); + error("KRL has invalid extension section"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_len(sect) != 0) { + error("KRL has invalid extension section: trailing data"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + debug_f("extension %s critical %u len %zu", + name, critical, sshbuf_len(value)); + /* no extensions are currently supported */ + if (critical) { + error("KRL contains unsupported critical section \"%s\"", name); + r = SSH_ERR_FEATURE_UNSUPPORTED; + goto out; + } + /* success */ + r = 0; + out: + free(name); + sshbuf_free(value); + return r; +} + /* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */ int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, @@ -1144,6 +1224,10 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, &krl->revoked_sha256s, 32)) != 0) goto out; break; + case KRL_SECTION_EXTENSION: + if ((r = extension_section(sect, krl)) != 0) + goto out; + break; case KRL_SECTION_SIGNATURE: /* Handled above, but still need to stay in synch */ sshbuf_free(sect); diff --git a/krl.h b/krl.h index ca6d3f284..d0f469870 100644 --- a/krl.h +++ b/krl.h @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.h,v 1.8 2020/04/03 02:26:56 djm Exp $ */ +/* $OpenBSD: krl.h,v 1.9 2023/07/17 03:57:21 djm Exp $ */ #ifndef _KRL_H #define _KRL_H @@ -30,12 +30,14 @@ #define KRL_SECTION_FINGERPRINT_SHA1 3 #define KRL_SECTION_SIGNATURE 4 #define KRL_SECTION_FINGERPRINT_SHA256 5 +#define KRL_SECTION_EXTENSION 255 /* KRL_SECTION_CERTIFICATES subsection types */ #define KRL_SECTION_CERT_SERIAL_LIST 0x20 #define KRL_SECTION_CERT_SERIAL_RANGE 0x21 #define KRL_SECTION_CERT_SERIAL_BITMAP 0x22 #define KRL_SECTION_CERT_KEY_ID 0x23 +#define KRL_SECTION_CERT_EXTENSION 0x39 struct sshkey; struct sshbuf;