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