diff options
author | David Howells <dhowells@redhat.com> | 2014-09-16 20:36:13 +0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2014-09-16 20:36:13 +0400 |
commit | 46963b774d441c833afc1535f6d84b3df2a94204 (patch) | |
tree | 335cbd163ef2581b72d462f49984a6809609a58b /crypto/asymmetric_keys/pkcs7_parser.c | |
parent | 7901c1a8effbe5f89673bfc09d6e37b8f334f1a7 (diff) | |
download | linux-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.c | 38 |
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; |