[v6,3/6] KEYS: Restrict key linkage using a specific keychain
diff mbox

Message ID 20160721233139.4085-4-mathew.j.martineau@linux.intel.com
State New
Headers show

Commit Message

Mat Martineau July 21, 2016, 11:31 p.m. UTC
Adds restrict_link_by_signature_keyring(), which uses the restrict_key
member of the provided destination_keyring data structure as the
keyring to search for signing keys.

Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
---
 crypto/asymmetric_keys/restrict.c | 55 +++++++++++++++++++++++++++++++++++++++
 include/crypto/public_key.h       |  4 +++
 2 files changed, 59 insertions(+)

Patch
diff mbox

diff --git a/crypto/asymmetric_keys/restrict.c b/crypto/asymmetric_keys/restrict.c
index ac4bddf..d6985f8 100644
--- a/crypto/asymmetric_keys/restrict.c
+++ b/crypto/asymmetric_keys/restrict.c
@@ -106,3 +106,58 @@  int restrict_link_by_signature(struct key *trust_keyring,
 	key_put(key);
 	return ret;
 }
+
+/**
+ * restrict_link_by_keyring - Restrict additions to a ring of public
+ * keys using the restrict_key information stored in the ring.
+ * @destination_keyring: Keyring being linked to.
+ * @type: The type of key being added.
+ * @payload: The payload of the new key.
+ *
+ * Check the new certificate only against the keys in the
+ * destination_keyring->restrict_key ring. 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_keyring(struct key *destination_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 (!destination_keyring)
+		return -ENOKEY;
+	else if (destination_keyring->type != &key_type_keyring)
+		return -EOPNOTSUPP;
+
+	if (!destination_keyring->restrict_key)
+		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;
+
+	/* See if we have a key that signed this one. */
+	key = find_asymmetric_key(destination_keyring->restrict_key,
+				  sig->auth_ids[0], sig->auth_ids[1],
+				  false);
+	if (IS_ERR(key))
+		return -ENOKEY;
+
+	ret = verify_signature(key, sig);
+	key_put(key);
+	return ret;
+}
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index c5e569b..53e8928 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -58,6 +58,10 @@  extern int restrict_link_by_signature(struct key *trust_keyring,
 				      const struct key_type *type,
 				      const union key_payload *payload);
 
+extern int restrict_link_by_keyring(struct key *trust_keyring,
+				    const struct key_type *type,
+				    const union key_payload *payload);
+
 extern int query_asymmetric_key(const struct kernel_pkey_params *,
 				struct kernel_pkey_query *);