1 /*
2 BAREOS® - Backup Archiving REcovery Open Sourced
3
4 Copyright (C) 2011-2012 Planets Communications B.V.
5 Copyright (C) 2013-2013 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,
120 (void *)&cdb, cdb_len,
121 (void *)&cmd_page, cmd_page_len);
122 }
123
124 /*
125 * Set an encryption key used by a tape drive
126 * using a lowlevel SCSI interface.
127 *
128 * The device is send a:
129 * - SPOUT Security Protocol OUT SCSI CDB. (0xB5)
130 * - SPOUT Send Encryption Key Page. (0x10)
131 *
132 * The Send Encryption Key page has the encryption
133 * and decryption set to not disabled and the key is filled.
134 */
SetScsiEncryptionKey(int fd,const char * device_name,char * encryption_key)135 bool SetScsiEncryptionKey(int fd, const char *device_name, char *encryption_key)
136 {
137 /*
138 * Create a SPOUT Set Encryption Key CDB and
139 * a SPOUT Send Encryption Key Page
140 */
141 SPP_SCSI_CDB cdb;
142 SPP_PAGE_BUFFER cmd_page;
143 SPP_PAGE_SDE *sps;
144 int cmd_page_len, cdb_len;
145
146 /*
147 * Put a SPOUT Set Data Encryption page into the start of
148 * the generic cmd_page structure.
149 */
150 memset(&cmd_page, 0, sizeof(cmd_page));
151 sps = (SPP_PAGE_SDE *)&cmd_page;
152 set_2_byte_value(sps->pageCode, SPOUT_SET_DATA_ENCRYPTION_PAGE);
153 sps->nexusScope = SPP_NEXUS_SC_ALL_I_T_NEXUS;
154 sps->encryptionMode = SPP_ENCR_MODE_ENCRYPT;
155 sps->decryptionMode = SPP_DECR_MODE_MIXED;
156 sps->algorithmIndex = 0x01;
157 sps->kadFormat = SPP_KAD_KEY_FORMAT_NORMAL;
158 set_2_byte_value(sps->keyLength, SPP_KEY_LENGTH);
159 bstrncpy((char *)sps->keyData, encryption_key, SPP_KEY_LENGTH);
160
161 /*
162 * Set the length to the size of the SPP_PAGE_SDE we just filled.
163 */
164 cmd_page_len = sizeof(SPP_PAGE_SDE);
165
166 /*
167 * Set the actual size of the cmd_page - 4 into the cmd_page length field
168 * (without the pageCode and pageLength)
169 */
170 set_2_byte_value(cmd_page.length, cmd_page_len - 4);
171
172 /*
173 * Fill the SCSI CDB.
174 */
175 cdb_len = sizeof(cdb);
176 memset(&cdb, 0, cdb_len);
177 cdb.opcode = SCSI_SPOUT_OPCODE;
178 cdb.scp = SPP_SP_PROTOCOL_TDE;
179 set_2_byte_value(cdb.scp_specific, SPOUT_SET_DATA_ENCRYPTION_PAGE);
180 set_4_byte_value(cdb.allocation_length, cmd_page_len);
181
182 /*
183 * Set the new encryption key.
184 */
185 return send_scsi_cmd_page(fd, device_name,
186 (void *)&cdb, cdb_len,
187 (void *)&cmd_page, cmd_page_len);
188 }
189
190 /*
191 * Request the encryption state of a drive
192 * using a lowlevel SCSI interface.
193 *
194 * The device is send a:
195 * - SPIN Security Protocol IN SCSI CDB. (0xA2)
196 * - SPIN Get Data Encryption Status page. (0x20)
197 *
198 * The return data is interpreted and a status report is build.
199 */
GetScsiDriveEncryptionStatus(int fd,const char * device_name,POOLMEM * & status,int indent)200 int GetScsiDriveEncryptionStatus(int fd, const char *device_name,
201 POOLMEM *&status, 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,
225 (void *)&cdb, cdb_len,
226 (void *)&cmd_page, cmd_page_len)) {
227 return 0;
228 }
229
230 /*
231 * We got a response which should contain a SPP_PAGE_DES.
232 * Create a pointer to the beginning of the generic
233 * cmd_page structure.
234 */
235 spd = (SPP_PAGE_DES *)&cmd_page;
236
237 PmStrcpy(status, "");
238 IndentStatusMsg(status, _("Drive encryption status:\n"), indent);
239
240 /*
241 * See what encrption mode is enabled.
242 */
243 switch (spd->encryptionMode) {
244 case SPP_ENCR_MODE_DISABLE:
245 IndentStatusMsg(status,
246 _("Encryption Mode: Disabled\n"),
247 indent + 3);
248 break;
249 case SPP_ENCR_MODE_EXTERNAL:
250 IndentStatusMsg(status,
251 _("Encryption Mode: External\n"),
252 indent + 3);
253 break;
254 case SPP_ENCR_MODE_ENCRYPT:
255 IndentStatusMsg(status,
256 _("Encryption Mode: Encrypt\n"),
257 indent + 3);
258 break;
259 default:
260 break;
261 }
262
263 /*
264 * See what decryption mode is enabled.
265 */
266 switch (spd->decryptionMode) {
267 case SPP_DECR_MODE_DISABLE:
268 IndentStatusMsg(status,
269 _("Decryption Mode: Disabled\n"),
270 indent + 3);
271 break;
272 case SPP_DECR_MODE_RAW:
273 IndentStatusMsg(status,
274 _("Decryption Mode: Raw\n"),
275 indent + 3);
276 break;
277 case SPP_DECR_MODE_DECRYPT:
278 IndentStatusMsg(status,
279 _("Decryption Mode: Decrypt\n"),
280 indent + 3);
281 break;
282 case SPP_DECR_MODE_MIXED:
283 IndentStatusMsg(status,
284 _("Decryption Mode: Mixed\n"),
285 indent + 3);
286 break;
287 default:
288 break;
289 }
290
291 /*
292 * See if RDMD is enabled.
293 */
294 if (spd->RDMD) {
295 IndentStatusMsg(status,
296 _("Raw Decryption Mode Disabled (RDMD): Enabled\n"),
297 indent + 3);
298 } else {
299 IndentStatusMsg(status,
300 _("Raw Decryption Mode Disabled (RDMD): Disabled\n"),
301 indent + 3);
302 }
303
304 /*
305 * See what Check External Encryption Mode Status is set.
306 */
307 switch (spd->CEEMS) {
308 case SPP_CEEM_NO_ENCR_CHECK:
309 IndentStatusMsg(status,
310 _("Check External Encryption Mode Status (CEEMS) : No\n"),
311 indent + 3);
312 break;
313 case SPP_CEEM_CHECK_EXTERNAL:
314 IndentStatusMsg(status,
315 _("Check External Encryption Mode Status (CEEMS) : External\n"),
316 indent + 3);
317 break;
318 case SPP_CEEM_CHECK_ENCR:
319 IndentStatusMsg(status,
320 _("Check External Encryption Mode Status (CEEMS) : Encrypt\n"),
321 indent + 3);
322 break;
323 default:
324 break;
325 }
326
327 /*
328 * See if VCELB is enabled.
329 */
330 if (spd->VCELB) {
331 IndentStatusMsg(status,
332 _("Volume Contains Encrypted Logical Blocks (VCELB): Enabled\n"),
333 indent + 3);
334 } else {
335 IndentStatusMsg(status,
336 _("Volume Contains Encrypted Logical Blocks (VCELB): Disabled\n"),
337 indent + 3);
338 }
339
340 /*
341 * See what is providing the encryption keys.
342 */
343 switch (spd->parametersControl) {
344 case SPP_PARM_LOG_BLOCK_ENCR_NONE:
345 IndentStatusMsg(status,
346 _("Logical Block encryption parameters: No report\n"),
347 indent + 3);
348 break;
349 case SPP_PARM_LOG_BLOCK_ENCR_AME:
350 IndentStatusMsg(status,
351 _("Logical Block encryption parameters: Application Managed\n"),
352 indent + 3);
353 break;
354 case SPP_PARM_LOG_BLOCK_ENCR_DRIVE:
355 IndentStatusMsg(status,
356 _("Logical Block encryption parameters: Drive Managed\n"),
357 indent + 3);
358 break;
359 case SPP_PARM_LOG_BLOCK_LME_ADC:
360 IndentStatusMsg(status,
361 _("Logical Block encryption parameters: Library/Key Management Appliance Managed\n"),
362 indent + 3);
363 break;
364 case SPP_PARM_LOG_BLOCK_UNSUP:
365 IndentStatusMsg(status,
366 _("Logical Block encryption parameters: Unsupported\n"),
367 indent + 3);
368 break;
369 default:
370 break;
371 }
372
373 /*
374 * Only when both encryption and decryption are disabled skip the KAD Format field.
375 */
376 if (spd->encryptionMode != SPP_ENCR_MODE_DISABLE &&
377 spd->decryptionMode != SPP_DECR_MODE_DISABLE) {
378 switch (spd->kadFormat) {
379 case SPP_KAD_KEY_FORMAT_NORMAL:
380 IndentStatusMsg(status,
381 _("Key Associated Data (KAD) Descriptor: Normal key\n"),
382 indent + 3);
383 break;
384 case SPP_KAD_KEY_FORMAT_REFERENCE:
385 IndentStatusMsg(status,
386 _("Key Associated Data (KAD) Descriptor: Vendor-specific reference\n"),
387 indent + 3);
388 break;
389 case SPP_KAD_KEY_FORMAT_WRAPPED:
390 IndentStatusMsg(status,
391 _("Key Associated Data (KAD) Descriptor: Wrapped public key\n"),
392 indent + 3);
393 break;
394 case SPP_KAD_KEY_FORMAT_ESP_SCSI:
395 IndentStatusMsg(status,
396 _("Key Associated Data (KAD) Descriptor: Key using ESP-SCSI\n"),
397 indent + 3);
398 break;
399 default:
400 break;
401 }
402 }
403
404 return strlen(status);
405 }
406
407 /*
408 * Request the encryption state of the next block
409 * using a lowlevel SCSI interface.
410 *
411 * The device is send a:
412 * - SPIN Security Protocol IN SCSI CDB. (0xA2)
413 * - SPIN Get Data Encryption Status page. (0x21)
414 *
415 * The return data is interpreted and a status report is build.
416 */
GetScsiVolumeEncryptionStatus(int fd,const char * device_name,POOLMEM * & status,int indent)417 int GetScsiVolumeEncryptionStatus(int fd, const char *device_name,
418 POOLMEM *&status, int indent)
419 {
420 SPP_SCSI_CDB cdb;
421 SPP_PAGE_BUFFER cmd_page;
422 SPP_PAGE_NBES *spnb;
423 int cmd_page_len, cdb_len;
424
425 cmd_page_len = sizeof(cmd_page);
426 memset(&cmd_page, 0, cmd_page_len);
427
428 /*
429 * Fill the SCSI CDB.
430 */
431 cdb_len = sizeof(cdb);
432 memset(&cdb, 0, cdb_len);
433 cdb.opcode = SCSI_SPIN_OPCODE;
434 cdb.scp = SPP_SP_PROTOCOL_TDE;
435 set_2_byte_value(cdb.scp_specific, SPIN_NEXT_BLOCK_ENCR_STATUS_PAGE);
436 set_4_byte_value(cdb.allocation_length, cmd_page_len);
437
438 /*
439 * Retrieve the volume encryption status.
440 */
441 if (!RecvScsiCmdPage(fd, device_name,
442 (void *)&cdb, cdb_len,
443 (void *)&cmd_page, cmd_page_len)) {
444 return 0;
445 }
446
447 /*
448 * We got a response which should contain a SPP_PAGE_NBES.
449 * Create a pointer to the beginning of the generic
450 * cmd_page structure.
451 */
452 spnb = (SPP_PAGE_NBES *)&cmd_page;
453
454 PmStrcpy(status, "");
455 IndentStatusMsg(status, _("Volume encryption status:\n"), indent);
456
457 switch (spnb->compressionStatus) {
458 case SPP_COMP_STATUS_UNKNOWN:
459 IndentStatusMsg(status,
460 _("Compression Status: Unknown\n"),
461 indent + 3);
462 break;
463 case SPP_COMP_STATUS_UNAVAIL:
464 IndentStatusMsg(status,
465 _("Compression Status: Unavailable\n"),
466 indent + 3);
467 break;
468 case SPP_COMP_STATUS_ILLEGAL:
469 IndentStatusMsg(status,
470 _("Compression Status: Illegal logical block\n"),
471 indent + 3);
472 break;
473 case SPP_COMP_STATUS_UNCOMPRESSED:
474 IndentStatusMsg(status,
475 _("Compression Status: Compression Disabled\n"),
476 indent + 3);
477 break;
478 case SPP_COMP_STATUS_COMPRESSED:
479 IndentStatusMsg(status,
480 _("Compression Status: Compression Enabled\n"),
481 indent + 3);
482 break;
483 default:
484 break;
485 }
486
487 switch (spnb->encryptionStatus) {
488 case SPP_ENCR_STATUS_UNKNOWN:
489 IndentStatusMsg(status,
490 _("Encryption Status: Unknown\n"),
491 indent + 3);
492 break;
493 case SPP_ENCR_STATUS_UNAVAIL:
494 IndentStatusMsg(status,
495 _("Encryption Status: Unavailable\n"),
496 indent + 3);
497 break;
498 case SPP_ENCR_STATUS_ILLEGAL:
499 IndentStatusMsg(status,
500 _("Encryption Status: Illegal logical block\n"),
501 indent + 3);
502 break;
503 case SPP_ENCR_STATUS_NOT_ENCRYPTED:
504 IndentStatusMsg(status,
505 _("Encryption Status: Encryption Disabled\n"),
506 indent + 3);
507 break;
508 case SPP_ENCR_STATUS_ENCR_ALG_NOT_SUPP:
509 IndentStatusMsg(status,
510 _("Encryption Status: Encryption Enabled but with non supported algorithm\n"),
511 indent + 3);
512 break;
513 case SPP_ENCR_STATUS_ENCRYPTED:
514 IndentStatusMsg(status,
515 _("Encryption Status: Encryption Enabled\n"),
516 indent + 3);
517 break;
518 case SPP_ENCR_STATUS_ENCR_NOT_AVAIL:
519 IndentStatusMsg(status,
520 _("Encryption Status: Encryption Enabled but no valid key available for decryption\n"),
521 indent + 3);
522 break;
523 default:
524 break;
525 }
526
527 if (spnb->RDMDS) {
528 IndentStatusMsg(status,
529 _("Raw Decryption Mode Disabled Status (RDMDS): Enabled\n"),
530 indent + 3);
531 } else {
532 IndentStatusMsg(status,
533 _("Raw Decryption Mode Disabled Status (RDMDS): Disabled\n"),
534 indent + 3);
535 }
536
537 if (spnb->EMES) {
538 IndentStatusMsg(status,
539 _("Encryption Mode External Status (EMES): Enabled\n"),
540 indent + 3);
541 } else {
542 IndentStatusMsg(status,
543 _("Encryption Mode External Status (EMES): Disabled\n"),
544 indent + 3);
545 }
546
547 /*
548 * Only when the encryption status is set to SPP_ENCR_STATUS_ENCRYPTED we
549 * can use the nextBlockKADFormat otherwise that value is bogus.
550 */
551 if (spnb->encryptionStatus == SPP_ENCR_STATUS_ENCRYPTED) {
552 switch (spnb->nextBlockKADFormat) {
553 case SPP_KAD_KEY_FORMAT_NORMAL:
554 IndentStatusMsg(status,
555 _("Next Block Key Associated Data (KAD) Descriptor: Normal key\n"),
556 indent + 3);
557 break;
558 case SPP_KAD_KEY_FORMAT_REFERENCE:
559 IndentStatusMsg(status,
560 _("Next Block Key Associated Data (KAD) Descriptor: Vendor-specific reference\n"),
561 indent + 3);
562 break;
563 case SPP_KAD_KEY_FORMAT_WRAPPED:
564 IndentStatusMsg(status,
565 _("Next Block Key Associated Data (KAD) Descriptor: Wrapped public key\n"),
566 indent + 3);
567 break;
568 case SPP_KAD_KEY_FORMAT_ESP_SCSI:
569 IndentStatusMsg(status,
570 _("Next Block Key Associated Data (KAD) Descriptor: Key using ESP-SCSI\n"),
571 indent + 3);
572 break;
573 default:
574 break;
575 }
576 }
577
578 return strlen(status);
579 }
580
581 /*
582 * See if we need a decryption key to read the next block
583 * using a lowlevel SCSI interface.
584 *
585 * The device is send a:
586 * - SPIN Security Protocol IN SCSI CDB. (0xA2)
587 * - SPIN Get Data Encryption Status page. (0x21)
588 */
NeedScsiCryptoKey(int fd,const char * device_name,bool use_drive_status)589 bool NeedScsiCryptoKey(int fd, const char *device_name, bool use_drive_status)
590 {
591 SPP_SCSI_CDB cdb;
592 SPP_PAGE_BUFFER cmd_page;
593 SPP_PAGE_DES *spd;
594 SPP_PAGE_NBES *spnb;
595 int cmd_page_len, cdb_len;
596
597 cmd_page_len = sizeof(cmd_page);
598 memset(&cmd_page, 0, cmd_page_len);
599
600 /*
601 * Fill the SCSI CDB.
602 */
603 cdb_len = sizeof(cdb);
604 memset(&cdb, 0, cdb_len);
605 cdb.opcode = SCSI_SPIN_OPCODE;
606 cdb.scp = SPP_SP_PROTOCOL_TDE;
607 if (use_drive_status) {
608 set_2_byte_value(cdb.scp_specific, SPIN_DATA_ENCR_STATUS_PAGE);
609 } else {
610 set_2_byte_value(cdb.scp_specific, SPIN_NEXT_BLOCK_ENCR_STATUS_PAGE);
611 }
612 set_4_byte_value(cdb.allocation_length, cmd_page_len);
613
614 /*
615 * Retrieve the volume encryption status.
616 */
617 if (!RecvScsiCmdPage(fd, device_name,
618 (void *)&cdb, cdb_len,
619 (void *)&cmd_page, cmd_page_len)) {
620 return false;
621 }
622
623 if (use_drive_status) {
624 /*
625 * We got a response which should contain a SPP_PAGE_DES.
626 * Create a pointer to the beginning of the generic
627 * cmd_page structure.
628 */
629 spd = (SPP_PAGE_DES *)&cmd_page;
630
631 /*
632 * Return the status of the Volume Contains Encrypted Logical Blocks (VCELB) field.
633 */
634 return (spd->VCELB) ? true : false;
635 } else {
636 /*
637 * We got a response which should contain a SPP_PAGE_NBES.
638 * Create a pointer to the beginning of the generic
639 * cmd_page structure.
640 */
641 spnb = (SPP_PAGE_NBES *)&cmd_page;
642
643 /*
644 * If the encryptionStatus is set to encrypted or encrypted but valid key not available
645 * we know we need to load a key to decrypt the data.
646 */
647 switch (spnb->encryptionStatus) {
648 case SPP_ENCR_STATUS_ENCRYPTED:
649 case SPP_ENCR_STATUS_ENCR_NOT_AVAIL:
650 return true;
651 default:
652 break;
653 }
654 }
655
656 return false;
657 }
658
659 /*
660 * See if encryption is enabled on a device using a lowlevel SCSI interface.
661 *
662 * The device is send a:
663 * - SPIN Security Protocol IN SCSI CDB. (0xA2)
664 * - SPIN Get Data Encryption Status page. (0x20)
665 */
IsScsiEncryptionEnabled(int fd,const char * device_name)666 bool IsScsiEncryptionEnabled(int fd, const char *device_name)
667 {
668 SPP_SCSI_CDB cdb;
669 SPP_PAGE_BUFFER cmd_page;
670 SPP_PAGE_DES *spd;
671 int cmd_page_len, cdb_len;
672
673 cmd_page_len = sizeof(cmd_page);
674 memset(&cmd_page, 0, cmd_page_len);
675
676 /*
677 * Fill the SCSI CDB.
678 */
679 cdb_len = sizeof(cdb);
680 memset(&cdb, 0, cdb_len);
681 cdb.opcode = SCSI_SPIN_OPCODE;
682 cdb.scp = SPP_SP_PROTOCOL_TDE;
683 set_2_byte_value(cdb.scp_specific, SPIN_DATA_ENCR_STATUS_PAGE);
684 set_4_byte_value(cdb.allocation_length, cmd_page_len);
685
686 /*
687 * Retrieve the drive encryption status.
688 */
689 if (!RecvScsiCmdPage(fd, device_name,
690 (void *)&cdb, cdb_len,
691 (void *)&cmd_page, cmd_page_len)) {
692 return false;
693 }
694
695 /*
696 * We got a response which should contain a SPP_PAGE_DES.
697 * Create a pointer to the beginning of the generic
698 * cmd_page structure.
699 */
700 spd = (SPP_PAGE_DES *)&cmd_page;
701
702 /*
703 * When either encryptionMode or decryptionMode are not disabled we return true
704 */
705 return (spd->encryptionMode != SPP_ENCR_MODE_DISABLE) ||
706 (spd->decryptionMode != SPP_DECR_MODE_DISABLE);
707 }
708
709 #else
710
ClearScsiEncryptionKey(int fd,const char * device_name)711 bool ClearScsiEncryptionKey(int fd, const char *device_name)
712 {
713 return false;
714 }
715
SetScsiEncryptionKey(int fd,const char * device_name,char * encryption_key)716 bool SetScsiEncryptionKey(int fd, const char *device_name, char *encryption_key)
717 {
718 return false;
719 }
720
GetScsiDriveEncryptionStatus(int fd,const char * device_name,POOLMEM * & status,int indent)721 int GetScsiDriveEncryptionStatus(int fd, const char *device_name,
722 POOLMEM *&status, int indent)
723 {
724 PmStrcpy(status, "");
725 IndentStatusMsg(status, _("Drive encryption status: Unknown\n"), indent);
726 return strlen(status);
727 }
728
GetScsiVolumeEncryptionStatus(int fd,const char * device_name,POOLMEM * & status,int indent)729 int GetScsiVolumeEncryptionStatus(int fd, const char *device_name,
730 POOLMEM *&status, int indent)
731 {
732 PmStrcpy(status, "");
733 IndentStatusMsg(status, _("Volume encryption status: Unknown\n"), indent);
734 return strlen(status);
735 }
736
NeedScsiCryptoKey(int fd,const char * device_name,bool use_drive_status)737 bool NeedScsiCryptoKey(int fd, const char *device_name, bool use_drive_status)
738 {
739 return false;
740 }
741
GetScsiEncryptionEnabled(int fd,const char * device_name)742 bool GetScsiEncryptionEnabled(int fd, const char *device_name)
743 {
744 return false;
745 }
746 #endif /* HAVE_LOWLEVEL_SCSI_INTERFACE */
747
IndentStatusMsg(POOLMEM * & status,const char * msg,int indent)748 static void IndentStatusMsg(POOLMEM *&status, const char *msg, int indent)
749 {
750 int cnt;
751 char indent_level[17];
752
753 /*
754 * See if we need to indent the line.
755 */
756 if (indent > 0) {
757 for (cnt = 0; cnt < indent && cnt < 16; cnt++) {
758 indent_level[cnt] = ' ';
759 }
760 indent_level[cnt] = '\0';
761 PmStrcat(status, indent_level);
762 }
763
764 PmStrcat(status, msg);
765 }
766