summaryrefslogtreecommitdiff
path: root/src/cryptsetup
diff options
context:
space:
mode:
authorJonas Witschel <diabonas@archlinux.org>2022-05-25 14:06:12 +0200
committerJonas Witschel <diabonas@archlinux.org>2022-08-05 12:19:57 +0200
commit35ba2b4f0193ea791a19d23ba9f316082f36852b (patch)
tree619339f371e8745e159a89ef0ac54b7d50356a67 /src/cryptsetup
parentd14114995776d6c6640bf7af3845581df8b6532c (diff)
downloadsystemd-35ba2b4f0193ea791a19d23ba9f316082f36852b.tar.gz
cryptsetup: implement cryptsetup_token_open_pin for systemd-tpm2 LUKS2 token
This finishes the implementation started in commit 1f895adac287b5f1b6b854caa586093616ccc172 ("cryptsetup: add libcryptsetup TPM2 PIN support"). Note that the previous implementation took a shortcut by returning EOPNOTSUPP instead of the correct ENOANO as per the cryptsetup documentation. This meant that systemd-cryptsetup fell back to the non-plugin implementation in order to ask for the PIN. Since this does not happen any more when returning ENOANO, we need to ask for the PIN in attach_luks2_by_tpm2_via_plugin() instead like attach_luks2_by_fido2_via_plugin() does.
Diffstat (limited to 'src/cryptsetup')
-rw-r--r--src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c48
-rw-r--r--src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.c26
-rw-r--r--src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.h2
-rw-r--r--src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c15
-rw-r--r--src/cryptsetup/cryptsetup-tokens/luks2-tpm2.h1
-rw-r--r--src/cryptsetup/cryptsetup.c24
6 files changed, 82 insertions, 34 deletions
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 ea56f552f0..7a9878e689 100644
--- a/src/cryptsetup/cryptsetup.c
+++ b/src/cryptsetup/cryptsetup.c
@@ -1275,11 +1275,11 @@ 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
@@ -1289,11 +1289,17 @@ static int attach_luks2_by_tpm2_via_plugin(
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, &params, 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,
+ &params,
+ flags,
+ "Please enter TPM2 PIN:",
+ "tpm2-pin",
+ "cryptsetup.tpm2-pin");
#else
return -EOPNOTSUPP;
#endif
@@ -1354,7 +1360,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)