xref: /spdk/lib/nvme/nvme_opal.c (revision f506f14e6752ed59c6d873d18a6180ea92e52d96)
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
opal_nvme_security_recv_done(void * arg,const struct spdk_nvme_cpl * cpl)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
opal_nvme_security_send_done(void * arg,const struct spdk_nvme_cpl * cpl)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
opal_nvme_security_send(struct spdk_opal_dev * dev,struct opal_session * sess,opal_sess_cb sess_cb,void * cb_arg)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
opal_send_recv_done(struct opal_session * sess,int status,void * ctx)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
opal_send_recv(struct spdk_opal_dev * dev,struct opal_session * sess)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 *
opal_alloc_session(struct spdk_opal_dev * dev)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
opal_add_token_u8(int * err,struct opal_session * sess,uint8_t token)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
opal_add_short_atom_header(struct opal_session * sess,bool bytestring,bool has_sign,size_t len)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
opal_add_medium_atom_header(struct opal_session * sess,bool bytestring,bool has_sign,size_t len)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
opal_add_token_bytestring(int * err,struct opal_session * sess,const uint8_t * bytestring,size_t len)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
opal_add_token_u64(int * err,struct opal_session * sess,uint64_t number)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
opal_add_tokens(int * err,struct opal_session * sess,int num,...)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
opal_cmd_finalize(struct opal_session * sess,uint32_t hsn,uint32_t tsn,bool eod)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
opal_response_parse_tiny(struct spdk_opal_resp_token * token,const uint8_t * pos)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
opal_response_parse_short(struct spdk_opal_resp_token * token,const uint8_t * pos)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
opal_response_parse_medium(struct spdk_opal_resp_token * token,const uint8_t * pos)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
opal_response_parse_long(struct spdk_opal_resp_token * token,const uint8_t * pos)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
opal_response_parse_token(struct spdk_opal_resp_token * token,const uint8_t * pos)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
opal_response_parse(const uint8_t * buf,size_t length,struct spdk_opal_resp_parsed * resp)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
opal_response_token_matches(const struct spdk_opal_resp_token * token,uint8_t match)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 *
opal_response_get_token(const struct spdk_opal_resp_parsed * resp,int index)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
opal_response_get_u64(const struct spdk_opal_resp_parsed * resp,int index)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
opal_response_get_u16(const struct spdk_opal_resp_parsed * resp,int index)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
opal_response_get_u8(const struct spdk_opal_resp_parsed * resp,int index)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
opal_response_get_string(const struct spdk_opal_resp_parsed * resp,int n,const char ** store)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
opal_response_status(const struct spdk_opal_resp_parsed * resp)575 opal_response_status(const struct spdk_opal_resp_parsed *resp)
576 {
577 	const struct spdk_opal_resp_token *tok;
578 	int startlist_idx = -1, endlist_idx = -1;
579 
580 	/* if we get an EOS token, just return 0 */
581 	tok = opal_response_get_token(resp, 0);
582 	if (opal_response_token_matches(tok, SPDK_OPAL_ENDOFSESSION)) {
583 		return 0;
584 	}
585 
586 	/* Search for a StartList token in the response. Start from the end to ensure that we find
587 	 * the StartList token after the EndOfData token and not any StartList token that is part
588 	 * of the * actual response data. */
589 	for (int i = resp->num - 1; i >= 0; i--) {
590 		tok = opal_response_get_token(resp, i);
591 		if (opal_response_token_matches(tok, SPDK_OPAL_STARTLIST) && startlist_idx == -1) {
592 			startlist_idx = i;
593 		}
594 		if (opal_response_token_matches(tok, SPDK_OPAL_ENDLIST) && endlist_idx == -1) {
595 			endlist_idx = i;
596 		}
597 	}
598 
599 	if (startlist_idx == -1 || endlist_idx == -1 || startlist_idx >= endlist_idx) {
600 		return SPDK_DTAERROR_NO_METHOD_STATUS;
601 	}
602 
603 	/* The second and third values in the status list are reserved, and are
604 	defined in core spec to be 0x00 and 0x00 and SHOULD be ignored by the host. */
605 	return (int)opal_response_get_u64(resp,
606 					  startlist_idx + 1); /* We only need the first value in the status list. */
607 }
608 
609 static int
opal_parse_and_check_status(struct opal_session * sess)610 opal_parse_and_check_status(struct opal_session *sess)
611 {
612 	int error;
613 
614 	error = opal_response_parse(sess->resp, IO_BUFFER_LENGTH, &sess->parsed_resp);
615 	if (error) {
616 		SPDK_ERRLOG("Couldn't parse response.\n");
617 		return error;
618 	}
619 	return opal_response_status(&sess->parsed_resp);
620 }
621 
622 static inline void
opal_clear_cmd(struct opal_session * sess)623 opal_clear_cmd(struct opal_session *sess)
624 {
625 	sess->cmd_pos = sizeof(struct spdk_opal_header);
626 	memset(sess->cmd, 0, IO_BUFFER_LENGTH);
627 }
628 
629 static inline void
opal_set_comid(struct opal_session * sess,uint16_t comid)630 opal_set_comid(struct opal_session *sess, uint16_t comid)
631 {
632 	struct spdk_opal_header *hdr = (struct spdk_opal_header *)sess->cmd;
633 
634 	hdr->com_packet.comid[0] = comid >> 8;
635 	hdr->com_packet.comid[1] = comid;
636 	hdr->com_packet.extended_comid[0] = 0;
637 	hdr->com_packet.extended_comid[1] = 0;
638 }
639 
640 static inline int
opal_init_key(struct spdk_opal_key * opal_key,const char * passwd)641 opal_init_key(struct spdk_opal_key *opal_key, const char *passwd)
642 {
643 	int len;
644 
645 	if (passwd == NULL || passwd[0] == '\0') {
646 		SPDK_ERRLOG("Password is empty. Create key failed\n");
647 		return -EINVAL;
648 	}
649 
650 	len = strlen(passwd);
651 
652 	if (len >= OPAL_KEY_MAX) {
653 		SPDK_ERRLOG("Password too long. Create key failed\n");
654 		return -EINVAL;
655 	}
656 
657 	opal_key->key_len = len;
658 	memcpy(opal_key->key, passwd, opal_key->key_len);
659 
660 	return 0;
661 }
662 
663 static void
opal_build_locking_range(uint8_t * buffer,uint8_t locking_range)664 opal_build_locking_range(uint8_t *buffer, uint8_t locking_range)
665 {
666 	memcpy(buffer, spdk_opal_uid[UID_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH);
667 
668 	/* global */
669 	if (locking_range == 0) {
670 		return;
671 	}
672 
673 	/* non-global */
674 	buffer[5] = LOCKING_RANGE_NON_GLOBAL;
675 	buffer[7] = locking_range;
676 }
677 
678 static void
opal_check_tper(struct spdk_opal_dev * dev,const void * data)679 opal_check_tper(struct spdk_opal_dev *dev, const void *data)
680 {
681 	const struct spdk_opal_d0_tper_feat *tper = data;
682 
683 	dev->feat_info.tper = *tper;
684 }
685 
686 /*
687  * check single user mode
688  */
689 static bool
opal_check_sum(struct spdk_opal_dev * dev,const void * data)690 opal_check_sum(struct spdk_opal_dev *dev, const void *data)
691 {
692 	const struct spdk_opal_d0_single_user_mode_feat *sum = data;
693 	uint32_t num_locking_objects = from_be32(&sum->num_locking_objects);
694 
695 	if (num_locking_objects == 0) {
696 		SPDK_NOTICELOG("Need at least one locking object.\n");
697 		return false;
698 	}
699 
700 	dev->feat_info.single_user = *sum;
701 
702 	return true;
703 }
704 
705 static void
opal_check_lock(struct spdk_opal_dev * dev,const void * data)706 opal_check_lock(struct spdk_opal_dev *dev, const void *data)
707 {
708 	const struct spdk_opal_d0_locking_feat *lock = data;
709 
710 	dev->feat_info.locking = *lock;
711 }
712 
713 static void
opal_check_geometry(struct spdk_opal_dev * dev,const void * data)714 opal_check_geometry(struct spdk_opal_dev *dev, const void *data)
715 {
716 	const struct spdk_opal_d0_geo_feat *geo = data;
717 
718 	dev->feat_info.geo = *geo;
719 }
720 
721 static void
opal_check_datastore(struct spdk_opal_dev * dev,const void * data)722 opal_check_datastore(struct spdk_opal_dev *dev, const void *data)
723 {
724 	const struct spdk_opal_d0_datastore_feat *datastore = data;
725 
726 	dev->feat_info.datastore = *datastore;
727 }
728 
729 static uint16_t
opal_get_comid_v100(struct spdk_opal_dev * dev,const void * data)730 opal_get_comid_v100(struct spdk_opal_dev *dev, const void *data)
731 {
732 	const struct spdk_opal_d0_v100_feat *v100 = data;
733 	uint16_t base_comid = from_be16(&v100->base_comid);
734 
735 	dev->feat_info.v100 = *v100;
736 
737 	return base_comid;
738 }
739 
740 static uint16_t
opal_get_comid_v200(struct spdk_opal_dev * dev,const void * data)741 opal_get_comid_v200(struct spdk_opal_dev *dev, const void *data)
742 {
743 	const struct spdk_opal_d0_v200_feat *v200 = data;
744 	uint16_t base_comid = from_be16(&v200->base_comid);
745 
746 	dev->feat_info.v200 = *v200;
747 
748 	return base_comid;
749 }
750 
751 static int
opal_discovery0_end(struct spdk_opal_dev * dev,void * payload,uint32_t payload_size)752 opal_discovery0_end(struct spdk_opal_dev *dev, void *payload, uint32_t payload_size)
753 {
754 	bool supported = false, single_user = false;
755 	const struct spdk_opal_d0_hdr *hdr = (struct spdk_opal_d0_hdr *)payload;
756 	struct spdk_opal_d0_feat_hdr *feat_hdr;
757 	const uint8_t *epos = payload, *cpos = payload;
758 	uint16_t comid = 0;
759 	uint32_t hlen = from_be32(&(hdr->length));
760 
761 	if (hlen > payload_size - sizeof(*hdr)) {
762 		SPDK_ERRLOG("Discovery length overflows buffer (%zu+%u)/%u\n",
763 			    sizeof(*hdr), hlen, payload_size);
764 		return -EFAULT;
765 	}
766 
767 	epos += hlen; /* end of buffer */
768 	cpos += sizeof(*hdr); /* current position on buffer */
769 
770 	while (cpos < epos) {
771 		feat_hdr = (struct spdk_opal_d0_feat_hdr *)cpos;
772 		uint16_t feat_code = from_be16(&feat_hdr->code);
773 
774 		switch (feat_code) {
775 		case FEATURECODE_TPER:
776 			opal_check_tper(dev, cpos);
777 			break;
778 		case FEATURECODE_SINGLEUSER:
779 			single_user = opal_check_sum(dev, cpos);
780 			break;
781 		case FEATURECODE_GEOMETRY:
782 			opal_check_geometry(dev, cpos);
783 			break;
784 		case FEATURECODE_LOCKING:
785 			opal_check_lock(dev, cpos);
786 			break;
787 		case FEATURECODE_DATASTORE:
788 			opal_check_datastore(dev, cpos);
789 			break;
790 		case FEATURECODE_OPALV100:
791 			comid = opal_get_comid_v100(dev, cpos);
792 			supported = true;
793 			break;
794 		case FEATURECODE_OPALV200:
795 			comid = opal_get_comid_v200(dev, cpos);
796 			supported = true;
797 			break;
798 		default:
799 			SPDK_INFOLOG(opal, "Unknown feature code: %d\n", feat_code);
800 		}
801 		cpos += feat_hdr->length + sizeof(*feat_hdr);
802 	}
803 
804 	if (supported == false) {
805 		SPDK_INFOLOG(opal, "Opal Not Supported.\n");
806 		return -ENOTSUP;
807 	}
808 
809 	if (single_user == false) {
810 		SPDK_INFOLOG(opal, "Single User Mode Not Supported\n");
811 	}
812 
813 	dev->comid = comid;
814 	return 0;
815 }
816 
817 static int
opal_discovery0(struct spdk_opal_dev * dev,void * payload,uint32_t payload_size)818 opal_discovery0(struct spdk_opal_dev *dev, void *payload, uint32_t payload_size)
819 {
820 	int ret;
821 	uint16_t i, sp_list_len;
822 	uint8_t *sp_list;
823 	bool sp_tcg_supported = false;
824 
825 	/* NVMe 1.4 chapter 5.25.2 Security Protocol 00h */
826 	ret = spdk_nvme_ctrlr_security_receive(dev->ctrlr, SPDK_SCSI_SECP_INFO, 0,
827 					       0, payload, payload_size);
828 	if (ret) {
829 		return ret;
830 	}
831 
832 	/* spc4r31 chapter 7.7.1.3 Supported security protocols list description */
833 	sp_list_len = from_be16((uint8_t *)payload + 6);
834 	sp_list = (uint8_t *)payload + 8;
835 
836 	if (sp_list_len + 8 > (int)payload_size) {
837 		return -EINVAL;
838 	}
839 
840 	for (i = 0; i < sp_list_len; i++) {
841 		if (sp_list[i] == SPDK_SCSI_SECP_TCG) {
842 			sp_tcg_supported = true;
843 			break;
844 		}
845 	}
846 
847 	if (!sp_tcg_supported) {
848 		return -ENOTSUP;
849 	}
850 
851 	memset(payload, 0, payload_size);
852 	ret = spdk_nvme_ctrlr_security_receive(dev->ctrlr, SPDK_SCSI_SECP_TCG, LV0_DISCOVERY_COMID,
853 					       0, payload, payload_size);
854 	if (ret) {
855 		return ret;
856 	}
857 
858 	return opal_discovery0_end(dev, payload, payload_size);
859 }
860 
861 static int
opal_end_session(struct spdk_opal_dev * dev,struct opal_session * sess,uint16_t comid)862 opal_end_session(struct spdk_opal_dev *dev, struct opal_session *sess, uint16_t comid)
863 {
864 	int err = 0;
865 	int ret;
866 
867 	opal_clear_cmd(sess);
868 	opal_set_comid(sess, comid);
869 	opal_add_token_u8(&err, sess, SPDK_OPAL_ENDOFSESSION);
870 
871 	if (err < 0) {
872 		return err;
873 	}
874 
875 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, false);
876 	if (ret) {
877 		return ret;
878 	}
879 
880 	ret = opal_send_recv(dev, sess);
881 	if (ret) {
882 		return ret;
883 	}
884 
885 	sess->hsn = 0;
886 	sess->tsn = 0;
887 
888 	return opal_parse_and_check_status(sess);
889 }
890 
891 void
spdk_opal_dev_destruct(struct spdk_opal_dev * dev)892 spdk_opal_dev_destruct(struct spdk_opal_dev *dev)
893 {
894 	free(dev);
895 }
896 
897 static int
opal_start_session_done(struct opal_session * sess)898 opal_start_session_done(struct opal_session *sess)
899 {
900 	uint32_t hsn, tsn;
901 	int error = 0;
902 
903 	error = opal_parse_and_check_status(sess);
904 	if (error) {
905 		return error;
906 	}
907 
908 	hsn = opal_response_get_u64(&sess->parsed_resp, 4);
909 	tsn = opal_response_get_u64(&sess->parsed_resp, 5);
910 
911 	if (hsn == 0 && tsn == 0) {
912 		SPDK_ERRLOG("Couldn't authenticate session\n");
913 		return -EPERM;
914 	}
915 
916 	sess->hsn = hsn;
917 	sess->tsn = tsn;
918 
919 	return 0;
920 }
921 
922 static int
opal_start_generic_session(struct spdk_opal_dev * dev,struct opal_session * sess,enum opal_uid_enum auth,enum opal_uid_enum sp_type,const char * key,uint8_t key_len)923 opal_start_generic_session(struct spdk_opal_dev *dev,
924 			   struct opal_session *sess,
925 			   enum opal_uid_enum auth,
926 			   enum opal_uid_enum sp_type,
927 			   const char *key,
928 			   uint8_t key_len)
929 {
930 	uint32_t hsn;
931 	int err = 0;
932 	int ret;
933 
934 	if (key == NULL && auth != UID_ANYBODY) {
935 		return OPAL_INVAL_PARAM;
936 	}
937 
938 	opal_clear_cmd(sess);
939 
940 	opal_set_comid(sess, dev->comid);
941 	hsn = GENERIC_HOST_SESSION_NUM;
942 
943 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
944 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_SMUID],
945 				  OPAL_UID_LENGTH);
946 	opal_add_token_bytestring(&err, sess, spdk_opal_method[STARTSESSION_METHOD],
947 				  OPAL_UID_LENGTH);
948 	opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
949 	opal_add_token_u64(&err, sess, hsn);
950 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[sp_type], OPAL_UID_LENGTH);
951 	opal_add_token_u8(&err, sess, SPDK_OPAL_TRUE); /* Write */
952 
953 	switch (auth) {
954 	case UID_ANYBODY:
955 		opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
956 		break;
957 	case UID_ADMIN1:
958 	case UID_SID:
959 		opal_add_token_u8(&err, sess, SPDK_OPAL_STARTNAME);
960 		opal_add_token_u8(&err, sess, 0); /* HostChallenge */
961 		opal_add_token_bytestring(&err, sess, key, key_len);
962 		opal_add_tokens(&err, sess, 3,    /* number of token */
963 				SPDK_OPAL_ENDNAME,
964 				SPDK_OPAL_STARTNAME,
965 				3);/* HostSignAuth */
966 		opal_add_token_bytestring(&err, sess, spdk_opal_uid[auth],
967 					  OPAL_UID_LENGTH);
968 		opal_add_token_u8(&err, sess, SPDK_OPAL_ENDNAME);
969 		opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
970 		break;
971 	default:
972 		SPDK_ERRLOG("Cannot start Admin SP session with auth %d\n", auth);
973 		return -EINVAL;
974 	}
975 
976 	if (err) {
977 		SPDK_ERRLOG("Error building start adminsp session command.\n");
978 		return err;
979 	}
980 
981 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
982 	if (ret) {
983 		return ret;
984 	}
985 
986 	ret = opal_send_recv(dev, sess);
987 	if (ret) {
988 		return ret;
989 	}
990 
991 	return opal_start_session_done(sess);
992 }
993 
994 static int
opal_get_msid_cpin_pin_done(struct opal_session * sess,struct spdk_opal_key * opal_key)995 opal_get_msid_cpin_pin_done(struct opal_session *sess,
996 			    struct spdk_opal_key *opal_key)
997 {
998 	const char *msid_pin;
999 	size_t strlen;
1000 	int error = 0;
1001 
1002 	error = opal_parse_and_check_status(sess);
1003 	if (error) {
1004 		return error;
1005 	}
1006 
1007 	strlen = opal_response_get_string(&sess->parsed_resp, 4, &msid_pin);
1008 	if (!msid_pin) {
1009 		SPDK_ERRLOG("Couldn't extract PIN from response\n");
1010 		return -EINVAL;
1011 	}
1012 
1013 	opal_key->key_len = strlen;
1014 	memcpy(opal_key->key, msid_pin, opal_key->key_len);
1015 
1016 	SPDK_DEBUGLOG(opal, "MSID = %p\n", opal_key->key);
1017 	return 0;
1018 }
1019 
1020 static int
opal_get_msid_cpin_pin(struct spdk_opal_dev * dev,struct opal_session * sess,struct spdk_opal_key * opal_key)1021 opal_get_msid_cpin_pin(struct spdk_opal_dev *dev, struct opal_session *sess,
1022 		       struct spdk_opal_key *opal_key)
1023 {
1024 	int err = 0;
1025 	int ret;
1026 
1027 	opal_clear_cmd(sess);
1028 	opal_set_comid(sess, dev->comid);
1029 
1030 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1031 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_C_PIN_MSID],
1032 				  OPAL_UID_LENGTH);
1033 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1034 
1035 	opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
1036 			SPDK_OPAL_STARTLIST,
1037 			SPDK_OPAL_STARTNAME,
1038 			SPDK_OPAL_STARTCOLUMN,
1039 			SPDK_OPAL_PIN,
1040 			SPDK_OPAL_ENDNAME,
1041 			SPDK_OPAL_STARTNAME,
1042 			SPDK_OPAL_ENDCOLUMN,
1043 			SPDK_OPAL_PIN,
1044 			SPDK_OPAL_ENDNAME,
1045 			SPDK_OPAL_ENDLIST,
1046 			SPDK_OPAL_ENDLIST);
1047 
1048 	if (err) {
1049 		SPDK_ERRLOG("Error building Get MSID CPIN PIN command.\n");
1050 		return err;
1051 	}
1052 
1053 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1054 	if (ret) {
1055 		return ret;
1056 	}
1057 
1058 	ret = opal_send_recv(dev, sess);
1059 	if (ret) {
1060 		return ret;
1061 	}
1062 
1063 	return opal_get_msid_cpin_pin_done(sess, opal_key);
1064 }
1065 
1066 static int
opal_build_generic_pw_cmd(struct opal_session * sess,uint8_t * key,size_t key_len,uint8_t * cpin_uid,struct spdk_opal_dev * dev)1067 opal_build_generic_pw_cmd(struct opal_session *sess, uint8_t *key, size_t key_len,
1068 			  uint8_t *cpin_uid, struct spdk_opal_dev *dev)
1069 {
1070 	int err = 0;
1071 
1072 	opal_clear_cmd(sess);
1073 	opal_set_comid(sess, dev->comid);
1074 
1075 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1076 	opal_add_token_bytestring(&err, sess, cpin_uid, OPAL_UID_LENGTH);
1077 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD],
1078 				  OPAL_UID_LENGTH);
1079 
1080 	opal_add_tokens(&err, sess, 6,
1081 			SPDK_OPAL_STARTLIST,
1082 			SPDK_OPAL_STARTNAME,
1083 			SPDK_OPAL_VALUES,
1084 			SPDK_OPAL_STARTLIST,
1085 			SPDK_OPAL_STARTNAME,
1086 			SPDK_OPAL_PIN);
1087 	opal_add_token_bytestring(&err, sess, key, key_len);
1088 	opal_add_tokens(&err, sess, 4,
1089 			SPDK_OPAL_ENDNAME,
1090 			SPDK_OPAL_ENDLIST,
1091 			SPDK_OPAL_ENDNAME,
1092 			SPDK_OPAL_ENDLIST);
1093 	if (err) {
1094 		return err;
1095 	}
1096 
1097 	return opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1098 }
1099 
1100 static int
opal_get_locking_sp_lifecycle_done(struct opal_session * sess)1101 opal_get_locking_sp_lifecycle_done(struct opal_session *sess)
1102 {
1103 	uint8_t lifecycle;
1104 	int error = 0;
1105 
1106 	error = opal_parse_and_check_status(sess);
1107 	if (error) {
1108 		return error;
1109 	}
1110 
1111 	lifecycle = opal_response_get_u64(&sess->parsed_resp, 4);
1112 	if (lifecycle != OPAL_MANUFACTURED_INACTIVE) { /* status before activate */
1113 		SPDK_ERRLOG("Couldn't determine the status of the Lifecycle state\n");
1114 		return -EINVAL;
1115 	}
1116 
1117 	return 0;
1118 }
1119 
1120 static int
opal_get_locking_sp_lifecycle(struct spdk_opal_dev * dev,struct opal_session * sess)1121 opal_get_locking_sp_lifecycle(struct spdk_opal_dev *dev, struct opal_session *sess)
1122 {
1123 	int err = 0;
1124 	int ret;
1125 
1126 	opal_clear_cmd(sess);
1127 	opal_set_comid(sess, dev->comid);
1128 
1129 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1130 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKINGSP],
1131 				  OPAL_UID_LENGTH);
1132 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1133 
1134 	opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
1135 			SPDK_OPAL_STARTLIST,
1136 			SPDK_OPAL_STARTNAME,
1137 			SPDK_OPAL_STARTCOLUMN,
1138 			SPDK_OPAL_LIFECYCLE,
1139 			SPDK_OPAL_ENDNAME,
1140 			SPDK_OPAL_STARTNAME,
1141 			SPDK_OPAL_ENDCOLUMN,
1142 			SPDK_OPAL_LIFECYCLE,
1143 			SPDK_OPAL_ENDNAME,
1144 			SPDK_OPAL_ENDLIST,
1145 			SPDK_OPAL_ENDLIST);
1146 
1147 	if (err) {
1148 		SPDK_ERRLOG("Error Building GET Lifecycle Status command\n");
1149 		return err;
1150 	}
1151 
1152 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1153 	if (ret) {
1154 		return ret;
1155 	}
1156 
1157 	ret = opal_send_recv(dev, sess);
1158 	if (ret) {
1159 		return ret;
1160 	}
1161 
1162 	return opal_get_locking_sp_lifecycle_done(sess);
1163 }
1164 
1165 static int
opal_activate(struct spdk_opal_dev * dev,struct opal_session * sess)1166 opal_activate(struct spdk_opal_dev *dev, struct opal_session *sess)
1167 {
1168 	int err = 0;
1169 	int ret;
1170 
1171 	opal_clear_cmd(sess);
1172 	opal_set_comid(sess, dev->comid);
1173 
1174 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1175 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKINGSP],
1176 				  OPAL_UID_LENGTH);
1177 	opal_add_token_bytestring(&err, sess, spdk_opal_method[ACTIVATE_METHOD],
1178 				  OPAL_UID_LENGTH);
1179 
1180 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
1181 
1182 	if (err) {
1183 		SPDK_ERRLOG("Error building Activate LockingSP command.\n");
1184 		return err;
1185 	}
1186 
1187 	/* TODO: Single User Mode for activation */
1188 
1189 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1190 	if (ret) {
1191 		return ret;
1192 	}
1193 
1194 	ret = opal_send_recv(dev, sess);
1195 	if (ret) {
1196 		return ret;
1197 	}
1198 
1199 	return opal_parse_and_check_status(sess);
1200 }
1201 
1202 static int
opal_start_auth_session(struct spdk_opal_dev * dev,struct opal_session * sess,enum spdk_opal_user user,struct spdk_opal_key * opal_key)1203 opal_start_auth_session(struct spdk_opal_dev *dev,
1204 			struct opal_session *sess,
1205 			enum spdk_opal_user user,
1206 			struct spdk_opal_key *opal_key)
1207 {
1208 	uint8_t uid_user[OPAL_UID_LENGTH];
1209 	int err = 0;
1210 	int ret;
1211 	uint32_t hsn = GENERIC_HOST_SESSION_NUM;
1212 
1213 	opal_clear_cmd(sess);
1214 	opal_set_comid(sess, dev->comid);
1215 
1216 	if (user != OPAL_ADMIN1) {
1217 		memcpy(uid_user, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
1218 		uid_user[7] = user;
1219 	} else {
1220 		memcpy(uid_user, spdk_opal_uid[UID_ADMIN1], OPAL_UID_LENGTH);
1221 	}
1222 
1223 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1224 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_SMUID],
1225 				  OPAL_UID_LENGTH);
1226 	opal_add_token_bytestring(&err, sess, spdk_opal_method[STARTSESSION_METHOD],
1227 				  OPAL_UID_LENGTH);
1228 
1229 	opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
1230 	opal_add_token_u64(&err, sess, hsn);
1231 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKINGSP],
1232 				  OPAL_UID_LENGTH);
1233 	opal_add_tokens(&err, sess, 3, SPDK_OPAL_TRUE, SPDK_OPAL_STARTNAME,
1234 			0); /* True for a Read-Write session  */
1235 	opal_add_token_bytestring(&err, sess, opal_key->key, opal_key->key_len);
1236 	opal_add_tokens(&err, sess, 3, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME, 3); /* HostSignAuth */
1237 	opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
1238 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_ENDLIST);
1239 
1240 	if (err) {
1241 		SPDK_ERRLOG("Error building STARTSESSION command.\n");
1242 		return err;
1243 	}
1244 
1245 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1246 	if (ret) {
1247 		return ret;
1248 	}
1249 
1250 	ret = opal_send_recv(dev, sess);
1251 	if (ret) {
1252 		return ret;
1253 	}
1254 
1255 	return opal_start_session_done(sess);
1256 }
1257 
1258 static int
opal_lock_unlock_range(struct spdk_opal_dev * dev,struct opal_session * sess,enum spdk_opal_locking_range locking_range,enum spdk_opal_lock_state l_state)1259 opal_lock_unlock_range(struct spdk_opal_dev *dev, struct opal_session *sess,
1260 		       enum spdk_opal_locking_range locking_range,
1261 		       enum spdk_opal_lock_state l_state)
1262 {
1263 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1264 	uint8_t read_locked, write_locked;
1265 	int err = 0;
1266 	int ret;
1267 
1268 	opal_clear_cmd(sess);
1269 	opal_set_comid(sess, dev->comid);
1270 
1271 	opal_build_locking_range(uid_locking_range, locking_range);
1272 
1273 	switch (l_state) {
1274 	case OPAL_READONLY:
1275 		read_locked = 0;
1276 		write_locked = 1;
1277 		break;
1278 	case OPAL_READWRITE:
1279 		read_locked = 0;
1280 		write_locked = 0;
1281 		break;
1282 	case OPAL_RWLOCK:
1283 		read_locked = 1;
1284 		write_locked = 1;
1285 		break;
1286 	default:
1287 		SPDK_ERRLOG("Tried to set an invalid locking state.\n");
1288 		return -EINVAL;
1289 	}
1290 
1291 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1292 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1293 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1294 
1295 	opal_add_tokens(&err, sess, 15, SPDK_OPAL_STARTLIST,
1296 			SPDK_OPAL_STARTNAME,
1297 			SPDK_OPAL_VALUES,
1298 			SPDK_OPAL_STARTLIST,
1299 			SPDK_OPAL_STARTNAME,
1300 			SPDK_OPAL_READLOCKED,
1301 			read_locked,
1302 			SPDK_OPAL_ENDNAME,
1303 			SPDK_OPAL_STARTNAME,
1304 			SPDK_OPAL_WRITELOCKED,
1305 			write_locked,
1306 			SPDK_OPAL_ENDNAME,
1307 			SPDK_OPAL_ENDLIST,
1308 			SPDK_OPAL_ENDNAME,
1309 			SPDK_OPAL_ENDLIST);
1310 
1311 	if (err) {
1312 		SPDK_ERRLOG("Error building SET command.\n");
1313 		return err;
1314 	}
1315 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1316 	if (ret) {
1317 		return ret;
1318 	}
1319 
1320 	ret = opal_send_recv(dev, sess);
1321 	if (ret) {
1322 		return ret;
1323 	}
1324 
1325 	return opal_parse_and_check_status(sess);
1326 }
1327 
1328 static int
opal_generic_locking_range_enable_disable(struct spdk_opal_dev * dev,struct opal_session * sess,uint8_t * uid,bool read_lock_enabled,bool write_lock_enabled)1329 opal_generic_locking_range_enable_disable(struct spdk_opal_dev *dev,
1330 		struct opal_session *sess,
1331 		uint8_t *uid, bool read_lock_enabled, bool write_lock_enabled)
1332 {
1333 	int err = 0;
1334 
1335 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1336 	opal_add_token_bytestring(&err, sess, uid, OPAL_UID_LENGTH);
1337 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1338 
1339 	opal_add_tokens(&err, sess, 23, SPDK_OPAL_STARTLIST,
1340 			SPDK_OPAL_STARTNAME,
1341 			SPDK_OPAL_VALUES,
1342 			SPDK_OPAL_STARTLIST,
1343 
1344 			SPDK_OPAL_STARTNAME,
1345 			SPDK_OPAL_READLOCKENABLED,
1346 			read_lock_enabled,
1347 			SPDK_OPAL_ENDNAME,
1348 
1349 			SPDK_OPAL_STARTNAME,
1350 			SPDK_OPAL_WRITELOCKENABLED,
1351 			write_lock_enabled,
1352 			SPDK_OPAL_ENDNAME,
1353 
1354 			SPDK_OPAL_STARTNAME,
1355 			SPDK_OPAL_READLOCKED,
1356 			0,
1357 			SPDK_OPAL_ENDNAME,
1358 
1359 			SPDK_OPAL_STARTNAME,
1360 			SPDK_OPAL_WRITELOCKED,
1361 			0,
1362 			SPDK_OPAL_ENDNAME,
1363 
1364 			SPDK_OPAL_ENDLIST,
1365 			SPDK_OPAL_ENDNAME,
1366 			SPDK_OPAL_ENDLIST);
1367 	if (err) {
1368 		SPDK_ERRLOG("Error building locking range enable/disable command.\n");
1369 	}
1370 	return err;
1371 }
1372 
1373 static int
opal_setup_locking_range(struct spdk_opal_dev * dev,struct opal_session * sess,enum spdk_opal_locking_range locking_range,uint64_t range_start,uint64_t range_length,bool read_lock_enabled,bool write_lock_enabled)1374 opal_setup_locking_range(struct spdk_opal_dev *dev, struct opal_session *sess,
1375 			 enum spdk_opal_locking_range locking_range,
1376 			 uint64_t range_start, uint64_t range_length,
1377 			 bool read_lock_enabled, bool write_lock_enabled)
1378 {
1379 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1380 	int err = 0;
1381 	int ret;
1382 
1383 	opal_clear_cmd(sess);
1384 	opal_set_comid(sess, dev->comid);
1385 
1386 	opal_build_locking_range(uid_locking_range, locking_range);
1387 
1388 	if (locking_range == 0) {
1389 		err = opal_generic_locking_range_enable_disable(dev, sess, uid_locking_range,
1390 				read_lock_enabled, write_lock_enabled);
1391 	} else {
1392 		opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1393 		opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1394 		opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD],
1395 					  OPAL_UID_LENGTH);
1396 
1397 		opal_add_tokens(&err, sess, 6,
1398 				SPDK_OPAL_STARTLIST,
1399 				SPDK_OPAL_STARTNAME,
1400 				SPDK_OPAL_VALUES,
1401 				SPDK_OPAL_STARTLIST,
1402 				SPDK_OPAL_STARTNAME,
1403 				SPDK_OPAL_RANGESTART);
1404 		opal_add_token_u64(&err, sess, range_start);
1405 		opal_add_tokens(&err, sess, 3,
1406 				SPDK_OPAL_ENDNAME,
1407 				SPDK_OPAL_STARTNAME,
1408 				SPDK_OPAL_RANGELENGTH);
1409 		opal_add_token_u64(&err, sess, range_length);
1410 		opal_add_tokens(&err, sess, 3,
1411 				SPDK_OPAL_ENDNAME,
1412 				SPDK_OPAL_STARTNAME,
1413 				SPDK_OPAL_READLOCKENABLED);
1414 		opal_add_token_u64(&err, sess, read_lock_enabled);
1415 		opal_add_tokens(&err, sess, 3,
1416 				SPDK_OPAL_ENDNAME,
1417 				SPDK_OPAL_STARTNAME,
1418 				SPDK_OPAL_WRITELOCKENABLED);
1419 		opal_add_token_u64(&err, sess, write_lock_enabled);
1420 		opal_add_tokens(&err, sess, 4,
1421 				SPDK_OPAL_ENDNAME,
1422 				SPDK_OPAL_ENDLIST,
1423 				SPDK_OPAL_ENDNAME,
1424 				SPDK_OPAL_ENDLIST);
1425 	}
1426 	if (err) {
1427 		SPDK_ERRLOG("Error building Setup Locking range command.\n");
1428 		return err;
1429 
1430 	}
1431 
1432 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1433 	if (ret) {
1434 		return ret;
1435 	}
1436 
1437 	ret = opal_send_recv(dev, sess);
1438 	if (ret) {
1439 		return ret;
1440 	}
1441 
1442 	return opal_parse_and_check_status(sess);
1443 }
1444 
1445 static int
opal_get_max_ranges_done(struct opal_session * sess)1446 opal_get_max_ranges_done(struct opal_session *sess)
1447 {
1448 	int error = 0;
1449 
1450 	error = opal_parse_and_check_status(sess);
1451 	if (error) {
1452 		return error;
1453 	}
1454 
1455 	/* "MaxRanges" is token 4 of response */
1456 	return opal_response_get_u16(&sess->parsed_resp, 4);
1457 }
1458 
1459 static int
opal_get_max_ranges(struct spdk_opal_dev * dev,struct opal_session * sess)1460 opal_get_max_ranges(struct spdk_opal_dev *dev, struct opal_session *sess)
1461 {
1462 	int err = 0;
1463 	int ret;
1464 
1465 	opal_clear_cmd(sess);
1466 	opal_set_comid(sess, dev->comid);
1467 
1468 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1469 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_LOCKING_INFO_TABLE],
1470 				  OPAL_UID_LENGTH);
1471 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1472 
1473 	opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
1474 			SPDK_OPAL_STARTLIST,
1475 			SPDK_OPAL_STARTNAME,
1476 			SPDK_OPAL_STARTCOLUMN,
1477 			SPDK_OPAL_MAXRANGES,
1478 			SPDK_OPAL_ENDNAME,
1479 			SPDK_OPAL_STARTNAME,
1480 			SPDK_OPAL_ENDCOLUMN,
1481 			SPDK_OPAL_MAXRANGES,
1482 			SPDK_OPAL_ENDNAME,
1483 			SPDK_OPAL_ENDLIST,
1484 			SPDK_OPAL_ENDLIST);
1485 
1486 	if (err) {
1487 		SPDK_ERRLOG("Error Building GET Lifecycle Status command\n");
1488 		return err;
1489 	}
1490 
1491 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1492 	if (ret) {
1493 		return ret;
1494 	}
1495 
1496 	ret = opal_send_recv(dev, sess);
1497 	if (ret) {
1498 		return ret;
1499 	}
1500 
1501 	return opal_get_max_ranges_done(sess);
1502 }
1503 
1504 static int
opal_get_locking_range_info_done(struct opal_session * sess,struct spdk_opal_locking_range_info * info)1505 opal_get_locking_range_info_done(struct opal_session *sess,
1506 				 struct spdk_opal_locking_range_info *info)
1507 {
1508 	int error = 0;
1509 
1510 	error = opal_parse_and_check_status(sess);
1511 	if (error) {
1512 		return error;
1513 	}
1514 
1515 	info->range_start = opal_response_get_u64(&sess->parsed_resp, 4);
1516 	info->range_length = opal_response_get_u64(&sess->parsed_resp, 8);
1517 	info->read_lock_enabled = opal_response_get_u8(&sess->parsed_resp, 12);
1518 	info->write_lock_enabled = opal_response_get_u8(&sess->parsed_resp, 16);
1519 	info->read_locked = opal_response_get_u8(&sess->parsed_resp, 20);
1520 	info->write_locked = opal_response_get_u8(&sess->parsed_resp, 24);
1521 
1522 	return 0;
1523 }
1524 
1525 static int
opal_get_locking_range_info(struct spdk_opal_dev * dev,struct opal_session * sess,enum spdk_opal_locking_range locking_range_id)1526 opal_get_locking_range_info(struct spdk_opal_dev *dev,
1527 			    struct opal_session *sess,
1528 			    enum spdk_opal_locking_range locking_range_id)
1529 {
1530 	int err = 0;
1531 	int ret;
1532 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1533 	struct spdk_opal_locking_range_info *info;
1534 
1535 	opal_build_locking_range(uid_locking_range, locking_range_id);
1536 
1537 	assert(locking_range_id < SPDK_OPAL_MAX_LOCKING_RANGE);
1538 	info = &dev->locking_ranges[locking_range_id];
1539 	memset(info, 0, sizeof(*info));
1540 	info->locking_range_id = locking_range_id;
1541 
1542 	opal_clear_cmd(sess);
1543 	opal_set_comid(sess, dev->comid);
1544 
1545 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1546 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1547 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD], OPAL_UID_LENGTH);
1548 
1549 
1550 	opal_add_tokens(&err, sess, 12, SPDK_OPAL_STARTLIST,
1551 			SPDK_OPAL_STARTLIST,
1552 			SPDK_OPAL_STARTNAME,
1553 			SPDK_OPAL_STARTCOLUMN,
1554 			SPDK_OPAL_RANGESTART,
1555 			SPDK_OPAL_ENDNAME,
1556 			SPDK_OPAL_STARTNAME,
1557 			SPDK_OPAL_ENDCOLUMN,
1558 			SPDK_OPAL_WRITELOCKED,
1559 			SPDK_OPAL_ENDNAME,
1560 			SPDK_OPAL_ENDLIST,
1561 			SPDK_OPAL_ENDLIST);
1562 
1563 	if (err) {
1564 		SPDK_ERRLOG("Error Building get locking range info command\n");
1565 		return err;
1566 	}
1567 
1568 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1569 	if (ret) {
1570 		return ret;
1571 	}
1572 
1573 	ret = opal_send_recv(dev, sess);
1574 	if (ret) {
1575 		return ret;
1576 	}
1577 
1578 	return opal_get_locking_range_info_done(sess, info);
1579 }
1580 
1581 static int
opal_enable_user(struct spdk_opal_dev * dev,struct opal_session * sess,enum spdk_opal_user user)1582 opal_enable_user(struct spdk_opal_dev *dev, struct opal_session *sess,
1583 		 enum spdk_opal_user user)
1584 {
1585 	int err = 0;
1586 	int ret;
1587 	uint8_t uid_user[OPAL_UID_LENGTH];
1588 
1589 	memcpy(uid_user, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
1590 	uid_user[7] = user;
1591 
1592 	opal_clear_cmd(sess);
1593 	opal_set_comid(sess, dev->comid);
1594 
1595 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1596 	opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
1597 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1598 
1599 	opal_add_tokens(&err, sess, 11,
1600 			SPDK_OPAL_STARTLIST,
1601 			SPDK_OPAL_STARTNAME,
1602 			SPDK_OPAL_VALUES,
1603 			SPDK_OPAL_STARTLIST,
1604 			SPDK_OPAL_STARTNAME,
1605 			SPDK_OPAL_AUTH_ENABLE,
1606 			SPDK_OPAL_TRUE,
1607 			SPDK_OPAL_ENDNAME,
1608 			SPDK_OPAL_ENDLIST,
1609 			SPDK_OPAL_ENDNAME,
1610 			SPDK_OPAL_ENDLIST);
1611 
1612 	if (err) {
1613 		SPDK_ERRLOG("Error Building enable user command\n");
1614 		return err;
1615 	}
1616 
1617 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1618 	if (ret) {
1619 		return ret;
1620 	}
1621 
1622 	ret = opal_send_recv(dev, sess);
1623 	if (ret) {
1624 		return ret;
1625 	}
1626 
1627 	return opal_parse_and_check_status(sess);
1628 }
1629 
1630 static int
opal_add_user_to_locking_range(struct spdk_opal_dev * dev,struct opal_session * sess,enum spdk_opal_user user,enum spdk_opal_locking_range locking_range,enum spdk_opal_lock_state l_state)1631 opal_add_user_to_locking_range(struct spdk_opal_dev *dev,
1632 			       struct opal_session *sess,
1633 			       enum spdk_opal_user user,
1634 			       enum spdk_opal_locking_range locking_range,
1635 			       enum spdk_opal_lock_state l_state)
1636 {
1637 	int err = 0;
1638 	int ret;
1639 	uint8_t uid_user[OPAL_UID_LENGTH];
1640 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1641 
1642 	memcpy(uid_user, spdk_opal_uid[UID_USER1], OPAL_UID_LENGTH);
1643 	uid_user[7] = user;
1644 
1645 	switch (l_state) {
1646 	case OPAL_READONLY:
1647 		memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_RDLOCKED], OPAL_UID_LENGTH);
1648 		break;
1649 	case OPAL_READWRITE:
1650 		memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_WRLOCKED], OPAL_UID_LENGTH);
1651 		break;
1652 	default:
1653 		SPDK_ERRLOG("locking state should only be OPAL_READONLY or OPAL_READWRITE\n");
1654 		return -EINVAL;
1655 	}
1656 
1657 	uid_locking_range[7] = locking_range;
1658 
1659 	opal_clear_cmd(sess);
1660 	opal_set_comid(sess, dev->comid);
1661 
1662 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1663 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1664 	opal_add_token_bytestring(&err, sess, spdk_opal_method[SET_METHOD], OPAL_UID_LENGTH);
1665 
1666 	opal_add_tokens(&err, sess, 8,
1667 			SPDK_OPAL_STARTLIST,
1668 			SPDK_OPAL_STARTNAME,
1669 			SPDK_OPAL_VALUES,
1670 			SPDK_OPAL_STARTLIST,
1671 			SPDK_OPAL_STARTNAME,
1672 			SPDK_OPAL_BOOLEAN_EXPR,
1673 			SPDK_OPAL_STARTLIST,
1674 			SPDK_OPAL_STARTNAME);
1675 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
1676 				  OPAL_UID_LENGTH / 2);
1677 	opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
1678 
1679 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
1680 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_HALF_AUTHORITY_OBJ_REF],
1681 				  OPAL_UID_LENGTH / 2);
1682 	opal_add_token_bytestring(&err, sess, uid_user, OPAL_UID_LENGTH);
1683 
1684 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_ENDNAME, SPDK_OPAL_STARTNAME);
1685 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_HALF_BOOLEAN_ACE], OPAL_UID_LENGTH / 2);
1686 	opal_add_tokens(&err, sess, 7,
1687 			SPDK_OPAL_TRUE,
1688 			SPDK_OPAL_ENDNAME,
1689 			SPDK_OPAL_ENDLIST,
1690 			SPDK_OPAL_ENDNAME,
1691 			SPDK_OPAL_ENDLIST,
1692 			SPDK_OPAL_ENDNAME,
1693 			SPDK_OPAL_ENDLIST);
1694 	if (err) {
1695 		SPDK_ERRLOG("Error building add user to locking range command\n");
1696 		return err;
1697 	}
1698 
1699 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1700 	if (ret) {
1701 		return ret;
1702 	}
1703 
1704 	ret = opal_send_recv(dev, sess);
1705 	if (ret) {
1706 		return ret;
1707 	}
1708 
1709 	return opal_parse_and_check_status(sess);
1710 }
1711 
1712 static int
opal_new_user_passwd(struct spdk_opal_dev * dev,struct opal_session * sess,enum spdk_opal_user user,struct spdk_opal_key * opal_key)1713 opal_new_user_passwd(struct spdk_opal_dev *dev, struct opal_session *sess,
1714 		     enum spdk_opal_user user,
1715 		     struct spdk_opal_key *opal_key)
1716 {
1717 	uint8_t uid_cpin[OPAL_UID_LENGTH];
1718 	int ret;
1719 
1720 	if (user == OPAL_ADMIN1) {
1721 		memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_ADMIN1], OPAL_UID_LENGTH);
1722 	} else {
1723 		memcpy(uid_cpin, spdk_opal_uid[UID_C_PIN_USER1], OPAL_UID_LENGTH);
1724 		uid_cpin[7] = user;
1725 	}
1726 
1727 	ret = opal_build_generic_pw_cmd(sess, opal_key->key, opal_key->key_len, uid_cpin, dev);
1728 	if (ret != 0) {
1729 		SPDK_ERRLOG("Error building set password command\n");
1730 		return ret;
1731 	}
1732 
1733 	ret = opal_send_recv(dev, sess);
1734 	if (ret) {
1735 		return ret;
1736 	}
1737 
1738 	return opal_parse_and_check_status(sess);
1739 }
1740 
1741 static int
opal_set_sid_cpin_pin(struct spdk_opal_dev * dev,struct opal_session * sess,char * new_passwd)1742 opal_set_sid_cpin_pin(struct spdk_opal_dev *dev, struct opal_session *sess, char *new_passwd)
1743 {
1744 	uint8_t cpin_uid[OPAL_UID_LENGTH];
1745 	struct spdk_opal_key opal_key = {};
1746 	int ret;
1747 
1748 	ret = opal_init_key(&opal_key, new_passwd);
1749 	if (ret != 0) {
1750 		return ret;
1751 	}
1752 
1753 	memcpy(cpin_uid, spdk_opal_uid[UID_C_PIN_SID], OPAL_UID_LENGTH);
1754 
1755 	if (opal_build_generic_pw_cmd(sess, opal_key.key, opal_key.key_len, cpin_uid, dev)) {
1756 		SPDK_ERRLOG("Error building Set SID cpin\n");
1757 		return -ERANGE;
1758 	}
1759 
1760 	ret = opal_send_recv(dev, sess);
1761 	if (ret) {
1762 		return ret;
1763 	}
1764 
1765 	return opal_parse_and_check_status(sess);
1766 }
1767 
1768 int
spdk_opal_cmd_take_ownership(struct spdk_opal_dev * dev,char * new_passwd)1769 spdk_opal_cmd_take_ownership(struct spdk_opal_dev *dev, char *new_passwd)
1770 {
1771 	int ret;
1772 	struct spdk_opal_key opal_key = {};
1773 	struct opal_session *sess;
1774 
1775 	assert(dev != NULL);
1776 
1777 	sess = opal_alloc_session(dev);
1778 	if (!sess) {
1779 		return -ENOMEM;
1780 	}
1781 
1782 	ret = opal_start_generic_session(dev, sess, UID_ANYBODY, UID_ADMINSP, NULL, 0);
1783 	if (ret) {
1784 		SPDK_ERRLOG("start admin SP session error %d\n", ret);
1785 		goto end;
1786 	}
1787 
1788 	ret = opal_get_msid_cpin_pin(dev, sess, &opal_key);
1789 	if (ret) {
1790 		SPDK_ERRLOG("get msid error %d\n", ret);
1791 		opal_end_session(dev, sess, dev->comid);
1792 		goto end;
1793 	}
1794 
1795 	ret = opal_end_session(dev, sess, dev->comid);
1796 	if (ret) {
1797 		SPDK_ERRLOG("end session error %d\n", ret);
1798 		goto end;
1799 	}
1800 
1801 	/* reuse the session structure */
1802 	memset(sess, 0, sizeof(*sess));
1803 	sess->dev = dev;
1804 	ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
1805 					 opal_key.key, opal_key.key_len);
1806 	if (ret) {
1807 		SPDK_ERRLOG("start admin SP session error %d\n", ret);
1808 		goto end;
1809 	}
1810 	memset(&opal_key, 0, sizeof(struct spdk_opal_key));
1811 
1812 	ret = opal_set_sid_cpin_pin(dev, sess, new_passwd);
1813 	if (ret) {
1814 		SPDK_ERRLOG("set cpin error %d\n", ret);
1815 		opal_end_session(dev, sess, dev->comid);
1816 		goto end;
1817 	}
1818 
1819 	ret = opal_end_session(dev, sess, dev->comid);
1820 	if (ret) {
1821 		SPDK_ERRLOG("end session error %d\n", ret);
1822 	}
1823 
1824 end:
1825 	free(sess);
1826 	return ret;
1827 }
1828 
1829 struct spdk_opal_dev *
spdk_opal_dev_construct(struct spdk_nvme_ctrlr * ctrlr)1830 	spdk_opal_dev_construct(struct spdk_nvme_ctrlr *ctrlr)
1831 {
1832 	struct spdk_opal_dev *dev;
1833 	void *payload;
1834 
1835 	dev = calloc(1, sizeof(*dev));
1836 	if (!dev) {
1837 		SPDK_ERRLOG("Memory allocation failed\n");
1838 		return NULL;
1839 	}
1840 
1841 	dev->ctrlr = ctrlr;
1842 
1843 	payload = calloc(1, IO_BUFFER_LENGTH);
1844 	if (!payload) {
1845 		free(dev);
1846 		return NULL;
1847 	}
1848 
1849 	if (opal_discovery0(dev, payload, IO_BUFFER_LENGTH)) {
1850 		SPDK_INFOLOG(opal, "Opal is not supported on this device\n");
1851 		free(dev);
1852 		free(payload);
1853 		return NULL;
1854 	}
1855 
1856 	free(payload);
1857 	return dev;
1858 }
1859 
1860 static int
opal_build_revert_tper_cmd(struct spdk_opal_dev * dev,struct opal_session * sess)1861 opal_build_revert_tper_cmd(struct spdk_opal_dev *dev, struct opal_session *sess)
1862 {
1863 	int err = 0;
1864 
1865 	opal_clear_cmd(sess);
1866 	opal_set_comid(sess, dev->comid);
1867 
1868 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1869 	opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_ADMINSP],
1870 				  OPAL_UID_LENGTH);
1871 	opal_add_token_bytestring(&err, sess, spdk_opal_method[REVERT_METHOD],
1872 				  OPAL_UID_LENGTH);
1873 	opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
1874 	opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
1875 	if (err) {
1876 		SPDK_ERRLOG("Error building REVERT TPER command.\n");
1877 		return -ERANGE;
1878 	}
1879 
1880 	return opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1881 }
1882 
1883 static int
opal_gen_new_active_key(struct spdk_opal_dev * dev,struct opal_session * sess,struct spdk_opal_key * active_key)1884 opal_gen_new_active_key(struct spdk_opal_dev *dev, struct opal_session *sess,
1885 			struct spdk_opal_key *active_key)
1886 {
1887 	uint8_t uid_data[OPAL_UID_LENGTH] = {0};
1888 	int err = 0;
1889 	int length;
1890 	int ret;
1891 
1892 	opal_clear_cmd(sess);
1893 	opal_set_comid(sess, dev->comid);
1894 
1895 	if (active_key->key_len == 0) {
1896 		SPDK_ERRLOG("Error finding previous data to generate new active key\n");
1897 		return -EINVAL;
1898 	}
1899 
1900 	length = spdk_min(active_key->key_len, OPAL_UID_LENGTH);
1901 	memcpy(uid_data, active_key->key, length);
1902 
1903 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1904 	opal_add_token_bytestring(&err, sess, uid_data, OPAL_UID_LENGTH);
1905 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GENKEY_METHOD],
1906 				  OPAL_UID_LENGTH);
1907 
1908 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
1909 
1910 	if (err) {
1911 		SPDK_ERRLOG("Error building new key generation command.\n");
1912 		return err;
1913 	}
1914 
1915 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1916 	if (ret) {
1917 		return ret;
1918 	}
1919 
1920 	ret = opal_send_recv(dev, sess);
1921 	if (ret) {
1922 		return ret;
1923 	}
1924 
1925 	return opal_parse_and_check_status(sess);
1926 }
1927 
1928 static int
opal_get_active_key_done(struct opal_session * sess,struct spdk_opal_key * active_key)1929 opal_get_active_key_done(struct opal_session *sess, struct spdk_opal_key *active_key)
1930 {
1931 	const char *key;
1932 	size_t str_len;
1933 	int error = 0;
1934 
1935 	error = opal_parse_and_check_status(sess);
1936 	if (error) {
1937 		return error;
1938 	}
1939 
1940 	str_len = opal_response_get_string(&sess->parsed_resp, 4, &key);
1941 	if (!key) {
1942 		SPDK_ERRLOG("Couldn't extract active key from response\n");
1943 		return -EINVAL;
1944 	}
1945 
1946 	active_key->key_len = str_len;
1947 	memcpy(active_key->key, key, active_key->key_len);
1948 
1949 	SPDK_DEBUGLOG(opal, "active key = %p\n", active_key->key);
1950 	return 0;
1951 }
1952 
1953 static int
opal_get_active_key(struct spdk_opal_dev * dev,struct opal_session * sess,enum spdk_opal_locking_range locking_range,struct spdk_opal_key * active_key)1954 opal_get_active_key(struct spdk_opal_dev *dev, struct opal_session *sess,
1955 		    enum spdk_opal_locking_range locking_range,
1956 		    struct spdk_opal_key *active_key)
1957 {
1958 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
1959 	int err = 0;
1960 	int ret;
1961 
1962 	opal_clear_cmd(sess);
1963 	opal_set_comid(sess, dev->comid);
1964 
1965 	opal_build_locking_range(uid_locking_range, locking_range);
1966 
1967 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
1968 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
1969 	opal_add_token_bytestring(&err, sess, spdk_opal_method[GET_METHOD],
1970 				  OPAL_UID_LENGTH);
1971 	opal_add_tokens(&err, sess, 12,
1972 			SPDK_OPAL_STARTLIST,
1973 			SPDK_OPAL_STARTLIST,
1974 			SPDK_OPAL_STARTNAME,
1975 			SPDK_OPAL_STARTCOLUMN,
1976 			SPDK_OPAL_ACTIVEKEY,
1977 			SPDK_OPAL_ENDNAME,
1978 			SPDK_OPAL_STARTNAME,
1979 			SPDK_OPAL_ENDCOLUMN,
1980 			SPDK_OPAL_ACTIVEKEY,
1981 			SPDK_OPAL_ENDNAME,
1982 			SPDK_OPAL_ENDLIST,
1983 			SPDK_OPAL_ENDLIST);
1984 
1985 	if (err) {
1986 		SPDK_ERRLOG("Error building get active key command.\n");
1987 		return err;
1988 	}
1989 
1990 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
1991 	if (ret) {
1992 		return ret;
1993 	}
1994 
1995 	ret = opal_send_recv(dev, sess);
1996 	if (ret) {
1997 		return ret;
1998 	}
1999 
2000 	return opal_get_active_key_done(sess, active_key);
2001 }
2002 
2003 static int
opal_erase_locking_range(struct spdk_opal_dev * dev,struct opal_session * sess,enum spdk_opal_locking_range locking_range)2004 opal_erase_locking_range(struct spdk_opal_dev *dev, struct opal_session *sess,
2005 			 enum spdk_opal_locking_range locking_range)
2006 {
2007 	uint8_t uid_locking_range[OPAL_UID_LENGTH];
2008 	int err = 0;
2009 	int ret;
2010 
2011 	opal_clear_cmd(sess);
2012 	opal_set_comid(sess, dev->comid);
2013 
2014 	opal_build_locking_range(uid_locking_range, locking_range);
2015 
2016 	opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
2017 	opal_add_token_bytestring(&err, sess, uid_locking_range, OPAL_UID_LENGTH);
2018 	opal_add_token_bytestring(&err, sess, spdk_opal_method[ERASE_METHOD],
2019 				  OPAL_UID_LENGTH);
2020 	opal_add_tokens(&err, sess, 2, SPDK_OPAL_STARTLIST, SPDK_OPAL_ENDLIST);
2021 
2022 	if (err) {
2023 		SPDK_ERRLOG("Error building erase locking range.\n");
2024 		return err;
2025 	}
2026 
2027 	ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
2028 	if (ret) {
2029 		return ret;
2030 	}
2031 
2032 	ret = opal_send_recv(dev, sess);
2033 	if (ret) {
2034 		return ret;
2035 	}
2036 
2037 	return opal_parse_and_check_status(sess);
2038 }
2039 
2040 int
spdk_opal_cmd_revert_tper(struct spdk_opal_dev * dev,const char * passwd)2041 spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd)
2042 {
2043 	int ret;
2044 	struct opal_session *sess;
2045 	struct spdk_opal_key opal_key = {};
2046 
2047 	assert(dev != NULL);
2048 
2049 	ret = opal_init_key(&opal_key, passwd);
2050 	if (ret) {
2051 		SPDK_ERRLOG("Init key failed\n");
2052 		return ret;
2053 	}
2054 
2055 	sess = opal_alloc_session(dev);
2056 	if (!sess) {
2057 		return -ENOMEM;
2058 	}
2059 
2060 	ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
2061 					 opal_key.key, opal_key.key_len);
2062 	if (ret) {
2063 		SPDK_ERRLOG("Error on starting admin SP session with error %d\n", ret);
2064 		free(sess);
2065 		return ret;
2066 	}
2067 
2068 	ret = opal_build_revert_tper_cmd(dev, sess);
2069 	if (ret) {
2070 		opal_end_session(dev, sess, dev->comid);
2071 		SPDK_ERRLOG("Build revert tper command with error %d\n", ret);
2072 		goto end;
2073 	}
2074 
2075 	ret = opal_send_recv(dev, sess);
2076 	if (ret) {
2077 		opal_end_session(dev, sess, dev->comid);
2078 		SPDK_ERRLOG("Error on reverting TPer with error %d\n", ret);
2079 		goto end;
2080 	}
2081 
2082 	ret = opal_parse_and_check_status(sess);
2083 	if (ret) {
2084 		opal_end_session(dev, sess, dev->comid);
2085 		SPDK_ERRLOG("Error on reverting TPer with error %d\n", ret);
2086 	}
2087 	/* No opal_end_session() required here for successful case */
2088 
2089 end:
2090 	free(sess);
2091 	return ret;
2092 }
2093 
2094 int
spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev * dev,const char * passwd)2095 spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev *dev, const char *passwd)
2096 {
2097 	struct opal_session *sess;
2098 	struct spdk_opal_key opal_key = {};
2099 	int ret;
2100 
2101 	ret = opal_init_key(&opal_key, passwd);
2102 	if (ret != 0) {
2103 		return ret;
2104 	}
2105 
2106 	sess = opal_alloc_session(dev);
2107 	if (!sess) {
2108 		return -ENOMEM;
2109 	}
2110 
2111 	ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
2112 					 opal_key.key, opal_key.key_len);
2113 	if (ret) {
2114 		SPDK_ERRLOG("Error on starting admin SP session with error %d\n", ret);
2115 		free(sess);
2116 		return ret;
2117 	}
2118 
2119 	ret = opal_get_locking_sp_lifecycle(dev, sess);
2120 	if (ret) {
2121 		SPDK_ERRLOG("Error on getting SP lifecycle with error %d\n", ret);
2122 		goto end;
2123 	}
2124 
2125 	ret = opal_activate(dev, sess);
2126 	if (ret) {
2127 		SPDK_ERRLOG("Error on activation with error %d\n", ret);
2128 	}
2129 
2130 end:
2131 	ret += opal_end_session(dev, sess, dev->comid);
2132 	if (ret) {
2133 		SPDK_ERRLOG("Error on ending session with error %d\n", ret);
2134 	}
2135 
2136 	free(sess);
2137 	return ret;
2138 }
2139 
2140 int
spdk_opal_cmd_lock_unlock(struct spdk_opal_dev * dev,enum spdk_opal_user user,enum spdk_opal_lock_state flag,enum spdk_opal_locking_range locking_range,const char * passwd)2141 spdk_opal_cmd_lock_unlock(struct spdk_opal_dev *dev, enum spdk_opal_user user,
2142 			  enum spdk_opal_lock_state flag, enum spdk_opal_locking_range locking_range,
2143 			  const char *passwd)
2144 {
2145 	struct opal_session *sess;
2146 	struct spdk_opal_key opal_key = {};
2147 	int ret;
2148 
2149 	assert(dev != NULL);
2150 
2151 	ret = opal_init_key(&opal_key, passwd);
2152 	if (ret != 0) {
2153 		return ret;
2154 	}
2155 
2156 	sess = opal_alloc_session(dev);
2157 	if (!sess) {
2158 		return -ENOMEM;
2159 	}
2160 
2161 	ret = opal_start_auth_session(dev, sess, user, &opal_key);
2162 	if (ret) {
2163 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2164 		free(sess);
2165 		return ret;
2166 	}
2167 
2168 	ret = opal_lock_unlock_range(dev, sess, locking_range, flag);
2169 	if (ret) {
2170 		SPDK_ERRLOG("lock unlock range error %d\n", ret);
2171 	}
2172 
2173 	ret += opal_end_session(dev, sess, dev->comid);
2174 	if (ret) {
2175 		SPDK_ERRLOG("end session error %d\n", ret);
2176 	}
2177 
2178 	free(sess);
2179 	return ret;
2180 }
2181 
2182 int
spdk_opal_cmd_setup_locking_range(struct spdk_opal_dev * dev,enum spdk_opal_user user,enum spdk_opal_locking_range locking_range_id,uint64_t range_start,uint64_t range_length,const char * passwd)2183 spdk_opal_cmd_setup_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user,
2184 				  enum spdk_opal_locking_range locking_range_id, uint64_t range_start,
2185 				  uint64_t range_length, const char *passwd)
2186 {
2187 	struct opal_session *sess;
2188 	struct spdk_opal_key opal_key = {};
2189 	int ret;
2190 
2191 	assert(dev != NULL);
2192 
2193 	ret = opal_init_key(&opal_key, passwd);
2194 	if (ret != 0) {
2195 		return ret;
2196 	}
2197 
2198 	sess = opal_alloc_session(dev);
2199 	if (!sess) {
2200 		return -ENOMEM;
2201 	}
2202 
2203 	ret = opal_start_auth_session(dev, sess, user, &opal_key);
2204 	if (ret) {
2205 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2206 		free(sess);
2207 		return ret;
2208 	}
2209 
2210 	ret = opal_setup_locking_range(dev, sess, locking_range_id, range_start, range_length, true,
2211 				       true);
2212 	if (ret) {
2213 		SPDK_ERRLOG("setup locking range error %d\n", ret);
2214 	}
2215 
2216 	ret += opal_end_session(dev, sess, dev->comid);
2217 	if (ret) {
2218 		SPDK_ERRLOG("end session error %d\n", ret);
2219 	}
2220 
2221 	free(sess);
2222 	return ret;
2223 }
2224 
2225 int
spdk_opal_cmd_get_max_ranges(struct spdk_opal_dev * dev,const char * passwd)2226 spdk_opal_cmd_get_max_ranges(struct spdk_opal_dev *dev, const char *passwd)
2227 {
2228 	struct opal_session *sess;
2229 	struct spdk_opal_key opal_key = {};
2230 	int ret;
2231 
2232 	assert(dev != NULL);
2233 
2234 	if (dev->max_ranges) {
2235 		return dev->max_ranges;
2236 	}
2237 
2238 	ret = opal_init_key(&opal_key, passwd);
2239 	if (ret != 0) {
2240 		return ret;
2241 	}
2242 
2243 	sess = opal_alloc_session(dev);
2244 	if (!sess) {
2245 		return -ENOMEM;
2246 	}
2247 
2248 	ret = opal_start_auth_session(dev, sess, OPAL_ADMIN1, &opal_key);
2249 	if (ret) {
2250 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2251 		free(sess);
2252 		return ret;
2253 	}
2254 
2255 	ret = opal_get_max_ranges(dev, sess);
2256 	if (ret > 0) {
2257 		dev->max_ranges = ret;
2258 	}
2259 
2260 	ret = opal_end_session(dev, sess, dev->comid);
2261 	if (ret) {
2262 		SPDK_ERRLOG("end session error %d\n", ret);
2263 	}
2264 
2265 	free(sess);
2266 
2267 	return (ret == 0 ? dev->max_ranges : ret);
2268 }
2269 
2270 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)2271 spdk_opal_cmd_get_locking_range_info(struct spdk_opal_dev *dev, const char *passwd,
2272 				     enum spdk_opal_user user_id,
2273 				     enum spdk_opal_locking_range locking_range_id)
2274 {
2275 	struct opal_session *sess;
2276 	struct spdk_opal_key opal_key = {};
2277 	int ret;
2278 
2279 	assert(dev != NULL);
2280 
2281 	ret = opal_init_key(&opal_key, passwd);
2282 	if (ret != 0) {
2283 		return ret;
2284 	}
2285 
2286 	sess = opal_alloc_session(dev);
2287 	if (!sess) {
2288 		return -ENOMEM;
2289 	}
2290 
2291 	ret = opal_start_auth_session(dev, sess, user_id, &opal_key);
2292 	if (ret) {
2293 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2294 		free(sess);
2295 		return ret;
2296 	}
2297 
2298 	ret = opal_get_locking_range_info(dev, sess, locking_range_id);
2299 	if (ret) {
2300 		SPDK_ERRLOG("get locking range info error %d\n", ret);
2301 	}
2302 
2303 	ret += opal_end_session(dev, sess, dev->comid);
2304 	if (ret) {
2305 		SPDK_ERRLOG("end session error %d\n", ret);
2306 	}
2307 
2308 	free(sess);
2309 	return ret;
2310 }
2311 
2312 int
spdk_opal_cmd_enable_user(struct spdk_opal_dev * dev,enum spdk_opal_user user_id,const char * passwd)2313 spdk_opal_cmd_enable_user(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2314 			  const char *passwd)
2315 {
2316 	struct opal_session *sess;
2317 	struct spdk_opal_key opal_key = {};
2318 	int ret;
2319 
2320 	assert(dev != NULL);
2321 
2322 	ret = opal_init_key(&opal_key, passwd);
2323 	if (ret != 0) {
2324 		return ret;
2325 	}
2326 
2327 	sess = opal_alloc_session(dev);
2328 	if (!sess) {
2329 		return -ENOMEM;
2330 	}
2331 
2332 	ret =  opal_start_generic_session(dev, sess, UID_ADMIN1, UID_LOCKINGSP,
2333 					  opal_key.key, opal_key.key_len);
2334 	if (ret) {
2335 		SPDK_ERRLOG("start locking SP session error %d\n", ret);
2336 		free(sess);
2337 		return ret;
2338 	}
2339 
2340 	ret = opal_enable_user(dev, sess, user_id);
2341 	if (ret) {
2342 		SPDK_ERRLOG("enable user error %d\n", ret);
2343 	}
2344 
2345 	ret += opal_end_session(dev, sess, dev->comid);
2346 	if (ret) {
2347 		SPDK_ERRLOG("end session error %d\n", ret);
2348 	}
2349 
2350 	free(sess);
2351 	return ret;
2352 }
2353 
2354 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)2355 spdk_opal_cmd_add_user_to_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2356 					enum spdk_opal_locking_range locking_range_id,
2357 					enum spdk_opal_lock_state lock_flag, const char *passwd)
2358 {
2359 	struct opal_session *sess;
2360 	struct spdk_opal_key opal_key = {};
2361 	int ret;
2362 
2363 	assert(dev != NULL);
2364 
2365 	ret = opal_init_key(&opal_key, passwd);
2366 	if (ret != 0) {
2367 		return ret;
2368 	}
2369 
2370 	sess = opal_alloc_session(dev);
2371 	if (!sess) {
2372 		return -ENOMEM;
2373 	}
2374 
2375 	ret =  opal_start_generic_session(dev, sess, UID_ADMIN1, UID_LOCKINGSP,
2376 					  opal_key.key, opal_key.key_len);
2377 	if (ret) {
2378 		SPDK_ERRLOG("start locking SP session error %d\n", ret);
2379 		free(sess);
2380 		return ret;
2381 	}
2382 
2383 	ret = opal_add_user_to_locking_range(dev, sess, user_id, locking_range_id, lock_flag);
2384 	if (ret) {
2385 		SPDK_ERRLOG("add user to locking range error %d\n", ret);
2386 	}
2387 
2388 	ret += opal_end_session(dev, sess, dev->comid);
2389 	if (ret) {
2390 		SPDK_ERRLOG("end session error %d\n", ret);
2391 	}
2392 
2393 	free(sess);
2394 	return ret;
2395 }
2396 
2397 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)2398 spdk_opal_cmd_set_new_passwd(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2399 			     const char *new_passwd, const char *old_passwd, bool new_user)
2400 {
2401 	struct opal_session *sess;
2402 	struct spdk_opal_key old_key = {};
2403 	struct spdk_opal_key new_key = {};
2404 	int ret;
2405 
2406 	assert(dev != NULL);
2407 
2408 	ret = opal_init_key(&old_key, old_passwd);
2409 	if (ret != 0) {
2410 		return ret;
2411 	}
2412 
2413 	ret = opal_init_key(&new_key, new_passwd);
2414 	if (ret != 0) {
2415 		return ret;
2416 	}
2417 
2418 	sess = opal_alloc_session(dev);
2419 	if (!sess) {
2420 		return -ENOMEM;
2421 	}
2422 
2423 	ret = opal_start_auth_session(dev, sess, new_user ? OPAL_ADMIN1 : user_id,
2424 				      &old_key);
2425 	if (ret) {
2426 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2427 		free(sess);
2428 		return ret;
2429 	}
2430 
2431 	ret = opal_new_user_passwd(dev, sess, user_id, &new_key);
2432 	if (ret) {
2433 		SPDK_ERRLOG("set new passwd error %d\n", ret);
2434 	}
2435 
2436 	ret += opal_end_session(dev, sess, dev->comid);
2437 	if (ret) {
2438 		SPDK_ERRLOG("end session error %d\n", ret);
2439 	}
2440 
2441 	free(sess);
2442 	return ret;
2443 }
2444 
2445 int
spdk_opal_cmd_erase_locking_range(struct spdk_opal_dev * dev,enum spdk_opal_user user_id,enum spdk_opal_locking_range locking_range_id,const char * password)2446 spdk_opal_cmd_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2447 				  enum spdk_opal_locking_range locking_range_id, const char *password)
2448 {
2449 	struct opal_session *sess;
2450 	struct spdk_opal_key opal_key = {};
2451 	int ret;
2452 
2453 	assert(dev != NULL);
2454 
2455 	ret = opal_init_key(&opal_key, password);
2456 	if (ret != 0) {
2457 		return ret;
2458 	}
2459 
2460 	sess = opal_alloc_session(dev);
2461 	if (!sess) {
2462 		return -ENOMEM;
2463 	}
2464 
2465 	ret = opal_start_auth_session(dev, sess, user_id, &opal_key);
2466 	if (ret) {
2467 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2468 		free(sess);
2469 		return ret;
2470 	}
2471 
2472 	ret = opal_erase_locking_range(dev, sess, locking_range_id);
2473 	if (ret) {
2474 		SPDK_ERRLOG("get active key error %d\n", ret);
2475 	}
2476 
2477 	ret += opal_end_session(dev, sess, dev->comid);
2478 	if (ret) {
2479 		SPDK_ERRLOG("end session error %d\n", ret);
2480 	}
2481 
2482 	free(sess);
2483 	return ret;
2484 }
2485 
2486 int
spdk_opal_cmd_secure_erase_locking_range(struct spdk_opal_dev * dev,enum spdk_opal_user user_id,enum spdk_opal_locking_range locking_range_id,const char * password)2487 spdk_opal_cmd_secure_erase_locking_range(struct spdk_opal_dev *dev, enum spdk_opal_user user_id,
2488 		enum spdk_opal_locking_range locking_range_id, const char *password)
2489 {
2490 	struct opal_session *sess;
2491 	struct spdk_opal_key opal_key = {};
2492 	struct spdk_opal_key *active_key;
2493 	int ret;
2494 
2495 	assert(dev != NULL);
2496 
2497 	ret = opal_init_key(&opal_key, password);
2498 	if (ret != 0) {
2499 		return ret;
2500 	}
2501 
2502 	active_key = calloc(1, sizeof(*active_key));
2503 	if (!active_key) {
2504 		return -ENOMEM;
2505 	}
2506 
2507 	sess = opal_alloc_session(dev);
2508 	if (!sess) {
2509 		free(active_key);
2510 		return -ENOMEM;
2511 	}
2512 
2513 	ret = opal_start_auth_session(dev, sess, user_id, &opal_key);
2514 	if (ret) {
2515 		SPDK_ERRLOG("start authenticate session error %d\n", ret);
2516 		free(active_key);
2517 		free(sess);
2518 		return ret;
2519 	}
2520 
2521 	ret = opal_get_active_key(dev, sess, locking_range_id, active_key);
2522 	if (ret) {
2523 		SPDK_ERRLOG("get active key error %d\n", ret);
2524 		goto end;
2525 	}
2526 
2527 	ret = opal_gen_new_active_key(dev, sess, active_key);
2528 	if (ret) {
2529 		SPDK_ERRLOG("generate new active key error %d\n", ret);
2530 		goto end;
2531 	}
2532 	memset(active_key, 0, sizeof(struct spdk_opal_key));
2533 
2534 end:
2535 	ret += opal_end_session(dev, sess, dev->comid);
2536 	if (ret) {
2537 		SPDK_ERRLOG("end session error %d\n", ret);
2538 	}
2539 	free(active_key);
2540 	free(sess);
2541 	return ret;
2542 }
2543 
2544 struct spdk_opal_d0_features_info *
spdk_opal_get_d0_features_info(struct spdk_opal_dev * dev)2545 spdk_opal_get_d0_features_info(struct spdk_opal_dev *dev)
2546 {
2547 	return &dev->feat_info;
2548 }
2549 
2550 struct spdk_opal_locking_range_info *
spdk_opal_get_locking_range_info(struct spdk_opal_dev * dev,enum spdk_opal_locking_range id)2551 spdk_opal_get_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id)
2552 {
2553 	assert(id < SPDK_OPAL_MAX_LOCKING_RANGE);
2554 	return &dev->locking_ranges[id];
2555 }
2556 
2557 void
spdk_opal_free_locking_range_info(struct spdk_opal_dev * dev,enum spdk_opal_locking_range id)2558 spdk_opal_free_locking_range_info(struct spdk_opal_dev *dev, enum spdk_opal_locking_range id)
2559 {
2560 	struct spdk_opal_locking_range_info *info;
2561 
2562 	assert(id < SPDK_OPAL_MAX_LOCKING_RANGE);
2563 	info = &dev->locking_ranges[id];
2564 	memset(info, 0, sizeof(*info));
2565 }
2566 
2567 /* Log component for opal submodule */
2568 SPDK_LOG_REGISTER_COMPONENT(opal)
2569