Move crypt specific segment validation in new routine.

Also rename all 'length' variable to 'size' since json
field is named size.

Make segment validation two step process. First
validate general segment object is valid and later
validate specific segment type has all necessary fields.

Without this patch older libraries won't be able to print out
(luksDump) basic information about devices created with newer
libraries.
This commit is contained in:
Ondrej Kozina
2018-07-30 11:52:21 +02:00
committed by Milan Broz
parent 974072bdae
commit c1777cfb89

View File

@@ -506,12 +506,66 @@ static int hdr_validate_tokens(json_object *hdr_jobj)
return 0; return 0;
} }
static int hdr_validate_crypt_segment(json_object *jobj, const char *key, json_object *jobj_digests,
uint64_t offset, uint64_t size)
{
json_object *jobj_ivoffset, *jobj_sector_size, *jobj_integrity;
uint32_t sector_size;
uint64_t ivoffset;
if (!(jobj_ivoffset = json_contains(jobj, key, "Segment", "iv_tweak", json_type_string)) ||
!json_contains(jobj, key, "Segment", "encryption", json_type_string) ||
!(jobj_sector_size = json_contains(jobj, key, "Segment", "sector_size", json_type_int)))
return 1;
/* integrity */
if (json_object_object_get_ex(jobj, "integrity", &jobj_integrity)) {
if (!json_contains(jobj, key, "Segment", "integrity", json_type_object) ||
!json_contains(jobj_integrity, key, "Segment integrity", "type", json_type_string) ||
!json_contains(jobj_integrity, key, "Segment integrity", "journal_encryption", json_type_string) ||
!json_contains(jobj_integrity, key, "Segment integrity", "journal_integrity", json_type_string))
return 1;
}
/* enforce uint32_t type */
if (!validate_json_uint32(jobj_sector_size)) {
log_dbg("Illegal field \"sector_size\":%s.",
json_object_get_string(jobj_sector_size));
return 1;
}
sector_size = json_object_get_uint32(jobj_sector_size);
if (!sector_size || sector_size % SECTOR_SIZE) {
log_dbg("Illegal sector size: %" PRIu32, sector_size);
return 1;
}
if (!numbered("iv_tweak", json_object_get_string(jobj_ivoffset)) ||
!json_str_to_uint64(jobj_ivoffset, &ivoffset))
return 1;
if (offset % sector_size) {
log_dbg("Offset field has to be aligned to sector size: %" PRIu32, sector_size);
return 1;
}
if (ivoffset % sector_size) {
log_dbg("IV offset field has to be aligned to sector size: %" PRIu32, sector_size);
return 1;
}
if (size % sector_size) {
log_dbg("Size field has to be aligned to sector size: %" PRIu32, sector_size);
return 1;
}
return !segment_has_digest(key, jobj_digests);
}
static int hdr_validate_segments(json_object *hdr_jobj) static int hdr_validate_segments(json_object *hdr_jobj)
{ {
json_object *jobj, *jobj_digests, *jobj_offset, *jobj_ivoffset, json_object *jobj, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type;
*jobj_length, *jobj_sector_size, *jobj_type, *jobj_integrity; uint64_t offset, size;
uint32_t sector_size;
uint64_t ivoffset, offset, length;
if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj)) { if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj)) {
log_dbg("Missing segments section."); log_dbg("Missing segments section.");
@@ -531,70 +585,37 @@ static int hdr_validate_segments(json_object *hdr_jobj)
if (!numbered("Segment", key)) if (!numbered("Segment", key))
return 1; return 1;
if (!json_contains(val, key, "Segment", "type", json_type_string) || /* those fields are mandatory for all segment types */
if (!(jobj_type = json_contains(val, key, "Segment", "type", json_type_string)) ||
!(jobj_offset = json_contains(val, key, "Segment", "offset", json_type_string)) || !(jobj_offset = json_contains(val, key, "Segment", "offset", json_type_string)) ||
!(jobj_ivoffset = json_contains(val, key, "Segment", "iv_tweak", json_type_string)) || !(jobj_size = json_contains(val, key, "Segment", "size", json_type_string)))
!(jobj_length = json_contains(val, key, "Segment", "size", json_type_string)) ||
!json_contains(val, key, "Segment", "encryption", json_type_string) ||
!(jobj_sector_size = json_contains(val, key, "Segment", "sector_size", json_type_int)))
return 1; return 1;
/* integrity */
if (json_object_object_get_ex(val, "integrity", &jobj_integrity)) {
if (!json_contains(val, key, "Segment", "integrity", json_type_object) ||
!json_contains(jobj_integrity, key, "Segment integrity", "type", json_type_string) ||
!json_contains(jobj_integrity, key, "Segment integrity", "journal_encryption", json_type_string) ||
!json_contains(jobj_integrity, key, "Segment integrity", "journal_integrity", json_type_string))
return 1;
}
/* enforce uint32_t type */
if (!validate_json_uint32(jobj_sector_size)) {
log_dbg("Illegal field \"sector_size\":%s.",
json_object_get_string(jobj_sector_size));
return 1;
}
sector_size = json_object_get_uint32(jobj_sector_size);
if (!sector_size || sector_size % 512) {
log_dbg("Illegal sector size: %" PRIu32, sector_size);
return 1;
}
if (!numbered("offset", json_object_get_string(jobj_offset)) || if (!numbered("offset", json_object_get_string(jobj_offset)) ||
!numbered("iv_tweak", json_object_get_string(jobj_ivoffset))) !json_str_to_uint64(jobj_offset, &offset))
return 1; return 1;
/* rule out values > UINT64_MAX */ /* size "dynamic" means whole device starting at 'offset' */
if (!json_str_to_uint64(jobj_offset, &offset) || if (strcmp(json_object_get_string(jobj_size), "dynamic")) {
!json_str_to_uint64(jobj_ivoffset, &ivoffset)) if (!numbered("size", json_object_get_string(jobj_size)) ||
!json_str_to_uint64(jobj_size, &size))
return 1; return 1;
} else
size = 0;
if (offset % sector_size) { /* all device-mapper devices are aligned to 512 sector size */
log_dbg("Offset field has to be aligned to sector size: %" PRIu32, sector_size); if (offset % SECTOR_SIZE) {
log_dbg("Offset field has to be aligned to sector size: %" PRIu32, SECTOR_SIZE);
return 1;
}
if (size % SECTOR_SIZE) {
log_dbg("Size field has to be aligned to sector size: %" PRIu32, SECTOR_SIZE);
return 1; return 1;
} }
if (ivoffset % sector_size) { /* crypt */
log_dbg("IV offset field has to be aligned to sector size: %" PRIu32, sector_size);
return 1;
}
/* length "dynamic" means whole device starting at 'offset' */
if (strcmp(json_object_get_string(jobj_length), "dynamic")) {
if (!numbered("size", json_object_get_string(jobj_length)) ||
!json_str_to_uint64(jobj_length, &length))
return 1;
if (length % sector_size) {
log_dbg("Length field has to be aligned to sector size: %" PRIu32, sector_size);
return 1;
}
}
json_object_object_get_ex(val, "type", &jobj_type);
if (!strcmp(json_object_get_string(jobj_type), "crypt") && if (!strcmp(json_object_get_string(jobj_type), "crypt") &&
!segment_has_digest(key, jobj_digests)) hdr_validate_crypt_segment(val, key, jobj_digests, offset, size))
return 1; return 1;
} }