linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC PKS/Trusted keys 0/2] trusted keys: Add PKS protection to trusted keys
@ 2020-10-09 20:14 ira.weiny
  2020-10-09 20:14 ` [PATCH RFC PKS/Trusted keys 1/2] vmalloc: Add vmalloc_pks() call ira.weiny
  2020-10-09 20:14 ` [PATCH RFC PKS/Trusted keys 2/2] keys/trusted: protect trusted keys using PKS ira.weiny
  0 siblings, 2 replies; 3+ messages in thread
From: ira.weiny @ 2020-10-09 20:14 UTC (permalink / raw)
  To: Jonathan Corbet, David Howells, Andrew Morton, James Bottomley,
	Mike Rapoport
  Cc: Ira Weiny, Dave Hansen, Dan Williams, Fenghua Yu, linux-doc,
	linux-kernel, linux-mm, open list:KEYS-TRUSTED,
	open list:KEYS-TRUSTED, open list:SECURITY SUBSYSTEM

From: Ira Weiny <ira.weiny@intel.com>

Leaking a trusted key would be a critical security issue.  PKS provides an
additional mechanism to restrict access to the memory holding trusted keys.

This series depends on the core patches and PMEM PKS API change submitted
separately.

	Core PKS support:
	https://lore.kernel.org/lkml/20201009194258.3207172-1-ira.weiny@intel.com/

	PKS/PMEM support (includes global API change):
	https://lore.kernel.org/lkml/20201009195033.3208459-1-ira.weiny@intel.com/

And contained in the git tree here:

	https://github.com/weiny2/linux-kernel/tree/pks-rfc-v3


Provide a skeleton of a new allocation call which provides a PKS restricted
mapping of the trusted key memory.  Allocate a PKS domain (pkey), create a
mapping with that key, and enable/disable access as needed to that mapping.

The issue with this approach is that it fails to protect the direct mapping.
The current ideas to protect the direct mapping are:

	1) Do nothing.
	2) Allow the direct map to be fragmented through a set_memory_pks() like call.
	3) Piggy back on secretmem's solution to map out some direct map memory
	   then overlay that with PKS.
	4) Integrate PKS into secretmem and use this enhanced secretmem for
	   trusted keys.

Doing nothing is not really providing the level of security we need for this
use case.

Allowing the direct map to fragment may be ok as trusted keys don't use a lot
of pages and are usually allocated early in the system boot but that is not
always the case.  In addition the current code could be made
to not allocating an entire page for each key to limit the number of pages, and
therfore the fragmentation, needed.

The use of secretmem is complicated by its newness but whatever solution is
used there should be used here.  And probalby through some nice interface.

The final thought is to determine if a 'general allocator' for PKS protected
memory should be developed at all.  The current implementation is limited in
key space and so a higher bar to entry may be a good thing.  On the other hand,
dealing with mappings for the average driver writer is complicated and doing
this wrong could result in a false sense of 'security'.


Elena Reshetova (1):
  keys/trusted: protect trusted keys using PKS

Ira Weiny (1):
  vmalloc: Add vmalloc_pks() call

 Documentation/core-api/protection-keys.rst |  4 +
 include/keys/trusted-type.h                |  2 +-
 include/keys/trusted_tpm.h                 | 15 ++++
 include/linux/vmalloc.h                    |  1 +
 mm/vmalloc.c                               | 28 +++++++
 security/keys/encrypted-keys/encrypted.c   | 38 ++++++---
 security/keys/trusted-keys/trusted_tpm1.c  | 90 +++++++++++++++++++---
 security/keys/trusted-keys/trusted_tpm2.c  |  9 +++
 8 files changed, 164 insertions(+), 23 deletions(-)

-- 
2.28.0.rc0.12.gb6a658bd00c9


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH RFC PKS/Trusted keys 1/2] vmalloc: Add vmalloc_pks() call
  2020-10-09 20:14 [PATCH RFC PKS/Trusted keys 0/2] trusted keys: Add PKS protection to trusted keys ira.weiny
@ 2020-10-09 20:14 ` ira.weiny
  2020-10-09 20:14 ` [PATCH RFC PKS/Trusted keys 2/2] keys/trusted: protect trusted keys using PKS ira.weiny
  1 sibling, 0 replies; 3+ messages in thread
From: ira.weiny @ 2020-10-09 20:14 UTC (permalink / raw)
  To: Jonathan Corbet, David Howells, Andrew Morton, James Bottomley,
	Mike Rapoport
  Cc: Ira Weiny, Dave Hansen, Dan Williams, Fenghua Yu, linux-doc,
	linux-kernel, linux-mm, open list:KEYS-TRUSTED,
	open list:KEYS-TRUSTED, open list:SECURITY SUBSYSTEM

From: Ira Weiny <ira.weiny@intel.com>

Add a vmalloc call which allocates and creates a new mapping with the
specified pkey in the mapping.

This is currently a placeholder for the idea of an interface.  This
does not attempt to update the direct map and as such leaves access via
that map open.  Protecting that map would potentially fragment the
direct map.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>
---
 Documentation/core-api/protection-keys.rst |  4 ++++
 include/linux/vmalloc.h                    |  1 +
 mm/vmalloc.c                               | 28 ++++++++++++++++++++++
 3 files changed, 33 insertions(+)

diff --git a/Documentation/core-api/protection-keys.rst b/Documentation/core-api/protection-keys.rst
index 9e8a98653e13..574c88f45830 100644
--- a/Documentation/core-api/protection-keys.rst
+++ b/Documentation/core-api/protection-keys.rst
@@ -121,6 +121,7 @@ mapping adds that mapping to the protection domain.
         int pks_key_alloc(const char * const pkey_user);
         #define PAGE_KERNEL_PKEY(pkey)
         #define _PAGE_KEY(pkey)
+        void * vmalloc_pks(unsigned long size, int pkey);
         void pks_mknoaccess(int pkey, bool global);
         void pks_mkread(int pkey, bool global);
         void pks_mkrdwr(int pkey, bool global);
@@ -138,6 +139,9 @@ Kernel users must set the PTE permissions in the page table entries for the
 mappings they want to protect.  This can be done with PAGE_KERNEL_PKEY() or
 _PAGE_KEY().
 
+Alternatively, vmalloc_pks() is provided to allocate memory within the pkey
+domain specified.
+
 The pks_mk*() family of calls allows kernel users the ability to change the
 protections for the domain identified by the pkey specified.  3 states are
 available pks_mknoaccess(), pks_mkread(), and pks_mkrdwr() which set the access
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 0221f852a7e1..f5aa1d54b9b7 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -115,6 +115,7 @@ extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
 			const void *caller);
 void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask,
 		int node, const void *caller);
+extern void *vmalloc_pks(unsigned long size, int pkey);
 
 extern void vfree(const void *addr);
 extern void vfree_atomic(const void *addr);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index be4724b916b3..8cc973a968c4 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2589,6 +2589,34 @@ void *vmalloc(unsigned long size)
 }
 EXPORT_SYMBOL(vmalloc);
 
+/**
+ * vmalloc_pks - allocate virtually contiguous memory within the specified pkey
+ * domain
+ *
+ * @size:     allocation size
+ * @pkey:     the pkey domain to allocate the memory under
+ *
+ * Allocate enough pages to cover @size from the page level allocator and map
+ * them into contiguous kernel virtual space with the specific PKS protections
+ * if the architecture supports it.
+ *
+ * NOTE: This does not change the PKS settings established with other mappings
+ * such as the direct map.
+ *
+ * WARNING: Calling this with an invalid pkey is undefined.
+ *
+ * Return: pointer to the allocated memory or %NULL on error
+ */
+void *vmalloc_pks(unsigned long size, int pkey)
+{
+	void *ret = __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
+					 GFP_KERNEL, PAGE_KERNEL_PKEY(pkey), 0,
+					 NUMA_NO_NODE, __builtin_return_address(0));
+	vm_unmap_aliases();
+	return ret;
+}
+EXPORT_SYMBOL(vmalloc_pks);
+
 /**
  * vzalloc - allocate virtually contiguous memory with zero fill
  * @size:    allocation size
-- 
2.28.0.rc0.12.gb6a658bd00c9


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH RFC PKS/Trusted keys 2/2] keys/trusted: protect trusted keys using PKS
  2020-10-09 20:14 [PATCH RFC PKS/Trusted keys 0/2] trusted keys: Add PKS protection to trusted keys ira.weiny
  2020-10-09 20:14 ` [PATCH RFC PKS/Trusted keys 1/2] vmalloc: Add vmalloc_pks() call ira.weiny
@ 2020-10-09 20:14 ` ira.weiny
  1 sibling, 0 replies; 3+ messages in thread
From: ira.weiny @ 2020-10-09 20:14 UTC (permalink / raw)
  To: Jonathan Corbet, David Howells, Andrew Morton, James Bottomley,
	Mike Rapoport
  Cc: Elena Reshetova, Ira Weiny, Dave Hansen, Dan Williams,
	Fenghua Yu, linux-doc, linux-kernel, linux-mm,
	open list:KEYS-TRUSTED, open list:KEYS-TRUSTED,
	open list:SECURITY SUBSYSTEM

From: Elena Reshetova <elena.reshetova@intel.com>

Enable additional protection for trusted keys against arbitrary reads
using Protection Keys Supervisor (PKS) feature on architectures which
support it.  PKS feature allows different 'domains' of page mappings
which have an extra level of protection beyond those specified in the
supervisor page table entries. Pages can be placed into such a 'domain'
upon allocation and the access to them is enforced based on the
per-thread per-CPU granularity.

The PKS protection 'domain' is acquired upon TPM initialization and, if
successful, will be used to limit access (both read and write) to pages
containing trusted key plaintext buffer. When a legitimate operation needs
to be performed on this buffer, the access to it is temporally enabled
for a particular thread on a particular CPU.

This is not a perfect solution, but a first step towards providing an
additional protection for the trusted keys residing in the kernel
memory.  Currently, it still does not prevent direct map aliased
attacks, i.e.  when the page with the key content is accessed via the
kernel direct map directly.  In order to address this concern, future
work could utilize PKS in secretmem[1] and/or secretment in trusted
keys.  For this patch, we are focused on just using PKS to remove the
non-direct map alias access to this key data when not needed.

In order to limit access to the pages containing the trusted key
plaintext buffer, trusted_key_enable/disable_access functions are used.
The "disable" function removes access (both read and write) to the pages
allocated for the trusted keys PKS 'domain' on a given CPU and for the
given thread, and the "enable" one enables read and write access on a
given CPU and for the given thread. By default the access to the trusted
keys PKS 'domain' is disabled for all threads on all CPUs.

[1] https://lore.kernel.org/linux-mm/20200924132904.1391-1-rppt@kernel.org/

Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
---
 include/keys/trusted-type.h               |  2 +-
 include/keys/trusted_tpm.h                | 15 ++++
 security/keys/encrypted-keys/encrypted.c  | 38 +++++++---
 security/keys/trusted-keys/trusted_tpm1.c | 90 ++++++++++++++++++++---
 security/keys/trusted-keys/trusted_tpm2.c |  9 +++
 5 files changed, 131 insertions(+), 23 deletions(-)

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index a94c03a61d8f..826525e22b45 100644
--- a/include/keys/trusted-type.h
+++ b/include/keys/trusted-type.h
@@ -22,7 +22,7 @@ struct trusted_key_payload {
 	unsigned int key_len;
 	unsigned int blob_len;
 	unsigned char migratable;
-	unsigned char key[MAX_KEY_SIZE + 1];
+	unsigned char  *key;
 	unsigned char blob[MAX_BLOB_SIZE];
 };
 
diff --git a/include/keys/trusted_tpm.h b/include/keys/trusted_tpm.h
index a56d8e1298f2..5aa254c70820 100644
--- a/include/keys/trusted_tpm.h
+++ b/include/keys/trusted_tpm.h
@@ -47,6 +47,21 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
 			struct trusted_key_payload *payload,
 			struct trusted_key_options *options);
 
+#if defined(CONFIG_TRUSTED_KEYS) || \
+	(defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE))
+void trusted_key_enable_access(void);
+void trusted_key_disable_access(void);
+#else
+static inline void trusted_key_enable_access(void)
+{
+
+}
+static inline void trusted_key_disable_access(void)
+{
+
+}
+#endif
+
 #define TPM_DEBUG 0
 
 #if TPM_DEBUG
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 192e531c146f..d996e9fd2dec 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -20,6 +20,7 @@
 #include <linux/err.h>
 #include <keys/user-type.h>
 #include <keys/trusted-type.h>
+#include <keys/trusted_tpm.h>
 #include <keys/encrypted-type.h>
 #include <linux/key-type.h>
 #include <linux/random.h>
@@ -344,10 +345,12 @@ static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen,
 }
 
 enum derived_key_type { ENC_KEY, AUTH_KEY };
+enum master_key_type { TRUSTED_KEY, USER_KEY };
 
 /* Derive authentication/encryption key from trusted key */
 static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
-			   const u8 *master_key, size_t master_keylen)
+			   const u8 *master_key, size_t master_keylen,
+			   enum master_key_type m_key_type)
 {
 	u8 *derived_buf;
 	unsigned int derived_buf_len;
@@ -366,8 +369,13 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
 	else
 		strcpy(derived_buf, "ENC_KEY");
 
+	if (unlikely(m_key_type == TRUSTED_KEY))
+		trusted_key_enable_access();
 	memcpy(derived_buf + strlen(derived_buf) + 1, master_key,
 	       master_keylen);
+	if (unlikely(m_key_type == TRUSTED_KEY))
+		trusted_key_disable_access();
+
 	ret = crypto_shash_tfm_digest(hash_tfm, derived_buf, derived_buf_len,
 				      derived_key);
 	kfree_sensitive(derived_buf);
@@ -408,7 +416,8 @@ static struct skcipher_request *init_skcipher_req(const u8 *key,
 }
 
 static struct key *request_master_key(struct encrypted_key_payload *epayload,
-				      const u8 **master_key, size_t *master_keylen)
+				      const u8 **master_key, size_t *master_keylen,
+				      enum master_key_type *m_key_type)
 {
 	struct key *mkey = ERR_PTR(-EINVAL);
 
@@ -417,11 +426,13 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload,
 		mkey = request_trusted_key(epayload->master_desc +
 					   KEY_TRUSTED_PREFIX_LEN,
 					   master_key, master_keylen);
+		*m_key_type = TRUSTED_KEY;
 	} else if (!strncmp(epayload->master_desc, KEY_USER_PREFIX,
 			    KEY_USER_PREFIX_LEN)) {
 		mkey = request_user_key(epayload->master_desc +
 					KEY_USER_PREFIX_LEN,
 					master_key, master_keylen);
+		*m_key_type = USER_KEY;
 	} else
 		goto out;
 
@@ -486,13 +497,14 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,
 }
 
 static int datablob_hmac_append(struct encrypted_key_payload *epayload,
-				const u8 *master_key, size_t master_keylen)
+				const u8 *master_key, size_t master_keylen,
+				enum master_key_type m_key_type)
 {
 	u8 derived_key[HASH_SIZE];
 	u8 *digest;
 	int ret;
 
-	ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen);
+	ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen, m_key_type);
 	if (ret < 0)
 		goto out;
 
@@ -509,7 +521,7 @@ static int datablob_hmac_append(struct encrypted_key_payload *epayload,
 /* verify HMAC before decrypting encrypted key */
 static int datablob_hmac_verify(struct encrypted_key_payload *epayload,
 				const u8 *format, const u8 *master_key,
-				size_t master_keylen)
+				size_t master_keylen, enum master_key_type m_key_type)
 {
 	u8 derived_key[HASH_SIZE];
 	u8 digest[HASH_SIZE];
@@ -517,7 +529,7 @@ static int datablob_hmac_verify(struct encrypted_key_payload *epayload,
 	char *p;
 	unsigned short len;
 
-	ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen);
+	ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen, m_key_type);
 	if (ret < 0)
 		goto out;
 
@@ -664,6 +676,7 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
 	size_t master_keylen;
 	size_t asciilen;
 	int ret;
+	enum master_key_type m_key_type;
 
 	encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
 	asciilen = (ivsize + 1 + encrypted_datalen + HASH_SIZE) * 2;
@@ -685,17 +698,17 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
 	if (ret < 0)
 		return -EINVAL;
 
-	mkey = request_master_key(epayload, &master_key, &master_keylen);
+	mkey = request_master_key(epayload, &master_key, &master_keylen, &m_key_type);
 	if (IS_ERR(mkey))
 		return PTR_ERR(mkey);
 
-	ret = datablob_hmac_verify(epayload, format, master_key, master_keylen);
+	ret = datablob_hmac_verify(epayload, format, master_key, master_keylen, m_key_type);
 	if (ret < 0) {
 		pr_err("encrypted_key: bad hmac (%d)\n", ret);
 		goto out;
 	}
 
-	ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen);
+	ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen, m_key_type);
 	if (ret < 0)
 		goto out;
 
@@ -908,6 +921,7 @@ static long encrypted_read(const struct key *key, char *buffer,
 	char *ascii_buf;
 	size_t asciiblob_len;
 	int ret;
+	enum master_key_type m_key_type;
 
 	epayload = dereference_key_locked(key);
 
@@ -919,11 +933,11 @@ static long encrypted_read(const struct key *key, char *buffer,
 	if (!buffer || buflen < asciiblob_len)
 		return asciiblob_len;
 
-	mkey = request_master_key(epayload, &master_key, &master_keylen);
+	mkey = request_master_key(epayload, &master_key, &master_keylen, &m_key_type);
 	if (IS_ERR(mkey))
 		return PTR_ERR(mkey);
 
-	ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen);
+	ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen, m_key_type);
 	if (ret < 0)
 		goto out;
 
@@ -931,7 +945,7 @@ static long encrypted_read(const struct key *key, char *buffer,
 	if (ret < 0)
 		goto out;
 
-	ret = datablob_hmac_append(epayload, master_key, master_keylen);
+	ret = datablob_hmac_append(epayload, master_key, master_keylen, m_key_type);
 	if (ret < 0)
 		goto out;
 
diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c
index b9fe02e5f84f..62e6c5eb8e2b 100644
--- a/security/keys/trusted-keys/trusted_tpm1.c
+++ b/security/keys/trusted-keys/trusted_tpm1.c
@@ -26,9 +26,49 @@
 #include <linux/capability.h>
 #include <linux/tpm.h>
 #include <linux/tpm_command.h>
+#include <linux/pkeys.h>
+#include <linux/vmalloc.h>
+#include <uapi/asm-generic/mman-common.h>
 
 #include <keys/trusted_tpm.h>
 
+#define PKEY_INVALID (INT_MIN)
+static int trusted_keys_pkey = PKEY_INVALID;
+
+#if defined(CONFIG_TRUSTED_KEYS) || \
+	(defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE))
+void trusted_key_disable_access(void)
+{
+	if (trusted_keys_pkey == PKEY_INVALID)
+		return;
+
+	pks_mknoaccess(trusted_keys_pkey, false);
+
+}
+EXPORT_SYMBOL_GPL(trusted_key_disable_access);
+
+void trusted_key_enable_access(void)
+{
+	if (trusted_keys_pkey == PKEY_INVALID)
+		return;
+
+	pks_mkrdwr(trusted_keys_pkey, false);
+}
+EXPORT_SYMBOL_GPL(trusted_key_enable_access);
+#endif
+
+static void trusted_payload_free(struct trusted_key_payload *p)
+{
+	if (!p)
+		return;
+
+	trusted_key_enable_access();
+	memzero_explicit(p->key, MAX_KEY_SIZE + 1);
+	trusted_key_disable_access();
+	vfree(p->key);
+	kzfree(p);
+}
+
 static const char hmac_alg[] = "hmac(sha1)";
 static const char hash_alg[] = "sha1";
 static struct tpm_chip *chip;
@@ -663,12 +703,15 @@ static int key_seal(struct trusted_key_payload *p,
 	if (ret)
 		return ret;
 
+	trusted_key_enable_access();
 	/* include migratable flag at end of sealed key */
 	p->key[p->key_len] = p->migratable;
 
 	ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth,
 		       p->key, p->key_len + 1, p->blob, &p->blob_len,
 		       o->blobauth, o->pcrinfo, o->pcrinfo_len);
+	trusted_key_disable_access();
+
 	if (ret < 0)
 		pr_info("trusted_key: srkseal failed (%d)\n", ret);
 
@@ -689,6 +732,7 @@ static int key_unseal(struct trusted_key_payload *p,
 	if (ret)
 		return ret;
 
+	trusted_key_enable_access();
 	ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,
 			 o->blobauth, p->key, &p->key_len);
 	if (ret < 0)
@@ -696,6 +740,7 @@ static int key_unseal(struct trusted_key_payload *p,
 	else
 		/* pull migratable flag out of sealed key */
 		p->migratable = p->key[--p->key_len];
+	trusted_key_disable_access();
 
 	tpm_buf_destroy(&tb);
 	return ret;
@@ -928,15 +973,26 @@ static struct trusted_key_options *trusted_options_alloc(void)
 
 static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
 {
-	struct trusted_key_payload *p = NULL;
+	struct trusted_key_payload *p;
 	int ret;
 
 	ret = key_payload_reserve(key, sizeof *p);
 	if (ret < 0)
-		return p;
+		return NULL;
 	p = kzalloc(sizeof *p, GFP_KERNEL);
-	if (p)
+	if (p) {
 		p->migratable = 1; /* migratable by default */
+		if (trusted_keys_pkey == PKEY_INVALID)
+			p->key = vmalloc(MAX_KEY_SIZE + 1);
+		else
+			p->key = vmalloc_pks(MAX_KEY_SIZE + 1, trusted_keys_pkey);
+
+		if (!(p->key)) {
+			kfree(p);
+			return NULL;
+		}
+	}
+
 	return p;
 }
 
@@ -1012,7 +1068,9 @@ static int trusted_instantiate(struct key *key,
 		break;
 	case Opt_new:
 		key_len = payload->key_len;
+		trusted_key_enable_access();
 		ret = tpm_get_random(chip, payload->key, key_len);
+		trusted_key_disable_access();
 		if (ret != key_len) {
 			pr_info("trusted_key: key_create failed (%d)\n", ret);
 			goto out;
@@ -1036,7 +1094,7 @@ static int trusted_instantiate(struct key *key,
 	if (!ret)
 		rcu_assign_keypointer(key, payload);
 	else
-		kfree_sensitive(payload);
+		trusted_payload_free(payload);
 	return ret;
 }
 
@@ -1045,7 +1103,7 @@ static void trusted_rcu_free(struct rcu_head *rcu)
 	struct trusted_key_payload *p;
 
 	p = container_of(rcu, struct trusted_key_payload, rcu);
-	kfree_sensitive(p);
+	trusted_payload_free(p);
 }
 
 /*
@@ -1087,34 +1145,38 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
 	ret = datablob_parse(datablob, new_p, new_o);
 	if (ret != Opt_update) {
 		ret = -EINVAL;
-		kfree_sensitive(new_p);
+		trusted_payload_free(new_p);
 		goto out;
 	}
 
 	if (!new_o->keyhandle) {
 		ret = -EINVAL;
-		kfree_sensitive(new_p);
+		trusted_payload_free(new_p);
 		goto out;
 	}
 
 	/* copy old key values, and reseal with new pcrs */
 	new_p->migratable = p->migratable;
 	new_p->key_len = p->key_len;
+
+	trusted_key_enable_access();
 	memcpy(new_p->key, p->key, p->key_len);
+	trusted_key_disable_access();
+
 	dump_payload(p);
 	dump_payload(new_p);
 
 	ret = key_seal(new_p, new_o);
 	if (ret < 0) {
 		pr_info("trusted_key: key_seal failed (%d)\n", ret);
-		kfree_sensitive(new_p);
+		trusted_payload_free(new_p);
 		goto out;
 	}
 	if (new_o->pcrlock) {
 		ret = pcrlock(new_o->pcrlock);
 		if (ret < 0) {
 			pr_info("trusted_key: pcrlock failed (%d)\n", ret);
-			kfree_sensitive(new_p);
+			trusted_payload_free(new_p);
 			goto out;
 		}
 	}
@@ -1219,7 +1281,7 @@ static int __init init_digests(void)
 
 static int __init init_trusted(void)
 {
-	int ret;
+	int ret, key_id;
 
 	/* encrypted_keys.ko depends on successful load of this module even if
 	 * TPM is not used.
@@ -1237,6 +1299,14 @@ static int __init init_trusted(void)
 	ret = register_key_type(&key_type_trusted);
 	if (ret < 0)
 		goto err_release;
+
+	/* Attempt to reserve a PKS key for protecting the trusted keys.
+	 * Note the pkey is never free'ed. This is run at init time and
+	 * we either get the key or we do not.
+	 */
+	key_id = pks_key_alloc("Keyring Trusted Keys");
+	if (key_id >= 0)
+		trusted_keys_pkey = key_id;
 	return 0;
 err_release:
 	trusted_shash_release();
diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index 08ec7f48f01d..67281394523f 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -8,6 +8,8 @@
 #include <linux/err.h>
 #include <linux/tpm.h>
 #include <linux/tpm_command.h>
+#include <linux/pkeys.h>
+#include <uapi/asm-generic/mman-common.h>
 
 #include <keys/trusted-type.h>
 #include <keys/trusted_tpm.h>
@@ -96,7 +98,11 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 	tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE);
 	tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE);
 	tpm_buf_append_u16(&buf, payload->key_len + 1);
+
+	trusted_key_enable_access();
 	tpm_buf_append(&buf, payload->key, payload->key_len);
+	trusted_key_disable_access();
+
 	tpm_buf_append_u8(&buf, payload->migratable);
 
 	/* public */
@@ -278,7 +284,10 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
 		}
 		data = &buf.data[TPM_HEADER_SIZE + 6];
 
+		trusted_key_enable_access();
 		memcpy(payload->key, data, data_len - 1);
+		trusted_key_disable_access();
+
 		payload->key_len = data_len - 1;
 		payload->migratable = data[data_len - 1];
 	}
-- 
2.28.0.rc0.12.gb6a658bd00c9


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-10-09 20:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-09 20:14 [PATCH RFC PKS/Trusted keys 0/2] trusted keys: Add PKS protection to trusted keys ira.weiny
2020-10-09 20:14 ` [PATCH RFC PKS/Trusted keys 1/2] vmalloc: Add vmalloc_pks() call ira.weiny
2020-10-09 20:14 ` [PATCH RFC PKS/Trusted keys 2/2] keys/trusted: protect trusted keys using PKS ira.weiny

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).