]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Add support for systemd-pkcs11 libcryptsetup plugin. 19797/head
authorOndrej Kozina <okozina@redhat.com>
Thu, 20 May 2021 13:37:08 +0000 (15:37 +0200)
committerOndrej Kozina <okozina@redhat.com>
Thu, 19 Aug 2021 11:58:10 +0000 (13:58 +0200)
Add support for systemd-pkcs11 based LUKS2 device activation
via libcryptsetup plugin. This make the feature (pkcs11 sealed
LUKS2 keyslot passphrase) usable from both systemd utilities
and cryptsetup cli.

The feature is configured via -Dlibcryptsetup-plugins combo
with default value set to 'auto'. It get's enabled automatically
when cryptsetup 2.4.0 or later is installed in build system.

meson.build
src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-pkcs11.c [new file with mode: 0644]
src/cryptsetup/cryptsetup-tokens/cryptsetup-token-util.h
src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c [new file with mode: 0644]
src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.h [new file with mode: 0644]
src/cryptsetup/cryptsetup-tokens/meson.build
src/cryptsetup/cryptsetup.c
src/shared/pkcs11-util.h

index 22e7ac1237a963f0308f659f8b8534dc1086265e..f7b18c6b98ee9a8d5f75c23f26675ef481484ec9 100644 (file)
@@ -1801,6 +1801,20 @@ if conf.get('HAVE_LIBCRYPTSETUP_PLUGINS') == 1
                         install : true,
                         install_dir : libcryptsetup_plugins_dir)
         endif
+
+        if conf.get('HAVE_P11KIT') == 1
+                cryptsetup_token_systemd_pkcs11 = shared_library(
+                        'cryptsetup-token-systemd-pkcs11',
+                        link_args : ['-shared',
+                                     '-Wl,--version-script=' + cryptsetup_token_sym_path],
+                        dependencies : libshared_deps + [libcryptsetup, versiondep],
+                        link_with : [libshared],
+                        link_whole : [cryptsetup_token_systemd_pkcs11_static],
+                        link_depends : cryptsetup_token_sym,
+                        install_rpath : rootlibexecdir,
+                        install : true,
+                        install_dir : libcryptsetup_plugins_dir)
+        endif
 endif
 
 ############################################################
diff --git a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-pkcs11.c b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-pkcs11.c
new file mode 100644 (file)
index 0000000..8e26f4f
--- /dev/null
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <errno.h>
+#include <libcryptsetup.h>
+
+#include "cryptsetup-token.h"
+#include "cryptsetup-token-util.h"
+#include "hexdecoct.h"
+#include "json.h"
+#include "luks2-pkcs11.h"
+#include "memory-util.h"
+#include "pkcs11-util.h"
+#include "version.h"
+
+#define TOKEN_NAME "systemd-pkcs11"
+#define TOKEN_VERSION_MAJOR "1"
+#define TOKEN_VERSION_MINOR "0"
+
+/* for libcryptsetup debug purpose */
+_public_ const char *cryptsetup_token_version(void) {
+        return TOKEN_VERSION_MAJOR "." TOKEN_VERSION_MINOR " systemd-v" STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")";
+}
+
+_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 */) {
+
+        const char *json;
+        int r;
+
+        assert(!pin || pin_size);
+        assert(token >= 0);
+
+        /* This must not fail at this moment (internal error) */
+        r = crypt_token_json_get(cd, token, &json);
+        assert(token == r);
+        assert(json);
+
+        return acquire_luks2_key(cd, json, usrptr, pin, pin_size, password, password_len);
+}
+
+/*
+ * 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-pkcs11'):
+ *
+ * - 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 funtion (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
+ */
+_public_ void cryptsetup_token_buffer_free(void *buffer, size_t buffer_len) {
+        erase_and_free(buffer);
+}
+
+/*
+ * prints systemd-pkcs11 token content in crypt_dump().
+ * 'type' and 'keyslots' fields are printed by libcryptsetup
+ */
+_public_ void cryptsetup_token_dump(
+                struct crypt_device *cd /* is always LUKS2 context */,
+                const char *json /* validated 'systemd-pkcs11' token if cryptsetup_token_validate is defined */) {
+
+        int r;
+        size_t pkcs11_key_size;
+        _cleanup_free_ char *pkcs11_uri = NULL, *key_str = NULL;
+        _cleanup_free_ void *pkcs11_key = NULL;
+
+        r = parse_luks2_pkcs11_data(cd, json, &pkcs11_uri, &pkcs11_key, &pkcs11_key_size);
+        if (r < 0)
+                return (void) crypt_log_debug_errno(cd, r, "Failed to parse " TOKEN_NAME " metadata: %m.");
+
+        r = crypt_dump_buffer_to_hex_string(pkcs11_key, pkcs11_key_size, &key_str);
+        if (r < 0)
+                return (void) crypt_log_debug_errno(cd, r, "Can not dump " TOKEN_NAME " content: %m");
+
+        crypt_log(cd, "\tpkcs11-uri: %s\n", pkcs11_uri);
+        crypt_log(cd, "\tpkcs11-key: %s\n", key_str);
+}
+
+/*
+ * Note:
+ *   If plugin is available in library path, it's called in before following libcryptsetup calls:
+ *
+ *   crypt_token_json_set, crypt_dump, any crypt_activate_by_token_* flavour
+ */
+_public_ int cryptsetup_token_validate(
+                struct crypt_device *cd, /* is always LUKS2 context */
+                const char *json /* contains valid 'type' and 'keyslots' fields. 'type' is 'systemd-pkcs11' */) {
+
+        int r;
+        JsonVariant *w;
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+
+        r = json_parse(json, 0, &v, NULL, NULL);
+        if (r < 0)
+                return crypt_log_debug_errno(cd, r, "Could not parse " TOKEN_NAME " json object: %m.");
+
+        w = json_variant_by_key(v, "pkcs11-uri");
+        if (!w || !json_variant_is_string(w)) {
+                crypt_log_debug(cd, "PKCS#11 token data lacks 'pkcs11-uri' field.");
+                return 1;
+        }
+
+        if (!pkcs11_uri_valid(json_variant_string(w))) {
+                crypt_log_debug(cd, "PKCS#11 token data contains invalid PKCS#11 URI.");
+                return 1;
+        }
+
+        w = json_variant_by_key(v, "pkcs11-key");
+        if (!w || !json_variant_is_string(w)) {
+                crypt_log_debug(cd, "PKCS#11 token data lacks 'pkcs11-key' field.");
+                return 1;
+        }
+
+        r = unbase64mem(json_variant_string(w), SIZE_MAX, NULL, NULL);
+        if (r < 0)
+                return crypt_log_debug_errno(cd, r, "Failed to decode base64 encoded key: %m.");
+
+        return 0;
+}
index 124bfab63b25b0a50a42441fe641aeee46f2e4ab..57ffca136f4740aa3528b4332b2d137c9c557b35 100644 (file)
@@ -4,13 +4,15 @@
 
 #include <stdbool.h>
 #include <stddef.h>
+#include <libcryptsetup.h>
 
 /* crypt_dump() internal indentation magic */
 #define CRYPT_DUMP_LINE_SEP "\n\t            "
 
-#define crypt_log_debug(cd, ...) crypt_logf(cd, CRYPT_LOG_DEBUG,  __VA_ARGS__)
-#define crypt_log_error(cd, ...) crypt_logf(cd, CRYPT_LOG_ERROR,  __VA_ARGS__)
-#define crypt_log(cd, ...)       crypt_logf(cd, CRYPT_LOG_NORMAL, __VA_ARGS__)
+#define crypt_log_debug(cd, ...)   crypt_logf(cd, CRYPT_LOG_DEBUG,   __VA_ARGS__)
+#define crypt_log_error(cd, ...)   crypt_logf(cd, CRYPT_LOG_ERROR,   __VA_ARGS__)
+#define crypt_log_verbose(cd, ...) crypt_logf(cd, CRYPT_LOG_VERBOSE, __VA_ARGS__)
+#define crypt_log(cd, ...)         crypt_logf(cd, CRYPT_LOG_NORMAL,  __VA_ARGS__)
 
 #define crypt_log_full_errno(cd, e, lvl, ...) ({ \
         int _e = abs(e), _s = errno; \
diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c b/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c
new file mode 100644 (file)
index 0000000..9e88c8c
--- /dev/null
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <p11-kit/p11-kit.h>
+#include <p11-kit/uri.h>
+
+#include "cryptsetup-token-util.h"
+#include "escape.h"
+#include "hexdecoct.h"
+#include "json.h"
+#include "luks2-pkcs11.h"
+#include "memory-util.h"
+#include "pkcs11-util.h"
+#include "time-util.h"
+
+struct luks2_pkcs11_callback_data {
+        struct crypt_device *cd;
+        const char *pin;
+        size_t pin_size;
+        void *encrypted_key;
+        size_t encrypted_key_size;
+        void *decrypted_key;
+        size_t decrypted_key_size;
+};
+
+static int luks2_pkcs11_callback(
+                CK_FUNCTION_LIST *m,
+                CK_SESSION_HANDLE session,
+                CK_SLOT_ID slot_id,
+                const CK_SLOT_INFO *slot_info,
+                const CK_TOKEN_INFO *token_info,
+                P11KitUri *uri,
+                void *userdata) {
+
+        CK_OBJECT_HANDLE object;
+        CK_RV rv;
+        CK_TOKEN_INFO updated_token_info;
+        int r;
+        _cleanup_free_ char *token_label = NULL;
+        struct luks2_pkcs11_callback_data *data = userdata;
+
+        assert(m);
+        assert(slot_info);
+        assert(token_info);
+        assert(uri);
+        assert(data);
+
+        token_label = pkcs11_token_label(token_info);
+        if (!token_label)
+                return -ENOMEM;
+
+        /* Called for every token matching our URI */
+        r = pkcs11_token_login_by_pin(m, session, token_info, token_label, data->pin, data->pin_size);
+        if (r == -ENOLCK) {
+                /* Referesh the token info, so that we can prompt knowing the new flags if they changed. */
+                rv = m->C_GetTokenInfo(slot_id, &updated_token_info);
+                if (rv != CKR_OK) {
+                        crypt_log_error(data->cd,
+                                       "Failed to acquire updated security token information for slot %lu: %s",
+                                       slot_id, p11_kit_strerror(rv));
+                        return -EIO;
+                }
+                token_info = &updated_token_info;
+                r = -ENOANO;
+        }
+
+        if (r == -ENOANO) {
+                if (FLAGS_SET(token_info->flags, CKF_USER_PIN_FINAL_TRY))
+                        crypt_log_error(data->cd, "Please enter correct PIN for security token "
+                                        "'%s' in order to unlock it (final try).", token_label);
+                else if (FLAGS_SET(token_info->flags, CKF_USER_PIN_COUNT_LOW))
+                        crypt_log_error(data->cd, "PIN has been entered incorrectly previously, "
+                                      "please enter correct PIN for security token '%s' in order to unlock it.",
+                                      token_label);
+        }
+
+        if (r == -EPERM) /* pin is locked, but map it to -ENOANO anyway */
+                r = -ENOANO;
+
+        if (r < 0)
+                return r;
+
+        r = pkcs11_token_find_private_key(m, session, uri, &object);
+        if (r < 0)
+                return r;
+
+        r = pkcs11_token_decrypt_data(
+                        m,
+                        session,
+                        object,
+                        data->encrypted_key,
+                        data->encrypted_key_size,
+                        &data->decrypted_key,
+                        &data->decrypted_key_size);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+static void luks2_pkcs11_callback_data_release(struct luks2_pkcs11_callback_data *data) {
+        erase_and_free(data->decrypted_key);
+}
+
+static int acquire_luks2_key_by_pin(
+                struct crypt_device *cd,
+                const char *pkcs11_uri,
+                const void *pin,
+                size_t pin_size,
+                void *encrypted_key,
+                size_t encrypted_key_size,
+                void **ret_decrypted_key,
+                size_t *ret_decrypted_key_size) {
+
+        int r;
+        _cleanup_(luks2_pkcs11_callback_data_release) struct luks2_pkcs11_callback_data data = {
+                .cd = cd,
+                .pin = pin,
+                .pin_size = pin_size,
+                .encrypted_key = encrypted_key,
+                .encrypted_key_size = encrypted_key_size,
+        };
+
+        assert(pkcs11_uri);
+        assert(encrypted_key);
+        assert(ret_decrypted_key);
+        assert(ret_decrypted_key_size);
+
+        r = pkcs11_find_token(pkcs11_uri, luks2_pkcs11_callback, &data);
+        if (r < 0)
+                return r;
+
+        *ret_decrypted_key = TAKE_PTR(data.decrypted_key);
+        *ret_decrypted_key_size = data.decrypted_key_size;
+
+        return 0;
+}
+
+/* called from within systemd utilities */
+static int acquire_luks2_key_systemd(
+                const char *pkcs11_uri,
+                systemd_pkcs11_plugin_params *params,
+                void *encrypted_key,
+                size_t encrypted_key_size,
+                void **ret_decrypted_key,
+                size_t *ret_decrypted_key_size) {
+
+        int r;
+        _cleanup_(pkcs11_crypt_device_callback_data_release) pkcs11_crypt_device_callback_data data = {
+                .encrypted_key = encrypted_key,
+                .encrypted_key_size = encrypted_key_size,
+                .free_encrypted_key = false
+        };
+
+        assert(pkcs11_uri);
+        assert(encrypted_key);
+        assert(ret_decrypted_key);
+        assert(ret_decrypted_key_size);
+        assert(params);
+
+        data.friendly_name = params->friendly_name;
+        data.headless = params->headless;
+        data.until = params->until;
+
+        /* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */
+        r = pkcs11_find_token(pkcs11_uri, pkcs11_crypt_device_callback, &data);
+        if (r < 0)
+                return r;
+
+        *ret_decrypted_key = TAKE_PTR(data.decrypted_key);
+        *ret_decrypted_key_size = data.decrypted_key_size;
+
+        return 0;
+}
+
+int acquire_luks2_key(
+                struct crypt_device *cd,
+                const char *json,
+                void *userdata,
+                const void *pin,
+                size_t pin_size,
+                char **ret_password,
+                size_t *ret_password_size) {
+
+        int r;
+        size_t decrypted_key_size, encrypted_key_size;
+        _cleanup_(erase_and_freep) void *decrypted_key = NULL;
+        _cleanup_(erase_and_freep) char *base64_encoded = NULL;
+        _cleanup_free_ char *pkcs11_uri = NULL;
+        _cleanup_free_ void *encrypted_key = NULL;
+        systemd_pkcs11_plugin_params *pkcs11_params = userdata;
+
+        assert(json);
+        assert(ret_password);
+        assert(ret_password_size);
+
+        r = parse_luks2_pkcs11_data(cd, json, &pkcs11_uri, &encrypted_key, &encrypted_key_size);
+        if (r < 0)
+                return r;
+
+        if (pkcs11_params && pin)
+                crypt_log_verbose(cd, "PIN parameter ignored in interactive mode.");
+
+        if (pkcs11_params) /* systemd based activation with interactive pin query callbacks */
+                r = acquire_luks2_key_systemd(
+                        pkcs11_uri,
+                        pkcs11_params,
+                        encrypted_key, encrypted_key_size,
+                        &decrypted_key, &decrypted_key_size);
+        else /* default activation that provides single PIN if needed */
+                r = acquire_luks2_key_by_pin(
+                        cd, pkcs11_uri, pin, pin_size,
+                        encrypted_key, encrypted_key_size,
+                        &decrypted_key, &decrypted_key_size);
+        if (r < 0)
+                return r;
+
+        r = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
+        if (r < 0)
+                return crypt_log_error_errno(cd, r, "Can not base64 encode key: %m");
+
+        *ret_password = TAKE_PTR(base64_encoded);
+        *ret_password_size = strlen(*ret_password);
+
+        return 0;
+}
+
+int parse_luks2_pkcs11_data(
+                struct crypt_device *cd,
+                const char *json,
+                char **ret_uri,
+                void **ret_encrypted_key,
+                size_t *ret_encrypted_key_size) {
+
+        int r;
+        size_t key_size;
+        _cleanup_free_ char *uri = NULL;
+        _cleanup_free_ void *key = NULL;
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        JsonVariant *w;
+
+        assert(json);
+        assert(ret_uri);
+        assert(ret_encrypted_key);
+        assert(ret_encrypted_key_size);
+
+        r = json_parse(json, 0, &v, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        w = json_variant_by_key(v, "pkcs11-uri");
+        if (!w)
+                return -EINVAL;
+
+        uri = strdup(json_variant_string(w));
+        if (!uri)
+                return -ENOMEM;
+
+        w = json_variant_by_key(v, "pkcs11-key");
+        if (!w)
+                return -EINVAL;
+
+        r = unbase64mem(json_variant_string(w), SIZE_MAX, &key, &key_size);
+        if (r < 0)
+                return crypt_log_debug_errno(cd, r, "Failed to decode base64 encoded key: %m.");
+
+        *ret_uri = TAKE_PTR(uri);
+        *ret_encrypted_key = TAKE_PTR(key);
+        *ret_encrypted_key_size = key_size;
+
+        return 0;
+}
diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.h b/src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.h
new file mode 100644 (file)
index 0000000..41ce9f0
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#pragma once
+
+struct crypt_device;
+
+int acquire_luks2_key(
+                struct crypt_device *cd,
+                const char *json,
+                void *userdata,
+                const void *pin,
+                size_t pin_size,
+                char **password,
+                size_t *password_size);
+
+int parse_luks2_pkcs11_data(
+                struct crypt_device *cd,
+                const char *json,
+                char **ret_uri,
+                void **ret_encrypted_key,
+                size_t *ret_encrypted_key_size);
index 569fafb89f48972af92876624af2b36934ab30e2..d174fcb714ec7f91845b08502b292da2baeb1a2e 100644 (file)
@@ -43,4 +43,22 @@ if conf.get('HAVE_LIBFIDO2') == 1
                 c_args : cryptsetup_token_c_args)
 endif
 
+if conf.get('HAVE_P11KIT') == 1
+        cryptsetup_token_systemd_pkcs11_sources = files('''
+                cryptsetup-token-systemd-pkcs11.c
+                cryptsetup-token.h
+                cryptsetup-token-util.h
+                cryptsetup-token-util.c
+                luks2-pkcs11.c
+                luks2-pkcs11.h
+        '''.split())
+
+        cryptsetup_token_systemd_pkcs11_static = static_library(
+                'cryptsetup-token-systemd-pkcs11_static',
+                cryptsetup_token_systemd_pkcs11_sources,
+                include_directories : includes,
+                dependencies : libshared_deps + [libcryptsetup, versiondep],
+                c_args : cryptsetup_token_c_args)
+endif
+
 endif
index 4615171b745356787dd0000696b8b4c8b36a2428..fdd57def86866bd17f15c2b0585bbe9d7356bec0 100644 (file)
@@ -996,6 +996,32 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
         return 0;
 }
 
+static int attach_luks2_by_pkcs11(
+                struct crypt_device *cd,
+                const char *name,
+                const char *friendly_name,
+                usec_t until,
+                bool headless,
+                uint32_t flags) {
+
+        int r = -ENOTSUP;
+#if HAVE_LIBCRYPTSETUP_PLUGINS
+        if (!crypt_get_type(cd) || strcmp(crypt_get_type(cd), CRYPT_LUKS2))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Automatic PKCS#11 metadata requires LUKS2 device.");
+
+        systemd_pkcs11_plugin_params params = {
+                .friendly_name = friendly_name,
+                .until = until,
+                .headless = headless
+        };
+
+        r = crypt_activate_by_token_pin(cd, name, "systemd-pkcs11", CRYPT_ANY_TOKEN, NULL, 0, &params, flags);
+        if (r > 0) /* returns unlocked keyslot id on success */
+                r = 0;
+#endif
+        return r;
+}
+
 static int attach_luks_or_plain_or_bitlk_by_pkcs11(
                 struct crypt_device *cd,
                 const char *name,
@@ -1013,23 +1039,26 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
         _cleanup_free_ void *discovered_key = NULL;
         int keyslot = arg_key_slot, r;
-        const char *uri;
+        const char *uri = NULL;
+        bool use_libcryptsetup_plugin = libcryptsetup_plugins_support();
 
         assert(cd);
         assert(name);
         assert(arg_pkcs11_uri || arg_pkcs11_uri_auto);
 
         if (arg_pkcs11_uri_auto) {
-                r = find_pkcs11_auto_data(cd, &discovered_uri, &discovered_key, &discovered_key_size, &keyslot);
-                if (IN_SET(r, -ENOTUNIQ, -ENXIO))
-                        return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
-                                               "Automatic PKCS#11 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
-                if (r < 0)
-                        return r;
+                if (!use_libcryptsetup_plugin) {
+                        r = find_pkcs11_auto_data(cd, &discovered_uri, &discovered_key, &discovered_key_size, &keyslot);
+                        if (IN_SET(r, -ENOTUNIQ, -ENXIO))
+                                return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
+                                                       "Automatic PKCS#11 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
+                        if (r < 0)
+                                return r;
 
-                uri = discovered_uri;
-                key_data = discovered_key;
-                key_data_size = discovered_key_size;
+                        uri = discovered_uri;
+                        key_data = discovered_key;
+                        key_data_size = discovered_key_size;
+                }
         } else {
                 uri = arg_pkcs11_uri;
 
@@ -1044,17 +1073,22 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
         for (;;) {
                 bool processed = false;
 
-                r = decrypt_pkcs11_key(
-                                name,
-                                friendly,
-                                uri,
-                                key_file, arg_keyfile_size, arg_keyfile_offset,
-                                key_data, key_data_size,
-                                until,
-                                arg_headless,
-                                &decrypted_key, &decrypted_key_size);
-                if (r >= 0)
-                        break;
+                if (use_libcryptsetup_plugin && arg_pkcs11_uri_auto)
+                        r = attach_luks2_by_pkcs11(cd, name, friendly, until, arg_headless, flags);
+                else {
+                        r = decrypt_pkcs11_key(
+                                        name,
+                                        friendly,
+                                        uri,
+                                        key_file, arg_keyfile_size, arg_keyfile_offset,
+                                        key_data, key_data_size,
+                                        until,
+                                        arg_headless,
+                                        &decrypted_key, &decrypted_key_size);
+                        if (r >= 0)
+                                break;
+                }
+
                 if (r != -EAGAIN) /* EAGAIN means: token not found */
                         return r;
 
@@ -1094,6 +1128,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
 
                 log_debug("Got one or more potentially relevant udev events, rescanning PKCS#11...");
         }
+        assert(decrypted_key);
 
         if (pass_volume_key)
                 r = crypt_activate_by_volume_key(cd, name, decrypted_key, decrypted_key_size, flags);
index afacec55bfbcefcee50c3bbc9d0e1fd13e2aefb2..f8195d7a369a0175e294d12b9c734520d54c09d2 100644 (file)
@@ -74,5 +74,11 @@ int pkcs11_crypt_device_callback(
 
 #endif
 
+typedef struct {
+        const char *friendly_name;
+        usec_t until;
+        bool headless;
+} systemd_pkcs11_plugin_params;
+
 int pkcs11_list_tokens(void);
 int pkcs11_find_token_auto(char **ret);