summaryrefslogtreecommitdiffstats
path: root/lib/keyslot_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/keyslot_context.c')
-rw-r--r--lib/keyslot_context.c364
1 files changed, 352 insertions, 12 deletions
diff --git a/lib/keyslot_context.c b/lib/keyslot_context.c
index 89bd433..5860247 100644
--- a/lib/keyslot_context.c
+++ b/lib/keyslot_context.c
@@ -1,8 +1,8 @@
/*
* LUKS - Linux Unified Key Setup, keyslot unlock helpers
*
- * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2022-2023 Ondrej Kozina
+ * Copyright (C) 2022-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2022-2024 Ondrej Kozina
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -173,7 +173,7 @@ static int get_luks1_volume_key_by_keyfile(struct crypt_device *cd,
return r;
}
-static int get_key_by_key(struct crypt_device *cd,
+static int get_key_by_key(struct crypt_device *cd __attribute__((unused)),
struct crypt_keyslot_context *kc,
int keyslot __attribute__((unused)),
int segment __attribute__((unused)),
@@ -204,19 +204,73 @@ static int get_volume_key_by_key(struct crypt_device *cd,
return get_key_by_key(cd, kc, -2 /* unused */, -2 /* unused */, r_vk);
}
+static int get_generic_volume_key_by_key(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ struct volume_key **r_vk)
+{
+ return get_key_by_key(cd, kc, -2 /* unused */, -2 /* unused */, r_vk);
+}
+
+static int get_generic_signed_key_by_key(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ struct volume_key **r_vk,
+ struct volume_key **r_signature)
+{
+ struct volume_key *vk, *vk_sig;
+
+ assert(kc && ((kc->type == CRYPT_KC_TYPE_KEY) ||
+ (kc->type == CRYPT_KC_TYPE_SIGNED_KEY)));
+ assert(r_vk);
+ assert(r_signature);
+
+ /* return key with no signature */
+ if (kc->type == CRYPT_KC_TYPE_KEY) {
+ *r_signature = NULL;
+ return get_key_by_key(cd, kc, -2 /* unused */, -2 /* unused */, r_vk);
+ }
+
+ if (!kc->u.ks.volume_key || !kc->u.ks.signature) {
+ kc->error = -EINVAL;
+ return kc->error;
+ }
+
+ vk = crypt_alloc_volume_key(kc->u.ks.volume_key_size, kc->u.ks.volume_key);
+ if (!vk) {
+ kc->error = -ENOMEM;
+ return kc->error;
+ }
+
+ vk_sig = crypt_alloc_volume_key(kc->u.ks.signature_size, kc->u.ks.signature);
+ if (!vk_sig) {
+ crypt_free_volume_key(vk);
+ kc->error = -ENOMEM;
+ return kc->error;
+ }
+
+ *r_vk = vk;
+ *r_signature = vk_sig;
+
+ return 0;
+}
+
static int get_luks2_key_by_token(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
- int keyslot __attribute__((unused)),
+ int keyslot,
int segment,
struct volume_key **r_vk)
{
int r;
+ struct luks2_hdr *hdr;
assert(cd);
assert(kc && kc->type == CRYPT_KC_TYPE_TOKEN);
assert(r_vk);
- r = LUKS2_token_unlock_key(cd, crypt_get_hdr(cd, CRYPT_LUKS2), kc->u.t.id, kc->u.t.type,
+ hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+ if (!hdr)
+ return -EINVAL;
+
+ r = LUKS2_token_unlock_key(cd, hdr, keyslot, kc->u.t.id, kc->u.t.type,
kc->u.t.pin, kc->u.t.pin_size, segment, kc->u.t.usrptr, r_vk);
if (r < 0)
kc->error = r;
@@ -226,10 +280,10 @@ static int get_luks2_key_by_token(struct crypt_device *cd,
static int get_luks2_volume_key_by_token(struct crypt_device *cd,
struct crypt_keyslot_context *kc,
- int keyslot __attribute__((unused)),
+ int keyslot,
struct volume_key **r_vk)
{
- return get_luks2_key_by_token(cd, kc, -2 /* unused */, CRYPT_DEFAULT_SEGMENT, r_vk);
+ return get_luks2_key_by_token(cd, kc, keyslot, CRYPT_DEFAULT_SEGMENT, r_vk);
}
static int get_passphrase_by_token(struct crypt_device *cd,
@@ -261,6 +315,136 @@ static int get_passphrase_by_token(struct crypt_device *cd,
return kc->u.t.id;
}
+static int get_passphrase_by_keyring(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ const char **r_passphrase,
+ size_t *r_passphrase_size)
+{
+ int r;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_KEYRING);
+ assert(r_passphrase);
+ assert(r_passphrase_size);
+
+ if (!kc->i_passphrase) {
+ r = crypt_keyring_get_user_key(cd, kc->u.kr.key_description,
+ &kc->i_passphrase, &kc->i_passphrase_size);
+ if (r < 0) {
+ log_err(cd, _("Failed to read passphrase from keyring."));
+ kc->error = -EINVAL;
+ return -EINVAL;
+ }
+ }
+
+ *r_passphrase = kc->i_passphrase;
+ *r_passphrase_size = kc->i_passphrase_size;
+
+ return 0;
+}
+
+static int get_luks2_key_by_keyring(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ int segment,
+ struct volume_key **r_vk)
+{
+ int r;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_KEYRING);
+ assert(r_vk);
+
+ r = get_passphrase_by_keyring(cd, kc, CONST_CAST(const char **) &kc->i_passphrase,
+ &kc->i_passphrase_size);
+ if (r < 0) {
+ log_err(cd, _("Failed to read passphrase from keyring."));
+ kc->error = -EINVAL;
+ return -EINVAL;
+ }
+
+ r = LUKS2_keyslot_open(cd, keyslot, segment, kc->i_passphrase, kc->i_passphrase_size, r_vk);
+ if (r < 0)
+ kc->error = r;
+
+ return 0;
+}
+
+static int get_luks2_volume_key_by_keyring(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ struct volume_key **r_vk)
+{
+ return get_luks2_key_by_keyring(cd, kc, keyslot, CRYPT_DEFAULT_SEGMENT, r_vk);
+}
+
+static int get_luks1_volume_key_by_keyring(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ struct volume_key **r_vk)
+{
+ int r;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_PASSPHRASE);
+ assert(r_vk);
+
+ r = get_passphrase_by_keyring(cd, kc, CONST_CAST(const char **) &kc->i_passphrase,
+ &kc->i_passphrase_size);
+ if (r < 0) {
+ log_err(cd, _("Failed to read passphrase from keyring."));
+ kc->error = -EINVAL;
+ return -EINVAL;
+ }
+
+ r = LUKS_open_key_with_hdr(keyslot, kc->i_passphrase, kc->i_passphrase_size,
+ crypt_get_hdr(cd, CRYPT_LUKS1), r_vk, cd);
+ if (r < 0)
+ kc->error = r;
+
+ 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)
+{
+ char *key;
+ size_t key_size;
+ int r;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_VK_KEYRING);
+ assert(r_vk);
+
+ r = crypt_keyring_get_key_by_name(cd, kc->u.vk_kr.key_description,
+ &key, &key_size);
+ if (r < 0) {
+ log_err(cd, _("Failed to read volume key candidate from keyring."));
+ kc->error = -EINVAL;
+ return -EINVAL;
+ }
+
+ *r_vk = crypt_alloc_volume_key(key_size, key);
+ crypt_safe_free(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);
@@ -270,6 +454,26 @@ static void unlock_method_init_internal(struct crypt_keyslot_context *kc)
kc->i_passphrase_size = 0;
}
+void crypt_keyslot_unlock_by_keyring_internal(struct crypt_keyslot_context *kc,
+ const char *key_description)
+{
+ assert(kc);
+
+ kc->type = CRYPT_KC_TYPE_KEYRING;
+ kc->u.kr.key_description = key_description;
+
+ kc->get_luks2_key = get_luks2_key_by_keyring;
+ kc->get_luks2_volume_key = get_luks2_volume_key_by_keyring;
+ kc->get_luks1_volume_key = get_luks1_volume_key_by_keyring;
+ kc->get_passphrase = get_passphrase_by_keyring;
+ 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_unlock_by_key_init_internal(struct crypt_keyslot_context *kc,
const char *volume_key,
size_t volume_key_size)
@@ -283,6 +487,36 @@ void crypt_keyslot_unlock_by_key_init_internal(struct crypt_keyslot_context *kc,
kc->get_luks2_volume_key = get_volume_key_by_key;
kc->get_luks1_volume_key = get_volume_key_by_key;
kc->get_passphrase = NULL; /* keyslot key context does not provide passphrase */
+ kc->get_plain_volume_key = get_generic_volume_key_by_key;
+ kc->get_bitlk_volume_key = get_generic_volume_key_by_key;
+ kc->get_fvault2_volume_key = get_generic_volume_key_by_key;
+ kc->get_verity_volume_key = get_generic_signed_key_by_key;
+ kc->get_integrity_volume_key = get_generic_volume_key_by_key;
+ unlock_method_init_internal(kc);
+}
+
+void crypt_keyslot_unlock_by_signed_key_init_internal(struct crypt_keyslot_context *kc,
+ const char *volume_key,
+ size_t volume_key_size,
+ const char *signature,
+ size_t signature_size)
+{
+ assert(kc);
+
+ kc->type = CRYPT_KC_TYPE_SIGNED_KEY;
+ kc->u.ks.volume_key = volume_key;
+ kc->u.ks.volume_key_size = volume_key_size;
+ kc->u.ks.signature = signature;
+ kc->u.ks.signature_size = signature_size;
+ kc->get_luks2_key = NULL;
+ kc->get_luks2_volume_key = NULL;
+ kc->get_luks1_volume_key = NULL;
+ kc->get_passphrase = NULL;
+ kc->get_plain_volume_key = NULL;
+ kc->get_bitlk_volume_key = NULL;
+ kc->get_fvault2_volume_key = NULL;
+ kc->get_verity_volume_key = get_generic_signed_key_by_key;
+ kc->get_integrity_volume_key = NULL;
unlock_method_init_internal(kc);
}
@@ -299,6 +533,11 @@ void crypt_keyslot_unlock_by_passphrase_init_internal(struct crypt_keyslot_conte
kc->get_luks2_volume_key = get_luks2_volume_key_by_passphrase;
kc->get_luks1_volume_key = get_luks1_volume_key_by_passphrase;
kc->get_passphrase = get_passphrase_by_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);
}
@@ -317,6 +556,11 @@ void crypt_keyslot_unlock_by_keyfile_init_internal(struct crypt_keyslot_context
kc->get_luks2_volume_key = get_luks2_volume_key_by_keyfile;
kc->get_luks1_volume_key = get_luks1_volume_key_by_keyfile;
kc->get_passphrase = get_passphrase_by_keyfile;
+ 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);
}
@@ -339,9 +583,35 @@ void crypt_keyslot_unlock_by_token_init_internal(struct crypt_keyslot_context *k
kc->get_luks2_volume_key = get_luks2_volume_key_by_token;
kc->get_luks1_volume_key = NULL; /* LUKS1 is not supported */
kc->get_passphrase = get_passphrase_by_token;
+ 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_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)
@@ -358,7 +628,7 @@ void crypt_keyslot_context_free(struct crypt_keyslot_context *kc)
free(kc);
}
-int crypt_keyslot_context_init_by_passphrase(struct crypt_device *cd,
+int crypt_keyslot_context_init_by_passphrase(struct crypt_device *cd __attribute__((unused)),
const char *passphrase,
size_t passphrase_size,
struct crypt_keyslot_context **kc)
@@ -379,7 +649,7 @@ int crypt_keyslot_context_init_by_passphrase(struct crypt_device *cd,
return 0;
}
-int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd,
+int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd __attribute__((unused)),
const char *keyfile,
size_t keyfile_size,
uint64_t keyfile_offset,
@@ -401,7 +671,7 @@ int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd,
return 0;
}
-int crypt_keyslot_context_init_by_token(struct crypt_device *cd,
+int crypt_keyslot_context_init_by_token(struct crypt_device *cd __attribute__((unused)),
int token,
const char *type,
const char *pin, size_t pin_size,
@@ -424,7 +694,7 @@ int crypt_keyslot_context_init_by_token(struct crypt_device *cd,
return 0;
}
-int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd,
+int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd __attribute__((unused)),
const char *volume_key,
size_t volume_key_size,
struct crypt_keyslot_context **kc)
@@ -445,12 +715,76 @@ int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd,
return 0;
}
+int crypt_keyslot_context_init_by_signed_key(struct crypt_device *cd __attribute__((unused)),
+ const char *volume_key,
+ size_t volume_key_size,
+ const char *signature,
+ size_t signature_size,
+ 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_signed_key_init_internal(tmp, volume_key, volume_key_size,
+ signature, signature_size);
+
+ *kc = tmp;
+
+ return 0;
+}
+
+int crypt_keyslot_context_init_by_keyring(struct crypt_device *cd __attribute__((unused)),
+ 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_keyring_internal(tmp, key_description);
+
+ *kc = tmp;
+
+ return 0;
+}
+
+int crypt_keyslot_context_init_by_vk_in_keyring(struct crypt_device *cd __attribute__((unused)),
+ 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;
}
-int crypt_keyslot_context_set_pin(struct crypt_device *cd,
+int crypt_keyslot_context_set_pin(struct crypt_device *cd __attribute__((unused)),
const char *pin, size_t pin_size,
struct crypt_keyslot_context *kc)
{
@@ -482,6 +816,12 @@ const char *keyslot_context_type_string(const struct crypt_keyslot_context *kc)
return "token";
case CRYPT_KC_TYPE_KEY:
return "key";
+ case CRYPT_KC_TYPE_KEYRING:
+ return "keyring";
+ case CRYPT_KC_TYPE_VK_KEYRING:
+ return "volume key in keyring";
+ case CRYPT_KC_TYPE_SIGNED_KEY:
+ return "signed key";
default:
return "<unknown>";
}