mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,6 @@ struct crypt_keyslot_context {
|
||||
|
||||
int error;
|
||||
|
||||
struct volume_key *i_vk;
|
||||
char *i_passphrase;
|
||||
size_t i_passphrase_size;
|
||||
|
||||
|
||||
15
lib/setup.c
15
lib/setup.c
@@ -6154,7 +6154,7 @@ int crypt_keyslot_add_by_keyslot_context(struct crypt_device *cd,
|
||||
int active_slots, r;
|
||||
const char *new_passphrase;
|
||||
size_t new_passphrase_size;
|
||||
struct volume_key *p_vk = NULL, *vk = NULL;
|
||||
struct volume_key *vk = NULL;
|
||||
|
||||
if (!kc || ((flags & CRYPT_VOLUME_KEY_NO_SEGMENT) &&
|
||||
(flags & CRYPT_VOLUME_KEY_SET)))
|
||||
@@ -6191,21 +6191,20 @@ int crypt_keyslot_add_by_keyslot_context(struct crypt_device *cd,
|
||||
if (active_slots == 0 && kc->type != CRYPT_KC_TYPE_KEY)
|
||||
r = -ENOENT;
|
||||
else if (is_luks1 && kc->get_luks1_volume_key)
|
||||
r = kc->get_luks1_volume_key(cd, kc, keyslot_existing, &p_vk);
|
||||
r = kc->get_luks1_volume_key(cd, kc, keyslot_existing, &vk);
|
||||
else if (!is_luks1 && kc->get_luks2_volume_key)
|
||||
r = kc->get_luks2_volume_key(cd, kc, keyslot_existing, &p_vk);
|
||||
r = kc->get_luks2_volume_key(cd, kc, keyslot_existing, &vk);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (r == -ENOENT) {
|
||||
if ((flags & CRYPT_VOLUME_KEY_NO_SEGMENT) && kc->type == CRYPT_KC_TYPE_KEY) {
|
||||
vk = crypt_generate_volume_key(cd, kc->u.k.volume_key_size);
|
||||
if (!vk)
|
||||
if (!(vk = crypt_generate_volume_key(cd, kc->u.k.volume_key_size)))
|
||||
return -ENOMEM;
|
||||
p_vk = vk;
|
||||
r = 0;
|
||||
} else if (cd->volume_key) {
|
||||
p_vk = cd->volume_key;
|
||||
if (!(vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key)))
|
||||
return -ENOMEM;
|
||||
r = 0;
|
||||
} else if (active_slots == 0) {
|
||||
log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided."));
|
||||
@@ -6221,7 +6220,7 @@ int crypt_keyslot_add_by_keyslot_context(struct crypt_device *cd,
|
||||
if (r >= 0 && new_kc->type == CRYPT_KC_TYPE_TOKEN && !is_luks1)
|
||||
r = LUKS2_token_assign(cd, &cd->u.luks2.hdr, keyslot_new, new_kc->u.t.id, 1, 0);
|
||||
if (r >= 0)
|
||||
r = keyslot_add_by_key(cd, is_luks1, keyslot_new, new_passphrase, new_passphrase_size, p_vk, flags);
|
||||
r = keyslot_add_by_key(cd, is_luks1, keyslot_new, new_passphrase, new_passphrase_size, vk, flags);
|
||||
|
||||
crypt_free_volume_key(vk);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user