Branch data 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 : 156 : opal_nvme_security_recv_done(void *arg, const struct spdk_nvme_cpl *cpl)
14 : : {
15 : 156 : struct opal_session *sess = arg;
16 : 156 : struct spdk_opal_dev *dev = sess->dev;
17 : 156 : void *response = sess->resp;
18 : 156 : struct spdk_opal_compacket *header = response;
19 : : int ret;
20 : :
21 [ + - + + ]: 156 : if (spdk_nvme_cpl_is_error(cpl)) {
22 : 3 : sess->sess_cb(sess, -EIO, sess->cb_arg);
23 : 3 : return;
24 : : }
25 : :
26 [ + + + - ]: 153 : if (!header->outstanding_data && !header->min_transfer) {
27 : 5 : sess->sess_cb(sess, 0, sess->cb_arg);
28 : 5 : return;
29 : : }
30 : :
31 [ - + ]: 148 : memset(response, 0, IO_BUFFER_LENGTH);
32 : 148 : ret = spdk_nvme_ctrlr_cmd_security_receive(dev->ctrlr, SPDK_SCSI_SECP_TCG,
33 : 148 : dev->comid, 0, sess->resp, IO_BUFFER_LENGTH,
34 : : opal_nvme_security_recv_done, sess);
35 [ + + ]: 148 : if (ret) {
36 : 3 : sess->sess_cb(sess, ret, sess->cb_arg);
37 : : }
38 : : }
39 : :
40 : : static void
41 : 8 : opal_nvme_security_send_done(void *arg, const struct spdk_nvme_cpl *cpl)
42 : : {
43 : 8 : struct opal_session *sess = arg;
44 : 8 : struct spdk_opal_dev *dev = sess->dev;
45 : : int ret;
46 : :
47 [ + - + + ]: 8 : if (spdk_nvme_cpl_is_error(cpl)) {
48 : 3 : sess->sess_cb(sess, -EIO, sess->cb_arg);
49 : 3 : return;
50 : : }
51 : :
52 : 5 : ret = spdk_nvme_ctrlr_cmd_security_receive(dev->ctrlr, SPDK_SCSI_SECP_TCG,
53 : 5 : dev->comid, 0, sess->resp, IO_BUFFER_LENGTH,
54 : : opal_nvme_security_recv_done, sess);
55 [ + + ]: 5 : if (ret) {
56 : 3 : sess->sess_cb(sess, ret, sess->cb_arg);
57 : : }
58 : : }
59 : :
60 : : static int
61 : 2 : opal_nvme_security_send(struct spdk_opal_dev *dev, struct opal_session *sess,
62 : : opal_sess_cb sess_cb, void *cb_arg)
63 : : {
64 : 2 : sess->sess_cb = sess_cb;
65 : 2 : sess->cb_arg = cb_arg;
66 : :
67 : 2 : return spdk_nvme_ctrlr_cmd_security_send(dev->ctrlr, SPDK_SCSI_SECP_TCG, dev->comid,
68 : 2 : 0, sess->cmd, IO_BUFFER_LENGTH,
69 : : opal_nvme_security_send_done, sess);
70 : : }
71 : :
72 : : static void
73 : 2 : opal_send_recv_done(struct opal_session *sess, int status, void *ctx)
74 : : {
75 : 2 : sess->status = status;
76 : 2 : sess->done = true;
77 : 2 : }
78 : :
79 : : static int
80 : 2 : opal_send_recv(struct spdk_opal_dev *dev, struct opal_session *sess)
81 : : {
82 : : int ret;
83 : :
84 : 2 : sess->done = false;
85 : 2 : ret = opal_nvme_security_send(dev, sess, opal_send_recv_done, NULL);
86 [ - + ]: 2 : if (ret) {
87 : 0 : return ret;
88 : : }
89 : :
90 [ - + + + ]: 1105 : while (!sess->done) {
91 : 1103 : spdk_nvme_ctrlr_process_admin_completions(dev->ctrlr);
92 : : }
93 : :
94 : 2 : return sess->status;
95 : : }
96 : :
97 : : static struct opal_session *
98 : 2 : opal_alloc_session(struct spdk_opal_dev *dev)
99 : : {
100 : : struct opal_session *sess;
101 : :
102 : 2 : sess = calloc(1, sizeof(*sess));
103 [ - + ]: 2 : if (!sess) {
104 : 0 : return NULL;
105 : : }
106 : 2 : sess->dev = dev;
107 : :
108 : 2 : return sess;
109 : : }
110 : :
111 : : static void
112 : 45 : opal_add_token_u8(int *err, struct opal_session *sess, uint8_t token)
113 : : {
114 [ - + ]: 45 : if (*err) {
115 : 0 : return;
116 : : }
117 [ - + ]: 45 : 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 : 45 : sess->cmd[sess->cmd_pos++] = token;
123 : : }
124 : :
125 : : static void
126 : 13 : opal_add_short_atom_header(struct opal_session *sess, bool bytestring,
127 : : bool has_sign, size_t len)
128 : : {
129 : : uint8_t atom;
130 : 13 : int err = 0;
131 : :
132 : 13 : atom = SPDK_SHORT_ATOM_ID;
133 [ + - ]: 13 : atom |= bytestring ? SPDK_SHORT_ATOM_BYTESTRING_FLAG : 0;
134 [ - + ]: 13 : atom |= has_sign ? SPDK_SHORT_ATOM_SIGN_FLAG : 0;
135 : 13 : atom |= len & SPDK_SHORT_ATOM_LEN_MASK;
136 : :
137 : 13 : opal_add_token_u8(&err, sess, atom);
138 : 13 : }
139 : :
140 : : static void
141 : 3 : 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 : 3 : header = SPDK_MEDIUM_ATOM_ID;
147 [ + - ]: 3 : header |= bytestring ? SPDK_MEDIUM_ATOM_BYTESTRING_FLAG : 0;
148 [ - + ]: 3 : header |= has_sign ? SPDK_MEDIUM_ATOM_SIGN_FLAG : 0;
149 : 3 : header |= (len >> 8) & SPDK_MEDIUM_ATOM_LEN_MASK;
150 : 3 : sess->cmd[sess->cmd_pos++] = header;
151 : 3 : sess->cmd[sess->cmd_pos++] = len;
152 : 3 : }
153 : :
154 : : static void
155 : 19 : opal_add_token_bytestring(int *err, struct opal_session *sess,
156 : : const uint8_t *bytestring, size_t len)
157 : : {
158 : 19 : size_t header_len = 1;
159 : 19 : bool is_short_atom = true;
160 : :
161 [ - + ]: 19 : if (*err) {
162 : 0 : return;
163 : : }
164 : :
165 [ + + ]: 19 : if (len & ~SPDK_SHORT_ATOM_LEN_MASK) {
166 : 6 : header_len = 2;
167 : 6 : is_short_atom = false;
168 : : }
169 : :
170 [ + + ]: 19 : if (len >= IO_BUFFER_LENGTH - sess->cmd_pos - header_len) {
171 : 3 : SPDK_ERRLOG("Error adding bytestring: end of buffer.\n");
172 : 3 : *err = -ERANGE;
173 : 3 : return;
174 : : }
175 : :
176 [ + + ]: 16 : if (is_short_atom) {
177 : 13 : opal_add_short_atom_header(sess, true, false, len);
178 : : } else {
179 : 3 : opal_add_medium_atom_header(sess, true, false, len);
180 : : }
181 : :
182 [ - + - + ]: 16 : memcpy(&sess->cmd[sess->cmd_pos], bytestring, len);
183 : 16 : sess->cmd_pos += len;
184 : : }
185 : :
186 : : static void
187 : 2 : opal_add_token_u64(int *err, struct opal_session *sess, uint64_t number)
188 : : {
189 : 2 : int startat = 0;
190 : :
191 [ - + ]: 2 : if (*err) {
192 : 0 : return;
193 : : }
194 : :
195 : : /* add header first */
196 [ - + ]: 2 : if (number <= SPDK_TINY_ATOM_DATA_MASK) {
197 : 0 : sess->cmd[sess->cmd_pos++] = (uint8_t) number & SPDK_TINY_ATOM_DATA_MASK;
198 : : } else {
199 [ + - ]: 2 : if (number < 0x100) {
200 : 2 : sess->cmd[sess->cmd_pos++] = 0x81; /* short atom, 1 byte length */
201 : 2 : startat = 0;
202 [ # # ]: 0 : } else if (number < 0x10000) {
203 : 0 : sess->cmd[sess->cmd_pos++] = 0x82; /* short atom, 2 byte length */
204 : 0 : startat = 1;
205 [ # # ]: 0 : } else if (number < 0x100000000) {
206 : 0 : sess->cmd[sess->cmd_pos++] = 0x84; /* short atom, 4 byte length */
207 : 0 : startat = 3;
208 : : } else {
209 : 0 : sess->cmd[sess->cmd_pos++] = 0x88; /* short atom, 8 byte length */
210 : 0 : startat = 7;
211 : : }
212 : :
213 : : /* add number value */
214 [ + + ]: 4 : for (int i = startat; i > -1; i--) {
215 [ - + ]: 2 : sess->cmd[sess->cmd_pos++] = (uint8_t)((number >> (i * 8)) & 0xff);
216 : : }
217 : : }
218 : : }
219 : :
220 : : static void
221 : 4 : opal_add_tokens(int *err, struct opal_session *sess, int num, ...)
222 : : {
223 : : int i;
224 : 2 : va_list args_ptr;
225 : : enum spdk_opal_token tmp;
226 : :
227 : 4 : va_start(args_ptr, num);
228 : :
229 [ + + ]: 22 : for (i = 0; i < num; i++) {
230 : 18 : tmp = va_arg(args_ptr, enum spdk_opal_token);
231 : 18 : opal_add_token_u8(err, sess, tmp);
232 [ - + ]: 18 : if (*err != 0) { break; }
233 : : }
234 : :
235 : 4 : va_end(args_ptr);
236 : 4 : }
237 : :
238 : : static int
239 : 2 : opal_cmd_finalize(struct opal_session *sess, uint32_t hsn, uint32_t tsn, bool eod)
240 : : {
241 : : struct spdk_opal_header *hdr;
242 : 2 : int err = 0;
243 : :
244 [ + - ]: 2 : if (eod) {
245 : 2 : opal_add_tokens(&err, sess, 6, SPDK_OPAL_ENDOFDATA,
246 : : SPDK_OPAL_STARTLIST,
247 : : 0, 0, 0,
248 : : SPDK_OPAL_ENDLIST);
249 : : }
250 : :
251 [ - + ]: 2 : if (err) {
252 : 0 : SPDK_ERRLOG("Error finalizing command.\n");
253 : 0 : return -EFAULT;
254 : : }
255 : :
256 : 2 : hdr = (struct spdk_opal_header *)sess->cmd;
257 : :
258 : 2 : to_be32(&hdr->packet.session_tsn, tsn);
259 : 2 : to_be32(&hdr->packet.session_hsn, hsn);
260 : :
261 : 2 : to_be32(&hdr->sub_packet.length, sess->cmd_pos - sizeof(*hdr));
262 [ + + ]: 4 : while (sess->cmd_pos % 4) {
263 [ - + ]: 2 : if (sess->cmd_pos >= IO_BUFFER_LENGTH) {
264 : 0 : SPDK_ERRLOG("Error: Buffer overrun\n");
265 : 0 : return -ERANGE;
266 : : }
267 : 2 : sess->cmd[sess->cmd_pos++] = 0;
268 : : }
269 : 2 : to_be32(&hdr->packet.length, sess->cmd_pos - sizeof(hdr->com_packet) -
270 : : sizeof(hdr->packet));
271 : 2 : to_be32(&hdr->com_packet.length, sess->cmd_pos - sizeof(hdr->com_packet));
272 : :
273 : 2 : return 0;
274 : : }
275 : :
276 : : static size_t
277 : 6 : opal_response_parse_tiny(struct spdk_opal_resp_token *token,
278 : : const uint8_t *pos)
279 : : {
280 : 6 : token->pos = pos;
281 : 6 : token->len = 1;
282 : 6 : token->width = OPAL_WIDTH_TINY;
283 : :
284 [ - + ]: 6 : if (pos[0] & SPDK_TINY_ATOM_SIGN_FLAG) {
285 : 0 : token->type = OPAL_DTA_TOKENID_SINT;
286 : : } else {
287 : 6 : token->type = OPAL_DTA_TOKENID_UINT;
288 : 6 : token->stored.unsigned_num = pos[0] & SPDK_TINY_ATOM_DATA_MASK;
289 : : }
290 : :
291 : 6 : return token->len;
292 : : }
293 : :
294 : : static int
295 : 8 : opal_response_parse_short(struct spdk_opal_resp_token *token,
296 : : const uint8_t *pos)
297 : : {
298 : 8 : token->pos = pos;
299 : 8 : token->len = (pos[0] & SPDK_SHORT_ATOM_LEN_MASK) + 1; /* plus 1-byte header */
300 : 8 : token->width = OPAL_WIDTH_SHORT;
301 : :
302 [ + + ]: 8 : if (pos[0] & SPDK_SHORT_ATOM_BYTESTRING_FLAG) {
303 : 4 : token->type = OPAL_DTA_TOKENID_BYTESTRING;
304 [ - + ]: 4 : } else if (pos[0] & SPDK_SHORT_ATOM_SIGN_FLAG) {
305 : 0 : token->type = OPAL_DTA_TOKENID_SINT;
306 : : } else {
307 : 4 : uint64_t u_integer = 0;
308 : 4 : size_t i, b = 0;
309 : :
310 : 4 : token->type = OPAL_DTA_TOKENID_UINT;
311 [ - + ]: 4 : if (token->len > 9) {
312 : 0 : SPDK_ERRLOG("uint64 with more than 8 bytes\n");
313 : 0 : return -EINVAL;
314 : : }
315 [ + + ]: 12 : for (i = token->len - 1; i > 0; i--) {
316 [ - + ]: 8 : u_integer |= ((uint64_t)pos[i] << (8 * b));
317 : 8 : b++;
318 : : }
319 : 4 : token->stored.unsigned_num = u_integer;
320 : : }
321 : :
322 : 8 : return token->len;
323 : : }
324 : :
325 : : static size_t
326 : 0 : opal_response_parse_medium(struct spdk_opal_resp_token *token,
327 : : const uint8_t *pos)
328 : : {
329 : 0 : token->pos = pos;
330 : 0 : token->len = (((pos[0] & SPDK_MEDIUM_ATOM_LEN_MASK) << 8) | pos[1]) + 2; /* plus 2-byte header */
331 : 0 : token->width = OPAL_WIDTH_MEDIUM;
332 : :
333 [ # # ]: 0 : if (pos[0] & SPDK_MEDIUM_ATOM_BYTESTRING_FLAG) {
334 : 0 : token->type = OPAL_DTA_TOKENID_BYTESTRING;
335 [ # # ]: 0 : } else if (pos[0] & SPDK_MEDIUM_ATOM_SIGN_FLAG) {
336 : 0 : token->type = OPAL_DTA_TOKENID_SINT;
337 : : } else {
338 : 0 : token->type = OPAL_DTA_TOKENID_UINT;
339 : : }
340 : :
341 : 0 : return token->len;
342 : : }
343 : :
344 : : static size_t
345 : 0 : opal_response_parse_long(struct spdk_opal_resp_token *token,
346 : : const uint8_t *pos)
347 : : {
348 : 0 : token->pos = pos;
349 [ # # # # ]: 0 : token->len = ((pos[1] << 16) | (pos[2] << 8) | pos[3]) + 4; /* plus 4-byte header */
350 : 0 : token->width = OPAL_WIDTH_LONG;
351 : :
352 [ # # ]: 0 : if (pos[0] & SPDK_LONG_ATOM_BYTESTRING_FLAG) {
353 : 0 : token->type = OPAL_DTA_TOKENID_BYTESTRING;
354 [ # # ]: 0 : } else if (pos[0] & SPDK_LONG_ATOM_SIGN_FLAG) {
355 : 0 : token->type = OPAL_DTA_TOKENID_SINT;
356 : : } else {
357 : 0 : token->type = OPAL_DTA_TOKENID_UINT;
358 : : }
359 : :
360 : 0 : return token->len;
361 : : }
362 : :
363 : : static size_t
364 : 12 : opal_response_parse_token(struct spdk_opal_resp_token *token,
365 : : const uint8_t *pos)
366 : : {
367 : 12 : token->pos = pos;
368 : 12 : token->len = 1;
369 : 12 : token->type = OPAL_DTA_TOKENID_TOKEN;
370 : 12 : token->width = OPAL_WIDTH_TOKEN;
371 : :
372 : 12 : return token->len;
373 : : }
374 : :
375 : : static int
376 : 2 : 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 : 2 : 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 [ + - - + ]: 2 : if (!buf || !resp) {
388 : 0 : return -EINVAL;
389 : : }
390 : :
391 : 2 : hdr = (struct spdk_opal_header *)buf;
392 : 2 : pos = buf + sizeof(*hdr);
393 : :
394 : 2 : clen = from_be32(&hdr->com_packet.length);
395 : 2 : plen = from_be32(&hdr->packet.length);
396 : 2 : slen = from_be32(&hdr->sub_packet.length);
397 [ - + - + ]: 2 : SPDK_DEBUGLOG(opal, "Response size: cp: %u, pkt: %u, subpkt: %u\n",
398 : : clen, plen, slen);
399 : :
400 [ + - + - : 2 : if (clen == 0 || plen == 0 || slen == 0 ||
+ - - + ]
401 : : slen > IO_BUFFER_LENGTH - sizeof(*hdr)) {
402 : 0 : SPDK_ERRLOG("Bad header length. cp: %u, pkt: %u, subpkt: %u\n",
403 : : clen, plen, slen);
404 : 0 : return -EINVAL;
405 : : }
406 : :
407 [ - + ]: 2 : if (pos > buf + length) {
408 : 0 : SPDK_ERRLOG("Pointer out of range\n");
409 : 0 : return -EFAULT;
410 : : }
411 : :
412 : 2 : token_iter = resp->resp_tokens;
413 : 2 : total = slen;
414 : :
415 [ + + ]: 28 : while (total > 0) {
416 [ + + ]: 26 : if (pos[0] <= SPDK_TINY_ATOM_TYPE_MAX) { /* tiny atom */
417 : 6 : token_length = opal_response_parse_tiny(token_iter, pos);
418 [ + + ]: 20 : } else if (pos[0] <= SPDK_SHORT_ATOM_TYPE_MAX) { /* short atom */
419 : 8 : token_length = opal_response_parse_short(token_iter, pos);
420 [ - + ]: 12 : } else if (pos[0] <= SPDK_MEDIUM_ATOM_TYPE_MAX) { /* medium atom */
421 : 0 : token_length = opal_response_parse_medium(token_iter, pos);
422 [ - + ]: 12 : } else if (pos[0] <= SPDK_LONG_ATOM_TYPE_MAX) { /* long atom */
423 : 0 : token_length = opal_response_parse_long(token_iter, pos);
424 : : } else { /* TOKEN */
425 : 12 : token_length = opal_response_parse_token(token_iter, pos);
426 : : }
427 : :
428 [ - + ]: 26 : if (token_length <= 0) {
429 : 0 : SPDK_ERRLOG("Parse response failure.\n");
430 : 0 : return -EINVAL;
431 : : }
432 : :
433 : 26 : pos += token_length;
434 : 26 : total -= token_length;
435 : 26 : token_iter++;
436 : 26 : num_entries++;
437 : :
438 [ - + ]: 26 : if (total < 0) {
439 : 0 : SPDK_ERRLOG("Length not matching.\n");
440 : 0 : return -EINVAL;
441 : : }
442 : : }
443 : :
444 [ - + ]: 2 : if (num_entries == 0) {
445 : 0 : SPDK_ERRLOG("Couldn't parse response.\n");
446 : 0 : return -EINVAL;
447 : : }
448 : 2 : resp->num = num_entries;
449 : :
450 : 2 : return 0;
451 : : }
452 : :
453 : : static inline bool
454 : 54 : opal_response_token_matches(const struct spdk_opal_resp_token *token,
455 : : uint8_t match)
456 : : {
457 [ + - ]: 54 : if (!token ||
458 [ + + ]: 54 : token->type != OPAL_DTA_TOKENID_TOKEN ||
459 [ + + ]: 26 : token->pos[0] != match) {
460 : 46 : return false;
461 : : }
462 : 8 : return true;
463 : : }
464 : :
465 : : static const struct spdk_opal_resp_token *
466 : 28 : opal_response_get_token(const struct spdk_opal_resp_parsed *resp, int index)
467 : : {
468 : : const struct spdk_opal_resp_token *token;
469 : :
470 [ - + ]: 28 : 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 : 28 : token = &resp->resp_tokens[index];
477 [ - + ]: 28 : if (token->len == 0) {
478 : 0 : SPDK_ERRLOG("Token length must be non-zero\n");
479 : 0 : return NULL;
480 : : }
481 : :
482 : 28 : return token;
483 : : }
484 : :
485 : : static uint64_t
486 : 2 : opal_response_get_u64(const struct spdk_opal_resp_parsed *resp, int index)
487 : : {
488 [ - + ]: 2 : if (!resp) {
489 : 0 : SPDK_ERRLOG("Response is NULL\n");
490 : 0 : return 0;
491 : : }
492 : :
493 [ - + ]: 2 : 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 [ - + ]: 2 : 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 : 2 : return resp->resp_tokens[index].stored.unsigned_num;
507 : : }
508 : :
509 : : static uint16_t
510 : 0 : opal_response_get_u16(const struct spdk_opal_resp_parsed *resp, int index)
511 : : {
512 : 0 : uint64_t i = opal_response_get_u64(resp, index);
513 [ # # ]: 0 : if (i > 0xffffull) {
514 : 0 : SPDK_ERRLOG("parse response u16 failed. Overflow\n");
515 : 0 : return 0;
516 : : }
517 : 0 : return (uint16_t) i;
518 : : }
519 : :
520 : : static uint8_t
521 : 0 : opal_response_get_u8(const struct spdk_opal_resp_parsed *resp, int index)
522 : : {
523 : 0 : uint64_t i = opal_response_get_u64(resp, index);
524 [ # # ]: 0 : if (i > 0xffull) {
525 : 0 : SPDK_ERRLOG("parse response u8 failed. Overflow\n");
526 : 0 : return 0;
527 : : }
528 : 0 : return (uint8_t) i;
529 : : }
530 : :
531 : : static size_t
532 : 0 : opal_response_get_string(const struct spdk_opal_resp_parsed *resp, int n,
533 : : const char **store)
534 : : {
535 : : uint8_t header_len;
536 : : struct spdk_opal_resp_token token;
537 : 0 : *store = NULL;
538 [ # # ]: 0 : if (!resp) {
539 : 0 : SPDK_ERRLOG("Response is NULL\n");
540 : 0 : return 0;
541 : : }
542 : :
543 [ # # ]: 0 : if (n > resp->num) {
544 : 0 : SPDK_ERRLOG("Response has %d tokens. Can't access %d\n",
545 : : resp->num, n);
546 : 0 : return 0;
547 : : }
548 : :
549 : 0 : token = resp->resp_tokens[n];
550 [ # # ]: 0 : if (token.type != OPAL_DTA_TOKENID_BYTESTRING) {
551 : 0 : SPDK_ERRLOG("Token is not a byte string!\n");
552 : 0 : return 0;
553 : : }
554 : :
555 [ # # # # ]: 0 : switch (token.width) {
556 : 0 : case OPAL_WIDTH_SHORT:
557 : 0 : header_len = 1;
558 : 0 : break;
559 : 0 : case OPAL_WIDTH_MEDIUM:
560 : 0 : header_len = 2;
561 : 0 : break;
562 : 0 : case OPAL_WIDTH_LONG:
563 : 0 : header_len = 4;
564 : 0 : break;
565 : 0 : default:
566 : 0 : SPDK_ERRLOG("Can't get string from this Token\n");
567 : 0 : return 0;
568 : : }
569 : :
570 : 0 : *store = token.pos + header_len;
571 : 0 : return token.len - header_len;
572 : : }
573 : :
574 : : static int
575 : 2 : opal_response_status(const struct spdk_opal_resp_parsed *resp)
576 : : {
577 : : const struct spdk_opal_resp_token *tok;
578 : 2 : int startlist_idx = -1, endlist_idx = -1;
579 : :
580 : : /* if we get an EOS token, just return 0 */
581 : 2 : tok = opal_response_get_token(resp, 0);
582 [ - + ]: 2 : 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 [ + + ]: 28 : for (int i = resp->num - 1; i >= 0; i--) {
590 : 26 : tok = opal_response_get_token(resp, i);
591 [ + + + + ]: 26 : if (opal_response_token_matches(tok, SPDK_OPAL_STARTLIST) && startlist_idx == -1) {
592 : 2 : startlist_idx = i;
593 : : }
594 [ + + + + ]: 26 : if (opal_response_token_matches(tok, SPDK_OPAL_ENDLIST) && endlist_idx == -1) {
595 : 2 : endlist_idx = i;
596 : : }
597 : : }
598 : :
599 [ + - + - : 2 : 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 : 2 : 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
610 : 2 : opal_parse_and_check_status(struct opal_session *sess)
611 : : {
612 : : int error;
613 : :
614 : 2 : error = opal_response_parse(sess->resp, IO_BUFFER_LENGTH, &sess->parsed_resp);
615 [ - + ]: 2 : if (error) {
616 : 0 : SPDK_ERRLOG("Couldn't parse response.\n");
617 : 0 : return error;
618 : : }
619 : 2 : return opal_response_status(&sess->parsed_resp);
620 : : }
621 : :
622 : : static inline void
623 : 2 : opal_clear_cmd(struct opal_session *sess)
624 : : {
625 : 2 : sess->cmd_pos = sizeof(struct spdk_opal_header);
626 [ - + ]: 2 : memset(sess->cmd, 0, IO_BUFFER_LENGTH);
627 : 2 : }
628 : :
629 : : static inline void
630 : 2 : opal_set_comid(struct opal_session *sess, uint16_t comid)
631 : : {
632 : 2 : struct spdk_opal_header *hdr = (struct spdk_opal_header *)sess->cmd;
633 : :
634 : 2 : hdr->com_packet.comid[0] = comid >> 8;
635 : 2 : hdr->com_packet.comid[1] = comid;
636 : 2 : hdr->com_packet.extended_comid[0] = 0;
637 : 2 : hdr->com_packet.extended_comid[1] = 0;
638 : 2 : }
639 : :
640 : : static inline int
641 : 2 : opal_init_key(struct spdk_opal_key *opal_key, const char *passwd)
642 : : {
643 : : int len;
644 : :
645 [ + - - + ]: 2 : if (passwd == NULL || passwd[0] == '\0') {
646 : 0 : SPDK_ERRLOG("Password is empty. Create key failed\n");
647 : 0 : return -EINVAL;
648 : : }
649 : :
650 [ - + ]: 2 : len = strlen(passwd);
651 : :
652 [ - + ]: 2 : if (len >= OPAL_KEY_MAX) {
653 : 0 : SPDK_ERRLOG("Password too long. Create key failed\n");
654 : 0 : return -EINVAL;
655 : : }
656 : :
657 : 2 : opal_key->key_len = len;
658 [ - + - + ]: 2 : memcpy(opal_key->key, passwd, opal_key->key_len);
659 : :
660 : 2 : return 0;
661 : : }
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 : : }
677 : :
678 : : static void
679 : 26 : opal_check_tper(struct spdk_opal_dev *dev, const void *data)
680 : : {
681 : 26 : const struct spdk_opal_d0_tper_feat *tper = data;
682 : :
683 : 26 : dev->feat_info.tper = *tper;
684 : 26 : }
685 : :
686 : : /*
687 : : * check single user mode
688 : : */
689 : : static bool
690 : 16 : opal_check_sum(struct spdk_opal_dev *dev, const void *data)
691 : : {
692 : 16 : const struct spdk_opal_d0_single_user_mode_feat *sum = data;
693 : 16 : uint32_t num_locking_objects = from_be32(&sum->num_locking_objects);
694 : :
695 [ - + ]: 16 : if (num_locking_objects == 0) {
696 : 0 : SPDK_NOTICELOG("Need at least one locking object.\n");
697 : 0 : return false;
698 : : }
699 : :
700 : 16 : dev->feat_info.single_user = *sum;
701 : :
702 : 16 : return true;
703 : : }
704 : :
705 : : static void
706 : 26 : opal_check_lock(struct spdk_opal_dev *dev, const void *data)
707 : : {
708 : 26 : const struct spdk_opal_d0_locking_feat *lock = data;
709 : :
710 : 26 : dev->feat_info.locking = *lock;
711 : 26 : }
712 : :
713 : : static void
714 : 26 : opal_check_geometry(struct spdk_opal_dev *dev, const void *data)
715 : : {
716 : 26 : const struct spdk_opal_d0_geo_feat *geo = data;
717 : :
718 : 26 : dev->feat_info.geo = *geo;
719 : 26 : }
720 : :
721 : : static void
722 : 26 : opal_check_datastore(struct spdk_opal_dev *dev, const void *data)
723 : : {
724 : 26 : const struct spdk_opal_d0_datastore_feat *datastore = data;
725 : :
726 : 26 : dev->feat_info.datastore = *datastore;
727 : 26 : }
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 : : }
739 : :
740 : : static uint16_t
741 : 26 : opal_get_comid_v200(struct spdk_opal_dev *dev, const void *data)
742 : : {
743 : 26 : const struct spdk_opal_d0_v200_feat *v200 = data;
744 : 26 : uint16_t base_comid = from_be16(&v200->base_comid);
745 : :
746 : 26 : dev->feat_info.v200 = *v200;
747 : :
748 : 26 : return base_comid;
749 : : }
750 : :
751 : : static int
752 : 26 : opal_discovery0_end(struct spdk_opal_dev *dev, void *payload, uint32_t payload_size)
753 : : {
754 : 26 : bool supported = false, single_user = false;
755 : 26 : const struct spdk_opal_d0_hdr *hdr = (struct spdk_opal_d0_hdr *)payload;
756 : : struct spdk_opal_d0_feat_hdr *feat_hdr;
757 : 26 : const uint8_t *epos = payload, *cpos = payload;
758 : 26 : uint16_t comid = 0;
759 : 26 : uint32_t hlen = from_be32(&(hdr->length));
760 : :
761 [ - + ]: 26 : 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 : 26 : epos += hlen; /* end of buffer */
768 : 26 : cpos += sizeof(*hdr); /* current position on buffer */
769 : :
770 [ + + ]: 198 : while (cpos < epos) {
771 : 172 : feat_hdr = (struct spdk_opal_d0_feat_hdr *)cpos;
772 : 172 : uint16_t feat_code = from_be16(&feat_hdr->code);
773 : :
774 [ + + + + : 172 : switch (feat_code) {
+ - + + ]
775 : 26 : case FEATURECODE_TPER:
776 : 26 : opal_check_tper(dev, cpos);
777 : 26 : break;
778 : 16 : case FEATURECODE_SINGLEUSER:
779 : 16 : single_user = opal_check_sum(dev, cpos);
780 : 16 : break;
781 : 26 : case FEATURECODE_GEOMETRY:
782 : 26 : opal_check_geometry(dev, cpos);
783 : 26 : break;
784 : 26 : case FEATURECODE_LOCKING:
785 : 26 : opal_check_lock(dev, cpos);
786 : 26 : break;
787 : 26 : case FEATURECODE_DATASTORE:
788 : 26 : opal_check_datastore(dev, cpos);
789 : 26 : break;
790 : 0 : case FEATURECODE_OPALV100:
791 : 0 : comid = opal_get_comid_v100(dev, cpos);
792 : 0 : supported = true;
793 : 0 : break;
794 : 26 : case FEATURECODE_OPALV200:
795 : 26 : comid = opal_get_comid_v200(dev, cpos);
796 : 26 : supported = true;
797 : 26 : break;
798 : 26 : default:
799 [ - + - + ]: 26 : SPDK_INFOLOG(opal, "Unknown feature code: %d\n", feat_code);
800 : : }
801 : 172 : cpos += feat_hdr->length + sizeof(*feat_hdr);
802 : : }
803 : :
804 [ - + ]: 26 : if (supported == false) {
805 [ # # # # ]: 0 : SPDK_INFOLOG(opal, "Opal Not Supported.\n");
806 : 0 : return -ENOTSUP;
807 : : }
808 : :
809 [ + + ]: 26 : if (single_user == false) {
810 [ - + - + ]: 10 : SPDK_INFOLOG(opal, "Single User Mode Not Supported\n");
811 : : }
812 : :
813 : 26 : dev->comid = comid;
814 : 26 : return 0;
815 : : }
816 : :
817 : : static int
818 : 26 : 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 : 26 : bool sp_tcg_supported = false;
824 : :
825 : : /* NVMe 1.4 chapter 5.25.2 Security Protocol 00h */
826 : 26 : ret = spdk_nvme_ctrlr_security_receive(dev->ctrlr, SPDK_SCSI_SECP_INFO, 0,
827 : : 0, payload, payload_size);
828 [ - + ]: 26 : if (ret) {
829 : 0 : return ret;
830 : : }
831 : :
832 : : /* spc4r31 chapter 7.7.1.3 Supported security protocols list description */
833 : 26 : sp_list_len = from_be16((uint8_t *)payload + 6);
834 : 26 : sp_list = (uint8_t *)payload + 8;
835 : :
836 [ - + ]: 26 : if (sp_list_len + 8 > (int)payload_size) {
837 : 0 : return -EINVAL;
838 : : }
839 : :
840 [ + - ]: 52 : for (i = 0; i < sp_list_len; i++) {
841 [ + + ]: 52 : if (sp_list[i] == SPDK_SCSI_SECP_TCG) {
842 : 26 : sp_tcg_supported = true;
843 : 26 : break;
844 : : }
845 : : }
846 : :
847 [ - + ]: 26 : if (!sp_tcg_supported) {
848 : 0 : return -ENOTSUP;
849 : : }
850 : :
851 [ - + ]: 26 : memset(payload, 0, payload_size);
852 : 26 : ret = spdk_nvme_ctrlr_security_receive(dev->ctrlr, SPDK_SCSI_SECP_TCG, LV0_DISCOVERY_COMID,
853 : : 0, payload, payload_size);
854 [ - + ]: 26 : if (ret) {
855 : 0 : return ret;
856 : : }
857 : :
858 : 26 : return opal_discovery0_end(dev, payload, payload_size);
859 : : }
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 : : 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 : : }
890 : :
891 : : void
892 : 26 : spdk_opal_dev_destruct(struct spdk_opal_dev *dev)
893 : : {
894 : 26 : free(dev);
895 : 26 : }
896 : :
897 : : static int
898 : 2 : opal_start_session_done(struct opal_session *sess)
899 : : {
900 : : uint32_t hsn, tsn;
901 : 2 : int error = 0;
902 : :
903 : 2 : error = opal_parse_and_check_status(sess);
904 [ + - ]: 2 : if (error) {
905 : 2 : 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 : : }
921 : :
922 : : static int
923 : 2 : 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 : 2 : int err = 0;
932 : : int ret;
933 : :
934 [ - + - - ]: 2 : if (key == NULL && auth != UID_ANYBODY) {
935 : 0 : return OPAL_INVAL_PARAM;
936 : : }
937 : :
938 : 2 : opal_clear_cmd(sess);
939 : :
940 : 2 : opal_set_comid(sess, dev->comid);
941 : 2 : hsn = GENERIC_HOST_SESSION_NUM;
942 : :
943 : 2 : opal_add_token_u8(&err, sess, SPDK_OPAL_CALL);
944 : 2 : opal_add_token_bytestring(&err, sess, spdk_opal_uid[UID_SMUID],
945 : : OPAL_UID_LENGTH);
946 : 2 : opal_add_token_bytestring(&err, sess, spdk_opal_method[STARTSESSION_METHOD],
947 : : OPAL_UID_LENGTH);
948 : 2 : opal_add_token_u8(&err, sess, SPDK_OPAL_STARTLIST);
949 : 2 : opal_add_token_u64(&err, sess, hsn);
950 : 2 : opal_add_token_bytestring(&err, sess, spdk_opal_uid[sp_type], OPAL_UID_LENGTH);
951 : 2 : opal_add_token_u8(&err, sess, SPDK_OPAL_TRUE); /* Write */
952 : :
953 [ - + - ]: 2 : switch (auth) {
954 : 0 : case UID_ANYBODY:
955 : 0 : opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
956 : 0 : break;
957 : 2 : case UID_ADMIN1:
958 : : case UID_SID:
959 : 2 : opal_add_token_u8(&err, sess, SPDK_OPAL_STARTNAME);
960 : 2 : opal_add_token_u8(&err, sess, 0); /* HostChallenge */
961 : 2 : opal_add_token_bytestring(&err, sess, key, key_len);
962 : 2 : opal_add_tokens(&err, sess, 3, /* number of token */
963 : : SPDK_OPAL_ENDNAME,
964 : : SPDK_OPAL_STARTNAME,
965 : : 3);/* HostSignAuth */
966 : 2 : opal_add_token_bytestring(&err, sess, spdk_opal_uid[auth],
967 : : OPAL_UID_LENGTH);
968 : 2 : opal_add_token_u8(&err, sess, SPDK_OPAL_ENDNAME);
969 : 2 : opal_add_token_u8(&err, sess, SPDK_OPAL_ENDLIST);
970 : 2 : break;
971 : 0 : default:
972 : 0 : SPDK_ERRLOG("Cannot start Admin SP session with auth %d\n", auth);
973 : 0 : return -EINVAL;
974 : : }
975 : :
976 [ - + ]: 2 : if (err) {
977 : 0 : SPDK_ERRLOG("Error building start adminsp session command.\n");
978 : 0 : return err;
979 : : }
980 : :
981 : 2 : ret = opal_cmd_finalize(sess, sess->hsn, sess->tsn, true);
982 [ - + ]: 2 : if (ret) {
983 : 0 : return ret;
984 : : }
985 : :
986 : 2 : ret = opal_send_recv(dev, sess);
987 [ - + ]: 2 : if (ret) {
988 : 0 : return ret;
989 : : }
990 : :
991 : 2 : return opal_start_session_done(sess);
992 : : }
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 : : 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 : : }
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 : : 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 : : }
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 : : }
1099 : :
1100 : : static int
1101 : 0 : opal_get_locking_sp_lifecycle_done(struct opal_session *sess)
1102 : : {
1103 : : 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 : : }
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 : : 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 : : }
1164 : :
1165 : : static int
1166 : 0 : opal_activate(struct spdk_opal_dev *dev, struct opal_session *sess)
1167 : : {
1168 : 0 : int err = 0;
1169 : : 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 : : }
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 : : 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 : : } 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 : : }
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 : : uint8_t read_locked, write_locked;
1265 : 0 : int err = 0;
1266 : : 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 : 0 : case OPAL_READONLY:
1275 : 0 : read_locked = 0;
1276 : 0 : write_locked = 1;
1277 : 0 : break;
1278 : 0 : case OPAL_READWRITE:
1279 : 0 : read_locked = 0;
1280 : 0 : write_locked = 0;
1281 : 0 : break;
1282 : 0 : case OPAL_RWLOCK:
1283 : 0 : read_locked = 1;
1284 : 0 : write_locked = 1;
1285 : 0 : break;
1286 : 0 : 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 : : 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 [ # # ]: 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 : : }
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 : : 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 [ # # ]: 0 : if (err) {
1368 : 0 : SPDK_ERRLOG("Error building locking range enable/disable command.\n");
1369 : : }
1370 : 0 : return err;
1371 : : }
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 : : 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 : : read_lock_enabled, write_lock_enabled);
1391 : : } 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 : : }
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 : : }
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 : : 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 : : }
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 : : }
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 : : int ret;
1532 : 0 : uint8_t uid_locking_range[OPAL_UID_LENGTH];
1533 : : 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 : : }
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 : : 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 : : }
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 : : 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 : 0 : case OPAL_READONLY:
1647 : 0 : memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_RDLOCKED], OPAL_UID_LENGTH);
1648 : 0 : break;
1649 : 0 : case OPAL_READWRITE:
1650 : 0 : memcpy(uid_locking_range, spdk_opal_uid[UID_LOCKINGRANGE_ACE_WRLOCKED], OPAL_UID_LENGTH);
1651 : 0 : break;
1652 : 0 : 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 : : }
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 : : 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 : : } 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 : : }
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 : : 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 : : }
1767 : :
1768 : : int
1769 : 0 : spdk_opal_cmd_take_ownership(struct spdk_opal_dev *dev, char *new_passwd)
1770 : : {
1771 : : int ret;
1772 : 0 : struct spdk_opal_key opal_key = {};
1773 : : 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 : : }
1823 : :
1824 : 0 : end:
1825 : 0 : free(sess);
1826 : 0 : return ret;
1827 : : }
1828 : :
1829 : : struct spdk_opal_dev *
1830 : 26 : spdk_opal_dev_construct(struct spdk_nvme_ctrlr *ctrlr)
1831 : : {
1832 : : struct spdk_opal_dev *dev;
1833 : : void *payload;
1834 : :
1835 : 26 : dev = calloc(1, sizeof(*dev));
1836 [ - + ]: 26 : if (!dev) {
1837 : 0 : SPDK_ERRLOG("Memory allocation failed\n");
1838 : 0 : return NULL;
1839 : : }
1840 : :
1841 : 26 : dev->ctrlr = ctrlr;
1842 : :
1843 : 26 : payload = calloc(1, IO_BUFFER_LENGTH);
1844 [ - + ]: 26 : if (!payload) {
1845 : 0 : free(dev);
1846 : 0 : return NULL;
1847 : : }
1848 : :
1849 [ - + ]: 26 : 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 : 26 : free(payload);
1857 : 26 : return dev;
1858 : : }
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 : : }
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 : : int length;
1890 : : 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 : : }
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 : : 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 : : }
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 : : 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 : : }
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 : : 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 : : }
2039 : :
2040 : : int
2041 : 2 : spdk_opal_cmd_revert_tper(struct spdk_opal_dev *dev, const char *passwd)
2042 : : {
2043 : : int ret;
2044 : : struct opal_session *sess;
2045 : 2 : struct spdk_opal_key opal_key = {};
2046 : :
2047 [ - + ]: 2 : assert(dev != NULL);
2048 : :
2049 : 2 : ret = opal_init_key(&opal_key, passwd);
2050 [ - + ]: 2 : if (ret) {
2051 : 0 : SPDK_ERRLOG("Init key failed\n");
2052 : 0 : return ret;
2053 : : }
2054 : :
2055 : 2 : sess = opal_alloc_session(dev);
2056 [ - + ]: 2 : if (!sess) {
2057 : 0 : return -ENOMEM;
2058 : : }
2059 : :
2060 : 2 : ret = opal_start_generic_session(dev, sess, UID_SID, UID_ADMINSP,
2061 : 2 : opal_key.key, opal_key.key_len);
2062 [ + - ]: 2 : if (ret) {
2063 : 2 : SPDK_ERRLOG("Error on starting admin SP session with error %d\n", ret);
2064 : 2 : free(sess);
2065 : 2 : 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 : : }
2087 : : /* No opal_end_session() required here for successful case */
2088 : :
2089 : 0 : end:
2090 : 0 : free(sess);
2091 : 0 : return ret;
2092 : : }
2093 : :
2094 : : int
2095 : 0 : spdk_opal_cmd_activate_locking_sp(struct spdk_opal_dev *dev, const char *passwd)
2096 : : {
2097 : : struct opal_session *sess;
2098 : 0 : struct spdk_opal_key opal_key = {};
2099 : : 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 : : }
2129 : :
2130 : 0 : 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 : : }
2135 : :
2136 : 0 : free(sess);
2137 : 0 : return ret;
2138 : : }
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 : : struct opal_session *sess;
2146 : 0 : struct spdk_opal_key opal_key = {};
2147 : : 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 : : }
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 : : }
2177 : :
2178 : 0 : free(sess);
2179 : 0 : return ret;
2180 : : }
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 : : struct opal_session *sess;
2188 : 0 : struct spdk_opal_key opal_key = {};
2189 : : 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 : : }
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 : : }
2220 : :
2221 : 0 : free(sess);
2222 : 0 : return ret;
2223 : : }
2224 : :
2225 : : int
2226 : 0 : spdk_opal_cmd_get_max_ranges(struct spdk_opal_dev *dev, const char *passwd)
2227 : : {
2228 : : struct opal_session *sess;
2229 : 0 : struct spdk_opal_key opal_key = {};
2230 : : 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 : : }
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 : : }
2264 : :
2265 : 0 : free(sess);
2266 : :
2267 [ # # ]: 0 : return (ret == 0 ? dev->max_ranges : ret);
2268 : : }
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 : : struct opal_session *sess;
2276 : 0 : struct spdk_opal_key opal_key = {};
2277 : : 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 : : }
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 : : }
2307 : :
2308 : 0 : free(sess);
2309 : 0 : return ret;
2310 : : }
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 : : struct opal_session *sess;
2317 : 0 : struct spdk_opal_key opal_key = {};
2318 : : 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 : : }
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 : : }
2349 : :
2350 : 0 : free(sess);
2351 : 0 : return ret;
2352 : : }
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 : : struct opal_session *sess;
2360 : 0 : struct spdk_opal_key opal_key = {};
2361 : : 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 : : }
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 : : }
2392 : :
2393 : 0 : free(sess);
2394 : 0 : return ret;
2395 : : }
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 : : struct opal_session *sess;
2402 : 0 : struct spdk_opal_key old_key = {};
2403 : 0 : struct spdk_opal_key new_key = {};
2404 : : 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 : : }
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 : : }
2440 : :
2441 : 0 : free(sess);
2442 : 0 : return ret;
2443 : : }
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 : : struct opal_session *sess;
2450 : 0 : struct spdk_opal_key opal_key = {};
2451 : : 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 : : }
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 : : }
2481 : :
2482 : 0 : free(sess);
2483 : 0 : return ret;
2484 : : }
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 : : struct opal_session *sess;
2491 : 0 : struct spdk_opal_key opal_key = {};
2492 : : struct spdk_opal_key *active_key;
2493 : : 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 : 0 : 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 : : }
2539 : 0 : free(active_key);
2540 : 0 : free(sess);
2541 : 0 : return ret;
2542 : : }
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 : : 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 : 2512 : SPDK_LOG_REGISTER_COMPONENT(opal)
|