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