Commit 75695195 authored by Ondrej Kozina's avatar Ondrej Kozina Committed by Milan Broz

Allow unbound keyslots to be assigned to existing digest.

If passed key matches any existing digest we will not create
new digest but assign the keyslot to already existing one.

Because reencryption should be able to create more than one
keyslot assigned to new key digest.

TODO: Tests for the new feature
parent a8481792
......@@ -957,6 +957,9 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
/** create keyslot with new volume key and assign it to current dm-crypt segment */
#define CRYPT_VOLUME_KEY_SET (1 << 1)
/** Assign key to first matching digest before creating new digest */
#define CRYPT_VOLUME_KEY_DIGEST_REUSE (1 << 2)
/**
* Add key slot using provided key.
*
......
......@@ -281,6 +281,10 @@ void json_segment_remove_flag(json_object *jobj_segment, const char *flag);
/*
* Generic LUKS2 digest
*/
int LUKS2_digest_any_matching(struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk);
int LUKS2_digest_by_segment(struct luks2_hdr *hdr, int segment);
int LUKS2_digest_verify_by_segment(struct crypt_device *cd,
......
......@@ -110,30 +110,38 @@ int LUKS2_digest_by_keyslot(struct luks2_hdr *hdr, int keyslot)
return -ENOENT;
}
static int _digest_verify(struct crypt_device *cd,
int digest,
const struct volume_key *vk)
{
const digest_handler *h;
int r;
h = LUKS2_digest_handler(cd, digest);
if (!h)
return -EINVAL;
r = h->verify(cd, digest, vk->key, vk->keylength);
if (r < 0)
log_dbg(cd, "Digest %d (%s) verify failed with %d.", digest, h->name, r);
return r;
}
int LUKS2_digest_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
struct volume_key *vk,
int keyslot)
{
const digest_handler *h;
int digest, r;
digest = LUKS2_digest_by_keyslot(hdr, keyslot);
if (digest < 0)
return digest;
log_dbg(cd, "Verifying key from keyslot %d, digest %d.", keyslot, digest);
h = LUKS2_digest_handler(cd, digest);
if (!h)
return -EINVAL;
r = h->verify(cd, digest, vk->key, vk->keylength);
if (r < 0) {
log_dbg(cd, "Digest %d (%s) verify failed with %d.", digest, h->name, r);
return r;
}
r = _digest_verify(cd, digest, vk);
return digest;
return r < 0 ? r : digest;
}
int LUKS2_digest_dump(struct crypt_device *cd, int digest)
......@@ -151,7 +159,6 @@ int LUKS2_digest_verify_by_segment(struct crypt_device *cd,
int segment,
const struct volume_key *vk)
{
const digest_handler *h;
int digest, r;
digest = LUKS2_digest_by_segment(hdr, segment);
......@@ -160,17 +167,24 @@ int LUKS2_digest_verify_by_segment(struct crypt_device *cd,
log_dbg(cd, "Verifying key digest %d.", digest);
h = LUKS2_digest_handler(cd, digest);
if (!h)
return -EINVAL;
r = _digest_verify(cd, digest, vk);
r = h->verify(cd, digest, vk->key, vk->keylength);
if (r < 0) {
log_dbg(cd, "Digest %d (%s) verify failed with %d.", digest, h->name, r);
return r;
return r < 0 ? r : digest;
}
int LUKS2_digest_any_matching(struct crypt_device *cd,
struct luks2_hdr *hdr,
const struct volume_key *vk)
{
int digest;
for (digest = 0; digest < LUKS2_DIGEST_MAX; digest++) {
if (_digest_verify(cd, digest, vk) < 0)
continue;
return digest;
}
return digest;
return -ENOENT;
}
/* FIXME: segment can have more digests */
......
......@@ -5281,9 +5281,15 @@ int crypt_keyslot_add_by_key(struct crypt_device *cd,
if (digest >= 0)
flags &= ~CRYPT_VOLUME_KEY_SET;
/* if key matches any existing digest, do not create new digest */
if (digest < 0 && (flags & CRYPT_VOLUME_KEY_DIGEST_REUSE))
digest = LUKS2_digest_any_matching(cd, &cd->u.luks2.hdr, vk);
/* no segment flag or new vk flag requires new key digest */
if (flags & (CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_SET))
digest = LUKS2_digest_create(cd, "pbkdf2", &cd->u.luks2.hdr, vk);
if (flags & (CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_SET)) {
if (digest < 0 || !(flags & CRYPT_VOLUME_KEY_DIGEST_REUSE))
digest = LUKS2_digest_create(cd, "pbkdf2", &cd->u.luks2.hdr, vk);
}
r = digest;
if (r < 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment