mirror of
https://github.com/systemd/systemd.git
synced 2025-02-02 13:47:27 +03:00
cryptenroll,homectl: Introduce --fido2-credential-algorithm option
* Some authenticators(like Yubikey) support credential algorithm other than ES256 * Introduce a new option so users can make use of it
This commit is contained in:
parent
6dc18ca5dd
commit
70e723c000
@ -356,6 +356,19 @@
|
||||
generally do not required that, and work out of the box.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--fido2-credential-algorithm=</option><replaceable>STRING</replaceable></term>
|
||||
<listitem><para>Specify COSE algorithm used in credential generation. The default value is
|
||||
<literal>es256</literal>. Supported values are <literal>es256</literal>, <literal>rs256</literal>
|
||||
and <literal>eddsa</literal>.</para>
|
||||
|
||||
<para><literal>es256</literal> denotes ECDSA over NIST P-256 with SHA-256. <literal>rs256</literal>
|
||||
denotes 2048-bit RSA with PKCS#1.5 padding and SHA-256. <literal>eddsa</literal> denotes
|
||||
EDDSA over Curve25519 with SHA-512.</para>
|
||||
|
||||
<para>Note that your authenticator may not support some algorithms.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--fido2-device=</option><replaceable>PATH</replaceable></term>
|
||||
|
||||
|
@ -122,6 +122,19 @@
|
||||
<filename>/etc/crypttab</filename> line.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--fido2-credential-algorithm=</option><replaceable>STRING</replaceable></term>
|
||||
<listitem><para>Specify COSE algorithm used in credential generation. The default value is
|
||||
<literal>es256</literal>. Supported values are <literal>es256</literal>, <literal>rs256</literal>
|
||||
and <literal>eddsa</literal>.</para>
|
||||
|
||||
<para><literal>es256</literal> denotes ECDSA over NIST P-256 with SHA-256. <literal>rs256</literal>
|
||||
denotes 2048-bit RSA with PKCS#1.5 padding and SHA-256. <literal>eddsa</literal> denotes
|
||||
EDDSA over Curve25519 with SHA-512.</para>
|
||||
|
||||
<para>Note that your authenticator may not support some algorithms.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--fido2-device=</option><replaceable>PATH</replaceable></term>
|
||||
|
||||
|
@ -12,7 +12,8 @@ int enroll_fido2(
|
||||
const void *volume_key,
|
||||
size_t volume_key_size,
|
||||
const char *device,
|
||||
Fido2EnrollFlags lock_with) {
|
||||
Fido2EnrollFlags lock_with,
|
||||
int cred_alg) {
|
||||
|
||||
_cleanup_(erase_and_freep) void *salt = NULL, *secret = NULL;
|
||||
_cleanup_(erase_and_freep) char *base64_encoded = NULL;
|
||||
@ -42,6 +43,7 @@ int enroll_fido2(
|
||||
/* user_icon_name= */ NULL,
|
||||
/* askpw_icon_name= */ "drive-harddisk",
|
||||
lock_with,
|
||||
cred_alg,
|
||||
&cid, &cid_size,
|
||||
&salt, &salt_size,
|
||||
&secret, &secret_size,
|
||||
|
@ -8,9 +8,9 @@
|
||||
#include "log.h"
|
||||
|
||||
#if HAVE_LIBFIDO2
|
||||
int enroll_fido2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Fido2EnrollFlags lock_with);
|
||||
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 enroll_fido2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, Fido2EnrollFlags lock_with) {
|
||||
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.");
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ static size_t arg_n_wipe_slots = 0;
|
||||
static WipeScope arg_wipe_slots_scope = WIPE_EXPLICIT;
|
||||
static unsigned arg_wipe_slots_mask = 0; /* Bitmask of (1U << EnrollType), for wiping all slots of specific types */
|
||||
static Fido2EnrollFlags arg_fido2_lock_with = FIDO2ENROLL_PIN | FIDO2ENROLL_UP;
|
||||
#if HAVE_LIBFIDO2
|
||||
static int arg_fido2_cred_alg = COSE_ES256;
|
||||
#else
|
||||
static int arg_fido2_cred_alg = 0;
|
||||
#endif
|
||||
|
||||
assert_cc(sizeof(arg_wipe_slots_mask) * 8 >= _ENROLL_TYPE_MAX);
|
||||
|
||||
@ -89,6 +94,8 @@ static int help(void) {
|
||||
" --recovery-key Enroll a recovery key\n"
|
||||
" --pkcs11-token-uri=URI\n"
|
||||
" Specify PKCS#11 security token URI\n"
|
||||
" --fido2-credential-algorithm=STRING\n"
|
||||
" Specify COSE algorithm for FIDO2 credential\n"
|
||||
" --fido2-device=PATH\n"
|
||||
" Enroll a FIDO2-HMAC security token\n"
|
||||
" --fido2-with-client-pin=BOOL\n"
|
||||
@ -129,6 +136,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_FIDO2_WITH_PIN,
|
||||
ARG_FIDO2_WITH_UP,
|
||||
ARG_FIDO2_WITH_UV,
|
||||
ARG_FIDO2_CRED_ALG,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -137,6 +145,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "password", no_argument, NULL, ARG_PASSWORD },
|
||||
{ "recovery-key", no_argument, NULL, ARG_RECOVERY_KEY },
|
||||
{ "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 },
|
||||
{ "fido2-with-client-pin", required_argument, NULL, ARG_FIDO2_WITH_PIN },
|
||||
{ "fido2-with-user-presence", required_argument, NULL, ARG_FIDO2_WITH_UP },
|
||||
@ -240,6 +249,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_FIDO2_CRED_ALG:
|
||||
r = parse_fido2_algorithm(optarg, &arg_fido2_cred_alg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse COSE algorithm: %s", optarg);
|
||||
break;
|
||||
|
||||
case ARG_FIDO2_DEVICE: {
|
||||
_cleanup_free_ char *device = NULL;
|
||||
|
||||
@ -566,7 +581,7 @@ static int run(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ENROLL_FIDO2:
|
||||
slot = enroll_fido2(cd, vk, vks, arg_fido2_device, arg_fido2_lock_with);
|
||||
slot = enroll_fido2(cd, vk, vks, arg_fido2_device, arg_fido2_lock_with, arg_fido2_cred_alg);
|
||||
break;
|
||||
|
||||
case ENROLL_TPM2:
|
||||
|
@ -118,7 +118,8 @@ static int add_fido2_salt(
|
||||
int identity_add_fido2_parameters(
|
||||
JsonVariant **v,
|
||||
const char *device,
|
||||
Fido2EnrollFlags lock_with) {
|
||||
Fido2EnrollFlags lock_with,
|
||||
int cred_alg) {
|
||||
|
||||
#if HAVE_LIBFIDO2
|
||||
JsonVariant *un, *realm, *rn;
|
||||
@ -165,6 +166,7 @@ int identity_add_fido2_parameters(
|
||||
/* user_icon_name= */ NULL,
|
||||
/* askpw_icon_name= */ "user-home",
|
||||
lock_with,
|
||||
cred_alg,
|
||||
&cid, &cid_size,
|
||||
&salt, &salt_size,
|
||||
&secret, &secret_size,
|
||||
|
@ -4,4 +4,4 @@
|
||||
#include "json.h"
|
||||
#include "libfido2-util.h"
|
||||
|
||||
int identity_add_fido2_parameters(JsonVariant **v, const char *device, Fido2EnrollFlags lock_with);
|
||||
int identity_add_fido2_parameters(JsonVariant **v, const char *device, Fido2EnrollFlags lock_with, int cred_alg);
|
||||
|
@ -61,6 +61,11 @@ static uint64_t arg_disk_size_relative = UINT64_MAX;
|
||||
static char **arg_pkcs11_token_uri = NULL;
|
||||
static char **arg_fido2_device = NULL;
|
||||
static Fido2EnrollFlags arg_fido2_lock_with = FIDO2ENROLL_PIN | FIDO2ENROLL_UP;
|
||||
#if HAVE_LIBFIDO2
|
||||
static int arg_fido2_cred_alg = COSE_ES256;
|
||||
#else
|
||||
static int arg_fido2_cred_alg = 0;
|
||||
#endif
|
||||
static bool arg_recovery_key = false;
|
||||
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
|
||||
static bool arg_and_resize = false;
|
||||
@ -1114,7 +1119,7 @@ static int acquire_new_home_record(UserRecord **ret) {
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, arg_fido2_device) {
|
||||
r = identity_add_fido2_parameters(&v, *i, arg_fido2_lock_with);
|
||||
r = identity_add_fido2_parameters(&v, *i, arg_fido2_lock_with, arg_fido2_cred_alg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -1473,7 +1478,7 @@ static int acquire_updated_home_record(
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, arg_fido2_device) {
|
||||
r = identity_add_fido2_parameters(&json, *i, arg_fido2_lock_with);
|
||||
r = identity_add_fido2_parameters(&json, *i, arg_fido2_lock_with, arg_fido2_cred_alg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -2387,6 +2392,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_LUKS_EXTRA_MOUNT_OPTIONS,
|
||||
ARG_AUTO_RESIZE_MODE,
|
||||
ARG_REBALANCE_WEIGHT,
|
||||
ARG_FIDO2_CRED_ALG,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -2463,6 +2469,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "json", required_argument, NULL, ARG_JSON },
|
||||
{ "export-format", required_argument, NULL, ARG_EXPORT_FORMAT },
|
||||
{ "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 },
|
||||
{ "fido2-with-client-pin", required_argument, NULL, ARG_FIDO2_WITH_PIN },
|
||||
{ "fido2-with-user-presence", required_argument, NULL, ARG_FIDO2_WITH_UP },
|
||||
@ -3485,6 +3492,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
strv_uniq(arg_pkcs11_token_uri);
|
||||
break;
|
||||
|
||||
case ARG_FIDO2_CRED_ALG:
|
||||
r = parse_fido2_algorithm(optarg, &arg_fido2_cred_alg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse COSE algorithm: %s", optarg);
|
||||
break;
|
||||
|
||||
case ARG_FIDO2_DEVICE:
|
||||
if (streq(optarg, "list"))
|
||||
return fido2_list_devices();
|
||||
|
@ -450,6 +450,20 @@ static int fido2_use_hmac_hash_specific_token(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* COSE_ECDH_ES256 is not usable with fido_cred_set_type() thus it's not listed here. */
|
||||
static const char *fido2_algorithm_to_string(int alg) {
|
||||
switch(alg) {
|
||||
case COSE_ES256:
|
||||
return "es256";
|
||||
case COSE_RS256:
|
||||
return "rs256";
|
||||
case COSE_EDDSA:
|
||||
return "eddsa";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int fido2_use_hmac_hash(
|
||||
const char *device,
|
||||
const char *rp_id,
|
||||
@ -532,6 +546,7 @@ int fido2_generate_hmac_hash(
|
||||
const char *user_icon,
|
||||
const char *askpw_icon_name,
|
||||
Fido2EnrollFlags lock_with,
|
||||
int cred_alg,
|
||||
void **ret_cid, size_t *ret_cid_size,
|
||||
void **ret_salt, size_t *ret_salt_size,
|
||||
void **ret_secret, size_t *ret_secret_size,
|
||||
@ -628,10 +643,10 @@ int fido2_generate_hmac_hash(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to set FIDO2 credential relying party ID/name: %s", sym_fido_strerr(r));
|
||||
|
||||
r = sym_fido_cred_set_type(c, COSE_ES256);
|
||||
r = sym_fido_cred_set_type(c, cred_alg);
|
||||
if (r != FIDO_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to set FIDO2 credential type to ES256: %s", sym_fido_strerr(r));
|
||||
"Failed to set FIDO2 credential type to %s: %s", fido2_algorithm_to_string(cred_alg), sym_fido_strerr(r));
|
||||
|
||||
r = sym_fido_cred_set_user(
|
||||
c,
|
||||
@ -721,6 +736,9 @@ int fido2_generate_hmac_hash(
|
||||
if (r == FIDO_ERR_ACTION_TIMEOUT)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOSTR),
|
||||
"Token action timeout. (User didn't interact with token quickly enough.)");
|
||||
if (r == FIDO_ERR_UNSUPPORTED_ALGORITHM)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Token doesn't support credential algorithm %s.", fido2_algorithm_to_string(cred_alg));
|
||||
if (r != FIDO_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Failed to generate FIDO2 credential: %s", sym_fido_strerr(r));
|
||||
@ -1124,3 +1142,24 @@ finish:
|
||||
"FIDO2 tokens not supported on this build.");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LIBFIDO2
|
||||
int parse_fido2_algorithm(const char *s, int *ret) {
|
||||
int a;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (streq(s, "es256"))
|
||||
a = COSE_ES256;
|
||||
else if (streq(s, "rs256"))
|
||||
a = COSE_RS256;
|
||||
else if (streq(s, "eddsa"))
|
||||
a = COSE_EDDSA;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (ret)
|
||||
*ret = a;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -109,12 +109,18 @@ int fido2_generate_hmac_hash(
|
||||
const char *user_icon,
|
||||
const char *askpw_icon_name,
|
||||
Fido2EnrollFlags lock_with,
|
||||
int cred_alg,
|
||||
void **ret_cid, size_t *ret_cid_size,
|
||||
void **ret_salt, size_t *ret_salt_size,
|
||||
void **ret_secret, size_t *ret_secret_size,
|
||||
char **ret_usedpin,
|
||||
Fido2EnrollFlags *ret_locked_with);
|
||||
|
||||
int parse_fido2_algorithm(const char *s, int *ret);
|
||||
#else
|
||||
static inline int parse_fido2_algorithm(const char *s, int *ret) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
int fido2_list_devices(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user