summaryrefslogtreecommitdiff
path: root/crypto/asymmetric_keys
diff options
context:
space:
mode:
authorMat Martineau <mathew.j.martineau@linux.intel.com>2016-06-27 16:45:16 -0700
committerMat Martineau <mathew.j.martineau@linux.intel.com>2017-04-04 14:10:13 -0700
commit7e3c4d22083f6e7316c5229b6197ca2d5335aa35 (patch)
tree5d8a79bfb32d3bb082ff2cffb8deba4ab588bb87 /crypto/asymmetric_keys
parent97d3aa0f313435a24440e7157c9c9115c58ca463 (diff)
KEYS: Restrict asymmetric key linkage using a specific keychain
Adds restrict_link_by_signature_keyring(), which uses the restrict_key member of the provided destination_keyring data structure as the key or keyring to search for signing keys. Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c35
-rw-r--r--crypto/asymmetric_keys/restrict.c71
2 files changed, 105 insertions, 1 deletions
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 2e3380d09631..72700ed81594 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -475,6 +475,11 @@ static struct key_restriction *asymmetric_restriction_alloc(
static struct key_restriction *asymmetric_lookup_restriction(
const char *restriction)
{
+ char *restrict_method;
+ char *parse_buf;
+ char *next;
+ struct key_restriction *ret = ERR_PTR(-EINVAL);
+
if (strcmp("builtin_trusted", restriction) == 0)
return asymmetric_restriction_alloc(
restrict_link_by_builtin_trusted, NULL);
@@ -483,7 +488,35 @@ static struct key_restriction *asymmetric_lookup_restriction(
return asymmetric_restriction_alloc(
restrict_link_by_builtin_and_secondary_trusted, NULL);
- return ERR_PTR(-EINVAL);
+ parse_buf = kstrndup(restriction, PAGE_SIZE, GFP_KERNEL);
+ if (!parse_buf)
+ return ERR_PTR(-ENOMEM);
+
+ next = parse_buf;
+ restrict_method = strsep(&next, ":");
+
+ if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) {
+ key_serial_t serial;
+ struct key *key;
+
+ if (kstrtos32(next, 0, &serial) < 0)
+ goto out;
+
+ key = key_lookup(serial);
+ if (IS_ERR(key)) {
+ ret = ERR_CAST(key);
+ goto out;
+ }
+
+ ret = asymmetric_restriction_alloc(
+ restrict_link_by_key_or_keyring, key);
+ if (IS_ERR(ret))
+ key_put(key);
+ }
+
+out:
+ kfree(parse_buf);
+ return ret;
}
struct key_type key_type_asymmetric = {
diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c
index a3afbf783255..183cb642580e 100644
--- a/crypto/asymmetric_keys/restrict.c
+++ b/crypto/asymmetric_keys/restrict.c
@@ -108,3 +108,74 @@ int restrict_link_by_signature(struct key *dest_keyring,
key_put(key);
return ret;
}
+
+/**
+ * restrict_link_by_key_or_keyring - Restrict additions to a ring of public
+ * keys using the restrict_key information stored in the ring.
+ * @dest_keyring: Keyring being linked to.
+ * @type: The type of key being added.
+ * @payload: The payload of the new key.
+ * @trusted: A key or ring of keys that can be used to vouch for the new cert.
+ *
+ * Check the new certificate only against the key or keys passed in the data
+ * parameter. If one of those is the signing key and validates the new
+ * certificate, then mark the new certificate as being ok to link.
+ *
+ * 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, and some other error if
+ * there is a matching certificate but the signature check cannot be
+ * performed.
+ */
+int restrict_link_by_key_or_keyring(struct key *dest_keyring,
+ const struct key_type *type,
+ const union key_payload *payload,
+ struct key *trusted)
+{
+ const struct public_key_signature *sig;
+ struct key *key;
+ int ret;
+
+ pr_devel("==>%s()\n", __func__);
+
+ if (!dest_keyring)
+ return -ENOKEY;
+ else if (dest_keyring->type != &key_type_keyring)
+ return -EOPNOTSUPP;
+
+ if (!trusted)
+ return -ENOKEY;
+
+ if (type != &key_type_asymmetric)
+ return -EOPNOTSUPP;
+
+ sig = payload->data[asym_auth];
+ if (!sig->auth_ids[0] && !sig->auth_ids[1])
+ return -ENOKEY;
+
+ if (trusted->type == &key_type_keyring) {
+ /* See if we have a key that signed this one. */
+ key = find_asymmetric_key(trusted, sig->auth_ids[0],
+ sig->auth_ids[1], false);
+ if (IS_ERR(key))
+ return -ENOKEY;
+ } else if (trusted->type == &key_type_asymmetric) {
+ const struct asymmetric_key_ids *kids;
+
+ kids = asymmetric_key_ids(trusted);
+
+ if (!asymmetric_key_id_same(kids->id[1], sig->auth_ids[0]))
+ return -ENOKEY;
+
+ key = __key_get(trusted);
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ ret = key_validate(key);
+ if (ret == 0)
+ ret = verify_signature(key, sig);
+
+ key_put(key);
+ return ret;
+}