Add repair for known glitches in LUKS2 json.

This commit is contained in:
Ondrej Kozina
2018-04-19 15:50:21 +02:00
committed by Milan Broz
parent dddd30bef8
commit f6be62ac5f
5 changed files with 96 additions and 0 deletions

View File

@@ -491,6 +491,15 @@ static int validate_luks2_json_object(json_object *jobj_hdr)
}
r = LUKS2_hdr_validate(jobj_hdr);
if (r) {
log_dbg("Repairing JSON metadata.");
/* try to correct known glitches */
LUKS2_hdr_repair(jobj_hdr);
/* run validation again */
r = LUKS2_hdr_validate(jobj_hdr);
}
if (r)
log_dbg("ERROR: LUKS2 validation failed");

View File

@@ -79,6 +79,12 @@ int LUKS2_check_json_size(const struct luks2_hdr *hdr);
int LUKS2_token_validate(json_object *hdr_jobj, json_object *jobj_token, const char *key);
void LUKS2_token_dump(struct crypt_device *cd, int token);
/*
* LUKS2 JSON repair for known glitches
*/
void LUKS2_hdr_repair(json_object *jobj_hdr);
void LUKS2_keyslots_repair(json_object *jobj_hdr);
/*
* JSON array helpers
*/
@@ -106,6 +112,7 @@ typedef int (*keyslot_store_func)(struct crypt_device *cd, int keyslot,
typedef int (*keyslot_wipe_func) (struct crypt_device *cd, int keyslot);
typedef int (*keyslot_dump_func) (struct crypt_device *cd, int keyslot);
typedef int (*keyslot_validate_func) (struct crypt_device *cd, json_object *jobj_keyslot);
typedef void(*keyslot_repair_func) (struct crypt_device *cd, json_object *jobj_keyslot);
/* see LUKS2_luks2_to_luks1 */
int placeholder_keyslot_alloc(struct crypt_device *cd,
@@ -126,6 +133,7 @@ typedef struct {
keyslot_wipe_func wipe;
keyslot_dump_func dump;
keyslot_validate_func validate;
keyslot_repair_func repair;
} keyslot_handler;
/**

View File

@@ -1938,3 +1938,26 @@ int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uin
/* any remaining unmasked requirement fails the check */
return reqs ? -EINVAL : 0;
}
/*
* NOTE: this routine is called on json object that failed validation.
* Proceed with caution :)
*
* known glitches so far:
*
* any version < 2.0.3:
* - luks2 keyslot pbkdf params change via crypt_keyslot_change_by_passphrase()
* could leave previous type parameters behind. Correct this by purging
* all params not needed by current type.
*/
void LUKS2_hdr_repair(json_object *hdr_jobj)
{
json_object *jobj_keyslots;
if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
return;
if (!json_object_is_type(jobj_keyslots, json_type_object))
return;
LUKS2_keyslots_repair(jobj_keyslots);
}

View File

@@ -608,3 +608,21 @@ int LUKS2_keyslots_validate(json_object *hdr_jobj)
return 0;
}
void LUKS2_keyslots_repair(json_object *jobj_keyslots)
{
const keyslot_handler *h;
json_object *jobj_type;
json_object_object_foreach(jobj_keyslots, slot, val) {
UNUSED(slot);
if (!json_object_is_type(val, json_type_object) ||
!json_object_object_get_ex(val, "type", &jobj_type) ||
!json_object_is_type(jobj_type, json_type_string))
continue;
h = LUKS2_keyslot_handler_type(NULL, json_object_get_string(jobj_type));
if (h && h->repair)
h->repair(NULL, val);
}
}

View File

@@ -734,6 +734,43 @@ static int luks2_keyslot_update(struct crypt_device *cd,
return r;
}
static void luks2_keyslot_repair(struct crypt_device *cd, json_object *jobj_keyslot)
{
const char *type;
json_object *jobj_kdf, *jobj_type;
if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) ||
!json_object_is_type(jobj_kdf, json_type_object))
return;
if (!json_object_object_get_ex(jobj_kdf, "type", &jobj_type) ||
!json_object_is_type(jobj_type, json_type_string))
return;
type = json_object_get_string(jobj_type);
if (!strcmp(type, CRYPT_KDF_PBKDF2)) {
/* type, salt, hash, iterations only */
json_object_object_foreach(jobj_kdf, key, val) {
UNUSED(val);
if (!strcmp(key, "type") || !strcmp(key, "salt") ||
!strcmp(key, "hash") || !strcmp(key, "iterations"))
continue;
json_object_object_del(jobj_kdf, key);
}
} else if (!strcmp(type, CRYPT_KDF_ARGON2I) || !strcmp(type, CRYPT_KDF_ARGON2ID)) {
/* type, salt, time, memory, cpus only */
json_object_object_foreach(jobj_kdf, key, val) {
UNUSED(val);
if (!strcmp(key, "type") || !strcmp(key, "salt") ||
!strcmp(key, "time") || !strcmp(key, "memory") ||
!strcmp(key, "cpus"))
continue;
json_object_object_del(jobj_kdf, key);
}
}
}
const keyslot_handler luks2_keyslot = {
.name = "luks2",
.alloc = luks2_keyslot_alloc,
@@ -743,4 +780,5 @@ const keyslot_handler luks2_keyslot = {
.wipe = luks2_keyslot_wipe,
.dump = luks2_keyslot_dump,
.validate = luks2_keyslot_validate,
.repair = luks2_keyslot_repair
};