diff --git a/Documentation/nvdimm/security.txt b/Documentation/nvdimm/security.txt
index 50cbb6cb96a1..11240ce48755 100644
--- a/Documentation/nvdimm/security.txt
+++ b/Documentation/nvdimm/security.txt
@@ -39,34 +39,39 @@ The DIMM id would be provided along with the key payload (passphrase) to
 the kernel.
 
 The security keys are managed on the basis of a single key per DIMM. The
-key "passphrase" is expected to be 32bytes long or padded to 32bytes. This is
+key "passphrase" is expected to be 32bytes long. This is
 similar to the ATA security specification [2]. A key is initially acquired
 via the request_key() kernel API call and retrieved from userspace. It is up to
 the user to provide an upcall application to retrieve the key in whatever
 fashion meets their security requirements.
 
-A nvdimm user logon key has the description format of:
+A nvdimm encrypted key has the description format of:
 nvdimm:<bus-provider-specific-unique-id>
 
+See Documentation/security/keys/trusted-encrypted.rst for details on encrypted
+keys. The encrypted key for the DIMM is generated from a master key that is
+either a trusted key created via TPM2 or a less secure user key. The payload
+for the nvdimm encrypted key is randomly generated by the kernel and is not
+visible to the user. The user is responsible for retaining the encrypted key
+blob generated from the encrypted key to be loaded at the next boot session.
+
 4. Unlocking
 ------------
 When the DIMMs are being enumerated by the kernel, the kernel will attempt to
-retrieve the key from its keyring. If that fails, it will attempt to
 acquire the key from the userspace upcall function. This is the only time
 a locked DIMM can be unlocked. Once unlocked, the DIMM will remain unlocked
 until reboot.
 
 5. Update
 ---------
-When doing an update, it is expected that the new key with the 64bit payload of
-format described above is added via the keyutils API or utility. The update
-command written to the sysfs attribute will be with the format:
+When doing an update, it is expected that the new key is added via the
+keyutils API or utility. The update command written to the sysfs attribute
+will be with the format:
 update <old keyid> <new keyid>
 
-It is expected that a user logon key has been injected via keyutils to provide
-the payload for the update operation. The kernel will take the new user key,
-attempt the update operation with the nvdimm, and replace the existing key's
-payload with the new passphrase.
+It is expected that a encrypted key has been injected via keyutils to provide
+the payload for the update operation. The kernel will take the new user key
+and the old user key to attempt the update operation.
 
 If there is no old key id due to a security enabling, then a 0 should be
 passed in.  If a nvdimm has an existing passphrase, then an "old" key should
@@ -80,7 +85,7 @@ frozen by a user with root privelege.
 7. Disable
 ----------
 The security disable command format is:
-disable <old keyid>
+disable <current keyid>
 
 An "old" key with the passphrase payload that is tied to the nvdimm should be
 injected with a key description that does not have the "nvdimm:" prefix and
@@ -89,7 +94,7 @@ its keyid should be passed in via sysfs.
 8. Secure Erase
 ---------------
 The command format for doing a secure erase is:
-erase <old keyid>
+erase <current keyid>
 
 An "old" key with the passphrase payload that is tied to the nvdimm should be
 injected with a key description that does not have the "nvdimm:" prefix and
diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c
index 225a8474c44a..c3886a22b5e4 100644
--- a/drivers/nvdimm/dimm.c
+++ b/drivers/nvdimm/dimm.c
@@ -112,9 +112,6 @@ static int nvdimm_probe(struct device *dev)
 static int nvdimm_remove(struct device *dev)
 {
 	struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
-	struct nvdimm *nvdimm = to_nvdimm(dev);
-
-	nvdimm_security_release(nvdimm);
 
 	if (!ndd)
 		return 0;
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 5d34251c4f3b..269f401a5e68 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -485,7 +485,7 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_dat
 	nvdimm->num_flush = num_flush;
 	nvdimm->flush_wpq = flush_wpq;
 	atomic_set(&nvdimm->busy, 0);
-	mutex_init(&nvdimm->key_mutex);
+	mutex_init(&nvdimm->sec_mutex);
 	dev = &nvdimm->dev;
 	dev_set_name(dev, "nmem%d", nvdimm->id);
 	dev->parent = &nvdimm_bus->dev;
diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h
index 6e2877996a9b..cfb87f71db8d 100644
--- a/drivers/nvdimm/nd-core.h
+++ b/drivers/nvdimm/nd-core.h
@@ -45,8 +45,7 @@ struct nvdimm {
 	const char *dimm_id;
 	const struct nvdimm_security_ops *security_ops;
 	enum nvdimm_security_state state;
-	struct key *key;
-	struct mutex key_mutex;
+	struct mutex sec_mutex;
 };
 
 /**
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 892f127bfd38..f8d8f0a2a40d 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -428,7 +428,6 @@ bool pmem_should_map_pages(struct device *dev);
 
 #ifdef CONFIG_NVDIMM_SECURITY
 int nvdimm_security_unlock_dimm(struct nvdimm *nvdimm);
-void nvdimm_security_release(struct nvdimm *nvdimm);
 int nvdimm_security_get_state(struct nvdimm *nvdimm);
 int nvdimm_security_change_key(struct nvdimm *nvdimm, unsigned int old_keyid,
 		unsigned int new_keyid);
@@ -441,10 +440,6 @@ static inline int nvdimm_security_unlock_dimm(struct nvdimm *nvdimm)
 	return 0;
 }
 
-static inline void nvdimm_security_release(struct nvdimm *nvdimm)
-{
-}
-
 static inline int nvdimm_security_get_state(struct nvdimm *nvdimm)
 {
 	return -EOPNOTSUPP;
diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
index 5aacc590b4c0..ee741199d623 100644
--- a/drivers/nvdimm/security.c
+++ b/drivers/nvdimm/security.c
@@ -10,43 +10,10 @@
 #include <linux/key.h>
 #include <linux/key-type.h>
 #include <keys/user-type.h>
+#include <keys/encrypted-type.h>
 #include "nd-core.h"
 #include "nd.h"
 
-/*
- * Replacing the user key with a kernel key. The function expects that
- * we hold the sem for the key passed in. The function will release that
- * sem when done process. We will also hold the sem for the valid new key
- * returned.
- */
-static struct key *make_kernel_key(struct key *key)
-{
-	struct key *new_key;
-	struct user_key_payload *payload;
-	int rc;
-
-	new_key = key_alloc(&key_type_logon, key->description,
-			GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
-			KEY_POS_ALL & ~KEY_POS_SETATTR,
-			KEY_ALLOC_NOT_IN_QUOTA, NULL);
-	if (IS_ERR(new_key))
-		return NULL;
-
-	payload = key->payload.data[0];
-	rc = key_instantiate_and_link(new_key, payload->data,
-			payload->datalen, NULL, NULL);
-	up_read(&key->sem);
-	if (rc < 0) {
-		key_put(new_key);
-		return NULL;
-	}
-
-	key_put(key);
-
-	down_read(&new_key->sem);
-	return new_key;
-}
-
 /*
  * Retrieve user injected key
  */
@@ -61,6 +28,10 @@ static struct key *nvdimm_lookup_user_key(struct device *dev,
 		return NULL;
 
 	key = key_ref_to_ptr(keyref);
+	if (key->type != &key_type_encrypted) {
+		key_put(key);
+		return NULL;
+	}
 	dev_dbg(dev, "%s: key found: %#x\n", __func__, key_serial(key));
 
 	return key;
@@ -76,7 +47,7 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm)
 	struct device *dev = &nvdimm->dev;
 
 	sprintf(desc, "%s%s", NVDIMM_PREFIX, nvdimm->dimm_id);
-	key = request_key(&key_type_logon, desc, "");
+	key = request_key(&key_type_encrypted, desc, "");
 	if (IS_ERR(key)) {
 		if (PTR_ERR(key) == -ENOKEY)
 			dev_warn(dev, "request_key() found no key\n");
@@ -88,52 +59,6 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm)
 	return key;
 }
 
-struct key *nvdimm_get_and_verify_key(struct nvdimm *nvdimm,
-		unsigned int user_key_id)
-{
-	int rc;
-	struct key *user_key, *key;
-	struct device *dev = &nvdimm->dev;
-	struct user_key_payload *upayload, *payload;
-
-	lockdep_assert_held(&nvdimm->key_mutex);
-	key = nvdimm->key;
-	if (!key) {
-		dev_dbg(dev, "No cached kernel key\n");
-		return ERR_PTR(-EAGAIN);;
-	}
-	dev_dbg(dev, "cached_key: %#x\n", key_serial(key));
-
-	user_key = nvdimm_lookup_user_key(dev, user_key_id);
-	if (!user_key) {
-		dev_dbg(dev, "Old user key lookup failed\n");
-		return ERR_PTR(-EINVAL);
-	}
-	dev_dbg(dev, "user_key: %#x\n", key_serial(user_key));
-
-	down_read(&key->sem);
-	down_read(&user_key->sem);
-	payload = key->payload.data[0];
-	upayload = user_key->payload.data[0];
-
-	rc = memcmp(payload->data, upayload->data, NVDIMM_PASSPHRASE_LEN);
-	up_read(&user_key->sem);
-	key_put(user_key);
-	up_read(&key->sem);
-
-	if (rc != 0) {
-		dev_warn(dev, "Supplied old user key fails check.\n");
-		return ERR_PTR(-EINVAL);
-	}
-	return key;
-}
-
-static void key_destroy(struct key *key)
-{
-	key_invalidate(key);
-	key_put(key);
-}
-
 int nvdimm_security_get_state(struct nvdimm *nvdimm)
 {
 	if (!nvdimm->security_ops)
@@ -146,14 +71,15 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid)
 {
 	int rc = 0;
 	struct key *key;
-	struct user_key_payload *payload;
+	struct encrypted_key_payload *epayload;
 	struct device *dev = &nvdimm->dev;
+	void *data;
 
 	if (!nvdimm->security_ops)
 		return -EOPNOTSUPP;
 
 	nvdimm_bus_lock(dev);
-	mutex_lock(&nvdimm->key_mutex);
+	mutex_lock(&nvdimm->sec_mutex);
 	if (atomic_read(&nvdimm->busy)) {
 		dev_warn(dev, "Unable to secure erase while DIMM active.\n");
 		rc = -EBUSY;
@@ -166,26 +92,23 @@ int nvdimm_security_erase(struct nvdimm *nvdimm, unsigned int keyid)
 		goto out;
 	}
 
-	/* look for a key from cached key if exists */
-	key = nvdimm_get_and_verify_key(nvdimm, keyid);
-	if (IS_ERR(key)) {
+	key = nvdimm_lookup_user_key(dev, keyid);
+	if (!key) {
 		dev_dbg(dev, "Unable to get and verify key\n");
-		rc = PTR_ERR(key);
+		rc = -ENOKEY;
 		goto out;
 	}
 
 	down_read(&key->sem);
-	payload = key->payload.data[0];
+	epayload = dereference_key_locked(key);
+	data = epayload->decrypted_data;
 	rc = nvdimm->security_ops->erase(nvdimm,
-			(const struct nvdimm_key_data *)payload->data);
+			(const struct nvdimm_key_data *)data);
 	up_read(&key->sem);
-
-	/* remove key since secure erase kills the passphrase */
-	key_destroy(key);
-	nvdimm->key = NULL;
+	key_put(key);
 
  out:
-	mutex_unlock(&nvdimm->key_mutex);
+	mutex_unlock(&nvdimm->sec_mutex);
 	nvdimm_bus_unlock(dev);
 	nvdimm_security_get_state(nvdimm);
 	return rc;
@@ -201,11 +124,15 @@ int nvdimm_security_freeze_lock(struct nvdimm *nvdimm)
 	if (nvdimm->state == NVDIMM_SECURITY_UNSUPPORTED)
 		return -EOPNOTSUPP;
 
+	mutex_lock(&nvdimm->sec_mutex);
 	rc = nvdimm->security_ops->freeze_lock(nvdimm);
-	if (rc < 0)
+	if (rc < 0) {
+		mutex_unlock(&nvdimm->sec_mutex);
 		return rc;
+	}
 
 	nvdimm_security_get_state(nvdimm);
+	mutex_unlock(&nvdimm->sec_mutex);
 	return 0;
 }
 
@@ -213,8 +140,9 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
 {
 	int rc;
 	struct key *key;
-	struct user_key_payload *payload;
+	struct encrypted_key_payload *epayload;
 	struct device *dev = &nvdimm->dev;
+	void *data;
 
 	if (!nvdimm->security_ops)
 		return -EOPNOTSUPP;
@@ -222,57 +150,52 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
 	if (nvdimm->state == NVDIMM_SECURITY_UNSUPPORTED)
 		return -EOPNOTSUPP;
 
-	mutex_lock(&nvdimm->key_mutex);
+	mutex_lock(&nvdimm->sec_mutex);
 	/* look for a key from cached key */
-	key = nvdimm_get_and_verify_key(nvdimm, keyid);
-	if (IS_ERR(key)) {
-		mutex_unlock(&nvdimm->key_mutex);
-		return PTR_ERR(key);
+	key = nvdimm_lookup_user_key(dev, keyid);
+	if (!key) {
+		mutex_unlock(&nvdimm->sec_mutex);
+		return -ENOKEY;
 	}
 
 	down_read(&key->sem);
-	payload = key->payload.data[0];
+	epayload = dereference_key_locked(key);
+	data = epayload->decrypted_data;
 
 	rc = nvdimm->security_ops->disable(nvdimm,
-			(const struct nvdimm_key_data *)payload->data);
+			(const struct nvdimm_key_data *)data);
 	up_read(&key->sem);
-	if (rc < 0) {
+	if (rc < 0)
 		dev_warn(dev, "security disable failed\n");
-		goto out;
-	}
 
-	/* If we succeed then remove the key */
-	key_destroy(key);
-	nvdimm->key = NULL;
-
- out:
-	mutex_unlock(&nvdimm->key_mutex);
+	key_put(key);
 	nvdimm_security_get_state(nvdimm);
+	mutex_unlock(&nvdimm->sec_mutex);
 	return rc;
 }
 
-static int nvdimm_self_verify_key(struct nvdimm *nvdimm)
+static struct key *nvdimm_self_verify_key(struct nvdimm *nvdimm)
 {
 	struct key *key;
-	struct user_key_payload *payload;
+	struct encrypted_key_payload *epayload;
 	void *data;
 	int rc;
 
-	lockdep_assert_held(&nvdimm->key_mutex);
-
+	lockdep_assert_held(&nvdimm->sec_mutex);
 	key = nvdimm_request_key(nvdimm);
 	if (!key)
-		return -ENOKEY;
+		return NULL;
+
+	down_read(&key->sem);
+	epayload = dereference_key_locked(key);
+	data = epayload->decrypted_data;
 
-	if (key->datalen != NVDIMM_PASSPHRASE_LEN) {
+	if (epayload->decrypted_datalen != NVDIMM_PASSPHRASE_LEN) {
 		key_put(key);
-		return -EINVAL;
+		key = NULL;
+		goto out;
 	}
 
-	down_read(&key->sem);
-	payload = key->payload.data[0];
-	data = payload->data;
-
 	/*
 	 * We send the same key to the hardware as new and old key to
 	 * verify that the key is good.
@@ -280,19 +203,21 @@ static int nvdimm_self_verify_key(struct nvdimm *nvdimm)
 	rc = nvdimm->security_ops->change_key(nvdimm, data, data);
 	if (rc < 0) {
 		key_put(key);
-		return rc;
+		key = NULL;
 	}
+
+out:
 	up_read(&key->sem);
-	nvdimm->key = key;
-	return 0;
+	return key;
 }
 
 int nvdimm_security_unlock_dimm(struct nvdimm *nvdimm)
 {
-	struct key *key;
-	int rc = -ENXIO;
-	struct user_key_payload *payload;
+	struct key *key = NULL;
+	int rc;
+	struct encrypted_key_payload *epayload;
 	struct device *dev = &nvdimm->dev;
+	void *data;
 
 	if (!nvdimm->security_ops)
 		return 0;
@@ -301,7 +226,7 @@ int nvdimm_security_unlock_dimm(struct nvdimm *nvdimm)
 			nvdimm->state == NVDIMM_SECURITY_DISABLED)
 		return 0;
 
-	mutex_lock(&nvdimm->key_mutex);
+	mutex_lock(&nvdimm->sec_mutex);
 	/*
 	 * If the pre-OS has unlocked the DIMM, we will attempt to send
 	 * the key from request_key() to the hardware for verification.
@@ -310,60 +235,50 @@ int nvdimm_security_unlock_dimm(struct nvdimm *nvdimm)
 	 * other security operations.
 	 */
 	if (nvdimm->state == NVDIMM_SECURITY_UNLOCKED) {
-		rc = nvdimm_self_verify_key(nvdimm);
-		if (rc < 0) {
+		key = nvdimm_self_verify_key(nvdimm);
+		if (!key) {
 			rc = nvdimm_security_freeze_lock(nvdimm);
-			mutex_unlock(&nvdimm->key_mutex);
-			return rc;
+			mutex_unlock(&nvdimm->sec_mutex);
+			return -ENOKEY;
 		}
 	}
 
-	key = nvdimm->key;
-	if (!key) {
+	if (!key)
 		key = nvdimm_request_key(nvdimm);
-		if (key && key->datalen != NVDIMM_PASSPHRASE_LEN) {
-			key_put(key);
-			key = NULL;
-			rc = -EINVAL;
-		}
-	}
+
 	if (!key) {
-		mutex_unlock(&nvdimm->key_mutex);
-		return rc;
+		mutex_unlock(&nvdimm->sec_mutex);
+		return -ENOKEY;
 	}
 
 	dev_dbg(dev, "%s: key: %#x\n", __func__, key_serial(key));
 	down_read(&key->sem);
-	payload = key->payload.data[0];
+	epayload = dereference_key_locked(key);
+	data = epayload->decrypted_data;
+
+	if (epayload->decrypted_datalen != NVDIMM_PASSPHRASE_LEN) {
+		up_read(&key->sem);
+		key_put(key);
+		mutex_unlock(&nvdimm->sec_mutex);
+		return -EINVAL;
+	}
+
 	rc = nvdimm->security_ops->unlock(nvdimm,
-			(const struct nvdimm_key_data *)payload->data);
+			(const struct nvdimm_key_data *)data);
 	up_read(&key->sem);
 
 	if (rc == 0) {
-		if (!nvdimm->key)
-			nvdimm->key = key;
 		nvdimm->state = NVDIMM_SECURITY_UNLOCKED;
 		dev_dbg(dev, "DIMM %s unlocked\n", dev_name(dev));
-	} else {
-		key_invalidate(key);
-		key_put(key);
-		nvdimm->key = NULL;
+	} else
 		dev_warn(dev, "Failed to unlock dimm: %s\n", dev_name(dev));
-	}
 
-	mutex_unlock(&nvdimm->key_mutex);
+	key_put(key);
 	nvdimm_security_get_state(nvdimm);
+	mutex_unlock(&nvdimm->sec_mutex);
 	return rc;
 }
 
-void nvdimm_security_release(struct nvdimm *nvdimm)
-{
-	mutex_lock(&nvdimm->key_mutex);
-	key_put(nvdimm->key);
-	nvdimm->key = NULL;
-	mutex_unlock(&nvdimm->key_mutex);
-}
-
 int nvdimm_security_change_key(struct nvdimm *nvdimm,
 		unsigned int old_keyid, unsigned int new_keyid)
 {
@@ -371,7 +286,7 @@ int nvdimm_security_change_key(struct nvdimm *nvdimm,
 	struct key *key, *old_key;
 	void *old_data = NULL, *new_data;
 	struct device *dev = &nvdimm->dev;
-	struct user_key_payload *payload, *old_payload;
+	struct encrypted_key_payload *epayload, *old_epayload;
 
 	if (!nvdimm->security_ops)
 		return -EOPNOTSUPP;
@@ -379,15 +294,10 @@ int nvdimm_security_change_key(struct nvdimm *nvdimm,
 	if (nvdimm->state == NVDIMM_SECURITY_FROZEN)
 		return -EBUSY;
 
-	mutex_lock(&nvdimm->key_mutex);
+	mutex_lock(&nvdimm->sec_mutex);
 	/* look for a key from cached key if exists */
-	old_key = nvdimm_get_and_verify_key(nvdimm, old_keyid);
-	if (IS_ERR(old_key) && PTR_ERR(old_key) == -EAGAIN)
-		old_key = NULL;
-	else if (IS_ERR(old_key)) {
-		mutex_unlock(&nvdimm->key_mutex);
-		return PTR_ERR(old_key);
-	} else
+	old_key = nvdimm_lookup_user_key(dev, old_keyid);
+	if (old_key)
 		dev_dbg(dev, "%s: old key: %#x\n", __func__,
 				key_serial(old_key));
 
@@ -402,76 +312,28 @@ int nvdimm_security_change_key(struct nvdimm *nvdimm,
 	dev_dbg(dev, "%s: new key: %#x\n", __func__, key_serial(key));
 
 	down_read(&key->sem);
-	payload = key->payload.data[0];
-	if (payload->datalen != NVDIMM_PASSPHRASE_LEN) {
-		rc = -EINVAL;
-		up_read(&key->sem);
-		goto out;
-	}
-
-	/*
-	 * Since there is no existing key this user key will become the
-	 * kernel's key.
-	 */
-	if (!old_key) {
-		key = make_kernel_key(key);
-		if (!key) {
-			rc = -ENOMEM;
-			goto out;
-		}
-	}
-
-	/*
-	 * We don't need to release key->sem here because
-	 * make_kernel_key() will have upgraded the user key to kernel
-	 * and handled the semaphore handoff.
-	 */
-	payload = key->payload.data[0];
+	epayload = dereference_key_locked(key);
+	new_data = epayload->decrypted_data;
 
 	if (old_key) {
 		down_read(&old_key->sem);
-		old_payload = old_key->payload.data[0];
-		old_data = old_payload->data;
+		old_epayload = dereference_key_locked(old_key);
+		old_data = old_epayload->decrypted_data;
 	}
 
-	new_data = payload->data;
-
 	rc = nvdimm->security_ops->change_key(nvdimm, old_data,
 			new_data);
 	if (rc)
 		dev_warn(dev, "key update failed: %d\n", rc);
 
-	if (old_key) {
+	if (old_key)
 		up_read(&old_key->sem);
-		/*
-		 * With the key update done via hardware, we no longer need
-		 * the old payload and need to replace it with the new
-		 * payload. key_update() will acquire write sem of the
-		 * old key and update with new data.
-		 */
-		if (rc == 0) {
-			rc = key_update(make_key_ref(old_key, 1), new_data,
-					old_key->datalen);
-			if (rc < 0) {
-				dev_warn(dev,
-					"kernel key update failed: %d\n", rc);
-				key_destroy(old_key);
-				nvdimm->key = NULL;
-			}
-		}
-	}
 	up_read(&key->sem);
-
-	if (!old_key) {
-		if (rc == 0) {
-			dev_dbg(dev, "key cached: %#x\n", key_serial(key));
-			nvdimm->key = key;
-		} else
-			key_destroy(key);
-	}
 	nvdimm_security_get_state(nvdimm);
 
  out:
-	mutex_unlock(&nvdimm->key_mutex);
+	mutex_unlock(&nvdimm->sec_mutex);
+	key_put(old_key);
+	key_put(key);
 	return rc;
 }
