mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Provide routine for setting LUKS2 requirement with version.
This commit is contained in:
@@ -405,6 +405,7 @@ int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint3
|
||||
*/
|
||||
int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *reqs);
|
||||
int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs, bool commit);
|
||||
int LUKS2_config_set_requirement_version(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id, uint32_t req_version, bool commit);
|
||||
|
||||
int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint32_t *version);
|
||||
|
||||
|
||||
@@ -1659,6 +1659,94 @@ err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static json_object *LUKS2_get_mandatory_requirements_filtered_jobj(struct luks2_hdr *hdr,
|
||||
uint32_t filter_req_ids)
|
||||
{
|
||||
int i, len;
|
||||
const struct requirement_flag *req;
|
||||
json_object *jobj_mandatory, *jobj_mandatory_filtered, *jobj;
|
||||
|
||||
jobj_mandatory_filtered = json_object_new_array();
|
||||
if (!jobj_mandatory_filtered)
|
||||
return NULL;
|
||||
|
||||
jobj_mandatory = mandatory_requirements_jobj(hdr);
|
||||
if (!jobj_mandatory)
|
||||
return jobj_mandatory_filtered;
|
||||
|
||||
len = (int) json_object_array_length(jobj_mandatory);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
jobj = json_object_array_get_idx(jobj_mandatory, i);
|
||||
req = get_requirement_by_name(json_object_get_string(jobj));
|
||||
if (req->flag == CRYPT_REQUIREMENT_UNKNOWN || req->flag & filter_req_ids)
|
||||
continue;
|
||||
json_object_array_add(jobj_mandatory_filtered,
|
||||
json_object_new_string(req->description));
|
||||
}
|
||||
|
||||
return jobj_mandatory_filtered;
|
||||
}
|
||||
|
||||
/*
|
||||
* The function looks for specific version of requirement id.
|
||||
* If it can't be fulfilled function fails.
|
||||
*/
|
||||
int LUKS2_config_set_requirement_version(struct crypt_device *cd,
|
||||
struct luks2_hdr *hdr,
|
||||
uint32_t req_id,
|
||||
uint32_t req_version,
|
||||
bool commit)
|
||||
{
|
||||
json_object *jobj_config, *jobj_requirements, *jobj_mandatory;
|
||||
const struct requirement_flag *req;
|
||||
int r = -EINVAL;
|
||||
|
||||
if (!hdr || req_id == CRYPT_REQUIREMENT_UNKNOWN)
|
||||
return -EINVAL;
|
||||
|
||||
req = requirements_flags;
|
||||
|
||||
while (req->description) {
|
||||
/* we have a match */
|
||||
if (req->flag == req_id && req->version == req_version)
|
||||
break;
|
||||
req++;
|
||||
}
|
||||
|
||||
if (!req->description)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Creates copy of mandatory requirements set without specific requirement
|
||||
* (no matter the version) we want to set.
|
||||
*/
|
||||
jobj_mandatory = LUKS2_get_mandatory_requirements_filtered_jobj(hdr, req_id);
|
||||
if (!jobj_mandatory)
|
||||
return -ENOMEM;
|
||||
|
||||
json_object_array_add(jobj_mandatory, json_object_new_string(req->description));
|
||||
|
||||
if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
|
||||
goto err;
|
||||
|
||||
if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements)) {
|
||||
jobj_requirements = json_object_new_object();
|
||||
if (!jobj_requirements) {
|
||||
r = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
json_object_object_add(jobj_config, "requirements", jobj_requirements);
|
||||
}
|
||||
|
||||
json_object_object_add(jobj_requirements, "mandatory", jobj_mandatory);
|
||||
|
||||
return commit ? LUKS2_hdr_write(cd, hdr) : 0;
|
||||
err:
|
||||
json_object_put(jobj_mandatory);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Header dump
|
||||
*/
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "luks2_internal.h"
|
||||
#include "utils_device_locking.h"
|
||||
|
||||
#define LUKS2_REENCRYPT_REQ_VERSION 2
|
||||
|
||||
struct luks2_reencrypt {
|
||||
/* reencryption window attributes */
|
||||
uint64_t offset;
|
||||
@@ -1201,7 +1203,8 @@ static int modify_offset(uint64_t *offset, uint64_t data_shift, crypt_reencrypt_
|
||||
return r;
|
||||
}
|
||||
|
||||
static int reencrypt_update_flag(struct crypt_device *cd, int enable, bool commit)
|
||||
static int reencrypt_update_flag(struct crypt_device *cd, uint32_t version,
|
||||
bool enable, bool commit)
|
||||
{
|
||||
uint32_t reqs;
|
||||
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
|
||||
@@ -1217,12 +1220,14 @@ static int reencrypt_update_flag(struct crypt_device *cd, int enable, bool commi
|
||||
if (!enable && !(reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT))
|
||||
return -EINVAL;
|
||||
|
||||
if (enable)
|
||||
reqs |= CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
|
||||
else
|
||||
reqs &= ~CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
|
||||
if (enable) {
|
||||
log_dbg(cd, "Going to store reencryption requirement flag (version: %u).", version);
|
||||
return LUKS2_config_set_requirement_version(cd, hdr, CRYPT_REQUIREMENT_ONLINE_REENCRYPT, version, commit);
|
||||
}
|
||||
|
||||
log_dbg(cd, "Going to %s reencryption requirement flag.", enable ? "store" : "wipe");
|
||||
reqs &= ~CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
|
||||
|
||||
log_dbg(cd, "Going to wipe reencryption requirement flag.");
|
||||
|
||||
return LUKS2_config_set_requirements(cd, hdr, reqs, commit);
|
||||
}
|
||||
@@ -2516,7 +2521,7 @@ static int reencrypt_init(struct crypt_device *cd,
|
||||
}
|
||||
|
||||
/* This must be first and only write in LUKS2 metadata during _reencrypt_init */
|
||||
r = reencrypt_update_flag(cd, 1, true);
|
||||
r = reencrypt_update_flag(cd, LUKS2_REENCRYPT_REQ_VERSION, true, true);
|
||||
if (r) {
|
||||
log_dbg(cd, "Failed to set online-reencryption requirement.");
|
||||
r = -EINVAL;
|
||||
@@ -3072,11 +3077,11 @@ static int reencrypt_repair_by_passphrase(
|
||||
goto out;
|
||||
|
||||
/* removes online-reencrypt flag v1 */
|
||||
if ((r = reencrypt_update_flag(cd, 0, false)))
|
||||
if ((r = reencrypt_update_flag(cd, 0, false, false)))
|
||||
goto out;
|
||||
|
||||
/* adds online-reencrypt flag v2 and commits metadata */
|
||||
r = reencrypt_update_flag(cd, 1, true);
|
||||
r = reencrypt_update_flag(cd, LUKS2_REENCRYPT_REQ_VERSION, true, true);
|
||||
out:
|
||||
LUKS2_reencrypt_unlock(cd, reencrypt_lock);
|
||||
crypt_free_volume_key(vks);
|
||||
@@ -3406,7 +3411,7 @@ static int reencrypt_teardown_ok(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||||
if (reencrypt_erase_backup_segments(cd, hdr))
|
||||
log_dbg(cd, "Failed to erase backup segments");
|
||||
|
||||
if (reencrypt_update_flag(cd, 0, false))
|
||||
if (reencrypt_update_flag(cd, 0, false, false))
|
||||
log_dbg(cd, "Failed to disable reencryption requirement flag.");
|
||||
|
||||
/* metadata commit point also removing reencryption flag on-disk */
|
||||
|
||||
Reference in New Issue
Block a user