]> git.ipfire.org Git - thirdparty/mdadm.git/blame - drive_encryption.c
Add key ENCRYPTION_NO_VERIFY to conf
[thirdparty/mdadm.git] / drive_encryption.c
CommitLineData
cc484068
BK
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Read encryption information for Opal and ATA devices.
4 *
5 * Copyright (C) 2024 Intel Corporation
6 * Author: Blazej Kucman <blazej.kucman@intel.com>
7 */
8
9#include "mdadm.h"
10
11#include <asm/types.h>
12#include <linux/nvme_ioctl.h>
df38df30
BK
13#include <scsi/sg.h>
14#include <scsi/scsi.h>
cc484068
BK
15#include "drive_encryption.h"
16
df38df30
BK
17#define DEFAULT_SECTOR_SIZE (512)
18
cc484068
BK
19/*
20 * Opal defines
21 * TCG Storage Opal SSC 2.01 chapter 3.3.3
22 * NVM ExpressTM Revision 1.4c, chapter 5
23 */
24#define TCG_SECP_01 (0x01)
25#define TCG_SECP_00 (0x00)
26#define OPAL_DISCOVERY_COMID (0x0001)
27#define OPAL_LOCKING_FEATURE (0x0002)
28#define OPAL_IO_BUFFER_LEN 2048
29#define OPAL_DISCOVERY_FEATURE_HEADER_LEN (4)
30
31/*
32 * NVMe defines
33 * NVM ExpressTM Revision 1.4c, chapter 5
34 */
35#define NVME_SECURITY_RECV (0x82)
36#define NVME_IDENTIFY (0x06)
37#define NVME_IDENTIFY_RESPONSE_LEN 4096
38#define NVME_OACS_BYTE_POSITION (256)
39#define NVME_IDENTIFY_CONTROLLER_DATA (1)
40
df38df30
BK
41/*
42 * ATA defines
43 * ATA/ATAPI Command Set ATA8-ACS
44 * SCSI / ATA Translation - 3 (SAT-3)
45 * SCSI Primary Commands - 4 (SPC-4)
46 * AT Attachment-8 - ATA Serial Transport (ATA8-AST)
47 * ATA Command Pass-Through
48 */
49#define ATA_IDENTIFY (0xec)
50#define ATA_TRUSTED_RECEIVE (0x5c)
51#define ATA_SECURITY_WORD_POSITION (128)
52#define HDIO_DRIVE_CMD (0x031f)
53#define ATA_TRUSTED_COMPUTING_POS (48)
54#define ATA_PASS_THROUGH_12 (0xa1)
55#define ATA_IDENTIFY_RESPONSE_LEN (512)
56#define ATA_PIO_DATA_IN (4)
57#define SG_CHECK_CONDITION (0x02)
58#define ATA_STATUS_RETURN_DESCRIPTOR (0x09)
59#define ATA_PT_INFORMATION_AVAILABLE_ASCQ (0x1d)
60#define ATA_PT_INFORMATION_AVAILABLE_ASC (0x00)
61#define ATA_INQUIRY_LENGTH (0x0c)
62#define SG_INTERFACE_ID 'S'
63#define SG_IO_TIMEOUT (60000)
64#define SG_SENSE_SIZE (32)
65#define SENSE_DATA_CURRENT_FIXED (0x70)
66#define SENSE_DATA_CURRENT_DESC (0x72)
67#define SENSE_CURRENT_RES_DESC_POS (8)
68#define SG_DRIVER_SENSE (0x08)
69
cc484068
BK
70typedef enum drive_feature_support_status {
71 /* Drive feature is supported. */
72 DRIVE_FEAT_SUP_ST = 0,
73 /* Drive feature is not supported. */
74 DRIVE_FEAT_NOT_SUP_ST,
75 /* Drive feature support check failed. */
76 DRIVE_FEAT_CHECK_FAILED_ST
77} drive_feat_sup_st;
78
79/* TCG Storage Opal SSC 2.01 chapter 3.1.1.3 */
80typedef struct opal_locking_feature {
81 /* feature header */
82 __u16 feature_code;
83 __u8 reserved : 4;
84 __u8 version : 4;
85 __u8 description_length;
86 /* feature description */
87 __u8 locking_supported : 1;
88 __u8 locking_enabled : 1;
89 __u8 locked : 1;
90 __u8 media_encryption : 1;
91 __u8 mbr_enabled : 1;
92 __u8 mbr_done : 1;
93 __u8 mbr_shadowing_not_supported : 1;
94 __u8 hw_reset_for_dor_supported : 1;
95 __u8 reserved1[11];
96} __attribute__((__packed__)) opal_locking_feature_t;
97
98/* TCG Storage Opal SSC 2.01 chapter 3.1.1.1 */
99typedef struct opal_level0_header {
100 __u32 length;
101 __u32 version;
102 __u64 reserved;
103 __u8 vendor_specific[32];
104} opal_level0_header_t;
105
106/**
107 * NVM ExpressTM Revision 1.4c, Figure 249
108 * Structure specifies only OACS filed, which is needed in the current use case.
109 */
110typedef struct nvme_identify_ctrl {
111 __u8 reserved[255];
112 __u16 oacs;
113 __u8 reserved2[3839];
114} nvme_identify_ctrl_t;
115
116/* SCSI Primary Commands - 4 (SPC-4), Table 512 */
117typedef struct supported_security_protocols {
118 __u8 reserved[6];
119 __u16 list_length;
120 __u8 list[504];
121} supported_security_protocols_t;
122
df38df30
BK
123/* ATA/ATAPI Command Set - 3 (ACS-3), Table 45 */
124typedef struct ata_security_status {
125 __u16 security_supported : 1;
126 __u16 security_enabled : 1;
127 __u16 security_locked : 1;
128 __u16 security_frozen : 1;
129 __u16 security_count_expired : 1;
130 __u16 enhanced_security_erase_supported : 1;
131 __u16 reserved1 : 2;
132 __u16 security_level : 1;
133 __u16 reserved2 : 7;
134} __attribute__((__packed__)) ata_security_status_t;
135
136/* ATA/ATAPI Command Set - 3 (ACS-3), Table 45 */
137typedef struct ata_trusted_computing {
138 __u16 tc_feature :1;
139 __u16 reserved : 13;
140 __u16 var1 : 1;
141 __u16 var2 : 1;
142} __attribute__((__packed__)) ata_trusted_computing_t;
143
cc484068
BK
144/**
145 * get_opal_locking_feature_description() - get opal locking feature description.
146 * @response: response from Opal Discovery Level 0.
147 *
148 * Based on the documentation TCG Storage Opal SSC 2.01 chapter 3.1.1,
149 * a Locking feature is searched for in Opal Level 0 Discovery response.
150 *
151 * Return: if locking feature is found, pointer to struct %opal_locking_feature_t, NULL otherwise.
152 */
153static opal_locking_feature_t *get_opal_locking_feature_description(__u8 *response)
154{
155 opal_level0_header_t *response_header = (opal_level0_header_t *)response;
156 int features_length = __be32_to_cpu(response_header->length);
157 int current_position = sizeof(*response_header);
158
159 while (current_position < features_length) {
160 opal_locking_feature_t *feature;
161
162 feature = (opal_locking_feature_t *)(response + current_position);
163
164 if (__be16_to_cpu(feature->feature_code) == OPAL_LOCKING_FEATURE)
165 return feature;
166
167 current_position += feature->description_length + OPAL_DISCOVERY_FEATURE_HEADER_LEN;
168 }
169
170 return NULL;
171}
172
173/**
174 * nvme_security_recv_ioctl() - nvme security receive ioctl.
175 * @disk_fd: a disk file descriptor.
176 * @sec_protocol: security protocol.
177 * @comm_id: command id.
178 * @response_buffer: response buffer to fill out.
179 * @buf_size: response buffer size.
180 * @verbose: verbose flag.
181 *
182 * Based on the documentations TCG Storage Opal SSC 2.01 chapter 3.3.3 and
183 * NVM ExpressTM Revision 1.4c, chapter 5.25,
184 * read security receive command via ioctl().
185 * On success, @response_buffer is completed.
186 *
187 * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
188 */
189static mdadm_status_t
190nvme_security_recv_ioctl(int disk_fd, __u8 sec_protocol, __u16 comm_id, void *response_buffer,
191 size_t buf_size, const int verbose)
192{
193 struct nvme_admin_cmd nvme_cmd = {0};
194 int status;
195
196 nvme_cmd.opcode = NVME_SECURITY_RECV;
197 nvme_cmd.cdw10 = sec_protocol << 24 | comm_id << 8;
198 nvme_cmd.cdw11 = buf_size;
199 nvme_cmd.data_len = buf_size;
200 nvme_cmd.addr = (__u64)response_buffer;
201
202 status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
203 if (status != 0) {
204 pr_vrb("Failed to read NVMe security receive ioctl() for device /dev/%s, status: %d\n",
205 fd2kname(disk_fd), status);
206 return MDADM_STATUS_ERROR;
207 }
208
209 return MDADM_STATUS_SUCCESS;
210}
211
212/**
213 * nvme_identify_ioctl() - NVMe identify ioctl.
214 * @disk_fd: a disk file descriptor.
215 * @response_buffer: response buffer to fill out.
216 * @buf_size: response buffer size.
217 * @verbose: verbose flag.
218 *
219 * Based on the documentations TCG Storage Opal SSC 2.01 chapter 3.3.3 and
220 * NVM ExpressTM Revision 1.4c, chapter 5.25,
221 * read NVMe identify via ioctl().
222 * On success, @response_buffer will be completed.
223 *
224 * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
225 */
226static mdadm_status_t
227nvme_identify_ioctl(int disk_fd, void *response_buffer, size_t buf_size, const int verbose)
228{
229 struct nvme_admin_cmd nvme_cmd = {0};
230 int status;
231
232 nvme_cmd.opcode = NVME_IDENTIFY;
233 nvme_cmd.cdw10 = NVME_IDENTIFY_CONTROLLER_DATA;
234 nvme_cmd.data_len = buf_size;
235 nvme_cmd.addr = (__u64)response_buffer;
236
237 status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
238 if (status != 0) {
239 pr_vrb("Failed to read NVMe identify ioctl() for device /dev/%s, status: %d\n",
240 fd2kname(disk_fd), status);
241 return MDADM_STATUS_ERROR;
242 }
243
244 return MDADM_STATUS_SUCCESS;
245}
246
247/**
248 * is_sec_prot_01h_supported() - check if security protocol 01h supported.
249 * @security_protocols: struct with response from disk (NVMe, SATA) describing supported
250 * security protocols.
251 *
252 * Return: true if TCG_SECP_01 found, false otherwise.
253 */
254static bool is_sec_prot_01h_supported(supported_security_protocols_t *security_protocols)
255{
256 int list_length = be16toh(security_protocols->list_length);
257 int index;
258
259 for (index = 0 ; index < list_length; index++) {
260 if (security_protocols->list[index] == TCG_SECP_01)
261 return true;
262 }
263
264 return false;
265}
266
267/**
268 * is_sec_prot_01h_supported_nvme() - check if security protocol 01h supported for given NVMe disk.
269 * @disk_fd: a disk file descriptor.
270 * @verbose: verbose flag.
271 *
272 * Return: %DRIVE_FEAT_SUP_ST if TCG_SECP_01 supported, %DRIVE_FEAT_NOT_SUP_ST if not supported,
273 * %DRIVE_FEAT_CHECK_FAILED_ST if failed to check.
274 */
275static drive_feat_sup_st is_sec_prot_01h_supported_nvme(int disk_fd, const int verbose)
276{
277 supported_security_protocols_t security_protocols = {0};
278
279 /* security_protocol: TCG_SECP_00, comm_id: not applicable */
280 if (nvme_security_recv_ioctl(disk_fd, TCG_SECP_00, 0x0, &security_protocols,
281 sizeof(security_protocols), verbose))
282 return DRIVE_FEAT_CHECK_FAILED_ST;
283
284 if (is_sec_prot_01h_supported(&security_protocols))
285 return DRIVE_FEAT_SUP_ST;
286
287 return DRIVE_FEAT_NOT_SUP_ST;
288}
289
290/**
291 * is_nvme_sec_send_recv_supported() - check if Security Send and Security Receive is supported.
292 * @disk_fd: a disk file descriptor.
293 * @verbose: verbose flag.
294 *
295 * Check if "Optional Admin Command Support" bit 0 is set in NVMe identify.
296 * Bit 0 set to 1 means controller supports the Security Send and Security Receive commands.
297 *
298 * Return: %DRIVE_FEAT_SUP_ST if security send/receive supported,
299 * %DRIVE_FEAT_NOT_SUP_ST if not supported, %DRIVE_FEAT_CHECK_FAILED_ST if check failed.
300 */
301static drive_feat_sup_st is_nvme_sec_send_recv_supported(int disk_fd, const int verbose)
302{
303 nvme_identify_ctrl_t nvme_identify = {0};
304 int status = 0;
305
306 status = nvme_identify_ioctl(disk_fd, &nvme_identify, sizeof(nvme_identify), verbose);
307 if (status)
308 return DRIVE_FEAT_CHECK_FAILED_ST;
309
310 if ((__le16_to_cpu(nvme_identify.oacs) & 0x1) == 0x1)
311 return DRIVE_FEAT_SUP_ST;
312
313 return DRIVE_FEAT_NOT_SUP_ST;
314}
315
316/**
317 * get_opal_encryption_information() - get Opal encryption information.
318 * @buffer: buffer with Opal Level 0 Discovery response.
319 * @information: struct to fill out, describing encryption status of disk.
320 *
321 * If Locking feature frame is in response from Opal Level 0 discovery, &encryption_information_t
322 * structure is completed with status and ability otherwise the status is set to &None.
323 * For possible encryption statuses and abilities,
324 * please refer to enums &encryption_status and &encryption_ability.
325 *
326 * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
327 */
328static mdadm_status_t get_opal_encryption_information(__u8 *buffer,
329 encryption_information_t *information)
330{
331 opal_locking_feature_t *opal_locking_feature =
332 get_opal_locking_feature_description(buffer);
333
334 if (!opal_locking_feature)
335 return MDADM_STATUS_ERROR;
336
337 if (opal_locking_feature->locking_supported == 1) {
338 information->ability = ENC_ABILITY_SED;
339
340 if (opal_locking_feature->locking_enabled == 0)
341 information->status = ENC_STATUS_UNENCRYPTED;
342 else if (opal_locking_feature->locked == 1)
343 information->status = ENC_STATUS_LOCKED;
344 else
345 information->status = ENC_STATUS_UNLOCKED;
346 } else {
347 information->ability = ENC_ABILITY_NONE;
348 information->status = ENC_STATUS_UNENCRYPTED;
349 }
350
351 return MDADM_STATUS_SUCCESS;
352}
353
354/**
355 * get_nvme_opal_encryption_information() - get NVMe Opal encryption information.
356 * @disk_fd: a disk file descriptor.
357 * @information: struct to fill out, describing encryption status of disk.
358 * @verbose: verbose flag.
359 *
360 * In case the disk supports Opal Level 0 discovery, &encryption_information_t structure
361 * is completed with status and ability based on ioctl response,
362 * otherwise the ability is set to %ENC_ABILITY_NONE and &status to %ENC_STATUS_UNENCRYPTED.
363 * As the current use case does not need the knowledge of Opal support, if there is no support,
364 * %MDADM_STATUS_SUCCESS will be returned, with the values described above.
365 * For possible encryption statuses and abilities,
366 * please refer to enums &encryption_status and &encryption_ability.
367 *
368 * %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
369 */
370mdadm_status_t
371get_nvme_opal_encryption_information(int disk_fd, encryption_information_t *information,
372 const int verbose)
373{
374 __u8 buffer[OPAL_IO_BUFFER_LEN];
375 int sec_send_recv_supported = 0;
376 int protocol_01h_supported = 0;
377 mdadm_status_t status;
378
379 information->ability = ENC_ABILITY_NONE;
380 information->status = ENC_STATUS_UNENCRYPTED;
381
382 sec_send_recv_supported = is_nvme_sec_send_recv_supported(disk_fd, verbose);
383 if (sec_send_recv_supported == DRIVE_FEAT_CHECK_FAILED_ST)
384 return MDADM_STATUS_ERROR;
385
386 /* Opal not supported */
387 if (sec_send_recv_supported == DRIVE_FEAT_NOT_SUP_ST)
388 return MDADM_STATUS_SUCCESS;
389
390 /**
391 * sec_send_recv_supported determine that it should be possible to read
392 * supported sec protocols
393 */
394 protocol_01h_supported = is_sec_prot_01h_supported_nvme(disk_fd, verbose);
395 if (protocol_01h_supported == DRIVE_FEAT_CHECK_FAILED_ST)
396 return MDADM_STATUS_ERROR;
397
398 /* Opal not supported */
399 if (sec_send_recv_supported == DRIVE_FEAT_SUP_ST &&
400 protocol_01h_supported == DRIVE_FEAT_NOT_SUP_ST)
401 return MDADM_STATUS_SUCCESS;
402
403 if (nvme_security_recv_ioctl(disk_fd, TCG_SECP_01, OPAL_DISCOVERY_COMID, (void *)&buffer,
404 OPAL_IO_BUFFER_LEN, verbose))
405 return MDADM_STATUS_ERROR;
406
407 status = get_opal_encryption_information((__u8 *)&buffer, information);
408 if (status)
409 pr_vrb("Locking feature description not found in Level 0 discovery response. Device /dev/%s.\n",
410 fd2kname(disk_fd));
411
412 if (information->ability == ENC_ABILITY_NONE)
413 assert(information->status == ENC_STATUS_UNENCRYPTED);
414
415 return status;
416}
df38df30
BK
417
418/**
419 * ata_pass_through12_ioctl() - ata pass through12 ioctl.
420 * @disk_fd: a disk file descriptor.
421 * @ata_command: ata command.
422 * @sec_protocol: security protocol.
423 * @comm_id: additional command id.
424 * @response_buffer: response buffer to fill out.
425 * @buf_size: response buffer size.
426 * @verbose: verbose flag.
427 *
428 * Based on the documentations ATA Command Pass-Through, chapter 13.2.2 and
429 * ATA Translation - 3 (SAT-3), send read ata pass through 12 command via ioctl().
430 * On success, @response_buffer will be completed.
431 *
432 * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR on fail.
433 */
434static mdadm_status_t
435ata_pass_through12_ioctl(int disk_fd, __u8 ata_command, __u8 sec_protocol, __u16 comm_id,
436 void *response_buffer, size_t buf_size, const int verbose)
437{
438 __u8 cdb[ATA_INQUIRY_LENGTH] = {0};
439 __u8 sense[SG_SENSE_SIZE] = {0};
440 __u8 *sense_desc = NULL;
441 sg_io_hdr_t sg = {0};
442
443 /*
444 * ATA Command Pass-Through, chapter 13.2.2
445 * SCSI Primary Commands - 4 (SPC-4)
446 * ATA Translation - 3 (SAT-3)
447 */
448 cdb[0] = ATA_PASS_THROUGH_12;
449 /* protocol, bits 1-4 */
450 cdb[1] = ATA_PIO_DATA_IN << 1;
451 /* Bytes: CK_COND=1, T_DIR = 1, BYTE_BLOCK = 1, Length in Sector Count = 2 */
452 cdb[2] = 0x2E;
453 cdb[3] = sec_protocol;
454 /* Sector count */
455 cdb[4] = buf_size / DEFAULT_SECTOR_SIZE;
456 cdb[6] = (comm_id) & 0xFF;
457 cdb[7] = (comm_id >> 8) & 0xFF;
458 cdb[9] = ata_command;
459
460 sg.interface_id = SG_INTERFACE_ID;
461 sg.cmd_len = sizeof(cdb);
462 sg.mx_sb_len = sizeof(sense);
463 sg.dxfer_direction = SG_DXFER_FROM_DEV;
464 sg.dxfer_len = buf_size;
465 sg.dxferp = response_buffer;
466 sg.cmdp = cdb;
467 sg.sbp = sense;
468 sg.timeout = SG_IO_TIMEOUT;
469 sg.usr_ptr = NULL;
470
471 if (ioctl(disk_fd, SG_IO, &sg) < 0) {
472 pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
473 return MDADM_STATUS_ERROR;
474 }
475
476 if ((sg.status && sg.status != SG_CHECK_CONDITION) || sg.host_status ||
477 (sg.driver_status && sg.driver_status != SG_DRIVER_SENSE)) {
478 pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
479 pr_vrb("SG_IO error: ATA_12 Status: %d Host Status: %d, Driver Status: %d\n",
480 sg.status, sg.host_status, sg.driver_status);
481 return MDADM_STATUS_ERROR;
482 }
483
484 /* verify expected sense response code */
485 if (!(sense[0] == SENSE_DATA_CURRENT_DESC || sense[0] == SENSE_DATA_CURRENT_FIXED)) {
486 pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
487 return MDADM_STATUS_ERROR;
488 }
489
490 sense_desc = sense + SENSE_CURRENT_RES_DESC_POS;
491 /* verify sense data current response with descriptor format */
492 if (sense[0] == SENSE_DATA_CURRENT_DESC &&
493 !(sense_desc[0] == ATA_STATUS_RETURN_DESCRIPTOR &&
494 sense_desc[1] == ATA_INQUIRY_LENGTH)) {
495 pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n",
496 fd2kname(disk_fd), sense[2], sense[3]);
497 return MDADM_STATUS_ERROR;
498 }
499
500 /* verify sense data current response with fixed format */
501 if (sense[0] == SENSE_DATA_CURRENT_FIXED &&
502 !(sense[12] == ATA_PT_INFORMATION_AVAILABLE_ASC &&
503 sense[13] == ATA_PT_INFORMATION_AVAILABLE_ASCQ)) {
504 pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n",
505 fd2kname(disk_fd), sense[12], sense[13]);
506 return MDADM_STATUS_ERROR;
507 }
508
509 return MDADM_STATUS_SUCCESS;
510}
511
512/**
513 * is_sec_prot_01h_supported_ata() - check if security protocol 01h supported for given SATA disk.
514 * @disk_fd: a disk file descriptor.
515 * @verbose: verbose flag.
516 *
517 * Return: %DRIVE_FEAT_SUP_ST if TCG_SECP_01 supported, %DRIVE_FEAT_NOT_SUP_ST if not supported,
518 * %DRIVE_FEAT_CHECK_FAILED_ST if failed.
519 */
520static drive_feat_sup_st is_sec_prot_01h_supported_ata(int disk_fd, const int verbose)
521{
522 supported_security_protocols_t security_protocols;
523
524 mdadm_status_t result = ata_pass_through12_ioctl(disk_fd, ATA_TRUSTED_RECEIVE, TCG_SECP_00,
525 0x0, &security_protocols,
526 sizeof(security_protocols), verbose);
527 if (result)
528 return DRIVE_FEAT_CHECK_FAILED_ST;
529
530 if (is_sec_prot_01h_supported(&security_protocols))
531 return DRIVE_FEAT_SUP_ST;
532
533 return DRIVE_FEAT_NOT_SUP_ST;
534}
535
536/**
537 * is_ata_trusted_computing_supported() - check if ata trusted computing supported.
538 * @buffer: buffer with ATA identify response, not NULL.
539 *
540 * Return: true if trusted computing bit set, false otherwise.
541 */
542bool is_ata_trusted_computing_supported(__u16 *buffer)
543{
544 /* Added due to warnings from the compiler about a possible uninitialized variable below. */
545 assert(buffer);
546
547 __u16 security_tc_frame = __le16_to_cpu(buffer[ATA_TRUSTED_COMPUTING_POS]);
548 ata_trusted_computing_t *security_tc = (ata_trusted_computing_t *)&security_tc_frame;
549
550 if (security_tc->tc_feature == 1)
551 return true;
552
553 return false;
554}
555
556/**
557 * get_ata_standard_security_status() - get ATA disk encryption information from ATA identify.
558 * @buffer: buffer with response from ATA identify, not NULL.
559 * @information: struct to fill out, describing encryption status of disk.
560 *
561 * The function based on the Security status frame from ATA identify,
562 * completed encryption information.
563 * For possible encryption statuses and abilities,
564 * please refer to enums &encryption_status and &encryption_ability.
565 *
566 * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR on fail.
567 */
568static mdadm_status_t get_ata_standard_security_status(__u16 *buffer,
569 struct encryption_information *information)
570{
571 /* Added due to warnings from the compiler about a possible uninitialized variable below. */
572 assert(buffer);
573
574 __u16 security_status_frame = __le16_to_cpu(buffer[ATA_SECURITY_WORD_POSITION]);
575 ata_security_status_t *security_status = (ata_security_status_t *)&security_status_frame;
576
577 if (!security_status->security_supported) {
578 information->ability = ENC_ABILITY_NONE;
579 information->status = ENC_STATUS_UNENCRYPTED;
580
581 return MDADM_STATUS_SUCCESS;
582 }
583
584 information->ability = ENC_ABILITY_OTHER;
585
586 if (security_status->security_enabled == 0)
587 information->status = ENC_STATUS_UNENCRYPTED;
588 else if (security_status->security_locked == 1)
589 information->status = ENC_STATUS_LOCKED;
590 else
591 information->status = ENC_STATUS_UNLOCKED;
592
593 return MDADM_STATUS_SUCCESS;
594}
595
596/**
597 * is_ata_opal() - check if SATA disk support Opal.
598 * @disk_fd: a disk file descriptor.
599 * @buffer: buffer with ATA identify response.
600 * @verbose: verbose flag.
601 *
602 * Return: %DRIVE_FEAT_SUP_ST if TCG_SECP_01 supported, %DRIVE_FEAT_NOT_SUP_ST if not supported,
603 * %DRIVE_FEAT_CHECK_FAILED_ST if failed to check.
604 */
605static drive_feat_sup_st is_ata_opal(int disk_fd, __u16 *buffer_identify, const int verbose)
606{
607 bool tc_status = is_ata_trusted_computing_supported(buffer_identify);
608 drive_feat_sup_st tcg_sec_prot_status;
609
610 if (!tc_status)
611 return DRIVE_FEAT_NOT_SUP_ST;
612
613 tcg_sec_prot_status = is_sec_prot_01h_supported_ata(disk_fd, verbose);
614
615 if (tcg_sec_prot_status == DRIVE_FEAT_CHECK_FAILED_ST) {
616 pr_vrb("Failed to verify if security protocol 01h supported. Device /dev/%s.\n",
617 fd2kname(disk_fd));
618 return DRIVE_FEAT_CHECK_FAILED_ST;
619 }
620
621 if (tc_status && tcg_sec_prot_status == DRIVE_FEAT_SUP_ST)
622 return DRIVE_FEAT_SUP_ST;
623
624 return DRIVE_FEAT_NOT_SUP_ST;
625}
626
627/**
628 * get_ata_encryption_information() - get ATA disk encryption information.
629 * @disk_fd: a disk file descriptor.
630 * @information: struct to fill out, describing encryption status of disk.
631 * @verbose: verbose flag.
632 *
633 * The function reads information about encryption, if the disk supports Opal,
634 * the information is completed based on Opal Level 0 discovery, otherwise,
635 * based on ATA security status frame from ATA identification response.
636 * For possible encryption statuses and abilities,
637 * please refer to enums &encryption_status and &encryption_ability.
638 *
639 * Based on the documentations ATA/ATAPI Command Set ATA8-ACS and
640 * AT Attachment-8 - ATA Serial Transport (ATA8-AST).
641 *
642 * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR on fail.
643 */
644mdadm_status_t
645get_ata_encryption_information(int disk_fd, struct encryption_information *information,
646 const int verbose)
647{
648 __u8 buffer_opal_level0_discovery[OPAL_IO_BUFFER_LEN] = {0};
649 __u16 buffer_identify[ATA_IDENTIFY_RESPONSE_LEN] = {0};
650 drive_feat_sup_st ata_opal_status;
651 mdadm_status_t status;
652
653 /* Get disk ATA identification */
654 status = ata_pass_through12_ioctl(disk_fd, ATA_IDENTIFY, 0x0, 0x0, buffer_identify,
655 sizeof(buffer_identify), verbose);
656 if (status == MDADM_STATUS_ERROR)
657 return MDADM_STATUS_ERROR;
658
336e13fc
BK
659 /* Possible OPAL support, further checks require tpm_enabled.*/
660 if (is_ata_trusted_computing_supported(buffer_identify)) {
661 /* OPAL SATA encryption checking disabled. */
662 if (conf_get_sata_opal_encryption_no_verify())
663 return MDADM_STATUS_SUCCESS;
664
665 if (!sysfs_is_libata_allow_tpm_enabled(verbose)) {
666 pr_vrb("Detected SATA drive /dev/%s with Trusted Computing support.\n",
667 fd2kname(disk_fd));
668 pr_vrb("Cannot verify encryption state. Requires libata.tpm_enabled=1.\n");
669 return MDADM_STATUS_ERROR;
670 }
df38df30
BK
671 }
672
673 ata_opal_status = is_ata_opal(disk_fd, buffer_identify, verbose);
674 if (ata_opal_status == DRIVE_FEAT_CHECK_FAILED_ST)
675 return MDADM_STATUS_ERROR;
676
677 if (ata_opal_status == DRIVE_FEAT_NOT_SUP_ST)
678 return get_ata_standard_security_status(buffer_identify, information);
679
680 /* SATA Opal */
681 status = ata_pass_through12_ioctl(disk_fd, ATA_TRUSTED_RECEIVE, TCG_SECP_01,
682 OPAL_DISCOVERY_COMID, buffer_opal_level0_discovery,
683 OPAL_IO_BUFFER_LEN, verbose);
684 if (status != MDADM_STATUS_SUCCESS)
685 return MDADM_STATUS_ERROR;
686
687 return get_opal_encryption_information(buffer_opal_level0_discovery, information);
688}