mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-11 10:50:01 +01:00
Add segments validation for reencryption.
Effective segments during LUKS2 reencryption must match key characteristics of backup segment (cipher, sector_size, segment type).
This commit is contained in:
committed by
Milan Broz
parent
7420f879e0
commit
b61ec23e48
@@ -263,6 +263,7 @@ uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned b
|
|||||||
json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption);
|
json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption);
|
||||||
json_object *json_segment_create_crypt(uint64_t offset, uint64_t iv_offset, const uint64_t *length, const char *cipher, uint32_t sector_size, unsigned reencryption);
|
json_object *json_segment_create_crypt(uint64_t offset, uint64_t iv_offset, const uint64_t *length, const char *cipher, uint32_t sector_size, unsigned reencryption);
|
||||||
int json_segments_segment_in_reencrypt(json_object *jobj_segments);
|
int json_segments_segment_in_reencrypt(json_object *jobj_segments);
|
||||||
|
bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2);
|
||||||
bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len);
|
bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len);
|
||||||
|
|
||||||
int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd,
|
int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd,
|
||||||
|
|||||||
@@ -607,6 +607,63 @@ static int reqs_reencrypt_online(uint32_t reqs)
|
|||||||
return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
|
return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Config section requirements object must be valid.
|
||||||
|
* Also general segments section must be validated first.
|
||||||
|
*/
|
||||||
|
static int validate_reencrypt_segments(struct crypt_device *cd, json_object *hdr_jobj, json_object *jobj_segments, int first_backup, int segments_count)
|
||||||
|
{
|
||||||
|
json_object *jobj, *jobj_backup_previous = NULL, *jobj_backup_final = NULL;
|
||||||
|
uint32_t reqs;
|
||||||
|
int i, r;
|
||||||
|
struct luks2_hdr dummy = {
|
||||||
|
.jobj = hdr_jobj
|
||||||
|
};
|
||||||
|
|
||||||
|
r = LUKS2_config_get_requirements(cd, &dummy, &reqs);
|
||||||
|
if (r)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (reqs_reencrypt_online(reqs)) {
|
||||||
|
for (i = first_backup; i < segments_count; i++) {
|
||||||
|
jobj = json_segments_get_segment(jobj_segments, i);
|
||||||
|
if (!jobj)
|
||||||
|
return 1;
|
||||||
|
if (json_segment_contains_flag(jobj, "backup-final", 0))
|
||||||
|
jobj_backup_final = jobj;
|
||||||
|
else if (json_segment_contains_flag(jobj, "backup-previous", 0))
|
||||||
|
jobj_backup_previous = jobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jobj_backup_final || !jobj_backup_previous) {
|
||||||
|
log_dbg(cd, "Backup segment is missing.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < first_backup; i++) {
|
||||||
|
jobj = json_segments_get_segment(jobj_segments, i);
|
||||||
|
if (!jobj)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (json_segment_contains_flag(jobj, "in-reencryption", 0)) {
|
||||||
|
if (!json_segment_cmp(jobj, jobj_backup_final)) {
|
||||||
|
log_dbg(cd, "Segment in reencryption does not match backup final segment.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_segment_cmp(jobj, jobj_backup_final) &&
|
||||||
|
!json_segment_cmp(jobj, jobj_backup_previous)) {
|
||||||
|
log_dbg(cd, "Segment does not match neither backup final or backup previous segment.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
|
static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
|
||||||
{
|
{
|
||||||
json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type, *jobj_flags, *jobj;
|
json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type, *jobj_flags, *jobj;
|
||||||
@@ -733,7 +790,7 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return validate_reencrypt_segments(cd, hdr_jobj, jobj_segments, first_backup, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t LUKS2_metadata_size_jobj(json_object *jobj)
|
static uint64_t LUKS2_metadata_size_jobj(json_object *jobj)
|
||||||
|
|||||||
@@ -410,3 +410,23 @@ json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag)
|
|||||||
|
|
||||||
return jobj_segment;
|
return jobj_segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* compares key characteristics of both segments */
|
||||||
|
bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2)
|
||||||
|
{
|
||||||
|
const char *type = json_segment_type(jobj_segment_1);
|
||||||
|
const char *type2 = json_segment_type(jobj_segment_2);
|
||||||
|
|
||||||
|
if (!type || !type2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (strcmp(type, type2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!strcmp(type, "crypt"))
|
||||||
|
return (json_segment_get_sector_size(jobj_segment_1) == json_segment_get_sector_size(jobj_segment_2) &&
|
||||||
|
!strcmp(json_segment_get_cipher(jobj_segment_1),
|
||||||
|
json_segment_get_cipher(jobj_segment_2)));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user