From 4a09a677551e47f51d6444565e3d98b4b8023c09 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Oct 2021 23:48:51 +0200 Subject: [PATCH 1/5] cryptsetup: also define crypt_token_max() as fallback locally, not just sym_crypt_token_max() Our code that links directly against libcryptsetup, and doesn't use dlopen() might want to use this fallback glue function too. --- src/shared/cryptsetup-util.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/cryptsetup-util.h b/src/shared/cryptsetup-util.h index 1bf9830a7d..ff44af8441 100644 --- a/src/shared/cryptsetup-util.h +++ b/src/shared/cryptsetup-util.h @@ -54,11 +54,12 @@ extern int (*sym_crypt_token_json_set)(struct crypt_device *cd, int token, const extern int (*sym_crypt_token_max)(const char *type); #else /* As a fallback, use the same hard-coded value libcryptsetup uses internally. */ -static inline int sym_crypt_token_max(_unused_ const char *type) { +static inline int crypt_token_max(_unused_ const char *type) { assert(streq(type, CRYPT_LUKS2)); return 32; } +#define sym_crypt_token_max(type) crypt_token_max(type) #endif extern crypt_token_info (*sym_crypt_token_status)(struct crypt_device *cd, int token, const char **type); extern int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size); From e7e30330ff9fe0c2df3debe8cdf89bf6f5ed1bfd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Oct 2021 16:58:42 +0200 Subject: [PATCH 2/5] homed: use crypt_token_max() where appropriate Let's use the new crypt_token_max() API in systemd-homework too, to cut iteration of tokens short. We already use it in cryptenroll/cryptsetup, so let's use it here too. --- src/home/homework-luks.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index 8af9223d57..b716218716 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -698,7 +698,7 @@ static int luks_validate_home_record( assert(cd); assert(h); - for (int token = 0;; token++) { + for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) { _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *rr = NULL; _cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *context = NULL; _cleanup_(user_record_unrefp) UserRecord *lhr = NULL; @@ -894,7 +894,7 @@ int home_store_header_identity_luks( _cleanup_(user_record_unrefp) UserRecord *header_home = NULL; _cleanup_free_ char *text = NULL; - int token = 0, r; + int r; assert(h); @@ -924,7 +924,7 @@ int home_store_header_identity_luks( if (r < 0) return r; - for (;; token++) { + for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) { crypt_token_info state; const char *type; From d71059072aebae5b15a41974142f5df2b8ce55f9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Oct 2021 16:59:35 +0200 Subject: [PATCH 3/5] homed: don't forget to look at all enrolled tokens We accidentally increased the token index twice whenever we found our token. Fix that. --- src/home/homework-luks.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index b716218716..c9c2476ed6 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -946,7 +946,6 @@ int home_store_header_identity_luks( /* Now, let's free the text so that for all further matching tokens we all crypt_json_token_set() * with a NULL text in order to invalidate the tokens. */ text = mfree(text); - token++; } if (text) From e0142d4ff86deaaae28b6eeedcda20458978df8b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Oct 2021 17:26:19 +0200 Subject: [PATCH 4/5] cryptenroll: politely refuse enrolling keys into homed volumes People should use homectl to enroll tokens into home directories, hence point them there. Otherwise the auth data for the account and for the LUKS volume will end up being different. --- src/cryptenroll/cryptenroll.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c index cf99aab96d..c9bc9a2489 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -381,6 +381,28 @@ static int parse_argv(int argc, char *argv[]) { return 1; } +static int check_for_homed(struct crypt_device *cd) { + int r; + + assert_se(cd); + + /* Politely refuse operating on homed volumes. The enrolled tokens for the user record and the LUKS2 + * volume should not get out of sync. */ + + for (int token = 0; token < crypt_token_max(CRYPT_LUKS2); token ++) { + r = cryptsetup_get_token_as_json(cd, token, "systemd-homed", NULL); + if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE)) + continue; + if (r < 0) + return log_error_errno(r, "Failed to read JSON token data off disk: %m"); + + return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN), + "LUKS2 volume is managed by systemd-homed, please use homectl to enroll tokens."); + } + + return 0; +} + static int prepare_luks( struct crypt_device **ret_cd, void **ret_volume_key, @@ -405,6 +427,10 @@ static int prepare_luks( if (r < 0) return log_error_errno(r, "Failed to load LUKS2 superblock: %m"); + r = check_for_homed(cd); + if (r < 0) + return r; + if (!ret_volume_key) { *ret_cd = TAKE_PTR(cd); return 0; From de4a575e412e8730c230fc975f4e00094a2fef56 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 8 Oct 2021 17:25:39 +0200 Subject: [PATCH 5/5] update TODO --- TODO | 3 --- 1 file changed, 3 deletions(-) diff --git a/TODO b/TODO index d8975158b9..0ccb03ae74 100644 --- a/TODO +++ b/TODO @@ -226,9 +226,6 @@ Features: * introduce a new group to own TPM devices -* cryptenroll: politely refuse enrolling new keys to homed volumes, since we - we cannot update identity info - * cryptsetup: if only recovery keys are registered and no regular passphrases, ask user for "recovery key", not "passphrase"