diff options
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r-- | crypto/asymmetric_keys/Kconfig | 6 | ||||
-rw-r--r-- | crypto/asymmetric_keys/Makefile | 5 | ||||
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_keys.h | 2 | ||||
-rw-r--r-- | crypto/asymmetric_keys/asymmetric_type.c | 89 | ||||
-rw-r--r-- | crypto/asymmetric_keys/mscode_parser.c | 21 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_key_type.c | 72 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_parser.c | 21 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_parser.h | 1 | ||||
-rw-r--r-- | crypto/asymmetric_keys/pkcs7_trust.c | 37 | ||||
-rw-r--r-- | crypto/asymmetric_keys/restrict.c | 108 | ||||
-rw-r--r-- | crypto/asymmetric_keys/verify_pefile.c | 40 | ||||
-rw-r--r-- | crypto/asymmetric_keys/verify_pefile.h | 5 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_parser.h | 1 | ||||
-rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 191 |
14 files changed, 275 insertions, 324 deletions
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 91a7e047a765..e28e912000a7 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -1,5 +1,5 @@ menuconfig ASYMMETRIC_KEY_TYPE - tristate "Asymmetric (public-key cryptographic) key type" + bool "Asymmetric (public-key cryptographic) key type" depends on KEYS help This option provides support for a key type that holds the data for @@ -40,8 +40,7 @@ config PKCS7_MESSAGE_PARSER config PKCS7_TEST_KEY tristate "PKCS#7 testing key type" - depends on PKCS7_MESSAGE_PARSER - select SYSTEM_TRUSTED_KEYRING + depends on SYSTEM_DATA_VERIFICATION help This option provides a type of key that can be loaded up from a PKCS#7 message - provided the message is signed by a trusted key. If @@ -54,6 +53,7 @@ config PKCS7_TEST_KEY config SIGNED_PE_FILE_VERIFICATION bool "Support for PE file signature verification" depends on PKCS7_MESSAGE_PARSER=y + depends on SYSTEM_DATA_VERIFICATION select ASN1 select OID_REGISTRY help diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index f90486256f01..6516855bec18 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -4,7 +4,10 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o -asymmetric_keys-y := asymmetric_type.o signature.o +asymmetric_keys-y := \ + asymmetric_type.o \ + restrict.o \ + signature.o obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h index 1d450b580245..ca8e9ac34ce6 100644 --- a/crypto/asymmetric_keys/asymmetric_keys.h +++ b/crypto/asymmetric_keys/asymmetric_keys.h @@ -9,6 +9,8 @@ * 2 of the Licence, or (at your option) any later version. */ +#include <keys/asymmetric-type.h> + extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id); extern int __asymmetric_key_hex_to_key_id(const char *id, diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index a79d30128821..6600181d5d01 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -35,6 +35,95 @@ static LIST_HEAD(asymmetric_key_parsers); static DECLARE_RWSEM(asymmetric_key_parsers_sem); /** + * find_asymmetric_key - Find a key by ID. + * @keyring: The keys to search. + * @id_0: The first ID to look for or NULL. + * @id_1: The second ID to look for or NULL. + * @partial: Use partial match if true, exact if false. + * + * Find a key in the given keyring by identifier. The preferred identifier is + * the id_0 and the fallback identifier is the id_1. If both are given, the + * lookup is by the former, but the latter must also match. + */ +struct key *find_asymmetric_key(struct key *keyring, + const struct asymmetric_key_id *id_0, + const struct asymmetric_key_id *id_1, + bool partial) +{ + struct key *key; + key_ref_t ref; + const char *lookup; + char *req, *p; + int len; + + if (id_0) { + lookup = id_0->data; + len = id_0->len; + } else { + lookup = id_1->data; + len = id_1->len; + } + + /* Construct an identifier "id:<keyid>". */ + p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); + if (!req) + return ERR_PTR(-ENOMEM); + + if (partial) { + *p++ = 'i'; + *p++ = 'd'; + } else { + *p++ = 'e'; + *p++ = 'x'; + } + *p++ = ':'; + p = bin2hex(p, lookup, len); + *p = 0; + + pr_debug("Look up: \"%s\"\n", req); + + ref = keyring_search(make_key_ref(keyring, 1), + &key_type_asymmetric, req); + if (IS_ERR(ref)) + pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); + kfree(req); + + if (IS_ERR(ref)) { + switch (PTR_ERR(ref)) { + /* Hide some search errors */ + case -EACCES: + case -ENOTDIR: + case -EAGAIN: + return ERR_PTR(-ENOKEY); + default: + return ERR_CAST(ref); + } + } + + key = key_ref_to_ptr(ref); + if (id_0 && id_1) { + const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); + + if (!kids->id[0]) { + pr_debug("First ID matches, but second is missing\n"); + goto reject; + } + if (!asymmetric_key_id_same(id_1, kids->id[1])) { + pr_debug("First ID matches, but second does not\n"); + goto reject; + } + } + + pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); + return key; + +reject: + key_put(key); + return ERR_PTR(-EKEYREJECTED); +} +EXPORT_SYMBOL_GPL(find_asymmetric_key); + +/** * asymmetric_key_generate_id: Construct an asymmetric key ID * @val_1: First binary blob * @len_1: Length of first binary blob diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c index 3242cbfaeaa2..6a76d5c70ef6 100644 --- a/crypto/asymmetric_keys/mscode_parser.c +++ b/crypto/asymmetric_keys/mscode_parser.c @@ -21,19 +21,13 @@ /* * Parse a Microsoft Individual Code Signing blob */ -int mscode_parse(struct pefile_context *ctx) +int mscode_parse(void *_ctx, const void *content_data, size_t data_len, + size_t asn1hdrlen) { - const void *content_data; - size_t data_len; - int ret; - - ret = pkcs7_get_content_data(ctx->pkcs7, &content_data, &data_len, 1); - - if (ret) { - pr_debug("PKCS#7 message does not contain data\n"); - return ret; - } + struct pefile_context *ctx = _ctx; + content_data -= asn1hdrlen; + data_len += asn1hdrlen; pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len), content_data); @@ -129,7 +123,6 @@ int mscode_note_digest(void *context, size_t hdrlen, { struct pefile_context *ctx = context; - ctx->digest = value; - ctx->digest_len = vlen; - return 0; + ctx->digest = kmemdup(value, vlen, GFP_KERNEL); + return ctx->digest ? 0 : -ENOMEM; } diff --git a/crypto/asymmetric_keys/pkcs7_key_type.c b/crypto/asymmetric_keys/pkcs7_key_type.c index e2d0edbbc71a..3b92523882e5 100644 --- a/crypto/asymmetric_keys/pkcs7_key_type.c +++ b/crypto/asymmetric_keys/pkcs7_key_type.c @@ -13,12 +13,9 @@ #include <linux/key.h> #include <linux/err.h> #include <linux/module.h> +#include <linux/verification.h> #include <linux/key-type.h> -#include <keys/asymmetric-type.h> -#include <crypto/pkcs7.h> #include <keys/user-type.h> -#include <keys/system_keyring.h> -#include "pkcs7_parser.h" MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("PKCS#7 testing key type"); @@ -29,60 +26,47 @@ MODULE_PARM_DESC(pkcs7_usage, "Usage to specify when verifying the PKCS#7 message"); /* - * Preparse a PKCS#7 wrapped and validated data blob. + * Retrieve the PKCS#7 message content. */ -static int pkcs7_preparse(struct key_preparsed_payload *prep) +static int pkcs7_view_content(void *ctx, const void *data, size_t len, + size_t asn1hdrlen) { - enum key_being_used_for usage = pkcs7_usage; - struct pkcs7_message *pkcs7; - const void *data, *saved_prep_data; - size_t datalen, saved_prep_datalen; - bool trusted; + struct key_preparsed_payload *prep = ctx; + const void *saved_prep_data; + size_t saved_prep_datalen; int ret; - kenter(""); - - if (usage >= NR__KEY_BEING_USED_FOR) { - pr_err("Invalid usage type %d\n", usage); - return -EINVAL; - } - saved_prep_data = prep->data; saved_prep_datalen = prep->datalen; - pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen); - if (IS_ERR(pkcs7)) { - ret = PTR_ERR(pkcs7); - goto error; - } - - ret = pkcs7_verify(pkcs7, usage); - if (ret < 0) - goto error_free; - - ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted); - if (ret < 0) - goto error_free; - if (!trusted) - pr_warn("PKCS#7 message doesn't chain back to a trusted key\n"); - - ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false); - if (ret < 0) - goto error_free; - prep->data = data; - prep->datalen = datalen; + prep->datalen = len; + ret = user_preparse(prep); + prep->data = saved_prep_data; prep->datalen = saved_prep_datalen; - -error_free: - pkcs7_free_message(pkcs7); -error: - kleave(" = %d", ret); return ret; } /* + * Preparse a PKCS#7 wrapped and validated data blob. + */ +static int pkcs7_preparse(struct key_preparsed_payload *prep) +{ + enum key_being_used_for usage = pkcs7_usage; + + if (usage >= NR__KEY_BEING_USED_FOR) { + pr_err("Invalid usage type %d\n", usage); + return -EINVAL; + } + + return verify_pkcs7_signature(NULL, 0, + prep->data, prep->datalen, + NULL, usage, + pkcs7_view_content, prep); +} + +/* * user defined keys take an arbitrary string as the description and an * arbitrary blob of data as the payload */ diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 835701613125..af4cd8649117 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -168,24 +168,25 @@ EXPORT_SYMBOL_GPL(pkcs7_parse_message); * @pkcs7: The preparsed PKCS#7 message to access * @_data: Place to return a pointer to the data * @_data_len: Place to return the data length - * @want_wrapper: True if the ASN.1 object header should be included in the data + * @_headerlen: Size of ASN.1 header not included in _data * - * Get access to the data content of the PKCS#7 message, including, optionally, - * the header of the ASN.1 object that contains it. Returns -ENODATA if the - * data object was missing from the message. + * Get access to the data content of the PKCS#7 message. The size of the + * header of the ASN.1 object that contains it is also provided and can be used + * to adjust *_data and *_data_len to get the entire object. + * + * Returns -ENODATA if the data object was missing from the message. */ int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, const void **_data, size_t *_data_len, - bool want_wrapper) + size_t *_headerlen) { - size_t wrapper; - if (!pkcs7->data) return -ENODATA; - wrapper = want_wrapper ? pkcs7->data_hdrlen : 0; - *_data = pkcs7->data - wrapper; - *_data_len = pkcs7->data_len + wrapper; + *_data = pkcs7->data; + *_data_len = pkcs7->data_len; + if (_headerlen) + *_headerlen = pkcs7->data_hdrlen; return 0; } EXPORT_SYMBOL_GPL(pkcs7_get_content_data); diff --git a/crypto/asymmetric_keys/pkcs7_parser.h b/crypto/asymmetric_keys/pkcs7_parser.h index d5eec31e95b6..f4e81074f5e0 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.h +++ b/crypto/asymmetric_keys/pkcs7_parser.h @@ -22,7 +22,6 @@ struct pkcs7_signed_info { struct pkcs7_signed_info *next; struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ unsigned index; - bool trusted; bool unsupported_crypto; /* T if not usable due to missing crypto */ /* Message digest - the digest of the Content Data (or NULL) */ diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index b9a5487cd82d..f6a009d88a33 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -30,7 +30,6 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, struct public_key_signature *sig = sinfo->sig; struct x509_certificate *x509, *last = NULL, *p; struct key *key; - bool trusted; int ret; kenter(",%u,", sinfo->index); @@ -42,10 +41,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, for (x509 = sinfo->signer; x509; x509 = x509->signer) { if (x509->seen) { - if (x509->verified) { - trusted = x509->trusted; + if (x509->verified) goto verified; - } kleave(" = -ENOKEY [cached]"); return -ENOKEY; } @@ -54,9 +51,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, /* Look to see if this certificate is present in the trusted * keys. */ - key = x509_request_asymmetric_key(trust_keyring, - x509->id, x509->skid, - false); + key = find_asymmetric_key(trust_keyring, + x509->id, x509->skid, false); if (!IS_ERR(key)) { /* One of the X.509 certificates in the PKCS#7 message * is apparently the same as one we already trust. @@ -87,10 +83,10 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, * trusted keys. */ if (last && (last->sig->auth_ids[0] || last->sig->auth_ids[1])) { - key = x509_request_asymmetric_key(trust_keyring, - last->sig->auth_ids[0], - last->sig->auth_ids[1], - false); + key = find_asymmetric_key(trust_keyring, + last->sig->auth_ids[0], + last->sig->auth_ids[1], + false); if (!IS_ERR(key)) { x509 = last; pr_devel("sinfo %u: Root cert %u signer is key %x\n", @@ -104,10 +100,8 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, /* As a last resort, see if we have a trusted public key that matches * the signed info directly. */ - key = x509_request_asymmetric_key(trust_keyring, - sinfo->sig->auth_ids[0], - NULL, - false); + key = find_asymmetric_key(trust_keyring, + sinfo->sig->auth_ids[0], NULL, false); if (!IS_ERR(key)) { pr_devel("sinfo %u: Direct signer is key %x\n", sinfo->index, key_serial(key)); @@ -122,7 +116,6 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, matched: ret = verify_signature(key, sig); - trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags); key_put(key); if (ret < 0) { if (ret == -ENOMEM) @@ -134,12 +127,9 @@ matched: verified: if (x509) { x509->verified = true; - for (p = sinfo->signer; p != x509; p = p->signer) { + for (p = sinfo->signer; p != x509; p = p->signer) p->verified = true; - p->trusted = trusted; - } } - sinfo->trusted = trusted; kleave(" = 0"); return 0; } @@ -148,7 +138,6 @@ verified: * pkcs7_validate_trust - Validate PKCS#7 trust chain * @pkcs7: The PKCS#7 certificate to validate * @trust_keyring: Signing certificates to use as starting points - * @_trusted: Set to true if trustworth, false otherwise * * Validate that the certificate chain inside the PKCS#7 message intersects * keys we already know and trust. @@ -170,16 +159,13 @@ verified: * May also return -ENOMEM. */ int pkcs7_validate_trust(struct pkcs7_message *pkcs7, - struct key *trust_keyring, - bool *_trusted) + struct key *trust_keyring) { struct pkcs7_signed_info *sinfo; struct x509_certificate *p; int cached_ret = -ENOKEY; int ret; - *_trusted = false; - for (p = pkcs7->certs; p; p = p->next) p->seen = false; @@ -193,7 +179,6 @@ int pkcs7_validate_trust(struct pkcs7_message *pkcs7, cached_ret = -ENOPKG; continue; case 0: - *_trusted |= sinfo->trusted; cached_ret = 0; continue; default: diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c new file mode 100644 index 000000000000..ac4bddf669de --- /dev/null +++ b/crypto/asymmetric_keys/restrict.c @@ -0,0 +1,108 @@ +/* Instantiate a public key crypto key from an X.509 Certificate + * + * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#define pr_fmt(fmt) "ASYM: "fmt +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/err.h> +#include <crypto/public_key.h> +#include "asymmetric_keys.h" + +static bool use_builtin_keys; +static struct asymmetric_key_id *ca_keyid; + +#ifndef MODULE +static struct { + struct asymmetric_key_id id; + unsigned char data[10]; +} cakey; + +static int __init ca_keys_setup(char *str) +{ + if (!str) /* default system keyring */ + return 1; + + if (strncmp(str, "id:", 3) == 0) { + struct asymmetric_key_id *p = &cakey.id; + size_t hexlen = (strlen(str) - 3) / 2; + int ret; + + if (hexlen == 0 || hexlen > sizeof(cakey.data)) { + pr_err("Missing or invalid ca_keys id\n"); + return 1; + } + + ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen); + if (ret < 0) + pr_err("Unparsable ca_keys id hex string\n"); + else + ca_keyid = p; /* owner key 'id:xxxxxx' */ + } else if (strcmp(str, "builtin") == 0) { + use_builtin_keys = true; + } + + return 1; +} +__setup("ca_keys=", ca_keys_setup); +#endif + +/** + * restrict_link_by_signature - Restrict additions to a ring of public keys + * @trust_keyring: A ring of keys that can be used to vouch for the new cert. + * @type: The type of key being added. + * @payload: The payload of the new key. + * + * Check the new certificate against the ones in the trust keyring. If one of + * those is the signing key and validates the new certificate, then mark the + * new certificate as being trusted. + * + * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a + * matching parent certificate in the trusted list, -EKEYREJECTED if the + * signature check fails or the key is blacklisted and some other error if + * there is a matching certificate but the signature check cannot be performed. + */ +int restrict_link_by_signature(struct key *trust_keyring, + const struct key_type *type, + const union key_payload *payload) +{ + const struct public_key_signature *sig; + struct key *key; + int ret; + + pr_devel("==>%s()\n", __func__); + + if (!trust_keyring) + return -ENOKEY; + + if (type != &key_type_asymmetric) + return -EOPNOTSUPP; + + sig = payload->data[asym_auth]; + if (!sig->auth_ids[0] && !sig->auth_ids[1]) + return 0; + + if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) + return -EPERM; + + /* See if we have a key that signed this one. */ + key = find_asymmetric_key(trust_keyring, + sig->auth_ids[0], sig->auth_ids[1], + false); + if (IS_ERR(key)) + return -ENOKEY; + + if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags)) + ret = -ENOKEY; + else + ret = verify_signature(key, sig); + key_put(key); + return ret; +} diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 7e8c2338ae25..672a94c2c3ff 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -16,7 +16,7 @@ #include <linux/err.h> #include <linux/pe.h> #include <linux/asn1.h> -#include <crypto/pkcs7.h> +#include <linux/verification.h> #include <crypto/hash.h> #include "verify_pefile.h" @@ -392,9 +392,8 @@ error_no_desc: * verify_pefile_signature - Verify the signature on a PE binary image * @pebuf: Buffer containing the PE binary image * @pelen: Length of the binary image - * @trust_keyring: Signing certificates to use as starting points + * @trust_keys: Signing certificate(s) to use as starting points * @usage: The use to which the key is being put. - * @_trusted: Set to true if trustworth, false otherwise * * Validate that the certificate chain inside the PKCS#7 message inside the PE * binary image intersects keys we already know and trust. @@ -418,14 +417,10 @@ error_no_desc: * May also return -ENOMEM. */ int verify_pefile_signature(const void *pebuf, unsigned pelen, - struct key *trusted_keyring, - enum key_being_used_for usage, - bool *_trusted) + struct key *trusted_keys, + enum key_being_used_for usage) { - struct pkcs7_message *pkcs7; struct pefile_context ctx; - const void *data; - size_t datalen; int ret; kenter(""); @@ -439,19 +434,10 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen, if (ret < 0) return ret; - pkcs7 = pkcs7_parse_message(pebuf + ctx.sig_offset, ctx.sig_len); - if (IS_ERR(pkcs7)) - return PTR_ERR(pkcs7); - ctx.pkcs7 = pkcs7; - - ret = pkcs7_get_content_data(ctx.pkcs7, &data, &datalen, false); - if (ret < 0 || datalen == 0) { - pr_devel("PKCS#7 message does not contain data\n"); - ret = -EBADMSG; - goto error; - } - - ret = mscode_parse(&ctx); + ret = verify_pkcs7_signature(NULL, 0, + pebuf + ctx.sig_offset, ctx.sig_len, + trusted_keys, usage, + mscode_parse, &ctx); if (ret < 0) goto error; @@ -462,16 +448,8 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen, * contents. */ ret = pefile_digest_pe(pebuf, pelen, &ctx); - if (ret < 0) - goto error; - - ret = pkcs7_verify(pkcs7, usage); - if (ret < 0) - goto error; - - ret = pkcs7_validate_trust(pkcs7, trusted_keyring, _trusted); error: - pkcs7_free_message(ctx.pkcs7); + kfree(ctx.digest); return ret; } diff --git a/crypto/asymmetric_keys/verify_pefile.h b/crypto/asymmetric_keys/verify_pefile.h index a133eb81a492..cd4d20930728 100644 --- a/crypto/asymmetric_keys/verify_pefile.h +++ b/crypto/asymmetric_keys/verify_pefile.h @@ -9,7 +9,6 @@ * 2 of the Licence, or (at your option) any later version. */ -#include <linux/verify_pefile.h> #include <crypto/pkcs7.h> #include <crypto/hash_info.h> @@ -23,7 +22,6 @@ struct pefile_context { unsigned sig_offset; unsigned sig_len; const struct section_header *secs; - struct pkcs7_message *pkcs7; /* PKCS#7 MS Individual Code Signing content */ const void *digest; /* Digest */ @@ -39,4 +37,5 @@ struct pefile_context { /* * mscode_parser.c */ -extern int mscode_parse(struct pefile_context *ctx); +extern int mscode_parse(void *_ctx, const void *content_data, size_t data_len, + size_t asn1hdrlen); diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h index f24f4d808e7f..05eef1c68881 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -39,7 +39,6 @@ struct x509_certificate { unsigned index; bool seen; /* Infinite recursion prevention */ bool verified; - bool trusted; bool self_signed; /* T if self-signed (check unsupported_sig too) */ bool unsupported_key; /* T if key uses unsupported crypto */ bool unsupported_sig; /* T if signature uses unsupported crypto */ diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index fc77a2bd70ba..fb732296cd36 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -20,133 +20,6 @@ #include "asymmetric_keys.h" #include "x509_parser.h" -static bool use_builtin_keys; -static struct asymmetric_key_id *ca_keyid; - -#ifndef MODULE -static struct { - struct asymmetric_key_id id; - unsigned char data[10]; -} cakey; - -static int __init ca_keys_setup(char *str) -{ - if (!str) /* default system keyring */ - return 1; - - if (strncmp(str, "id:", 3) == 0) { - struct asymmetric_key_id *p = &cakey.id; - size_t hexlen = (strlen(str) - 3) / 2; - int ret; - - if (hexlen == 0 || hexlen > sizeof(cakey.data)) { - pr_err("Missing or invalid ca_keys id\n"); - return 1; - } - - ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen); - if (ret < 0) - pr_err("Unparsable ca_keys id hex string\n"); - else - ca_keyid = p; /* owner key 'id:xxxxxx' */ - } else if (strcmp(str, "builtin") == 0) { - use_builtin_keys = true; - } - - return 1; -} -__setup("ca_keys=", ca_keys_setup); -#endif - -/** - * x509_request_asymmetric_key - Request a key by X.509 certificate params. - * @keyring: The keys to search. - * @id: The issuer & serialNumber to look for or NULL. - * @skid: The subjectKeyIdentifier to look for or NULL. - * @partial: Use partial match if true, exact if false. - * - * Find a key in the given keyring by identifier. The preferred identifier is - * the issuer + serialNumber and the fallback identifier is the - * subjectKeyIdentifier. If both are given, the lookup is by the former, but - * the latter must also match. - */ -struct key *x509_request_asymmetric_key(struct key *keyring, - const struct asymmetric_key_id *id, - const struct asymmetric_key_id *skid, - bool partial) -{ - struct key *key; - key_ref_t ref; - const char *lookup; - char *req, *p; - int len; - - if (id) { - lookup = id->data; - len = id->len; - } else { - lookup = skid->data; - len = skid->len; - } - - /* Construct an identifier "id:<keyid>". */ - p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); - if (!req) - return ERR_PTR(-ENOMEM); - - if (partial) { - *p++ = 'i'; - *p++ = 'd'; - } else { - *p++ = 'e'; - *p++ = 'x'; - } - *p++ = ':'; - p = bin2hex(p, lookup, len); - *p = 0; - - pr_debug("Look up: \"%s\"\n", req); - - ref = keyring_search(make_key_ref(keyring, 1), - &key_type_asymmetric, req); - if (IS_ERR(ref)) - pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); - kfree(req); - - if (IS_ERR(ref)) { - switch (PTR_ERR(ref)) { - /* Hide some search errors */ - case -EACCES: - case -ENOTDIR: - case -EAGAIN: - return ERR_PTR(-ENOKEY); - default: - return ERR_CAST(ref); - } - } - - key = key_ref_to_ptr(ref); - if (id && skid) { - const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); - if (!kids->id[1]) { - pr_debug("issuer+serial match, but expected SKID missing\n"); - goto reject; - } - if (!asymmetric_key_id_same(skid, kids->id[1])) { - pr_debug("issuer+serial match, but SKID does not\n"); - goto reject; - } - } - - pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); - return key; - -reject: - key_put(key); - return ERR_PTR(-EKEYREJECTED); -} -EXPORT_SYMBOL_GPL(x509_request_asymmetric_key); - /* * Set up the signature parameters in an X.509 certificate. This involves * digesting the signed data and extracting the signature. @@ -277,49 +150,6 @@ not_self_signed: } /* - * Check the new certificate against the ones in the trust keyring. If one of - * those is the signing key and validates the new certificate, then mark the - * new certificate as being trusted. - * - * Return 0 if the new certificate was successfully validated, 1 if we couldn't - * find a matching parent certificate in the trusted list and an error if there - * is a matching certificate but the signature check fails. - */ -static int x509_validate_trust(struct x509_certificate *cert, - struct key *trust_keyring) -{ - struct public_key_signature *sig = cert->sig; - struct key *key; - int ret = 1; - - if (!sig->auth_ids[0] && !sig->auth_ids[1]) - return 1; - - if (!trust_keyring) - return -EOPNOTSUPP; - if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) - return -EPERM; - if (cert->unsupported_sig) - return -ENOPKG; - - key = x509_request_asymmetric_key(trust_keyring, - sig->auth_ids[0], sig->auth_ids[1], - false); - if (IS_ERR(key)) - return PTR_ERR(key); - - if (!use_builtin_keys || - test_bit(KEY_FLAG_BUILTIN, &key->flags)) { - ret = public_key_verify_signature( - key->payload.data[asym_crypto], cert->sig); - if (ret == -ENOPKG) - cert->unsupported_sig = true; - } - key_put(key); - return ret; -} - -/* * Attempt to parse a data blob for a key as an X509 certificate. */ static int x509_key_preparse(struct key_preparsed_payload *prep) @@ -348,31 +178,12 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) cert->pub->id_type = "X509"; - /* See if we can derive the trustability of this certificate. - * - * When it comes to self-signed certificates, we cannot evaluate - * trustedness except by the fact that we obtained it from a trusted - * location. So we just rely on x509_validate_trust() failing in this - * case. - * - * Note that there's a possibility of a self-signed cert matching a - * cert that we have (most likely a duplicate that we already trust) - - * in which case it will be marked trusted. - */ - if (cert->unsupported_sig || cert->self_signed) { + if (cert->unsupported_sig) { public_key_signature_free(cert->sig); cert->sig = NULL; } else { pr_devel("Cert Signature: %s + %s\n", cert->sig->pkey_algo, cert->sig->hash_algo); - - ret = x509_validate_trust(cert, get_system_trusted_keyring()); - if (ret) - ret = x509_validate_trust(cert, get_ima_mok_keyring()); - if (ret == -EKEYREJECTED) - goto error_free_cert; - if (!ret) - prep->trusted = true; } /* Propose a description */ |