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;
+static Fido2EnrollFlags arg_fido2_lock_with = FIDO2ENROLL_PIN | FIDO2ENROLL_UP;
assert_cc(sizeof(arg_wipe_slots_mask) * 8 >= _ENROLL_TYPE_MAX);
" Enroll a FIDO2-HMAC security token\n"
" --fido2-with-client-pin=BOOL\n"
" Whether to require entering a PIN to unlock the volume\n"
+ " --fido2-with-user-presence=BOOL\n"
+ " Whether to require user presence to unlock the volume\n"
" --tpm2-device=PATH\n"
" Enroll a TPM2 device\n"
" --tpm2-pcrs=PCR1,PCR2,PCR3,…\n"
ARG_TPM2_PCRS,
ARG_WIPE_SLOT,
ARG_FIDO2_WITH_PIN,
+ ARG_FIDO2_WITH_UP,
};
static const struct option options[] = {
{ "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI },
{ "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 },
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
{ "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
{ "wipe-slot", required_argument, NULL, ARG_WIPE_SLOT },
break;
}
+ case ARG_FIDO2_WITH_UP: {
+ bool lock_with_up;
+
+ r = parse_boolean_argument("--fido2-with-user-presence=", optarg, &lock_with_up);
+ if (r < 0)
+ return r;
+
+ SET_FLAG(arg_fido2_lock_with, FIDO2ENROLL_UP, lock_with_up);
+
+ break;
+ }
+
case ARG_PASSWORD:
if (arg_enroll_type >= 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
const void *cid,
size_t cid_size,
char **pins,
- bool up, /* user presence permitted */
- Fido2EnrollFlags required, /* client pin required */
+ Fido2EnrollFlags required, /* client pin/user presence required */
void **ret_hmac,
size_t *ret_hmac_size) {
"PIN required to unlock, but FIDO2 device %s does not support it.",
path);
+ if (!has_up && FLAGS_SET(required, FIDO2ENROLL_UP))
+ return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON),
+ "User presence test required to unlock, but FIDO2 device %s does not support it.",
+ path);
+
a = sym_fido_assert_new();
if (!a)
return log_oom();
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to add FIDO2 assertion credential ID: %s", sym_fido_strerr(r));
- if (has_up) {
- r = sym_fido_assert_set_up(a, FIDO_OPT_FALSE);
- if (r != FIDO_OK)
- return log_error_errno(SYNTHETIC_ERRNO(EIO),
- "Failed to set FIDO2 assertion user presence: %s", sym_fido_strerr(r));
- }
-
log_info("Asking FIDO2 token for authentication.");
- r = sym_fido_dev_get_assert(d, a, NULL); /* try without pin and without up first */
- if (r == FIDO_ERR_UP_REQUIRED && up) {
-
- if (!has_up)
- log_warning("Weird, device asked for User Presence check, but does not advertise it as feature. Ignoring.");
-
- r = sym_fido_assert_set_up(a, FIDO_OPT_TRUE);
+ if (has_up) {
+ r = sym_fido_assert_set_up(a, FLAGS_SET(required, FIDO2ENROLL_UP) ? FIDO_OPT_TRUE : FIDO_OPT_FALSE);
if (r != FIDO_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
- "Failed to set FIDO2 assertion user presence: %s", sym_fido_strerr(r));
-
- log_info("Security token requires user presence.");
+ "Failed to %s FIDO2 user presence test: %s",
+ enable_disable(FLAGS_SET(required, FIDO2ENROLL_UP)),
+ sym_fido_strerr(r));
- r = sym_fido_dev_get_assert(d, a, NULL); /* try without pin but with up now */
+ if (FLAGS_SET(required, FIDO2ENROLL_UP))
+ log_info("User presence required to unlock.");
}
+
if (FLAGS_SET(required, FIDO2ENROLL_PIN)) {
char **i;
if (r != FIDO_ERR_PIN_INVALID)
break;
}
- }
+ } else
+ r = sym_fido_dev_get_assert(d, a, NULL);
switch (r) {
case FIDO_OK:
const void *cid,
size_t cid_size,
char **pins,
- bool up, /* user presence permitted */
- Fido2EnrollFlags required, /* client pin required */
+ Fido2EnrollFlags required, /* client pin/user presence required */
void **ret_hmac,
size_t *ret_hmac_size) {
return log_error_errno(r, "FIDO2 support is not installed.");
if (device)
- return fido2_use_hmac_hash_specific_token(device, rp_id, salt, salt_size, cid, cid_size, pins, up, required, ret_hmac, ret_hmac_size);
+ return fido2_use_hmac_hash_specific_token(device, rp_id, salt, salt_size, cid, cid_size, pins, required, ret_hmac, ret_hmac_size);
di = sym_fido_dev_info_new(allocated);
if (!di)
goto finish;
}
- r = fido2_use_hmac_hash_specific_token(path, rp_id, salt, salt_size, cid, cid_size, pins, up, required, ret_hmac, ret_hmac_size);
+ r = fido2_use_hmac_hash_specific_token(path, rp_id, salt, salt_size, cid, cid_size, pins, required, ret_hmac, ret_hmac_size);
if (!IN_SET(r,
-EBADSLT, /* device doesn't understand our credential hash */
-ENODEV /* device is not a FIDO2 device with HMAC-SECRET */))
"Requested to lock with PIN, but FIDO2 device %s does not support it.",
device);
+ if (!has_up && FLAGS_SET(lock_with, FIDO2ENROLL_UP))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Locking with user presence test requested, but FIDO2 device %s does not support it.",
+ device);
+
c = sym_fido_cred_new();
if (!c)
return log_oom();
return log_error_errno(SYNTHETIC_ERRNO(EIO),
"Failed to add FIDO2 assertion credential ID: %s", sym_fido_strerr(r));
+ log_info("Generating secret key on FIDO2 security token.");
+
if (has_up) {
- r = sym_fido_assert_set_up(a, FIDO_OPT_FALSE);
+ r = sym_fido_assert_set_up(a, FLAGS_SET(lock_with, FIDO2ENROLL_UP) ? FIDO_OPT_TRUE : FIDO_OPT_FALSE);
if (r != FIDO_OK)
return log_error_errno(SYNTHETIC_ERRNO(EIO),
- "Failed to turn off FIDO2 assertion user presence: %s", sym_fido_strerr(r));
+ "Failed to %s FIDO2 user presence test: %s",
+ enable_disable(FLAGS_SET(lock_with, FIDO2ENROLL_UP)),
+ sym_fido_strerr(r));
+
+ if (FLAGS_SET(lock_with, FIDO2ENROLL_UP))
+ log_notice("%s%sIn order to allow secret key generation, please confirm presence on security token.",
+ emoji_enabled() ? special_glyph(SPECIAL_GLYPH_TOUCH) : "",
+ emoji_enabled() ? " " : "");
}
- log_info("Generating secret key on FIDO2 security token.");
-
r = sym_fido_dev_get_assert(d, a, FLAGS_SET(lock_with, FIDO2ENROLL_PIN) ? used_pin : NULL);
- if (r == FIDO_ERR_UP_REQUIRED) {
-
- if (!has_up)
- log_warning("Weird, device asked for User Presence check, but does not advertise it as feature. Ignoring.");
-
- r = sym_fido_assert_set_up(a, FIDO_OPT_TRUE);
- if (r != FIDO_OK)
- return log_error_errno(SYNTHETIC_ERRNO(EIO),
- "Failed to turn on FIDO2 assertion user presence: %s", sym_fido_strerr(r));
-
- log_notice("%s%sIn order to allow secret key generation, please verify presence on security token.",
- emoji_enabled() ? special_glyph(SPECIAL_GLYPH_TOUCH) : "",
- emoji_enabled() ? " " : "");
-
- r = sym_fido_dev_get_assert(d, a, FLAGS_SET(lock_with, FIDO2ENROLL_PIN) ? used_pin : NULL);
- }
+ if (r == FIDO_ERR_UP_REQUIRED && !FLAGS_SET(lock_with, FIDO2ENROLL_UP))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Locking without user presence test requested, but FIDO2 device %s requires it.",
+ device);
if (r == FIDO_ERR_ACTION_TIMEOUT)
return log_error_errno(SYNTHETIC_ERRNO(ENOSTR),
"Token action timeout. (User didn't interact with token quickly enough.)");