1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2011-2012 Planets Communications B.V.
5 Copyright (C) 2013-2018 Bareos GmbH & Co. KG
6
7 This program is Free Software; you can redistribute it and/or
8 modify it under the terms of version three of the GNU Affero General Public
9 License as published by the Free Software Foundation and included
10 in the file LICENSE.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Affero General Public License for more details.
16
17 You should have received a copy of the GNU Affero General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.
21 */
22
23 /*
24 * Low level SCSI interface for SCSI crypto services
25 *
26 * Marco van Wieringen, March 2012
27 */
28
29 #include "include/bareos.h"
30
31 /* Forward referenced functions */
32
33 static void IndentStatusMsg(POOLMEM*& status, const char* msg, int indent);
34
35 #include "lib/scsi_crypto.h"
36
37 #ifdef HAVE_LOWLEVEL_SCSI_INTERFACE
38
39 /*
40 * Store a value as 2 bytes MSB/LSB
41 */
set_2_byte_value(unsigned char * field,int value)42 static inline void set_2_byte_value(unsigned char* field, int value)
43 {
44 field[0] = (unsigned char)((value & 0xff00) >> 8);
45 field[1] = (unsigned char)(value & 0x00ff);
46 }
47
48 /*
49 * Store a value as 4 bytes MSB/LSB
50 */
set_4_byte_value(unsigned char * field,int value)51 static inline void set_4_byte_value(unsigned char* field, int value)
52 {
53 field[0] = (unsigned char)((value & 0xff000000) >> 24);
54 field[1] = (unsigned char)((value & 0x00ff0000) >> 16);
55 field[2] = (unsigned char)((value & 0x0000ff00) >> 8);
56 field[3] = (unsigned char)(value & 0x000000ff);
57 }
58
59 /*
60 * Clear an encryption key used by a tape drive
61 * using a lowlevel SCSI interface.
62 *
63 * The device is send a:
64 * - SPOUT Security Protocol OUT SCSI CDB. (0xB5)
65 * - SPOUT Send Encryption Key Page. (0x10)
66 *
67 * The Send Encryption Key page has the encryption
68 * and decryption set to disabled and the key is empty.
69 */
ClearScsiEncryptionKey(int fd,const char * device_name)70 bool ClearScsiEncryptionKey(int fd, const char* device_name)
71 {
72 /*
73 * Create a SPOUT Set Encryption Key CDB and
74 * a SPOUT Clear Encryption Mode Page
75 */
76 SPP_SCSI_CDB cdb;
77 SPP_PAGE_BUFFER cmd_page;
78 SPP_PAGE_SDE* sps;
79 int cmd_page_len, cdb_len;
80
81 /*
82 * Put a SPOUT Set Data Encryption page into the start of
83 * the generic cmd_page structure.
84 */
85 memset(&cmd_page, 0, sizeof(cmd_page));
86 sps = (SPP_PAGE_SDE*)&cmd_page;
87 set_2_byte_value(sps->pageCode, SPOUT_SET_DATA_ENCRYPTION_PAGE);
88 sps->nexusScope = SPP_NEXUS_SC_ALL_I_T_NEXUS;
89 sps->encryptionMode = SPP_ENCR_MODE_DISABLE;
90 sps->decryptionMode = SPP_DECR_MODE_DISABLE;
91 sps->algorithmIndex = 0x01;
92 sps->kadFormat = SPP_KAD_KEY_FORMAT_NORMAL;
93 set_2_byte_value(sps->keyLength, SPP_KEY_LENGTH);
94
95 /*
96 * Set the length to the size of the SPP_PAGE_SDE we just filled.
97 */
98 cmd_page_len = sizeof(SPP_PAGE_SDE);
99
100 /*
101 * Set the actual size of the cmd_page - 4 into the cmd_page length field
102 * (without the pageCode and pageLength)
103 */
104 set_2_byte_value(cmd_page.length, cmd_page_len - 4);
105
106 /*
107 * Fill the SCSI CDB.
108 */
109 cdb_len = sizeof(cdb);
110 memset(&cdb, 0, cdb_len);
111 cdb.opcode = SCSI_SPOUT_OPCODE;
112 cdb.scp = SPP_SP_PROTOCOL_TDE;
113 set_2_byte_value(cdb.scp_specific, SPOUT_SET_DATA_ENCRYPTION_PAGE);
114 set_4_byte_value(cdb.allocation_length, cmd_page_len);
115
116 /*
117 * Clear the encryption key.
118 */
119 return send_scsi_cmd_page(fd, device_name, (void*)&cdb, cdb_len,
120 (void*)&cmd_page, cmd_page_len);
121 }
122
123 /*
124 * Set an encryption key used by a tape drive
125 * using a lowlevel SCSI interface.
126 *
127 * The device is send a:
128 * - SPOUT Security Protocol OUT SCSI CDB. (0xB5)
129 * - SPOUT Send Encryption Key Page. (0x10)
130 *
131 * The Send Encryption Key page has the encryption
132 * and decryption set to not disabled and the key is filled.
133 */
SetScsiEncryptionKey(int fd,const char * device_name,char * encryption_key)134 bool SetScsiEncryptionKey(int fd, const char* device_name, char* encryption_key)
135 {
136 /*
137 * Create a SPOUT Set Encryption Key CDB and
138 * a SPOUT Send Encryption Key Page
139 */
140 SPP_SCSI_CDB cdb;
141 SPP_PAGE_BUFFER cmd_page;
142 SPP_PAGE_SDE* sps;
143 int cmd_page_len, cdb_len;
144
145 /*
146 * Put a SPOUT Set Data Encryption page into the start of
147 * the generic cmd_page structure.
148 */
149 memset(&cmd_page, 0, sizeof(cmd_page));
150 sps = (SPP_PAGE_SDE*)&cmd_page;
151 set_2_byte_value(sps->pageCode, SPOUT_SET_DATA_ENCRYPTION_PAGE);
152 sps->nexusScope = SPP_NEXUS_SC_ALL_I_T_NEXUS;
153 sps->encryptionMode = SPP_ENCR_MODE_ENCRYPT;
154 sps->decryptionMode = SPP_DECR_MODE_MIXED;
155 sps->algorithmIndex = 0x01;
156 sps->kadFormat = SPP_KAD_KEY_FORMAT_NORMAL;
157 set_2_byte_value(sps->keyLength, SPP_KEY_LENGTH);
158 bstrncpy((char*)sps->keyData, encryption_key, SPP_KEY_LENGTH);
159
160 /*
161 * Set the length to the size of the SPP_PAGE_SDE we just filled.
162 */
163 cmd_page_len = sizeof(SPP_PAGE_SDE);
164
165 /*
166 * Set the actual size of the cmd_page - 4 into the cmd_page length field
167 * (without the pageCode and pageLength)
168 */
169 set_2_byte_value(cmd_page.length, cmd_page_len - 4);
170
171 /*
172 * Fill the SCSI CDB.
173 */
174 cdb_len = sizeof(cdb);
175 memset(&cdb, 0, cdb_len);
176 cdb.opcode = SCSI_SPOUT_OPCODE;
177 cdb.scp = SPP_SP_PROTOCOL_TDE;
178 set_2_byte_value(cdb.scp_specific, SPOUT_SET_DATA_ENCRYPTION_PAGE);
179 set_4_byte_value(cdb.allocation_length, cmd_page_len);
180
181 /*
182 * Set the new encryption key.
183 */
184 return send_scsi_cmd_page(fd, device_name, (void*)&cdb, cdb_len,
185 (void*)&cmd_page, cmd_page_len);
186 }
187
188 /*
189 * Request the encryption state of a drive
190 * using a lowlevel SCSI interface.
191 *
192 * The device is send a:
193 * - SPIN Security Protocol IN SCSI CDB. (0xA2)
194 * - SPIN Get Data Encryption Status page. (0x20)
195 *
196 * The return data is interpreted and a status report is build.
197 */
GetScsiDriveEncryptionStatus(int fd,const char * device_name,POOLMEM * & status,int indent)198 int GetScsiDriveEncryptionStatus(int fd,
199 const char* device_name,
200 POOLMEM*& status,
201 int indent)
202 {
203 SPP_SCSI_CDB cdb;
204 SPP_PAGE_BUFFER cmd_page;
205 SPP_PAGE_DES* spd;
206 int cmd_page_len, cdb_len;
207
208 cmd_page_len = sizeof(cmd_page);
209 memset(&cmd_page, 0, cmd_page_len);
210
211 /*
212 * Fill the SCSI CDB.
213 */
214 cdb_len = sizeof(cdb);
215 memset(&cdb, 0, cdb_len);
216 cdb.opcode = SCSI_SPIN_OPCODE;
217 cdb.scp = SPP_SP_PROTOCOL_TDE;
218 set_2_byte_value(cdb.scp_specific, SPIN_DATA_ENCR_STATUS_PAGE);
219 set_4_byte_value(cdb.allocation_length, cmd_page_len);
220
221 /*
222 * Retrieve the drive encryption status.
223 */
224 if (!RecvScsiCmdPage(fd, device_name, (void*)&cdb, cdb_len, (void*)&cmd_page,
225 cmd_page_len)) {
226 return 0;
227 }
228
229 /*
230 * We got a response which should contain a SPP_PAGE_DES.
231 * Create a pointer to the beginning of the generic
232 * cmd_page structure.
233 */
234 spd = (SPP_PAGE_DES*)&cmd_page;
235
236 PmStrcpy(status, "");
237 IndentStatusMsg(status, _("Drive encryption status:\n"), indent);
238
239 /*
240 * See what encrption mode is enabled.
241 */
242 switch (spd->encryptionMode) {
243 case SPP_ENCR_MODE_DISABLE:
244 IndentStatusMsg(status, _("Encryption Mode: Disabled\n"), indent + 3);
245 break;
246 case SPP_ENCR_MODE_EXTERNAL:
247 IndentStatusMsg(status, _("Encryption Mode: External\n"), indent + 3);
248 break;
249 case SPP_ENCR_MODE_ENCRYPT:
250 IndentStatusMsg(status, _("Encryption Mode: Encrypt\n"), indent + 3);
251 break;
252 default:
253 break;
254 }
255
256 /*
257 * See what decryption mode is enabled.
258 */
259 switch (spd->decryptionMode) {
260 case SPP_DECR_MODE_DISABLE:
261 IndentStatusMsg(status, _("Decryption Mode: Disabled\n"), indent + 3);
262 break;
263 case SPP_DECR_MODE_RAW:
264 IndentStatusMsg(status, _("Decryption Mode: Raw\n"), indent + 3);
265 break;
266 case SPP_DECR_MODE_DECRYPT:
267 IndentStatusMsg(status, _("Decryption Mode: Decrypt\n"), indent + 3);
268 break;
269 case SPP_DECR_MODE_MIXED:
270 IndentStatusMsg(status, _("Decryption Mode: Mixed\n"), indent + 3);
271 break;
272 default:
273 break;
274 }
275
276 /*
277 * See if RDMD is enabled.
278 */
279 if (spd->RDMD) {
280 IndentStatusMsg(status, _("Raw Decryption Mode Disabled (RDMD): Enabled\n"),
281 indent + 3);
282 } else {
283 IndentStatusMsg(status,
284 _("Raw Decryption Mode Disabled (RDMD): Disabled\n"),
285 indent + 3);
286 }
287
288 /*
289 * See what Check External Encryption Mode Status is set.
290 */
291 switch (spd->CEEMS) {
292 case SPP_CEEM_NO_ENCR_CHECK:
293 IndentStatusMsg(status,
294 _("Check External Encryption Mode Status (CEEMS) : No\n"),
295 indent + 3);
296 break;
297 case SPP_CEEM_CHECK_EXTERNAL:
298 IndentStatusMsg(
299 status,
300 _("Check External Encryption Mode Status (CEEMS) : External\n"),
301 indent + 3);
302 break;
303 case SPP_CEEM_CHECK_ENCR:
304 IndentStatusMsg(
305 status,
306 _("Check External Encryption Mode Status (CEEMS) : Encrypt\n"),
307 indent + 3);
308 break;
309 default:
310 break;
311 }
312
313 /*
314 * See if VCELB is enabled.
315 */
316 if (spd->VCELB) {
317 IndentStatusMsg(
318 status,
319 _("Volume Contains Encrypted Logical Blocks (VCELB): Enabled\n"),
320 indent + 3);
321 } else {
322 IndentStatusMsg(
323 status,
324 _("Volume Contains Encrypted Logical Blocks (VCELB): Disabled\n"),
325 indent + 3);
326 }
327
328 /*
329 * See what is providing the encryption keys.
330 */
331 switch (spd->parametersControl) {
332 case SPP_PARM_LOG_BLOCK_ENCR_NONE:
333 IndentStatusMsg(status,
334 _("Logical Block encryption parameters: No report\n"),
335 indent + 3);
336 break;
337 case SPP_PARM_LOG_BLOCK_ENCR_AME:
338 IndentStatusMsg(
339 status,
340 _("Logical Block encryption parameters: Application Managed\n"),
341 indent + 3);
342 break;
343 case SPP_PARM_LOG_BLOCK_ENCR_DRIVE:
344 IndentStatusMsg(status,
345 _("Logical Block encryption parameters: Drive Managed\n"),
346 indent + 3);
347 break;
348 case SPP_PARM_LOG_BLOCK_LME_ADC:
349 IndentStatusMsg(status,
350 _("Logical Block encryption parameters: Library/Key "
351 "Management Appliance Managed\n"),
352 indent + 3);
353 break;
354 case SPP_PARM_LOG_BLOCK_UNSUP:
355 IndentStatusMsg(status,
356 _("Logical Block encryption parameters: Unsupported\n"),
357 indent + 3);
358 break;
359 default:
360 break;
361 }
362
363 /*
364 * Only when both encryption and decryption are disabled skip the KAD Format
365 * field.
366 */
367 if (spd->encryptionMode != SPP_ENCR_MODE_DISABLE
368 && spd->decryptionMode != SPP_DECR_MODE_DISABLE) {
369 switch (spd->kadFormat) {
370 case SPP_KAD_KEY_FORMAT_NORMAL:
371 IndentStatusMsg(status,
372 _("Key Associated Data (KAD) Descriptor: Normal key\n"),
373 indent + 3);
374 break;
375 case SPP_KAD_KEY_FORMAT_REFERENCE:
376 IndentStatusMsg(status,
377 _("Key Associated Data (KAD) Descriptor: "
378 "Vendor-specific reference\n"),
379 indent + 3);
380 break;
381 case SPP_KAD_KEY_FORMAT_WRAPPED:
382 IndentStatusMsg(
383 status,
384 _("Key Associated Data (KAD) Descriptor: Wrapped public key\n"),
385 indent + 3);
386 break;
387 case SPP_KAD_KEY_FORMAT_ESP_SCSI:
388 IndentStatusMsg(
389 status,
390 _("Key Associated Data (KAD) Descriptor: Key using ESP-SCSI\n"),
391 indent + 3);
392 break;
393 default:
394 break;
395 }
396 }
397
398 return strlen(status);
399 }
400
401 /*
402 * Request the encryption state of the next block
403 * using a lowlevel SCSI interface.
404 *
405 * The device is send a:
406 * - SPIN Security Protocol IN SCSI CDB. (0xA2)
407 * - SPIN Get Data Encryption Status page. (0x21)
408 *
409 * The return data is interpreted and a status report is build.
410 */
GetScsiVolumeEncryptionStatus(int fd,const char * device_name,POOLMEM * & status,int indent)411 int GetScsiVolumeEncryptionStatus(int fd,
412 const char* device_name,
413 POOLMEM*& status,
414 int indent)
415 {
416 SPP_SCSI_CDB cdb;
417 SPP_PAGE_BUFFER cmd_page;
418 SPP_PAGE_NBES* spnb;
419 int cmd_page_len, cdb_len;
420
421 cmd_page_len = sizeof(cmd_page);
422 memset(&cmd_page, 0, cmd_page_len);
423
424 /*
425 * Fill the SCSI CDB.
426 */
427 cdb_len = sizeof(cdb);
428 memset(&cdb, 0, cdb_len);
429 cdb.opcode = SCSI_SPIN_OPCODE;
430 cdb.scp = SPP_SP_PROTOCOL_TDE;
431 set_2_byte_value(cdb.scp_specific, SPIN_NEXT_BLOCK_ENCR_STATUS_PAGE);
432 set_4_byte_value(cdb.allocation_length, cmd_page_len);
433
434 /*
435 * Retrieve the volume encryption status.
436 */
437 if (!RecvScsiCmdPage(fd, device_name, (void*)&cdb, cdb_len, (void*)&cmd_page,
438 cmd_page_len)) {
439 return 0;
440 }
441
442 /*
443 * We got a response which should contain a SPP_PAGE_NBES.
444 * Create a pointer to the beginning of the generic
445 * cmd_page structure.
446 */
447 spnb = (SPP_PAGE_NBES*)&cmd_page;
448
449 PmStrcpy(status, "");
450 IndentStatusMsg(status, _("Volume encryption status:\n"), indent);
451
452 switch (spnb->compressionStatus) {
453 case SPP_COMP_STATUS_UNKNOWN:
454 IndentStatusMsg(status, _("Compression Status: Unknown\n"), indent + 3);
455 break;
456 case SPP_COMP_STATUS_UNAVAIL:
457 IndentStatusMsg(status, _("Compression Status: Unavailable\n"),
458 indent + 3);
459 break;
460 case SPP_COMP_STATUS_ILLEGAL:
461 IndentStatusMsg(status, _("Compression Status: Illegal logical block\n"),
462 indent + 3);
463 break;
464 case SPP_COMP_STATUS_UNCOMPRESSED:
465 IndentStatusMsg(status, _("Compression Status: Compression Disabled\n"),
466 indent + 3);
467 break;
468 case SPP_COMP_STATUS_COMPRESSED:
469 IndentStatusMsg(status, _("Compression Status: Compression Enabled\n"),
470 indent + 3);
471 break;
472 default:
473 break;
474 }
475
476 switch (spnb->encryptionStatus) {
477 case SPP_ENCR_STATUS_UNKNOWN:
478 IndentStatusMsg(status, _("Encryption Status: Unknown\n"), indent + 3);
479 break;
480 case SPP_ENCR_STATUS_UNAVAIL:
481 IndentStatusMsg(status, _("Encryption Status: Unavailable\n"),
482 indent + 3);
483 break;
484 case SPP_ENCR_STATUS_ILLEGAL:
485 IndentStatusMsg(status, _("Encryption Status: Illegal logical block\n"),
486 indent + 3);
487 break;
488 case SPP_ENCR_STATUS_NOT_ENCRYPTED:
489 IndentStatusMsg(status, _("Encryption Status: Encryption Disabled\n"),
490 indent + 3);
491 break;
492 case SPP_ENCR_STATUS_ENCR_ALG_NOT_SUPP:
493 IndentStatusMsg(status,
494 _("Encryption Status: Encryption Enabled but with non "
495 "supported algorithm\n"),
496 indent + 3);
497 break;
498 case SPP_ENCR_STATUS_ENCRYPTED:
499 IndentStatusMsg(status, _("Encryption Status: Encryption Enabled\n"),
500 indent + 3);
501 break;
502 case SPP_ENCR_STATUS_ENCR_NOT_AVAIL:
503 IndentStatusMsg(status,
504 _("Encryption Status: Encryption Enabled but no valid "
505 "key available for decryption\n"),
506 indent + 3);
507 break;
508 default:
509 break;
510 }
511
512 if (spnb->RDMDS) {
513 IndentStatusMsg(status,
514 _("Raw Decryption Mode Disabled Status (RDMDS): Enabled\n"),
515 indent + 3);
516 } else {
517 IndentStatusMsg(
518 status, _("Raw Decryption Mode Disabled Status (RDMDS): Disabled\n"),
519 indent + 3);
520 }
521
522 if (spnb->EMES) {
523 IndentStatusMsg(status,
524 _("Encryption Mode External Status (EMES): Enabled\n"),
525 indent + 3);
526 } else {
527 IndentStatusMsg(status,
528 _("Encryption Mode External Status (EMES): Disabled\n"),
529 indent + 3);
530 }
531
532 /*
533 * Only when the encryption status is set to SPP_ENCR_STATUS_ENCRYPTED we
534 * can use the nextBlockKADFormat otherwise that value is bogus.
535 */
536 if (spnb->encryptionStatus == SPP_ENCR_STATUS_ENCRYPTED) {
537 switch (spnb->nextBlockKADFormat) {
538 case SPP_KAD_KEY_FORMAT_NORMAL:
539 IndentStatusMsg(
540 status,
541 _("Next Block Key Associated Data (KAD) Descriptor: Normal key\n"),
542 indent + 3);
543 break;
544 case SPP_KAD_KEY_FORMAT_REFERENCE:
545 IndentStatusMsg(status,
546 _("Next Block Key Associated Data (KAD) Descriptor: "
547 "Vendor-specific reference\n"),
548 indent + 3);
549 break;
550 case SPP_KAD_KEY_FORMAT_WRAPPED:
551 IndentStatusMsg(status,
552 _("Next Block Key Associated Data (KAD) Descriptor: "
553 "Wrapped public key\n"),
554 indent + 3);
555 break;
556 case SPP_KAD_KEY_FORMAT_ESP_SCSI:
557 IndentStatusMsg(status,
558 _("Next Block Key Associated Data (KAD) Descriptor: "
559 "Key using ESP-SCSI\n"),
560 indent + 3);
561 break;
562 default:
563 break;
564 }
565 }
566
567 return strlen(status);
568 }
569
570 /*
571 * See if we need a decryption key to read the next block
572 * using a lowlevel SCSI interface.
573 *
574 * The device is send a:
575 * - SPIN Security Protocol IN SCSI CDB. (0xA2)
576 * - SPIN Get Data Encryption Status page. (0x21)
577 */
NeedScsiCryptoKey(int fd,const char * device_name,bool use_drive_status)578 bool NeedScsiCryptoKey(int fd, const char* device_name, bool use_drive_status)
579 {
580 SPP_SCSI_CDB cdb;
581 SPP_PAGE_BUFFER cmd_page;
582 SPP_PAGE_DES* spd;
583 SPP_PAGE_NBES* spnb;
584 int cmd_page_len, cdb_len;
585
586 cmd_page_len = sizeof(cmd_page);
587 memset(&cmd_page, 0, cmd_page_len);
588
589 /*
590 * Fill the SCSI CDB.
591 */
592 cdb_len = sizeof(cdb);
593 memset(&cdb, 0, cdb_len);
594 cdb.opcode = SCSI_SPIN_OPCODE;
595 cdb.scp = SPP_SP_PROTOCOL_TDE;
596 if (use_drive_status) {
597 set_2_byte_value(cdb.scp_specific, SPIN_DATA_ENCR_STATUS_PAGE);
598 } else {
599 set_2_byte_value(cdb.scp_specific, SPIN_NEXT_BLOCK_ENCR_STATUS_PAGE);
600 }
601 set_4_byte_value(cdb.allocation_length, cmd_page_len);
602
603 /*
604 * Retrieve the volume encryption status.
605 */
606 if (!RecvScsiCmdPage(fd, device_name, (void*)&cdb, cdb_len, (void*)&cmd_page,
607 cmd_page_len)) {
608 return false;
609 }
610
611 if (use_drive_status) {
612 /*
613 * We got a response which should contain a SPP_PAGE_DES.
614 * Create a pointer to the beginning of the generic
615 * cmd_page structure.
616 */
617 spd = (SPP_PAGE_DES*)&cmd_page;
618
619 /*
620 * Return the status of the Volume Contains Encrypted Logical Blocks (VCELB)
621 * field.
622 */
623 return (spd->VCELB) ? true : false;
624 } else {
625 /*
626 * We got a response which should contain a SPP_PAGE_NBES.
627 * Create a pointer to the beginning of the generic
628 * cmd_page structure.
629 */
630 spnb = (SPP_PAGE_NBES*)&cmd_page;
631
632 /*
633 * If the encryptionStatus is set to encrypted or encrypted but valid key
634 * not available we know we need to load a key to decrypt the data.
635 */
636 switch (spnb->encryptionStatus) {
637 case SPP_ENCR_STATUS_ENCRYPTED:
638 case SPP_ENCR_STATUS_ENCR_NOT_AVAIL:
639 return true;
640 default:
641 break;
642 }
643 }
644
645 return false;
646 }
647
648 /*
649 * See if encryption is enabled on a device using a lowlevel SCSI interface.
650 *
651 * The device is send a:
652 * - SPIN Security Protocol IN SCSI CDB. (0xA2)
653 * - SPIN Get Data Encryption Status page. (0x20)
654 */
IsScsiEncryptionEnabled(int fd,const char * device_name)655 bool IsScsiEncryptionEnabled(int fd, const char* device_name)
656 {
657 SPP_SCSI_CDB cdb;
658 SPP_PAGE_BUFFER cmd_page;
659 SPP_PAGE_DES* spd;
660 int cmd_page_len, cdb_len;
661
662 cmd_page_len = sizeof(cmd_page);
663 memset(&cmd_page, 0, cmd_page_len);
664
665 /*
666 * Fill the SCSI CDB.
667 */
668 cdb_len = sizeof(cdb);
669 memset(&cdb, 0, cdb_len);
670 cdb.opcode = SCSI_SPIN_OPCODE;
671 cdb.scp = SPP_SP_PROTOCOL_TDE;
672 set_2_byte_value(cdb.scp_specific, SPIN_DATA_ENCR_STATUS_PAGE);
673 set_4_byte_value(cdb.allocation_length, cmd_page_len);
674
675 /*
676 * Retrieve the drive encryption status.
677 */
678 if (!RecvScsiCmdPage(fd, device_name, (void*)&cdb, cdb_len, (void*)&cmd_page,
679 cmd_page_len)) {
680 return false;
681 }
682
683 /*
684 * We got a response which should contain a SPP_PAGE_DES.
685 * Create a pointer to the beginning of the generic
686 * cmd_page structure.
687 */
688 spd = (SPP_PAGE_DES*)&cmd_page;
689
690 /*
691 * When either encryptionMode or decryptionMode are not disabled we return
692 * true
693 */
694 return (spd->encryptionMode != SPP_ENCR_MODE_DISABLE)
695 || (spd->decryptionMode != SPP_DECR_MODE_DISABLE);
696 }
697
698 #else
699
ClearScsiEncryptionKey(int fd,const char * device_name)700 bool ClearScsiEncryptionKey(int fd, const char* device_name) { return false; }
701
SetScsiEncryptionKey(int fd,const char * device_name,char * encryption_key)702 bool SetScsiEncryptionKey(int fd, const char* device_name, char* encryption_key)
703 {
704 return false;
705 }
706
GetScsiDriveEncryptionStatus(int fd,const char * device_name,POOLMEM * & status,int indent)707 int GetScsiDriveEncryptionStatus(int fd,
708 const char* device_name,
709 POOLMEM*& status,
710 int indent)
711 {
712 PmStrcpy(status, "");
713 IndentStatusMsg(status, _("Drive encryption status: Unknown\n"), indent);
714 return strlen(status);
715 }
716
GetScsiVolumeEncryptionStatus(int fd,const char * device_name,POOLMEM * & status,int indent)717 int GetScsiVolumeEncryptionStatus(int fd,
718 const char* device_name,
719 POOLMEM*& status,
720 int indent)
721 {
722 PmStrcpy(status, "");
723 IndentStatusMsg(status, _("Volume encryption status: Unknown\n"), indent);
724 return strlen(status);
725 }
726
NeedScsiCryptoKey(int fd,const char * device_name,bool use_drive_status)727 bool NeedScsiCryptoKey(int fd, const char* device_name, bool use_drive_status)
728 {
729 return false;
730 }
731
GetScsiEncryptionEnabled(int fd,const char * device_name)732 bool GetScsiEncryptionEnabled(int fd, const char* device_name) { return false; }
733 #endif /* HAVE_LOWLEVEL_SCSI_INTERFACE */
734
IndentStatusMsg(POOLMEM * & status,const char * msg,int indent)735 static void IndentStatusMsg(POOLMEM*& status, const char* msg, int indent)
736 {
737 int cnt;
738 char indent_level[17];
739
740 /*
741 * See if we need to indent the line.
742 */
743 if (indent > 0) {
744 for (cnt = 0; cnt < indent && cnt < 16; cnt++) { indent_level[cnt] = ' '; }
745 indent_level[cnt] = '\0';
746 PmStrcat(status, indent_level);
747 }
748
749 PmStrcat(status, msg);
750 }
751