From 0fae4f64c45e64f6b5784daa0764fbb405ffecd9 Mon Sep 17 00:00:00 2001 From: Chunyang Hui Date: Fri, 16 Aug 2019 01:03:40 +0800 Subject: [PATCH] Opal: Add support for erase locking range Change-Id: Ie40ea642bc266f84ad5a3dbad8012b9eac178360 Signed-off-by: Chunyang Hui Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465244 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Changpeng Liu --- examples/nvme/nvme_manage/nvme_manage.c | 77 +++++++++--- include/spdk/opal.h | 3 +- lib/nvme/nvme_opal.c | 157 ++++++++++++++++++++++++ 3 files changed, 222 insertions(+), 15 deletions(-) diff --git a/examples/nvme/nvme_manage/nvme_manage.c b/examples/nvme/nvme_manage/nvme_manage.c index 982ca575f..db208fa67 100644 --- a/examples/nvme/nvme_manage/nvme_manage.c +++ b/examples/nvme/nvme_manage/nvme_manage.c @@ -962,13 +962,14 @@ opal_usage(void) printf("\n"); printf("\t[1: scan device]\n"); printf("\t[2: init - take ownership and activate locking]\n"); - printf("\t[3: setup locking range]\n"); - printf("\t[4: list locking ranges]\n"); - printf("\t[5: enable user]\n"); - printf("\t[6: set new password]\n"); - printf("\t[7: add user to locking range]\n"); - printf("\t[8: lock/unlock range]\n"); - printf("\t[9: revert tper]\n"); + printf("\t[3: revert tper]\n"); + printf("\t[4: setup locking range]\n"); + printf("\t[5: list locking ranges]\n"); + printf("\t[6: enable user]\n"); + printf("\t[7: set new password]\n"); + printf("\t[8: add user to locking range]\n"); + printf("\t[9: lock/unlock range]\n"); + printf("\t[10: erase locking range]\n"); printf("\t[0: quit]\n"); } @@ -1493,6 +1494,51 @@ opal_revert_tper(struct dev *iter) } } +static void +opal_erase_locking_range(struct dev *iter) +{ + char passwd[MAX_PASSWORD_SIZE] = {0}; + char *passwd_p; + int ret; + int ch; + int locking_range_id; + + if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) { + iter->opal_dev = spdk_opal_init_dev(iter->ctrlr); + if (iter->opal_dev == NULL) { + return; + } + if (spdk_opal_supported(iter->opal_dev)) { + printf("Please be noted this operation will erase ALL DATA on this range\n"); + printf("Please input password for erase locking range:"); + while ((ch = getchar()) != '\n' && ch != EOF); + passwd_p = get_line(passwd, MAX_PASSWORD_SIZE, stdin, true); + if (passwd_p) { + printf("\nSpecify locking range id:\n"); + if (!scanf("%d", &locking_range_id)) { + printf("Invalid locking range id\n"); + spdk_opal_close(iter->opal_dev); + return; + } + printf("\n...\n"); + ret = spdk_opal_cmd_erase_locking_range(iter->opal_dev, OPAL_ADMIN1, locking_range_id, passwd_p); + if (ret) { + printf("Erase locking range failure: %d\n", ret); + spdk_opal_close(iter->opal_dev); + return; + } + printf("...\nErase locking range Success\n"); + } else { + printf("Input password invalid. Erase locking range failure\n"); + } + } + spdk_opal_close(iter->opal_dev); + } else { + printf("%04x:%02x:%02x.%02x: NVMe Security Support/Receive Not supported.\nOpal Not Supported\n\n\n", + iter->pci_addr.domain, iter->pci_addr.bus, iter->pci_addr.dev, iter->pci_addr.func); + } +} + static void test_opal(void) { @@ -1526,25 +1572,28 @@ test_opal(void) opal_init(ctrlr); /* Take ownership, Activate Locking SP */ break; case 3: - opal_setup_lockingrange(ctrlr); + opal_revert_tper(ctrlr); break; case 4: - opal_list_locking_ranges(ctrlr); + opal_setup_lockingrange(ctrlr); break; case 5: - opal_new_user_enable(ctrlr); + opal_list_locking_ranges(ctrlr); break; case 6: - opal_change_password(ctrlr); + opal_new_user_enable(ctrlr); break; case 7: - opal_add_user_to_locking_range(ctrlr); + opal_change_password(ctrlr); break; case 8: - opal_user_lock_unlock_range(ctrlr); + opal_add_user_to_locking_range(ctrlr); break; case 9: - opal_revert_tper(ctrlr); + opal_user_lock_unlock_range(ctrlr); + break; + case 10: + opal_erase_locking_range(ctrlr); break; default: diff --git a/include/spdk/opal.h b/include/spdk/opal.h index 41e186ba6..5f16fc87b 100644 --- a/include/spdk/opal.h +++ b/include/spdk/opal.h @@ -193,7 +193,8 @@ 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); struct spdk_opal_locking_range_info *spdk_opal_get_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 deca3a902..99ad2bfa2 100644 --- a/lib/nvme/nvme_opal.c +++ b/lib/nvme/nvme_opal.c @@ -1927,6 +1927,113 @@ opal_revert_tper(struct spdk_opal_dev *dev) return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL); } +static int +opal_gen_new_active_key(struct spdk_opal_dev *dev) +{ + uint8_t uid_data[OPAL_UID_LENGTH] = {0}; + int err = 0; + int length; + + opal_clear_cmd(dev); + opal_set_comid(dev, dev->comid); + + if (dev->prev_data == NULL || dev->prev_d_len == 0) { + SPDK_ERRLOG("Error finding previous data to generate new active key\n"); + return -EINVAL; + } + + length = spdk_min(dev->prev_d_len, OPAL_UID_LENGTH); + memcpy(uid_data, dev->prev_data, length); + free(dev->prev_data); + dev->prev_data = NULL; + + opal_add_token_u8(&err, dev, SPDK_OPAL_CALL); + opal_add_token_bytestring(&err, dev, uid_data, OPAL_UID_LENGTH); + opal_add_token_bytestring(&err, dev, spdk_opal_method[GENKEY_METHOD], + OPAL_UID_LENGTH); + + opal_add_tokens(&err, dev, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST); + + if (err) { + SPDK_ERRLOG("Error building new key generation command.\n"); + return err; + } + + return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL); +} + +static int +opal_get_active_key_cb(struct spdk_opal_dev *dev, void *data) +{ + const char *active_key; + size_t str_len; + int error = 0; + + error = opal_parse_and_check_status(dev, NULL); + if (error) { + return error; + } + + str_len = opal_response_get_string(&dev->parsed_resp, 4, &active_key); + if (!active_key) { + SPDK_ERRLOG("Couldn't extract active key from response\n"); + return -EINVAL; + } + + dev->prev_d_len = str_len; + dev->prev_data = calloc(1, str_len); + if (!dev->prev_data) { + SPDK_ERRLOG("memory allocation error\n"); + return -ENOMEM; + } + memcpy(dev->prev_data, active_key, str_len); + + SPDK_DEBUGLOG(SPDK_LOG_OPAL, "active key = %p\n", dev->prev_data); + return 0; +} + +static int +opal_get_active_key(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[GET_METHOD], + OPAL_UID_LENGTH); + opal_add_tokens(&err, dev, 12, + SPDK_OPAL_STARTLIST, + SPDK_OPAL_STARTLIST, + SPDK_OPAL_STARTNAME, + SPDK_OPAL_STARTCOLUMN, + SPDK_OPAL_ACTIVEKEY, + SPDK_OPAL_ENDNAME, + SPDK_OPAL_STARTNAME, + SPDK_OPAL_ENDCOLUMN, + SPDK_OPAL_ACTIVEKEY, + SPDK_OPAL_ENDNAME, + SPDK_OPAL_ENDLIST, + SPDK_OPAL_ENDLIST); + + if (err) { + SPDK_ERRLOG("Error building get active key command.\n"); + return err; + } + + return opal_finalize_and_send(dev, 1, opal_get_active_key_cb, NULL); +} + int spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd) { @@ -2347,6 +2454,56 @@ end: return ret; } +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 = {}; + struct spdk_opal_key opal_key; + int ret; + + if (!dev || dev->supported == false) { + return -ENODEV; + } + + ret = opal_init_key(&opal_key, password, locking_range_id); + if (ret != 0) { + return ret; + } + + session.opal_key = &opal_key; + 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: %s\n", ret, opal_error_to_human(ret)); + pthread_mutex_unlock(&dev->mutex_lock); + return ret; + } + + ret = opal_get_active_key(dev, &session); + if (ret) { + SPDK_ERRLOG("get active key error %d: %s\n", ret, opal_error_to_human(ret)); + goto end; + } + + ret = opal_gen_new_active_key(dev); + if (ret) { + SPDK_ERRLOG("generate new active key error %d: %s\n", ret, opal_error_to_human(ret)); + goto end; + } + +end: + ret += opal_end_session(dev); + if (ret) { + SPDK_ERRLOG("end session error %d: %s\n", ret, opal_error_to_human(ret)); + } + + pthread_mutex_unlock(&dev->mutex_lock); + return ret; +} + struct spdk_opal_info * spdk_opal_get_info(struct spdk_opal_dev *dev) {