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