diff options
Diffstat (limited to 'src/cryptsetup')
-rw-r--r-- | src/cryptsetup/cryptsetup-generator.c | 25 | ||||
-rw-r--r-- | src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-fido2.c | 15 | ||||
-rw-r--r-- | src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c | 48 | ||||
-rw-r--r-- | src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.c | 26 | ||||
-rw-r--r-- | src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.h | 2 | ||||
-rw-r--r-- | src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c | 15 | ||||
-rw-r--r-- | src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h | 1 | ||||
-rw-r--r-- | src/cryptsetup/cryptsetup.c | 77 |
8 files changed, 149 insertions, 60 deletions
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 8f5ad67f48..07903f1044 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -227,9 +227,11 @@ static int generate_device_umount(const char *name, return 0; } -static int print_dependencies(FILE *f, const char* device_path) { +static int print_dependencies(FILE *f, const char* device_path, const char* timeout_value, bool canfail) { int r; + assert(!canfail || timeout_value); + if (STR_IN_SET(device_path, "-", "none")) /* None, nothing to do */ return 0; @@ -259,9 +261,16 @@ static int print_dependencies(FILE *f, const char* device_path) { if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); - fprintf(f, - "After=%1$s\n" - "Requires=%1$s\n", unit); + fprintf(f, "After=%1$s\n", unit); + if (canfail) { + fprintf(f, "Wants=%1$s\n", unit); + r = write_drop_in_format(arg_dest, unit, 90, "device-timeout", + "# Automatically generated by systemd-cryptsetup-generator \n\n" + "[Unit]\nJobRunningTimeoutSec=%s", timeout_value); + if (r < 0) + return log_error_errno(r, "Failed to write device drop-in: %m"); + } else + fprintf(f, "Requires=%1$s\n", unit); } else { /* Regular file, add mount dependency */ _cleanup_free_ char *escaped_path = specifier_escape(device_path); @@ -463,14 +472,18 @@ static int create_disk( netdev ? "remote-cryptsetup.target" : "cryptsetup.target"); if (key_file && !keydev) { - r = print_dependencies(f, key_file); + r = print_dependencies(f, key_file, + keyfile_timeout_value, + /* canfail= */ keyfile_can_timeout > 0); if (r < 0) return r; } /* Check if a header option was specified */ if (detached_header > 0 && !headerdev) { - r = print_dependencies(f, header_path); + r = print_dependencies(f, header_path, + NULL, + /* canfail= */ false); /* header is always necessary */ if (r < 0) return r; } diff --git a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-fido2.c b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-fido2.c index 0db0f562e5..3027804065 100644 --- a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-fido2.c +++ b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-fido2.c @@ -43,18 +43,11 @@ _public_ int cryptsetup_token_open_pin( assert_se(token == r); assert(json); - if (pin && memchr(pin, 0, pin_size - 1)) - return crypt_log_error_errno(cd, ENOANO, "PIN must be characters string."); - - /* pin was passed as pin = pin, pin_size = strlen(pin). We need to add terminating - * NULL byte to addressable memory*/ - if (pin && pin[pin_size-1] != '\0') { - pin_string = strndup(pin, pin_size); - if (!pin_string) - return crypt_log_oom(cd); - } + r = crypt_normalize_pin(pin, pin_size, &pin_string); + if (r < 0) + return crypt_log_debug_errno(cd, r, "Can not normalize PIN: %m"); - return acquire_luks2_key(cd, json, (const char *)usrptr, pin_string ?: pin, password, password_len); + return acquire_luks2_key(cd, json, (const char *)usrptr, pin_string, password, password_len); } /* diff --git a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c index 23df974999..bbc8a39c98 100644 --- a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c +++ b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c @@ -35,22 +35,11 @@ static int log_debug_open_error(struct crypt_device *cd, int r) { return crypt_log_debug_errno(cd, r, TOKEN_NAME " open failed: %m."); } -/* - * This function is called from within following libcryptsetup calls - * provided conditions further below are met: - * - * crypt_activate_by_token(), crypt_activate_by_token_type(type == 'systemd-tpm2'): - * - * - token is assigned to at least one luks2 keyslot eligible to activate LUKS2 device - * (alternatively: name is set to null, flags contains CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY - * and token is assigned to at least single keyslot). - * - * - if plugin defines validate function (see cryptsetup_token_validate below) it must have - * passed the check (aka return 0) - */ -_public_ int cryptsetup_token_open( +_public_ int cryptsetup_token_open_pin( struct crypt_device *cd, /* is always LUKS2 context */ int token /* is always >= 0 */, + const char *pin, + size_t pin_size, char **password, /* freed by cryptsetup_token_buffer_free */ size_t *password_len, void *usrptr /* plugin defined parameter passed to crypt_activate_by_token*() API */) { @@ -66,8 +55,9 @@ _public_ int cryptsetup_token_open( _cleanup_free_ void *blob = NULL, *policy_hash = NULL; _cleanup_free_ char *base64_blob = NULL, *hex_policy_hash = NULL; _cleanup_(erase_and_freep) void *decrypted_key = NULL; - _cleanup_(erase_and_freep) char *base64_encoded = NULL; + _cleanup_(erase_and_freep) char *base64_encoded = NULL, *pin_string = NULL; + assert(!pin || pin_size); assert(password); assert(password_len); assert(token >= 0); @@ -77,6 +67,10 @@ _public_ int cryptsetup_token_open( assert(token == r); assert(json); + r = crypt_normalize_pin(pin, pin_size, &pin_string); + if (r < 0) + return crypt_log_debug_errno(cd, r, "Can not normalize PIN: %m"); + if (usrptr) params = *(systemd_tpm2_plugin_params *)usrptr; @@ -105,6 +99,7 @@ _public_ int cryptsetup_token_open( policy_hash, policy_hash_size, flags, + pin_string, &decrypted_key, &decrypted_key_size); if (r < 0) @@ -123,6 +118,29 @@ _public_ int cryptsetup_token_open( } /* + * This function is called from within following libcryptsetup calls + * provided conditions further below are met: + * + * crypt_activate_by_token(), crypt_activate_by_token_type(type == 'systemd-tpm2'): + * + * - token is assigned to at least one luks2 keyslot eligible to activate LUKS2 device + * (alternatively: name is set to null, flags contains CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY + * and token is assigned to at least single keyslot). + * + * - if plugin defines validate function (see cryptsetup_token_validate below) it must have + * passed the check (aka return 0) + */ +_public_ int cryptsetup_token_open( + struct crypt_device *cd, /* is always LUKS2 context */ + int token /* is always >= 0 */, + char **password, /* freed by cryptsetup_token_buffer_free */ + size_t *password_len, + void *usrptr /* plugin defined parameter passed to crypt_activate_by_token*() API */) { + + return cryptsetup_token_open_pin(cd, token, NULL, 0, password, password_len, usrptr); +} + +/* * libcryptsetup callback for memory deallocation of 'password' parameter passed in * any crypt_token_open_* plugin function */ diff --git a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.c b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.c index f4086ae367..e305d8ba79 100644 --- a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.c +++ b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.c @@ -56,3 +56,29 @@ int crypt_dump_hex_string(const char *hex_str, char **ret_dump_str) { return 0; } + +int crypt_normalize_pin(const void *pin, size_t pin_size, char **ret_pin_string) { + + _cleanup_free_ char *pin_string = NULL; + + assert(pin || !pin_size); + assert(ret_pin_string); + + if (!pin) { + *ret_pin_string = NULL; + return 0; + } + + /* Refuse embedded NULL bytes, but allow trailing NULL */ + if (memchr(pin, 0, pin_size - 1)) + return -EINVAL; + + /* Enforce trailing NULL byte if missing */ + pin_string = memdup_suffix0(pin, pin_size); + if (!pin_string) + return -ENOMEM; + + *ret_pin_string = TAKE_PTR(pin_string); + + return 0; +} diff --git a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.h b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.h index 57ffca136f..146beffb30 100644 --- a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.h +++ b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.h @@ -36,3 +36,5 @@ int crypt_dump_buffer_to_hex_string( char **ret_dump_str); int crypt_dump_hex_string(const char *hex_str, char **ret_dump_str); + +int crypt_normalize_pin(const void *pin, size_t pin_size, char **ret_pin_string); diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c index 0d6e4bc0f8..f0286ec1bf 100644 --- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c +++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c @@ -22,11 +22,11 @@ int acquire_luks2_key( const void *policy_hash, size_t policy_hash_size, TPM2Flags flags, + const char *pin, void **ret_decrypted_key, size_t *ret_decrypted_key_size) { _cleanup_free_ char *auto_device = NULL; - _cleanup_(erase_and_freep) char *pin_str = NULL; int r; assert(ret_decrypted_key); @@ -42,22 +42,15 @@ int acquire_luks2_key( device = auto_device; } - r = getenv_steal_erase("PIN", &pin_str); - if (r < 0) - return log_error_errno(r, "Failed to acquire PIN from environment: %m"); - if (!r) { - /* PIN entry is not supported by plugin, let it fallback, possibly to sd-cryptsetup's - * internal handling. */ - if (flags & TPM2_FLAGS_USE_PIN) - return -EOPNOTSUPP; - } + if ((flags & TPM2_FLAGS_USE_PIN) && !pin) + return -ENOANO; return tpm2_unseal( device, pcr_mask, pcr_bank, primary_alg, key_data, key_data_size, - policy_hash, policy_hash_size, pin_str, + policy_hash, policy_hash_size, pin, ret_decrypted_key, ret_decrypted_key_size); } diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h index 34c93216ee..5e33418025 100644 --- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h +++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h @@ -16,6 +16,7 @@ int acquire_luks2_key( const void *policy_hash, size_t policy_hash_size, TPM2Flags flags, + const char *pin, void **ret_decrypted_key, size_t *ret_decrypted_key_size); diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index da6d77b0b0..f0130eb238 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -964,20 +964,24 @@ static int acquire_pins_from_env_variable(char ***ret_pins) { } #endif -static int attach_luks2_by_fido2_via_plugin( +static int crypt_activate_by_token_pin_ask_password( struct crypt_device *cd, const char *name, + const char *type, usec_t until, bool headless, void *usrptr, - uint32_t activation_flags) { + uint32_t activation_flags, + const char *message, + const char *key_name, + const char *credential_name) { #if HAVE_LIBCRYPTSETUP_PLUGINS AskPasswordFlags flags = ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED; _cleanup_strv_free_erase_ char **pins = NULL; int r; - r = crypt_activate_by_token_pin(cd, name, "systemd-fido2", CRYPT_ANY_TOKEN, NULL, 0, usrptr, activation_flags); + r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, NULL, 0, usrptr, activation_flags); if (r > 0) /* returns unlocked keyslot id on success */ r = 0; if (r != -ENOANO) /* needs pin or pin is wrong */ @@ -988,7 +992,7 @@ static int attach_luks2_by_fido2_via_plugin( return r; STRV_FOREACH(p, pins) { - r = crypt_activate_by_token_pin(cd, name, "systemd-fido2", CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags); + r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags); if (r > 0) /* returns unlocked keyslot id on success */ r = 0; if (r != -ENOANO) /* needs pin or pin is wrong */ @@ -1000,12 +1004,12 @@ static int attach_luks2_by_fido2_via_plugin( for (;;) { pins = strv_free_erase(pins); - r = ask_password_auto("Please enter security token PIN:", "drive-harddisk", NULL, "fido2-pin", "cryptsetup.fido2-pin", until, flags, &pins); + r = ask_password_auto(message, "drive-harddisk", 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, "systemd-fido2", CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags); + r = crypt_activate_by_token_pin(cd, name, type, CRYPT_ANY_TOKEN, *p, strlen(*p), usrptr, activation_flags); if (r > 0) /* returns unlocked keyslot id on success */ r = 0; if (r != -ENOANO) /* needs pin or pin is wrong */ @@ -1020,6 +1024,27 @@ static int attach_luks2_by_fido2_via_plugin( #endif } +static int attach_luks2_by_fido2_via_plugin( + struct crypt_device *cd, + const char *name, + usec_t until, + bool headless, + void *usrptr, + uint32_t activation_flags) { + + return crypt_activate_by_token_pin_ask_password( + cd, + name, + "systemd-fido2", + until, + headless, + usrptr, + activation_flags, + "Please enter security token PIN:", + "fido2-pin", + "cryptsetup.fido2-pin"); +} + static int attach_luks_or_plain_or_bitlk_by_fido2( struct crypt_device *cd, const char *name, @@ -1363,25 +1388,31 @@ static int make_tpm2_device_monitor( static int attach_luks2_by_tpm2_via_plugin( struct crypt_device *cd, const char *name, + usec_t until, + bool headless, uint32_t flags) { #if HAVE_LIBCRYPTSETUP_PLUGINS - int r; - systemd_tpm2_plugin_params params = { .search_pcr_mask = arg_tpm2_pcr_mask, .device = arg_tpm2_device }; - if (!crypt_token_external_path()) + if (!libcryptsetup_plugins_support()) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Libcryptsetup has external plugins support disabled."); - r = crypt_activate_by_token_pin(cd, name, "systemd-tpm2", CRYPT_ANY_TOKEN, NULL, 0, ¶ms, flags); - if (r > 0) /* returns unlocked keyslot id on success */ - r = 0; - - return r; + return crypt_activate_by_token_pin_ask_password( + cd, + name, + "systemd-tpm2", + until, + headless, + ¶ms, + flags, + "Please enter TPM2 PIN:", + "tpm2-pin", + "cryptsetup.tpm2-pin"); #else return -EOPNOTSUPP; #endif @@ -1442,7 +1473,9 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2( return -EAGAIN; /* Mangle error code: let's make any form of TPM2 failure non-fatal. */ } } else { - r = attach_luks2_by_tpm2_via_plugin(cd, name, flags); + r = attach_luks2_by_tpm2_via_plugin(cd, name, until, arg_headless, flags); + if (r >= 0) + return 0; /* EAGAIN means: no tpm2 chip found * EOPNOTSUPP means: no libcryptsetup plugins support */ if (r == -ENXIO) @@ -1966,8 +1999,18 @@ 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) { - r = crypt_activate_by_token(cd, volume, CRYPT_ANY_TOKEN, NULL, flags); + if (!key_file && !key_data && getenv_bool("SYSTEMD_CRYPTSETUP_USE_TOKEN_MODULE") != 0) { + r = crypt_activate_by_token_pin_ask_password( + cd, + volume, + NULL, + until, + arg_headless, + NULL, + flags, + "Please enter LUKS2 token PIN:", + "luks2-pin", + "cryptsetup.luks2-pin"); if (r >= 0) { log_debug("Volume %s activated with LUKS token id %i.", volume, r); return 0; |