From c50a7776c18357819fd1a04aefcda6dd163dae50 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Nov 2023 17:56:16 +0100 Subject: [PATCH 1/4] cryptsetup: rename usrptr to userdata Across our codebase we call the generic pointer "userdata", not "userptr". Do so here too. --- src/cryptsetup/cryptsetup.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index a0f93178f73..618fd91d5c0 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -1175,7 +1175,7 @@ static int crypt_activate_by_token_pin_ask_password( const char *type, usec_t until, bool headless, - void *usrptr, + void *userdata, uint32_t activation_flags, const char *message, const char *key_name, @@ -1186,9 +1186,9 @@ static int crypt_activate_by_token_pin_ask_password( _cleanup_strv_free_erase_ char **pins = NULL; int r; - r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, NULL, 0, usrptr, activation_flags); + r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, /* pin=*/ NULL, /* pin_size= */ 0, userdata, activation_flags); if (r > 0) /* returns unlocked keyslot id on success */ - r = 0; + return 0; if (r != -ENOANO) /* needs pin or pin is wrong */ return r; @@ -1197,9 +1197,9 @@ static int crypt_activate_by_token_pin_ask_password( return r; STRV_FOREACH(p, pins) { - r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags); + r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), userdata, activation_flags); if (r > 0) /* returns unlocked keyslot id on success */ - r = 0; + return 0; if (r != -ENOANO) /* needs pin or pin is wrong */ return r; } @@ -1209,14 +1209,14 @@ static int crypt_activate_by_token_pin_ask_password( for (;;) { pins = strv_free_erase(pins); - r = ask_password_auto(message, "drive-harddisk", NULL, key_name, credential_name, until, flags, &pins); + r = ask_password_auto(message, "drive-harddisk", /* id= */ NULL, key_name, credential_name, until, flags, &pins); if (r < 0) return r; STRV_FOREACH(p, pins) { - r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags); + r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), userdata, activation_flags); if (r > 0) /* returns unlocked keyslot id on success */ - r = 0; + return 0; if (r != -ENOANO) /* needs pin or pin is wrong */ return r; } @@ -1234,7 +1234,7 @@ static int attach_luks2_by_fido2_via_plugin( const char *name, usec_t until, bool headless, - void *usrptr, + void *userdata, uint32_t activation_flags) { return crypt_activate_by_token_pin_ask_password( @@ -1243,7 +1243,7 @@ static int attach_luks2_by_fido2_via_plugin( "systemd-fido2", until, headless, - usrptr, + userdata, activation_flags, "Please enter security token PIN:", "fido2-pin", @@ -2264,10 +2264,10 @@ static int run(int argc, char *argv[]) { r = crypt_activate_by_token_pin_ask_password( cd, volume, - NULL, + /* type= */ NULL, until, arg_headless, - NULL, + /* userdata= */ NULL, flags, "Please enter LUKS2 token PIN:", "luks2-pin", From 58925605e7193328976af462c8f718e23015b8bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Nov 2023 17:56:47 +0100 Subject: [PATCH 2/4] cryptsetup: honour configured ask password flags also when activating via token See: #28665 (this is not a fix for that PR though) --- src/cryptsetup/cryptsetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 618fd91d5c0..dd435b23a24 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -1182,7 +1182,7 @@ static int crypt_activate_by_token_pin_ask_password( const char *credential_name) { #if HAVE_LIBCRYPTSETUP_PLUGINS - AskPasswordFlags flags = ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED; + AskPasswordFlags flags = arg_ask_password_flags | ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED; _cleanup_strv_free_erase_ char **pins = NULL; int r; From 00392b14373496681f35fadccf3b28bd2586a387 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Nov 2023 17:58:29 +0100 Subject: [PATCH 3/4] cryptsetup: disable activation via token plugin if we shall measure the volume key if we allow cryptsetup to activate a volume via token plugin we never get access to the volume key, which we'd like to measure. Hence disable token plugins in that case. (I tempted to say we probably should disable them entirely, and only use them if classic cryptsetup is used, but that's a discussion for another day.) Fixes: #29790 --- src/cryptsetup/cryptsetup.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index dd435b23a24..204ffa9922f 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -1578,6 +1578,20 @@ static int make_tpm2_device_monitor( return 0; } +static bool use_token_plugins(void) { + int r; + + /* Disable tokens if we shall measure, since we won't get access to the volume key then. */ + if (arg_tpm2_measure_pcr != UINT_MAX) + return false; + + r = getenv_bool("SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE"); + if (r < 0 && r != -ENXIO) + log_debug_errno(r, "Failed to parse $SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE value, ignoring: %m"); + + return r != 0; +} + static int attach_luks2_by_tpm2_via_plugin( struct crypt_device *cd, const char *name, @@ -2260,7 +2274,7 @@ static int run(int argc, char *argv[]) { } /* Tokens are available in LUKS2 only, but it is ok to call (and fail) with LUKS1. */ - if (!key_file && !key_data && getenv_bool("SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE") != 0) { + if (!key_file && !key_data && use_token_plugins()) { r = crypt_activate_by_token_pin_ask_password( cd, volume, From a758a128709cbcd99eddd1de6ea0e9846b9ce2eb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 2 Nov 2023 22:32:36 +0100 Subject: [PATCH 4/4] cryptsetup: pass AskPasswordFlags down into pkcs11 module The pkcs11 cryptsetup token module is a bit different from the tpm2 + fido2 ones: it asks for the PIN itself, rather than bubbling up a request to get a PIN. That's because it might need multiple, and because we don't want to destroy a the pkcs11 session half-way and thus risk increasing pin counters. Hence, we sometimes ask for PINs from our code, rather than let the libcryptsetup caller do that. So far we didn't pass the AskPasswordFlags field down into the module though. Fix that. Fixes: #28665 --- .../cryptsetup-tokens/luks2-pkcs11.c | 1 + src/cryptsetup/cryptsetup.c | 3 ++- src/shared/pkcs11-util.c | 20 +++++++++++++++++-- src/shared/pkcs11-util.h | 5 ++++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c b/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c index 98fd83a014c..8cbb1f7d885 100644 --- a/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c +++ b/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c @@ -158,6 +158,7 @@ static int acquire_luks2_key_systemd( data.friendly_name = params->friendly_name; data.headless = params->headless; + data.askpw_flags = params->askpw_flags; data.until = params->until; /* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */ diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 204ffa9922f..1ebebcb2033 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -1399,7 +1399,8 @@ static int attach_luks2_by_pkcs11_via_plugin( systemd_pkcs11_plugin_params params = { .friendly_name = friendly_name, .until = until, - .headless = headless + .headless = headless, + .askpw_flags = arg_ask_password_flags, }; r = crypt_activate_by_token_pin(cd, name, "systemd-pkcs11", CRYPT_ANY_TOKEN, NULL, 0, ¶ms, flags); diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c index 70469d02062..6e88dc38038 100644 --- a/src/shared/pkcs11-util.c +++ b/src/shared/pkcs11-util.c @@ -291,6 +291,7 @@ int pkcs11_token_login( const char *key_name, const char *credential_name, usec_t until, + AskPasswordFlags ask_password_flags, bool headless, char **ret_used_pin) { @@ -371,7 +372,7 @@ int pkcs11_token_login( return log_oom(); /* We never cache PINs, simply because it's fatal if we use wrong PINs, since usually there are only 3 tries */ - r = ask_password_auto(text, icon_name, id, key_name, credential_name, until, 0, &passwords); + r = ask_password_auto(text, icon_name, id, key_name, credential_name, until, ask_password_flags, &passwords); if (r < 0) return log_error_errno(r, "Failed to query PIN for security token '%s': %m", token_label); } @@ -1058,6 +1059,8 @@ struct pkcs11_acquire_certificate_callback_data { char *pin_used; X509 *cert; const char *askpw_friendly_name, *askpw_icon_name; + AskPasswordFlags askpw_flags; + bool headless; }; static void pkcs11_acquire_certificate_callback_data_release(struct pkcs11_acquire_certificate_callback_data *data) { @@ -1086,7 +1089,19 @@ static int pkcs11_acquire_certificate_callback( /* Called for every token matching our URI */ - r = pkcs11_token_login(m, session, slot_id, token_info, data->askpw_friendly_name, data->askpw_icon_name, "pkcs11-pin", "pkcs11-pin", UINT64_MAX, false, &pin_used); + r = pkcs11_token_login( + m, + session, + slot_id, + token_info, + data->askpw_friendly_name, + data->askpw_icon_name, + "pkcs11-pin", + "pkcs11-pin", + UINT64_MAX, + data->askpw_flags, + data->headless, + &pin_used); if (r < 0) return r; @@ -1325,6 +1340,7 @@ int pkcs11_crypt_device_callback( "pkcs11-pin", "cryptsetup.pkcs11-pin", data->until, + data->askpw_flags, data->headless, NULL); if (r < 0) diff --git a/src/shared/pkcs11-util.h b/src/shared/pkcs11-util.h index ac2ee08535f..5bc23c14c4c 100644 --- a/src/shared/pkcs11-util.h +++ b/src/shared/pkcs11-util.h @@ -8,6 +8,7 @@ # include #endif +#include "ask-password-api.h" #include "macro.h" #include "openssl-util.h" #include "time-util.h" @@ -47,7 +48,7 @@ char *pkcs11_token_manufacturer_id(const CK_TOKEN_INFO *token_info); char *pkcs11_token_model(const CK_TOKEN_INFO *token_info); int pkcs11_token_login_by_pin(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, const CK_TOKEN_INFO *token_info, const char *token_label, const void *pin, size_t pin_size); -int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *key_name, const char *credential_name, usec_t until, bool headless, char **ret_used_pin); +int pkcs11_token_login(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, CK_SLOT_ID slotid, const CK_TOKEN_INFO *token_info, const char *friendly_name, const char *icon_name, const char *key_name, const char *credential_name, usec_t until, AskPasswordFlags ask_password_flags, bool headless, char **ret_used_pin); int pkcs11_token_find_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object); #if HAVE_OPENSSL @@ -75,6 +76,7 @@ typedef struct { size_t decrypted_key_size; bool free_encrypted_key; bool headless; + AskPasswordFlags askpw_flags; } pkcs11_crypt_device_callback_data; void pkcs11_crypt_device_callback_data_release(pkcs11_crypt_device_callback_data *data); @@ -102,6 +104,7 @@ typedef struct { const char *friendly_name; usec_t until; bool headless; + AskPasswordFlags askpw_flags; } systemd_pkcs11_plugin_params; int pkcs11_list_tokens(void);