[PATCH] block: sed-opal: Implement RevertSP IOCTL

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch implements an ioctl for Reverting SP functionality.
RevertSP fucntionality can be used under scenarios where user
data shall not be erased after TPer reverting.

The pacth adds a new optional parameter 'keep_glbl_rn_key' to opal_key struct.
If the optional parameter, keep_glbl_rn_key(KeepGlobalRangeKey),is provided
with a value of TRUE, then the media encryption key associated with
Locking_GlobalRange is preserved. Else, all user data is cryptographically
erased.

Test Scenarios:
RevertSP(keep_glbl_rn_key = true)  + RevertTper => Data is retained
RevertSP(keep_glbl_rn_key = false) + RevertTper => Data is erased
RevertSP(no keep_glbl_rn_key)      + RevertTper => Data is erased

Reference:
1. Section 5.1.3 of https://trustedcomputinggroup.org/wp-content/uploads/TCG_Storage-Opal_SSC_v2.01_rev1.00.pdf
2. Section 3.2.12.2 of https://trustedcomputinggroup.org/wp-content/uploads/TCG_Storage_Opal_SSC_Application_Note_1-00_1-00-Final.pdf

Signed-off-by: Revanth Rajashekar <revanth.rajashekar@xxxxxxxxx>
---
 block/opal_proto.h            |  6 ++++
 block/sed-opal.c              | 52 +++++++++++++++++++++++++++++++----
 include/linux/sed-opal.h      |  1 +
 include/uapi/linux/sed-opal.h |  4 ++-
 4 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/block/opal_proto.h b/block/opal_proto.h
index b486b3ec7dc4..8c6faa418ab4 100644
--- a/block/opal_proto.h
+++ b/block/opal_proto.h
@@ -140,6 +140,12 @@ enum opal_method {
 	OPAL_ERASE,
 };

+enum opal_revert_method {
+	OPAL_REVERT_TPER,
+	OPAL_REVERT_PSID,
+	OPAL_REVERT_SP,
+};
+
 enum opal_token {
 	/* Boolean */
 	OPAL_TRUE = 0x01,
diff --git a/block/sed-opal.c b/block/sed-opal.c
index daafadbb88ca..1939df83c45e 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -1552,6 +1552,28 @@ static int revert_tper(struct opal_dev *dev, void *data)
 	return finalize_and_send(dev, parse_and_check_status);
 }

+static int revert_sp(struct opal_dev *dev, void *data)
+{
+	int err;
+	struct opal_key *key = data;
+
+	err = cmd_start(dev, opaluid[OPAL_THISSP_UID],
+			opalmethod[OPAL_REVERTSP]);
+
+	add_token_u8(&err, dev, OPAL_STARTNAME);
+	add_token_u64(&err, dev, OPAL_SUM_SET_LIST);
+
+	/*
+	 * If KeepGlobalRangeKey is true, then the media encryption key
+	 * associated with Locking_GlobalRange is preserved.
+	 * If not true, then all user data is cryptographically erased.
+	 */
+	add_token_u8(&err, dev, key->keep_glbl_rn_key ? OPAL_TRUE : OPAL_FALSE);
+	add_token_u8(&err, dev, OPAL_ENDNAME);
+
+	return finalize_and_send(dev, parse_and_check_status);
+}
+
 static int internal_activate_user(struct opal_dev *dev, void *data)
 {
 	struct opal_session_info *session = data;
@@ -2327,7 +2349,8 @@ static int opal_add_user_to_lr(struct opal_dev *dev,
 	return ret;
 }

-static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psid)
+static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal,
+			   enum opal_revert_method revert_type)
 {
 	/* controller will terminate session */
 	const struct opal_step revert_steps[] = {
@@ -2338,17 +2361,33 @@ static int opal_reverttper(struct opal_dev *dev, struct opal_key *opal, bool psi
 		{ start_PSID_opal_session, opal },
 		{ revert_tper, }
 	};
+	const struct opal_step revertsp_steps[] = {
+		{ start_admin1LSP_opal_session, opal },
+		{ revert_sp, opal }
+	};

 	int ret;

 	mutex_lock(&dev->dev_lock);
 	setup_opal_dev(dev);
-	if (psid)
+	switch (revert_type) {
+	case OPAL_REVERT_PSID:
 		ret = execute_steps(dev, psid_revert_steps,
 				    ARRAY_SIZE(psid_revert_steps));
-	else
+		break;
+	case OPAL_REVERT_TPER:
 		ret = execute_steps(dev, revert_steps,
 				    ARRAY_SIZE(revert_steps));
+		break;
+	case OPAL_REVERT_SP:
+		ret = execute_steps(dev, revertsp_steps,
+				    ARRAY_SIZE(revertsp_steps));
+		break;
+	default:
+		pr_debug("Invalid revert type\n");
+		ret = -EINVAL;
+		break;
+	}
 	mutex_unlock(&dev->dev_lock);

 	/*
@@ -2656,7 +2695,7 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
 		ret = opal_activate_user(dev, p);
 		break;
 	case IOC_OPAL_REVERT_TPR:
-		ret = opal_reverttper(dev, p, false);
+		ret = opal_reverttper(dev, p, OPAL_REVERT_TPER);
 		break;
 	case IOC_OPAL_LR_SETUP:
 		ret = opal_setup_locking_range(dev, p);
@@ -2680,11 +2719,14 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
 		ret = opal_secure_erase_locking_range(dev, p);
 		break;
 	case IOC_OPAL_PSID_REVERT_TPR:
-		ret = opal_reverttper(dev, p, true);
+		ret = opal_reverttper(dev, p, OPAL_REVERT_PSID);
 		break;
 	case IOC_OPAL_GENERIC_TABLE_RW:
 		ret = opal_generic_read_write_table(dev, p);
 		break;
+	case IOC_OPAL_REVERT_SP:
+		ret = opal_reverttper(dev, p, OPAL_REVERT_SP);
+		break;
 	default:
 		break;
 	}
diff --git a/include/linux/sed-opal.h b/include/linux/sed-opal.h
index 1ac0d712a9c3..85ad7bb7da41 100644
--- a/include/linux/sed-opal.h
+++ b/include/linux/sed-opal.h
@@ -43,6 +43,7 @@ static inline bool is_sed_ioctl(unsigned int cmd)
 	case IOC_OPAL_MBR_DONE:
 	case IOC_OPAL_WRITE_SHADOW_MBR:
 	case IOC_OPAL_GENERIC_TABLE_RW:
+	case IOC_OPAL_REVERT_SP:
 		return true;
 	}
 	return false;
diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h
index 6f5af1a84213..ac59fbc1d06b 100644
--- a/include/uapi/linux/sed-opal.h
+++ b/include/uapi/linux/sed-opal.h
@@ -47,7 +47,8 @@ enum opal_lock_state {
 struct opal_key {
 	__u8 lr;
 	__u8 key_len;
-	__u8 __align[6];
+	__u8 keep_glbl_rn_key;
+	__u8 __align[5];
 	__u8 key[OPAL_KEY_MAX];
 };

@@ -148,5 +149,6 @@ struct opal_read_write_table {
 #define IOC_OPAL_MBR_DONE           _IOW('p', 233, struct opal_mbr_done)
 #define IOC_OPAL_WRITE_SHADOW_MBR   _IOW('p', 234, struct opal_shadow_mbr)
 #define IOC_OPAL_GENERIC_TABLE_RW   _IOW('p', 235, struct opal_read_write_table)
+#define IOC_OPAL_REVERT_SP          _IOW('p', 236, struct opal_key)

 #endif /* _UAPI_SED_OPAL_H */
--
2.17.1




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux