From 8c1d107487a0728e4706df0e375d4d4fde85356a Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Tue, 10 Mar 2020 23:20:04 +0800 Subject: [PATCH] nvme/opal: add erase locking range method support The previous erase locking range API didn't take the real erase action, it's kind of secure erase, so rename it with another name and add the real erase support. This method is used to cryptographically erase user data within a specific LBA Range and to reset the access control Locking of that LBA Range. The TPer SHALL reset the ReadLockEnabled, WriteLockEnabled, ReadLocked, and WriteLocked column values to False for the Locking object on which the method is invoked. Change-Id: I0c83df589382b0a2f189642d8119e389aa4bc559 Signed-off-by: Changpeng Liu Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/1210 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris --- include/spdk/opal.h | 4 ++ lib/nvme/nvme_opal.c | 71 +++++++++++++++++++++++++++++++++++ lib/nvme/nvme_opal_internal.h | 3 ++ 3 files changed, 78 insertions(+) diff --git a/include/spdk/opal.h b/include/spdk/opal.h index e91bec528..22238142b 100644 --- a/include/spdk/opal.h +++ b/include/spdk/opal.h @@ -153,9 +153,13 @@ int spdk_opal_cmd_add_user_to_locking_range(struct spdk_opal_dev *dev, enum spdk enum spdk_opal_lock_state lock_flag, const char *passwd); int spdk_opal_cmd_set_new_passwd(struct spdk_opal_dev *dev, enum spdk_opal_user user_id, const char *new_passwd, const char *old_passwd, bool new_user); + int spdk_opal_cmd_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id, enum spdk_opal_locking_range locking_range_id, const char *password); +int spdk_opal_cmd_secure_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id, + enum spdk_opal_locking_range locking_range_id, const char *password); + struct spdk_opal_locking_range_info *spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id); void spdk_opal_free_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id); diff --git a/lib/nvme/nvme_opal.c b/lib/nvme/nvme_opal.c index 9bc1ce2a2..615abc5b0 100644 --- a/lib/nvme/nvme_opal.c +++ b/lib/nvme/nvme_opal.c @@ -1907,6 +1907,36 @@ opal_get_active_key(struct spdk_opal_dev *dev, struct opal_common_session *sessi return opal_finalize_and_send(dev, 1, opal_get_active_key_cb, (void *)active_key); } +static int +opal_erase_locking_range(struct spdk_opal_dev *dev, struct opal_common_session *session) +{ + uint8_t uid_locking_range[OPAL_UID_LENGTH]; + uint8_t locking_range_id; + int err = 0; + + opal_clear_cmd(dev); + opal_set_comid(dev, dev->comid); + + locking_range_id = session->opal_key.locking_range; + err = opal_build_locking_range(uid_locking_range, OPAL_UID_LENGTH, locking_range_id); + if (err) { + return err; + } + + opal_add_token_u8(&err, dev, SPDK_OPAL_CALL); + opal_add_token_bytestring(&err, dev, uid_locking_range, OPAL_UID_LENGTH); + opal_add_token_bytestring(&err, dev, spdk_opal_method[ERASE_METHOD], + OPAL_UID_LENGTH); + opal_add_tokens(&err, dev, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST); + + if (err) { + SPDK_ERRLOG("Error building erase locking range.\n"); + return err; + } + + return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL); +} + int spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd) { @@ -2403,6 +2433,47 @@ end: int spdk_opal_cmd_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id, enum spdk_opal_locking_range locking_range_id, const char *password) +{ + struct opal_common_session session = {}; + int ret; + + if (dev->supported == false) { + return -ENODEV; + } + + ret = opal_init_key(&session.opal_key, password, locking_range_id); + if (ret != 0) { + return ret; + } + session.who = user_id; + + pthread_mutex_lock(&dev->mutex_lock); + ret = opal_start_auth_session(dev, &session); + if (ret) { + SPDK_ERRLOG("start authenticate session error %d\n", ret); + pthread_mutex_unlock(&dev->mutex_lock); + return ret; + } + + ret = opal_erase_locking_range(dev, &session); + if (ret) { + SPDK_ERRLOG("get active key error %d\n", ret); + goto end; + } + +end: + ret += opal_end_session(dev); + if (ret) { + SPDK_ERRLOG("end session error %d\n", ret); + } + + pthread_mutex_unlock(&dev->mutex_lock); + return ret; +} + +int +spdk_opal_cmd_secure_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id, + enum spdk_opal_locking_range locking_range_id, const char *password) { struct opal_common_session session = {}; struct spdk_opal_key active_key = {}; diff --git a/lib/nvme/nvme_opal_internal.h b/lib/nvme/nvme_opal_internal.h index 729184541..3bd64bc15 100644 --- a/lib/nvme/nvme_opal_internal.h +++ b/lib/nvme/nvme_opal_internal.h @@ -115,6 +115,7 @@ enum opal_method_enum { SET_METHOD, AUTHENTICATE_METHOD, RANDOM_METHOD, + ERASE_METHOD, }; struct spdk_opal_key { @@ -226,6 +227,8 @@ const uint8_t spdk_opal_method[][OPAL_UID_LENGTH] = { { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c }, [RANDOM_METHOD] = { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x01 }, + [ERASE_METHOD] = + { 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x03 }, }; /*