Commit 8522624d authored by Chunyang Hui's avatar Chunyang Hui Committed by Changpeng Liu
Browse files

opal: Add multiuser support



Admin can enable user and add user to locking range.
Then the user can lock/unlock his range.

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


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 63133871
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -96,6 +96,8 @@ NVMe Opal library add support for activating locking SP which will make the tran
from "Manufactured-Inactive" state to "Manufactured" state. Upon successfully invoking
of this method, lock and unlock features will be enabled.
NVMe Opal library add support for locking/unlocking range and list locking range info.
NVMe opal library add support for multiuser. Admin can enable user and add user to specific
locking range and the user can lock/unlock his range.

Added spdk_nvme_ctrlr_io_cmd_raw_no_payload_build() allowing a caller to pass
a completely formed command to an NVMe submission queue (buffer addresses and all).
+269 −42
Original line number Diff line number Diff line
@@ -962,8 +962,12 @@ 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 and enable 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[0: quit]\n");
}
@@ -1053,10 +1057,8 @@ opal_setup_lockingrange(struct dev *iter)
	int ch;
	uint64_t range_start;
	uint64_t range_length;
	int locking_range_flag;
	int locking_range_id;
	struct spdk_opal_locking_range_info *info;
	int state;
	enum spdk_opal_lock_state state_flag;

	if (spdk_nvme_ctrlr_get_flags(iter->ctrlr) & SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED) {
		iter->opal_dev = spdk_opal_init_dev(iter->ctrlr);
@@ -1068,15 +1070,8 @@ opal_setup_lockingrange(struct dev *iter)
			while ((ch = getchar()) != '\n' && ch != EOF);
			passwd_p = get_line(passwd, MAX_PASSWORD_SIZE, stdin, true);
			if (passwd_p) {
				ret = spdk_opal_cmd_lock_unlock(iter->opal_dev, OPAL_ADMIN1, OPAL_READWRITE,
								OPAL_LOCKING_RANGE_GLOBAL, passwd_p);
				if (ret) {
					printf("Unlock range failure: %d\n", ret);
					return;
				}

				printf("Specify locking range id:\n");
				if (!scanf("%d", &locking_range_flag)) {
				if (!scanf("%d", &locking_range_id)) {
					printf("Invalid locking range id\n");
				}

@@ -1090,46 +1085,20 @@ opal_setup_lockingrange(struct dev *iter)
					printf("Invalid range start address\n");
				}

				opal_locking_usage();
				if (!scanf("%d", &state)) {
					printf("Invalid option\n");
				}
				switch (state) {
				case 1:
					state_flag = OPAL_RWLOCK;
					break;
				case 2:
					state_flag = OPAL_READONLY;
					break;
				case 3:
					state_flag = OPAL_READWRITE;
					break;
				default:
					printf("Invalid options\n");
					return;
				}

				ret = spdk_opal_cmd_setup_locking_range(iter->opal_dev,
									OPAL_ADMIN1, locking_range_flag, range_start, range_length, passwd_p);
									OPAL_ADMIN1, locking_range_id, range_start, range_length, passwd_p);
				if (ret) {
					printf("Setup locking range failure: %d\n", ret);
					return;
				}

				ret = spdk_opal_cmd_lock_unlock(iter->opal_dev, OPAL_ADMIN1, state_flag,
								locking_range_flag, passwd_p);
				if (ret) {
					printf("Unlock range failure: %d\n", ret);
					return;
				}

				ret = spdk_opal_cmd_get_locking_range_info(iter->opal_dev,
						passwd_p, locking_range_flag);
						passwd_p, OPAL_ADMIN1, locking_range_id);
				if (ret) {
					printf("Get locking range info failure: %d\n", ret);
					return;
				}
				info = spdk_opal_get_locking_range_info(iter->opal_dev, locking_range_flag);
				info = spdk_opal_get_locking_range_info(iter->opal_dev, locking_range_id);

				printf("locking range ID: %d\n", info->locking_range_id);
				printf("range start: %ld\n", info->range_start);
@@ -1181,7 +1150,7 @@ opal_list_locking_ranges(struct dev *iter)
				max_ranges = spdk_opal_get_max_locking_ranges(iter->opal_dev);
				for (i = 0; i < max_ranges; i++) {
					ret = spdk_opal_cmd_get_locking_range_info(iter->opal_dev,
							passwd_p, i);
							passwd_p, OPAL_ADMIN1, i);
					if (ret) {
						printf("Get locking range info failure: %d\n", ret);
						return;
@@ -1214,6 +1183,251 @@ opal_list_locking_ranges(struct dev *iter)
	}
}

static void
opal_new_user_enable(struct dev *iter)
{
	int user_id;
	char passwd[MAX_PASSWORD_SIZE] = {0};
	char *passwd_p;
	char user_pw[MAX_PASSWORD_SIZE] = {0};
	char *user_pw_p;
	int ret;
	int ch;

	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 input admin password:\n");
			while ((ch = getchar()) != '\n' && ch != EOF);
			passwd_p = get_line(passwd, MAX_PASSWORD_SIZE, stdin, true);
			if (passwd_p) {
				printf("which user to enable: ");
				if (!scanf("%d", &user_id)) {
					printf("Invalid user id\n");
					spdk_opal_close(iter->opal_dev);
					return;
				}

				ret = spdk_opal_cmd_enable_user(iter->opal_dev, user_id, passwd_p);
				if (ret) {
					printf("Enable user failure error code: %d\n", ret);
					spdk_opal_close(iter->opal_dev);
					return;
				}
				printf("Please set a new password for this user:\n");
				while ((ch = getchar()) != '\n' && ch != EOF);
				user_pw_p = get_line(user_pw, MAX_PASSWORD_SIZE, stdin, true);
				if (user_pw_p == NULL) {
					printf("Input password invalid. Enable user failure\n");
					spdk_opal_close(iter->opal_dev);
					return;
				}

				ret = spdk_opal_cmd_set_new_passwd(iter->opal_dev, user_id, user_pw_p, passwd_p, true);
				if (ret) {
					printf("Set new password failure error code: %d\n", ret);
					spdk_opal_close(iter->opal_dev);
					return;
				}

				printf("...\n...\nEnable User Success\n");
			} else {
				printf("Input password invalid. Enable user 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
opal_change_password(struct dev *iter)
{
	int user_id;
	char old_passwd[MAX_PASSWORD_SIZE] = {0};
	char *old_passwd_p;
	char new_passwd[MAX_PASSWORD_SIZE] = {0};
	char *new_passwd_p;
	int ret;
	int ch;

	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("user id: ");
			if (!scanf("%d", &user_id)) {
				printf("Invalid user id\n");
				spdk_opal_close(iter->opal_dev);
				return;
			}
			printf("Password:\n");
			while ((ch = getchar()) != '\n' && ch != EOF);
			old_passwd_p = get_line(old_passwd, MAX_PASSWORD_SIZE, stdin, true);
			if (old_passwd_p) {
				printf("Please input new password:\n");
				new_passwd_p = get_line(new_passwd, MAX_PASSWORD_SIZE, stdin, true);
				if (new_passwd_p == NULL) {
					printf("Input password invalid. Change password failure\n");
					spdk_opal_close(iter->opal_dev);
					return;
				}

				ret = spdk_opal_cmd_set_new_passwd(iter->opal_dev, user_id, new_passwd_p, old_passwd_p, false);
				if (ret) {
					printf("Set new password failure error code: %d\n", ret);
					spdk_opal_close(iter->opal_dev);
					return;
				}

				printf("...\n...\nChange password Success\n");
			} else {
				printf("Input password invalid. Change password 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
opal_add_user_to_locking_range(struct dev *iter)
{
	int locking_range_id, user_id;
	char passwd[MAX_PASSWORD_SIZE] = {0};
	char *passwd_p;
	int ret;
	int ch;

	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 input admin password:\n");
			while ((ch = getchar()) != '\n' && ch != EOF);
			passwd_p = get_line(passwd, MAX_PASSWORD_SIZE, stdin, true);
			if (passwd_p) {
				printf("Specify locking range id:\n");
				if (!scanf("%d", &locking_range_id)) {
					printf("Invalid locking range id\n");
					spdk_opal_close(iter->opal_dev);
					return;
				}

				printf("which user to enable:\n");
				if (!scanf("%d", &user_id)) {
					printf("Invalid user id\n");
					spdk_opal_close(iter->opal_dev);
					return;
				}

				ret = spdk_opal_cmd_add_user_to_locking_range(iter->opal_dev, user_id, locking_range_id,
						OPAL_READONLY,
						passwd_p);
				ret += spdk_opal_cmd_add_user_to_locking_range(iter->opal_dev, user_id, locking_range_id,
						OPAL_READWRITE,
						passwd_p);
				if (ret) {
					printf("Add user to locking range error: %d\n", ret);
					return;
				}

				printf("...\n...\nAdd user to locking range Success\n");
			} else {
				printf("Input password invalid. Add user to 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
opal_user_lock_unlock_range(struct dev *iter)
{
	char passwd[MAX_PASSWORD_SIZE] = {0};
	char *passwd_p;
	int ch;
	int ret;
	int user_id;
	int locking_range_id;
	int state;
	enum spdk_opal_lock_state state_flag;

	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("User id: ");
			if (!scanf("%d", &user_id)) {
				printf("Invalid user id\n");
				spdk_opal_close(iter->opal_dev);
				return;
			}

			printf("Please input password:\n");
			while ((ch = getchar()) != '\n' && ch != EOF);
			passwd_p = get_line(passwd, MAX_PASSWORD_SIZE, stdin, true);
			if (passwd_p) {
				printf("Specify locking range id:\n");
				if (!scanf("%d", &locking_range_id)) {
					printf("Invalid locking range id\n");
					spdk_opal_close(iter->opal_dev);
					return;
				}

				opal_locking_usage();
				if (!scanf("%d", &state)) {
					printf("Invalid option\n");
				}
				switch (state) {
				case 1:
					state_flag = OPAL_RWLOCK;
					break;
				case 2:
					state_flag = OPAL_READONLY;
					break;
				case 3:
					state_flag = OPAL_READWRITE;
					break;
				default:
					printf("Invalid options\n");
					return;
				}

				ret = spdk_opal_cmd_lock_unlock(iter->opal_dev, user_id, state_flag,
								locking_range_id, passwd_p);
				if (ret) {
					printf("lock/unlock range failure: %d\n", ret);
					return;
				}
				printf("...\n...\nLock/unlock range Success\n");
			} else {
				printf("Input password invalid. lock/unlock 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
opal_revert_tper(struct dev *iter)
{
@@ -1222,6 +1436,7 @@ opal_revert_tper(struct dev *iter)
	int ret;
	int ch;


	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) {
@@ -1289,6 +1504,18 @@ test_opal(void)
		case 4:
			opal_list_locking_ranges(ctrlr);
			break;
		case 5:
			opal_new_user_enable(ctrlr);
			break;
		case 6:
			opal_change_password(ctrlr);
			break;
		case 7:
			opal_add_user_to_locking_range(ctrlr);
			break;
		case 8:
			opal_user_lock_unlock_range(ctrlr);
			break;
		case 9:
			opal_revert_tper(ctrlr);
			break;
+10 −0
Original line number Diff line number Diff line
@@ -184,7 +184,17 @@ int spdk_opal_cmd_setup_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_

int spdk_opal_cmd_get_max_ranges(struct spdk_opal_dev *dev, const char *passwd);
int spdk_opal_cmd_get_locking_range_info(struct spdk_opal_dev *dev, const char *passwd,
		enum spdk_opal_user user_id,
		enum spdk_opal_locking_range locking_range_id);
int spdk_opal_cmd_enable_user(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
			      const char *passwd);
int spdk_opal_cmd_add_user_to_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
		enum spdk_opal_locking_range locking_range_id,
		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);


struct spdk_opal_locking_range_info *spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev,
		enum spdk_opal_locking_range id);
uint8_t spdk_opal_get_max_locking_ranges(struct spdk_opal_dev *dev);
+3 −0
Original line number Diff line number Diff line
@@ -177,6 +177,9 @@ enum spdk_opal_token {

	/* Autority table */
	SPDK_OPAL_AUTH_ENABLE		= 0x05,

	/* ACE table */
	SPDK_OPAL_BOOLEAN_EXPR		= 0x03,
};

/*
+290 −3
Original line number Diff line number Diff line
@@ -1048,6 +1048,19 @@ opal_start_anybody_adminsp_session(struct spdk_opal_dev *dev)
					  UID_ADMINSP, NULL, 0);
}

static int
opal_start_admin_session(struct spdk_opal_dev *dev, void *data)
{
	struct spdk_opal_key *opal_key = data;

	if (opal_key == NULL) {
		SPDK_ERRLOG("No key found for auth session\n");
		return -EINVAL;
	}
	return opal_start_generic_session(dev, UID_ADMIN1, UID_LOCKINGSP,
					  opal_key->key, opal_key->key_len);
}

static int
opal_get_msid_cpin_pin_cb(struct spdk_opal_dev *dev, void *data)
{
@@ -1540,7 +1553,7 @@ opal_get_locking_range_info_cb(struct spdk_opal_dev *dev, void *data)
		return error;
	}

	if (id > dev->max_ranges) {
	if (dev->max_ranges != 0 && id > dev->max_ranges) {
		SPDK_ERRLOG("Locking range ID not valid\n");
		return -EINVAL;
	}
@@ -1606,6 +1619,134 @@ opal_get_locking_range_info(struct spdk_opal_dev *dev,
	return opal_finalize_and_send(dev, 1, opal_get_locking_range_info_cb, &locking_range_id);
}

static int
opal_enable_user(struct spdk_opal_dev *dev, struct opal_common_session *session)
{
	int err = 0;
	uint8_t uid_user[OPAL_UID_LENGTH];

	err = opal_build_locking_user(uid_user, OPAL_UID_LENGTH, session->who);

	opal_clear_cmd(dev);
	opal_set_comid(dev, dev->comid);

	opal_add_token_u8(&err, dev, SPDK_OPAL_CALL);
	opal_add_token_bytestring(&err, dev, uid_user, OPAL_UID_LENGTH);
	opal_add_token_bytestring(&err, dev, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);

	opal_add_tokens(&err, dev, 11,
			SPDK_OPAL_STARTLIST,
			SPDK_OPAL_STARTNAME,
			SPDK_OPAL_VALUES,
			SPDK_OPAL_STARTLIST,
			SPDK_OPAL_STARTNAME,
			SPDK_OPAL_AUTH_ENABLE,
			SPDK_OPAL_TRUE,
			SPDK_OPAL_ENDNAME,
			SPDK_OPAL_ENDLIST,
			SPDK_OPAL_ENDNAME,
			SPDK_OPAL_ENDLIST);

	if (err) {
		SPDK_ERRLOG("Error Building enable user command\n");
		return err;
	}

	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
}

static int
opal_add_user_to_locking_range(struct spdk_opal_dev *dev,
			       struct spdk_opal_locking_session *locking_session)
{
	int err = 0;
	uint8_t uid_user[OPAL_UID_LENGTH];
	uint8_t uid_locking_range[OPAL_UID_LENGTH];

	err = opal_build_locking_user(uid_user, OPAL_UID_LENGTH, locking_session->session.who);
	if (err) {
		return err;
	}

	switch (locking_session->l_state) {
	case OPAL_READONLY:
		memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_RDLOCKED], OPAL_UID_LENGTH);
		break;
	case OPAL_READWRITE:
		memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_WRLOCKED], OPAL_UID_LENGTH);
		break;
	default:
		SPDK_ERRLOG("locking state should only be OPAL_READONLY or OPAL_READWRITE\n");
		return -EINVAL;
	}

	uid_locking_range[7] = locking_session->session.opal_key->locking_range;

	opal_clear_cmd(dev);
	opal_set_comid(dev, dev->comid);

	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[SET_METHOD], OPAL_UID_LENGTH);

	opal_add_tokens(&err, dev, 8,
			SPDK_OPAL_STARTLIST,
			SPDK_OPAL_STARTNAME,
			SPDK_OPAL_VALUES,
			SPDK_OPAL_STARTLIST,
			SPDK_OPAL_STARTNAME,
			SPDK_OPAL_BOOLEAN_EXPR,
			SPDK_OPAL_STARTLIST,
			SPDK_OPAL_STARTNAME);
	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
				  OPAL_UID_LENGTH / 2);
	opal_add_token_bytestring(&err, dev, uid_user, OPAL_UID_LENGTH);

	opal_add_tokens(&err, dev, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
				  OPAL_UID_LENGTH / 2);
	opal_add_token_bytestring(&err, dev, uid_user, OPAL_UID_LENGTH);

	opal_add_tokens(&err, dev, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
	opal_add_token_bytestring(&err, dev, spdk_opal_uid[UID_HALF_BOOLEAN_ACE], OPAL_UID_LENGTH / 2);
	opal_add_tokens(&err, dev, 7,
			SPDK_OPAL_TRUE,
			SPDK_OPAL_ENDNAME,
			SPDK_OPAL_ENDLIST,
			SPDK_OPAL_ENDNAME,
			SPDK_OPAL_ENDLIST,
			SPDK_OPAL_ENDNAME,
			SPDK_OPAL_ENDLIST);
	if (err) {
		SPDK_ERRLOG("Error building add user to locking range command\n");
		return err;
	}

	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
}

static int
opal_new_user_passwd(struct spdk_opal_dev *dev, struct opal_common_session *session)
{
	uint8_t uid_cpin[OPAL_UID_LENGTH];
	int ret;

	if (session->who == OPAL_ADMIN1) {
		memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_ADMIN1], OPAL_UID_LENGTH);
	} else {
		memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_USER1], OPAL_UID_LENGTH);
		uid_cpin[7] = session->who;
	}

	ret = opal_generic_pw_cmd(session->opal_key->key, session->opal_key->key_len, uid_cpin, dev);
	if (ret != 0) {
		SPDK_ERRLOG("Error building set password command\n");
		return ret;
	}

	return opal_finalize_and_send(dev, 1, opal_parse_and_check_status, NULL);
}

static int
opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, void *data)
{
@@ -1994,6 +2135,7 @@ end:

int
spdk_opal_cmd_get_locking_range_info(struct spdk_opal_dev *dev, const char *passwd,
				     enum spdk_opal_user user_id,
				     enum spdk_opal_locking_range locking_range_id)
{
	struct spdk_opal_key opal_key;
@@ -2004,14 +2146,14 @@ spdk_opal_cmd_get_locking_range_info(struct spdk_opal_dev *dev, const char *pass
		return -ENODEV;
	}

	ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
	ret = opal_init_key(&opal_key, passwd, locking_range_id);
	if (ret != 0) {
		return ret;
	}

	memset(&session, 0, sizeof(struct opal_common_session));
	session.opal_key = &opal_key;
	session.who = OPAL_ADMIN1;
	session.who = user_id;

	pthread_mutex_lock(&dev->mutex_lock);
	ret = opal_start_auth_session(dev, &session);
@@ -2037,6 +2179,151 @@ end:
	return ret;
}

int
spdk_opal_cmd_enable_user(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
			  const char *passwd)
{
	struct spdk_opal_key opal_key;
	struct opal_common_session session;
	int ret;

	if (!dev || dev->supported == false) {
		return -ENODEV;
	}

	ret = opal_init_key(&opal_key, passwd, OPAL_LOCKING_RANGE_GLOBAL);
	if (ret != 0) {
		return ret;
	}

	memset(&session, 0, sizeof(struct opal_common_session));
	session.opal_key = &opal_key;
	session.who = user_id;

	pthread_mutex_lock(&dev->mutex_lock);
	ret = opal_start_admin_session(dev, session.opal_key);
	if (ret) {
		SPDK_ERRLOG("start locking SP session error %d: %s\n", ret, opal_error_to_human(ret));
		pthread_mutex_unlock(&dev->mutex_lock);
		return ret;
	}

	ret = opal_enable_user(dev, &session);
	if (ret) {
		SPDK_ERRLOG("enable user 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;
}

int
spdk_opal_cmd_add_user_to_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
					enum spdk_opal_locking_range locking_range_id,
					enum spdk_opal_lock_state lock_flag, const char *passwd)
{
	struct spdk_opal_key opal_key;
	struct spdk_opal_locking_session locking_session;
	int ret;

	if (!dev || dev->supported == false) {
		return -ENODEV;
	}

	ret = opal_init_key(&opal_key, passwd, locking_range_id);
	if (ret != 0) {
		return ret;
	}

	memset(&locking_session, 0, sizeof(struct spdk_opal_locking_session));
	locking_session.session.opal_key = &opal_key;
	locking_session.session.who = user_id;
	locking_session.l_state = lock_flag;

	pthread_mutex_lock(&dev->mutex_lock);
	ret = opal_start_admin_session(dev, locking_session.session.opal_key);
	if (ret) {
		SPDK_ERRLOG("start locking SP session error %d: %s\n", ret, opal_error_to_human(ret));
		pthread_mutex_unlock(&dev->mutex_lock);
		return ret;
	}

	ret = opal_add_user_to_locking_range(dev, &locking_session);
	if (ret) {
		SPDK_ERRLOG("add user to locking range 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;
}

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)
{
	struct spdk_opal_key old_key;
	struct spdk_opal_key new_key;
	struct spdk_opal_new_pw_session session;
	int ret;

	if (!dev || dev->supported == false) {
		return -ENODEV;
	}

	ret = opal_init_key(&old_key, old_passwd, OPAL_LOCKING_RANGE_GLOBAL);
	if (ret != 0) {
		return ret;
	}

	ret = opal_init_key(&new_key, new_passwd, OPAL_LOCKING_RANGE_GLOBAL);
	if (ret != 0) {
		return ret;
	}

	memset(&session, 0, sizeof(struct spdk_opal_new_pw_session));
	session.new_session.who = user_id;
	session.new_session.opal_key = &new_key;
	session.old_session.who = new_user ? OPAL_ADMIN1 : user_id;
	session.old_session.opal_key = &old_key;

	pthread_mutex_lock(&dev->mutex_lock);
	ret = opal_start_auth_session(dev, &session.old_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_new_user_passwd(dev, &session.new_session);
	if (ret) {
		SPDK_ERRLOG("set new passwd 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)
{
Loading