Opal: Add support for erase locking range

Change-Id: Ie40ea642bc266f84ad5a3dbad8012b9eac178360
Signed-off-by: Chunyang Hui <chunyang.hui@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465244
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Chunyang Hui 2019-08-16 01:03:40 +08:00 committed by Jim Harris
parent a1d0f799c2
commit 0fae4f64c4
3 changed files with 222 additions and 15 deletions

View File

@ -962,13 +962,14 @@ opal_usage(void)
printf("\n"); printf("\n");
printf("\t[1: scan device]\n"); printf("\t[1: scan device]\n");
printf("\t[2: init - take ownership and activate locking]\n"); printf("\t[2: init - take ownership and activate locking]\n");
printf("\t[3: setup locking range]\n"); printf("\t[3: revert tper]\n");
printf("\t[4: list locking ranges]\n"); printf("\t[4: setup locking range]\n");
printf("\t[5: enable user]\n"); printf("\t[5: list locking ranges]\n");
printf("\t[6: set new password]\n"); printf("\t[6: enable user]\n");
printf("\t[7: add user to locking range]\n"); printf("\t[7: set new password]\n");
printf("\t[8: lock/unlock range]\n"); printf("\t[8: add user to locking range]\n");
printf("\t[9: revert tper]\n"); printf("\t[9: lock/unlock range]\n");
printf("\t[10: erase locking range]\n");
printf("\t[0: quit]\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 static void
test_opal(void) test_opal(void)
{ {
@ -1526,25 +1572,28 @@ test_opal(void)
opal_init(ctrlr); /* Take ownership, Activate Locking SP */ opal_init(ctrlr); /* Take ownership, Activate Locking SP */
break; break;
case 3: case 3:
opal_setup_lockingrange(ctrlr); opal_revert_tper(ctrlr);
break; break;
case 4: case 4:
opal_list_locking_ranges(ctrlr); opal_setup_lockingrange(ctrlr);
break; break;
case 5: case 5:
opal_new_user_enable(ctrlr); opal_list_locking_ranges(ctrlr);
break; break;
case 6: case 6:
opal_change_password(ctrlr); opal_new_user_enable(ctrlr);
break; break;
case 7: case 7:
opal_add_user_to_locking_range(ctrlr); opal_change_password(ctrlr);
break; break;
case 8: case 8:
opal_user_lock_unlock_range(ctrlr); opal_add_user_to_locking_range(ctrlr);
break; break;
case 9: case 9:
opal_revert_tper(ctrlr); opal_user_lock_unlock_range(ctrlr);
break;
case 10:
opal_erase_locking_range(ctrlr);
break; break;
default: default:

View File

@ -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); 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, 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); 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, struct spdk_opal_locking_range_info *spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev,
enum spdk_opal_locking_range id); enum spdk_opal_locking_range id);

View File

@ -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); 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 int
spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd) spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd)
{ {
@ -2347,6 +2454,56 @@ end:
return ret; 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 * struct spdk_opal_info *
spdk_opal_get_info(struct spdk_opal_dev *dev) spdk_opal_get_info(struct spdk_opal_dev *dev)
{ {