summaryrefslogtreecommitdiff
path: root/crypto/asymmetric_keys/pkcs7_parser.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2014-09-16 20:36:13 +0400
committerDavid Howells <dhowells@redhat.com>2014-09-16 20:36:13 +0400
commit46963b774d441c833afc1535f6d84b3df2a94204 (patch)
tree335cbd163ef2581b72d462f49984a6809609a58b /crypto/asymmetric_keys/pkcs7_parser.c
parent7901c1a8effbe5f89673bfc09d6e37b8f334f1a7 (diff)
downloadlinux-46963b774d441c833afc1535f6d84b3df2a94204.tar.xz
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:<hex>" 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 <dhowells@redhat.com> Acked-by: Vivek Goyal <vgoyal@redhat.com>
Diffstat (limited to 'crypto/asymmetric_keys/pkcs7_parser.c')
-rw-r--r--crypto/asymmetric_keys/pkcs7_parser.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
index 1e9861da7ee4..3bd5a1e4c493 100644
--- a/crypto/asymmetric_keys/pkcs7_parser.c
+++ b/crypto/asymmetric_keys/pkcs7_parser.c
@@ -29,6 +29,10 @@ struct pkcs7_parse_context {
enum OID last_oid; /* Last OID encountered */
unsigned x509_index;
unsigned sinfo_index;
+ const void *raw_serial;
+ unsigned raw_serial_size;
+ unsigned raw_issuer_size;
+ const void *raw_issuer;
};
/*
@@ -39,6 +43,7 @@ static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
if (sinfo) {
mpi_free(sinfo->sig.mpi[0]);
kfree(sinfo->sig.digest);
+ kfree(sinfo->signing_cert_id);
kfree(sinfo);
}
}
@@ -251,10 +256,10 @@ int pkcs7_extract_cert(void *context, size_t hdrlen,
if (IS_ERR(x509))
return PTR_ERR(x509);
- pr_debug("Got cert for %s\n", x509->subject);
- pr_debug("- fingerprint %s\n", x509->fingerprint);
-
x509->index = ++ctx->x509_index;
+ pr_debug("Got cert %u for %s\n", x509->index, x509->subject);
+ pr_debug("- fingerprint %*phN\n", x509->id->len, x509->id->data);
+
*ctx->ppcerts = x509;
ctx->ppcerts = &x509->next;
return 0;
@@ -343,8 +348,8 @@ int pkcs7_sig_note_serial(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct pkcs7_parse_context *ctx = context;
- ctx->sinfo->raw_serial = value;
- ctx->sinfo->raw_serial_size = vlen;
+ ctx->raw_serial = value;
+ ctx->raw_serial_size = vlen;
return 0;
}
@@ -356,8 +361,8 @@ int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct pkcs7_parse_context *ctx = context;
- ctx->sinfo->raw_issuer = value;
- ctx->sinfo->raw_issuer_size = vlen;
+ ctx->raw_issuer = value;
+ ctx->raw_issuer_size = vlen;
return 0;
}
@@ -390,10 +395,21 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct pkcs7_parse_context *ctx = context;
-
- ctx->sinfo->index = ++ctx->sinfo_index;
- *ctx->ppsinfo = ctx->sinfo;
- ctx->ppsinfo = &ctx->sinfo->next;
+ struct pkcs7_signed_info *sinfo = ctx->sinfo;
+ struct asymmetric_key_id *kid;
+
+ /* Generate cert issuer + serial number key ID */
+ kid = asymmetric_key_generate_id(ctx->raw_serial,
+ ctx->raw_serial_size,
+ ctx->raw_issuer,
+ ctx->raw_issuer_size);
+ if (IS_ERR(kid))
+ return PTR_ERR(kid);
+
+ sinfo->signing_cert_id = kid;
+ sinfo->index = ++ctx->sinfo_index;
+ *ctx->ppsinfo = sinfo;
+ ctx->ppsinfo = &sinfo->next;
ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
if (!ctx->sinfo)
return -ENOMEM;