diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 4192aa7b..fd5cacf6 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -980,12 +980,64 @@ static int set_pbkdf_params(struct crypt_device *cd, const char *dev_type) return crypt_set_pbkdf_type(cd, &pbkdf); } +static int _do_luks2_reencrypt_recovery(struct crypt_device *cd) +{ + int r; + size_t passwordLen; + char *password = NULL; + struct crypt_params_reencrypt recovery_params = { + .flags = CRYPT_REENCRYPT_RECOVERY + }; + + crypt_reencrypt_info ri = crypt_reencrypt_status(cd, NULL); + switch (ri) { + case CRYPT_REENCRYPT_NONE: + /* fall through */ + case CRYPT_REENCRYPT_CLEAN: + r = noDialog(_("Seems device does not require reencryption recovery.\n" + "Do you want to proceed anyway?"), NULL); + if (!r) + return 0; + break; + case CRYPT_REENCRYPT_CRASH: + r = yesDialog(_("Really proceed with LUKS2 reencryption recovery?"), + _("Operation aborted.\n")); + if (!r) + return -EINVAL; + break; + default: + return -EINVAL; + } + + r = tools_get_key(_("Enter passphrase for reencryption recovery: "), + &password, &passwordLen, opt_keyfile_offset, + opt_keyfile_size, opt_key_file, opt_timeout, + _verify_passphrase(0), 0, cd); + if (r < 0) + return r; + + r = crypt_activate_by_passphrase(cd, NULL, opt_key_slot, + password, passwordLen, 0); + if (r < 0) + goto out; + + r = crypt_reencrypt_init_by_passphrase(cd, NULL, password, passwordLen, + opt_key_slot, opt_key_slot, NULL, NULL, &recovery_params); + if (r > 0) + r = 0; +out: + crypt_safe_free(password); + + return r; +} + static int action_luksRepair(void) { struct crypt_device *cd = NULL; int r; - if ((r = crypt_init(&cd, action_argv[0]))) + if ((r = crypt_init_data_device(&cd, opt_header_device ?: action_argv[0], + action_argv[0]))) goto out; crypt_set_log_callback(cd, quiet_log, NULL); @@ -993,7 +1045,7 @@ static int action_luksRepair(void) crypt_set_log_callback(cd, tool_log, NULL); if (r == 0) { log_verbose(_("No known problems detected for LUKS header.")); - goto out; + goto skip_repair; } r = tools_detect_signatures(action_argv[0], 1, NULL); @@ -1004,6 +1056,9 @@ static int action_luksRepair(void) _("Operation aborted.\n")) ? 0 : -EINVAL; if (r == 0) r = crypt_repair(cd, luksType(opt_type), NULL); +skip_repair: + if (!r && crypt_get_type(cd) && !strcmp(crypt_get_type(cd), CRYPT_LUKS2)) + r = _do_luks2_reencrypt_recovery(cd); out: crypt_free(cd); return r;