From: David Howells <dhowells@redhat.com>
To: keyrings@linux-nfs.org
Cc: mcgrof@gmail.com, zohar@linux.vnet.ibm.com, kyle@kernel.org,
linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org, dwmw2@infradead.org
Subject: [PATCH 03/27] X.509: Extract both parts of the AuthorityKeyIdentifier [ver #7]
Date: Wed, 05 Aug 2015 14:43:56 +0100 [thread overview]
Message-ID: <20150805134356.9984.13185.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <20150805134323.9984.4454.stgit@warthog.procyon.org.uk>
Extract both parts of the AuthorityKeyIdentifier, not just the keyIdentifier,
as the second part can be used to match X.509 certificates by issuer and
serialNumber.
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Vivek Goyal <vgoyal@redhat.com>
---
crypto/asymmetric_keys/Makefile | 8 +-
crypto/asymmetric_keys/pkcs7_trust.c | 4 -
crypto/asymmetric_keys/pkcs7_verify.c | 12 +-
crypto/asymmetric_keys/x509_akid.asn1 | 35 +++++++
crypto/asymmetric_keys/x509_cert_parser.c | 142 ++++++++++++++++++-----------
crypto/asymmetric_keys/x509_parser.h | 5 +
crypto/asymmetric_keys/x509_public_key.c | 8 +-
7 files changed, 145 insertions(+), 69 deletions(-)
create mode 100644 crypto/asymmetric_keys/x509_akid.asn1
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index e47fcd9ac5e8..cd1406f9b14a 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -15,15 +15,21 @@ obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
x509_key_parser-y := \
x509-asn1.o \
+ x509_akid-asn1.o \
x509_rsakey-asn1.o \
x509_cert_parser.o \
x509_public_key.o
-$(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h
+$(obj)/x509_cert_parser.o: \
+ $(obj)/x509-asn1.h \
+ $(obj)/x509_akid-asn1.h \
+ $(obj)/x509_rsakey-asn1.h
$(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h
+$(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h
$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h
clean-files += x509-asn1.c x509-asn1.h
+clean-files += x509_akid-asn1.c x509_akid-asn1.h
clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h
#
diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c
index 1d29376072da..0f6463b6692b 100644
--- a/crypto/asymmetric_keys/pkcs7_trust.c
+++ b/crypto/asymmetric_keys/pkcs7_trust.c
@@ -85,8 +85,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
/* No match - see if the root certificate has a signer amongst the
* trusted keys.
*/
- if (last && last->authority) {
- key = x509_request_asymmetric_key(trust_keyring, last->authority,
+ if (last && last->akid_skid) {
+ key = x509_request_asymmetric_key(trust_keyring, last->akid_skid,
false);
if (!IS_ERR(key)) {
x509 = last;
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index cd455450b069..a4d083f7e9e1 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -187,11 +187,11 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
goto maybe_missing_crypto_in_x509;
pr_debug("- issuer %s\n", x509->issuer);
- if (x509->authority)
+ if (x509->akid_skid)
pr_debug("- authkeyid %*phN\n",
- x509->authority->len, x509->authority->data);
+ x509->akid_skid->len, x509->akid_skid->data);
- if (!x509->authority ||
+ if (!x509->akid_skid ||
strcmp(x509->subject, x509->issuer) == 0) {
/* If there's no authority certificate specified, then
* the certificate must be self-signed and is the root
@@ -216,13 +216,13 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
* list to see if the next one is there.
*/
pr_debug("- want %*phN\n",
- x509->authority->len, x509->authority->data);
+ x509->akid_skid->len, x509->akid_skid->data);
for (p = pkcs7->certs; p; p = p->next) {
if (!p->skid)
continue;
pr_debug("- cmp [%u] %*phN\n",
p->index, p->skid->len, p->skid->data);
- if (asymmetric_key_id_same(p->skid, x509->authority))
+ if (asymmetric_key_id_same(p->skid, x509->akid_skid))
goto found_issuer;
}
@@ -338,8 +338,6 @@ int pkcs7_verify(struct pkcs7_message *pkcs7)
ret = x509_get_sig_params(x509);
if (ret < 0)
return ret;
- pr_debug("X.509[%u] %*phN\n",
- n, x509->authority->len, x509->authority->data);
}
for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
diff --git a/crypto/asymmetric_keys/x509_akid.asn1 b/crypto/asymmetric_keys/x509_akid.asn1
new file mode 100644
index 000000000000..1a33231a75a8
--- /dev/null
+++ b/crypto/asymmetric_keys/x509_akid.asn1
@@ -0,0 +1,35 @@
+-- X.509 AuthorityKeyIdentifier
+-- rfc5280 section 4.2.1.1
+
+AuthorityKeyIdentifier ::= SEQUENCE {
+ keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
+ authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
+ authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL
+ }
+
+KeyIdentifier ::= OCTET STRING ({ x509_akid_note_kid })
+
+CertificateSerialNumber ::= INTEGER ({ x509_akid_note_serial })
+
+GeneralNames ::= SEQUENCE OF GeneralName
+
+GeneralName ::= CHOICE {
+ otherName [0] ANY,
+ rfc822Name [1] IA5String,
+ dNSName [2] IA5String,
+ x400Address [3] ANY,
+ directoryName [4] Name ({ x509_akid_note_name }),
+ ediPartyName [5] ANY,
+ uniformResourceIdentifier [6] IA5String,
+ iPAddress [7] OCTET STRING,
+ registeredID [8] OBJECT IDENTIFIER
+ }
+
+Name ::= SEQUENCE OF RelativeDistinguishedName
+
+RelativeDistinguishedName ::= SET OF AttributeValueAssertion
+
+AttributeValueAssertion ::= SEQUENCE {
+ attributeType OBJECT IDENTIFIER ({ x509_note_OID }),
+ attributeValue ANY ({ x509_extract_name_segment })
+ }
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index a668d90302d3..6c130dd56f35 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -18,6 +18,7 @@
#include "public_key.h"
#include "x509_parser.h"
#include "x509-asn1.h"
+#include "x509_akid-asn1.h"
#include "x509_rsakey-asn1.h"
struct x509_parse_context {
@@ -35,6 +36,10 @@ struct x509_parse_context {
u16 o_offset; /* Offset of organizationName (O) */
u16 cn_offset; /* Offset of commonName (CN) */
u16 email_offset; /* Offset of emailAddress */
+ unsigned raw_akid_size;
+ const void *raw_akid; /* Raw authorityKeyId in ASN.1 */
+ const void *akid_raw_issuer; /* Raw directoryName in authorityKeyId */
+ unsigned akid_raw_issuer_size;
};
/*
@@ -48,7 +53,8 @@ void x509_free_certificate(struct x509_certificate *cert)
kfree(cert->subject);
kfree(cert->id);
kfree(cert->skid);
- kfree(cert->authority);
+ kfree(cert->akid_id);
+ kfree(cert->akid_skid);
kfree(cert->sig.digest);
mpi_free(cert->sig.rsa.s);
kfree(cert);
@@ -85,6 +91,18 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
if (ret < 0)
goto error_decode;
+ /* Decode the AuthorityKeyIdentifier */
+ if (ctx->raw_akid) {
+ pr_devel("AKID: %u %*phN\n",
+ ctx->raw_akid_size, ctx->raw_akid_size, ctx->raw_akid);
+ ret = asn1_ber_decoder(&x509_akid_decoder, ctx,
+ ctx->raw_akid, ctx->raw_akid_size);
+ if (ret < 0) {
+ pr_warn("Couldn't decode AuthKeyIdentifier\n");
+ goto error_decode;
+ }
+ }
+
/* Decode the public key */
ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx,
ctx->key, ctx->key_size);
@@ -422,7 +440,6 @@ int x509_process_extension(void *context, size_t hdrlen,
struct x509_parse_context *ctx = context;
struct asymmetric_key_id *kid;
const unsigned char *v = value;
- int i;
pr_debug("Extension: %u\n", ctx->last_oid);
@@ -449,57 +466,8 @@ int x509_process_extension(void *context, size_t hdrlen,
if (ctx->last_oid == OID_authorityKeyIdentifier) {
/* Get hold of the CA key fingerprint */
- if (ctx->cert->authority || vlen < 5)
- return -EBADMSG;
-
- /* Authority Key Identifier must be a Constructed SEQUENCE */
- if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5)))
- return -EBADMSG;
-
- /* Authority Key Identifier is not indefinite length */
- if (unlikely(vlen == ASN1_INDEFINITE_LENGTH))
- return -EBADMSG;
-
- if (vlen < ASN1_INDEFINITE_LENGTH) {
- /* Short Form length */
- if (v[1] != vlen - 2 ||
- v[2] != SEQ_TAG_KEYID ||
- v[3] > vlen - 4)
- return -EBADMSG;
-
- vlen = v[3];
- v += 4;
- } else {
- /* Long Form length */
- size_t seq_len = 0;
- size_t sub = v[1] - ASN1_INDEFINITE_LENGTH;
-
- if (sub > 2)
- return -EBADMSG;
-
- /* calculate the length from subsequent octets */
- v += 2;
- for (i = 0; i < sub; i++) {
- seq_len <<= 8;
- seq_len |= v[i];
- }
-
- if (seq_len != vlen - 2 - sub ||
- v[sub] != SEQ_TAG_KEYID ||
- v[sub + 1] > vlen - 4 - sub)
- return -EBADMSG;
-
- vlen = v[sub + 1];
- v += (sub + 2);
- }
-
- kid = asymmetric_key_generate_id(ctx->cert->raw_issuer,
- ctx->cert->raw_issuer_size,
- v, vlen);
- if (IS_ERR(kid))
- return PTR_ERR(kid);
- pr_debug("authkeyid %*phN\n", kid->len, kid->data);
- ctx->cert->authority = kid;
+ ctx->raw_akid = v;
+ ctx->raw_akid_size = vlen;
return 0;
}
@@ -569,3 +537,71 @@ int x509_note_not_after(void *context, size_t hdrlen,
struct x509_parse_context *ctx = context;
return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen);
}
+
+/*
+ * Note a key identifier-based AuthorityKeyIdentifier
+ */
+int x509_akid_note_kid(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ struct asymmetric_key_id *kid;
+
+ pr_debug("AKID: keyid: %*phN\n", (int)vlen, value);
+
+ if (ctx->cert->akid_skid)
+ return 0;
+
+ kid = asymmetric_key_generate_id(ctx->cert->raw_issuer,
+ ctx->cert->raw_issuer_size,
+ value, vlen);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+ pr_debug("authkeyid %*phN\n", kid->len, kid->data);
+ ctx->cert->akid_skid = kid;
+ return 0;
+}
+
+/*
+ * Note a directoryName in an AuthorityKeyIdentifier
+ */
+int x509_akid_note_name(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+
+ pr_debug("AKID: name: %*phN\n", (int)vlen, value);
+
+ ctx->akid_raw_issuer = value;
+ ctx->akid_raw_issuer_size = vlen;
+ return 0;
+}
+
+/*
+ * Note a serial number in an AuthorityKeyIdentifier
+ */
+int x509_akid_note_serial(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct x509_parse_context *ctx = context;
+ struct asymmetric_key_id *kid;
+
+ pr_debug("AKID: serial: %*phN\n", (int)vlen, value);
+
+ if (!ctx->akid_raw_issuer || ctx->cert->akid_id)
+ return 0;
+
+ kid = asymmetric_key_generate_id(value,
+ vlen,
+ ctx->akid_raw_issuer,
+ ctx->akid_raw_issuer_size);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+
+ pr_debug("authkeyid %*phN\n", kid->len, kid->data);
+ ctx->cert->akid_id = kid;
+ return 0;
+}
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index 3dfe6b5d6f0b..dcdb5c94f514 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -19,9 +19,10 @@ struct x509_certificate {
struct public_key_signature sig; /* Signature parameters */
char *issuer; /* Name of certificate issuer */
char *subject; /* Name of certificate subject */
- struct asymmetric_key_id *id; /* Serial number + issuer */
+ struct asymmetric_key_id *id; /* Issuer + Serial number */
struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */
- struct asymmetric_key_id *authority; /* Authority key identifier (optional) */
+ struct asymmetric_key_id *akid_id; /* CA AuthKeyId matching ->id (optional) */
+ struct asymmetric_key_id *akid_skid; /* CA AuthKeyId matching ->skid (optional) */
struct tm valid_from;
struct tm valid_to;
const void *tbs; /* Signed data */
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 24f17e6c5904..bb55d6074d5f 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -227,10 +227,10 @@ static int x509_validate_trust(struct x509_certificate *cert,
if (!trust_keyring)
return -EOPNOTSUPP;
- if (ca_keyid && !asymmetric_key_id_partial(cert->authority, ca_keyid))
+ if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid))
return -EPERM;
- key = x509_request_asymmetric_key(trust_keyring, cert->authority,
+ key = x509_request_asymmetric_key(trust_keyring, cert->akid_skid,
false);
if (!IS_ERR(key)) {
if (!use_builtin_keys
@@ -287,8 +287,8 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
cert->pub->id_type = PKEY_ID_X509;
/* Check the signature on the key if it appears to be self-signed */
- if (!cert->authority ||
- asymmetric_key_id_same(cert->skid, cert->authority)) {
+ if (!cert->akid_skid ||
+ asymmetric_key_id_same(cert->skid, cert->akid_skid)) {
ret = x509_check_signature(cert->pub, cert); /* self-signed */
if (ret < 0)
goto error_free_cert;
next prev parent reply other threads:[~2015-08-05 13:57 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-05 13:43 [PATCH 00/27] MODSIGN: Use PKCS#7 for module signatures " David Howells
2015-08-05 13:43 ` [PATCH 01/27] ASN.1: Add an ASN.1 compiler option to dump the element tree " David Howells
2015-08-05 13:43 ` [PATCH 02/27] ASN.1: Copy string names to tokens in ASN.1 compiler " David Howells
2015-08-05 18:13 ` Mimi Zohar
2015-08-05 18:26 ` David Howells
2015-08-05 18:56 ` Mimi Zohar
2015-08-05 13:43 ` David Howells [this message]
2015-08-05 13:44 ` [PATCH 04/27] X.509: Support X.509 lookup by Issuer+Serial form AuthorityKeyIdentifier " David Howells
2015-08-05 13:44 ` [PATCH 05/27] PKCS#7: Allow detached data to be supplied for signature checking purposes " David Howells
2015-08-05 13:44 ` [PATCH 06/27] MODSIGN: Provide a utility to append a PKCS#7 signature to a module " David Howells
2015-08-05 13:44 ` [PATCH 07/27] MODSIGN: Use PKCS#7 messages as module signatures " David Howells
2015-08-05 13:44 ` [PATCH 08/27] sign-file: Add option to only create signature file " David Howells
2015-08-05 13:44 ` [PATCH 09/27] system_keyring.c doesn't need to #include module-internal.h " David Howells
2015-08-05 13:45 ` [PATCH 10/27] MODSIGN: Extract the blob PKCS#7 signature verifier from module signing " David Howells
2015-08-05 13:45 ` [PATCH 11/27] modsign: Abort modules_install when signing fails " David Howells
2015-08-05 13:45 ` [PATCH 12/27] modsign: Allow password to be specified for signing key " David Howells
2015-08-05 13:45 ` [PATCH 13/27] modsign: Allow signing key to be PKCS#11 " David Howells
2015-08-05 13:45 ` [PATCH 14/27] modsign: Allow external signing key to be specified " David Howells
2015-08-05 13:45 ` [PATCH 15/27] modsign: Extract signing cert from CONFIG_MODULE_SIG_KEY if needed " David Howells
2015-08-05 13:46 ` [PATCH 16/27] modsign: Use single PEM file for autogenerated key " David Howells
2015-08-05 13:46 ` [PATCH 17/27] modsign: Add explicit CONFIG_SYSTEM_TRUSTED_KEYS option " David Howells
2015-08-05 13:46 ` [PATCH 18/27] PKCS#7: Check content type and versions " David Howells
2015-08-05 13:46 ` [PATCH 19/27] X.509: Change recorded SKID & AKID to not include Subject or Issuer " David Howells
2015-08-05 13:46 ` [PATCH 20/27] PKCS#7: Support CMS messages also [RFC5652] " David Howells
2015-08-05 13:47 ` [PATCH 21/27] sign-file: Generate CMS message as signature instead of PKCS#7 " David Howells
2015-08-05 13:47 ` [PATCH 22/27] extract-cert: Cope with multiple X.509 certificates in a single file " David Howells
2015-08-05 13:47 ` [PATCH 23/27] modsign: Use extract-cert to process CONFIG_SYSTEM_TRUSTED_KEYS " David Howells
2015-08-05 13:47 ` [PATCH 24/27] PKCS#7: Improve and export the X.509 ASN.1 time object decoder " David Howells
2015-08-05 13:47 ` [PATCH 25/27] PKCS#7: Appropriately require or forbid authenticated attributes " David Howells
2015-08-05 13:47 ` [PATCH 26/27] KEYS: Add a name for PKEY_ID_PKCS7 " David Howells
2015-08-05 13:48 ` [PATCH 27/27] PKCS#7: Restrict content type and authenticated attributes by purpose " David Howells
2015-08-05 14:27 ` [PATCH 25/27] PKCS#7: Appropriately require or forbid authenticated attributes " David Howells
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150805134356.9984.13185.stgit@warthog.procyon.org.uk \
--to=dhowells@redhat.com \
--cc=dwmw2@infradead.org \
--cc=keyrings@linux-nfs.org \
--cc=kyle@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mcgrof@gmail.com \
--cc=zohar@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome