mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
Merge pull request #19797 from oniko/systemd-fido2-pkcs11-plugins
Add support for remaining systemd fido2 and pkcs11 libcryptsetup plugins
This commit is contained in:
commit
7b58fcdd70
28
meson.build
28
meson.build
@ -1787,6 +1787,34 @@ if conf.get('HAVE_LIBCRYPTSETUP_PLUGINS') == 1
|
||||
install : true,
|
||||
install_dir : libcryptsetup_plugins_dir)
|
||||
endif
|
||||
|
||||
if conf.get('HAVE_LIBFIDO2') == 1
|
||||
cryptsetup_token_systemd_fido2 = shared_library(
|
||||
'cryptsetup-token-systemd-fido2',
|
||||
link_args : ['-shared',
|
||||
'-Wl,--version-script=' + cryptsetup_token_sym_path],
|
||||
dependencies : libshared_deps + [libcryptsetup, versiondep],
|
||||
link_with : [libshared],
|
||||
link_whole : [cryptsetup_token_systemd_fido2_static],
|
||||
link_depends : cryptsetup_token_sym,
|
||||
install_rpath : rootlibexecdir,
|
||||
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
|
||||
|
||||
############################################################
|
||||
|
@ -24,83 +24,6 @@
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
struct pkcs11_callback_data {
|
||||
const char *friendly_name;
|
||||
usec_t until;
|
||||
void *encrypted_key;
|
||||
size_t encrypted_key_size;
|
||||
void *decrypted_key;
|
||||
size_t decrypted_key_size;
|
||||
bool free_encrypted_key;
|
||||
bool headless;
|
||||
};
|
||||
|
||||
static void pkcs11_callback_data_release(struct pkcs11_callback_data *data) {
|
||||
erase_and_free(data->decrypted_key);
|
||||
|
||||
if (data->free_encrypted_key)
|
||||
free(data->encrypted_key);
|
||||
}
|
||||
|
||||
static int 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) {
|
||||
|
||||
struct pkcs11_callback_data *data = userdata;
|
||||
CK_OBJECT_HANDLE object;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(slot_info);
|
||||
assert(token_info);
|
||||
assert(uri);
|
||||
assert(data);
|
||||
|
||||
/* Called for every token matching our URI */
|
||||
|
||||
r = pkcs11_token_login(
|
||||
m,
|
||||
session,
|
||||
slot_id,
|
||||
token_info,
|
||||
data->friendly_name,
|
||||
"drive-harddisk",
|
||||
"pkcs11-pin",
|
||||
"cryptsetup.pkcs11-pin",
|
||||
data->until,
|
||||
data->headless,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* We are likely called during early boot, where entropy is scarce. Mix some data from the PKCS#11
|
||||
* token, if it supports that. It should be cheap, given that we already are talking to it anyway and
|
||||
* shouldn't hurt. */
|
||||
(void) pkcs11_token_acquire_rng(m, session);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int decrypt_pkcs11_key(
|
||||
const char *volume_name,
|
||||
const char *friendly_name,
|
||||
@ -115,7 +38,7 @@ int decrypt_pkcs11_key(
|
||||
void **ret_decrypted_key,
|
||||
size_t *ret_decrypted_key_size) {
|
||||
|
||||
_cleanup_(pkcs11_callback_data_release) struct pkcs11_callback_data data = {
|
||||
_cleanup_(pkcs11_crypt_device_callback_data_release) pkcs11_crypt_device_callback_data data = {
|
||||
.friendly_name = friendly_name,
|
||||
.until = until,
|
||||
.headless = headless,
|
||||
@ -155,7 +78,7 @@ int decrypt_pkcs11_key(
|
||||
data.free_encrypted_key = true;
|
||||
}
|
||||
|
||||
r = pkcs11_find_token(pkcs11_uri, pkcs11_callback, &data);
|
||||
r = pkcs11_find_token(pkcs11_uri, pkcs11_crypt_device_callback, &data);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -0,0 +1,224 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <errno.h>
|
||||
#include <libcryptsetup.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cryptsetup-token.h"
|
||||
#include "cryptsetup-token-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "json.h"
|
||||
#include "luks2-fido2.h"
|
||||
#include "memory-util.h"
|
||||
#include "version.h"
|
||||
|
||||
#define TOKEN_NAME "systemd-fido2"
|
||||
#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 */) {
|
||||
|
||||
int r;
|
||||
const char *json;
|
||||
_cleanup_(erase_and_freep) char *pin_string = NULL;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return acquire_luks2_key(cd, json, (const char *)usrptr, pin_string ?: pin, 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-fido2'):
|
||||
*
|
||||
* - 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-fido2 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-tpm2' token if cryptsetup_token_validate is defined */) {
|
||||
|
||||
int r;
|
||||
Fido2EnrollFlags required;
|
||||
size_t cid_size, salt_size;
|
||||
const char *client_pin_req_str, *up_req_str, *uv_req_str;
|
||||
_cleanup_free_ void *cid = NULL, *salt = NULL;
|
||||
_cleanup_free_ char *rp_id = NULL, *cid_str = NULL, *salt_str = NULL;
|
||||
|
||||
assert(json);
|
||||
|
||||
r = parse_luks2_fido2_data(cd, json, &rp_id, &salt, &salt_size, &cid, &cid_size, &required);
|
||||
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(cid, cid_size, &cid_str);
|
||||
if (r < 0)
|
||||
return (void) crypt_log_debug_errno(cd, r, "Can not dump " TOKEN_NAME " content: %m");
|
||||
|
||||
r = crypt_dump_buffer_to_hex_string(salt, salt_size, &salt_str);
|
||||
if (r < 0)
|
||||
return (void) crypt_log_debug_errno(cd, r, "Can not dump " TOKEN_NAME " content: %m");
|
||||
|
||||
if (required & FIDO2ENROLL_PIN)
|
||||
client_pin_req_str = "true";
|
||||
else if (required & FIDO2ENROLL_PIN_IF_NEEDED)
|
||||
client_pin_req_str = NULL;
|
||||
else
|
||||
client_pin_req_str = "false";
|
||||
|
||||
if (required & FIDO2ENROLL_UP)
|
||||
up_req_str = "true";
|
||||
else if (required & FIDO2ENROLL_UP_IF_NEEDED)
|
||||
up_req_str = NULL;
|
||||
else
|
||||
up_req_str = "false";
|
||||
|
||||
if (required & FIDO2ENROLL_UV)
|
||||
uv_req_str = "true";
|
||||
else if (required & FIDO2ENROLL_UV_OMIT)
|
||||
uv_req_str = NULL;
|
||||
else
|
||||
uv_req_str = "false";
|
||||
|
||||
crypt_log(cd, "\tfido2-credential:" CRYPT_DUMP_LINE_SEP "%s\n", cid_str);
|
||||
crypt_log(cd, "\tfido2-salt: %s\n", salt_str);
|
||||
|
||||
/* optional fields */
|
||||
if (rp_id)
|
||||
crypt_log(cd, "\tfido2-rp: %s\n", rp_id);
|
||||
if (client_pin_req_str)
|
||||
crypt_log(cd, "\tfido2-clientPin-required:" CRYPT_DUMP_LINE_SEP "%s\n",
|
||||
client_pin_req_str);
|
||||
if (up_req_str)
|
||||
crypt_log(cd, "\tfido2-up-required:" CRYPT_DUMP_LINE_SEP "%s\n", up_req_str);
|
||||
if (uv_req_str)
|
||||
crypt_log(cd, "\tfido2-uv-required:" CRYPT_DUMP_LINE_SEP "%s\n", uv_req_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-tpm2' */) {
|
||||
|
||||
int r;
|
||||
JsonVariant *w;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
|
||||
assert(json);
|
||||
|
||||
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, "fido2-credential");
|
||||
if (!w || !json_variant_is_string(w)) {
|
||||
crypt_log_debug(cd, "FIDO2 token data lacks 'fido2-credential' field.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = unbase64mem(json_variant_string(w), SIZE_MAX, NULL, NULL);
|
||||
if (r < 0)
|
||||
return crypt_log_debug_errno(cd, r, "Invalid base64 data in 'fido2-credential' field: %m");
|
||||
|
||||
w = json_variant_by_key(v, "fido2-salt");
|
||||
if (!w || !json_variant_is_string(w)) {
|
||||
crypt_log_debug(cd, "FIDO2 token data lacks 'fido2-salt' 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 salt: %m.");
|
||||
|
||||
/* The "rp" field is optional. */
|
||||
w = json_variant_by_key(v, "fido2-rp");
|
||||
if (w && !json_variant_is_string(w)) {
|
||||
crypt_log_debug(cd, "FIDO2 token data's 'fido2-rp' field is not a string.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The "fido2-clientPin-required" field is optional. */
|
||||
w = json_variant_by_key(v, "fido2-clientPin-required");
|
||||
if (w && !json_variant_is_boolean(w)) {
|
||||
crypt_log_debug(cd, "FIDO2 token data's 'fido2-clientPin-required' field is not a boolean.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The "fido2-up-required" field is optional. */
|
||||
w = json_variant_by_key(v, "fido2-up-required");
|
||||
if (w && !json_variant_is_boolean(w)) {
|
||||
crypt_log_debug(cd, "FIDO2 token data's 'fido2-up-required' field is not a boolean.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The "fido2-uv-required" field is optional. */
|
||||
w = json_variant_by_key(v, "fido2-uv-required");
|
||||
if (w && !json_variant_is_boolean(w)) {
|
||||
crypt_log_debug(cd, "FIDO2 token data's 'fido2-uv-required' field is not a boolean.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -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;
|
||||
}
|
@ -2,23 +2,34 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#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_debug_errno(cd, e, ...) ({ \
|
||||
#define crypt_log_full_errno(cd, e, lvl, ...) ({ \
|
||||
int _e = abs(e), _s = errno; \
|
||||
errno = _e; \
|
||||
crypt_logf(cd, CRYPT_LOG_DEBUG, __VA_ARGS__); \
|
||||
crypt_logf(cd, lvl, __VA_ARGS__); \
|
||||
errno = _s; \
|
||||
-_e; \
|
||||
})
|
||||
|
||||
#define crypt_log_debug_errno(cd, e, ...) \
|
||||
crypt_log_full_errno(cd, e, CRYPT_LOG_DEBUG, __VA_ARGS__)
|
||||
|
||||
#define crypt_log_error_errno(cd, e, ...) \
|
||||
crypt_log_full_errno(cd, e, CRYPT_LOG_ERROR, __VA_ARGS__)
|
||||
|
||||
#define crypt_log_oom(cd) crypt_log_error_errno(cd, ENOMEM, "Not enough memory.")
|
||||
|
||||
int crypt_dump_buffer_to_hex_string(
|
||||
const char *buf,
|
||||
size_t buf_size,
|
||||
|
@ -8,6 +8,10 @@ const char *cryptsetup_token_version(void);
|
||||
int cryptsetup_token_open(struct crypt_device *cd, int token,
|
||||
char **password, size_t *password_len, void *usrptr);
|
||||
|
||||
int cryptsetup_token_open_pin(struct crypt_device *cd, int token,
|
||||
const char *pin, size_t pin_size,
|
||||
char **password, size_t *password_len, void *usrptr);
|
||||
|
||||
void cryptsetup_token_dump(struct crypt_device *cd, const char *json);
|
||||
|
||||
int cryptsetup_token_validate(struct crypt_device *cd, const char *json);
|
||||
|
@ -10,6 +10,7 @@
|
||||
CRYPTSETUP_TOKEN_1.0 {
|
||||
global:
|
||||
cryptsetup_token_open;
|
||||
cryptsetup_token_open_pin;
|
||||
cryptsetup_token_buffer_free;
|
||||
cryptsetup_token_validate;
|
||||
cryptsetup_token_dump;
|
||||
|
158
src/cryptsetup/cryptsetup-tokens/luks2-fido2.c
Normal file
158
src/cryptsetup/cryptsetup-tokens/luks2-fido2.c
Normal file
@ -0,0 +1,158 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <libcryptsetup.h>
|
||||
|
||||
#include "cryptsetup-token-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "json.h"
|
||||
#include "luks2-fido2.h"
|
||||
#include "memory-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
int acquire_luks2_key(
|
||||
struct crypt_device *cd,
|
||||
const char *json,
|
||||
const char *device,
|
||||
const char *pin,
|
||||
char **ret_keyslot_passphrase,
|
||||
size_t *ret_keyslot_passphrase_size) {
|
||||
|
||||
int r;
|
||||
Fido2EnrollFlags required;
|
||||
size_t cid_size, salt_size, decrypted_key_size;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
_cleanup_free_ void *cid = NULL, *salt = NULL;
|
||||
_cleanup_free_ char *rp_id = NULL;
|
||||
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
|
||||
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
|
||||
_cleanup_strv_free_erase_ char **pins = NULL;
|
||||
|
||||
assert(ret_keyslot_passphrase);
|
||||
assert(ret_keyslot_passphrase_size);
|
||||
|
||||
r = parse_luks2_fido2_data(cd, json, &rp_id, &salt, &salt_size, &cid, &cid_size, &required);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (pin) {
|
||||
pins = strv_new(pin);
|
||||
if (!pins)
|
||||
return crypt_log_oom(cd);
|
||||
}
|
||||
|
||||
/* configured to use pin but none was provided */
|
||||
if ((required & FIDO2ENROLL_PIN) && strv_isempty(pins))
|
||||
return -ENOANO;
|
||||
|
||||
r = fido2_use_hmac_hash(
|
||||
device,
|
||||
rp_id ?: "io.systemd.cryptsetup",
|
||||
salt, salt_size,
|
||||
cid, cid_size,
|
||||
pins,
|
||||
required,
|
||||
&decrypted_key,
|
||||
&decrypted_key_size);
|
||||
if (r == -ENOLCK) /* libcryptsetup returns -ENOANO also on wrong pin */
|
||||
r = -ENOANO;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Before using this key as passphrase we base64 encode it, for compat with homed */
|
||||
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_keyslot_passphrase = TAKE_PTR(base64_encoded);
|
||||
*ret_keyslot_passphrase_size = strlen(*ret_keyslot_passphrase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this function expects valid "systemd-fido2" in json */
|
||||
int parse_luks2_fido2_data(
|
||||
struct crypt_device *cd,
|
||||
const char *json,
|
||||
char **ret_rp_id,
|
||||
void **ret_salt,
|
||||
size_t *ret_salt_size,
|
||||
void **ret_cid,
|
||||
size_t *ret_cid_size,
|
||||
Fido2EnrollFlags *ret_required) {
|
||||
|
||||
_cleanup_free_ void *cid = NULL, *salt = NULL;
|
||||
size_t cid_size = 0, salt_size = 0;
|
||||
_cleanup_free_ char *rp = NULL;
|
||||
int r;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
JsonVariant *w;
|
||||
Fido2EnrollFlags required = 0;
|
||||
|
||||
assert(json);
|
||||
assert(ret_rp_id);
|
||||
assert(ret_salt);
|
||||
assert(ret_salt_size);
|
||||
assert(ret_cid);
|
||||
assert(ret_cid_size);
|
||||
assert(ret_required);
|
||||
|
||||
r = json_parse(json, 0, &v, NULL, NULL);
|
||||
if (r < 0)
|
||||
return crypt_log_error_errno(cd, r, "Failed to parse JSON token data: %m");
|
||||
|
||||
w = json_variant_by_key(v, "fido2-credential");
|
||||
if (!w)
|
||||
return -EINVAL;
|
||||
|
||||
r = unbase64mem(json_variant_string(w), SIZE_MAX, &cid, &cid_size);
|
||||
if (r < 0)
|
||||
return crypt_log_error_errno(cd, r, "Failed to parse 'fido2-credentials' field: %m");
|
||||
|
||||
w = json_variant_by_key(v, "fido2-salt");
|
||||
if (!w)
|
||||
return -EINVAL;
|
||||
|
||||
r = unbase64mem(json_variant_string(w), SIZE_MAX, &salt, &salt_size);
|
||||
if (r < 0)
|
||||
return crypt_log_error_errno(cd, r, "Failed to parse 'fido2-salt' field: %m");
|
||||
|
||||
w = json_variant_by_key(v, "fido2-rp");
|
||||
if (w) {
|
||||
/* The "rp" field is optional. */
|
||||
rp = strdup(json_variant_string(w));
|
||||
if (!rp) {
|
||||
crypt_log_error(cd, "Not enough memory.");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
w = json_variant_by_key(v, "fido2-clientPin-required");
|
||||
if (w)
|
||||
/* The "fido2-clientPin-required" field is optional. */
|
||||
SET_FLAG(required, FIDO2ENROLL_PIN, json_variant_boolean(w));
|
||||
else
|
||||
required |= FIDO2ENROLL_PIN_IF_NEEDED; /* compat with 248, where the field was unset */
|
||||
|
||||
w = json_variant_by_key(v, "fido2-up-required");
|
||||
if (w)
|
||||
/* The "fido2-up-required" field is optional. */
|
||||
SET_FLAG(required, FIDO2ENROLL_UP, json_variant_boolean(w));
|
||||
else
|
||||
required |= FIDO2ENROLL_UP_IF_NEEDED; /* compat with 248 */
|
||||
|
||||
w = json_variant_by_key(v, "fido2-uv-required");
|
||||
if (w)
|
||||
/* The "fido2-uv-required" field is optional. */
|
||||
SET_FLAG(required, FIDO2ENROLL_UV, json_variant_boolean(w));
|
||||
else
|
||||
required |= FIDO2ENROLL_UV_OMIT; /* compat with 248 */
|
||||
|
||||
*ret_rp_id = TAKE_PTR(rp);
|
||||
*ret_cid = TAKE_PTR(cid);
|
||||
*ret_cid_size = cid_size;
|
||||
*ret_salt = TAKE_PTR(salt);
|
||||
*ret_salt_size = salt_size;
|
||||
*ret_required = required;
|
||||
|
||||
return 0;
|
||||
}
|
24
src/cryptsetup/cryptsetup-tokens/luks2-fido2.h
Normal file
24
src/cryptsetup/cryptsetup-tokens/luks2-fido2.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "libfido2-util.h"
|
||||
|
||||
struct crypt_device;
|
||||
|
||||
int acquire_luks2_key(
|
||||
struct crypt_device *cd,
|
||||
const char *json,
|
||||
const char *device,
|
||||
const char *pin,
|
||||
char **ret_keyslot_passphrase,
|
||||
size_t *ret_keyslot_passphrase_size);
|
||||
|
||||
int parse_luks2_fido2_data(
|
||||
struct crypt_device *cd,
|
||||
const char *json,
|
||||
char **ret_rp_id,
|
||||
void **ret_salt,
|
||||
size_t *ret_salt_size,
|
||||
void **ret_cid,
|
||||
size_t *ret_cid_size,
|
||||
Fido2EnrollFlags *ret_required);
|
271
src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c
Normal file
271
src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.c
Normal file
@ -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;
|
||||
}
|
21
src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.h
Normal file
21
src/cryptsetup/cryptsetup-tokens/luks2-pkcs11.h
Normal file
@ -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);
|
@ -25,4 +25,40 @@ if conf.get('HAVE_TPM2') == 1
|
||||
c_args : cryptsetup_token_c_args)
|
||||
endif
|
||||
|
||||
if conf.get('HAVE_LIBFIDO2') == 1
|
||||
cryptsetup_token_systemd_fido2_sources = files('''
|
||||
cryptsetup-token-systemd-fido2.c
|
||||
cryptsetup-token.h
|
||||
cryptsetup-token-util.h
|
||||
cryptsetup-token-util.c
|
||||
luks2-fido2.c
|
||||
luks2-fido2.h
|
||||
'''.split())
|
||||
|
||||
cryptsetup_token_systemd_fido2_static = static_library(
|
||||
'cryptsetup-token-systemd-fido2_static',
|
||||
cryptsetup_token_systemd_fido2_sources,
|
||||
include_directories : includes,
|
||||
dependencies : libshared_deps + [libcryptsetup, versiondep],
|
||||
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
|
||||
|
@ -736,6 +736,105 @@ static int make_security_device_monitor(sd_event *event, sd_device_monitor **ret
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool libcryptsetup_plugins_support(void) {
|
||||
#if HAVE_LIBCRYPTSETUP_PLUGINS
|
||||
return crypt_token_external_path() != NULL;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LIBCRYPTSETUP_PLUGINS
|
||||
static int acquire_pins_from_env_variable(char ***ret_pins) {
|
||||
char *e;
|
||||
_cleanup_strv_free_erase_ char **pins = NULL;
|
||||
|
||||
assert(ret_pins);
|
||||
|
||||
e = getenv("PIN");
|
||||
if (e) {
|
||||
pins = strv_new(e);
|
||||
if (!pins)
|
||||
return log_oom();
|
||||
|
||||
string_erase(e);
|
||||
if (unsetenv("PIN") < 0)
|
||||
return log_error_errno(errno, "Failed to unset $PIN: %m");
|
||||
}
|
||||
|
||||
*ret_pins = TAKE_PTR(pins);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int attach_luks2_by_fido2(
|
||||
struct crypt_device *cd,
|
||||
const char *name,
|
||||
usec_t until,
|
||||
bool headless,
|
||||
void *usrptr,
|
||||
uint32_t activation_flags) {
|
||||
|
||||
int r = -EOPNOTSUPP;
|
||||
#if HAVE_LIBCRYPTSETUP_PLUGINS
|
||||
char **p;
|
||||
_cleanup_strv_free_erase_ char **pins = NULL;
|
||||
AskPasswordFlags flags = ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED;
|
||||
|
||||
r = crypt_activate_by_token_pin(cd, name, "systemd-fido2", 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 */
|
||||
return r;
|
||||
|
||||
r = acquire_pins_from_env_variable(&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);
|
||||
if (r > 0) /* returns unlocked keyslot id on success */
|
||||
r = 0;
|
||||
if (r != -ENOANO) /* needs pin or pin is wrong */
|
||||
return r;
|
||||
}
|
||||
|
||||
if (headless)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOPKG), "PIN querying disabled via 'headless' option. Use the '$PIN' environment variable.");
|
||||
|
||||
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);
|
||||
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);
|
||||
if (r > 0) /* returns unlocked keyslot id on success */
|
||||
r = 0;
|
||||
if (r != -ENOANO) /* needs pin or pin is wrong */
|
||||
return r;
|
||||
}
|
||||
|
||||
flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
|
||||
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);
|
||||
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);
|
||||
if (r > 0) /* returns unlocked keyslot id on success */
|
||||
r = 0;
|
||||
if (r != -ENOANO) /* needs pin or pin is wrong */
|
||||
return r;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||
struct crypt_device *cd,
|
||||
const char *name,
|
||||
@ -750,12 +849,13 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
_cleanup_free_ void *discovered_salt = NULL, *discovered_cid = NULL;
|
||||
size_t discovered_salt_size, discovered_cid_size, cid_size, decrypted_key_size;
|
||||
size_t discovered_salt_size, discovered_cid_size, decrypted_key_size, cid_size = 0;
|
||||
_cleanup_free_ char *friendly = NULL, *discovered_rp_id = NULL;
|
||||
int keyslot = arg_key_slot, r;
|
||||
const char *rp_id;
|
||||
const void *cid;
|
||||
const char *rp_id = NULL;
|
||||
const void *cid = NULL;
|
||||
Fido2EnrollFlags required;
|
||||
bool use_libcryptsetup_plugin = libcryptsetup_plugins_support();
|
||||
|
||||
assert(cd);
|
||||
assert(name);
|
||||
@ -775,7 +875,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||
* use PIN + UP when needed, and do not configure UV at all. Eventually, we should make this
|
||||
* explicitly configurable. */
|
||||
required = FIDO2ENROLL_PIN_IF_NEEDED | FIDO2ENROLL_UP_IF_NEEDED | FIDO2ENROLL_UV_OMIT;
|
||||
} else {
|
||||
} else if (!use_libcryptsetup_plugin) {
|
||||
r = find_fido2_auto_data(
|
||||
cd,
|
||||
&discovered_rp_id,
|
||||
@ -810,21 +910,30 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||
for (;;) {
|
||||
bool processed = false;
|
||||
|
||||
r = acquire_fido2_key(
|
||||
name,
|
||||
friendly,
|
||||
arg_fido2_device,
|
||||
rp_id,
|
||||
cid, cid_size,
|
||||
key_file, arg_keyfile_size, arg_keyfile_offset,
|
||||
key_data, key_data_size,
|
||||
until,
|
||||
arg_headless,
|
||||
required,
|
||||
&decrypted_key, &decrypted_key_size,
|
||||
arg_ask_password_flags);
|
||||
if (r >= 0)
|
||||
break;
|
||||
if (use_libcryptsetup_plugin && !arg_fido2_cid) {
|
||||
r = attach_luks2_by_fido2(cd, name, until, arg_headless, arg_fido2_device, flags);
|
||||
if (IN_SET(r, -ENOTUNIQ, -ENXIO, -ENOENT))
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN),
|
||||
"Automatic FIDO2 metadata discovery was not possible because missing or not unique, falling back to traditional unlocking.");
|
||||
|
||||
} else {
|
||||
r = acquire_fido2_key(
|
||||
name,
|
||||
friendly,
|
||||
arg_fido2_device,
|
||||
rp_id,
|
||||
cid, cid_size,
|
||||
key_file, arg_keyfile_size, arg_keyfile_offset,
|
||||
key_data, key_data_size,
|
||||
until,
|
||||
arg_headless,
|
||||
required,
|
||||
&decrypted_key, &decrypted_key_size,
|
||||
arg_ask_password_flags);
|
||||
if (r >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (r != -EAGAIN) /* EAGAIN means: token not found */
|
||||
return r;
|
||||
|
||||
@ -887,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, ¶ms, 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,
|
||||
@ -904,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;
|
||||
|
||||
@ -935,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;
|
||||
|
||||
@ -985,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);
|
||||
|
@ -175,6 +175,55 @@ char *pkcs11_token_model(const CK_TOKEN_INFO *token_info) {
|
||||
return t;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
CK_RV rv;
|
||||
|
||||
assert(m);
|
||||
assert(token_info);
|
||||
|
||||
if (FLAGS_SET(token_info->flags, CKF_PROTECTED_AUTHENTICATION_PATH)) {
|
||||
rv = m->C_Login(session, CKU_USER, NULL, 0);
|
||||
if (rv != CKR_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
|
||||
|
||||
log_info("Successfully logged into security token '%s' via protected authentication path.", token_label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!FLAGS_SET(token_info->flags, CKF_LOGIN_REQUIRED)) {
|
||||
log_info("No login into security token '%s' required.", token_label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!pin)
|
||||
return -ENOANO;
|
||||
|
||||
rv = m->C_Login(session, CKU_USER, (CK_UTF8CHAR*) pin, pin_size);
|
||||
if (rv == CKR_OK) {
|
||||
log_info("Successfully logged into security token '%s'.", token_label);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rv == CKR_PIN_LOCKED)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
|
||||
"PIN has been locked, please reset PIN of security token '%s'.", token_label);
|
||||
if (!IN_SET(rv, CKR_PIN_INCORRECT, CKR_PIN_LEN_RANGE))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
|
||||
|
||||
log_notice("PIN for token '%s' is incorrect, please try again.", token_label);
|
||||
|
||||
return -ENOLCK;
|
||||
}
|
||||
|
||||
int pkcs11_token_login(
|
||||
CK_FUNCTION_LIST *m,
|
||||
CK_SESSION_HANDLE session,
|
||||
@ -209,24 +258,12 @@ int pkcs11_token_login(
|
||||
if (uri_result != P11_KIT_URI_OK)
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EAGAIN), "Failed to format slot URI: %s", p11_kit_uri_message(uri_result));
|
||||
|
||||
if (FLAGS_SET(token_info->flags, CKF_PROTECTED_AUTHENTICATION_PATH)) {
|
||||
rv = m->C_Login(session, CKU_USER, NULL, 0);
|
||||
if (rv != CKR_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
|
||||
r = pkcs11_token_login_by_pin(m, session, token_info, token_label, /* pin= */ NULL, 0);
|
||||
if (r == 0 && ret_used_pin)
|
||||
*ret_used_pin = NULL;
|
||||
|
||||
log_info("Successfully logged into security token '%s' via protected authentication path.", token_label);
|
||||
if (ret_used_pin)
|
||||
*ret_used_pin = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!FLAGS_SET(token_info->flags, CKF_LOGIN_REQUIRED)) {
|
||||
log_info("No login into security token '%s' required.", token_label);
|
||||
if (ret_used_pin)
|
||||
*ret_used_pin = NULL;
|
||||
return 0;
|
||||
}
|
||||
if (r != -ENOANO) /* pin required */
|
||||
return r;
|
||||
|
||||
token_uri_escaped = cescape(token_uri_string);
|
||||
if (!token_uri_escaped)
|
||||
@ -278,28 +315,19 @@ int pkcs11_token_login(
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, passwords) {
|
||||
rv = m->C_Login(session, CKU_USER, (CK_UTF8CHAR*) *i, strlen(*i));
|
||||
if (rv == CKR_OK) {
|
||||
r = pkcs11_token_login_by_pin(m, session, token_info, token_label, *i, strlen(*i));
|
||||
if (r == 0 && ret_used_pin) {
|
||||
char *c;
|
||||
|
||||
if (ret_used_pin) {
|
||||
char *c;
|
||||
c = strdup(*i);
|
||||
if (!c)
|
||||
return log_oom();
|
||||
|
||||
c = strdup(*i);
|
||||
if (!c)
|
||||
return log_oom();
|
||||
|
||||
*ret_used_pin = c;
|
||||
}
|
||||
|
||||
log_info("Successfully logged into security token '%s'.", token_label);
|
||||
return 0;
|
||||
*ret_used_pin = c;
|
||||
}
|
||||
if (rv == CKR_PIN_LOCKED)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
|
||||
"PIN has been locked, please reset PIN of security token '%s'.", token_label);
|
||||
if (!IN_SET(rv, CKR_PIN_INCORRECT, CKR_PIN_LEN_RANGE))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv));
|
||||
|
||||
if (r != -ENOLCK)
|
||||
return r;
|
||||
|
||||
/* Referesh the token info, so that we can prompt knowing the new flags if they changed. */
|
||||
rv = m->C_GetTokenInfo(slotid, &updated_token_info);
|
||||
@ -309,7 +337,6 @@ int pkcs11_token_login(
|
||||
slotid, p11_kit_strerror(rv));
|
||||
|
||||
token_info = &updated_token_info;
|
||||
log_notice("PIN for token '%s' is incorrect, please try again.", token_label);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1154,3 +1181,71 @@ int pkcs11_find_token_auto(char **ret) {
|
||||
"PKCS#11 tokens not supported on this build.");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_P11KIT
|
||||
void pkcs11_crypt_device_callback_data_release(pkcs11_crypt_device_callback_data *data) {
|
||||
erase_and_free(data->decrypted_key);
|
||||
|
||||
if (data->free_encrypted_key)
|
||||
free(data->encrypted_key);
|
||||
}
|
||||
|
||||
int pkcs11_crypt_device_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) {
|
||||
|
||||
pkcs11_crypt_device_callback_data *data = userdata;
|
||||
CK_OBJECT_HANDLE object;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(slot_info);
|
||||
assert(token_info);
|
||||
assert(uri);
|
||||
assert(data);
|
||||
|
||||
/* Called for every token matching our URI */
|
||||
|
||||
r = pkcs11_token_login(
|
||||
m,
|
||||
session,
|
||||
slot_id,
|
||||
token_info,
|
||||
data->friendly_name,
|
||||
"drive-harddisk",
|
||||
"pkcs11-pin",
|
||||
"cryptsetup.pkcs11-pin",
|
||||
data->until,
|
||||
data->headless,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* We are likely called during early boot, where entropy is scarce. Mix some data from the PKCS#11
|
||||
* token, if it supports that. It should be cheap, given that we already are talking to it anyway and
|
||||
* shouldn't hurt. */
|
||||
(void) pkcs11_token_acquire_rng(m, session);
|
||||
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
@ -30,6 +30,7 @@ char *pkcs11_token_label(const CK_TOKEN_INFO *token_info);
|
||||
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_find_x509_certificate(CK_FUNCTION_LIST *m, CK_SESSION_HANDLE session, P11KitUri *search_uri, CK_OBJECT_HANDLE *ret_object);
|
||||
@ -49,7 +50,35 @@ int pkcs11_find_token(const char *pkcs11_uri, pkcs11_find_token_callback_t callb
|
||||
int pkcs11_acquire_certificate(const char *uri, const char *askpw_friendly_name, const char *askpw_icon_name, X509 **ret_cert, char **ret_pin_used);
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char *friendly_name;
|
||||
usec_t until;
|
||||
void *encrypted_key;
|
||||
size_t encrypted_key_size;
|
||||
void *decrypted_key;
|
||||
size_t decrypted_key_size;
|
||||
bool free_encrypted_key;
|
||||
bool headless;
|
||||
} pkcs11_crypt_device_callback_data;
|
||||
|
||||
void pkcs11_crypt_device_callback_data_release(pkcs11_crypt_device_callback_data *data);
|
||||
|
||||
int pkcs11_crypt_device_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);
|
||||
|
||||
#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);
|
||||
|
Loading…
Reference in New Issue
Block a user