mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-15 12:50:06 +01:00
Add empty string check to LUKS2 JSON validation.
Most of the LUKS2 fields cannot be empty, add check for JSON validation for it to fail early. Fixes: #746
This commit is contained in:
@@ -75,6 +75,8 @@ void JSON_DBG(struct crypt_device *cd, json_object *jobj, const char *desc);
|
||||
json_bool validate_json_uint32(json_object *jobj);
|
||||
json_object *json_contains(struct crypt_device *cd, json_object *jobj, const char *name,
|
||||
const char *section, const char *key, json_type type);
|
||||
json_object *json_contains_string(struct crypt_device *cd, json_object *jobj,
|
||||
const char *name, const char *section, const char *key);
|
||||
|
||||
int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t json_size);
|
||||
int LUKS2_check_json_size(struct crypt_device *cd, const struct luks2_hdr *hdr);
|
||||
|
||||
@@ -292,6 +292,20 @@ json_object *json_contains(struct crypt_device *cd, json_object *jobj, const cha
|
||||
return sobj;
|
||||
}
|
||||
|
||||
json_object *json_contains_string(struct crypt_device *cd, json_object *jobj,
|
||||
const char *name, const char *section, const char *key)
|
||||
{
|
||||
json_object *sobj = json_contains(cd, jobj, name, section, key, json_type_string);
|
||||
|
||||
if (!sobj)
|
||||
return NULL;
|
||||
|
||||
if (strlen(json_object_get_string(sobj)) < 1)
|
||||
return NULL;
|
||||
|
||||
return sobj;
|
||||
}
|
||||
|
||||
json_bool validate_json_uint32(json_object *jobj)
|
||||
{
|
||||
int64_t tmp;
|
||||
@@ -406,7 +420,7 @@ static int LUKS2_keyslot_validate(struct crypt_device *cd, json_object *hdr_keys
|
||||
{
|
||||
json_object *jobj_key_size;
|
||||
|
||||
if (!json_contains(cd, hdr_keyslot, key, "Keyslot", "type", json_type_string))
|
||||
if (!json_contains_string(cd, hdr_keyslot, key, "Keyslot", "type"))
|
||||
return 1;
|
||||
if (!(jobj_key_size = json_contains(cd, hdr_keyslot, key, "Keyslot", "key_size", json_type_int)))
|
||||
return 1;
|
||||
@@ -430,7 +444,7 @@ int LUKS2_token_validate(struct crypt_device *cd,
|
||||
if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
|
||||
return 1;
|
||||
|
||||
if (!json_contains(cd, jobj_token, key, "Token", "type", json_type_string))
|
||||
if (!json_contains_string(cd, jobj_token, key, "Token", "type"))
|
||||
return 1;
|
||||
|
||||
jarr = json_contains(cd, jobj_token, key, "Token", "keyslots", json_type_array);
|
||||
@@ -518,17 +532,17 @@ static int hdr_validate_crypt_segment(struct crypt_device *cd, json_object *jobj
|
||||
uint32_t sector_size;
|
||||
uint64_t ivoffset;
|
||||
|
||||
if (!(jobj_ivoffset = json_contains(cd, jobj, key, "Segment", "iv_tweak", json_type_string)) ||
|
||||
!json_contains(cd, jobj, key, "Segment", "encryption", json_type_string) ||
|
||||
if (!(jobj_ivoffset = json_contains_string(cd, jobj, key, "Segment", "iv_tweak")) ||
|
||||
!json_contains_string(cd, jobj, key, "Segment", "encryption") ||
|
||||
!(jobj_sector_size = json_contains(cd, jobj, key, "Segment", "sector_size", json_type_int)))
|
||||
return 1;
|
||||
|
||||
/* integrity */
|
||||
if (json_object_object_get_ex(jobj, "integrity", &jobj_integrity)) {
|
||||
if (!json_contains(cd, jobj, key, "Segment", "integrity", json_type_object) ||
|
||||
!json_contains(cd, jobj_integrity, key, "Segment integrity", "type", json_type_string) ||
|
||||
!json_contains(cd, jobj_integrity, key, "Segment integrity", "journal_encryption", json_type_string) ||
|
||||
!json_contains(cd, jobj_integrity, key, "Segment integrity", "journal_integrity", json_type_string))
|
||||
!json_contains_string(cd, jobj_integrity, key, "Segment integrity", "type") ||
|
||||
!json_contains_string(cd, jobj_integrity, key, "Segment integrity", "journal_encryption") ||
|
||||
!json_contains_string(cd, jobj_integrity, key, "Segment integrity", "journal_integrity"))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -689,9 +703,9 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
|
||||
return 1;
|
||||
|
||||
/* those fields are mandatory for all segment types */
|
||||
if (!(jobj_type = json_contains(cd, val, key, "Segment", "type", json_type_string)) ||
|
||||
!(jobj_offset = json_contains(cd, val, key, "Segment", "offset", json_type_string)) ||
|
||||
!(jobj_size = json_contains(cd, val, key, "Segment", "size", json_type_string)))
|
||||
if (!(jobj_type = json_contains_string(cd, val, key, "Segment", "type")) ||
|
||||
!(jobj_offset = json_contains_string(cd, val, key, "Segment", "offset")) ||
|
||||
!(jobj_size = json_contains_string(cd, val, key, "Segment", "size")))
|
||||
return 1;
|
||||
|
||||
if (!numbered(cd, "offset", json_object_get_string(jobj_offset)) ||
|
||||
@@ -845,9 +859,9 @@ static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj)
|
||||
json_object_object_foreach(jobj_keyslots, key, val) {
|
||||
|
||||
if (!(jobj_area = json_contains(cd, val, key, "Keyslot", "area", json_type_object)) ||
|
||||
!json_contains(cd, jobj_area, key, "Keyslot area", "type", json_type_string) ||
|
||||
!(jobj_offset = json_contains(cd, jobj_area, key, "Keyslot", "offset", json_type_string)) ||
|
||||
!(jobj_length = json_contains(cd, jobj_area, key, "Keyslot", "size", json_type_string)) ||
|
||||
!json_contains_string(cd, jobj_area, key, "Keyslot area", "type") ||
|
||||
!(jobj_offset = json_contains_string(cd, jobj_area, key, "Keyslot", "offset")) ||
|
||||
!(jobj_length = json_contains_string(cd, jobj_area, key, "Keyslot", "size")) ||
|
||||
!numbered(cd, "offset", json_object_get_string(jobj_offset)) ||
|
||||
!numbered(cd, "size", json_object_get_string(jobj_length))) {
|
||||
free(intervals);
|
||||
@@ -895,7 +909,7 @@ static int hdr_validate_digests(struct crypt_device *cd, json_object *hdr_jobj)
|
||||
if (!numbered(cd, "Digest", key))
|
||||
return 1;
|
||||
|
||||
if (!json_contains(cd, val, key, "Digest", "type", json_type_string) ||
|
||||
if (!json_contains_string(cd, val, key, "Digest", "type") ||
|
||||
!(jarr_keys = json_contains(cd, val, key, "Digest", "keyslots", json_type_array)) ||
|
||||
!(jarr_segs = json_contains(cd, val, key, "Digest", "segments", json_type_array)))
|
||||
return 1;
|
||||
@@ -919,7 +933,7 @@ static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
|
||||
if (!(jobj_config = json_contains(cd, hdr_jobj, "", "JSON area", "config", json_type_object)))
|
||||
return 1;
|
||||
|
||||
if (!(jobj = json_contains(cd, jobj_config, "section", "Config", "json_size", json_type_string)) ||
|
||||
if (!(jobj = json_contains_string(cd, jobj_config, "section", "Config", "json_size")) ||
|
||||
!json_str_to_uint64(jobj, &metadata_size))
|
||||
return 1;
|
||||
|
||||
@@ -927,7 +941,7 @@ static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
|
||||
* binary header size */
|
||||
metadata_size += LUKS2_HDR_BIN_LEN;
|
||||
|
||||
if (!(jobj = json_contains(cd, jobj_config, "section", "Config", "keyslots_size", json_type_string)) ||
|
||||
if (!(jobj = json_contains_string(cd, jobj_config, "section", "Config", "keyslots_size")) ||
|
||||
!json_str_to_uint64(jobj, &keyslots_size))
|
||||
return 1;
|
||||
|
||||
|
||||
@@ -680,49 +680,49 @@ static int luks2_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
|
||||
|
||||
count = json_object_object_length(jobj_kdf);
|
||||
|
||||
jobj1 = json_contains(cd, jobj_kdf, "", "kdf section", "type", json_type_string);
|
||||
jobj1 = json_contains_string(cd, jobj_kdf, "", "kdf section", "type");
|
||||
if (!jobj1)
|
||||
return -EINVAL;
|
||||
type = json_object_get_string(jobj1);
|
||||
|
||||
if (!strcmp(type, CRYPT_KDF_PBKDF2)) {
|
||||
if (count != 4 || /* type, salt, hash, iterations only */
|
||||
!json_contains(cd, jobj_kdf, "kdf type", type, "hash", json_type_string) ||
|
||||
!json_contains_string(cd, jobj_kdf, "kdf type", type, "hash") ||
|
||||
!json_contains(cd, jobj_kdf, "kdf type", type, "iterations", json_type_int) ||
|
||||
!json_contains(cd, jobj_kdf, "kdf type", type, "salt", json_type_string))
|
||||
!json_contains_string(cd, jobj_kdf, "kdf type", type, "salt"))
|
||||
return -EINVAL;
|
||||
} else if (!strcmp(type, CRYPT_KDF_ARGON2I) || !strcmp(type, CRYPT_KDF_ARGON2ID)) {
|
||||
if (count != 5 || /* type, salt, time, memory, cpus only */
|
||||
!json_contains(cd, jobj_kdf, "kdf type", type, "time", json_type_int) ||
|
||||
!json_contains(cd, jobj_kdf, "kdf type", type, "memory", json_type_int) ||
|
||||
!json_contains(cd, jobj_kdf, "kdf type", type, "cpus", json_type_int) ||
|
||||
!json_contains(cd, jobj_kdf, "kdf type", type, "salt", json_type_string))
|
||||
!json_contains_string(cd, jobj_kdf, "kdf type", type, "salt"))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
jobj1 = json_contains(cd, jobj_af, "", "af section", "type", json_type_string);
|
||||
jobj1 = json_contains_string(cd, jobj_af, "", "af section", "type");
|
||||
if (!jobj1)
|
||||
return -EINVAL;
|
||||
type = json_object_get_string(jobj1);
|
||||
|
||||
if (!strcmp(type, "luks1")) {
|
||||
if (!json_contains(cd, jobj_af, "", "luks1 af", "hash", json_type_string) ||
|
||||
if (!json_contains_string(cd, jobj_af, "", "luks1 af", "hash") ||
|
||||
!json_contains(cd, jobj_af, "", "luks1 af", "stripes", json_type_int))
|
||||
return -EINVAL;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
// FIXME check numbered
|
||||
jobj1 = json_contains(cd, jobj_area, "", "area section", "type", json_type_string);
|
||||
jobj1 = json_contains_string(cd, jobj_area, "", "area section", "type");
|
||||
if (!jobj1)
|
||||
return -EINVAL;
|
||||
type = json_object_get_string(jobj1);
|
||||
|
||||
if (!strcmp(type, "raw")) {
|
||||
if (!json_contains(cd, jobj_area, "area", "raw type", "encryption", json_type_string) ||
|
||||
if (!json_contains_string(cd, jobj_area, "area", "raw type", "encryption") ||
|
||||
!json_contains(cd, jobj_area, "area", "raw type", "key_size", json_type_int) ||
|
||||
!json_contains(cd, jobj_area, "area", "raw type", "offset", json_type_string) ||
|
||||
!json_contains(cd, jobj_area, "area", "raw type", "size", json_type_string))
|
||||
!json_contains_string(cd, jobj_area, "area", "raw type", "offset") ||
|
||||
!json_contains_string(cd, jobj_area, "area", "raw type", "size"))
|
||||
return -EINVAL;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
@@ -310,8 +310,8 @@ static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
|
||||
return -EINVAL;
|
||||
|
||||
jobj_key_size = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "key_size", json_type_int);
|
||||
jobj_mode = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "mode", json_type_string);
|
||||
jobj_direction = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "direction", json_type_string);
|
||||
jobj_mode = json_contains_string(cd, jobj_keyslot, "", "reencrypt keyslot", "mode");
|
||||
jobj_direction = json_contains_string(cd, jobj_keyslot, "", "reencrypt keyslot", "direction");
|
||||
|
||||
if (!jobj_mode || !jobj_direction || !jobj_key_size)
|
||||
return -EINVAL;
|
||||
@@ -337,8 +337,8 @@ static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
|
||||
}
|
||||
|
||||
if (!strcmp(type, "checksum") || !strcmp(type, "datashift-checksum")) {
|
||||
jobj_hash = json_contains(cd, jobj_area, "type:checksum",
|
||||
"Keyslot area", "hash", json_type_string);
|
||||
jobj_hash = json_contains_string(cd, jobj_area, "type:checksum",
|
||||
"Keyslot area", "hash");
|
||||
jobj_sector_size = json_contains(cd, jobj_area, "type:checksum",
|
||||
"Keyslot area", "sector_size", json_type_int);
|
||||
if (!jobj_hash || !jobj_sector_size)
|
||||
@@ -354,8 +354,8 @@ static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
|
||||
} else if (!strcmp(type, "datashift") ||
|
||||
!strcmp(type, "datashift-checksum") ||
|
||||
!strcmp(type, "datashift-journal")) {
|
||||
if (!(jobj_shift_size = json_contains(cd, jobj_area, "type:datashift",
|
||||
"Keyslot area", "shift_size", json_type_string)))
|
||||
if (!(jobj_shift_size = json_contains_string(cd, jobj_area, "type:datashift",
|
||||
"Keyslot area", "shift_size")))
|
||||
return -EINVAL;
|
||||
|
||||
shift_size = crypt_jobj_get_uint64(jobj_shift_size);
|
||||
|
||||
39
tests/generators/generate-luks2-segment-crypt-empty-encryption.img.sh
Executable file
39
tests/generators/generate-luks2-segment-crypt-empty-encryption.img.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
. lib.sh
|
||||
|
||||
#
|
||||
# *** Description ***
|
||||
#
|
||||
# generate primary header with segment empty encryption field
|
||||
#
|
||||
# secondary header is corrupted on purpose as well
|
||||
#
|
||||
|
||||
# $1 full target dir
|
||||
# $2 full source luks2 image
|
||||
|
||||
function generate()
|
||||
{
|
||||
# remove mandatory encryption field
|
||||
json_str=$(jq -c '.segments."0".encryption = ""' $TMPDIR/json0)
|
||||
test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
|
||||
|
||||
write_luks2_json "$json_str" $TMPDIR/json0
|
||||
|
||||
lib_mangle_json_hdr0_kill_hdr1
|
||||
}
|
||||
|
||||
function check()
|
||||
{
|
||||
lib_hdr1_killed || exit 2
|
||||
|
||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||
jq -c 'if .segments."0".encryption != ""
|
||||
then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
|
||||
}
|
||||
|
||||
lib_prepare $@
|
||||
generate
|
||||
check
|
||||
lib_cleanup
|
||||
@@ -204,6 +204,7 @@ RUN luks2-segment-wrong-flags.img "F" "Failed to detect invalid flags field"
|
||||
RUN luks2-segment-wrong-flags-element.img "F" "Failed to detect invalid flags content"
|
||||
RUN luks2-segment-wrong-backup-key-0.img "F" "Failed to detect gap in backup segments"
|
||||
RUN luks2-segment-wrong-backup-key-1.img "F" "Failed to detect gap in backup segments"
|
||||
RUN luks2-segment-crypt-empty-encryption.img "F" "Failed to detect empty encryption field"
|
||||
|
||||
echo "[6] Test metadata size and keyslots size (config section)"
|
||||
RUN luks2-invalid-keyslots-size-c0.img "F" "Failed to detect too large keyslots_size in config section"
|
||||
|
||||
Reference in New Issue
Block a user