Do not cache volume key in keyslot context.

First, there was a bug where passphrase based
keyslot contextets did not cache volume keys
properly and caused leaks.

Second, it causes problems when keyslot context
is used twice with different keyslot id, e.g.:
CRYPT_ANY_SLOT vs specific id, unbound key vs
volume key, etc.
This commit is contained in:
Ondrej Kozina
2022-11-02 11:41:40 +01:00
parent 01c16111d7
commit 0e6264c53c
3 changed files with 26 additions and 59 deletions

View File

@@ -130,21 +130,15 @@ static int get_luks2_key_by_keyfile(struct crypt_device *cd,
assert(kc && kc->type == CRYPT_KC_TYPE_KEYFILE);
assert(r_vk);
if (!kc->i_vk) {
r = get_passphrase_by_keyfile(cd, kc, &passphrase, &passphrase_size);
if (r)
return r;
r = get_passphrase_by_keyfile(cd, kc, &passphrase, &passphrase_size);
if (r)
return r;
r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase, passphrase_size, &kc->i_vk);
if (r < 0) {
kc->error = r;
return r;
}
}
r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase, passphrase_size, r_vk);
if (r < 0)
kc->error = r;
*r_vk = kc->i_vk;
return 0;
return r;
}
static int get_luks2_volume_key_by_keyfile(struct crypt_device *cd,
@@ -168,22 +162,16 @@ static int get_luks1_volume_key_by_keyfile(struct crypt_device *cd,
assert(kc && kc->type == CRYPT_KC_TYPE_KEYFILE);
assert(r_vk);
if (!kc->i_vk) {
r = get_passphrase_by_keyfile(cd, kc, &passphrase, &passphrase_size);
if (r)
return r;
r = get_passphrase_by_keyfile(cd, kc, &passphrase, &passphrase_size);
if (r)
return r;
r = LUKS_open_key_with_hdr(keyslot, passphrase, passphrase_size,
crypt_get_hdr(cd, CRYPT_LUKS1), &kc->i_vk, cd);
if (r < 0) {
kc->error = r;
return r;
}
}
r = LUKS_open_key_with_hdr(keyslot, passphrase, passphrase_size,
crypt_get_hdr(cd, CRYPT_LUKS1), r_vk, cd);
if (r < 0)
kc->error = r;
*r_vk = kc->i_vk;
return 0;
return r;
}
static int get_key_by_key(struct crypt_device *cd,
@@ -195,24 +183,17 @@ static int get_key_by_key(struct crypt_device *cd,
assert(kc && kc->type == CRYPT_KC_TYPE_KEY);
assert(r_vk);
if (kc->i_vk) {
*r_vk = kc->i_vk;
return 0;
}
if (!kc->u.k.volume_key) {
kc->error = -ENOENT;
return kc->error;
}
kc->i_vk = crypt_alloc_volume_key(kc->u.k.volume_key_size, kc->u.k.volume_key);
if (!kc->i_vk) {
*r_vk = crypt_alloc_volume_key(kc->u.k.volume_key_size, kc->u.k.volume_key);
if (!*r_vk) {
kc->error = -ENOMEM;
return kc->error;
}
*r_vk = kc->i_vk;
return 0;
}
@@ -236,19 +217,10 @@ static int get_luks2_key_by_token(struct crypt_device *cd,
assert(kc && kc->type == CRYPT_KC_TYPE_TOKEN);
assert(r_vk);
if (kc->i_vk) {
*r_vk = kc->i_vk;
return 0;
}
r = LUKS2_token_unlock_key(cd, crypt_get_hdr(cd, CRYPT_LUKS2), kc->u.t.id, kc->u.t.type,
kc->u.t.pin, kc->u.t.pin_size, segment, kc->u.t.usrptr, &kc->i_vk);
if (r < 0) {
kc->u.t.pin, kc->u.t.pin_size, segment, kc->u.t.usrptr, r_vk);
if (r < 0)
kc->error = r;
return r;
}
*r_vk = kc->i_vk;
return r;
}
@@ -297,7 +269,6 @@ static void unlock_method_init_internal(struct crypt_keyslot_context *kc)
kc->error = 0;
kc->i_passphrase = NULL;
kc->i_passphrase_size = 0;
kc->i_vk = NULL;
}
void crypt_keyslot_unlock_by_key_init_internal(struct crypt_keyslot_context *kc,
@@ -378,8 +349,6 @@ void crypt_keyslot_context_destroy_internal(struct crypt_keyslot_context *kc)
return;
crypt_safe_free(kc->i_passphrase);
crypt_free_volume_key(kc->i_vk);
kc->i_vk = NULL;
kc->i_passphrase = NULL;
kc->i_passphrase_size = 0;
}