mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
cryptsetup: support for hw-opal in luksErase
Wipe and disable the segment. Also support the factory reset ioctl for a complete wipe of the entire drive with a specific argument. Signed-off-by: Luca Boccassi <bluca@debian.org>
This commit is contained in:
@@ -2325,6 +2325,35 @@ int crypt_wipe(struct crypt_device *cd,
|
||||
#define CRYPT_WIPE_NO_DIRECT_IO (UINT32_C(1) << 0)
|
||||
/** @} */
|
||||
|
||||
enum {
|
||||
CRYPT_LUKS2_SEGMENT = -2,
|
||||
CRYPT_NO_SEGMENT = -1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Safe erase of a partition or an entire OPAL device. WARNING: ALL DATA ON
|
||||
* PARTITION/DISK WILL BE LOST. If the CRYPT_NO_SEGMENT is passed as the segment
|
||||
* parameter, the entire device will be wiped, not just what is included in the
|
||||
* LUKS2 device/partition.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param segment the segment number to wipe (0..8), or CRYPT_LUKS2_SEGMENT
|
||||
* to wipe the segment configured in the LUKS2 header, or CRYPT_NO_SEGMENT
|
||||
* to wipe the entire device via a factory reset.
|
||||
* @param password admin password/PSID (for factory reset) to wipe the
|
||||
* partition/device
|
||||
* @param password_size length of password/PSID
|
||||
* @param flags (currently unused)
|
||||
*
|
||||
* @return @e 0 on success or negative errno value otherwise.
|
||||
*/
|
||||
int crypt_wipe_hw_opal(struct crypt_device *cd,
|
||||
int segment, /* 0..8, CRYPT_LUKS2_SEGMENT -2, CRYPT_NO_SEGMENT -1 */
|
||||
const char *password, /* Admin1 PIN or PSID */
|
||||
size_t password_size,
|
||||
uint32_t flags /* currently unused */
|
||||
);
|
||||
|
||||
/**
|
||||
* @defgroup crypt-tokens LUKS2 token wrapper access
|
||||
*
|
||||
|
||||
@@ -170,4 +170,5 @@ CRYPTSETUP_2.7 {
|
||||
global:
|
||||
crypt_format_luks2_opal;
|
||||
crypt_get_hw_encryption_type;
|
||||
crypt_wipe_hw_opal;
|
||||
} CRYPTSETUP_2.6;
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <linux/fs.h>
|
||||
#include "internal.h"
|
||||
#include "luks2/luks2_internal.h"
|
||||
#include "luks2/hw_opal/hw_opal.h"
|
||||
|
||||
/* block device zeroout ioctls, introduced in Linux kernel 3.7 */
|
||||
#ifndef BLKZEROOUT
|
||||
@@ -309,3 +311,62 @@ int crypt_wipe(struct crypt_device *cd,
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_wipe_hw_opal(struct crypt_device *cd,
|
||||
int segment,
|
||||
const char *password,
|
||||
size_t password_size,
|
||||
uint32_t flags)
|
||||
{
|
||||
int r;
|
||||
struct luks2_hdr *hdr;
|
||||
uint32_t opal_segment_number;
|
||||
|
||||
if (!cd)
|
||||
return -EINVAL;
|
||||
|
||||
if (!password)
|
||||
return -EINVAL;
|
||||
|
||||
if (segment < CRYPT_LUKS2_SEGMENT || segment > 8)
|
||||
return -EINVAL;
|
||||
|
||||
r = crypt_opal_supported(cd, crypt_data_device(cd));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (segment == CRYPT_NO_SEGMENT) {
|
||||
r = opal_factory_reset(cd, crypt_data_device(cd), password, password_size);
|
||||
if (r == -EPERM)
|
||||
log_err(cd, _("Incorrect OPAL PSID."));
|
||||
else if (r < 0)
|
||||
log_err(cd, _("Cannot erase OPAL device."));
|
||||
return r;
|
||||
}
|
||||
|
||||
if (onlyLUKS2(cd) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
|
||||
if (!hdr)
|
||||
return -EINVAL;
|
||||
|
||||
if (segment == CRYPT_LUKS2_SEGMENT) {
|
||||
r = LUKS2_get_opal_segment_number(hdr, CRYPT_DEFAULT_SEGMENT, &opal_segment_number);
|
||||
if (r < 0) {
|
||||
log_dbg(cd, "Can not get OPAL segment number.");
|
||||
return r;
|
||||
}
|
||||
} else
|
||||
opal_segment_number = segment;
|
||||
|
||||
r = opal_reset_segment(cd,
|
||||
crypt_data_device(cd),
|
||||
opal_segment_number,
|
||||
password,
|
||||
password_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return LUKS2_wipe_header_areas(cd, hdr, crypt_header_is_detached(cd));
|
||||
}
|
||||
|
||||
@@ -2672,23 +2672,62 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int opal_erase(struct crypt_device *cd, bool factory_reset) {
|
||||
char *password = NULL;
|
||||
size_t password_size = 0;
|
||||
int r;
|
||||
|
||||
r = tools_get_key(factory_reset ? _("Enter OPAL PSID: ") : _("Enter OPAL Admin password: "),
|
||||
&password, &password_size,
|
||||
0, 0, NULL,
|
||||
ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(1), !ARG_SET(OPT_FORCE_PASSWORD_ID), cd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (factory_reset && !ARG_SET(OPT_BATCH_MODE_ID) &&
|
||||
!yesDialog(_("WARNING: WHOLE disk will be factory reset and all data will be lost! Continue?"),
|
||||
_("Operation aborted.\n"))) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return crypt_wipe_hw_opal(cd,
|
||||
factory_reset ? CRYPT_NO_SEGMENT : CRYPT_LUKS2_SEGMENT,
|
||||
password,
|
||||
password_size,
|
||||
0);
|
||||
}
|
||||
|
||||
static int action_luksErase(void)
|
||||
{
|
||||
struct crypt_device *cd = NULL;
|
||||
crypt_keyslot_info ki;
|
||||
char *msg = NULL;
|
||||
int i, max, r;
|
||||
int i, max, r, hw_enc;
|
||||
|
||||
if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
|
||||
goto out;
|
||||
|
||||
/* Allow factory reset even if there's no LUKS header, as long as OPAL is enabled on the device */
|
||||
if (ARG_SET(OPT_HW_OPAL_FACTORY_RESET_ID)) {
|
||||
r = opal_erase(cd, true);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((r = crypt_load(cd, luksType(device_type), NULL))) {
|
||||
log_err(_("Device %s is not a valid LUKS device."),
|
||||
uuid_or_device_header(NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(asprintf(&msg, _("This operation will erase all keyslots on device %s.\n"
|
||||
hw_enc = crypt_get_hw_encryption_type(cd);
|
||||
if (hw_enc < 0)
|
||||
goto out;
|
||||
if (hw_enc == CRYPT_OPAL_HW_ONLY || hw_enc == CRYPT_SW_AND_OPAL_HW) {
|
||||
r = opal_erase(cd, false);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (asprintf(&msg, _("This operation will erase all keyslots on device %s.\n"
|
||||
"Device will become unusable after this operation."),
|
||||
uuid_or_device_header(NULL)) == -1) {
|
||||
r = -ENOMEM;
|
||||
@@ -3539,7 +3578,10 @@ int main(int argc, const char **argv)
|
||||
aname = CLOSE_ACTION;
|
||||
} else if (!strcmp(aname, "luksErase")) {
|
||||
aname = ERASE_ACTION;
|
||||
device_type = "luks";
|
||||
if (ARG_SET(OPT_TYPE_ID))
|
||||
device_type = ARG_STR(OPT_TYPE_ID);
|
||||
else
|
||||
device_type = "luks";
|
||||
} else if (!strcmp(aname, "luksConfig")) {
|
||||
aname = CONFIG_ACTION;
|
||||
device_type = "luks2";
|
||||
|
||||
@@ -73,6 +73,8 @@ ARG(OPT_HW_OPAL, '\0', POPT_ARG_NONE, N_("Use HW OPAL encryption together with S
|
||||
|
||||
ARG(OPT_HW_OPAL_ONLY, '\0', POPT_ARG_NONE, N_("Use only HW OPAL encryption."), NULL, CRYPT_ARG_BOOL, {}, {})
|
||||
|
||||
ARG(OPT_HW_OPAL_FACTORY_RESET, '\0', POPT_ARG_NONE, N_("Wipe WHOLE OPAL disk on luksErase."), NULL, CRYPT_ARG_BOOL, {}, OPT_ERASE_ACTIONS)
|
||||
|
||||
ARG(OPT_INIT_ONLY, '\0', POPT_ARG_NONE, N_("Initialize LUKS2 reencryption in metadata only."), NULL, CRYPT_ARG_BOOL, {}, {})
|
||||
|
||||
ARG(OPT_INTEGRITY, 'I', POPT_ARG_STRING, N_("Data integrity algorithm (LUKS2 only)"), NULL, CRYPT_ARG_STRING, {}, OPT_INTEGRITY_ACTIONS)
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#define OPT_DEFERRED_ACTIONS { CLOSE_ACTION }
|
||||
#define OPT_DEVICE_SIZE_ACTIONS { OPEN_ACTION, RESIZE_ACTION, REENCRYPT_ACTION }
|
||||
#define OPT_DISABLE_VERACRYPT_ACTIONS { OPEN_ACTION, TCRYPTDUMP_ACTION }
|
||||
#define OPT_ERASE_ACTIONS { ERASE_ACTION }
|
||||
#define OPT_HOTZONE_SIZE_ACTIONS { REENCRYPT_ACTION }
|
||||
#define OPT_FORCE_OFFLINE_REENCRYPT_ACTIONS { REENCRYPT_ACTION }
|
||||
#define OPT_INTEGRITY_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION }
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#define OPT_HOTZONE_SIZE "hotzone-size"
|
||||
#define OPT_HW_OPAL "hw-opal"
|
||||
#define OPT_HW_OPAL_ONLY "hw-opal-only"
|
||||
#define OPT_HW_OPAL_FACTORY_RESET "hw-opal-factory-reset"
|
||||
#define OPT_IGNORE_CORRUPTION "ignore-corruption"
|
||||
#define OPT_IGNORE_ZERO_BLOCKS "ignore-zero-blocks"
|
||||
#define OPT_INIT_ONLY "init-only"
|
||||
|
||||
Reference in New Issue
Block a user