diff --git a/lib/luks2/luks2.h b/lib/luks2/luks2.h index fa33d682..b1938691 100644 --- a/lib/luks2/luks2.h +++ b/lib/luks2/luks2.h @@ -244,6 +244,12 @@ int LUKS2_token_is_assigned(struct crypt_device *cd, int keyslot, int token); +int LUKS2_token_assignment_copy(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot_from, + int keyslot_to, + int commit); + int LUKS2_token_create(struct crypt_device *cd, struct luks2_hdr *hdr, int token, diff --git a/lib/luks2/luks2_token.c b/lib/luks2/luks2_token.c index 5d6a10ca..3da9dcc0 100644 --- a/lib/luks2/luks2_token.c +++ b/lib/luks2/luks2_token.c @@ -670,16 +670,12 @@ int LUKS2_token_assign(struct crypt_device *cd, struct luks2_hdr *hdr, return token; } -int LUKS2_token_is_assigned(struct crypt_device *cd, struct luks2_hdr *hdr, - int keyslot, int token) +static int token_is_assigned(struct luks2_hdr *hdr, int keyslot, int token) { int i; - json_object *jobj_token, *jobj_token_keyslots, *jobj; + json_object *jobj, *jobj_token_keyslots, + *jobj_token = LUKS2_get_token_jobj(hdr, token); - if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX || token < 0 || token >= LUKS2_TOKENS_MAX) - return -EINVAL; - - jobj_token = LUKS2_get_token_jobj(hdr, token); if (!jobj_token) return -ENOENT; @@ -694,6 +690,15 @@ int LUKS2_token_is_assigned(struct crypt_device *cd, struct luks2_hdr *hdr, return -ENOENT; } +int LUKS2_token_is_assigned(struct crypt_device *cd, struct luks2_hdr *hdr, + int keyslot, int token) +{ + if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX || token < 0 || token >= LUKS2_TOKENS_MAX) + return -EINVAL; + + return token_is_assigned(hdr, keyslot, token); +} + int LUKS2_tokens_count(struct luks2_hdr *hdr) { json_object *jobj_tokens = LUKS2_get_tokens_jobj(hdr); @@ -702,3 +707,28 @@ int LUKS2_tokens_count(struct luks2_hdr *hdr) return json_object_object_length(jobj_tokens); } + +int LUKS2_token_assignment_copy(struct crypt_device *cd, + struct luks2_hdr *hdr, + int keyslot_from, + int keyslot_to, + int commit) +{ + int i, r; + + if (keyslot_from < 0 || keyslot_from >= LUKS2_KEYSLOTS_MAX || keyslot_to < 0 || keyslot_to >= LUKS2_KEYSLOTS_MAX) + return -EINVAL; + + r = LUKS2_tokens_count(hdr); + if (r <= 0) + return r; + + for (i = 0; i < LUKS2_TOKENS_MAX; i++) { + if (!token_is_assigned(hdr, keyslot_from, i)) { + if ((r = assign_one_token(cd, hdr, keyslot_to, i, 1))) + return r; + } + } + + return commit ? LUKS2_hdr_write(cd, hdr) : 0; +} diff --git a/lib/setup.c b/lib/setup.c index 4813bdff..60f4c034 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -3476,6 +3476,9 @@ int crypt_keyslot_change_by_passphrase(struct crypt_device *cd, r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot_new, digest, 1, 0); if (r < 0) goto out; + r = LUKS2_token_assignment_copy(cd, &cd->u.luks2.hdr, keyslot_old, keyslot_new, 0); + if (r < 0) + goto out; } else { log_dbg(cd, "Key slot %d is going to be overwritten.", keyslot_old); /* FIXME: improve return code so that we can detect area is damaged */