mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-06 00:10:04 +01:00
Add keyslot_context for volume key stored in a keyring.
This commit is contained in:
@@ -362,6 +362,42 @@ static int get_luks1_volume_key_by_keyring(struct crypt_device *cd,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int get_key_by_vk_in_keyring(struct crypt_device *cd,
|
||||
struct crypt_keyslot_context *kc,
|
||||
int keyslot __attribute__((unused)),
|
||||
int segment __attribute__((unused)),
|
||||
struct volume_key **r_vk)
|
||||
{
|
||||
int r;
|
||||
|
||||
assert(cd);
|
||||
assert(kc && kc->type == CRYPT_KC_TYPE_VK_KEYRING);
|
||||
assert(r_vk);
|
||||
|
||||
r = keyring_read_by_id(kc->u.vk_kr.key_description, &kc->i_volume_key, &kc->i_volume_key_size);
|
||||
if (r < 0) {
|
||||
log_err(cd, _("Failed to read volume key from keyring."));
|
||||
kc->error = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*r_vk = crypt_alloc_volume_key(kc->i_volume_key_size, kc->i_volume_key);
|
||||
if (!*r_vk) {
|
||||
kc->error = -ENOMEM;
|
||||
return kc->error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_volume_key_by_vk_in_keyring(struct crypt_device *cd,
|
||||
struct crypt_keyslot_context *kc,
|
||||
int keyslot __attribute__((unused)),
|
||||
struct volume_key **r_vk)
|
||||
{
|
||||
return get_key_by_vk_in_keyring(cd, kc, -2 /* unused */, -2 /* unused */, r_vk);
|
||||
}
|
||||
|
||||
static void unlock_method_init_internal(struct crypt_keyslot_context *kc)
|
||||
{
|
||||
assert(kc);
|
||||
@@ -369,6 +405,8 @@ 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_volume_key = NULL;
|
||||
kc->i_volume_key_size = 0;
|
||||
}
|
||||
|
||||
void crypt_keyslot_unlock_by_keyring_internal(struct crypt_keyslot_context *kc,
|
||||
@@ -483,6 +521,27 @@ void crypt_keyslot_unlock_by_token_init_internal(struct crypt_keyslot_context *k
|
||||
unlock_method_init_internal(kc);
|
||||
}
|
||||
|
||||
void crypt_keyslot_unlock_by_vk_in_keyring_internal(struct crypt_keyslot_context *kc,
|
||||
const char *key_description)
|
||||
{
|
||||
assert(kc);
|
||||
|
||||
kc->type = CRYPT_KC_TYPE_VK_KEYRING;
|
||||
kc->u.vk_kr.key_description = key_description;
|
||||
|
||||
kc->get_luks2_key = get_key_by_vk_in_keyring;
|
||||
kc->get_luks2_volume_key = get_volume_key_by_vk_in_keyring;
|
||||
kc->get_luks1_volume_key = NULL;
|
||||
kc->get_passphrase = NULL; /* keyslot key context does not provide passphrase */
|
||||
kc->get_plain_volume_key = NULL;
|
||||
kc->get_bitlk_volume_key = NULL;
|
||||
kc->get_fvault2_volume_key = NULL;
|
||||
kc->get_verity_volume_key = NULL;
|
||||
kc->get_integrity_volume_key = NULL;
|
||||
unlock_method_init_internal(kc);
|
||||
}
|
||||
|
||||
|
||||
void crypt_keyslot_context_destroy_internal(struct crypt_keyslot_context *kc)
|
||||
{
|
||||
if (!kc)
|
||||
@@ -491,6 +550,9 @@ void crypt_keyslot_context_destroy_internal(struct crypt_keyslot_context *kc)
|
||||
crypt_safe_free(kc->i_passphrase);
|
||||
kc->i_passphrase = NULL;
|
||||
kc->i_passphrase_size = 0;
|
||||
crypt_safe_free(kc->i_volume_key);
|
||||
kc->i_volume_key = NULL;
|
||||
kc->i_volume_key_size = 0;
|
||||
}
|
||||
|
||||
void crypt_keyslot_context_free(struct crypt_keyslot_context *kc)
|
||||
@@ -606,6 +668,26 @@ int crypt_keyslot_context_init_by_keyring(struct crypt_device *cd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_keyslot_context_init_by_vk_in_keyring(struct crypt_device *cd,
|
||||
const char *key_description,
|
||||
struct crypt_keyslot_context **kc)
|
||||
{
|
||||
struct crypt_keyslot_context *tmp;
|
||||
|
||||
if (!kc)
|
||||
return -EINVAL;
|
||||
|
||||
tmp = malloc(sizeof(*tmp));
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
crypt_keyslot_unlock_by_vk_in_keyring_internal(tmp, key_description);
|
||||
|
||||
*kc = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_keyslot_context_get_error(struct crypt_keyslot_context *kc)
|
||||
{
|
||||
return kc ? kc->error : -EINVAL;
|
||||
@@ -645,6 +727,8 @@ const char *keyslot_context_type_string(const struct crypt_keyslot_context *kc)
|
||||
return "key";
|
||||
case CRYPT_KC_TYPE_KEYRING:
|
||||
return "keyring";
|
||||
case CRYPT_KC_TYPE_VK_KEYRING:
|
||||
return "volume key in keyring";
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
@@ -79,12 +79,17 @@ struct crypt_keyslot_context {
|
||||
struct {
|
||||
const char *key_description;
|
||||
} kr;
|
||||
struct {
|
||||
const char *key_description;
|
||||
} vk_kr;
|
||||
} u;
|
||||
|
||||
int error;
|
||||
|
||||
char *i_passphrase;
|
||||
size_t i_passphrase_size;
|
||||
char *i_volume_key;
|
||||
size_t i_volume_key_size;
|
||||
|
||||
keyslot_context_get_key get_luks2_key;
|
||||
keyslot_context_get_volume_key get_luks1_volume_key;
|
||||
@@ -122,6 +127,9 @@ void crypt_keyslot_unlock_by_token_init_internal(struct crypt_keyslot_context *k
|
||||
void crypt_keyslot_unlock_by_keyring_internal(struct crypt_keyslot_context *kc,
|
||||
const char *key_description);
|
||||
|
||||
void crypt_keyslot_unlock_by_vk_in_keyring_internal(struct crypt_keyslot_context *kc,
|
||||
const char *key_description);
|
||||
|
||||
const char *keyslot_context_type_string(const struct crypt_keyslot_context *kc);
|
||||
|
||||
#endif /* KEYSLOT_CONTEXT_H */
|
||||
|
||||
@@ -1294,6 +1294,22 @@ int crypt_keyslot_context_init_by_keyring(struct crypt_device *cd,
|
||||
const char *key_description,
|
||||
struct crypt_keyslot_context **kc);
|
||||
|
||||
/**
|
||||
* Initialize keyslot context via volume key stored in a keyring.
|
||||
*
|
||||
* @param cd crypt device handle initialized to LUKS device context
|
||||
*
|
||||
* @param key_description kernel keyring key description library should look
|
||||
* for passphrase in. The key can be passed either as number in ASCII,
|
||||
* or a text representation in the form "%<key_type>:<key_name>"
|
||||
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_KEYRING
|
||||
*
|
||||
* @return zero on success or negative errno otherwise.
|
||||
*/
|
||||
int crypt_keyslot_context_init_by_vk_in_keyring(struct crypt_device *cd,
|
||||
const char *key_description,
|
||||
struct crypt_keyslot_context **kc);
|
||||
|
||||
/**
|
||||
* Get error code per keyslot context from last failed call.
|
||||
*
|
||||
@@ -1341,6 +1357,10 @@ int crypt_keyslot_context_set_pin(struct crypt_device *cd,
|
||||
* (@link crypt_keyslot_context_init_by_keyring @endlink)
|
||||
*/
|
||||
#define CRYPT_KC_TYPE_KEYRING INT16_C(5)
|
||||
/** keyslot context initialized by description of a keyring key containing the volume key
|
||||
* (@link crypt_keyslot_context_init_by_vk_in_keyring @endlink)
|
||||
*/
|
||||
#define CRYPT_KC_TYPE_VK_KEYRING INT16_C(6)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@@ -174,6 +174,7 @@ CRYPTSETUP_2.7 {
|
||||
crypt_get_hw_encryption_key_size;
|
||||
crypt_get_vk_keyring_type;
|
||||
crypt_keyslot_context_init_by_keyring;
|
||||
crypt_keyslot_context_init_by_vk_in_keyring;
|
||||
crypt_resume_by_keyslot_context;
|
||||
crypt_set_keyring_to_link;
|
||||
crypt_set_vk_keyring_type;
|
||||
|
||||
@@ -162,6 +162,7 @@ static key_serial_t keyring_process_proc_keys_line(char *line, const char *type,
|
||||
}
|
||||
|
||||
/* inspired by keyutils written by David Howells (dhowells@redhat.com), returns 0 ID on failure */
|
||||
|
||||
static key_serial_t find_key_by_type_and_desc(const char *type, const char *desc, key_serial_t destringid)
|
||||
{
|
||||
key_serial_t id;
|
||||
@@ -264,6 +265,54 @@ int keyring_get_key(const char *key_desc,
|
||||
return keyring_get_passphrase(key_desc, key, key_size);
|
||||
}
|
||||
|
||||
int keyring_read_by_id(const char *key_desc,
|
||||
char **passphrase,
|
||||
size_t *passphrase_len)
|
||||
{
|
||||
#ifdef KERNEL_KEYRING
|
||||
int err;
|
||||
key_serial_t kid;
|
||||
long ret;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
do
|
||||
kid = request_key(key_type_name(USER_KEY), key_desc, NULL, 0);
|
||||
while (kid < 0 && errno == EINTR);
|
||||
|
||||
kid = keyring_by_name(key_desc);
|
||||
if (kid < 0)
|
||||
return kid;
|
||||
else if (kid == 0)
|
||||
return -ENOENT;
|
||||
|
||||
/* just get payload size */
|
||||
ret = keyctl_read(kid, NULL, 0);
|
||||
if (ret > 0) {
|
||||
len = ret;
|
||||
buf = crypt_safe_alloc(len);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* retrieve actual payload data */
|
||||
ret = keyctl_read(kid, buf, len);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
err = errno;
|
||||
crypt_safe_free(buf);
|
||||
return -err;
|
||||
}
|
||||
|
||||
*passphrase = buf;
|
||||
*passphrase_len = len;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int keyring_get_passphrase(const char *key_desc,
|
||||
char **passphrase,
|
||||
size_t *passphrase_len)
|
||||
|
||||
@@ -37,6 +37,10 @@ int keyring_get_key(const char *key_desc,
|
||||
char **key,
|
||||
size_t *key_size);
|
||||
|
||||
int keyring_read_by_id(const char *key_desc,
|
||||
char **passphrase,
|
||||
size_t *passphrase_len);
|
||||
|
||||
int keyring_get_passphrase(const char *key_desc,
|
||||
char **passphrase,
|
||||
size_t *passphrase_len);
|
||||
|
||||
Reference in New Issue
Block a user