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