Skip to contentSkip to conversation

Add Opal unlock support to NVMe.

PATCH In review Rafael Antognolli 5 participants 9 messages Apr 22, 2016 – Jun 20, 2016

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Add Opal unlock support to NVMe.

This patch series implement a small set of the Opal protocol for self encrypting devices. It's implemented only what is needed for saving a password and unlocking a given "locking range". The password is saved on the driver and replayed back to the device on resume from suspend to RAM. It is specifically supporting the single user mode.

It is not planned to implement the full Opal protocol (at least not for now).

Rafael Antognolli (2):
Add optane OPAL unlocking code.
NVMe: Add ioctls to save and unlock an Opal locking range.

 drivers/nvme/host/Kconfig         |    7 +
 drivers/nvme/host/Makefile        |    1 +
 drivers/nvme/host/core.c          |    9 +
 drivers/nvme/host/opal.c          | 1270 +++++++++++++++++++++++++++++++++++++
 drivers/nvme/host/opal.h          |   73 +++
 drivers/nvme/host/opal_internal.h |  501 +++++++++++++++
 include/uapi/linux/nvme_ioctl.h   |    7 +
 7 files changed, 1868 insertions(+)
 create mode 100644 drivers/nvme/host/opal.c
 create mode 100644 drivers/nvme/host/opal.h
 create mode 100644 drivers/nvme/host/opal_internal.h
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/2 Add optane OPAL unlocking code.

This code is used to unlock a device during resume from "suspend to RAM". It allows the userspace to set a key for a locking range. This key is stored in the module memory, and will be replayed later (using the OPAL protocol, through the NVMe driver) to unlock the locking range.

The nvme_opal_unlock() will search through the list of saved devices + locking_range + namespaces + keys and check if it is a match for this namespace. For every match, it adds an "unlocking job" to a list, and after this, these jobs are "consumed" by running the respective OPAL "unlock range" commands (from the OPAL spec):
* STARTSESSION
* SET(locking range, readwrite)
* ENDSESSION

Signed-off-by Rafael Antognolli <rafael.antognolli at intel.com>
---
 drivers/nvme/host/Kconfig         |    7 +
 drivers/nvme/host/Makefile        |    1 +
 drivers/nvme/host/opal.c          | 1270 +++++++++++++++++++++++++++++++++++++
 drivers/nvme/host/opal.h          |   73 +++
 drivers/nvme/host/opal_internal.h |  501 +++++++++++++++
 5 files changed, 1852 insertions(+)
 create mode 100644 drivers/nvme/host/opal.c
 create mode 100644 drivers/nvme/host/opal.h
 create mode 100644 drivers/nvme/host/opal_internal.h
drivers/nvme/host/Kconfig +7 -0
index c894841..f326c40 100644
@@ -24,3 +24,10 @@ config BLK_DEV_NVME_SCSI
 	  to say N here, unless you run a distro that abuses the SCSI
 	  emulation to provide stable device names for mount by id, like
 	  some OpenSuSE and SLES versions.
+
+config BLK_DEV_NVME_OPAL
+	bool "Opal encryption resume support"
+	depends on BLK_DEV_NVME
+	---help---
+	  Self encrypting devices that support the Opal specification need this
+	  option enabled to support resume from S3 and S0ix states.
drivers/nvme/host/Makefile +1 -0
index 9a3ca89..fdaa3cb 100644
@@ -4,5 +4,6 @@ obj-$(CONFIG_BLK_DEV_NVME)		+= nvme.o
 nvme-core-y				:= core.o
 nvme-core-$(CONFIG_BLK_DEV_NVME_SCSI)	+= scsi.o
 nvme-core-$(CONFIG_NVM)			+= lightnvm.o
+nvme-core-$(CONFIG_BLK_DEV_NVME_OPAL)	+= opal.o
 
 nvme-y					+= pci.o
drivers/nvme/host/opal.c new file +1270 -0

1,270 lines not on this page · raw message

drivers/nvme/host/opal.h new file +73 -0

73 lines not on this page · raw message

drivers/nvme/host/opal_internal.h new file +501 -0

501 lines not on this page · raw message

Signature · 1 line
1.9.1
#2 lore raw

PATCH 2/2 NVMe: Add ioctls to save and unlock an Opal locking range.

In reply to Rafael Antognolli

Two ioctls are added to the NVMe namespace: NVME_IOCTL_SAVE_OPAL_KEY and NVME_IOCTL_UNLOCK_OPAL. These ioctls map directly to the respective nvme_opal_register() and nvme_opal_unlock() functions.

Additionally, nvme_opal_unlock() is called upon nvme_revalidate_disk, so it will try to unlock a locking range (if a password for it is saved) during PM resume.

Signed-off-by Rafael Antognolli <rafael.antognolli at intel.com>
---
 drivers/nvme/host/core.c        | 9 +++++++++
 include/uapi/linux/nvme_ioctl.h | 7 +++++++
 2 files changed, 16 insertions(+)
drivers/nvme/host/core.c +9 -0
index 643f457..1f4b78c 100644
@@ -30,6 +30,7 @@
 #include <asm/unaligned.h>
 
 #include "nvme.h"
+#include "opal.h"
 
 #define NVME_MINORS		(1U << MINORBITS)
 
@@ -517,6 +518,10 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode,
 	case SG_IO:
 		return nvme_sg_io(ns, (void __user *)arg);
 #endif
+	case NVME_IOCTL_SAVE_OPAL_KEY:
+		return nvme_opal_register(ns, (void __user *)arg);
+	case NVME_IOCTL_UNLOCK_OPAL:
+		return nvme_opal_unlock(ns);
 	default:
 		return -ENOTTY;
 	}
@@ -675,6 +680,7 @@ static int nvme_revalidate_disk(struct gendisk *disk)
 	if (ns->ctrl->oncs & NVME_CTRL_ONCS_DSM)
 		nvme_config_discard(ns);
 	blk_mq_unfreeze_queue(disk->queue);
+	nvme_opal_unlock(ns);
 
 	kfree(id);
 	return 0;
@@ -1596,6 +1602,8 @@ int __init nvme_core_init(void)
 		goto unregister_chrdev;
 	}
 
+	nvme_opal_init();
+
 	return 0;
 
  unregister_chrdev:
@@ -1607,6 +1615,7 @@ int __init nvme_core_init(void)
 
 void nvme_core_exit(void)
 {
+	nvme_opal_exit();
 	unregister_blkdev(nvme_major, "nvme");
 	class_destroy(nvme_class);
 	__unregister_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme");
include/uapi/linux/nvme_ioctl.h +7 -0
index c4b2a3f..8f8ab02 100644
@@ -53,6 +53,11 @@ struct nvme_passthru_cmd {
 	__u32	result;
 };
 
+struct nvme_opal_key {
+	__u8	locking_range;
+	__u8	key[256];
+};
+
 #define nvme_admin_cmd nvme_passthru_cmd
 
 #define NVME_IOCTL_ID		_IO('N', 0x40)
@@ -61,5 +66,7 @@ struct nvme_passthru_cmd {
 #define NVME_IOCTL_IO_CMD	_IOWR('N', 0x43, struct nvme_passthru_cmd)
 #define NVME_IOCTL_RESET	_IO('N', 0x44)
 #define NVME_IOCTL_SUBSYS_RESET	_IO('N', 0x45)
+#define NVME_IOCTL_SAVE_OPAL_KEY _IOW('N', 0X46, struct nvme_opal_key)
+#define NVME_IOCTL_UNLOCK_OPAL  _IO('N', 0X47)
 
 #endif /* _UAPI_LINUX_NVME_IOCTL_H */
Signature · 1 line
1.9.1
#3 lore raw
In reply to Rafael Antognolli
Quoted 7 lines · Rafael Antognolli

This patch series implement a small set of the Opal protocol for self encrypting devices. It's implemented only what is needed for saving a password and unlocking a given "locking range". The password is saved on the driver and replayed back to the device on resume from suspend to RAM. It is specifically supporting the single user mode.

It is not planned to implement the full Opal protocol (at least not for now).

I think the OPAL code should be a generic library outside the NVMe code so that we can use it for SATA and SAS as well, just with a little glue code for the Security Send / Receive commands to wire it up to NVMe.

#4 lore raw

cover Add Opal unlock support to NVMe.

Quoted 7 lines · Christoph Hellwig
Quoted 6 lines · Rafael Antognolli

This patch series implement a small set of the Opal protocol for self encrypting devices. It's implemented only what is needed for saving a password and unlocking a given "locking range". The password is saved on the driver and replayed back to the device on resume from suspend to RAM. It is specifically supporting the single user mode.

Quoted 7 lines
Quoted 1 line

It is not planned to implement the full Opal protocol (at least not for now).

I think the OPAL code should be a generic library outside the NVMe code so that we can use it for SATA and SAS as well, just with a little glue code for the Security Send / Receive commands to wire it up to NVMe.

Fully agree. Having generic OPAL support would be a major benefit.

Cheers,

Hannes

Signature · 5 lines
Dr. Hannes Reinecke		   Teamlead Storage & Networking
hare at suse.de			               +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg
GF: F. Imend?rffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG N?rnberg)
#5 lore raw
In reply to Christoph Hellwig
Quoted 11 lines

-----Original Message-----
From: linux-block-owner at vger.kernel.org [mailto:linux-block- owner at vger.kernel.org] On Behalf Of Christoph Hellwig
Sent: Monday, April 25, 2016 3:24 AM
To: Rafael Antognolli <rafael.antognolli at intel.com>
Cc: linux-nvme at lists.infradead.org; linux-kernel at vger.kernel.org; linux-block at vger.kernel.org
Subject: Re: [PATCH 0/2] Add Opal unlock support to NVMe.

Quoted 7 lines
Quoted 6 lines · Rafael Antognolli

This patch series implement a small set of the Opal protocol for self encrypting devices. It's implemented only what is needed for saving a password and unlocking a given "locking range". The password is saved on the driver and replayed back to the device on resume from suspend to RAM. It is specifically supporting the single user mode.

Passwords stored in memory are subject to cold boot attacks.

Could you tie this into the keyring infrastructure, so it would least be no worse than other kernel modules? This would allow support for TPM-based keys (if present) to resist more attacks. If register-based key storage or other techniques prove viable, they would probably show up there first.

Quoted 7 lines
Quoted 2 lines

It is not planned to implement the full Opal protocol (at least not for now).

I think the OPAL code should be a generic library outside the NVMe code so that we can use it for SATA and SAS as well, just with a little glue code for the Security Send / Receive commands to wire it up to NVMe.

NVDIMMs would benefit from that as well.

#6 lore raw
Quoted 19 lines · Robert (Persistent Memory)
Quoted 11 lines

-----Original Message-----
From: linux-block-owner at vger.kernel.org [mailto:linux-block- owner at vger.kernel.org] On Behalf Of Christoph Hellwig
Sent: Monday, April 25, 2016 3:24 AM
To: Rafael Antognolli <rafael.antognolli at intel.com>
Cc: linux-nvme at lists.infradead.org; linux-kernel at vger.kernel.org; linux-block at vger.kernel.org
Subject: Re: [PATCH 0/2] Add Opal unlock support to NVMe.

Quoted 7 lines
Quoted 6 lines · Rafael Antognolli

This patch series implement a small set of the Opal protocol for self encrypting devices. It's implemented only what is needed for saving a password and unlocking a given "locking range". The password is saved on the driver and replayed back to the device on resume from suspend to RAM. It is specifically supporting the single user mode.

Quoted 7 lines

Passwords stored in memory are subject to cold boot attacks.

Could you tie this into the keyring infrastructure, so it would least be no worse than other kernel modules? This would allow support for TPM-based keys (if present) to resist more attacks. If register-based key storage or other techniques prove viable, they would probably show up there first.

I'll take a look at it.

Quoted 9 lines
Quoted 7 lines
Quoted 2 lines

It is not planned to implement the full Opal protocol (at least not for now).

I think the OPAL code should be a generic library outside the NVMe code so that we can use it for SATA and SAS as well, just with a little glue code for the Security Send / Receive commands to wire it up to NVMe.

NVDIMMs would benefit from that as well.

Yes, I can definitely change it to be that generic.

Thank you,
Rafael

#7 lore raw
Quoted 22 lines · Rafael Antognolli
Quoted 21 lines · Robert (Persistent Memory)
Quoted 11 lines

-----Original Message-----
From: linux-block-owner at vger.kernel.org [mailto:linux-block- owner at vger.kernel.org] On Behalf Of Christoph Hellwig
Sent: Monday, April 25, 2016 3:24 AM
To: Rafael Antognolli <rafael.antognolli at intel.com>
Cc: linux-nvme at lists.infradead.org; linux-kernel at vger.kernel.org; linux-block at vger.kernel.org
Subject: Re: [PATCH 0/2] Add Opal unlock support to NVMe.

Quoted 7 lines
Quoted 6 lines · Rafael Antognolli

This patch series implement a small set of the Opal protocol for self encrypting devices. It's implemented only what is needed for saving a password and unlocking a given "locking range". The password is saved on the driver and replayed back to the device on resume from suspend to RAM. It is specifically supporting the single user mode.

Passwords stored in memory are subject to cold boot attacks.

Quoted 7 lines
Quoted 5 lines

Could you tie this into the keyring infrastructure, so it would least be no worse than other kernel modules? This would allow support for TPM-based keys (if present) to resist more attacks. If register-based key storage or other techniques prove viable, they would probably show up there first.

I'll take a look at it.

Hi Robert, I've been looking at possibilities to integrate this into the keyring infra as you suggested, particularly with the trusted (TPM-based) and/or encrypted key types. However, these key types do not support any way of loading a key from userspace; the API for creating trusted or encrypted keys generate them inside the kernel and it's never available to userspace. And at the same time, the current utility to set a password on Opal devices (sedutil [1]) is a userspace program.

I could not find an easy way to connect both things unless, for instance, I generated a trusted key that the Opal kernel code can access, and used that key to encrypt the password to the Opal device. That would work but would mean the user has to request a trusted/encrypted key to be created, and then point to that when requesting to save the password. IMHO the API of this module would start to be a bit tricky.

Another solution would be to add support to at least encrypted or trusted keys to be loaded from userspace (as unencrypted keys, not encrypted blobs), even if they never get available again to userspace. This should be easy to do, I'm just not sure if it would make sense to have that on the trusted/encrypted keys.

And yet another solution would be to implement a lot more of the Opal protocol in this module, and make it support setting up the locking ranges and passwords (trusted/encrypted keys that the userspace never saw unencrypted). But at least for now, my intention was to implement just the least needed to unlock devices, not really implement the whole OPAL spec.

Anyway, do you see other options, or would you mind giving your opinion about this?

[1]: https://github.com/Drive-Trust-Alliance/sedutil

Thank you,
Rafael

#8 lore raw

cover Add Opal unlock support to NVMe.

In reply to Rafael Antognolli
Quoted 8 lines · Rafael Antognolli
Quoted 6 lines
Quoted 4 lines

I think the OPAL code should be a generic library outside the NVMe code so that we can use it for SATA and SAS as well, just with a little glue code for the Security Send / Receive commands to wire it up to NVMe.

NVDIMMs would benefit from that as well.

Yes, I can definitely change it to be that generic.

Hi Rafael,

Did you make any progress making this generic? I ran into the same thing for ATA security:

http://lists.infradead.org/pipermail/linux-nvme/2016-June/005116.html

I think the kernel would benefit from some sort of generic drive security state tracker. Would you like to join forces on this?

Jethro Beekman