diff options
Diffstat (limited to 'security/integrity/digsig_asymmetric.c')
| -rw-r--r-- | security/integrity/digsig_asymmetric.c | 86 |
1 files changed, 52 insertions, 34 deletions
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index b4754667659d..457c0a396caf 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -1,36 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2013 Intel Corporation * * Author: * Dmitry Kasatkin <dmitry.kasatkin@intel.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/err.h> +#include <linux/ratelimit.h> #include <linux/key-type.h> #include <crypto/public_key.h> +#include <crypto/hash_info.h> #include <keys/asymmetric-type.h> +#include <keys/system_keyring.h> #include "integrity.h" /* - * signature format v2 - for using with asymmetric keys - */ -struct signature_v2_hdr { - uint8_t version; /* signature format version */ - uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */ - uint32_t keyid; /* IMA key identifier - not X509/PGP specific*/ - uint16_t sig_size; /* signature size */ - uint8_t sig[0]; /* signature payload */ -} __packed; - -/* * Request an asymmetric key. */ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) @@ -38,15 +24,28 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) struct key *key; char name[12]; - sprintf(name, "id:%x", keyid); + sprintf(name, "id:%08x", keyid); pr_debug("key search: \"%s\"\n", name); + key = get_ima_blacklist_keyring(); + if (key) { + key_ref_t kref; + + kref = keyring_search(make_key_ref(key, 1), + &key_type_asymmetric, name, true); + if (!IS_ERR(kref)) { + pr_err("Key '%s' is in ima_blacklist_keyring\n", name); + return ERR_PTR(-EKEYREJECTED); + } + } + if (keyring) { /* search in specific keyring */ key_ref_t kref; + kref = keyring_search(make_key_ref(keyring, 1), - &key_type_asymmetric, name); + &key_type_asymmetric, name, true); if (IS_ERR(kref)) key = ERR_CAST(kref); else @@ -56,8 +55,14 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) } if (IS_ERR(key)) { - pr_warn("Request for unknown key '%s' err %ld\n", - name, PTR_ERR(key)); + if (keyring) + pr_err_ratelimited("Request for unknown key '%s' in '%s' keyring. err %ld\n", + name, keyring->description, + PTR_ERR(key)); + else + pr_err_ratelimited("Request for unknown key '%s' err %ld\n", + name, PTR_ERR(key)); + switch (PTR_ERR(key)) { /* Hide some search errors */ case -EACCES: @@ -79,36 +84,49 @@ int asymmetric_verify(struct key *keyring, const char *sig, { struct public_key_signature pks; struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig; + const struct public_key *pk; struct key *key; - int ret = -ENOMEM; + int ret; if (siglen <= sizeof(*hdr)) return -EBADMSG; siglen -= sizeof(*hdr); - if (siglen != __be16_to_cpu(hdr->sig_size)) + if (siglen != be16_to_cpu(hdr->sig_size)) return -EBADMSG; - if (hdr->hash_algo >= PKEY_HASH__LAST) + if (hdr->hash_algo >= HASH_ALGO__LAST) return -ENOPKG; - key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid)); + key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid)); if (IS_ERR(key)) return PTR_ERR(key); memset(&pks, 0, sizeof(pks)); - pks.pkey_hash_algo = hdr->hash_algo; + pks.hash_algo = hash_algo_name[hdr->hash_algo]; + + pk = asymmetric_key_public_key(key); + pks.pkey_algo = pk->pkey_algo; + if (!strcmp(pk->pkey_algo, "rsa")) { + pks.encoding = "pkcs1"; + } else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) { + /* edcsa-nist-p192 etc. */ + pks.encoding = "x962"; + } else if (!strcmp(pk->pkey_algo, "ecrdsa")) { + pks.encoding = "raw"; + } else { + ret = -ENOPKG; + goto out; + } + pks.digest = (u8 *)data; pks.digest_size = datalen; - pks.nr_mpi = 1; - pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen); - - if (pks.rsa.s) - ret = verify_signature(key, &pks); - - mpi_free(pks.rsa.s); + pks.s = hdr->sig; + pks.s_size = siglen; + ret = verify_signature(key, &pks); +out: key_put(key); pr_debug("%s() = %d\n", __func__, ret); return ret; |
