mirror of
https://github.com/systemd/systemd.git
synced 2025-08-26 17:49:52 +03:00
Merge pull request #25777 from PeterCxy/enroll-fido2
cryptenroll: Implement support for unlocking via FIDO2 tokens
This commit is contained in:
@ -1,12 +1,65 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "ask-password-api.h"
|
||||
#include "cryptenroll-fido2.h"
|
||||
#include "cryptsetup-fido2.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "json.h"
|
||||
#include "libfido2-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "random-util.h"
|
||||
|
||||
int load_volume_key_fido2(
|
||||
struct crypt_device *cd,
|
||||
const char *cd_node,
|
||||
const char *device,
|
||||
void *ret_vk,
|
||||
size_t *ret_vks) {
|
||||
|
||||
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
|
||||
_cleanup_(erase_and_freep) char *passphrase = NULL;
|
||||
size_t decrypted_key_size;
|
||||
int r;
|
||||
|
||||
assert_se(cd);
|
||||
assert_se(cd_node);
|
||||
assert_se(ret_vk);
|
||||
assert_se(ret_vks);
|
||||
|
||||
r = acquire_fido2_key_auto(
|
||||
cd,
|
||||
cd_node,
|
||||
cd_node,
|
||||
device,
|
||||
/* until= */ 0,
|
||||
/* headless= */ false,
|
||||
&decrypted_key,
|
||||
&decrypted_key_size,
|
||||
ASK_PASSWORD_PUSH_CACHE|ASK_PASSWORD_ACCEPT_CACHED);
|
||||
if (r == -EAGAIN)
|
||||
return log_error_errno(r, "FIDO2 token does not exist, or UV is blocked. Please try again.");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Because cryptenroll requires a LUKS header, we can assume that this device is not
|
||||
* a PLAIN device. In this case, we need to base64 encode the secret to use as the passphrase */
|
||||
r = base64mem(decrypted_key, decrypted_key_size, &passphrase);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = crypt_volume_key_get(
|
||||
cd,
|
||||
CRYPT_ANY_SLOT,
|
||||
ret_vk,
|
||||
ret_vks,
|
||||
passphrase,
|
||||
/* passphrase_size= */ r);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unlocking via FIDO2 device failed: %m");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int enroll_fido2(
|
||||
struct crypt_device *cd,
|
||||
const void *volume_key,
|
||||
|
@ -8,8 +8,15 @@
|
||||
#include "log.h"
|
||||
|
||||
#if HAVE_LIBFIDO2
|
||||
int load_volume_key_fido2(struct crypt_device *cd, const char *cd_node, const char *device, void *ret_vk, size_t *ret_vks);
|
||||
int enroll_fido2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Fido2EnrollFlags lock_with, int cred_alg);
|
||||
|
||||
#else
|
||||
static inline int load_volume_key_fido2(struct crypt_device *cd, const char *cd_node, const char *device, void *ret_vk, size_t *ret_vks) {
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"FIDO2 unlocking not supported.");
|
||||
}
|
||||
|
||||
static inline int enroll_fido2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Fido2EnrollFlags lock_with, int cred_alg) {
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"FIDO2 key enrollment not supported.");
|
||||
|
@ -8,6 +8,86 @@
|
||||
#include "pwquality-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
int load_volume_key_password(
|
||||
struct crypt_device *cd,
|
||||
const char *cd_node,
|
||||
void *ret_vk,
|
||||
size_t *ret_vks) {
|
||||
|
||||
_cleanup_(erase_and_freep) char *envpw = NULL;
|
||||
int r;
|
||||
|
||||
assert_se(cd);
|
||||
assert_se(cd_node);
|
||||
assert_se(ret_vk);
|
||||
assert_se(ret_vks);
|
||||
|
||||
r = getenv_steal_erase("PASSWORD", &envpw);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire password from environment: %m");
|
||||
if (r > 0) {
|
||||
r = crypt_volume_key_get(
|
||||
cd,
|
||||
CRYPT_ANY_SLOT,
|
||||
ret_vk,
|
||||
ret_vks,
|
||||
envpw,
|
||||
strlen(envpw));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Password from environment variable $PASSWORD did not work.");
|
||||
} else {
|
||||
AskPasswordFlags ask_password_flags = ASK_PASSWORD_PUSH_CACHE|ASK_PASSWORD_ACCEPT_CACHED;
|
||||
_cleanup_free_ char *question = NULL, *disk_path = NULL;
|
||||
unsigned i = 5;
|
||||
const char *id;
|
||||
|
||||
question = strjoin("Please enter current passphrase for disk ", cd_node, ":");
|
||||
if (!question)
|
||||
return log_oom();
|
||||
|
||||
disk_path = cescape(cd_node);
|
||||
if (!disk_path)
|
||||
return log_oom();
|
||||
|
||||
id = strjoina("cryptsetup:", disk_path);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_strv_free_erase_ char **passwords = NULL;
|
||||
|
||||
if (--i == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOKEY),
|
||||
"Too many attempts, giving up:");
|
||||
|
||||
r = ask_password_auto(
|
||||
question, "drive-harddisk", id, "cryptenroll", "cryptenroll.passphrase", USEC_INFINITY,
|
||||
ask_password_flags,
|
||||
&passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
r = -EPERM;
|
||||
STRV_FOREACH(p, passwords) {
|
||||
r = crypt_volume_key_get(
|
||||
cd,
|
||||
CRYPT_ANY_SLOT,
|
||||
ret_vk,
|
||||
ret_vks,
|
||||
*p,
|
||||
strlen(*p));
|
||||
if (r >= 0)
|
||||
break;
|
||||
}
|
||||
if (r >= 0)
|
||||
break;
|
||||
|
||||
log_error_errno(r, "Password not correct, please try again.");
|
||||
ask_password_flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int enroll_password(
|
||||
struct crypt_device *cd,
|
||||
const void *volume_key,
|
||||
|
@ -5,4 +5,5 @@
|
||||
|
||||
#include "cryptsetup-util.h"
|
||||
|
||||
int load_volume_key_password(struct crypt_device *cd, const char* cd_node, void *ret_vk, size_t *ret_vks);
|
||||
int enroll_password(struct crypt_device *cd, const void *volume_key, size_t volume_key_size);
|
||||
|
@ -32,6 +32,8 @@
|
||||
|
||||
static EnrollType arg_enroll_type = _ENROLL_TYPE_INVALID;
|
||||
static char *arg_unlock_keyfile = NULL;
|
||||
static UnlockType arg_unlock_type = UNLOCK_PASSWORD;
|
||||
static char *arg_unlock_fido2_device = NULL;
|
||||
static char *arg_pkcs11_token_uri = NULL;
|
||||
static char *arg_fido2_device = NULL;
|
||||
static char *arg_tpm2_device = NULL;
|
||||
@ -55,6 +57,7 @@ static int arg_fido2_cred_alg = 0;
|
||||
assert_cc(sizeof(arg_wipe_slots_mask) * 8 >= _ENROLL_TYPE_MAX);
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_unlock_keyfile, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_unlock_fido2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_token_uri, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||
@ -105,6 +108,8 @@ static int help(void) {
|
||||
" --recovery-key Enroll a recovery key\n"
|
||||
" --unlock-key-file=PATH\n"
|
||||
" Use a file to unlock the volume\n"
|
||||
" --unlock-fido2-device=PATH\n"
|
||||
" Use a FIDO2 device to unlock the volume\n"
|
||||
" --pkcs11-token-uri=URI\n"
|
||||
" Specify PKCS#11 security token URI\n"
|
||||
" --fido2-credential-algorithm=STRING\n"
|
||||
@ -148,6 +153,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_PASSWORD,
|
||||
ARG_RECOVERY_KEY,
|
||||
ARG_UNLOCK_KEYFILE,
|
||||
ARG_UNLOCK_FIDO2_DEVICE,
|
||||
ARG_PKCS11_TOKEN_URI,
|
||||
ARG_FIDO2_DEVICE,
|
||||
ARG_TPM2_DEVICE,
|
||||
@ -169,6 +175,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "password", no_argument, NULL, ARG_PASSWORD },
|
||||
{ "recovery-key", no_argument, NULL, ARG_RECOVERY_KEY },
|
||||
{ "unlock-key-file", required_argument, NULL, ARG_UNLOCK_KEYFILE },
|
||||
{ "unlock-fido2-device", required_argument, NULL, ARG_UNLOCK_FIDO2_DEVICE },
|
||||
{ "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI },
|
||||
{ "fido2-credential-algorithm", required_argument, NULL, ARG_FIDO2_CRED_ALG },
|
||||
{ "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE },
|
||||
@ -250,11 +257,37 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_UNLOCK_KEYFILE:
|
||||
if (arg_unlock_type != UNLOCK_PASSWORD)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Multiple unlock methods specified at once, refusing.");
|
||||
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_unlock_keyfile);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
arg_unlock_type = UNLOCK_KEYFILE;
|
||||
break;
|
||||
|
||||
case ARG_UNLOCK_FIDO2_DEVICE: {
|
||||
_cleanup_free_ char *device = NULL;
|
||||
|
||||
if (arg_unlock_type != UNLOCK_PASSWORD)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Multiple unlock methods specified at once, refusing.");
|
||||
|
||||
assert(!arg_unlock_fido2_device);
|
||||
|
||||
if (!streq(optarg, "auto")) {
|
||||
device = strdup(optarg);
|
||||
if (!device)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
arg_unlock_type = UNLOCK_FIDO2;
|
||||
arg_unlock_fido2_device = TAKE_PTR(device);
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_PKCS11_TOKEN_URI: {
|
||||
_cleanup_free_ char *uri = NULL;
|
||||
|
||||
@ -299,11 +332,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Multiple operations specified at once, refusing.");
|
||||
|
||||
if (streq(optarg, "auto")) {
|
||||
r = fido2_find_device_auto(&device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
if (!streq(optarg, "auto")) {
|
||||
device = strdup(optarg);
|
||||
if (!device)
|
||||
return log_oom();
|
||||
@ -432,6 +461,18 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((arg_enroll_type == ENROLL_FIDO2 && arg_unlock_type == UNLOCK_FIDO2)
|
||||
&& !(arg_fido2_device && arg_unlock_fido2_device))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"When both enrolling and unlocking with FIDO2 tokens, automatic discovery is unsupported. "
|
||||
"Please specify device paths for enrolling and unlocking respectively.");
|
||||
|
||||
if (arg_enroll_type == ENROLL_FIDO2 && !arg_fido2_device) {
|
||||
r = fido2_find_device_auto(&arg_fido2_device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"No block device node specified, refusing.");
|
||||
@ -474,13 +515,50 @@ static int check_for_homed(struct crypt_device *cd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_volume_key_keyfile(
|
||||
struct crypt_device *cd,
|
||||
void *ret_vk,
|
||||
size_t *ret_vks) {
|
||||
|
||||
_cleanup_(erase_and_freep) char *password = NULL;
|
||||
size_t password_len;
|
||||
int r;
|
||||
|
||||
assert_se(cd);
|
||||
assert_se(ret_vk);
|
||||
assert_se(ret_vks);
|
||||
|
||||
r = read_full_file_full(
|
||||
AT_FDCWD,
|
||||
arg_unlock_keyfile,
|
||||
0,
|
||||
SIZE_MAX,
|
||||
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
|
||||
NULL,
|
||||
&password,
|
||||
&password_len);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Reading keyfile %s failed: %m", arg_unlock_keyfile);
|
||||
|
||||
r = crypt_volume_key_get(
|
||||
cd,
|
||||
CRYPT_ANY_SLOT,
|
||||
ret_vk,
|
||||
ret_vks,
|
||||
password,
|
||||
password_len);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unlocking via keyfile failed: %m");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int prepare_luks(
|
||||
struct crypt_device **ret_cd,
|
||||
void **ret_volume_key,
|
||||
size_t *ret_volume_key_size) {
|
||||
|
||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||
_cleanup_(erase_and_freep) char *envpw = NULL;
|
||||
_cleanup_(erase_and_freep) void *vk = NULL;
|
||||
size_t vks;
|
||||
int r;
|
||||
@ -516,99 +594,27 @@ static int prepare_luks(
|
||||
if (!vk)
|
||||
return log_oom();
|
||||
|
||||
if (arg_unlock_keyfile) {
|
||||
_cleanup_(erase_and_freep) char *password = NULL;
|
||||
size_t password_len;
|
||||
switch (arg_unlock_type) {
|
||||
|
||||
r = read_full_file_full(
|
||||
AT_FDCWD,
|
||||
arg_unlock_keyfile,
|
||||
0,
|
||||
SIZE_MAX,
|
||||
READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET,
|
||||
NULL,
|
||||
&password,
|
||||
&password_len);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Reading keyfile %s failed: %m", arg_unlock_keyfile);
|
||||
case UNLOCK_KEYFILE:
|
||||
r = load_volume_key_keyfile(cd, vk, &vks);
|
||||
break;
|
||||
|
||||
r = crypt_volume_key_get(
|
||||
cd,
|
||||
CRYPT_ANY_SLOT,
|
||||
vk,
|
||||
&vks,
|
||||
password,
|
||||
password_len);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unlocking via keyfile failed: %m");
|
||||
case UNLOCK_FIDO2:
|
||||
r = load_volume_key_fido2(cd, arg_node, arg_unlock_fido2_device, vk, &vks);
|
||||
break;
|
||||
|
||||
goto out;
|
||||
case UNLOCK_PASSWORD:
|
||||
r = load_volume_key_password(cd, arg_node, vk, &vks);
|
||||
break;
|
||||
|
||||
default:
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown LUKS unlock method");
|
||||
}
|
||||
|
||||
r = getenv_steal_erase("PASSWORD", &envpw);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire password from environment: %m");
|
||||
if (r > 0) {
|
||||
r = crypt_volume_key_get(
|
||||
cd,
|
||||
CRYPT_ANY_SLOT,
|
||||
vk,
|
||||
&vks,
|
||||
envpw,
|
||||
strlen(envpw));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Password from environment variable $PASSWORD did not work.");
|
||||
} else {
|
||||
AskPasswordFlags ask_password_flags = ASK_PASSWORD_PUSH_CACHE|ASK_PASSWORD_ACCEPT_CACHED;
|
||||
_cleanup_free_ char *question = NULL, *disk_path = NULL;
|
||||
unsigned i = 5;
|
||||
const char *id;
|
||||
return r;
|
||||
|
||||
question = strjoin("Please enter current passphrase for disk ", arg_node, ":");
|
||||
if (!question)
|
||||
return log_oom();
|
||||
|
||||
disk_path = cescape(arg_node);
|
||||
if (!disk_path)
|
||||
return log_oom();
|
||||
|
||||
id = strjoina("cryptsetup:", disk_path);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_strv_free_erase_ char **passwords = NULL;
|
||||
|
||||
if (--i == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOKEY),
|
||||
"Too many attempts, giving up:");
|
||||
|
||||
r = ask_password_auto(
|
||||
question, "drive-harddisk", id, "cryptenroll", "cryptenroll.passphrase", USEC_INFINITY,
|
||||
ask_password_flags,
|
||||
&passwords);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to query password: %m");
|
||||
|
||||
r = -EPERM;
|
||||
STRV_FOREACH(p, passwords) {
|
||||
r = crypt_volume_key_get(
|
||||
cd,
|
||||
CRYPT_ANY_SLOT,
|
||||
vk,
|
||||
&vks,
|
||||
*p,
|
||||
strlen(*p));
|
||||
if (r >= 0)
|
||||
break;
|
||||
}
|
||||
if (r >= 0)
|
||||
break;
|
||||
|
||||
log_error_errno(r, "Password not correct, please try again.");
|
||||
ask_password_flags &= ~ASK_PASSWORD_ACCEPT_CACHED;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
*ret_cd = TAKE_PTR(cd);
|
||||
*ret_volume_key = TAKE_PTR(vk);
|
||||
*ret_volume_key_size = vks;
|
||||
|
@ -13,6 +13,14 @@ typedef enum EnrollType {
|
||||
_ENROLL_TYPE_INVALID = -EINVAL,
|
||||
} EnrollType;
|
||||
|
||||
typedef enum UnlockType {
|
||||
UNLOCK_PASSWORD,
|
||||
UNLOCK_KEYFILE,
|
||||
UNLOCK_FIDO2,
|
||||
_UNLOCK_TYPE_MAX,
|
||||
_UNLOCK_TYPE_INVALID = -EINVAL,
|
||||
} UnlockType;
|
||||
|
||||
typedef enum WipeScope {
|
||||
WIPE_EXPLICIT, /* only wipe the listed slots */
|
||||
WIPE_ALL, /* wipe all slots */
|
||||
|
@ -1121,7 +1121,6 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||
name,
|
||||
friendly,
|
||||
arg_fido2_device,
|
||||
key_file, arg_keyfile_size, arg_keyfile_offset,
|
||||
until,
|
||||
arg_headless,
|
||||
&decrypted_key, &decrypted_key_size,
|
||||
|
@ -1,7 +1,6 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
systemd_cryptsetup_sources = files(
|
||||
'cryptsetup-fido2.h',
|
||||
'cryptsetup-keyfile.c',
|
||||
'cryptsetup-keyfile.h',
|
||||
'cryptsetup-pkcs11.h',
|
||||
@ -12,10 +11,6 @@ if conf.get('HAVE_P11KIT') == 1
|
||||
systemd_cryptsetup_sources += files('cryptsetup-pkcs11.c')
|
||||
endif
|
||||
|
||||
if conf.get('HAVE_LIBFIDO2') == 1
|
||||
systemd_cryptsetup_sources += files('cryptsetup-fido2.c')
|
||||
endif
|
||||
|
||||
if conf.get('HAVE_TPM2') == 1
|
||||
systemd_cryptsetup_sources += files('cryptsetup-tpm2.c')
|
||||
endif
|
||||
|
@ -132,9 +132,6 @@ int acquire_fido2_key_auto(
|
||||
const char *name,
|
||||
const char *friendly_name,
|
||||
const char *fido2_device,
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
usec_t until,
|
||||
bool headless,
|
||||
void **ret_decrypted_key,
|
||||
@ -252,7 +249,9 @@ int acquire_fido2_key_auto(
|
||||
fido2_device,
|
||||
rp,
|
||||
cid, cid_size,
|
||||
key_file, key_file_size, key_file_offset,
|
||||
/* key_file= */ NULL, /* salt is read from LUKS header instead of key_file */
|
||||
/* key_file_size= */ 0,
|
||||
/* key_file_offset= */ 0,
|
||||
salt, salt_size,
|
||||
until,
|
||||
headless,
|
@ -34,9 +34,6 @@ int acquire_fido2_key_auto(
|
||||
const char *name,
|
||||
const char *friendly_name,
|
||||
const char *fido2_device,
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
usec_t until,
|
||||
bool headless,
|
||||
void **ret_decrypted_key,
|
||||
@ -73,9 +70,6 @@ static inline int acquire_fido2_key_auto(
|
||||
const char *name,
|
||||
const char *friendly_name,
|
||||
const char *fido2_device,
|
||||
const char *key_file,
|
||||
size_t key_file_size,
|
||||
uint64_t key_file_offset,
|
||||
usec_t until,
|
||||
bool headless,
|
||||
void **ret_decrypted_key,
|
@ -85,6 +85,7 @@ shared_sources = files(
|
||||
'cpu-set-util.h',
|
||||
'creds-util.c',
|
||||
'creds-util.h',
|
||||
'cryptsetup-fido2.h',
|
||||
'cryptsetup-util.c',
|
||||
'cryptsetup-util.h',
|
||||
'daemon-util.c',
|
||||
@ -405,6 +406,10 @@ if conf.get('ENABLE_NSCD') == 1
|
||||
shared_sources += files('nscd-flush.c')
|
||||
endif
|
||||
|
||||
if conf.get('HAVE_LIBFIDO2') == 1
|
||||
shared_sources += files('cryptsetup-fido2.c')
|
||||
endif
|
||||
|
||||
generate_ip_protocol_list = find_program('generate-ip-protocol-list.sh')
|
||||
ip_protocol_list_txt = custom_target(
|
||||
'ip-protocol-list.txt',
|
||||
|
Reference in New Issue
Block a user