Commit 0fae4f64 authored by Chunyang Hui's avatar Chunyang Hui Committed by Jim Harris
Browse files

Opal: Add support for erase locking range



Change-Id: Ie40ea642bc266f84ad5a3dbad8012b9eac178360
Signed-off-by: default avatarChunyang Hui <chunyang.hui@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465244


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
parent a1d0f799
Loading
Loading
Loading
Loading
+63 −14
Original line number Diff line number Diff line
@@ -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:
+2 −1
Original line number Diff line number Diff line
@@ -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);
+157 −0
Original line number Diff line number Diff line
@@ -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)
{