xref: /spdk/lib/nvme/nvme_opal.c (revision 58549382d02320e5d13bd57a16e33c39dc648848)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2019 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/opal.h"
7 #include "spdk/log.h"
8 #include "spdk/util.h"
9 
10 #include "nvme_opal_internal.h"
11 
12 static void
13 opal_nvme_security_recv_done(void *arg, const struct spdk_nvme_cpl *cpl)
14 {
15 	struct opal_session *sess = arg;
16 	struct spdk_opal_dev *dev = sess->dev;
17 	void *response = sess->resp;
18 	struct spdk_opal_compacket *header = response;
19 	int ret;
20 
21 	if (spdk_nvme_cpl_is_error(cpl)) {
22 		sess->sess_cb(sess, -EIO, sess->cb_arg);
23 		return;
24 	}
25 
26 	if (!header->outstanding_data && !header->min_transfer) {
27 		sess->sess_cb(sess, 0, sess->cb_arg);
28 		return;
29 	}
30 
31 	memset(response, 0, IO_BUFFER_LENGTH);
32 	ret = spdk_nvme_ctrlr_cmd_security_receive(dev->ctrlr, SPDK_SCSI_SECP_TCG,
33 			dev->comid, 0, sess->resp, IO_BUFFER_LENGTH,
34 			opal_nvme_security_recv_done, sess);
35 	if (ret) {
36 		sess->sess_cb(sess, ret, sess->cb_arg);
37 	}
38 }
39 
40 static void
41 opal_nvme_security_send_done(void *arg, const struct spdk_nvme_cpl *cpl)
42 {
43 	struct opal_session *sess = arg;
44 	struct spdk_opal_dev *dev = sess->dev;
45 	int ret;
46 
47 	if (spdk_nvme_cpl_is_error(cpl)) {
48 		sess->sess_cb(sess, -EIO, sess->cb_arg);
49 		return;
50 	}
51 
52 	ret = spdk_nvme_ctrlr_cmd_security_receive(dev->ctrlr, SPDK_SCSI_SECP_TCG,
53 			dev->comid, 0, sess->resp, IO_BUFFER_LENGTH,
54 			opal_nvme_security_recv_done, sess);
55 	if (ret) {
56 		sess->sess_cb(sess, ret, sess->cb_arg);
57 	}
58 }
59 
60 static int
61 opal_nvme_security_send(struct spdk_opal_dev *dev, struct opal_session *sess,
62 			opal_sess_cb sess_cb, void *cb_arg)
63 {
64 	sess->sess_cb = sess_cb;
65 	sess->cb_arg = cb_arg;
66 
67 	return spdk_nvme_ctrlr_cmd_security_send(dev->ctrlr, SPDK_SCSI_SECP_TCG, dev->comid,
68 			0, sess->cmd, IO_BUFFER_LENGTH,
69 			opal_nvme_security_send_done, sess);
70 }
71 
72 static void
73 opal_send_recv_done(struct opal_session *sess, int status, void *ctx)
74 {
75 	sess->status = status;
76 	sess->done = true;
77 }
78 
79 static int
80 opal_send_recv(struct spdk_opal_dev *dev, struct opal_session *sess)
81 {
82 	int ret;
83 
84 	sess->done = false;
85 	ret = opal_nvme_security_send(dev, sess, opal_send_recv_done, NULL);
86 	if (ret) {
87 		return ret;
88 	}
89 
90 	while (!sess->done) {
91 		spdk_nvme_ctrlr_process_admin_completions(dev->ctrlr);
92 	}
93 
94 	return sess->status;
95 }
96 
97 static struct opal_session *
98 opal_alloc_session(struct spdk_opal_dev *dev)
99 {
100 	struct opal_session *sess;
101 
102 	sess = calloc(1, sizeof(*sess));
103 	if (!sess) {
104 		return NULL;
105 	}
106 	sess->dev = dev;
107 
108 	return sess;
109 }
110 
111 static void
112 opal_add_token_u8(int *err, struct opal_session *sess, uint8_t token)
113 {
114 	if (*err) {
115 		return;
116 	}
117 	if (sess->cmd_pos >= IO_BUFFER_LENGTH - 1) {
118 		SPDK_ERRLOG("Error adding u8: end of buffer.\n");
119 		*err = -ERANGE;
120 		return;
121 	}
122 	sess->cmd[sess->cmd_pos++] = token;
123 }
124 
125 static void
126 opal_add_short_atom_header(struct opal_session *sess, bool bytestring,
127 			   bool has_sign, size_t len)
128 {
129 	uint8_t atom;
130 	int err = 0;
131 
132 	atom = SPDK_SHORT_ATOM_ID;
133 	atom |= bytestring ? SPDK_SHORT_ATOM_BYTESTRING_FLAG : 0;
134 	atom |= has_sign ? SPDK_SHORT_ATOM_SIGN_FLAG : 0;
135 	atom |= len & SPDK_SHORT_ATOM_LEN_MASK;
136 
137 	opal_add_token_u8(&err, sess, atom);
138 }
139 
140 static void
141 opal_add_medium_atom_header(struct opal_session *sess, bool bytestring,
142 			    bool has_sign, size_t len)
143 {
144 	uint8_t header;
145 
146 	header = SPDK_MEDIUM_ATOM_ID;
147 	header |= bytestring ? SPDK_MEDIUM_ATOM_BYTESTRING_FLAG : 0;
148 	header |= has_sign ? SPDK_MEDIUM_ATOM_SIGN_FLAG : 0;
149 	header |= (len >> 8) & SPDK_MEDIUM_ATOM_LEN_MASK;
150 	sess->cmd[sess->cmd_pos++] = header;
151 	sess->cmd[sess->cmd_pos++] = len;
152 }
153 
154 static void
155 opal_add_token_bytestring(int *err, struct opal_session *sess,
156 			  const uint8_t *bytestring, size_t len)
157 {
158 	size_t header_len = 1;
159 	bool is_short_atom = true;
160 
161 	if (*err) {
162 		return;
163 	}
164 
165 	if (len & ~SPDK_SHORT_ATOM_LEN_MASK) {
166 		header_len = 2;
167 		is_short_atom = false;
168 	}
169 
170 	if (len >= IO_BUFFER_LENGTH - sess->cmd_pos - header_len) {
171 		SPDK_ERRLOG("Error adding bytestring: end of buffer.\n");
172 		*err = -ERANGE;
173 		return;
174 	}
175 
176 	if (is_short_atom) {
177 		opal_add_short_atom_header(sess, true, false, len);
178 	} else {
179 		opal_add_medium_atom_header(sess, true, false, len);
180 	}
181 
182 	memcpy(&sess->cmd[sess->cmd_pos], bytestring, len);
183 	sess->cmd_pos += len;
184 }
185 
186 static void
187 opal_add_token_u64(int *err, struct opal_session *sess, uint64_t number)
188 {
189 	int startat = 0;
190 
191 	if (*err) {
192 		return;
193 	}
194 
195 	/* add header first */
196 	if (number <= SPDK_TINY_ATOM_DATA_MASK) {
197 		sess->cmd[sess->cmd_pos++] = (uint8_t) number & SPDK_TINY_ATOM_DATA_MASK;
198 	} else {
199 		if (number < 0x100) {
200 			sess->cmd[sess->cmd_pos++] = 0x81; /* short atom, 1 byte length */
201 			startat = 0;
202 		} else if (number < 0x10000) {
203 			sess->cmd[sess->cmd_pos++] = 0x82; /* short atom, 2 byte length */
204 			startat = 1;
205 		} else if (number < 0x100000000) {
206 			sess->cmd[sess->cmd_pos++] = 0x84; /* short atom, 4 byte length */
207 			startat = 3;
208 		} else {
209 			sess->cmd[sess->cmd_pos++] = 0x88; /* short atom, 8 byte length */
210 			startat = 7;
211 		}
212 
213 		/* add number value */
214 		for (int i = startat; i > -1; i--) {
215 			sess->cmd[sess->cmd_pos++] = (uint8_t)((number >> (i * 8)) & 0xff);
216 		}
217 	}
218 }
219 
220 static void
221 opal_add_tokens(int *err, struct opal_session *sess, int num, ...)
222 {
223 	int i;
224 	va_list args_ptr;
225 	enum spdk_opal_token tmp;
226 
227 	va_start(args_ptr, num);
228 
229 	for (i = 0; i < num; i++) {
230 		tmp = va_arg(args_ptr, enum spdk_opal_token);
231 		opal_add_token_u8(err, sess, tmp);
232 		if (*err != 0) { break; }
233 	}
234 
235 	va_end(args_ptr);
236 }
237 
238 static int
239 opal_cmd_finalize(struct opal_session *sess, uint32_t hsn, uint32_t tsn, bool eod)
240 {
241 	struct spdk_opal_header *hdr;
242 	int err = 0;
243 
244 	if (eod) {
245 		opal_add_tokens(&err, sess, 6, SPDK_OPAL_ENDOFDATA,
246 				SPDK_OPAL_STARTLIST,
247 				0, 0, 0,
248 				SPDK_OPAL_ENDLIST);
249 	}
250 
251 	if (err) {
252 		SPDK_ERRLOG("Error finalizing command.\n");
253 		return -EFAULT;
254 	}
255 
256 	hdr = (struct spdk_opal_header *)sess->cmd;
257 
258 	to_be32(&hdr->packet.session_tsn, tsn);
259 	to_be32(&hdr->packet.session_hsn, hsn);
260 
261 	to_be32(&hdr->sub_packet.length, sess->cmd_pos - sizeof(*hdr));
262 	while (sess->cmd_pos % 4) {
263 		if (sess->cmd_pos >= IO_BUFFER_LENGTH) {
264 			SPDK_ERRLOG("Error: Buffer overrun\n");
265 			return -ERANGE;
266 		}
267 		sess->cmd[sess->cmd_pos++] = 0;
268 	}
269 	to_be32(&hdr->packet.length, sess->cmd_pos - sizeof(hdr->com_packet) -
270 		sizeof(hdr->packet));
271 	to_be32(&hdr->com_packet.length, sess->cmd_pos - sizeof(hdr->com_packet));
272 
273 	return 0;
274 }
275 
276 static size_t
277 opal_response_parse_tiny(struct spdk_opal_resp_token *token,
278 			 const uint8_t *pos)
279 {
280 	token->pos = pos;
281 	token->len = 1;
282 	token->width = OPAL_WIDTH_TINY;
283 
284 	if (pos[0] & SPDK_TINY_ATOM_SIGN_FLAG) {
285 		token->type = OPAL_DTA_TOKENID_SINT;
286 	} else {
287 		token->type = OPAL_DTA_TOKENID_UINT;
288 		token->stored.unsigned_num = pos[0] & SPDK_TINY_ATOM_DATA_MASK;
289 	}
290 
291 	return token->len;
292 }
293 
294 static int
295 opal_response_parse_short(struct spdk_opal_resp_token *token,
296 			  const uint8_t *pos)
297 {
298 	token->pos = pos;
299 	token->len = (pos[0] & SPDK_SHORT_ATOM_LEN_MASK) + 1; /* plus 1-byte header */
300 	token->width = OPAL_WIDTH_SHORT;
301 
302 	if (pos[0] & SPDK_SHORT_ATOM_BYTESTRING_FLAG) {
303 		token->type = OPAL_DTA_TOKENID_BYTESTRING;
304 	} else if (pos[0] & SPDK_SHORT_ATOM_SIGN_FLAG) {
305 		token->type = OPAL_DTA_TOKENID_SINT;
306 	} else {
307 		uint64_t u_integer = 0;
308 		size_t i, b = 0;
309 
310 		token->type = OPAL_DTA_TOKENID_UINT;
311 		if (token->len > 9) {
312 			SPDK_ERRLOG("uint64 with more than 8 bytes\n");
313 			return -EINVAL;
314 		}
315 		for (i = token->len - 1; i > 0; i--) {
316 			u_integer |= ((uint64_t)pos[i] << (8 * b));
317 			b++;
318 		}
319 		token->stored.unsigned_num = u_integer;
320 	}
321 
322 	return token->len;
323 }
324 
325 static size_t
326 opal_response_parse_medium(struct spdk_opal_resp_token *token,
327 			   const uint8_t *pos)
328 {
329 	token->pos = pos;
330 	token->len = (((pos[0] & SPDK_MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2; /* plus 2-byte header */
331 	token->width = OPAL_WIDTH_MEDIUM;
332 
333 	if (pos[0] & SPDK_MEDIUM_ATOM_BYTESTRING_FLAG) {
334 		token->type = OPAL_DTA_TOKENID_BYTESTRING;
335 	} else if (pos[0] & SPDK_MEDIUM_ATOM_SIGN_FLAG) {
336 		token->type = OPAL_DTA_TOKENID_SINT;
337 	} else {
338 		token->type = OPAL_DTA_TOKENID_UINT;
339 	}
340 
341 	return token->len;
342 }
343 
344 static size_t
345 opal_response_parse_long(struct spdk_opal_resp_token *token,
346 			 const uint8_t *pos)
347 {
348 	token->pos = pos;
349 	token->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4; /* plus 4-byte header */
350 	token->width = OPAL_WIDTH_LONG;
351 
352 	if (pos[0] & SPDK_LONG_ATOM_BYTESTRING_FLAG) {
353 		token->type = OPAL_DTA_TOKENID_BYTESTRING;
354 	} else if (pos[0] & SPDK_LONG_ATOM_SIGN_FLAG) {
355 		token->type = OPAL_DTA_TOKENID_SINT;
356 	} else {
357 		token->type = OPAL_DTA_TOKENID_UINT;
358 	}
359 
360 	return token->len;
361 }
362 
363 static size_t
364 opal_response_parse_token(struct spdk_opal_resp_token *token,
365 			  const uint8_t *pos)
366 {
367 	token->pos = pos;
368 	token->len = 1;
369 	token->type = OPAL_DTA_TOKENID_TOKEN;
370 	token->width = OPAL_WIDTH_TOKEN;
371 
372 	return token->len;
373 }
374 
375 static int
376 opal_response_parse(const uint8_t *buf, size_t length,
377 		    struct spdk_opal_resp_parsed *resp)
378 {
379 	const struct spdk_opal_header *hdr;
380 	struct spdk_opal_resp_token *token_iter;
381 	int num_entries = 0;
382 	int total;
383 	size_t token_length;
384 	const uint8_t *pos;
385 	uint32_t clen, plen, slen;
386 
387 	if (!buf || !resp) {
388 		return -EINVAL;
389 	}
390 
391 	hdr = (struct spdk_opal_header *)buf;
392 	pos = buf + sizeof(*hdr);
393 
394 	clen = from_be32(&hdr->com_packet.length);
395 	plen = from_be32(&hdr->packet.length);
396 	slen = from_be32(&hdr->sub_packet.length);
397 	SPDK_DEBUGLOG(opal, "Response size: cp: %u, pkt: %u, subpkt: %u\n",
398 		      clen, plen, slen);
399 
400 	if (clen == 0 || plen == 0 || slen == 0 ||
401 	    slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
402 		SPDK_ERRLOG("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
403 			    clen, plen, slen);
404 		return -EINVAL;
405 	}
406 
407 	if (pos > buf + length) {
408 		SPDK_ERRLOG("Pointer out of range\n");
409 		return -EFAULT;
410 	}
411 
412 	token_iter = resp->resp_tokens;
413 	total = slen;
414 
415 	while (total > 0) {
416 		if (pos[0] <= SPDK_TINY_ATOM_TYPE_MAX) { /* tiny atom */
417 			token_length = opal_response_parse_tiny(token_iter, pos);
418 		} else if (pos[0] <= SPDK_SHORT_ATOM_TYPE_MAX) { /* short atom */
419 			token_length = opal_response_parse_short(token_iter, pos);
420 		} else if (pos[0] <= SPDK_MEDIUM_ATOM_TYPE_MAX) { /* medium atom */
421 			token_length = opal_response_parse_medium(token_iter, pos);
422 		} else if (pos[0] <= SPDK_LONG_ATOM_TYPE_MAX) { /* long atom */
423 			token_length = opal_response_parse_long(token_iter, pos);
424 		} else { /* TOKEN */
425 			token_length = opal_response_parse_token(token_iter, pos);
426 		}
427 
428 		if (token_length <= 0) {
429 			SPDK_ERRLOG("Parse response failure.\n");
430 			return -EINVAL;
431 		}
432 
433 		pos += token_length;
434 		total -= token_length;
435 		token_iter++;
436 		num_entries++;
437 
438 		if (total < 0) {
439 			SPDK_ERRLOG("Length not matching.\n");
440 			return -EINVAL;
441 		}
442 	}
443 
444 	if (num_entries == 0) {
445 		SPDK_ERRLOG("Couldn't parse response.\n");
446 		return -EINVAL;
447 	}
448 	resp->num = num_entries;
449 
450 	return 0;
451 }
452 
453 static inline bool
454 opal_response_token_matches(const struct spdk_opal_resp_token *token,
455 			    uint8_t match)
456 {
457 	if (!token ||
458 	    token->type != OPAL_DTA_TOKENID_TOKEN ||
459 	    token->pos[0] != match) {
460 		return false;
461 	}
462 	return true;
463 }
464 
465 static const struct spdk_opal_resp_token *
466 opal_response_get_token(const struct spdk_opal_resp_parsed *resp, int index)
467 {
468 	const struct spdk_opal_resp_token *token;
469 
470 	if (index >= resp->num) {
471 		SPDK_ERRLOG("Token number doesn't exist: %d, resp: %d\n",
472 			    index, resp->num);
473 		return NULL;
474 	}
475 
476 	token = &resp->resp_tokens[index];
477 	if (token->len == 0) {
478 		SPDK_ERRLOG("Token length must be non-zero\n");
479 		return NULL;
480 	}
481 
482 	return token;
483 }
484 
485 static uint64_t
486 opal_response_get_u64(const struct spdk_opal_resp_parsed *resp, int index)
487 {
488 	if (!resp) {
489 		SPDK_ERRLOG("Response is NULL\n");
490 		return 0;
491 	}
492 
493 	if (resp->resp_tokens[index].type != OPAL_DTA_TOKENID_UINT) {
494 		SPDK_ERRLOG("Token is not unsigned int: %d\n",
495 			    resp->resp_tokens[index].type);
496 		return 0;
497 	}
498 
499 	if (!(resp->resp_tokens[index].width == OPAL_WIDTH_TINY ||
500 	      resp->resp_tokens[index].width == OPAL_WIDTH_SHORT)) {
501 		SPDK_ERRLOG("Atom is not short or tiny: %d\n",
502 			    resp->resp_tokens[index].width);
503 		return 0;
504 	}
505 
506 	return resp->resp_tokens[index].stored.unsigned_num;
507 }
508 
509 static uint16_t
510 opal_response_get_u16(const struct spdk_opal_resp_parsed *resp, int index)
511 {
512 	uint64_t i = opal_response_get_u64(resp, index);
513 	if (i > 0xffffull) {
514 		SPDK_ERRLOG("parse response u16 failed. Overflow\n");
515 		return 0;
516 	}
517 	return (uint16_t) i;
518 }
519 
520 static uint8_t
521 opal_response_get_u8(const struct spdk_opal_resp_parsed *resp, int index)
522 {
523 	uint64_t i = opal_response_get_u64(resp, index);
524 	if (i > 0xffull) {
525 		SPDK_ERRLOG("parse response u8 failed. Overflow\n");
526 		return 0;
527 	}
528 	return (uint8_t) i;
529 }
530 
531 static size_t
532 opal_response_get_string(const struct spdk_opal_resp_parsed *resp, int n,
533 			 const char **store)
534 {
535 	uint8_t header_len;
536 	struct spdk_opal_resp_token token;
537 	*store = NULL;
538 	if (!resp) {
539 		SPDK_ERRLOG("Response is NULL\n");
540 		return 0;
541 	}
542 
543 	if (n > resp->num) {
544 		SPDK_ERRLOG("Response has %d tokens. Can't access %d\n",
545 			    resp->num, n);
546 		return 0;
547 	}
548 
549 	token = resp->resp_tokens[n];
550 	if (token.type != OPAL_DTA_TOKENID_BYTESTRING) {
551 		SPDK_ERRLOG("Token is not a byte string!\n");
552 		return 0;
553 	}
554 
555 	switch (token.width) {
556 	case OPAL_WIDTH_SHORT:
557 		header_len = 1;
558 		break;
559 	case OPAL_WIDTH_MEDIUM:
560 		header_len = 2;
561 		break;
562 	case OPAL_WIDTH_LONG:
563 		header_len = 4;
564 		break;
565 	default:
566 		SPDK_ERRLOG("Can't get string from this Token\n");
567 		return 0;
568 	}
569 
570 	*store = token.pos + header_len;
571 	return token.len - header_len;
572 }
573 
574 static int
575 opal_response_status(const struct spdk_opal_resp_parsed *resp)
576 {
577 	const struct spdk_opal_resp_token *tok;
578 
579 	/* if we get an EOS token, just return 0 */
580 	tok = opal_response_get_token(resp, 0);
581 	if (opal_response_token_matches(tok, SPDK_OPAL_ENDOFSESSION)) {
582 		return 0;
583 	}
584 
585 	if (resp->num < 5) {
586 		return SPDK_DTAERROR_NO_METHOD_STATUS;
587 	}
588 
589 	tok = opal_response_get_token(resp, resp->num - 5); /* the first token should be STARTLIST */
590 	if (!opal_response_token_matches(tok, SPDK_OPAL_STARTLIST)) {
591 		return SPDK_DTAERROR_NO_METHOD_STATUS;
592 	}
593 
594 	tok = opal_response_get_token(resp, resp->num - 1); /* the last token should be ENDLIST */
595 	if (!opal_response_token_matches(tok, SPDK_OPAL_ENDLIST)) {
596 		return SPDK_DTAERROR_NO_METHOD_STATUS;
597 	}
598 
599 	/* The second and third values in the status list are reserved, and are
600 	defined in core spec to be 0x00 and 0x00 and SHOULD be ignored by the host. */
601 	return (int)opal_response_get_u64(resp,
602 					  resp->num - 4); /* We only need the first value in the status list. */
603 }
604 
605 static int
606 opal_parse_and_check_status(struct opal_session *sess)
607 {
608 	int error;
609 
610 	error = opal_response_parse(sess->resp, IO_BUFFER_LENGTH, &sess->parsed_resp);
611 	if (error) {
612 		SPDK_ERRLOG("Couldn't parse response.\n");
613 		return error;
614 	}
615 	return opal_response_status(&sess->parsed_resp);
616 }
617 
618 static inline void
619 opal_clear_cmd(struct opal_session *sess)
620 {
621 	sess->cmd_pos = sizeof(struct spdk_opal_header);
622 	memset(sess->cmd, 0, IO_BUFFER_LENGTH);
623 }
624 
625 static inline void
626 opal_set_comid(struct opal_session *sess, uint16_t comid)
627 {
628 	struct spdk_opal_header *hdr = (struct spdk_opal_header *)sess->cmd;
629 
630 	hdr->com_packet.comid[0] = comid >> 8;
631 	hdr->com_packet.comid[1] = comid;
632 	hdr->com_packet.extended_comid[0] = 0;
633 	hdr->com_packet.extended_comid[1] = 0;
634 }
635 
636 static inline int
637 opal_init_key(struct spdk_opal_key *opal_key, const char *passwd)
638 {
639 	int len;
640 
641 	if (passwd == NULL || passwd[0] == '\0') {
642 		SPDK_ERRLOG("Password is empty. Create key failed\n");
643 		return -EINVAL;
644 	}
645 
646 	len = strlen(passwd);
647 
648 	if (len >= OPAL_KEY_MAX) {
649 		SPDK_ERRLOG("Password too long. Create key failed\n");
650 		return -EINVAL;
651 	}
652 
653 	opal_key->key_len = len;
654 	memcpy(opal_key->key, passwd, opal_key->key_len);
655 
656 	return 0;
657 }
658 
659 static void
660 opal_build_locking_range(uint8_t *buffer, uint8_t locking_range)
661 {
662 	memcpy(buffer, spdk_opal_uid[UID_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
663 
664 	/* global */
665 	if (locking_range == 0) {
666 		return;
667 	}
668 
669 	/* non-global */
670 	buffer[5] = LOCKING_RANGE_NON_GLOBAL;
671 	buffer[7] = locking_range;
672 }
673 
674 static void
675 opal_check_tper(struct spdk_opal_dev *dev, const void *data)
676 {
677 	const struct spdk_opal_d0_tper_feat *tper = data;
678 
679 	dev->feat_info.tper = *tper;
680 }
681 
682 /*
683  * check single user mode
684  */
685 static bool
686 opal_check_sum(struct spdk_opal_dev *dev, const void *data)
687 {
688 	const struct spdk_opal_d0_single_user_mode_feat *sum = data;
689 	uint32_t num_locking_objects = from_be32(&sum->num_locking_objects);
690 
691 	if (num_locking_objects == 0) {
692 		SPDK_NOTICELOG("Need at least one locking object.\n");
693 		return false;
694 	}
695 
696 	dev->feat_info.single_user = *sum;
697 
698 	return true;
699 }
700 
701 static void
702 opal_check_lock(struct spdk_opal_dev *dev, const void *data)
703 {
704 	const struct spdk_opal_d0_locking_feat *lock = data;
705 
706 	dev->feat_info.locking = *lock;
707 }
708 
709 static void
710 opal_check_geometry(struct spdk_opal_dev *dev, const void *data)
711 {
712 	const struct spdk_opal_d0_geo_feat *geo = data;
713 
714 	dev->feat_info.geo = *geo;
715 }
716 
717 static void
718 opal_check_datastore(struct spdk_opal_dev *dev, const void *data)
719 {
720 	const struct spdk_opal_d0_datastore_feat *datastore = data;
721 
722 	dev->feat_info.datastore = *datastore;
723 }
724 
725 static uint16_t
726 opal_get_comid_v100(struct spdk_opal_dev *dev, const void *data)
727 {
728 	const struct spdk_opal_d0_v100_feat *v100 = data;
729 	uint16_t base_comid = from_be16(&v100->base_comid);
730 
731 	dev->feat_info.v100 = *v100;
732 
733 	return base_comid;
734 }
735 
736 static uint16_t
737 opal_get_comid_v200(struct spdk_opal_dev *dev, const void *data)
738 {
739 	const struct spdk_opal_d0_v200_feat *v200 = data;
740 	uint16_t base_comid = from_be16(&v200->base_comid);
741 
742 	dev->feat_info.v200 = *v200;
743 
744 	return base_comid;
745 }
746 
747 static int
748 opal_discovery0_end(struct spdk_opal_dev *dev, void *payload, uint32_t payload_size)
749 {
750 	bool supported = false, single_user = false;
751 	const struct spdk_opal_d0_hdr *hdr = (struct spdk_opal_d0_hdr *)payload;
752 	struct spdk_opal_d0_feat_hdr *feat_hdr;
753 	const uint8_t *epos = payload, *cpos = payload;
754 	uint16_t comid = 0;
755 	uint32_t hlen = from_be32(&(hdr->length));
756 
757 	if (hlen > payload_size - sizeof(*hdr)) {
758 		SPDK_ERRLOG("Discovery length overflows buffer (%zu+%u)/%u\n",
759 			    sizeof(*hdr), hlen, payload_size);
760 		return -EFAULT;
761 	}
762 
763 	epos += hlen; /* end of buffer */
764 	cpos += sizeof(*hdr); /* current position on buffer */
765 
766 	while (cpos < epos) {
767 		feat_hdr = (struct spdk_opal_d0_feat_hdr *)cpos;
768 		uint16_t feat_code = from_be16(&feat_hdr->code);
769 
770 		switch (feat_code) {
771 		case FEATURECODE_TPER:
772 			opal_check_tper(dev, cpos);
773 			break;
774 		case FEATURECODE_SINGLEUSER:
775 			single_user = opal_check_sum(dev, cpos);
776 			break;
777 		case FEATURECODE_GEOMETRY:
778 			opal_check_geometry(dev, cpos);
779 			break;
780 		case FEATURECODE_LOCKING:
781 			opal_check_lock(dev, cpos);
782 			break;
783 		case FEATURECODE_DATASTORE:
784 			opal_check_datastore(dev, cpos);
785 			break;
786 		case FEATURECODE_OPALV100:
787 			comid = opal_get_comid_v100(dev, cpos);
788 			supported = true;
789 			break;
790 		case FEATURECODE_OPALV200:
791 			comid = opal_get_comid_v200(dev, cpos);
792 			supported = true;
793 			break;
794 		default:
795 			SPDK_INFOLOG(opal, "Unknown feature code: %d\n", feat_code);
796 		}
797 		cpos += feat_hdr->length + sizeof(*feat_hdr);
798 	}
799 
800 	if (supported == false) {
801 		SPDK_INFOLOG(opal, "Opal Not Supported.\n");
802 		return -ENOTSUP;
803 	}
804 
805 	if (single_user == false) {
806 		SPDK_INFOLOG(opal, "Single User Mode Not Supported\n");
807 	}
808 
809 	dev->comid = comid;
810 	return 0;
811 }
812 
813 static int
814 opal_discovery0(struct spdk_opal_dev *dev, void *payload, uint32_t payload_size)
815 {
816 	int ret;
817 	uint16_t i, sp_list_len;
818 	uint8_t *sp_list;
819 	bool sp_tcg_supported = false;
820 
821 	/* NVMe 1.4 chapter 5.25.2 Security Protocol 00h */
822 	ret = spdk_nvme_ctrlr_security_receive(dev->ctrlr, SPDK_SCSI_SECP_INFO, 0,
823 					       0, payload, payload_size);
824 	if (ret) {
825 		return ret;
826 	}
827 
828 	/* spc4r31 chapter 7.7.1.3 Supported security protocols list description */
829 	sp_list_len = from_be16(payload + 6);
830 	sp_list = (uint8_t *)payload + 8;
831 
832 	if (sp_list_len + 8 > (int)payload_size) {
833 		return -EINVAL;
834 	}
835 
836 	for (i = 0; i < sp_list_len; i++) {
837 		if (sp_list[i] == SPDK_SCSI_SECP_TCG) {
838 			sp_tcg_supported = true;
839 			break;
840 		}
841 	}
842 
843 	if (!sp_tcg_supported) {
844 		return -ENOTSUP;
845 	}
846 
847 	memset(payload, 0, payload_size);
848 	ret = spdk_nvme_ctrlr_security_receive(dev->ctrlr, SPDK_SCSI_SECP_TCG, LV0_DISCOVERY_COMID,
849 					       0, payload, payload_size);
850 	if (ret) {
851 		return ret;
852 	}
853 
854 	return opal_discovery0_end(dev, payload, payload_size);
855 }
856 
857 static int
858 opal_end_session(struct spdk_opal_dev *dev, struct opal_session *sess, uint16_t comid)
859 {
860 	int err = 0;
861 	int ret;
862 
863 	opal_clear_cmd(sess);
864 	opal_set_comid(sess, comid);
865 	opal_add_token_u8(&err, sess, SPDK_OPAL_ENDOFSESSION);
866 
867 	if (err < 0) {
868 		return err;
869 	}
870 
871 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, false);
872 	if (ret) {
873 		return ret;
874 	}
875 
876 	ret = opal_send_recv(dev, sess);
877 	if (ret) {
878 		return ret;
879 	}
880 
881 	sess->hsn = 0;
882 	sess->tsn = 0;
883 
884 	return opal_parse_and_check_status(sess);
885 }
886 
887 void
888 spdk_opal_dev_destruct(struct spdk_opal_dev *dev)
889 {
890 	free(dev);
891 }
892 
893 static int
894 opal_start_session_done(struct opal_session *sess)
895 {
896 	uint32_t hsn, tsn;
897 	int error = 0;
898 
899 	error = opal_parse_and_check_status(sess);
900 	if (error) {
901 		return error;
902 	}
903 
904 	hsn = opal_response_get_u64(&sess->parsed_resp, 4);
905 	tsn = opal_response_get_u64(&sess->parsed_resp, 5);
906 
907 	if (hsn == 0 && tsn == 0) {
908 		SPDK_ERRLOG("Couldn't authenticate session\n");
909 		return -EPERM;
910 	}
911 
912 	sess->hsn = hsn;
913 	sess->tsn = tsn;
914 
915 	return 0;
916 }
917 
918 static int
919 opal_start_generic_session(struct spdk_opal_dev *dev,
920 			   struct opal_session *sess,
921 			   enum opal_uid_enum auth,
922 			   enum opal_uid_enum sp_type,
923 			   const char *key,
924 			   uint8_t key_len)
925 {
926 	uint32_t hsn;
927 	int err = 0;
928 	int ret;
929 
930 	if (key == NULL && auth != UID_ANYBODY) {
931 		return OPAL_INVAL_PARAM;
932 	}
933 
934 	opal_clear_cmd(sess);
935 
936 	opal_set_comid(sess, dev->comid);
937 	hsn = GENERIC_HOST_SESSION_NUM;
938 
939 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
940 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_SMUID],
941 				  OPAL_UID_LENGTH);
942 	opal_add_token_bytestring(&err, sess, spdk_opal_method[STARTSESSION_METHOD],
943 				  OPAL_UID_LENGTH);
944 	opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
945 	opal_add_token_u64(&err, sess, hsn);
946 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[sp_type], OPAL_UID_LENGTH);
947 	opal_add_token_u8(&err, sess, SPDK_OPAL_TRUE); /* Write */
948 
949 	switch (auth) {
950 	case UID_ANYBODY:
951 		opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
952 		break;
953 	case UID_ADMIN1:
954 	case UID_SID:
955 		opal_add_token_u8(&err, sess, SPDK_OPAL_STARTNAME);
956 		opal_add_token_u8(&err, sess, 0); /* HostChallenge */
957 		opal_add_token_bytestring(&err, sess, key, key_len);
958 		opal_add_tokens(&err, sess, 3,    /* number of token */
959 				SPDK_OPAL_ENDNAME,
960 				SPDK_OPAL_STARTNAME,
961 				3);/* HostSignAuth */
962 		opal_add_token_bytestring(&err, sess, spdk_opal_uid[auth],
963 					  OPAL_UID_LENGTH);
964 		opal_add_token_u8(&err, sess, SPDK_OPAL_ENDNAME);
965 		opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
966 		break;
967 	default:
968 		SPDK_ERRLOG("Cannot start Admin SP session with auth %d\n", auth);
969 		return -EINVAL;
970 	}
971 
972 	if (err) {
973 		SPDK_ERRLOG("Error building start adminsp session command.\n");
974 		return err;
975 	}
976 
977 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
978 	if (ret) {
979 		return ret;
980 	}
981 
982 	ret = opal_send_recv(dev, sess);
983 	if (ret) {
984 		return ret;
985 	}
986 
987 	return opal_start_session_done(sess);
988 }
989 
990 static int
991 opal_get_msid_cpin_pin_done(struct opal_session *sess,
992 			    struct spdk_opal_key *opal_key)
993 {
994 	const char *msid_pin;
995 	size_t strlen;
996 	int error = 0;
997 
998 	error = opal_parse_and_check_status(sess);
999 	if (error) {
1000 		return error;
1001 	}
1002 
1003 	strlen = opal_response_get_string(&sess->parsed_resp, 4, &msid_pin);
1004 	if (!msid_pin) {
1005 		SPDK_ERRLOG("Couldn't extract PIN from response\n");
1006 		return -EINVAL;
1007 	}
1008 
1009 	opal_key->key_len = strlen;
1010 	memcpy(opal_key->key, msid_pin, opal_key->key_len);
1011 
1012 	SPDK_DEBUGLOG(opal, "MSID = %p\n", opal_key->key);
1013 	return 0;
1014 }
1015 
1016 static int
1017 opal_get_msid_cpin_pin(struct spdk_opal_dev *dev, struct opal_session *sess,
1018 		       struct spdk_opal_key *opal_key)
1019 {
1020 	int err = 0;
1021 	int ret;
1022 
1023 	opal_clear_cmd(sess);
1024 	opal_set_comid(sess, dev->comid);
1025 
1026 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1027 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_C_PIN_MSID],
1028 				  OPAL_UID_LENGTH);
1029 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1030 
1031 	opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
1032 			SPDK_OPAL_STARTLIST,
1033 			SPDK_OPAL_STARTNAME,
1034 			SPDK_OPAL_STARTCOLUMN,
1035 			SPDK_OPAL_PIN,
1036 			SPDK_OPAL_ENDNAME,
1037 			SPDK_OPAL_STARTNAME,
1038 			SPDK_OPAL_ENDCOLUMN,
1039 			SPDK_OPAL_PIN,
1040 			SPDK_OPAL_ENDNAME,
1041 			SPDK_OPAL_ENDLIST,
1042 			SPDK_OPAL_ENDLIST);
1043 
1044 	if (err) {
1045 		SPDK_ERRLOG("Error building Get MSID CPIN PIN command.\n");
1046 		return err;
1047 	}
1048 
1049 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1050 	if (ret) {
1051 		return ret;
1052 	}
1053 
1054 	ret = opal_send_recv(dev, sess);
1055 	if (ret) {
1056 		return ret;
1057 	}
1058 
1059 	return opal_get_msid_cpin_pin_done(sess, opal_key);
1060 }
1061 
1062 static int
1063 opal_build_generic_pw_cmd(struct opal_session *sess, uint8_t *key, size_t key_len,
1064 			  uint8_t *cpin_uid, struct spdk_opal_dev *dev)
1065 {
1066 	int err = 0;
1067 
1068 	opal_clear_cmd(sess);
1069 	opal_set_comid(sess, dev->comid);
1070 
1071 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1072 	opal_add_token_bytestring(&err, sess, cpin_uid, OPAL_UID_LENGTH);
1073 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD],
1074 				  OPAL_UID_LENGTH);
1075 
1076 	opal_add_tokens(&err, sess, 6,
1077 			SPDK_OPAL_STARTLIST,
1078 			SPDK_OPAL_STARTNAME,
1079 			SPDK_OPAL_VALUES,
1080 			SPDK_OPAL_STARTLIST,
1081 			SPDK_OPAL_STARTNAME,
1082 			SPDK_OPAL_PIN);
1083 	opal_add_token_bytestring(&err, sess, key, key_len);
1084 	opal_add_tokens(&err, sess, 4,
1085 			SPDK_OPAL_ENDNAME,
1086 			SPDK_OPAL_ENDLIST,
1087 			SPDK_OPAL_ENDNAME,
1088 			SPDK_OPAL_ENDLIST);
1089 	if (err) {
1090 		return err;
1091 	}
1092 
1093 	return opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1094 }
1095 
1096 static int
1097 opal_get_locking_sp_lifecycle_done(struct opal_session *sess)
1098 {
1099 	uint8_t lifecycle;
1100 	int error = 0;
1101 
1102 	error = opal_parse_and_check_status(sess);
1103 	if (error) {
1104 		return error;
1105 	}
1106 
1107 	lifecycle = opal_response_get_u64(&sess->parsed_resp, 4);
1108 	if (lifecycle != OPAL_MANUFACTURED_INACTIVE) { /* status before activate */
1109 		SPDK_ERRLOG("Couldn't determine the status of the Lifecycle state\n");
1110 		return -EINVAL;
1111 	}
1112 
1113 	return 0;
1114 }
1115 
1116 static int
1117 opal_get_locking_sp_lifecycle(struct spdk_opal_dev *dev, struct opal_session *sess)
1118 {
1119 	int err = 0;
1120 	int ret;
1121 
1122 	opal_clear_cmd(sess);
1123 	opal_set_comid(sess, dev->comid);
1124 
1125 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1126 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKINGSP],
1127 				  OPAL_UID_LENGTH);
1128 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1129 
1130 	opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
1131 			SPDK_OPAL_STARTLIST,
1132 			SPDK_OPAL_STARTNAME,
1133 			SPDK_OPAL_STARTCOLUMN,
1134 			SPDK_OPAL_LIFECYCLE,
1135 			SPDK_OPAL_ENDNAME,
1136 			SPDK_OPAL_STARTNAME,
1137 			SPDK_OPAL_ENDCOLUMN,
1138 			SPDK_OPAL_LIFECYCLE,
1139 			SPDK_OPAL_ENDNAME,
1140 			SPDK_OPAL_ENDLIST,
1141 			SPDK_OPAL_ENDLIST);
1142 
1143 	if (err) {
1144 		SPDK_ERRLOG("Error Building GET Lifecycle Status command\n");
1145 		return err;
1146 	}
1147 
1148 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1149 	if (ret) {
1150 		return ret;
1151 	}
1152 
1153 	ret = opal_send_recv(dev, sess);
1154 	if (ret) {
1155 		return ret;
1156 	}
1157 
1158 	return opal_get_locking_sp_lifecycle_done(sess);
1159 }
1160 
1161 static int
1162 opal_activate(struct spdk_opal_dev *dev, struct opal_session *sess)
1163 {
1164 	int err = 0;
1165 	int ret;
1166 
1167 	opal_clear_cmd(sess);
1168 	opal_set_comid(sess, dev->comid);
1169 
1170 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1171 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKINGSP],
1172 				  OPAL_UID_LENGTH);
1173 	opal_add_token_bytestring(&err, sess, spdk_opal_method[ACTIVATE_METHOD],
1174 				  OPAL_UID_LENGTH);
1175 
1176 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
1177 
1178 	if (err) {
1179 		SPDK_ERRLOG("Error building Activate LockingSP command.\n");
1180 		return err;
1181 	}
1182 
1183 	/* TODO: Single User Mode for activation */
1184 
1185 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1186 	if (ret) {
1187 		return ret;
1188 	}
1189 
1190 	ret = opal_send_recv(dev, sess);
1191 	if (ret) {
1192 		return ret;
1193 	}
1194 
1195 	return opal_parse_and_check_status(sess);
1196 }
1197 
1198 static int
1199 opal_start_auth_session(struct spdk_opal_dev *dev,
1200 			struct opal_session *sess,
1201 			enum spdk_opal_user user,
1202 			struct spdk_opal_key *opal_key)
1203 {
1204 	uint8_t uid_user[OPAL_UID_LENGTH];
1205 	int err = 0;
1206 	int ret;
1207 	uint32_t hsn = GENERIC_HOST_SESSION_NUM;
1208 
1209 	opal_clear_cmd(sess);
1210 	opal_set_comid(sess, dev->comid);
1211 
1212 	if (user != OPAL_ADMIN1) {
1213 		memcpy(uid_user, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
1214 		uid_user[7] = user;
1215 	} else {
1216 		memcpy(uid_user, spdk_opal_uid[UID_ADMIN1], OPAL_UID_LENGTH);
1217 	}
1218 
1219 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1220 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_SMUID],
1221 				  OPAL_UID_LENGTH);
1222 	opal_add_token_bytestring(&err, sess, spdk_opal_method[STARTSESSION_METHOD],
1223 				  OPAL_UID_LENGTH);
1224 
1225 	opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
1226 	opal_add_token_u64(&err, sess, hsn);
1227 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKINGSP],
1228 				  OPAL_UID_LENGTH);
1229 	opal_add_tokens(&err, sess, 3, SPDK_OPAL_TRUE, SPDK_OPAL_STARTNAME,
1230 			0); /* True for a Read-Write session  */
1231 	opal_add_token_bytestring(&err, sess, opal_key->key, opal_key->key_len);
1232 	opal_add_tokens(&err, sess, 3, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME, 3); /* HostSignAuth */
1233 	opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
1234 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_ENDLIST);
1235 
1236 	if (err) {
1237 		SPDK_ERRLOG("Error building STARTSESSION command.\n");
1238 		return err;
1239 	}
1240 
1241 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1242 	if (ret) {
1243 		return ret;
1244 	}
1245 
1246 	ret = opal_send_recv(dev, sess);
1247 	if (ret) {
1248 		return ret;
1249 	}
1250 
1251 	return opal_start_session_done(sess);
1252 }
1253 
1254 static int
1255 opal_lock_unlock_range(struct spdk_opal_dev *dev, struct opal_session *sess,
1256 		       enum spdk_opal_locking_range locking_range,
1257 		       enum spdk_opal_lock_state l_state)
1258 {
1259 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1260 	uint8_t read_locked, write_locked;
1261 	int err = 0;
1262 	int ret;
1263 
1264 	opal_clear_cmd(sess);
1265 	opal_set_comid(sess, dev->comid);
1266 
1267 	opal_build_locking_range(uid_locking_range, locking_range);
1268 
1269 	switch (l_state) {
1270 	case OPAL_READONLY:
1271 		read_locked = 0;
1272 		write_locked = 1;
1273 		break;
1274 	case OPAL_READWRITE:
1275 		read_locked = 0;
1276 		write_locked = 0;
1277 		break;
1278 	case OPAL_RWLOCK:
1279 		read_locked = 1;
1280 		write_locked = 1;
1281 		break;
1282 	default:
1283 		SPDK_ERRLOG("Tried to set an invalid locking state.\n");
1284 		return -EINVAL;
1285 	}
1286 
1287 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1288 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1289 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1290 
1291 	opal_add_tokens(&err, sess, 15, SPDK_OPAL_STARTLIST,
1292 			SPDK_OPAL_STARTNAME,
1293 			SPDK_OPAL_VALUES,
1294 			SPDK_OPAL_STARTLIST,
1295 			SPDK_OPAL_STARTNAME,
1296 			SPDK_OPAL_READLOCKED,
1297 			read_locked,
1298 			SPDK_OPAL_ENDNAME,
1299 			SPDK_OPAL_STARTNAME,
1300 			SPDK_OPAL_WRITELOCKED,
1301 			write_locked,
1302 			SPDK_OPAL_ENDNAME,
1303 			SPDK_OPAL_ENDLIST,
1304 			SPDK_OPAL_ENDNAME,
1305 			SPDK_OPAL_ENDLIST);
1306 
1307 	if (err) {
1308 		SPDK_ERRLOG("Error building SET command.\n");
1309 		return err;
1310 	}
1311 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1312 	if (ret) {
1313 		return ret;
1314 	}
1315 
1316 	ret = opal_send_recv(dev, sess);
1317 	if (ret) {
1318 		return ret;
1319 	}
1320 
1321 	return opal_parse_and_check_status(sess);
1322 }
1323 
1324 static int
1325 opal_generic_locking_range_enable_disable(struct spdk_opal_dev *dev,
1326 		struct opal_session *sess,
1327 		uint8_t *uid, bool read_lock_enabled, bool write_lock_enabled)
1328 {
1329 	int err = 0;
1330 
1331 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1332 	opal_add_token_bytestring(&err, sess, uid, OPAL_UID_LENGTH);
1333 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1334 
1335 	opal_add_tokens(&err, sess, 23, SPDK_OPAL_STARTLIST,
1336 			SPDK_OPAL_STARTNAME,
1337 			SPDK_OPAL_VALUES,
1338 			SPDK_OPAL_STARTLIST,
1339 
1340 			SPDK_OPAL_STARTNAME,
1341 			SPDK_OPAL_READLOCKENABLED,
1342 			read_lock_enabled,
1343 			SPDK_OPAL_ENDNAME,
1344 
1345 			SPDK_OPAL_STARTNAME,
1346 			SPDK_OPAL_WRITELOCKENABLED,
1347 			write_lock_enabled,
1348 			SPDK_OPAL_ENDNAME,
1349 
1350 			SPDK_OPAL_STARTNAME,
1351 			SPDK_OPAL_READLOCKED,
1352 			0,
1353 			SPDK_OPAL_ENDNAME,
1354 
1355 			SPDK_OPAL_STARTNAME,
1356 			SPDK_OPAL_WRITELOCKED,
1357 			0,
1358 			SPDK_OPAL_ENDNAME,
1359 
1360 			SPDK_OPAL_ENDLIST,
1361 			SPDK_OPAL_ENDNAME,
1362 			SPDK_OPAL_ENDLIST);
1363 	if (err) {
1364 		SPDK_ERRLOG("Error building locking range enable/disable command.\n");
1365 	}
1366 	return err;
1367 }
1368 
1369 static int
1370 opal_setup_locking_range(struct spdk_opal_dev *dev, struct opal_session *sess,
1371 			 enum spdk_opal_locking_range locking_range,
1372 			 uint64_t range_start, uint64_t range_length,
1373 			 bool read_lock_enabled, bool write_lock_enabled)
1374 {
1375 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1376 	int err = 0;
1377 	int ret;
1378 
1379 	opal_clear_cmd(sess);
1380 	opal_set_comid(sess, dev->comid);
1381 
1382 	opal_build_locking_range(uid_locking_range, locking_range);
1383 
1384 	if (locking_range == 0) {
1385 		err = opal_generic_locking_range_enable_disable(dev, sess, uid_locking_range,
1386 				read_lock_enabled, write_lock_enabled);
1387 	} else {
1388 		opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1389 		opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1390 		opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD],
1391 					  OPAL_UID_LENGTH);
1392 
1393 		opal_add_tokens(&err, sess, 6,
1394 				SPDK_OPAL_STARTLIST,
1395 				SPDK_OPAL_STARTNAME,
1396 				SPDK_OPAL_VALUES,
1397 				SPDK_OPAL_STARTLIST,
1398 				SPDK_OPAL_STARTNAME,
1399 				SPDK_OPAL_RANGESTART);
1400 		opal_add_token_u64(&err, sess, range_start);
1401 		opal_add_tokens(&err, sess, 3,
1402 				SPDK_OPAL_ENDNAME,
1403 				SPDK_OPAL_STARTNAME,
1404 				SPDK_OPAL_RANGELENGTH);
1405 		opal_add_token_u64(&err, sess, range_length);
1406 		opal_add_tokens(&err, sess, 3,
1407 				SPDK_OPAL_ENDNAME,
1408 				SPDK_OPAL_STARTNAME,
1409 				SPDK_OPAL_READLOCKENABLED);
1410 		opal_add_token_u64(&err, sess, read_lock_enabled);
1411 		opal_add_tokens(&err, sess, 3,
1412 				SPDK_OPAL_ENDNAME,
1413 				SPDK_OPAL_STARTNAME,
1414 				SPDK_OPAL_WRITELOCKENABLED);
1415 		opal_add_token_u64(&err, sess, write_lock_enabled);
1416 		opal_add_tokens(&err, sess, 4,
1417 				SPDK_OPAL_ENDNAME,
1418 				SPDK_OPAL_ENDLIST,
1419 				SPDK_OPAL_ENDNAME,
1420 				SPDK_OPAL_ENDLIST);
1421 	}
1422 	if (err) {
1423 		SPDK_ERRLOG("Error building Setup Locking range command.\n");
1424 		return err;
1425 
1426 	}
1427 
1428 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1429 	if (ret) {
1430 		return ret;
1431 	}
1432 
1433 	ret = opal_send_recv(dev, sess);
1434 	if (ret) {
1435 		return ret;
1436 	}
1437 
1438 	return opal_parse_and_check_status(sess);
1439 }
1440 
1441 static int
1442 opal_get_max_ranges_done(struct opal_session *sess)
1443 {
1444 	int error = 0;
1445 
1446 	error = opal_parse_and_check_status(sess);
1447 	if (error) {
1448 		return error;
1449 	}
1450 
1451 	/* "MaxRanges" is token 4 of response */
1452 	return opal_response_get_u16(&sess->parsed_resp, 4);
1453 }
1454 
1455 static int
1456 opal_get_max_ranges(struct spdk_opal_dev *dev, struct opal_session *sess)
1457 {
1458 	int err = 0;
1459 	int ret;
1460 
1461 	opal_clear_cmd(sess);
1462 	opal_set_comid(sess, dev->comid);
1463 
1464 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1465 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKING_INFO_TABLE],
1466 				  OPAL_UID_LENGTH);
1467 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1468 
1469 	opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
1470 			SPDK_OPAL_STARTLIST,
1471 			SPDK_OPAL_STARTNAME,
1472 			SPDK_OPAL_STARTCOLUMN,
1473 			SPDK_OPAL_MAXRANGES,
1474 			SPDK_OPAL_ENDNAME,
1475 			SPDK_OPAL_STARTNAME,
1476 			SPDK_OPAL_ENDCOLUMN,
1477 			SPDK_OPAL_MAXRANGES,
1478 			SPDK_OPAL_ENDNAME,
1479 			SPDK_OPAL_ENDLIST,
1480 			SPDK_OPAL_ENDLIST);
1481 
1482 	if (err) {
1483 		SPDK_ERRLOG("Error Building GET Lifecycle Status command\n");
1484 		return err;
1485 	}
1486 
1487 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1488 	if (ret) {
1489 		return ret;
1490 	}
1491 
1492 	ret = opal_send_recv(dev, sess);
1493 	if (ret) {
1494 		return ret;
1495 	}
1496 
1497 	return opal_get_max_ranges_done(sess);
1498 }
1499 
1500 static int
1501 opal_get_locking_range_info_done(struct opal_session *sess,
1502 				 struct spdk_opal_locking_range_info *info)
1503 {
1504 	int error = 0;
1505 
1506 	error = opal_parse_and_check_status(sess);
1507 	if (error) {
1508 		return error;
1509 	}
1510 
1511 	info->range_start = opal_response_get_u64(&sess->parsed_resp, 4);
1512 	info->range_length = opal_response_get_u64(&sess->parsed_resp, 8);
1513 	info->read_lock_enabled = opal_response_get_u8(&sess->parsed_resp, 12);
1514 	info->write_lock_enabled = opal_response_get_u8(&sess->parsed_resp, 16);
1515 	info->read_locked = opal_response_get_u8(&sess->parsed_resp, 20);
1516 	info->write_locked = opal_response_get_u8(&sess->parsed_resp, 24);
1517 
1518 	return 0;
1519 }
1520 
1521 static int
1522 opal_get_locking_range_info(struct spdk_opal_dev *dev,
1523 			    struct opal_session *sess,
1524 			    enum spdk_opal_locking_range locking_range_id)
1525 {
1526 	int err = 0;
1527 	int ret;
1528 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1529 	struct spdk_opal_locking_range_info *info;
1530 
1531 	opal_build_locking_range(uid_locking_range, locking_range_id);
1532 
1533 	assert(locking_range_id < SPDK_OPAL_MAX_LOCKING_RANGE);
1534 	info = &dev->locking_ranges[locking_range_id];
1535 	memset(info, 0, sizeof(*info));
1536 	info->locking_range_id = locking_range_id;
1537 
1538 	opal_clear_cmd(sess);
1539 	opal_set_comid(sess, dev->comid);
1540 
1541 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1542 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1543 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1544 
1545 
1546 	opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
1547 			SPDK_OPAL_STARTLIST,
1548 			SPDK_OPAL_STARTNAME,
1549 			SPDK_OPAL_STARTCOLUMN,
1550 			SPDK_OPAL_RANGESTART,
1551 			SPDK_OPAL_ENDNAME,
1552 			SPDK_OPAL_STARTNAME,
1553 			SPDK_OPAL_ENDCOLUMN,
1554 			SPDK_OPAL_WRITELOCKED,
1555 			SPDK_OPAL_ENDNAME,
1556 			SPDK_OPAL_ENDLIST,
1557 			SPDK_OPAL_ENDLIST);
1558 
1559 	if (err) {
1560 		SPDK_ERRLOG("Error Building get locking range info command\n");
1561 		return err;
1562 	}
1563 
1564 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1565 	if (ret) {
1566 		return ret;
1567 	}
1568 
1569 	ret = opal_send_recv(dev, sess);
1570 	if (ret) {
1571 		return ret;
1572 	}
1573 
1574 	return opal_get_locking_range_info_done(sess, info);
1575 }
1576 
1577 static int
1578 opal_enable_user(struct spdk_opal_dev *dev, struct opal_session *sess,
1579 		 enum spdk_opal_user user)
1580 {
1581 	int err = 0;
1582 	int ret;
1583 	uint8_t uid_user[OPAL_UID_LENGTH];
1584 
1585 	memcpy(uid_user, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
1586 	uid_user[7] = user;
1587 
1588 	opal_clear_cmd(sess);
1589 	opal_set_comid(sess, dev->comid);
1590 
1591 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1592 	opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
1593 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1594 
1595 	opal_add_tokens(&err, sess, 11,
1596 			SPDK_OPAL_STARTLIST,
1597 			SPDK_OPAL_STARTNAME,
1598 			SPDK_OPAL_VALUES,
1599 			SPDK_OPAL_STARTLIST,
1600 			SPDK_OPAL_STARTNAME,
1601 			SPDK_OPAL_AUTH_ENABLE,
1602 			SPDK_OPAL_TRUE,
1603 			SPDK_OPAL_ENDNAME,
1604 			SPDK_OPAL_ENDLIST,
1605 			SPDK_OPAL_ENDNAME,
1606 			SPDK_OPAL_ENDLIST);
1607 
1608 	if (err) {
1609 		SPDK_ERRLOG("Error Building enable user command\n");
1610 		return err;
1611 	}
1612 
1613 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1614 	if (ret) {
1615 		return ret;
1616 	}
1617 
1618 	ret = opal_send_recv(dev, sess);
1619 	if (ret) {
1620 		return ret;
1621 	}
1622 
1623 	return opal_parse_and_check_status(sess);
1624 }
1625 
1626 static int
1627 opal_add_user_to_locking_range(struct spdk_opal_dev *dev,
1628 			       struct opal_session *sess,
1629 			       enum spdk_opal_user user,
1630 			       enum spdk_opal_locking_range locking_range,
1631 			       enum spdk_opal_lock_state l_state)
1632 {
1633 	int err = 0;
1634 	int ret;
1635 	uint8_t uid_user[OPAL_UID_LENGTH];
1636 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1637 
1638 	memcpy(uid_user, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
1639 	uid_user[7] = user;
1640 
1641 	switch (l_state) {
1642 	case OPAL_READONLY:
1643 		memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_RDLOCKED], OPAL_UID_LENGTH);
1644 		break;
1645 	case OPAL_READWRITE:
1646 		memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_WRLOCKED], OPAL_UID_LENGTH);
1647 		break;
1648 	default:
1649 		SPDK_ERRLOG("locking state should only be OPAL_READONLY or OPAL_READWRITE\n");
1650 		return -EINVAL;
1651 	}
1652 
1653 	uid_locking_range[7] = locking_range;
1654 
1655 	opal_clear_cmd(sess);
1656 	opal_set_comid(sess, dev->comid);
1657 
1658 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1659 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1660 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1661 
1662 	opal_add_tokens(&err, sess, 8,
1663 			SPDK_OPAL_STARTLIST,
1664 			SPDK_OPAL_STARTNAME,
1665 			SPDK_OPAL_VALUES,
1666 			SPDK_OPAL_STARTLIST,
1667 			SPDK_OPAL_STARTNAME,
1668 			SPDK_OPAL_BOOLEAN_EXPR,
1669 			SPDK_OPAL_STARTLIST,
1670 			SPDK_OPAL_STARTNAME);
1671 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
1672 				  OPAL_UID_LENGTH / 2);
1673 	opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
1674 
1675 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
1676 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
1677 				  OPAL_UID_LENGTH / 2);
1678 	opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
1679 
1680 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
1681 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_HALF_BOOLEAN_ACE], OPAL_UID_LENGTH / 2);
1682 	opal_add_tokens(&err, sess, 7,
1683 			SPDK_OPAL_TRUE,
1684 			SPDK_OPAL_ENDNAME,
1685 			SPDK_OPAL_ENDLIST,
1686 			SPDK_OPAL_ENDNAME,
1687 			SPDK_OPAL_ENDLIST,
1688 			SPDK_OPAL_ENDNAME,
1689 			SPDK_OPAL_ENDLIST);
1690 	if (err) {
1691 		SPDK_ERRLOG("Error building add user to locking range command\n");
1692 		return err;
1693 	}
1694 
1695 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1696 	if (ret) {
1697 		return ret;
1698 	}
1699 
1700 	ret = opal_send_recv(dev, sess);
1701 	if (ret) {
1702 		return ret;
1703 	}
1704 
1705 	return opal_parse_and_check_status(sess);
1706 }
1707 
1708 static int
1709 opal_new_user_passwd(struct spdk_opal_dev *dev, struct opal_session *sess,
1710 		     enum spdk_opal_user user,
1711 		     struct spdk_opal_key *opal_key)
1712 {
1713 	uint8_t uid_cpin[OPAL_UID_LENGTH];
1714 	int ret;
1715 
1716 	if (user == OPAL_ADMIN1) {
1717 		memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1718 	} else {
1719 		memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_USER1], OPAL_UID_LENGTH);
1720 		uid_cpin[7] = user;
1721 	}
1722 
1723 	ret = opal_build_generic_pw_cmd(sess, opal_key->key, opal_key->key_len, uid_cpin, dev);
1724 	if (ret != 0) {
1725 		SPDK_ERRLOG("Error building set password command\n");
1726 		return ret;
1727 	}
1728 
1729 	ret = opal_send_recv(dev, sess);
1730 	if (ret) {
1731 		return ret;
1732 	}
1733 
1734 	return opal_parse_and_check_status(sess);
1735 }
1736 
1737 static int
1738 opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, struct opal_session *sess, char *new_passwd)
1739 {
1740 	uint8_t cpin_uid[OPAL_UID_LENGTH];
1741 	struct spdk_opal_key opal_key = {};
1742 	int ret;
1743 
1744 	ret = opal_init_key(&opal_key, new_passwd);
1745 	if (ret != 0) {
1746 		return ret;
1747 	}
1748 
1749 	memcpy(cpin_uid, spdk_opal_uid[UID_C_PIN_SID], OPAL_UID_LENGTH);
1750 
1751 	if (opal_build_generic_pw_cmd(sess, opal_key.key, opal_key.key_len, cpin_uid, dev)) {
1752 		SPDK_ERRLOG("Error building Set SID cpin\n");
1753 		return -ERANGE;
1754 	}
1755 
1756 	ret = opal_send_recv(dev, sess);
1757 	if (ret) {
1758 		return ret;
1759 	}
1760 
1761 	return opal_parse_and_check_status(sess);
1762 }
1763 
1764 int
1765 spdk_opal_cmd_take_ownership(struct spdk_opal_dev *dev, char *new_passwd)
1766 {
1767 	int ret;
1768 	struct spdk_opal_key opal_key = {};
1769 	struct opal_session *sess;
1770 
1771 	assert(dev != NULL);
1772 
1773 	sess = opal_alloc_session(dev);
1774 	if (!sess) {
1775 		return -ENOMEM;
1776 	}
1777 
1778 	ret = opal_start_generic_session(dev, sess, UID_ANYBODY, UID_ADMINSP, NULL, 0);
1779 	if (ret) {
1780 		SPDK_ERRLOG("start admin SP session error %d\n", ret);
1781 		goto end;
1782 	}
1783 
1784 	ret = opal_get_msid_cpin_pin(dev, sess, &opal_key);
1785 	if (ret) {
1786 		SPDK_ERRLOG("get msid error %d\n", ret);
1787 		opal_end_session(dev, sess, dev->comid);
1788 		goto end;
1789 	}
1790 
1791 	ret = opal_end_session(dev, sess, dev->comid);
1792 	if (ret) {
1793 		SPDK_ERRLOG("end session error %d\n", ret);
1794 		goto end;
1795 	}
1796 
1797 	/* reuse the session structure */
1798 	memset(sess, 0, sizeof(*sess));
1799 	sess->dev = dev;
1800 	ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
1801 					 opal_key.key, opal_key.key_len);
1802 	if (ret) {
1803 		SPDK_ERRLOG("start admin SP session error %d\n", ret);
1804 		goto end;
1805 	}
1806 	memset(&opal_key, 0, sizeof(struct spdk_opal_key));
1807 
1808 	ret = opal_set_sid_cpin_pin(dev, sess, new_passwd);
1809 	if (ret) {
1810 		SPDK_ERRLOG("set cpin error %d\n", ret);
1811 		opal_end_session(dev, sess, dev->comid);
1812 		goto end;
1813 	}
1814 
1815 	ret = opal_end_session(dev, sess, dev->comid);
1816 	if (ret) {
1817 		SPDK_ERRLOG("end session error %d\n", ret);
1818 	}
1819 
1820 end:
1821 	free(sess);
1822 	return ret;
1823 }
1824 
1825 struct spdk_opal_dev *
1826 	spdk_opal_dev_construct(struct spdk_nvme_ctrlr *ctrlr)
1827 {
1828 	struct spdk_opal_dev *dev;
1829 	void *payload;
1830 
1831 	dev = calloc(1, sizeof(*dev));
1832 	if (!dev) {
1833 		SPDK_ERRLOG("Memory allocation failed\n");
1834 		return NULL;
1835 	}
1836 
1837 	dev->ctrlr = ctrlr;
1838 
1839 	payload = calloc(1, IO_BUFFER_LENGTH);
1840 	if (!payload) {
1841 		free(dev);
1842 		return NULL;
1843 	}
1844 
1845 	if (opal_discovery0(dev, payload, IO_BUFFER_LENGTH)) {
1846 		SPDK_INFOLOG(opal, "Opal is not supported on this device\n");
1847 		free(dev);
1848 		free(payload);
1849 		return NULL;
1850 	}
1851 
1852 	free(payload);
1853 	return dev;
1854 }
1855 
1856 static int
1857 opal_build_revert_tper_cmd(struct spdk_opal_dev *dev, struct opal_session *sess)
1858 {
1859 	int err = 0;
1860 
1861 	opal_clear_cmd(sess);
1862 	opal_set_comid(sess, dev->comid);
1863 
1864 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1865 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_ADMINSP],
1866 				  OPAL_UID_LENGTH);
1867 	opal_add_token_bytestring(&err, sess, spdk_opal_method[REVERT_METHOD],
1868 				  OPAL_UID_LENGTH);
1869 	opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
1870 	opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
1871 	if (err) {
1872 		SPDK_ERRLOG("Error building REVERT TPER command.\n");
1873 		return -ERANGE;
1874 	}
1875 
1876 	return opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1877 }
1878 
1879 static int
1880 opal_gen_new_active_key(struct spdk_opal_dev *dev, struct opal_session *sess,
1881 			struct spdk_opal_key *active_key)
1882 {
1883 	uint8_t uid_data[OPAL_UID_LENGTH] = {0};
1884 	int err = 0;
1885 	int length;
1886 	int ret;
1887 
1888 	opal_clear_cmd(sess);
1889 	opal_set_comid(sess, dev->comid);
1890 
1891 	if (active_key->key_len == 0) {
1892 		SPDK_ERRLOG("Error finding previous data to generate new active key\n");
1893 		return -EINVAL;
1894 	}
1895 
1896 	length = spdk_min(active_key->key_len, OPAL_UID_LENGTH);
1897 	memcpy(uid_data, active_key->key, length);
1898 
1899 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1900 	opal_add_token_bytestring(&err, sess, uid_data, OPAL_UID_LENGTH);
1901 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GENKEY_METHOD],
1902 				  OPAL_UID_LENGTH);
1903 
1904 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
1905 
1906 	if (err) {
1907 		SPDK_ERRLOG("Error building new key generation command.\n");
1908 		return err;
1909 	}
1910 
1911 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1912 	if (ret) {
1913 		return ret;
1914 	}
1915 
1916 	ret = opal_send_recv(dev, sess);
1917 	if (ret) {
1918 		return ret;
1919 	}
1920 
1921 	return opal_parse_and_check_status(sess);
1922 }
1923 
1924 static int
1925 opal_get_active_key_done(struct opal_session *sess, struct spdk_opal_key *active_key)
1926 {
1927 	const char *key;
1928 	size_t str_len;
1929 	int error = 0;
1930 
1931 	error = opal_parse_and_check_status(sess);
1932 	if (error) {
1933 		return error;
1934 	}
1935 
1936 	str_len = opal_response_get_string(&sess->parsed_resp, 4, &key);
1937 	if (!key) {
1938 		SPDK_ERRLOG("Couldn't extract active key from response\n");
1939 		return -EINVAL;
1940 	}
1941 
1942 	active_key->key_len = str_len;
1943 	memcpy(active_key->key, key, active_key->key_len);
1944 
1945 	SPDK_DEBUGLOG(opal, "active key = %p\n", active_key->key);
1946 	return 0;
1947 }
1948 
1949 static int
1950 opal_get_active_key(struct spdk_opal_dev *dev, struct opal_session *sess,
1951 		    enum spdk_opal_locking_range locking_range,
1952 		    struct spdk_opal_key *active_key)
1953 {
1954 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1955 	int err = 0;
1956 	int ret;
1957 
1958 	opal_clear_cmd(sess);
1959 	opal_set_comid(sess, dev->comid);
1960 
1961 	opal_build_locking_range(uid_locking_range, locking_range);
1962 
1963 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1964 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1965 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD],
1966 				  OPAL_UID_LENGTH);
1967 	opal_add_tokens(&err, sess, 12,
1968 			SPDK_OPAL_STARTLIST,
1969 			SPDK_OPAL_STARTLIST,
1970 			SPDK_OPAL_STARTNAME,
1971 			SPDK_OPAL_STARTCOLUMN,
1972 			SPDK_OPAL_ACTIVEKEY,
1973 			SPDK_OPAL_ENDNAME,
1974 			SPDK_OPAL_STARTNAME,
1975 			SPDK_OPAL_ENDCOLUMN,
1976 			SPDK_OPAL_ACTIVEKEY,
1977 			SPDK_OPAL_ENDNAME,
1978 			SPDK_OPAL_ENDLIST,
1979 			SPDK_OPAL_ENDLIST);
1980 
1981 	if (err) {
1982 		SPDK_ERRLOG("Error building get active key command.\n");
1983 		return err;
1984 	}
1985 
1986 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1987 	if (ret) {
1988 		return ret;
1989 	}
1990 
1991 	ret = opal_send_recv(dev, sess);
1992 	if (ret) {
1993 		return ret;
1994 	}
1995 
1996 	return opal_get_active_key_done(sess, active_key);
1997 }
1998 
1999 static int
2000 opal_erase_locking_range(struct spdk_opal_dev *dev, struct opal_session *sess,
2001 			 enum spdk_opal_locking_range locking_range)
2002 {
2003 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
2004 	int err = 0;
2005 	int ret;
2006 
2007 	opal_clear_cmd(sess);
2008 	opal_set_comid(sess, dev->comid);
2009 
2010 	opal_build_locking_range(uid_locking_range, locking_range);
2011 
2012 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
2013 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
2014 	opal_add_token_bytestring(&err, sess, spdk_opal_method[ERASE_METHOD],
2015 				  OPAL_UID_LENGTH);
2016 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
2017 
2018 	if (err) {
2019 		SPDK_ERRLOG("Error building erase locking range.\n");
2020 		return err;
2021 	}
2022 
2023 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
2024 	if (ret) {
2025 		return ret;
2026 	}
2027 
2028 	ret = opal_send_recv(dev, sess);
2029 	if (ret) {
2030 		return ret;
2031 	}
2032 
2033 	return opal_parse_and_check_status(sess);
2034 }
2035 
2036 int
2037 spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd)
2038 {
2039 	int ret;
2040 	struct opal_session *sess;
2041 	struct spdk_opal_key opal_key = {};
2042 
2043 	assert(dev != NULL);
2044 
2045 	ret = opal_init_key(&opal_key, passwd);
2046 	if (ret) {
2047 		SPDK_ERRLOG("Init key failed\n");
2048 		return ret;
2049 	}
2050 
2051 	sess = opal_alloc_session(dev);
2052 	if (!sess) {
2053 		return -ENOMEM;
2054 	}
2055 
2056 	ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
2057 					 opal_key.key, opal_key.key_len);
2058 	if (ret) {
2059 		SPDK_ERRLOG("Error on starting admin SP session with error %d\n", ret);
2060 		free(sess);
2061 		return ret;
2062 	}
2063 
2064 	ret = opal_build_revert_tper_cmd(dev, sess);
2065 	if (ret) {
2066 		opal_end_session(dev, sess, dev->comid);
2067 		SPDK_ERRLOG("Build revert tper command with error %d\n", ret);
2068 		goto end;
2069 	}
2070 
2071 	ret = opal_send_recv(dev, sess);
2072 	if (ret) {
2073 		opal_end_session(dev, sess, dev->comid);
2074 		SPDK_ERRLOG("Error on reverting TPer with error %d\n", ret);
2075 		goto end;
2076 	}
2077 
2078 	ret = opal_parse_and_check_status(sess);
2079 	if (ret) {
2080 		opal_end_session(dev, sess, dev->comid);
2081 		SPDK_ERRLOG("Error on reverting TPer with error %d\n", ret);
2082 	}
2083 	/* No opal_end_session() required here for successful case */
2084 
2085 end:
2086 	free(sess);
2087 	return ret;
2088 }
2089 
2090 int
2091 spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev *dev, const char *passwd)
2092 {
2093 	struct opal_session *sess;
2094 	struct spdk_opal_key opal_key = {};
2095 	int ret;
2096 
2097 	ret = opal_init_key(&opal_key, passwd);
2098 	if (ret != 0) {
2099 		return ret;
2100 	}
2101 
2102 	sess = opal_alloc_session(dev);
2103 	if (!sess) {
2104 		return -ENOMEM;
2105 	}
2106 
2107 	ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
2108 					 opal_key.key, opal_key.key_len);
2109 	if (ret) {
2110 		SPDK_ERRLOG("Error on starting admin SP session with error %d\n", ret);
2111 		free(sess);
2112 		return ret;
2113 	}
2114 
2115 	ret = opal_get_locking_sp_lifecycle(dev, sess);
2116 	if (ret) {
2117 		SPDK_ERRLOG("Error on getting SP lifecycle with error %d\n", ret);
2118 		goto end;
2119 	}
2120 
2121 	ret = opal_activate(dev, sess);
2122 	if (ret) {
2123 		SPDK_ERRLOG("Error on activation with error %d\n", ret);
2124 	}
2125 
2126 end:
2127 	ret += opal_end_session(dev, sess, dev->comid);
2128 	if (ret) {
2129 		SPDK_ERRLOG("Error on ending session with error %d\n", ret);
2130 	}
2131 
2132 	free(sess);
2133 	return ret;
2134 }
2135 
2136 int
2137 spdk_opal_cmd_lock_unlock(struct spdk_opal_dev *dev, enum spdk_opal_user user,
2138 			  enum spdk_opal_lock_state flag, enum spdk_opal_locking_range locking_range,
2139 			  const char *passwd)
2140 {
2141 	struct opal_session *sess;
2142 	struct spdk_opal_key opal_key = {};
2143 	int ret;
2144 
2145 	assert(dev != NULL);
2146 
2147 	ret = opal_init_key(&opal_key, passwd);
2148 	if (ret != 0) {
2149 		return ret;
2150 	}
2151 
2152 	sess = opal_alloc_session(dev);
2153 	if (!sess) {
2154 		return -ENOMEM;
2155 	}
2156 
2157 	ret = opal_start_auth_session(dev, sess, user, &opal_key);
2158 	if (ret) {
2159 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2160 		free(sess);
2161 		return ret;
2162 	}
2163 
2164 	ret = opal_lock_unlock_range(dev, sess, locking_range, flag);
2165 	if (ret) {
2166 		SPDK_ERRLOG("lock unlock range error %d\n", ret);
2167 	}
2168 
2169 	ret += opal_end_session(dev, sess, dev->comid);
2170 	if (ret) {
2171 		SPDK_ERRLOG("end session error %d\n", ret);
2172 	}
2173 
2174 	free(sess);
2175 	return ret;
2176 }
2177 
2178 int
2179 spdk_opal_cmd_setup_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user,
2180 				  enum spdk_opal_locking_range locking_range_id, uint64_t range_start,
2181 				  uint64_t range_length, const char *passwd)
2182 {
2183 	struct opal_session *sess;
2184 	struct spdk_opal_key opal_key = {};
2185 	int ret;
2186 
2187 	assert(dev != NULL);
2188 
2189 	ret = opal_init_key(&opal_key, passwd);
2190 	if (ret != 0) {
2191 		return ret;
2192 	}
2193 
2194 	sess = opal_alloc_session(dev);
2195 	if (!sess) {
2196 		return -ENOMEM;
2197 	}
2198 
2199 	ret = opal_start_auth_session(dev, sess, user, &opal_key);
2200 	if (ret) {
2201 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2202 		free(sess);
2203 		return ret;
2204 	}
2205 
2206 	ret = opal_setup_locking_range(dev, sess, locking_range_id, range_start, range_length, true,
2207 				       true);
2208 	if (ret) {
2209 		SPDK_ERRLOG("setup locking range error %d\n", ret);
2210 	}
2211 
2212 	ret += opal_end_session(dev, sess, dev->comid);
2213 	if (ret) {
2214 		SPDK_ERRLOG("end session error %d\n", ret);
2215 	}
2216 
2217 	free(sess);
2218 	return ret;
2219 }
2220 
2221 int
2222 spdk_opal_cmd_get_max_ranges(struct spdk_opal_dev *dev, const char *passwd)
2223 {
2224 	struct opal_session *sess;
2225 	struct spdk_opal_key opal_key = {};
2226 	int ret;
2227 
2228 	assert(dev != NULL);
2229 
2230 	if (dev->max_ranges) {
2231 		return dev->max_ranges;
2232 	}
2233 
2234 	ret = opal_init_key(&opal_key, passwd);
2235 	if (ret != 0) {
2236 		return ret;
2237 	}
2238 
2239 	sess = opal_alloc_session(dev);
2240 	if (!sess) {
2241 		return -ENOMEM;
2242 	}
2243 
2244 	ret = opal_start_auth_session(dev, sess, OPAL_ADMIN1, &opal_key);
2245 	if (ret) {
2246 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2247 		free(sess);
2248 		return ret;
2249 	}
2250 
2251 	ret = opal_get_max_ranges(dev, sess);
2252 	if (ret > 0) {
2253 		dev->max_ranges = ret;
2254 	}
2255 
2256 	ret = opal_end_session(dev, sess, dev->comid);
2257 	if (ret) {
2258 		SPDK_ERRLOG("end session error %d\n", ret);
2259 	}
2260 
2261 	free(sess);
2262 
2263 	return (ret == 0 ? dev->max_ranges : ret);
2264 }
2265 
2266 int
2267 spdk_opal_cmd_get_locking_range_info(struct spdk_opal_dev *dev, const char *passwd,
2268 				     enum spdk_opal_user user_id,
2269 				     enum spdk_opal_locking_range locking_range_id)
2270 {
2271 	struct opal_session *sess;
2272 	struct spdk_opal_key opal_key = {};
2273 	int ret;
2274 
2275 	assert(dev != NULL);
2276 
2277 	ret = opal_init_key(&opal_key, passwd);
2278 	if (ret != 0) {
2279 		return ret;
2280 	}
2281 
2282 	sess = opal_alloc_session(dev);
2283 	if (!sess) {
2284 		return -ENOMEM;
2285 	}
2286 
2287 	ret = opal_start_auth_session(dev, sess, user_id, &opal_key);
2288 	if (ret) {
2289 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2290 		free(sess);
2291 		return ret;
2292 	}
2293 
2294 	ret = opal_get_locking_range_info(dev, sess, locking_range_id);
2295 	if (ret) {
2296 		SPDK_ERRLOG("get locking range info error %d\n", ret);
2297 	}
2298 
2299 	ret += opal_end_session(dev, sess, dev->comid);
2300 	if (ret) {
2301 		SPDK_ERRLOG("end session error %d\n", ret);
2302 	}
2303 
2304 	free(sess);
2305 	return ret;
2306 }
2307 
2308 int
2309 spdk_opal_cmd_enable_user(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2310 			  const char *passwd)
2311 {
2312 	struct opal_session *sess;
2313 	struct spdk_opal_key opal_key = {};
2314 	int ret;
2315 
2316 	assert(dev != NULL);
2317 
2318 	ret = opal_init_key(&opal_key, passwd);
2319 	if (ret != 0) {
2320 		return ret;
2321 	}
2322 
2323 	sess = opal_alloc_session(dev);
2324 	if (!sess) {
2325 		return -ENOMEM;
2326 	}
2327 
2328 	ret =  opal_start_generic_session(dev, sess, UID_ADMIN1, UID_LOCKINGSP,
2329 					  opal_key.key, opal_key.key_len);
2330 	if (ret) {
2331 		SPDK_ERRLOG("start locking SP session error %d\n", ret);
2332 		free(sess);
2333 		return ret;
2334 	}
2335 
2336 	ret = opal_enable_user(dev, sess, user_id);
2337 	if (ret) {
2338 		SPDK_ERRLOG("enable user error %d\n", ret);
2339 	}
2340 
2341 	ret += opal_end_session(dev, sess, dev->comid);
2342 	if (ret) {
2343 		SPDK_ERRLOG("end session error %d\n", ret);
2344 	}
2345 
2346 	free(sess);
2347 	return ret;
2348 }
2349 
2350 int
2351 spdk_opal_cmd_add_user_to_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2352 					enum spdk_opal_locking_range locking_range_id,
2353 					enum spdk_opal_lock_state lock_flag, const char *passwd)
2354 {
2355 	struct opal_session *sess;
2356 	struct spdk_opal_key opal_key = {};
2357 	int ret;
2358 
2359 	assert(dev != NULL);
2360 
2361 	ret = opal_init_key(&opal_key, passwd);
2362 	if (ret != 0) {
2363 		return ret;
2364 	}
2365 
2366 	sess = opal_alloc_session(dev);
2367 	if (!sess) {
2368 		return -ENOMEM;
2369 	}
2370 
2371 	ret =  opal_start_generic_session(dev, sess, UID_ADMIN1, UID_LOCKINGSP,
2372 					  opal_key.key, opal_key.key_len);
2373 	if (ret) {
2374 		SPDK_ERRLOG("start locking SP session error %d\n", ret);
2375 		free(sess);
2376 		return ret;
2377 	}
2378 
2379 	ret = opal_add_user_to_locking_range(dev, sess, user_id, locking_range_id, lock_flag);
2380 	if (ret) {
2381 		SPDK_ERRLOG("add user to locking range error %d\n", ret);
2382 	}
2383 
2384 	ret += opal_end_session(dev, sess, dev->comid);
2385 	if (ret) {
2386 		SPDK_ERRLOG("end session error %d\n", ret);
2387 	}
2388 
2389 	free(sess);
2390 	return ret;
2391 }
2392 
2393 int
2394 spdk_opal_cmd_set_new_passwd(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2395 			     const char *new_passwd, const char *old_passwd, bool new_user)
2396 {
2397 	struct opal_session *sess;
2398 	struct spdk_opal_key old_key = {};
2399 	struct spdk_opal_key new_key = {};
2400 	int ret;
2401 
2402 	assert(dev != NULL);
2403 
2404 	ret = opal_init_key(&old_key, old_passwd);
2405 	if (ret != 0) {
2406 		return ret;
2407 	}
2408 
2409 	ret = opal_init_key(&new_key, new_passwd);
2410 	if (ret != 0) {
2411 		return ret;
2412 	}
2413 
2414 	sess = opal_alloc_session(dev);
2415 	if (!sess) {
2416 		return -ENOMEM;
2417 	}
2418 
2419 	ret = opal_start_auth_session(dev, sess, new_user ? OPAL_ADMIN1 : user_id,
2420 				      &old_key);
2421 	if (ret) {
2422 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2423 		free(sess);
2424 		return ret;
2425 	}
2426 
2427 	ret = opal_new_user_passwd(dev, sess, user_id, &new_key);
2428 	if (ret) {
2429 		SPDK_ERRLOG("set new passwd error %d\n", ret);
2430 	}
2431 
2432 	ret += opal_end_session(dev, sess, dev->comid);
2433 	if (ret) {
2434 		SPDK_ERRLOG("end session error %d\n", ret);
2435 	}
2436 
2437 	free(sess);
2438 	return ret;
2439 }
2440 
2441 int
2442 spdk_opal_cmd_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2443 				  enum spdk_opal_locking_range locking_range_id, const char *password)
2444 {
2445 	struct opal_session *sess;
2446 	struct spdk_opal_key opal_key = {};
2447 	int ret;
2448 
2449 	assert(dev != NULL);
2450 
2451 	ret = opal_init_key(&opal_key, password);
2452 	if (ret != 0) {
2453 		return ret;
2454 	}
2455 
2456 	sess = opal_alloc_session(dev);
2457 	if (!sess) {
2458 		return -ENOMEM;
2459 	}
2460 
2461 	ret = opal_start_auth_session(dev, sess, user_id, &opal_key);
2462 	if (ret) {
2463 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2464 		free(sess);
2465 		return ret;
2466 	}
2467 
2468 	ret = opal_erase_locking_range(dev, sess, locking_range_id);
2469 	if (ret) {
2470 		SPDK_ERRLOG("get active key error %d\n", ret);
2471 	}
2472 
2473 	ret += opal_end_session(dev, sess, dev->comid);
2474 	if (ret) {
2475 		SPDK_ERRLOG("end session error %d\n", ret);
2476 	}
2477 
2478 	free(sess);
2479 	return ret;
2480 }
2481 
2482 int
2483 spdk_opal_cmd_secure_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2484 		enum spdk_opal_locking_range locking_range_id, const char *password)
2485 {
2486 	struct opal_session *sess;
2487 	struct spdk_opal_key opal_key = {};
2488 	struct spdk_opal_key *active_key;
2489 	int ret;
2490 
2491 	assert(dev != NULL);
2492 
2493 	ret = opal_init_key(&opal_key, password);
2494 	if (ret != 0) {
2495 		return ret;
2496 	}
2497 
2498 	active_key = calloc(1, sizeof(*active_key));
2499 	if (!active_key) {
2500 		return -ENOMEM;
2501 	}
2502 
2503 	sess = opal_alloc_session(dev);
2504 	if (!sess) {
2505 		free(active_key);
2506 		return -ENOMEM;
2507 	}
2508 
2509 	ret = opal_start_auth_session(dev, sess, user_id, &opal_key);
2510 	if (ret) {
2511 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2512 		free(active_key);
2513 		free(sess);
2514 		return ret;
2515 	}
2516 
2517 	ret = opal_get_active_key(dev, sess, locking_range_id, active_key);
2518 	if (ret) {
2519 		SPDK_ERRLOG("get active key error %d\n", ret);
2520 		goto end;
2521 	}
2522 
2523 	ret = opal_gen_new_active_key(dev, sess, active_key);
2524 	if (ret) {
2525 		SPDK_ERRLOG("generate new active key error %d\n", ret);
2526 		goto end;
2527 	}
2528 	memset(active_key, 0, sizeof(struct spdk_opal_key));
2529 
2530 end:
2531 	ret += opal_end_session(dev, sess, dev->comid);
2532 	if (ret) {
2533 		SPDK_ERRLOG("end session error %d\n", ret);
2534 	}
2535 	free(active_key);
2536 	free(sess);
2537 	return ret;
2538 }
2539 
2540 struct spdk_opal_d0_features_info *
2541 spdk_opal_get_d0_features_info(struct spdk_opal_dev *dev)
2542 {
2543 	return &dev->feat_info;
2544 }
2545 
2546 struct spdk_opal_locking_range_info *
2547 spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id)
2548 {
2549 	assert(id < SPDK_OPAL_MAX_LOCKING_RANGE);
2550 	return &dev->locking_ranges[id];
2551 }
2552 
2553 void
2554 spdk_opal_free_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id)
2555 {
2556 	struct spdk_opal_locking_range_info *info;
2557 
2558 	assert(id < SPDK_OPAL_MAX_LOCKING_RANGE);
2559 	info = &dev->locking_ranges[id];
2560 	memset(info, 0, sizeof(*info));
2561 }
2562 
2563 /* Log component for opal submodule */
2564 SPDK_LOG_REGISTER_COMPONENT(opal)
2565