diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptsetup.c | 637 | ||||
-rw-r--r-- | src/cryptsetup.h | 4 | ||||
-rw-r--r-- | src/cryptsetup_arg_list.h | 56 | ||||
-rw-r--r-- | src/cryptsetup_args.h | 43 | ||||
-rw-r--r-- | src/integritysetup.c | 30 | ||||
-rw-r--r-- | src/integritysetup_arg_list.h | 34 | ||||
-rw-r--r-- | src/integritysetup_args.h | 17 | ||||
-rw-r--r-- | src/meson.build | 77 | ||||
-rw-r--r-- | src/utils_arg_macros.h | 4 | ||||
-rw-r--r-- | src/utils_arg_names.h | 11 | ||||
-rw-r--r-- | src/utils_args.c | 4 | ||||
-rw-r--r-- | src/utils_blockdev.c | 18 | ||||
-rw-r--r-- | src/utils_luks.c | 9 | ||||
-rw-r--r-- | src/utils_luks.h | 6 | ||||
-rw-r--r-- | src/utils_password.c | 5 | ||||
-rw-r--r-- | src/utils_progress.c | 4 | ||||
-rw-r--r-- | src/utils_reencrypt.c | 43 | ||||
-rw-r--r-- | src/utils_reencrypt_luks1.c | 4 | ||||
-rw-r--r-- | src/utils_tools.c | 17 | ||||
-rw-r--r-- | src/veritysetup.c | 7 | ||||
-rw-r--r-- | src/veritysetup_arg_list.h | 4 | ||||
-rw-r--r-- | src/veritysetup_args.h | 6 |
22 files changed, 839 insertions, 201 deletions
diff --git a/src/cryptsetup.c b/src/cryptsetup.c index e387c1c..a46e2dd 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -3,8 +3,8 @@ * * Copyright (C) 2004 Jana Saout <jana@saout.de> * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org> - * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2023 Milan Broz + * Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,9 +28,13 @@ #include "utils_luks.h" static char *keyfiles[MAX_KEYFILES]; +static char *keyring_links[MAX_KEYRING_LINKS]; +static char *vks_in_keyring[MAX_VK_IN_KEYRING]; static char *keyfile_stdin = NULL; static int keyfiles_count = 0; +static int keyring_links_count = 0; +static int vks_in_keyring_count = 0; int64_t data_shift = 0; const char *device_type = "luks"; @@ -57,6 +61,10 @@ void tools_cleanup(void) while (keyfiles_count) free(keyfiles[--keyfiles_count]); + while (keyring_links_count) + free(keyring_links[--keyring_links_count]); + while (vks_in_keyring_count) + free(vks_in_keyring[--vks_in_keyring_count]); total_keyfiles = 0; } @@ -89,27 +97,49 @@ static int _set_keyslot_encryption_params(struct crypt_device *cd) return crypt_keyslot_set_encryption(cd, ARG_STR(OPT_KEYSLOT_CIPHER_ID), ARG_UINT32(OPT_KEYSLOT_KEY_SIZE_ID) / 8); } -static int _try_token_pin_unlock(struct crypt_device *cd, - int token_id, - const char *activated_name, - const char *token_type, - uint32_t activate_flags, - int tries, - bool activation) +static int _try_token_unlock(struct crypt_device *cd, + int keyslot, + int token_id, + const char *activated_name, + const char *token_type, + uint32_t activate_flags, + int tries, + bool activation, + bool token_only) { + int r; + struct crypt_keyslot_context *kc; size_t pin_len; char msg[64], *pin = NULL; - int r; assert(tries >= 1); assert(token_id >= 0 || token_id == CRYPT_ANY_TOKEN); + assert(keyslot >= 0 || keyslot == CRYPT_ANY_SLOT); + + r = crypt_keyslot_context_init_by_token(cd, token_id, token_type, NULL, 0, NULL, &kc); + if (r < 0) + return r; + + if (activation) + r = crypt_activate_by_keyslot_context(cd, activated_name, keyslot, kc, CRYPT_ANY_SLOT, NULL, activate_flags); + else + r = crypt_resume_by_keyslot_context(cd, activated_name, keyslot, kc); + + tools_keyslot_msg(r, UNLOCKED); + tools_token_error_msg(r, token_type, token_id, false); + + /* Token requires PIN (-ENOANO). Ask for it if there is evident preference for tokens */ + if (r != -ENOANO || (!token_only && !token_type && token_id == CRYPT_ANY_TOKEN)) + goto out; if (token_id == CRYPT_ANY_TOKEN) r = snprintf(msg, sizeof(msg), _("Enter token PIN: ")); else r = snprintf(msg, sizeof(msg), _("Enter token %d PIN: "), token_id); - if (r < 0 || (size_t)r >= sizeof(msg)) - return -EINVAL; + if (r < 0 || (size_t)r >= sizeof(msg)) { + r = -EINVAL; + goto out; + } do { r = tools_get_key(msg, &pin, &pin_len, 0, 0, NULL, @@ -117,20 +147,26 @@ static int _try_token_pin_unlock(struct crypt_device *cd, if (r < 0) break; + r = crypt_keyslot_context_set_pin(cd, pin, pin_len, kc); + if (r < 0) { + crypt_safe_free(pin); + break; + } + if (activation) - r = crypt_activate_by_token_pin(cd, activated_name, token_type, - token_id, pin, pin_len, NULL, - activate_flags); + r = crypt_activate_by_keyslot_context(cd, activated_name, keyslot, + kc, CRYPT_ANY_SLOT, NULL, activate_flags); else - r = crypt_resume_by_token_pin(cd, activated_name, token_type, - token_id, pin, pin_len, NULL); + r = crypt_resume_by_keyslot_context(cd, activated_name, keyslot, kc); + crypt_safe_free(pin); pin = NULL; tools_keyslot_msg(r, UNLOCKED); - tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), token_id, true); + tools_token_error_msg(r, token_type, token_id, true); check_signal(&r); } while (r == -ENOANO && (--tries > 0)); - +out: + crypt_keyslot_context_free(kc); return r; } @@ -151,6 +187,7 @@ static int action_open_plain(void) size_t passwordLen, key_size_max, signatures = 0, key_size = (ARG_UINT32(OPT_KEY_SIZE_ID) ?: DEFAULT_PLAIN_KEYBITS) / 8; uint32_t activate_flags = 0; + bool compat_warning = false; int r; r = crypt_parse_name_and_mode(ARG_STR(OPT_CIPHER_ID) ?: DEFAULT_CIPHER(PLAIN), @@ -160,6 +197,23 @@ static int action_open_plain(void) goto out; } + /* + * Warn user if no cipher options and passphrase hashing is not specified. + * For keyfile, password hashing is not used, no need to print warning for missing --hash. + * Keep this enabled even in batch mode to fix scripts and avoid data corruption. + */ + if (!ARG_SET(OPT_CIPHER_ID) || !ARG_SET(OPT_KEY_SIZE_ID)) { + log_err(_("WARNING: Using default options for cipher (%s-%s, key size %u bits) that could be incompatible with older versions."), + cipher, cipher_mode, key_size * 8); + compat_warning = true; + } + if (!ARG_SET(OPT_HASH_ID) && !ARG_SET(OPT_KEY_FILE_ID)) { + log_err(_("WARNING: Using default options for hash (%s) that could be incompatible with older versions."), params.hash); + compat_warning = true; + } + if (compat_warning) + log_err(_("For plain mode, always use options --cipher, --key-size and if no keyfile is used, then also --hash.")); + /* FIXME: temporary hack, no hashing for keyfiles in plain mode */ if (ARG_SET(OPT_KEY_FILE_ID) && !tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID))) { params.hash = NULL; @@ -204,11 +258,14 @@ static int action_open_plain(void) goto out; /* Skip blkid scan when activating plain device with offset */ - if (!ARG_UINT64(OPT_OFFSET_ID)) { + if (!ARG_UINT64(OPT_OFFSET_ID) && !ARG_SET(OPT_DISABLE_BLKID_ID)) { /* Print all present signatures in read-only mode */ r = tools_detect_signatures(action_argv[0], PRB_FILTER_NONE, &signatures, ARG_SET(OPT_BATCH_MODE_ID)); - if (r < 0) + if (r < 0) { + if (r == -EIO) + log_err(_("Blkid scan failed for %s."), action_argv[0]); goto out; + } } if (signatures && !ARG_SET(OPT_BATCH_MODE_ID)) { @@ -829,6 +886,15 @@ static int action_resize(void) else if (ARG_SET(OPT_SIZE_ID)) dev_size = ARG_UINT64(OPT_SIZE_ID); + if (ARG_SET(OPT_EXTERNAL_TOKENS_PATH_ID)) { + r = crypt_token_set_external_path(ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + if (r < 0) { + log_err(_("Failed to set external tokens path %s."), + ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + goto out; + } + } + if (cad.flags & CRYPT_ACTIVATE_KEYRING_KEY) { if (ARG_SET(OPT_DISABLE_KEYRING_ID)) { r = -EINVAL; @@ -838,16 +904,9 @@ static int action_resize(void) } /* try load VK in kernel keyring using token */ - r = crypt_activate_by_token_pin(cd, NULL, ARG_STR(OPT_TOKEN_TYPE_ID), - ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL, - CRYPT_ACTIVATE_KEYRING_KEY); - tools_keyslot_msg(r, UNLOCKED); - tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), ARG_INT32(OPT_TOKEN_ID_ID), false); - - /* Token requires PIN. Ask if there is evident preference for tokens */ - if (r == -ENOANO && (ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) || - ARG_SET(OPT_TOKEN_ID_ID))) - r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), NULL, ARG_STR(OPT_TOKEN_TYPE_ID), CRYPT_ACTIVATE_KEYRING_KEY, 1, true); + r = _try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_TOKEN_ID_ID), + NULL, ARG_STR(OPT_TOKEN_TYPE_ID), CRYPT_ACTIVATE_KEYRING_KEY, + 1, true, ARG_SET(OPT_TOKEN_ONLY_ID)); if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID)) goto out; @@ -883,7 +942,7 @@ static int action_status(void) struct crypt_device *cd = NULL; char *backing_file; const char *device; - int path = 0, r = 0; + int path = 0, r = 0, hw_enc; /* perhaps a path, not a dm device name */ if (strchr(action_argv[0], '/')) @@ -932,13 +991,33 @@ static int action_status(void) if (r < 0 && r != -ENOTSUP) goto out; - log_std(" cipher: %s-%s\n", crypt_get_cipher(cd), crypt_get_cipher_mode(cd)); - log_std(" keysize: %d bits\n", crypt_get_volume_key_size(cd) * 8); - log_std(" key location: %s\n", (cad.flags & CRYPT_ACTIVATE_KEYRING_KEY) ? "keyring" : "dm-crypt"); + hw_enc = crypt_get_hw_encryption_type(cd); + if (hw_enc < 0) { + r = hw_enc; + goto out; + } + + if (hw_enc == CRYPT_SW_ONLY) { + log_std(" cipher: %s-%s\n", crypt_get_cipher(cd), crypt_get_cipher_mode(cd)); + log_std(" keysize: %d bits\n", crypt_get_volume_key_size(cd) * 8); + log_std(" key location: %s\n", (cad.flags & CRYPT_ACTIVATE_KEYRING_KEY) ? "keyring" : "dm-crypt"); + } else if (hw_enc == CRYPT_OPAL_HW_ONLY) { + log_std(" encryption: HW OPAL only\n"); + log_std(" OPAL keysize: %d bits\n", crypt_get_hw_encryption_key_size(cd) * 8); + } else if (hw_enc == CRYPT_SW_AND_OPAL_HW) { + log_std(" encryption: dm-crypt over HW OPAL\n"); + log_std(" OPAL keysize: %d bits\n", crypt_get_hw_encryption_key_size(cd) * 8); + log_std(" cipher: %s-%s\n", crypt_get_cipher(cd), crypt_get_cipher_mode(cd)); + log_std(" keysize: %d bits\n", (crypt_get_volume_key_size(cd) - crypt_get_hw_encryption_key_size(cd)) * 8); + log_std(" key location: %s\n", (cad.flags & CRYPT_ACTIVATE_KEYRING_KEY) ? "keyring" : "dm-crypt"); + } + if (ip.integrity) log_std(" integrity: %s\n", ip.integrity); if (ip.integrity_key_size) log_std(" integrity keysize: %d bits\n", ip.integrity_key_size * 8); + if (ip.tag_size) + log_std(" integrity tag size: %u bytes\n", ip.tag_size); device = crypt_get_device_name(cd); log_std(" device: %s\n", device); if ((backing_file = crypt_loop_backing_file(device))) { @@ -1282,9 +1361,14 @@ static int action_luksRepair(void) goto out; } - r = tools_detect_signatures(action_argv[0], PRB_FILTER_LUKS, NULL, ARG_SET(OPT_BATCH_MODE_ID)); - if (r < 0) - goto out; + if (!ARG_SET(OPT_DISABLE_BLKID_ID)) { + r = tools_detect_signatures(action_argv[0], PRB_FILTER_LUKS, NULL, ARG_SET(OPT_BATCH_MODE_ID)); + if (r < 0) { + if (r == -EIO) + log_err(_("Blkid scan failed for %s."), action_argv[0]); + goto out; + } + } if (!ARG_SET(OPT_BATCH_MODE_ID) && !yesDialog(_("Really try to repair LUKS device header?"), @@ -1353,12 +1437,13 @@ static int strcmp_or_null(const char *str, const char *expected) int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_passwordLen) { - int r = -EINVAL, keysize, integrity_keysize = 0, fd, created = 0; + bool wipe_signatures = false; + int encrypt_type, r = -EINVAL, keysize, integrity_keysize = 0, fd, created = 0; struct stat st; const char *header_device, *type; char *msg = NULL, *key = NULL, *password = NULL; char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN], integrity[MAX_CIPHER_LEN]; - size_t passwordLen, signatures; + size_t passwordLen, signatures = 0; struct crypt_device *cd = NULL; struct crypt_params_luks1 params1 = { .hash = ARG_STR(OPT_HASH_ID) ?: DEFAULT_LUKS1_HASH, @@ -1372,6 +1457,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); @@ -1397,6 +1485,11 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password log_err(_("Unsupported LUKS2 metadata size options.")); return -EINVAL; } + + if (ARG_SET(OPT_HW_OPAL_ID) || ARG_SET(OPT_HW_OPAL_ONLY_ID)) { + log_err(_("OPAL is supported only for LUKS2 format.")); + return -EINVAL; + } } else return -EINVAL; @@ -1466,9 +1559,14 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password } /* Print all present signatures in read-only mode */ - r = tools_detect_signatures(header_device, PRB_FILTER_NONE, &signatures, ARG_SET(OPT_BATCH_MODE_ID)); - if (r < 0) - goto out; + if (!ARG_SET(OPT_DISABLE_BLKID_ID)) { + r = tools_detect_signatures(header_device, PRB_FILTER_NONE, &signatures, ARG_SET(OPT_BATCH_MODE_ID)); + if (r < 0) { + if (r == -EIO) + log_err(_("Blkid scan failed for %s."), header_device); + goto out; + } + } if (!created && !ARG_SET(OPT_BATCH_MODE_ID)) { r = asprintf(&msg, _("This will overwrite data on %s irrevocably."), header_device); @@ -1485,6 +1583,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)) @@ -1496,6 +1599,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) @@ -1509,13 +1625,20 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password } /* Signature candidates found */ - if (signatures && ((r = tools_wipe_all_signatures(header_device, true, false)) < 0)) + if (!ARG_SET(OPT_DISABLE_BLKID_ID) && signatures && + ((r = tools_wipe_all_signatures(header_device, true, false)) < 0)) goto out; 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) @@ -1529,25 +1652,44 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password key, keysize, password, passwordLen); if (r < 0) { - (void) tools_wipe_all_signatures(header_device, true, false); + wipe_signatures = true; goto out; } tools_keyslot_msg(r, CREATED); if (ARG_SET(OPT_INTEGRITY_ID) && !ARG_SET(OPT_INTEGRITY_NO_WIPE_ID) && - strcmp_or_null(params2.integrity, "none")) + strcmp_or_null(params2.integrity, "none")) { r = _wipe_data_device(cd); + /* Interrupted wipe should not fail luksFormat action */ + if (r == -EINTR) + r = 0; + } out: + crypt_safe_free(key); + + if (r < 0) { + encrypt_type = crypt_get_hw_encryption_type(cd); + if (encrypt_type == CRYPT_OPAL_HW_ONLY || + encrypt_type == CRYPT_SW_AND_OPAL_HW) { + (void) crypt_wipe_hw_opal(cd, CRYPT_LUKS2_SEGMENT, + opal_params.admin_key, opal_params.admin_key_size, + 0); + } + if (wipe_signatures) + (void) tools_wipe_all_signatures(header_device, true, false); + } + + crypt_safe_free(CONST_CAST(void *)opal_params.admin_key); + if (r >= 0 && r_cd && r_password && r_passwordLen) { *r_cd = cd; *r_password = password; *r_passwordLen = passwordLen; - } else { - crypt_free(cd); - crypt_safe_free(password); + return r; } - crypt_safe_free(key); + crypt_free(cd); + crypt_safe_free(password); return r; } @@ -1557,17 +1699,166 @@ static int action_luksFormat(void) return luksFormat(NULL, NULL, NULL); } +static int parse_vk_description(const char *key_description, char **ret_key_description) +{ + char *tmp; + int r; + + assert(key_description); + assert(ret_key_description); + + /* apply default key type */ + if (*key_description != '%') + r = asprintf(&tmp, "%%user:%s", key_description) < 0 ? -EINVAL : 0; + else + r = (tmp = strdup(key_description)) ? 0 : -ENOMEM; + if (!r) + *ret_key_description = tmp; + + return r; +} + +static int parse_single_vk_and_keyring_description( + struct crypt_device *cd, + char *keyring_key_description, char **keyring_part_out, char + **key_part_out, char **type_part_out) +{ + int r = -EINVAL; + char *endp, *sep, *key_part, *type_part = NULL; + char *key_part_copy = NULL, *type_part_copy = NULL, *keyring_part = NULL; + + if (!cd || !keyring_key_description) + return -EINVAL; + + /* "::" is separator between keyring specification a key description */ + key_part = strstr(keyring_key_description, "::"); + if (!key_part) + goto out; + + *key_part = '\0'; + key_part = key_part + 2; + + if (*key_part == '%') { + type_part = key_part + 1; + sep = strstr(type_part, ":"); + if (!sep) + goto out; + *sep = '\0'; + + key_part = sep + 1; + } + + if (*keyring_key_description == '%') { + keyring_key_description = strstr(keyring_key_description, ":"); + if (!keyring_key_description) + goto out; + log_verbose(_("Type specification in --link-vk-to-keyring keyring specification is ignored.")); + keyring_key_description++; + } + + (void)strtol(keyring_key_description, &endp, 0); + + r = 0; + if (*keyring_key_description == '@' || !*endp) + keyring_part = strdup(keyring_key_description); + else + r = asprintf(&keyring_part, "%%:%s", keyring_key_description); + + if (!keyring_part || r < 0) { + r = -ENOMEM; + goto out; + } + + if (!(key_part_copy = strdup(key_part))) { + r = -ENOMEM; + goto out; + } + if (type_part && !(type_part_copy = strdup(type_part))) + r = -ENOMEM; + +out: + if (r < 0) { + free(keyring_part); + free(key_part_copy); + free(type_part_copy); + } else { + *keyring_part_out = keyring_part; + *key_part_out = key_part_copy; + *type_part_out = type_part_copy; + } + + return r; +} + +static int parse_vk_and_keyring_description( + struct crypt_device *cd, + char **keyring_key_descriptions, + int keyring_key_links_count) +{ + int r = 0; + + char *keyring_part_out1 = NULL, *key_part_out1 = NULL, *type_part_out1 = NULL; + char *keyring_part_out2 = NULL, *key_part_out2 = NULL, *type_part_out2 = NULL; + + if (keyring_key_links_count > 0) { + r = parse_single_vk_and_keyring_description(cd, + keyring_key_descriptions[0], + &keyring_part_out1, &key_part_out1, + &type_part_out1); + if (r < 0) + goto out; + } + if (keyring_key_links_count > 1) { + r = parse_single_vk_and_keyring_description(cd, + keyring_key_descriptions[1], + &keyring_part_out2, &key_part_out2, + &type_part_out2); + if (r < 0) + goto out; + + if ((type_part_out1 && type_part_out2) && strcmp(type_part_out1, type_part_out2)) { + log_err(_("Key types have to be the same for both volume keys.")); + r = -EINVAL; + goto out; + } + if ((keyring_part_out1 && keyring_part_out2) && strcmp(keyring_part_out1, keyring_part_out2)) { + log_err(_("Both volume keys have to be linked to the same keyring.")); + r = -EINVAL; + goto out; + } + } + + if (keyring_key_links_count > 0) { + r = crypt_set_keyring_to_link(cd, key_part_out1, key_part_out2, + type_part_out1, keyring_part_out1); + if (r == -EAGAIN) + log_err(_("You need to supply more key names.")); + } +out: + if (r == -EINVAL) + log_err(_("Invalid --link-vk-to-keyring value.")); + free(keyring_part_out1); + free(key_part_out1); + free(type_part_out1); + free(keyring_part_out2); + free(key_part_out2); + free(type_part_out2); + + return r; +} + static int action_open_luks(void) { struct crypt_active_device cad; struct crypt_device *cd = NULL; const char *data_device, *header_device, *activated_name; - char *key = NULL; + char *key = NULL, *vk_description_activation1 = NULL, *vk_description_activation2 = NULL; uint32_t activate_flags = 0; int r, keysize, tries; char *password = NULL; size_t passwordLen; struct stat st; + struct crypt_keyslot_context *kc1 = NULL, *kc2 = NULL; if (ARG_SET(OPT_REFRESH_ID)) { activated_name = action_argc > 1 ? action_argv[1] : action_argv[0]; @@ -1606,6 +1897,21 @@ static int action_open_luks(void) set_activation_flags(&activate_flags); + if (ARG_SET(OPT_EXTERNAL_TOKENS_PATH_ID)) { + r = crypt_token_set_external_path(ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + if (r < 0) { + log_err(_("Failed to set external tokens path %s."), + ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + goto out; + } + } + + if (ARG_SET(OPT_LINK_VK_TO_KEYRING_ID)) { + r = parse_vk_and_keyring_description(cd, keyring_links, keyring_links_count); + if (r < 0) + goto out; + } + if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) { keysize = crypt_get_volume_key_size(cd); if (!keysize && !ARG_SET(OPT_KEY_SIZE_ID)) { @@ -1620,16 +1926,37 @@ static int action_open_luks(void) goto out; r = crypt_activate_by_volume_key(cd, activated_name, key, keysize, activate_flags); + } else if (ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) { + if (vks_in_keyring_count == 1) { + r = parse_vk_description(vks_in_keyring[0], &vk_description_activation1); + if (r < 0) + goto out; + r = crypt_keyslot_context_init_by_vk_in_keyring(cd, vk_description_activation1, &kc1); + if (r) + goto out; + r = crypt_activate_by_keyslot_context(cd, activated_name, CRYPT_ANY_SLOT, kc1, CRYPT_ANY_SLOT, NULL, activate_flags); + } else if (vks_in_keyring_count == 2) { + r = parse_vk_description(vks_in_keyring[0], &vk_description_activation1); + if (r < 0) + goto out; + r = parse_vk_description(vks_in_keyring[1], &vk_description_activation2); + if (r < 0) + goto out; + r = crypt_keyslot_context_init_by_vk_in_keyring(cd, vk_description_activation1, &kc1); + if (r) + goto out; + r = crypt_keyslot_context_init_by_vk_in_keyring(cd, vk_description_activation2, &kc2); + if (r) + goto out; + r = crypt_activate_by_keyslot_context(cd, activated_name, CRYPT_ANY_SLOT, kc1, CRYPT_ANY_SLOT, kc2, activate_flags); + } + if (r) + goto out; } else { - r = crypt_activate_by_token_pin(cd, activated_name, ARG_STR(OPT_TOKEN_TYPE_ID), - ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL, activate_flags); - tools_keyslot_msg(r, UNLOCKED); - tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), ARG_INT32(OPT_TOKEN_ID_ID), false); - - /* Token requires PIN. Ask if there is evident preference for tokens */ - if (r == -ENOANO && (ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) || - ARG_SET(OPT_TOKEN_ID_ID))) - r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), activated_name, ARG_STR(OPT_TOKEN_TYPE_ID), activate_flags, set_tries_tty(), true); + r = _try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID), + ARG_INT32(OPT_TOKEN_ID_ID), activated_name, + ARG_STR(OPT_TOKEN_TYPE_ID), activate_flags, + set_tries_tty(), true, ARG_SET(OPT_TOKEN_ONLY_ID)); if (r >= 0 || r == -EEXIST || quit || ARG_SET(OPT_TOKEN_ONLY_ID)) goto out; @@ -1657,9 +1984,14 @@ out: crypt_persistent_flags_set(cd, CRYPT_FLAGS_ACTIVATION, cad.flags & activate_flags))) log_err(_("Device activated but cannot make flags persistent.")); + crypt_keyslot_context_free(kc1); + crypt_keyslot_context_free(kc2); crypt_safe_free(key); crypt_safe_free(password); crypt_free(cd); + free(vk_description_activation1); + free(vk_description_activation2); + return r; } @@ -1839,6 +2171,15 @@ static int luksAddUnboundKey(void) goto out; } + if (ARG_SET(OPT_EXTERNAL_TOKENS_PATH_ID)) { + r = crypt_token_set_external_path(ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + if (r < 0) { + log_err(_("Failed to set external tokens path %s."), + ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + goto out; + } + } + r = _set_keyslot_encryption_params(cd); if (r < 0) goto out; @@ -1943,7 +2284,8 @@ static int action_luksAddKey(void) { int keyslot_old, keyslot_new, keysize = 0, r = -EINVAL; const char *new_key_file = (action_argc > 1 ? action_argv[1] : NULL); - char *key = NULL, *password = NULL, *password_new = NULL, *pin = NULL, *pin_new = NULL; + char *key = NULL, *password = NULL, *password_new = NULL, *pin = NULL, *pin_new = NULL, + *vk_description = NULL; size_t pin_size, pin_size_new, password_size = 0, password_new_size = 0; struct crypt_device *cd = NULL; struct crypt_keyslot_context *p_kc_new = NULL, *kc = NULL, *kc_new = NULL; @@ -1983,6 +2325,15 @@ static int action_luksAddKey(void) if (r < 0) goto out; + if (ARG_SET(OPT_EXTERNAL_TOKENS_PATH_ID)) { + r = crypt_token_set_external_path(ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + if (r < 0) { + log_err(_("Failed to set external tokens path %s."), + ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + goto out; + } + } + /* Never call pwquality if using null cipher */ if (crypt_is_cipher_null(crypt_get_cipher(cd))) ARG_SET_TRUE(OPT_FORCE_PASSWORD_ID); @@ -2019,7 +2370,11 @@ static int action_luksAddKey(void) ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_UINT64(OPT_KEYFILE_OFFSET_ID), &kc); - else if (ARG_SET(OPT_TOKEN_ID_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) || ARG_SET(OPT_TOKEN_ONLY_ID)) { + else if (ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) { + r = parse_vk_description(ARG_STR(OPT_VOLUME_KEY_KEYRING_ID), &vk_description); + if (!r) + r = crypt_keyslot_context_init_by_vk_in_keyring(cd, vk_description, &kc); + } else if (ARG_SET(OPT_TOKEN_ID_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) || ARG_SET(OPT_TOKEN_ONLY_ID)) { r = crypt_keyslot_context_init_by_token(cd, ARG_INT32(OPT_TOKEN_ID_ID), ARG_STR(OPT_TOKEN_TYPE_ID), @@ -2034,7 +2389,7 @@ static int action_luksAddKey(void) goto out; /* Check password before asking for new one */ - r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, + r = crypt_activate_by_passphrase(cd, NULL, keyslot_old, password, password_size, 0); check_signal(&r); tools_passphrase_msg(r); @@ -2107,6 +2462,7 @@ static int action_luksAddKey(void) } out: tools_keyslot_msg(r, CREATED); + free(vk_description); crypt_keyslot_context_free(kc); crypt_keyslot_context_free(kc_new); crypt_safe_free(password); @@ -2416,6 +2772,15 @@ static int action_luksDump(void) goto out; } + if (ARG_SET(OPT_EXTERNAL_TOKENS_PATH_ID)) { + r = crypt_token_set_external_path(ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + if (r < 0) { + log_err(_("Failed to set external tokens path %s."), + ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + goto out; + } + } + if (ARG_SET(OPT_DUMP_VOLUME_KEY_ID)) r = luksDump_with_volume_key(cd); else if (ARG_SET(OPT_UNBOUND_ID)) @@ -2448,11 +2813,12 @@ static int action_luksSuspend(void) static int action_luksResume(void) { struct crypt_device *cd = NULL; - char *password = NULL; + char *password = NULL, *vk_description_activation = NULL; size_t passwordLen; int r, tries; struct crypt_active_device cad; const char *req_type = luksType(device_type); + struct crypt_keyslot_context *kc = NULL; if (req_type && !isLUKS(req_type)) return -EINVAL; @@ -2460,7 +2826,14 @@ static int action_luksResume(void) if ((r = crypt_init_by_name_and_header(&cd, action_argv[0], uuid_or_device(ARG_STR(OPT_HEADER_ID))))) return r; + if (ARG_SET(OPT_LINK_VK_TO_KEYRING_ID)) { + r = parse_vk_and_keyring_description(cd, keyring_links, keyring_links_count); + if (r < 0) + goto out; + } + r = -EINVAL; + if (!isLUKS(crypt_get_type(cd))) { log_err(_("%s is not active LUKS device name or header is missing."), action_argv[0]); goto out; @@ -2481,20 +2854,34 @@ static int action_luksResume(void) goto out; } - /* try to resume LUKS2 device by token first */ - r = crypt_resume_by_token_pin(cd, action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID), - ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL); - tools_keyslot_msg(r, UNLOCKED); - tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), ARG_INT32(OPT_TOKEN_ID_ID), false); + if (ARG_SET(OPT_EXTERNAL_TOKENS_PATH_ID)) { + r = crypt_token_set_external_path(ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + if (r < 0) { + log_err(_("Failed to set external tokens path %s."), + ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + goto out; + } + } - /* Token requires PIN. Ask if there is evident preference for tokens */ - if (r == -ENOANO && (ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) || - ARG_SET(OPT_TOKEN_ID_ID))) - r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID), 0, set_tries_tty(), false); + /* try to resume LUKS2 device by token first */ + r = _try_token_unlock(cd, ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_TOKEN_ID_ID), + action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID), 0, + set_tries_tty(), false, ARG_SET(OPT_TOKEN_ONLY_ID)); if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID)) goto out; + if (ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) { + r = parse_vk_description(ARG_STR(OPT_VOLUME_KEY_KEYRING_ID), &vk_description_activation); + if (r < 0) + goto out; + r = crypt_keyslot_context_init_by_vk_in_keyring(cd, vk_description_activation, &kc); + if (r) + goto out; + r = crypt_resume_by_keyslot_context(cd, action_argv[0], CRYPT_ANY_SLOT, kc); + goto out; + } + tries = set_tries_tty(); do { r = tools_get_key(NULL, &password, &passwordLen, @@ -2513,7 +2900,9 @@ static int action_luksResume(void) password = NULL; } while ((r == -EPERM || r == -ERANGE) && (--tries > 0)); out: + crypt_keyslot_context_free(kc); crypt_safe_free(password); + free(vk_description_activation); crypt_free(cd); return r; } @@ -2642,15 +3031,48 @@ 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, ARG_UINT64(OPT_KEYFILE_OFFSET_ID), + ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID), + ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), + !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"))) { + crypt_safe_free(password); + return -EPERM; + } + + r = crypt_wipe_hw_opal(cd, factory_reset ? CRYPT_NO_SEGMENT : CRYPT_LUKS2_SEGMENT, + password, password_size, 0); + + crypt_safe_free(password); + return r; +} + 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)))) + if ((r = crypt_init_data_device(&cd, uuid_or_device(ARG_STR(OPT_HEADER_ID) ?: action_argv[0]), action_argv[0]))) + return r; + + /* 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."), @@ -2658,7 +3080,15 @@ static int action_luksErase(void) 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; @@ -2951,6 +3381,16 @@ static int action_token(void) return r; } + if (ARG_SET(OPT_EXTERNAL_TOKENS_PATH_ID)) { + r = crypt_token_set_external_path(ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + if (r < 0) { + log_err(_("Failed to set external tokens path %s."), + ARG_STR(OPT_EXTERNAL_TOKENS_PATH_ID)); + crypt_free(cd); + return r; + } + } + r = -EINVAL; if (!strcmp(action_argv[0], "add")) { @@ -3063,7 +3503,7 @@ static const char *verify_resize(void) static const char *verify_reencrypt(void) { if (ARG_SET(OPT_REDUCE_DEVICE_SIZE_ID) && ARG_SET(OPT_DEVICE_SIZE_ID)) - return _("Options --reduce-device-size and --data-size cannot be combined."); + return _("Options --reduce-device-size and --device-size cannot be combined."); if (isLUKS1(luksType(device_type)) && ARG_SET(OPT_ACTIVE_NAME_ID)) return _("Option --active-name can be set only for LUKS2 device."); @@ -3220,10 +3660,10 @@ static void help(poptContext popt_context, path = crypt_token_external_path(); if (path) { - log_std(_("\nLUKS2 external token plugin support is %s.\n"), _("compiled-in")); + log_std(_("\nLUKS2 external token plugin support is enabled.\n")); log_std(_("LUKS2 external token plugin path: %s.\n"), path); } else - log_std(_("\nLUKS2 external token plugin support is %s.\n"), _("disabled")); + log_std(_("\nLUKS2 external token plugin support is disabled.\n")); pbkdf_luks1 = crypt_get_pbkdf_default(CRYPT_LUKS1); pbkdf_luks2 = crypt_get_pbkdf_default(CRYPT_LUKS2); @@ -3315,6 +3755,7 @@ static void basic_options_cb(poptContext popt_context, const char *arg, void *data __attribute__((unused))) { + char buf[128]; tools_parse_arg_value(popt_context, tool_core_args[key->val].type, tool_core_args + key->val, arg, key->val, needs_size_conversion); /* special cases additional handling */ @@ -3366,6 +3807,29 @@ static void basic_options_cb(poptContext popt_context, _("Key size must be a multiple of 8 bits"), poptGetInvocationName(popt_context)); break; + case OPT_VOLUME_KEY_KEYRING_ID: + if (vks_in_keyring_count < MAX_VK_IN_KEYRING) + vks_in_keyring[vks_in_keyring_count++] = strdup(ARG_STR(OPT_VOLUME_KEY_KEYRING_ID)); + else { + if (snprintf(buf, sizeof(buf), _("At most %d volume key specifications can be supplied."), MAX_KEYRING_LINKS) < 0) + buf[0] = '\0'; + usage(popt_context, EXIT_FAILURE, + buf, + poptGetInvocationName(popt_context)); + } + break; + case OPT_LINK_VK_TO_KEYRING_ID: + if (keyring_links_count < MAX_KEYRING_LINKS) + keyring_links[keyring_links_count++] = strdup(ARG_STR(OPT_LINK_VK_TO_KEYRING_ID)); + else { + + if (snprintf(buf, sizeof(buf), _("At most %d keyring link specifications can be supplied."), MAX_KEYRING_LINKS) < 0) + buf[0] = '\0'; + usage(popt_context, EXIT_FAILURE, + buf, + poptGetInvocationName(popt_context)); + } + break; case OPT_REDUCE_DEVICE_SIZE_ID: if (ARG_UINT64(OPT_REDUCE_DEVICE_SIZE_ID) > 1024 * 1024 * 1024) usage(popt_context, EXIT_FAILURE, _("Maximum device reduce size is 1 GiB."), @@ -3439,6 +3903,9 @@ int main(int argc, const char **argv) textdomain(PACKAGE); popt_context = poptGetContext(PACKAGE, argc, argv, popt_options, 0); + if (!popt_context) + exit(EXIT_FAILURE); + poptSetOtherOptionHelp(popt_context, _("[OPTION...] <action> <action-specific>")); @@ -3506,7 +3973,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"; @@ -3562,6 +4032,11 @@ int main(int argc, const char **argv) _("PBKDF forced iterations cannot be combined with iteration time option."), poptGetInvocationName(popt_context)); + if (ARG_SET(OPT_DISABLE_KEYRING_ID) && ARG_SET(OPT_LINK_VK_TO_KEYRING_ID)) + usage(popt_context, EXIT_FAILURE, + _("Cannot link volume key to a keyring when keyring is disabled."), + poptGetInvocationName(popt_context)); + if (ARG_SET(OPT_DEBUG_ID) || ARG_SET(OPT_DEBUG_JSON_ID)) { crypt_set_debug_level(ARG_SET(OPT_DEBUG_JSON_ID)? CRYPT_DEBUG_JSON : CRYPT_DEBUG_ALL); dbg_version_and_cmd(argc, argv); diff --git a/src/cryptsetup.h b/src/cryptsetup.h index 011a669..8de8744 100644 --- a/src/cryptsetup.h +++ b/src/cryptsetup.h @@ -3,8 +3,8 @@ * * Copyright (C) 2004 Jana Saout <jana@saout.de> * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org> - * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2023 Milan Broz + * Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/cryptsetup_arg_list.h b/src/cryptsetup_arg_list.h index a7e5bb0..7496748 100644 --- a/src/cryptsetup_arg_list.h +++ b/src/cryptsetup_arg_list.h @@ -1,8 +1,8 @@ /* * Cryptsetup command line arguments list * - * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2020-2023 Ondrej Kozina + * Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2020-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -37,11 +37,13 @@ ARG(OPT_DEBUG, '\0', POPT_ARG_NONE, N_("Show debug messages"), NULL, CRYPT_ARG_B ARG(OPT_DEBUG_JSON, '\0', POPT_ARG_NONE, N_("Show debug messages including JSON metadata"), NULL, CRYPT_ARG_BOOL, {}, {}) +ARG(OPT_DECRYPT, '\0', POPT_ARG_NONE, N_("Decrypt LUKS2 device (remove encryption)"), NULL, CRYPT_ARG_BOOL, {}, {}) + ARG(OPT_DEFERRED, '\0', POPT_ARG_NONE, N_("Device removal is deferred until the last user closes it"), NULL, CRYPT_ARG_BOOL, {}, OPT_DEFERRED_ACTIONS) -ARG(OPT_DEVICE_SIZE, '\0', POPT_ARG_STRING, N_("Use only specified device size (ignore rest of device). DANGEROUS!"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_DEVICE_SIZE_ACTIONS) +ARG(OPT_DEVICE_SIZE, '\0', POPT_ARG_STRING, N_("Use only specified device size (ignore rest of device), DANGEROUS!"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_DEVICE_SIZE_ACTIONS) -ARG(OPT_DECRYPT, '\0', POPT_ARG_NONE, N_("Decrypt LUKS2 device (remove encryption)."), NULL, CRYPT_ARG_BOOL, {}, {}) +ARG(OPT_DISABLE_BLKID, '\0', POPT_ARG_NONE, N_("Disable blkid on-disk signature detection and wiping"), NULL, CRYPT_ARG_BOOL, {}, OPT_DISABLE_BLKID_ACTIONS) ARG(OPT_DISABLE_EXTERNAL_TOKENS, '\0', POPT_ARG_NONE, N_("Disable loading of external LUKS2 token plugins"), NULL, CRYPT_ARG_BOOL, {}, {}) @@ -55,11 +57,13 @@ ARG(OPT_DUMP_JSON, '\0', POPT_ARG_NONE, N_("Dump info in JSON format (LUKS2 only ARG(OPT_DUMP_VOLUME_KEY, '\0', POPT_ARG_NONE, N_("Dump volume key instead of keyslots info"), NULL, CRYPT_ARG_BOOL, {}, {}) -ARG(OPT_ENCRYPT, '\0', POPT_ARG_NONE, N_("Encrypt LUKS2 device (in-place encryption)."), NULL, CRYPT_ARG_BOOL, {}, {}) +ARG(OPT_ENCRYPT, '\0', POPT_ARG_NONE, N_("Encrypt LUKS2 device (in-place encryption)"), NULL, CRYPT_ARG_BOOL, {}, {}) + +ARG(OPT_EXTERNAL_TOKENS_PATH, '\0', POPT_ARG_STRING, N_("Path to directory with external token handlers (plugins)."), NULL, CRYPT_ARG_STRING, {}, OPT_EXTERNAL_TOKENS_PATH_ACTIONS) ARG(OPT_FORCE_PASSWORD, '\0', POPT_ARG_NONE, N_("Disable password quality check (if enabled)"), NULL, CRYPT_ARG_BOOL, {}, {}) -ARG(OPT_FORCE_OFFLINE_REENCRYPT, '\0', POPT_ARG_NONE, N_("Force offline LUKS2 reencryption and bypass active device detection."), NULL, CRYPT_ARG_BOOL, {}, OPT_FORCE_OFFLINE_REENCRYPT_ACTIONS) +ARG(OPT_FORCE_OFFLINE_REENCRYPT, '\0', POPT_ARG_NONE, N_("Force offline LUKS2 reencryption and bypass active device detection"), NULL, CRYPT_ARG_BOOL, {}, OPT_FORCE_OFFLINE_REENCRYPT_ACTIONS) ARG(OPT_HASH, 'h', POPT_ARG_STRING, N_("The hash used to create the encryption key from the passphrase"), NULL, CRYPT_ARG_STRING, {}, {}) @@ -67,9 +71,15 @@ ARG(OPT_HEADER, '\0', POPT_ARG_STRING, N_("Device or file with separated LUKS he ARG(OPT_HEADER_BACKUP_FILE, '\0', POPT_ARG_STRING, N_("File with LUKS header and keyslots backup"), NULL, CRYPT_ARG_STRING, {}, {}) -ARG(OPT_HOTZONE_SIZE, '\0', POPT_ARG_STRING, N_("Maximal reencryption hotzone size."), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_HOTZONE_SIZE_ACTIONS) +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, {}, OPT_HW_OPAL_ACTIONS) + +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_HW_OPAL_ONLY, '\0', POPT_ARG_NONE, N_("Use only HW OPAL encryption"), NULL, CRYPT_ARG_BOOL, {}, OPT_HW_OPAL_ONLY_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) @@ -85,7 +95,7 @@ ARG(OPT_IV_LARGE_SECTORS, '\0', POPT_ARG_NONE, N_("Use IV counted in sector size ARG(OPT_JSON_FILE, '\0', POPT_ARG_STRING, N_("Read or write the json from or to a file"), NULL, CRYPT_ARG_STRING, {}, {}) -ARG(OPT_KEEP_KEY, '\0', POPT_ARG_NONE, N_("Do not change volume key."), NULL, CRYPT_ARG_BOOL, {}, OPT_KEEP_KEY_ACTIONS) +ARG(OPT_KEEP_KEY, '\0', POPT_ARG_NONE, N_("Do not change volume key"), NULL, CRYPT_ARG_BOOL, {}, OPT_KEEP_KEY_ACTIONS) ARG(OPT_KEY_DESCRIPTION, '\0', POPT_ARG_STRING, N_("Key description"), NULL, CRYPT_ARG_STRING, {}, {}) @@ -105,20 +115,20 @@ ARG(OPT_KEYSLOT_KEY_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 keyslot: The size of ARG(OPT_LABEL, '\0', POPT_ARG_STRING, N_("Set label for the LUKS2 device"), NULL, CRYPT_ARG_STRING, {}, OPT_LABEL_ACTIONS) +ARG(OPT_LINK_VK_TO_KEYRING, '\0', POPT_ARG_STRING, N_("Set keyring where to link volume key"), NULL, CRYPT_ARG_STRING, {}, OPT_LINK_VK_TO_KEYRING_ACTIONS) + ARG(OPT_LUKS2_KEYSLOTS_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 header keyslots area size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_LUKS2_KEYSLOTS_SIZE_ACTIONS) ARG(OPT_LUKS2_METADATA_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 header metadata area size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_LUKS2_METADATA_SIZE_ACTIONS) -ARG(OPT_VOLUME_KEY_FILE, '\0', POPT_ARG_STRING, N_("Use the volume key from file."), NULL, CRYPT_ARG_STRING, {}, {}) - ARG(OPT_NEW_KEYFILE, '\0', POPT_ARG_STRING, N_("Read the key for a new slot from a file"), NULL, CRYPT_ARG_STRING, {}, OPT_NEW_KEYFILE_ACTIONS) -ARG(OPT_NEW_KEY_SLOT, '\0', POPT_ARG_STRING, N_("Slot number for new key (default is first free)"), "INT", CRYPT_ARG_INT32, { .i32_value = CRYPT_ANY_SLOT }, OPT_NEW_KEY_SLOT_ACTIONS) - ARG(OPT_NEW_KEYFILE_OFFSET , '\0', POPT_ARG_STRING, N_("Number of bytes to skip in newly added keyfile"), N_("bytes"), CRYPT_ARG_UINT64, {}, {}) ARG(OPT_NEW_KEYFILE_SIZE, '\0', POPT_ARG_STRING, N_("Limits the read from newly added keyfile"), N_("bytes"), CRYPT_ARG_UINT32, {}, {}) +ARG(OPT_NEW_KEY_SLOT, '\0', POPT_ARG_STRING, N_("Slot number for new key (default is first free)"), "INT", CRYPT_ARG_INT32, { .i32_value = CRYPT_ANY_SLOT }, OPT_NEW_KEY_SLOT_ACTIONS) + ARG(OPT_NEW_TOKEN_ID, '\0', POPT_ARG_STRING, N_("Token number (default: any)"), "INT", CRYPT_ARG_INT32, { .i32_value = CRYPT_ANY_TOKEN }, OPT_NEW_TOKEN_ID_ACTIONS) ARG(OPT_OFFSET, 'o', POPT_ARG_STRING, N_("The start offset in the backend device"), N_("SECTORS"), CRYPT_ARG_UINT64, {}, OPT_OFFSET_ACTIONS) @@ -149,7 +159,7 @@ ARG(OPT_PROGRESS_FREQUENCY, '\0', POPT_ARG_STRING, N_("Progress line update (in ARG(OPT_READONLY, 'r', POPT_ARG_NONE, N_("Create a readonly mapping"), NULL, CRYPT_ARG_BOOL, {}, {}) -ARG(OPT_REDUCE_DEVICE_SIZE, '\0', POPT_ARG_STRING, N_("Reduce data device size (move data offset). DANGEROUS!"), N_("bytes"), CRYPT_ARG_UINT64, {}, {}) +ARG(OPT_REDUCE_DEVICE_SIZE, '\0', POPT_ARG_STRING, N_("Reduce data device size (move data offset), DANGEROUS!"), N_("bytes"), CRYPT_ARG_UINT64, {}, {}) ARG(OPT_REFRESH, '\0', POPT_ARG_NONE, N_("Refresh (reactivate) device with new parameters"), NULL, CRYPT_ARG_BOOL, {}, OPT_REFRESH_ACTIONS) @@ -157,7 +167,7 @@ ARG(OPT_RESILIENCE, '\0', POPT_ARG_STRING, N_("Reencryption hotzone resilience t ARG(OPT_RESILIENCE_HASH, '\0', POPT_ARG_STRING, N_("Reencryption hotzone checksums hash"), NULL, CRYPT_ARG_STRING, {}, {}) -ARG(OPT_RESUME_ONLY, '\0', POPT_ARG_NONE, N_("Resume initialized LUKS2 reencryption only."), NULL, CRYPT_ARG_BOOL, {}, {}) +ARG(OPT_RESUME_ONLY, '\0', POPT_ARG_NONE, N_("Resume initialized LUKS2 reencryption only"), NULL, CRYPT_ARG_BOOL, {}, {}) ARG(OPT_SECTOR_SIZE, '\0', POPT_ARG_STRING, N_("Encryption sector size (default: 512 bytes)"), "INT", CRYPT_ARG_UINT32, {}, OPT_SECTOR_SIZE_ACTIONS) @@ -171,12 +181,6 @@ ARG(OPT_SKIP, 'p', POPT_ARG_STRING, N_("How many sectors of the encrypted data t ARG(OPT_SUBSYSTEM, '\0', POPT_ARG_STRING, N_("Set subsystem label for the LUKS2 device"), NULL, CRYPT_ARG_STRING, {}, OPT_SUBSYSTEM_ACTIONS) -ARG(OPT_TCRYPT_BACKUP, '\0', POPT_ARG_NONE, N_("Use backup (secondary) TCRYPT header"), NULL, CRYPT_ARG_BOOL, {}, OPT_TCRYPT_BACKUP_ACTIONS) - -ARG(OPT_TCRYPT_HIDDEN, '\0', POPT_ARG_NONE, N_("Use hidden header (hidden TCRYPT device)"), NULL, CRYPT_ARG_BOOL, {}, OPT_TCRYPT_HIDDEN_ACTIONS) - -ARG(OPT_TCRYPT_SYSTEM, '\0', POPT_ARG_NONE, N_("Device is system TCRYPT drive (with bootloader)"), NULL, CRYPT_ARG_BOOL, {}, OPT_TCRYPT_SYSTEM_ACTIONS) - ARG(OPT_TEST_ARGS, '\0', POPT_ARG_NONE, N_("Do not run action, just validate all command line parameters"), NULL, CRYPT_ARG_BOOL, {}, {}) ARG(OPT_TEST_PASSPHRASE, '\0', POPT_ARG_NONE, N_("Do not activate device, just check passphrase"), NULL, CRYPT_ARG_BOOL, {}, OPT_TEST_PASSPHRASE_ACTIONS) @@ -191,6 +195,12 @@ ARG(OPT_TOKEN_REPLACE, '\0', POPT_ARG_NONE, N_("Replace the current token"), NUL ARG(OPT_TOKEN_TYPE, '\0', POPT_ARG_STRING, N_("Restrict allowed token types used to retrieve LUKS2 key"), NULL, CRYPT_ARG_STRING, {}, {}) +ARG(OPT_TCRYPT_BACKUP, '\0', POPT_ARG_NONE, N_("Use backup (secondary) TCRYPT header"), NULL, CRYPT_ARG_BOOL, {}, OPT_TCRYPT_BACKUP_ACTIONS) + +ARG(OPT_TCRYPT_HIDDEN, '\0', POPT_ARG_NONE, N_("Use hidden header (hidden TCRYPT device)"), NULL, CRYPT_ARG_BOOL, {}, OPT_TCRYPT_HIDDEN_ACTIONS) + +ARG(OPT_TCRYPT_SYSTEM, '\0', POPT_ARG_NONE, N_("Device is system TCRYPT drive (with bootloader)"), NULL, CRYPT_ARG_BOOL, {}, OPT_TCRYPT_SYSTEM_ACTIONS) + ARG(OPT_TRIES, 'T', POPT_ARG_STRING, N_("How often the input of the passphrase can be retried"), "INT", CRYPT_ARG_UINT32, { .u32_value = 3 }, {}) ARG(OPT_TYPE, 'M', POPT_ARG_STRING, N_("Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"), NULL, CRYPT_ARG_STRING, {}, {}) @@ -213,6 +223,10 @@ ARG(OPT_VERBOSE, 'v', POPT_ARG_NONE, N_("Shows more detailed error messages"), N ARG(OPT_VERIFY_PASSPHRASE, 'y', POPT_ARG_NONE, N_("Verifies the passphrase by asking for it twice"), NULL, CRYPT_ARG_BOOL, {}, {}) +ARG(OPT_VOLUME_KEY_FILE, '\0', POPT_ARG_STRING, N_("Use the volume key from file"), NULL, CRYPT_ARG_STRING, {}, {}) + +ARG(OPT_VOLUME_KEY_KEYRING, '\0', POPT_ARG_STRING, N_("Use the specified keyring key as a volume key"), NULL, CRYPT_ARG_STRING, {}, {}) + /* added for reencryption */ ARG(OPT_BLOCK_SIZE, 'B', POPT_ARG_STRING, N_("Reencryption block size"), N_("MiB"), CRYPT_ARG_UINT32, { .u32_value = 4 }, {}) diff --git a/src/cryptsetup_args.h b/src/cryptsetup_args.h index 63604a3..5df9e1e 100644 --- a/src/cryptsetup_args.h +++ b/src/cryptsetup_args.h @@ -1,8 +1,8 @@ /* * Command line arguments helpers * - * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2020-2023 Ondrej Kozina + * Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2020-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,57 +25,64 @@ #include "utils_arg_names.h" #include "utils_arg_macros.h" +#define ADDKEY_ACTION "luksAddKey" #define BITLKDUMP_ACTION "bitlkDump" #define BENCHMARK_ACTION "benchmark" +#define CHANGEKEY_ACTION "luksChangeKey" #define CLOSE_ACTION "close" +#define CONVERTKEY_ACTION "luksConvertKey" #define CONFIG_ACTION "config" #define CONVERT_ACTION "convert" #define ERASE_ACTION "erase" -#define FVAULT2DUMP_ACTION "fvault2Dump" -#define ISLUKS_ACTION "isLuks" -#define ADDKEY_ACTION "luksAddKey" -#define CHANGEKEY_ACTION "luksChangeKey" -#define CONVERTKEY_ACTION "luksConvertKey" -#define LUKSDUMP_ACTION "luksDump" #define FORMAT_ACTION "luksFormat" +#define FVAULT2DUMP_ACTION "fvault2Dump" #define HEADERBACKUP_ACTION "luksHeaderBackup" #define HEADERRESTORE_ACTION "luksHeaderRestore" +#define ISLUKS_ACTION "isLuks" #define KILLKEY_ACTION "luksKillSlot" -#define REMOVEKEY_ACTION "luksRemoveKey" -#define RESUME_ACTION "luksResume" -#define SUSPEND_ACTION "luksSuspend" -#define UUID_ACTION "luksUUID" +#define LUKSDUMP_ACTION "luksDump" #define OPEN_ACTION "open" #define REENCRYPT_ACTION "reencrypt" +#define REMOVEKEY_ACTION "luksRemoveKey" #define REPAIR_ACTION "repair" #define RESIZE_ACTION "resize" +#define RESUME_ACTION "luksResume" #define STATUS_ACTION "status" +#define SUSPEND_ACTION "luksSuspend" #define TCRYPTDUMP_ACTION "tcryptDump" #define TOKEN_ACTION "token" +#define UUID_ACTION "luksUUID" /* avoid unshielded commas in ARG() macros later */ #define OPT_ALIGN_PAYLOAD_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION } #define OPT_ALLOW_DISCARDS_ACTIONS { OPEN_ACTION } #define OPT_DEFERRED_ACTIONS { CLOSE_ACTION } #define OPT_DEVICE_SIZE_ACTIONS { OPEN_ACTION, RESIZE_ACTION, REENCRYPT_ACTION } +#define OPT_DISABLE_BLKID_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION } #define OPT_DISABLE_VERACRYPT_ACTIONS { OPEN_ACTION, TCRYPTDUMP_ACTION } -#define OPT_HOTZONE_SIZE_ACTIONS { REENCRYPT_ACTION } +#define OPT_ERASE_ACTIONS { ERASE_ACTION } +#define OPT_EXTERNAL_TOKENS_PATH_ACTIONS { RESIZE_ACTION, OPEN_ACTION, ADDKEY_ACTION, LUKSDUMP_ACTION, RESUME_ACTION, TOKEN_ACTION } #define OPT_FORCE_OFFLINE_REENCRYPT_ACTIONS { REENCRYPT_ACTION } -#define OPT_INTEGRITY_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION } -#define OPT_INTEGRITY_NO_WIPE_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION } +#define OPT_HOTZONE_SIZE_ACTIONS { REENCRYPT_ACTION } +#define OPT_HW_OPAL_ACTIONS { FORMAT_ACTION } +#define OPT_HW_OPAL_ONLY_ACTIONS OPT_HW_OPAL_ACTIONS +#define OPT_INTEGRITY_ACTIONS { FORMAT_ACTION } +#define OPT_INTEGRITY_NO_WIPE_ACTIONS { FORMAT_ACTION } #define OPT_ITER_TIME_ACTIONS { BENCHMARK_ACTION, FORMAT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION, REENCRYPT_ACTION } #define OPT_IV_LARGE_SECTORS_ACTIONS { OPEN_ACTION } #define OPT_KEEP_KEY_ACTIONS { REENCRYPT_ACTION } +#define OPT_KEY_DESCRIPTION_ACTIONS { TOKEN_ACTION } #define OPT_KEY_SIZE_ACTIONS { OPEN_ACTION, BENCHMARK_ACTION, FORMAT_ACTION, REENCRYPT_ACTION, ADDKEY_ACTION } #define OPT_KEY_SLOT_ACTIONS { OPEN_ACTION, REENCRYPT_ACTION, CONFIG_ACTION, FORMAT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION, LUKSDUMP_ACTION, TOKEN_ACTION, RESUME_ACTION } #define OPT_KEYSLOT_CIPHER_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION } #define OPT_KEYSLOT_KEY_SIZE_ACTIONS OPT_KEYSLOT_CIPHER_ACTIONS -#define OPT_NEW_KEYFILE_ACTIONS { ADDKEY_ACTION } -#define OPT_NEW_KEY_SLOT_ACTIONS { ADDKEY_ACTION } -#define OPT_NEW_TOKEN_ID_ACTIONS { ADDKEY_ACTION } #define OPT_LABEL_ACTIONS { CONFIG_ACTION, FORMAT_ACTION, REENCRYPT_ACTION } +#define OPT_LINK_VK_TO_KEYRING_ACTIONS { OPEN_ACTION, RESUME_ACTION } #define OPT_LUKS2_KEYSLOTS_SIZE_ACTIONS { REENCRYPT_ACTION, FORMAT_ACTION } #define OPT_LUKS2_METADATA_SIZE_ACTIONS { REENCRYPT_ACTION, FORMAT_ACTION } +#define OPT_NEW_KEYFILE_ACTIONS { ADDKEY_ACTION } +#define OPT_NEW_KEY_SLOT_ACTIONS { ADDKEY_ACTION } +#define OPT_NEW_TOKEN_ID_ACTIONS { ADDKEY_ACTION } #define OPT_OFFSET_ACTIONS { OPEN_ACTION, REENCRYPT_ACTION, FORMAT_ACTION } #define OPT_PBKDF_ACTIONS { BENCHMARK_ACTION, FORMAT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION, REENCRYPT_ACTION } #define OPT_PBKDF_FORCE_ITERATIONS_ACTIONS { FORMAT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION, REENCRYPT_ACTION } diff --git a/src/integritysetup.c b/src/integritysetup.c index eee6171..0e5d70f 100644 --- a/src/integritysetup.c +++ b/src/integritysetup.c @@ -1,8 +1,8 @@ /* * integritysetup - setup integrity protected volumes for dm-integrity * - * Copyright (C) 2017-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2017-2023 Milan Broz + * Copyright (C) 2017-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2017-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -190,13 +190,18 @@ static int action_format(void) goto out; } - r = tools_detect_signatures(action_argv[0], PRB_FILTER_NONE, &signatures, ARG_SET(OPT_BATCH_MODE_ID)); - if (r < 0) - goto out; + if (!ARG_SET(OPT_DISABLE_BLKID_ID)) { + r = tools_detect_signatures(action_argv[0], PRB_FILTER_NONE, &signatures, ARG_SET(OPT_BATCH_MODE_ID)); + if (r < 0) { + if (r == -EIO) + log_err(_("Blkid scan failed for %s."), action_argv[0]); + goto out; + } - /* Signature candidates found */ - if (signatures && ((r = tools_wipe_all_signatures(action_argv[0], true, false)) < 0)) - goto out; + /* Signature candidates found */ + if (signatures && ((r = tools_wipe_all_signatures(action_argv[0], true, false)) < 0)) + goto out; + } if (ARG_SET(OPT_INTEGRITY_LEGACY_PADDING_ID)) crypt_set_compatibility(cd, CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING); @@ -212,8 +217,12 @@ static int action_format(void) log_std(_("Formatted with tag size %u, internal integrity %s.\n"), params2.tag_size, params2.integrity); - if (!ARG_SET(OPT_NO_WIPE_ID)) + if (!ARG_SET(OPT_NO_WIPE_ID)) { r = _wipe_data_device(cd, integrity_key); + /* Interrupted wipe should not fail format action */ + if (r == -EINTR) + r = 0; + } out: crypt_safe_free(integrity_key); crypt_safe_free(CONST_CAST(void*)params.journal_integrity_key); @@ -660,6 +669,9 @@ int main(int argc, const char **argv) textdomain(PACKAGE); popt_context = poptGetContext("integrity", argc, argv, popt_options, 0); + if (!popt_context) + exit(EXIT_FAILURE); + poptSetOtherOptionHelp(popt_context, _("[OPTION...] <action> <action-specific>")); diff --git a/src/integritysetup_arg_list.h b/src/integritysetup_arg_list.h index 39f2906..083184b 100644 --- a/src/integritysetup_arg_list.h +++ b/src/integritysetup_arg_list.h @@ -1,8 +1,8 @@ /* * Integritysetup command line arguments list * - * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2020-2023 Ondrej Kozina + * Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2020-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -29,7 +29,7 @@ ARG(OPT_BUFFER_SECTORS, '\0', POPT_ARG_STRING, N_("Buffers size"), N_("SECTORS") ARG(OPT_BITMAP_FLUSH_TIME, '\0', POPT_ARG_STRING, N_("Bitmap mode flush time"), N_("ms"), CRYPT_ARG_UINT32, {}, {}) -ARG(OPT_BITMAP_SECTORS_PER_BIT, '\0', POPT_ARG_STRING, N_("Number of 512-byte sectors per bit (bitmap mode)."), "INT", CRYPT_ARG_UINT32, {}, {}) +ARG(OPT_BITMAP_SECTORS_PER_BIT, '\0', POPT_ARG_STRING, N_("Number of 512-byte sectors per bit (bitmap mode)"), "INT", CRYPT_ARG_UINT32, {}, {}) ARG(OPT_CANCEL_DEFERRED, '\0', POPT_ARG_NONE, N_("Cancel a previously set deferred device removal"), NULL, CRYPT_ARG_BOOL, {}, OPT_DEFERRED_ACTIONS) @@ -39,8 +39,14 @@ ARG(OPT_DEBUG, '\0', POPT_ARG_NONE, N_("Show debug messages"), NULL, CRYPT_ARG_B ARG(OPT_DEFERRED, '\0', POPT_ARG_NONE, N_("Device removal is deferred until the last user closes it"), NULL, CRYPT_ARG_BOOL, {}, OPT_DEFERRED_ACTIONS) +ARG(OPT_DEVICE_SIZE, '\0', POPT_ARG_STRING, N_("Use only specified device size (ignore rest of device), DANGEROUS!"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_DEVICE_SIZE_ACTIONS) + +ARG(OPT_DISABLE_BLKID, '\0', POPT_ARG_NONE, N_("Disable blkid on-disk signature detection and wiping"), NULL, CRYPT_ARG_BOOL, {}, OPT_DISABLE_BLKID_ACTIONS) + ARG(OPT_INTEGRITY, 'I', POPT_ARG_STRING, N_("Data integrity algorithm"), NULL, CRYPT_ARG_STRING, { .str_value = CONST_CAST(void *)DEFAULT_ALG_NAME }, {}) +ARG(OPT_INTEGRITY_BITMAP_MODE, 'B', POPT_ARG_NONE, N_("Use bitmap to track changes and disable journal for integrity device"), NULL, CRYPT_ARG_BOOL, {}, {}) + ARG(OPT_INTEGRITY_KEY_FILE, '\0', POPT_ARG_STRING, N_("Read the integrity key from a file"), NULL, CRYPT_ARG_STRING, {}, {}) ARG(OPT_INTEGRITY_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the data integrity key"), N_("BITS"), CRYPT_ARG_UINT32, {}, {}) @@ -53,6 +59,12 @@ ARG(OPT_INTEGRITY_LEGACY_RECALC, '\0', POPT_ARG_NONE, N_("Allow recalculating of ARG(OPT_INTEGRITY_NO_JOURNAL, 'D', POPT_ARG_NONE, N_("Disable journal for integrity device"), NULL, CRYPT_ARG_BOOL, {}, {}) +ARG(OPT_INTEGRITY_RECALCULATE, '\0', POPT_ARG_NONE, N_("Recalculate initial tags automatically"), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS) + +ARG(OPT_INTEGRITY_RECALCULATE_RESET, '\0', POPT_ARG_NONE, N_("Reset automatic recalculate position"), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS) + +ARG(OPT_INTEGRITY_RECOVERY_MODE, 'R', POPT_ARG_NONE, N_("Recovery mode (no journal, no tag checking)"), NULL, CRYPT_ARG_BOOL, {}, {}) + ARG(OPT_INTERLEAVE_SECTORS, '\0', POPT_ARG_STRING, N_("Interleave sectors"), N_("SECTORS"), CRYPT_ARG_UINT32, {}, OPT_INTERLEAVE_SECTORS_ACTIONS) ARG(OPT_JOURNAL_COMMIT_TIME, '\0', POPT_ARG_STRING, N_("Journal commit time"), N_("ms"), CRYPT_ARG_UINT32, {}, {}) @@ -75,26 +87,16 @@ ARG(OPT_JOURNAL_WATERMARK, '\0', POPT_ARG_STRING, N_("Journal watermark"), N_("p ARG(OPT_NO_WIPE, '\0', POPT_ARG_NONE, N_("Do not wipe device after format"), NULL, CRYPT_ARG_BOOL, {}, OPT_NO_WIPE_ACTIONS) -ARG(OPT_WIPE, '\0', POPT_ARG_NONE, N_("Wipe the end of the device after resize"), NULL, CRYPT_ARG_BOOL, {}, OPT_WIPE_ACTIONS) - ARG(OPT_PROGRESS_FREQUENCY, '\0', POPT_ARG_STRING, N_("Progress line update (in seconds)"), N_("secs"), CRYPT_ARG_UINT32, {}, {}) ARG(OPT_PROGRESS_JSON, '\0', POPT_ARG_NONE, N_("Print wipe progress data in json format (suitable for machine processing)"), NULL, CRYPT_ARG_BOOL, {}, OPT_PROGRESS_JSON_ACTIONS) -ARG(OPT_INTEGRITY_BITMAP_MODE, 'B', POPT_ARG_NONE, N_("Use bitmap to track changes and disable journal for integrity device"), NULL, CRYPT_ARG_BOOL, {}, {}) - -ARG(OPT_INTEGRITY_RECALCULATE, '\0', POPT_ARG_NONE, N_("Recalculate initial tags automatically."), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS) - -ARG(OPT_INTEGRITY_RECALCULATE_RESET, '\0', POPT_ARG_NONE, N_("Reset automatic recalculate position."), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS) - -ARG(OPT_INTEGRITY_RECOVERY_MODE, 'R', POPT_ARG_NONE, N_("Recovery mode (no journal, no tag checking)"), NULL, CRYPT_ARG_BOOL, {}, {}) - ARG(OPT_SECTOR_SIZE, 's', POPT_ARG_STRING, N_("Sector size"), N_("bytes"), CRYPT_ARG_UINT32, { .u32_value = 512 }, OPT_SECTOR_SIZE_ACTIONS) +ARG(OPT_SIZE, 'b', POPT_ARG_STRING, N_("The size of the device"), N_("SECTORS"), CRYPT_ARG_UINT64, {}, OPT_SIZE_ACTIONS) + ARG(OPT_TAG_SIZE, 't', POPT_ARG_STRING, N_("Tag size (per-sector)"), N_("bytes"), CRYPT_ARG_UINT32, {}, OPT_TAG_SIZE_ACTIONS) ARG(OPT_VERBOSE, 'v', POPT_ARG_NONE, N_("Shows more detailed error messages"), NULL, CRYPT_ARG_BOOL, {}, {}) -ARG(OPT_DEVICE_SIZE, '\0', POPT_ARG_STRING, N_("Use only specified device size (ignore rest of device). DANGEROUS!"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_DEVICE_SIZE_ACTIONS) - -ARG(OPT_SIZE, 'b', POPT_ARG_STRING, N_("The size of the device"), N_("SECTORS"), CRYPT_ARG_UINT64, {}, OPT_SIZE_ACTIONS) +ARG(OPT_WIPE, '\0', POPT_ARG_NONE, N_("Wipe the end of the device after resize"), NULL, CRYPT_ARG_BOOL, {}, OPT_WIPE_ACTIONS) diff --git a/src/integritysetup_args.h b/src/integritysetup_args.h index 8241008..5595a84 100644 --- a/src/integritysetup_args.h +++ b/src/integritysetup_args.h @@ -1,8 +1,8 @@ /* * Command line arguments helpers * - * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2020-2023 Ondrej Kozina + * Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2020-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,24 +25,25 @@ #include "utils_arg_names.h" #include "utils_arg_macros.h" +#define DUMP_ACTION "dump" #define FORMAT_ACTION "format" -#define OPEN_ACTION "open" #define CLOSE_ACTION "close" -#define STATUS_ACTION "status" -#define DUMP_ACTION "dump" +#define OPEN_ACTION "open" #define RESIZE_ACTION "resize" +#define STATUS_ACTION "status" #define OPT_ALLOW_DISCARDS_ACTIONS { OPEN_ACTION } #define OPT_DEFERRED_ACTIONS { CLOSE_ACTION } +#define OPT_DEVICE_SIZE_ACTIONS { RESIZE_ACTION } +#define OPT_DISABLE_BLKID_ACTIONS { FORMAT_ACTION } #define OPT_INTEGRITY_RECALCULATE_ACTIONS { OPEN_ACTION } +#define OPT_INTERLEAVE_SECTORS_ACTIONS { FORMAT_ACTION } #define OPT_JOURNAL_SIZE_ACTIONS { FORMAT_ACTION } #define OPT_NO_WIPE_ACTIONS { FORMAT_ACTION } -#define OPT_INTERLEAVE_SECTORS_ACTIONS { FORMAT_ACTION } #define OPT_PROGRESS_JSON_ACTIONS { FORMAT_ACTION, RESIZE_ACTION } #define OPT_SECTOR_SIZE_ACTIONS { FORMAT_ACTION } -#define OPT_TAG_SIZE_ACTIONS { FORMAT_ACTION } -#define OPT_DEVICE_SIZE_ACTIONS { RESIZE_ACTION } #define OPT_SIZE_ACTIONS { RESIZE_ACTION } +#define OPT_TAG_SIZE_ACTIONS { FORMAT_ACTION } #define OPT_WIPE_ACTIONS { RESIZE_ACTION } enum { diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..3fd1ff5 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,77 @@ +src_build_dir = meson.current_build_dir() + +if get_option('cryptsetup') + cryptsetup_files = files( + 'cryptsetup.c', + 'utils_args.c', + 'utils_blockdev.c', + 'utils_luks.c', + 'utils_password.c', + 'utils_progress.c', + 'utils_reencrypt.c', + 'utils_reencrypt_luks1.c', + 'utils_tools.c', + ) + cryptsetup_files += lib_tools_files + cryptsetup_deps = [ + popt, + pwquality, + passwdqc, + uuid, + blkid, + ] + cryptsetup = executable('cryptsetup', + cryptsetup_files, + dependencies: cryptsetup_deps, + link_with: libcryptsetup, + link_args: link_args, + include_directories: includes_tools) +endif + +if get_option('veritysetup') + veritysetup_files = files( + 'utils_args.c', + 'utils_tools.c', + 'veritysetup.c', + ) + veritysetup_files += lib_tools_files + veritysetup_deps = [ + popt, + blkid, + ] + + veritysetup = executable('veritysetup', + veritysetup_files, + dependencies: veritysetup_deps, + link_with: libcryptsetup, + link_args: link_args, + include_directories: includes_tools) +endif + +if get_option('integritysetup') + integritysetup_files = files( + 'integritysetup.c', + 'utils_args.c', + 'utils_blockdev.c', + 'utils_progress.c', + 'utils_tools.c', + ) + integritysetup_files += lib_tools_files + integritysetup_deps = [ + popt, + uuid, + blkid, + ] + + integritysetup = executable('integritysetup', + integritysetup_files, + dependencies: integritysetup_deps, + link_with: libcryptsetup, + link_args: link_args, + include_directories: includes_tools) +endif + +src_ssh_token_files = files( + 'utils_password.c', + 'utils_tools.c', +) diff --git a/src/utils_arg_macros.h b/src/utils_arg_macros.h index 901b3f4..eba0eca 100644 --- a/src/utils_arg_macros.h +++ b/src/utils_arg_macros.h @@ -1,8 +1,8 @@ /* * Command line arguments parsing helpers * - * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2020-2023 Ondrej Kozina + * Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2020-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/utils_arg_names.h b/src/utils_arg_names.h index 66a59e8..4ec5510 100644 --- a/src/utils_arg_names.h +++ b/src/utils_arg_names.h @@ -1,8 +1,8 @@ /* * Command line arguments name list * - * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2020-2023 Ondrej Kozina + * Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2020-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -41,6 +41,7 @@ #define OPT_DEFERRED "deferred" #define OPT_DEVICE_SIZE "device-size" #define OPT_DECRYPT "decrypt" +#define OPT_DISABLE_BLKID "disable-blkid" #define OPT_DISABLE_EXTERNAL_TOKENS "disable-external-tokens" #define OPT_DISABLE_KEYRING "disable-keyring" #define OPT_DISABLE_LOCKS "disable-locks" @@ -49,6 +50,7 @@ #define OPT_DUMP_MASTER_KEY "dump-master-key" #define OPT_DUMP_VOLUME_KEY "dump-volume-key" #define OPT_ENCRYPT "encrypt" +#define OPT_EXTERNAL_TOKENS_PATH "external-tokens-path" #define OPT_FEC_DEVICE "fec-device" #define OPT_FEC_OFFSET "fec-offset" #define OPT_FEC_ROOTS "fec-roots" @@ -61,6 +63,9 @@ #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_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" @@ -102,10 +107,12 @@ #define OPT_NO_WIPE "no-wipe" #define OPT_WIPE "wipe" #define OPT_LABEL "label" +#define OPT_LINK_VK_TO_KEYRING "link-vk-to-keyring" #define OPT_LUKS2_KEYSLOTS_SIZE "luks2-keyslots-size" #define OPT_LUKS2_METADATA_SIZE "luks2-metadata-size" #define OPT_MASTER_KEY_FILE "master-key-file" #define OPT_VOLUME_KEY_FILE "volume-key-file" +#define OPT_VOLUME_KEY_KEYRING "volume-key-keyring" #define OPT_NEW "new" #define OPT_NEW_KEY_SLOT "new-key-slot" #define OPT_NEW_KEYFILE "new-keyfile" diff --git a/src/utils_args.c b/src/utils_args.c index fda2350..47be0c3 100644 --- a/src/utils_args.c +++ b/src/utils_args.c @@ -1,8 +1,8 @@ /* * Command line arguments parsing helpers * - * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2020-2023 Ondrej Kozina + * Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2020-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/utils_blockdev.c b/src/utils_blockdev.c index ae6dec4..c797cf4 100644 --- a/src/utils_blockdev.c +++ b/src/utils_blockdev.c @@ -1,8 +1,8 @@ /* * Linux block devices helpers * - * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2018-2023 Ondrej Kozina + * Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2018-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -222,17 +222,22 @@ int tools_detect_signatures(const char *device, tools_probe_filter_info filter, switch (filter) { case PRB_FILTER_LUKS: + log_dbg("Blkid check (filter LUKS)."); if (blk_superblocks_filter_luks(h)) { r = -EINVAL; + log_dbg("Blkid filter LUKS probe failed."); goto out; } /* fall-through */ case PRB_FILTER_NONE: + log_dbg("Blkid check (filter none)."); blk_set_chains_for_full_print(h); break; case PRB_ONLY_LUKS: + log_dbg("Blkid check (LUKS only)."); blk_set_chains_for_fast_detection(h); if (blk_superblocks_only_luks(h)) { + log_dbg("Blkid only LUKS probe failed."); r = -EINVAL; goto out; } @@ -251,8 +256,11 @@ int tools_detect_signatures(const char *device, tools_probe_filter_info filter, (*count)++; } - if (pr == PRB_FAIL) - r = -EINVAL; + if (pr == PRB_FAIL) { + /* Expect device cannot be read */ + r = -EIO; + log_dbg("Blkid probe failed."); + } out: blk_free(h); return r; @@ -302,6 +310,8 @@ int tools_wipe_all_signatures(const char *path, bool exclusive, bool only_luks) goto out; } + log_dbg("Blkid wipe."); + while ((pr = blk_probe(h)) < PRB_EMPTY) { if (blk_is_partition(h)) log_verbose(_("Existing '%s' partition signature on device %s will be wiped."), diff --git a/src/utils_luks.c b/src/utils_luks.c index 6a10ab6..5007b3f 100644 --- a/src/utils_luks.c +++ b/src/utils_luks.c @@ -1,9 +1,9 @@ /* * Helper utilities for LUKS2 features * - * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2018-2023 Milan Broz - * Copyright (C) 2018-2023 Ondrej Kozina + * Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2018-2024 Milan Broz + * Copyright (C) 2018-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -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) diff --git a/src/utils_luks.h b/src/utils_luks.h index 28220ab..6183b26 100644 --- a/src/utils_luks.h +++ b/src/utils_luks.h @@ -1,9 +1,9 @@ /* * Helper utilities for LUKS in cryptsetup * - * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2018-2023 Milan Broz - * Copyright (C) 2018-2023 Ondrej Kozina + * Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2018-2024 Milan Broz + * Copyright (C) 2018-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/utils_password.c b/src/utils_password.c index 3374e18..70da4b0 100644 --- a/src/utils_password.c +++ b/src/utils_password.c @@ -1,8 +1,8 @@ /* * Password quality check wrapper * - * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2023 Milan Broz + * Copyright (C) 2012-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -98,6 +98,7 @@ static int tools_check_password(const char *password) #elif defined ENABLE_PASSWDQC return tools_check_passwdqc(password); #else + UNUSED(password); return 0; #endif } diff --git a/src/utils_progress.c b/src/utils_progress.c index 76b1818..3105bed 100644 --- a/src/utils_progress.c +++ b/src/utils_progress.c @@ -1,8 +1,8 @@ /* * cryptsetup - progress output utilities * - * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2023 Milan Broz + * Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/utils_reencrypt.c b/src/utils_reencrypt.c index a78557c..7546811 100644 --- a/src/utils_reencrypt.c +++ b/src/utils_reencrypt.c @@ -1,9 +1,9 @@ /* * cryptsetup - action re-encryption utilities * - * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2023 Milan Broz - * Copyright (C) 2021-2023 Ondrej Kozina + * Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2024 Milan Broz + * Copyright (C) 2021-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -306,7 +306,7 @@ static int reencrypt_luks2_load(struct crypt_device *cd, const char *data_device if (!ARG_SET(OPT_BATCH_MODE_ID) && !ARG_SET(OPT_RESUME_ONLY_ID)) { r = asprintf(&msg, _("Device %s is already in LUKS2 reencryption. " "Do you wish to resume previously initialised operation?"), - crypt_get_metadata_device_name(cd) ?: data_device); + crypt_get_metadata_device_name(cd) ?: crypt_get_device_name(cd)); if (r < 0) { r = -ENOMEM; goto out; @@ -349,11 +349,6 @@ static int luks2_reencrypt_in_progress(struct crypt_device *cd) if (crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &flags)) return -EINVAL; - if (flags & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT) { - log_err(_("Legacy LUKS2 reencryption is no longer supported.")); - return -EINVAL; - } - return flags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT; } @@ -411,14 +406,34 @@ static enum device_status_info load_luks(struct crypt_device **r_cd, static bool luks2_reencrypt_eligible(struct crypt_device *cd) { + uint32_t flags; struct crypt_params_integrity ip = { 0 }; + if (crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &flags)) + return false; + + if (flags & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT) { + log_err(_("Legacy LUKS2 reencryption is no longer supported.")); + return false; + } + + if (flags & CRYPT_REQUIREMENT_OPAL) { + log_err(_("Can not reencrypt LUKS2 device configured to use OPAL.")); + return false; + } + /* raw integrity info is available since 2.0 */ if (crypt_get_integrity_info(cd, &ip) || ip.tag_size) { log_err(_("Reencryption of device with integrity profile is not supported.")); return false; } + /* Check that cipher is in compatible format */ + if (!crypt_get_cipher(cd)) { + log_err(_("No known cipher specification pattern detected in LUKS2 header.")); + return false; + } + return true; } @@ -1322,9 +1337,15 @@ static int check_broken_luks_signature(const char *device) int r; size_t count; + if (ARG_SET(OPT_DISABLE_BLKID_ID)) + return 0; + r = tools_detect_signatures(device, PRB_ONLY_LUKS, &count, ARG_SET(OPT_BATCH_MODE_ID)); - if (r < 0) + if (r < 0) { + if (r == -EIO) + log_err(_("Blkid scan failed for %s."), device); return -EINVAL; + } if (count) { log_err(_("Device %s contains broken LUKS metadata. Aborting operation."), device); return -EINVAL; @@ -1449,6 +1470,8 @@ static int _decrypt(struct crypt_device **cd, enum device_status_info dev_st, co if ((r = reencrypt_luks2_load(*cd, data_device)) < 0) return r; } else if (dev_st == DEVICE_LUKS2) { + if (!luks2_reencrypt_eligible(*cd)) + return -EINVAL; if (!ARG_SET(OPT_HEADER_ID)) { log_err(_("LUKS2 decryption requires --header option.")); return -EINVAL; diff --git a/src/utils_reencrypt_luks1.c b/src/utils_reencrypt_luks1.c index ae849c0..1e36ad9 100644 --- a/src/utils_reencrypt_luks1.c +++ b/src/utils_reencrypt_luks1.c @@ -1,8 +1,8 @@ /* * cryptsetup - LUKS1 utility for offline re-encryption * - * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2023 Milan Broz + * Copyright (C) 2012-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/utils_tools.c b/src/utils_tools.c index a0e2ebc..5cfd9e6 100644 --- a/src/utils_tools.c +++ b/src/utils_tools.c @@ -3,8 +3,8 @@ * * Copyright (C) 2004 Jana Saout <jana@saout.de> * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org> - * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2009-2023 Milan Broz + * Copyright (C) 2009-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2009-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -435,8 +435,9 @@ int tools_write_mk(const char *file, const char *key, int keysize) void tools_package_version(const char *name, bool use_pwlibs) { - bool udev = false, blkid = false, keyring = false, fips = false; - bool kernel_capi = false, pwquality = false, passwdqc = false; + bool udev = false, blkid = false, keyring = false, fips = false, + kernel_capi = false, pwquality = false, passwdqc = false, + hw_opal = false; #ifdef USE_UDEV udev = true; #endif @@ -457,12 +458,16 @@ void tools_package_version(const char *name, bool use_pwlibs) #elif defined(ENABLE_PASSWDQC) passwdqc = true; #endif - log_std("%s %s flags: %s%s%s%s%s%s%s\n", name, PACKAGE_VERSION, +#ifdef HAVE_HW_OPAL + hw_opal = true; +#endif + log_std("%s %s flags: %s%s%s%s%s%s%s%s\n", name, PACKAGE_VERSION, udev ? "UDEV " : "", blkid ? "BLKID " : "", keyring ? "KEYRING " : "", fips ? "FIPS " : "", kernel_capi ? "KERNEL_CAPI " : "", pwquality && use_pwlibs ? "PWQUALITY " : "", - passwdqc && use_pwlibs ? "PASSWDQC " : ""); + passwdqc && use_pwlibs ? "PASSWDQC " : "", + hw_opal ? "HW_OPAL " : ""); } diff --git a/src/veritysetup.c b/src/veritysetup.c index 8be81cc..3fd90fc 100644 --- a/src/veritysetup.c +++ b/src/veritysetup.c @@ -1,8 +1,8 @@ /* * veritysetup - setup cryptographic volumes for dm-verity * - * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2012-2023 Milan Broz + * Copyright (C) 2012-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2012-2024 Milan Broz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -599,6 +599,9 @@ int main(int argc, const char **argv) textdomain(PACKAGE); popt_context = poptGetContext("verity", argc, argv, popt_options, 0); + if (!popt_context) + exit(EXIT_FAILURE); + poptSetOtherOptionHelp(popt_context, _("[OPTION...] <action> <action-specific>")); diff --git a/src/veritysetup_arg_list.h b/src/veritysetup_arg_list.h index 014273e..34002f3 100644 --- a/src/veritysetup_arg_list.h +++ b/src/veritysetup_arg_list.h @@ -1,8 +1,8 @@ /* * Veritysetup command line arguments list * - * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2020-2023 Ondrej Kozina + * Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2020-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/veritysetup_args.h b/src/veritysetup_args.h index d47813d..43f4a23 100644 --- a/src/veritysetup_args.h +++ b/src/veritysetup_args.h @@ -1,8 +1,8 @@ /* * Command line arguments helpers * - * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved. - * Copyright (C) 2020-2023 Ondrej Kozina + * Copyright (C) 2020-2024 Red Hat, Inc. All rights reserved. + * Copyright (C) 2020-2024 Ondrej Kozina * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -35,8 +35,8 @@ #define OPT_DEFERRED_ACTIONS { CLOSE_ACTION } #define OPT_IGNORE_CORRUPTION_ACTIONS { OPEN_ACTION } #define OPT_IGNORE_ZERO_BLOCKS_ACTIONS { OPEN_ACTION } -#define OPT_RESTART_ON_CORRUPTION_ACTIONS { OPEN_ACTION } #define OPT_PANIC_ON_CORRUPTION_ACTIONS { OPEN_ACTION } +#define OPT_RESTART_ON_CORRUPTION_ACTIONS { OPEN_ACTION } #define OPT_ROOT_HASH_FILE_ACTIONS { FORMAT_ACTION, OPEN_ACTION, VERIFY_ACTION } #define OPT_ROOT_HASH_SIGNATURE_ACTIONS { OPEN_ACTION } #define OPT_USE_TASKLETS_ACTIONS { OPEN_ACTION } |