diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 3572da34..3d28f507 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -1374,6 +1374,9 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password .label = ARG_STR(OPT_LABEL_ID), .subsystem = ARG_STR(OPT_SUBSYSTEM_ID) }; + struct crypt_params_hw_opal opal_params = { + .user_key_size = DEFAULT_LUKS1_KEYBITS / 8 + }; void *params; type = luksType(device_type); @@ -1487,6 +1490,11 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password keysize = get_adjusted_key_size(cipher_mode, DEFAULT_LUKS1_KEYBITS, integrity_keysize); + if (ARG_SET(OPT_HW_OPAL_ONLY_ID)) + keysize = opal_params.user_key_size; + else if (ARG_SET(OPT_HW_OPAL_ID)) + keysize += opal_params.user_key_size; + if (ARG_SET(OPT_USE_RANDOM_ID)) crypt_set_rng_type(cd, CRYPT_RNG_RANDOM); else if (ARG_SET(OPT_USE_URANDOM_ID)) @@ -1498,6 +1506,19 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password if (r < 0) goto out; + if (ARG_SET(OPT_HW_OPAL_ID) || ARG_SET(OPT_HW_OPAL_ONLY_ID)) { + r = tools_get_key("Enter OPAL Admin password: ", CONST_CAST(char **)&opal_params.admin_key, &opal_params.admin_key_size, + 0, 0, NULL, + ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(1), !ARG_SET(OPT_FORCE_PASSWORD_ID), cd); + if (r < 0) + goto out; + if (opal_params.admin_key_size == 0) { + log_err(_("OPAL Admin password cannot be empty.")); + r = -EPERM; + goto out; + } + } + if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) { r = tools_read_vk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), &key, keysize); if (r < 0) @@ -1517,7 +1538,13 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password if (ARG_SET(OPT_INTEGRITY_LEGACY_PADDING_ID)) crypt_set_compatibility(cd, CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING); - r = crypt_format(cd, type, cipher, cipher_mode, + if (ARG_SET(OPT_HW_OPAL_ID) || ARG_SET(OPT_HW_OPAL_ONLY_ID)) + r = crypt_format_luks2_opal(cd, + ARG_SET(OPT_HW_OPAL_ONLY_ID) ? NULL : cipher, + ARG_SET(OPT_HW_OPAL_ONLY_ID) ? NULL : cipher_mode, + ARG_STR(OPT_UUID_ID), key, keysize, params, &opal_params); + else + r = crypt_format(cd, type, cipher, cipher_mode, ARG_STR(OPT_UUID_ID), key, keysize, params); check_signal(&r); if (r < 0) @@ -1550,6 +1577,7 @@ out: } crypt_safe_free(key); + crypt_safe_free(CONST_CAST(void *)opal_params.admin_key); return r; } diff --git a/src/cryptsetup_arg_list.h b/src/cryptsetup_arg_list.h index a7e5bb0c..98f7c34d 100644 --- a/src/cryptsetup_arg_list.h +++ b/src/cryptsetup_arg_list.h @@ -69,6 +69,10 @@ ARG(OPT_HEADER_BACKUP_FILE, '\0', POPT_ARG_STRING, N_("File with LUKS header and ARG(OPT_HOTZONE_SIZE, '\0', POPT_ARG_STRING, N_("Maximal reencryption hotzone size."), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_HOTZONE_SIZE_ACTIONS) +ARG(OPT_HW_OPAL, '\0', POPT_ARG_NONE, N_("Use HW OPAL encryption together with SW encryption."), NULL, CRYPT_ARG_BOOL, {}, {}) + +ARG(OPT_HW_OPAL_ONLY, '\0', POPT_ARG_NONE, N_("Use only HW OPAL encryption."), NULL, CRYPT_ARG_BOOL, {}, {}) + 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) diff --git a/src/utils_arg_names.h b/src/utils_arg_names.h index 66a59e83..e3994bc2 100644 --- a/src/utils_arg_names.h +++ b/src/utils_arg_names.h @@ -61,6 +61,8 @@ #define OPT_HEADER "header" #define OPT_HEADER_BACKUP_FILE "header-backup-file" #define OPT_HOTZONE_SIZE "hotzone-size" +#define OPT_HW_OPAL "hw-opal" +#define OPT_HW_OPAL_ONLY "hw-opal-only" #define OPT_IGNORE_CORRUPTION "ignore-corruption" #define OPT_IGNORE_ZERO_BLOCKS "ignore-zero-blocks" #define OPT_INIT_ONLY "init-only" diff --git a/src/utils_luks.c b/src/utils_luks.c index 6a10ab64..34eee7d1 100644 --- a/src/utils_luks.c +++ b/src/utils_luks.c @@ -50,7 +50,8 @@ bool isLUKS1(const char *type) bool isLUKS2(const char *type) { - return type && !strcmp(type, CRYPT_LUKS2); + /* OPAL just changes the driver, header format is identical, so overload */ + return type && (!strcmp(type, CRYPT_LUKS2)); } int verify_passphrase(int def)