From 517fcc6309aed9fd3e1bf679a49a1e328f24ee5f Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 16 Sep 2014 17:36:13 +0100 Subject: KEYS: Overhaul key identification when searching for asymmetric keys Make use of the new match string preparsing to overhaul key identification when searching for asymmetric keys. The following changes are made: (1) Use the previously created asymmetric_key_id struct to hold the following key IDs derived from the X.509 certificate or PKCS#7 message: id: serial number + issuer skid: subjKeyId + subject authority: authKeyId + issuer (2) Replace the hex fingerprint attached to key->type_data[1] with an asymmetric_key_ids struct containing the id and the skid (if present). (3) Make the asymmetric_type match data preparse select one of two searches: (a) An iterative search for the key ID given if prefixed with "id:". The prefix is expected to be followed by a hex string giving the ID to search for. The criterion key ID is checked against all key IDs recorded on the key. (b) A direct search if the key ID is not prefixed with "id:". This will look for an exact match on the key description. (4) Make x509_request_asymmetric_key() take a key ID. This is then converted into "id:" and passed into keyring_search() where match preparsing will turn it back into a binary ID. (5) X.509 certificate verification then takes the authority key ID and looks up a key that matches it to find the public key for the certificate signature. (6) PKCS#7 certificate verification then takes the id key ID and looks up a key that matches it to find the public key for the signed information block signature. Additional changes: (1) Multiple subjKeyId and authKeyId values on an X.509 certificate cause the cert to be rejected with -EBADMSG. (2) The 'fingerprint' ID is gone. This was primarily intended to convey PGP public key fingerprints. If PGP is supported in future, this should generate a key ID that carries the fingerprint. (3) Th ca_keyid= kernel command line option is now converted to a key ID and used to match the authority key ID. Possibly this should only match the actual authKeyId part and not the issuer as well. Signed-off-by: David Howells Acked-by: Vivek Goyal --- crypto/asymmetric_keys/x509_cert_parser.c | 55 ++++++++++++++++++------------- 1 file changed, 33 insertions(+), 22 deletions(-) (limited to 'crypto/asymmetric_keys/x509_cert_parser.c') diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index ac72348c..96151b2b 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -46,7 +46,8 @@ void x509_free_certificate(struct x509_certificate *cert) public_key_destroy(cert->pub); kfree(cert->issuer); kfree(cert->subject); - kfree(cert->fingerprint); + kfree(cert->id); + kfree(cert->skid); kfree(cert->authority); kfree(cert->sig.digest); mpi_free(cert->sig.rsa.s); @@ -62,6 +63,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) { struct x509_certificate *cert; struct x509_parse_context *ctx; + struct asymmetric_key_id *kid; long ret; ret = -ENOMEM; @@ -89,6 +91,17 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) if (ret < 0) goto error_decode; + /* Generate cert issuer + serial number key ID */ + kid = asymmetric_key_generate_id(cert->raw_serial, + cert->raw_serial_size, + cert->raw_issuer, + cert->raw_issuer_size); + if (IS_ERR(kid)) { + ret = PTR_ERR(kid); + goto error_decode; + } + cert->id = kid; + kfree(ctx); return cert; @@ -407,36 +420,34 @@ int x509_process_extension(void *context, size_t hdrlen, const void *value, size_t vlen) { struct x509_parse_context *ctx = context; + struct asymmetric_key_id *kid; const unsigned char *v = value; - char *f; int i; pr_debug("Extension: %u\n", ctx->last_oid); if (ctx->last_oid == OID_subjectKeyIdentifier) { /* Get hold of the key fingerprint */ - if (vlen < 3) + if (ctx->cert->skid || vlen < 3) return -EBADMSG; if (v[0] != ASN1_OTS || v[1] != vlen - 2) return -EBADMSG; v += 2; vlen -= 2; - f = kmalloc(vlen * 2 + 1, GFP_KERNEL); - if (!f) - return -ENOMEM; - for (i = 0; i < vlen; i++) - sprintf(f + i * 2, "%02x", v[i]); - pr_debug("fingerprint %s\n", f); - ctx->cert->fingerprint = f; + kid = asymmetric_key_generate_id(v, vlen, + ctx->cert->raw_subject, + ctx->cert->raw_subject_size); + if (IS_ERR(kid)) + return PTR_ERR(kid); + ctx->cert->skid = kid; + pr_debug("subjkeyid %*phN\n", kid->len, kid->data); return 0; } if (ctx->last_oid == OID_authorityKeyIdentifier) { - size_t key_len; - /* Get hold of the CA key fingerprint */ - if (vlen < 5) + if (ctx->cert->authority || vlen < 5) return -EBADMSG; /* Authority Key Identifier must be a Constructed SEQUENCE */ @@ -454,7 +465,7 @@ int x509_process_extension(void *context, size_t hdrlen, v[3] > vlen - 4) return -EBADMSG; - key_len = v[3]; + vlen = v[3]; v += 4; } else { /* Long Form length */ @@ -476,17 +487,17 @@ int x509_process_extension(void *context, size_t hdrlen, v[sub + 1] > vlen - 4 - sub) return -EBADMSG; - key_len = v[sub + 1]; + vlen = v[sub + 1]; v += (sub + 2); } - f = kmalloc(key_len * 2 + 1, GFP_KERNEL); - if (!f) - return -ENOMEM; - for (i = 0; i < key_len; i++) - sprintf(f + i * 2, "%02x", v[i]); - pr_debug("authority %s\n", f); - ctx->cert->authority = f; + kid = asymmetric_key_generate_id(v, vlen, + ctx->cert->raw_issuer, + ctx->cert->raw_issuer_size); + if (IS_ERR(kid)) + return PTR_ERR(kid); + pr_debug("authkeyid %*phN\n", kid->len, kid->data); + ctx->cert->authority = kid; return 0; } -- cgit v1.2.3 From 6730820e44bab3648430513b190db60e6cebf3a0 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 3 Oct 2014 16:17:02 +0100 Subject: X.509: If available, use the raw subjKeyId to form the key description Module signing matches keys by comparing against the key description exactly. However, the way the key description gets constructed got changed to be composed of the subject name plus the certificate serial number instead of the subject name and the subjectKeyId. I changed this to avoid problems with certificates that don't *have* a subjectKeyId. Instead, if available, use the raw subjectKeyId to form the key description and only use the serial number if the subjectKeyId doesn't exist. Reported-by: Dmitry Kasatkin Signed-off-by: David Howells --- crypto/asymmetric_keys/x509_cert_parser.c | 2 ++ crypto/asymmetric_keys/x509_parser.h | 2 ++ crypto/asymmetric_keys/x509_public_key.c | 9 +++++++-- 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'crypto/asymmetric_keys/x509_cert_parser.c') diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 96151b2b..393706f3 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -435,6 +435,8 @@ int x509_process_extension(void *context, size_t hdrlen, v += 2; vlen -= 2; + ctx->cert->raw_skid_size = vlen; + ctx->cert->raw_skid = v; kid = asymmetric_key_generate_id(v, vlen, ctx->cert->raw_subject, ctx->cert->raw_subject_size); diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 4e1a3849..3f0f0f08 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -34,6 +34,8 @@ struct x509_certificate { const void *raw_issuer; /* Raw issuer name in ASN.1 */ const void *raw_subject; /* Raw subject name in ASN.1 */ unsigned raw_subject_size; + unsigned raw_skid_size; + const void *raw_skid; /* Raw subjectKeyId in ASN.1 */ unsigned index; bool seen; /* Infinite recursion prevention */ bool verified; diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 1d9a4c55..8bffb06b 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -279,8 +279,13 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) /* Propose a description */ sulen = strlen(cert->subject); - srlen = cert->raw_serial_size; - q = cert->raw_serial; + if (cert->raw_skid) { + srlen = cert->raw_skid_size; + q = cert->raw_skid; + } else { + srlen = cert->raw_serial_size; + q = cert->raw_serial; + } if (srlen > 1 && *q == 0) { srlen--; q++; -- cgit v1.2.3 From 8715e2fc4bb2844dae78ddcdcd070d44b245a22b Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Mon, 6 Oct 2014 16:52:12 +0100 Subject: KEYS: use swapped SKID for performing partial matching Earlier KEYS code used pure subject key identifiers (fingerprint) for searching keys. Latest merged code removed that and broke compatibility with integrity subsytem signatures and original format of module signatures. This patch returns back partial matching on SKID. Reported-by: Dmitry Kasatkin Signed-off-by: Dmitry Kasatkin Signed-off-by: David Howells --- crypto/asymmetric_keys/x509_cert_parser.c | 12 ++++++------ crypto/asymmetric_keys/x509_parser.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'crypto/asymmetric_keys/x509_cert_parser.c') diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 393706f3..a668d903 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -437,9 +437,9 @@ int x509_process_extension(void *context, size_t hdrlen, ctx->cert->raw_skid_size = vlen; ctx->cert->raw_skid = v; - kid = asymmetric_key_generate_id(v, vlen, - ctx->cert->raw_subject, - ctx->cert->raw_subject_size); + kid = asymmetric_key_generate_id(ctx->cert->raw_subject, + ctx->cert->raw_subject_size, + v, vlen); if (IS_ERR(kid)) return PTR_ERR(kid); ctx->cert->skid = kid; @@ -493,9 +493,9 @@ int x509_process_extension(void *context, size_t hdrlen, v += (sub + 2); } - kid = asymmetric_key_generate_id(v, vlen, - ctx->cert->raw_issuer, - ctx->cert->raw_issuer_size); + 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); diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index 3f0f0f08..3dfe6b5d 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -19,9 +19,9 @@ 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; /* Issuer + serial number */ - struct asymmetric_key_id *skid; /* Subject key identifier */ - struct asymmetric_key_id *authority; /* Authority key identifier */ + struct asymmetric_key_id *id; /* Serial number + issuer */ + struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */ + struct asymmetric_key_id *authority; /* Authority key identifier (optional) */ struct tm valid_from; struct tm valid_to; const void *tbs; /* Signed data */ -- cgit v1.2.3