Compile flag for AuthenticatorConfig (#628)
* Adds a compile flag for AuthenticatorConfig The command can be disabled for authenticators that don't want users to change their configuration. * adds tool for calling Config * std now implies config_command * removes obsolete comment
This commit is contained in:
@@ -22,7 +22,7 @@ libtock_drivers = { path = "third_party/libtock-drivers" }
|
|||||||
libtock_console = { path = "third_party/libtock-rs/apis/console" }
|
libtock_console = { path = "third_party/libtock-rs/apis/console" }
|
||||||
libtock_leds = { path = "third_party/libtock-rs/apis/leds" }
|
libtock_leds = { path = "third_party/libtock-rs/apis/leds" }
|
||||||
lang_items = { path = "third_party/lang-items" }
|
lang_items = { path = "third_party/lang-items" }
|
||||||
opensk = { path = "libraries/opensk" }
|
opensk = { path = "libraries/opensk", default-features = false }
|
||||||
sk-cbor = { path = "libraries/cbor" }
|
sk-cbor = { path = "libraries/cbor" }
|
||||||
crypto = { path = "libraries/crypto" }
|
crypto = { path = "libraries/crypto" }
|
||||||
persistent_store = { path = "libraries/persistent_store" }
|
persistent_store = { path = "libraries/persistent_store" }
|
||||||
@@ -33,6 +33,7 @@ rand_core = "0.6.4"
|
|||||||
ed25519-compact = { version = "1", default-features = false, optional = true }
|
ed25519-compact = { version = "1", default-features = false, optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
config_command = ["opensk/config_command"]
|
||||||
debug_allocations = ["lang_items/debug_allocations"]
|
debug_allocations = ["lang_items/debug_allocations"]
|
||||||
debug_ctap = ["libtock_drivers/debug_ctap", "opensk/debug_ctap"]
|
debug_ctap = ["libtock_drivers/debug_ctap", "opensk/debug_ctap"]
|
||||||
panic_console = ["lang_items/panic_console"]
|
panic_console = ["lang_items/panic_console"]
|
||||||
|
|||||||
@@ -1091,6 +1091,13 @@ if __name__ == "__main__":
|
|||||||
help=("Compiles the OpenSK application without backward compatible "
|
help=("Compiles the OpenSK application without backward compatible "
|
||||||
"support for U2F/CTAP1 protocol."),
|
"support for U2F/CTAP1 protocol."),
|
||||||
)
|
)
|
||||||
|
main_parser.add_argument(
|
||||||
|
"--no-config-command",
|
||||||
|
action=RemoveConstAction,
|
||||||
|
const="config_command",
|
||||||
|
dest="features",
|
||||||
|
help=("Removes the AuthenticatorConfig command."),
|
||||||
|
)
|
||||||
main_parser.add_argument(
|
main_parser.add_argument(
|
||||||
"--rust-crypto",
|
"--rust-crypto",
|
||||||
action="append_const",
|
action="append_const",
|
||||||
@@ -1174,7 +1181,7 @@ if __name__ == "__main__":
|
|||||||
help=("Firmware version that is built."),
|
help=("Firmware version that is built."),
|
||||||
)
|
)
|
||||||
|
|
||||||
main_parser.set_defaults(features=["with_ctap1"])
|
main_parser.set_defaults(features=["with_ctap1", "config_command"])
|
||||||
|
|
||||||
# Start parsing to know if we're going to list things or not.
|
# Start parsing to know if we're going to list things or not.
|
||||||
partial_args, _ = main_parser.parse_known_args()
|
partial_args, _ = main_parser.parse_known_args()
|
||||||
|
|||||||
@@ -36,8 +36,10 @@ features = ["alloc", "ecdh", "ecdsa"]
|
|||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["config_command", "with_ctap1"]
|
||||||
|
config_command = []
|
||||||
debug_ctap = []
|
debug_ctap = []
|
||||||
std = ["crypto/std", "persistent_store/std", "rand/std_rng"]
|
std = ["crypto/std", "persistent_store/std", "rand/std_rng", "config_command"]
|
||||||
with_ctap1 = ["crypto/with_ctap1"]
|
with_ctap1 = ["crypto/with_ctap1"]
|
||||||
vendor_hid = []
|
vendor_hid = []
|
||||||
fuzz = ["arbitrary", "std"]
|
fuzz = ["arbitrary", "std"]
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ pub enum PinPermission {
|
|||||||
CredentialManagement = 0x04,
|
CredentialManagement = 0x04,
|
||||||
_BioEnrollment = 0x08,
|
_BioEnrollment = 0x08,
|
||||||
LargeBlobWrite = 0x10,
|
LargeBlobWrite = 0x10,
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
AuthenticatorConfiguration = 0x20,
|
AuthenticatorConfiguration = 0x20,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,14 @@
|
|||||||
use super::cbor_read;
|
use super::cbor_read;
|
||||||
use super::data_formats::{
|
use super::data_formats::{
|
||||||
extract_array, extract_byte_string, extract_map, extract_text_string, extract_unsigned,
|
extract_array, extract_byte_string, extract_map, extract_text_string, extract_unsigned,
|
||||||
ok_or_missing, ClientPinSubCommand, ConfigSubCommand, ConfigSubCommandParams, CoseKey,
|
ok_or_missing, ClientPinSubCommand, CoseKey, CredentialManagementSubCommand,
|
||||||
CredentialManagementSubCommand, CredentialManagementSubCommandParameters,
|
CredentialManagementSubCommandParameters, GetAssertionExtensions, GetAssertionOptions,
|
||||||
GetAssertionExtensions, GetAssertionOptions, MakeCredentialExtensions, MakeCredentialOptions,
|
MakeCredentialExtensions, MakeCredentialOptions, PinUvAuthProtocol,
|
||||||
PinUvAuthProtocol, PublicKeyCredentialDescriptor, PublicKeyCredentialParameter,
|
PublicKeyCredentialDescriptor, PublicKeyCredentialParameter, PublicKeyCredentialRpEntity,
|
||||||
PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity, SetMinPinLengthParams,
|
PublicKeyCredentialUserEntity,
|
||||||
};
|
};
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
|
use super::data_formats::{ConfigSubCommand, ConfigSubCommandParams, SetMinPinLengthParams};
|
||||||
use super::status_code::Ctap2StatusCode;
|
use super::status_code::Ctap2StatusCode;
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
@@ -46,6 +48,7 @@ pub enum Command {
|
|||||||
AuthenticatorCredentialManagement(AuthenticatorCredentialManagementParameters),
|
AuthenticatorCredentialManagement(AuthenticatorCredentialManagementParameters),
|
||||||
AuthenticatorSelection,
|
AuthenticatorSelection,
|
||||||
AuthenticatorLargeBlobs(AuthenticatorLargeBlobsParameters),
|
AuthenticatorLargeBlobs(AuthenticatorLargeBlobsParameters),
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
AuthenticatorConfig(AuthenticatorConfigParameters),
|
AuthenticatorConfig(AuthenticatorConfigParameters),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +64,7 @@ impl Command {
|
|||||||
const AUTHENTICATOR_CREDENTIAL_MANAGEMENT: u8 = 0x0A;
|
const AUTHENTICATOR_CREDENTIAL_MANAGEMENT: u8 = 0x0A;
|
||||||
const AUTHENTICATOR_SELECTION: u8 = 0x0B;
|
const AUTHENTICATOR_SELECTION: u8 = 0x0B;
|
||||||
const AUTHENTICATOR_LARGE_BLOBS: u8 = 0x0C;
|
const AUTHENTICATOR_LARGE_BLOBS: u8 = 0x0C;
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
const AUTHENTICATOR_CONFIG: u8 = 0x0D;
|
const AUTHENTICATOR_CONFIG: u8 = 0x0D;
|
||||||
const _AUTHENTICATOR_VENDOR_FIRST: u8 = 0x40;
|
const _AUTHENTICATOR_VENDOR_FIRST: u8 = 0x40;
|
||||||
// This commands is the same as AUTHENTICATOR_CREDENTIAL_MANAGEMENT but is duplicated as a
|
// This commands is the same as AUTHENTICATOR_CREDENTIAL_MANAGEMENT but is duplicated as a
|
||||||
@@ -124,6 +128,7 @@ impl Command {
|
|||||||
AuthenticatorLargeBlobsParameters::try_from(decoded_cbor)?,
|
AuthenticatorLargeBlobsParameters::try_from(decoded_cbor)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
Command::AUTHENTICATOR_CONFIG => {
|
Command::AUTHENTICATOR_CONFIG => {
|
||||||
let decoded_cbor = cbor_read(&bytes[1..])?;
|
let decoded_cbor = cbor_read(&bytes[1..])?;
|
||||||
Ok(Command::AuthenticatorConfig(
|
Ok(Command::AuthenticatorConfig(
|
||||||
@@ -429,6 +434,7 @@ impl TryFrom<cbor::Value> for AuthenticatorLargeBlobsParameters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct AuthenticatorConfigParameters {
|
pub struct AuthenticatorConfigParameters {
|
||||||
pub sub_command: ConfigSubCommand,
|
pub sub_command: ConfigSubCommand,
|
||||||
@@ -437,6 +443,7 @@ pub struct AuthenticatorConfigParameters {
|
|||||||
pub pin_uv_auth_param: Option<Vec<u8>>,
|
pub pin_uv_auth_param: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
impl TryFrom<cbor::Value> for AuthenticatorConfigParameters {
|
impl TryFrom<cbor::Value> for AuthenticatorConfigParameters {
|
||||||
type Error = Ctap2StatusCode;
|
type Error = Ctap2StatusCode;
|
||||||
|
|
||||||
@@ -684,6 +691,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
fn test_from_cbor_config_parameters() {
|
fn test_from_cbor_config_parameters() {
|
||||||
let cbor_value = cbor_map! {
|
let cbor_value = cbor_map! {
|
||||||
0x01 => ConfigSubCommand::SetMinPinLength as u64,
|
0x01 => ConfigSubCommand::SetMinPinLength as u64,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
pub mod apdu;
|
pub mod apdu;
|
||||||
mod client_pin;
|
mod client_pin;
|
||||||
pub mod command;
|
pub mod command;
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
mod config_command;
|
mod config_command;
|
||||||
mod credential_management;
|
mod credential_management;
|
||||||
pub mod crypto_wrapper;
|
pub mod crypto_wrapper;
|
||||||
@@ -39,6 +40,7 @@ use self::client_pin::{ClientPin, PinPermission};
|
|||||||
use self::command::{
|
use self::command::{
|
||||||
AuthenticatorGetAssertionParameters, AuthenticatorMakeCredentialParameters, Command,
|
AuthenticatorGetAssertionParameters, AuthenticatorMakeCredentialParameters, Command,
|
||||||
};
|
};
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
use self::config_command::process_config;
|
use self::config_command::process_config;
|
||||||
use self::credential_management::process_credential_management;
|
use self::credential_management::process_credential_management;
|
||||||
use self::data_formats::{
|
use self::data_formats::{
|
||||||
@@ -655,6 +657,7 @@ impl<E: Env> CtapState<E> {
|
|||||||
self.large_blobs
|
self.large_blobs
|
||||||
.process_command(env, &mut self.client_pin, params)
|
.process_command(env, &mut self.client_pin, params)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
Command::AuthenticatorConfig(params) => {
|
Command::AuthenticatorConfig(params) => {
|
||||||
process_config(env, &mut self.client_pin, params)
|
process_config(env, &mut self.client_pin, params)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ pub enum ResponseData {
|
|||||||
AuthenticatorCredentialManagement(Option<AuthenticatorCredentialManagementResponse>),
|
AuthenticatorCredentialManagement(Option<AuthenticatorCredentialManagementResponse>),
|
||||||
AuthenticatorSelection,
|
AuthenticatorSelection,
|
||||||
AuthenticatorLargeBlobs(Option<AuthenticatorLargeBlobsResponse>),
|
AuthenticatorLargeBlobs(Option<AuthenticatorLargeBlobsResponse>),
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
AuthenticatorConfig,
|
AuthenticatorConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ impl From<ResponseData> for Option<cbor::Value> {
|
|||||||
ResponseData::AuthenticatorCredentialManagement(data) => data.map(|d| d.into()),
|
ResponseData::AuthenticatorCredentialManagement(data) => data.map(|d| d.into()),
|
||||||
ResponseData::AuthenticatorSelection => None,
|
ResponseData::AuthenticatorSelection => None,
|
||||||
ResponseData::AuthenticatorLargeBlobs(data) => data.map(|d| d.into()),
|
ResponseData::AuthenticatorLargeBlobs(data) => data.map(|d| d.into()),
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
ResponseData::AuthenticatorConfig => None,
|
ResponseData::AuthenticatorConfig => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -586,6 +588,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
fn test_config_into_cbor() {
|
fn test_config_into_cbor() {
|
||||||
let response_cbor: Option<cbor::Value> = ResponseData::AuthenticatorConfig.into();
|
let response_cbor: Option<cbor::Value> = ResponseData::AuthenticatorConfig.into();
|
||||||
assert_eq!(response_cbor, None);
|
assert_eq!(response_cbor, None);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
mod key;
|
mod key;
|
||||||
|
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
use crate::api::attestation_store::{self, AttestationStore};
|
use crate::api::attestation_store::{self, AttestationStore};
|
||||||
use crate::api::customization::Customization;
|
use crate::api::customization::Customization;
|
||||||
use crate::api::key_store::KeyStore;
|
use crate::api::key_store::KeyStore;
|
||||||
@@ -31,6 +32,7 @@ use arrayref::array_ref;
|
|||||||
use core::cmp;
|
use core::cmp;
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use persistent_store::{fragment, StoreUpdate};
|
use persistent_store::{fragment, StoreUpdate};
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
use sk_cbor::cbor_array_vec;
|
use sk_cbor::cbor_array_vec;
|
||||||
|
|
||||||
/// Wrapper for PIN properties.
|
/// Wrapper for PIN properties.
|
||||||
@@ -39,6 +41,7 @@ struct PinProperties {
|
|||||||
hash: [u8; PIN_AUTH_LENGTH],
|
hash: [u8; PIN_AUTH_LENGTH],
|
||||||
|
|
||||||
/// Length of the current PIN in code points.
|
/// Length of the current PIN in code points.
|
||||||
|
#[cfg_attr(not(feature = "config_command"), allow(dead_code))]
|
||||||
code_point_length: u8,
|
code_point_length: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +271,7 @@ pub fn pin_hash(env: &mut impl Env) -> Result<Option<[u8; PIN_AUTH_LENGTH]>, Cta
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the length of the currently set PIN if defined.
|
/// Returns the length of the currently set PIN if defined.
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
pub fn pin_code_point_length(env: &mut impl Env) -> Result<Option<u8>, Ctap2StatusCode> {
|
pub fn pin_code_point_length(env: &mut impl Env) -> Result<Option<u8>, Ctap2StatusCode> {
|
||||||
Ok(pin_properties(env)?.map(|p| p.code_point_length))
|
Ok(pin_properties(env)?.map(|p| p.code_point_length))
|
||||||
}
|
}
|
||||||
@@ -328,6 +332,7 @@ pub fn min_pin_length(env: &mut impl Env) -> Result<u8, Ctap2StatusCode> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the minimum PIN length.
|
/// Sets the minimum PIN length.
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
pub fn set_min_pin_length(env: &mut impl Env, min_pin_length: u8) -> Result<(), Ctap2StatusCode> {
|
pub fn set_min_pin_length(env: &mut impl Env, min_pin_length: u8) -> Result<(), Ctap2StatusCode> {
|
||||||
Ok(env.store().insert(key::MIN_PIN_LENGTH, &[min_pin_length])?)
|
Ok(env.store().insert(key::MIN_PIN_LENGTH, &[min_pin_length])?)
|
||||||
}
|
}
|
||||||
@@ -344,6 +349,7 @@ pub fn min_pin_length_rp_ids(env: &mut impl Env) -> Result<Vec<String>, Ctap2Sta
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the list of RP IDs that are used to check if reading the minimum PIN length is allowed.
|
/// Sets the list of RP IDs that are used to check if reading the minimum PIN length is allowed.
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
pub fn set_min_pin_length_rp_ids(
|
pub fn set_min_pin_length_rp_ids(
|
||||||
env: &mut impl Env,
|
env: &mut impl Env,
|
||||||
min_pin_length_rp_ids: Vec<String>,
|
min_pin_length_rp_ids: Vec<String>,
|
||||||
@@ -428,6 +434,7 @@ pub fn has_force_pin_change(env: &mut impl Env) -> Result<bool, Ctap2StatusCode>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Marks the PIN as outdated with respect to the new PIN policy.
|
/// Marks the PIN as outdated with respect to the new PIN policy.
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
pub fn force_pin_change(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
|
pub fn force_pin_change(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
|
||||||
Ok(env.store().insert(key::FORCE_PIN_CHANGE, &[])?)
|
Ok(env.store().insert(key::FORCE_PIN_CHANGE, &[])?)
|
||||||
}
|
}
|
||||||
@@ -442,6 +449,7 @@ pub fn enterprise_attestation(env: &mut impl Env) -> Result<bool, Ctap2StatusCod
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Marks enterprise attestation as enabled.
|
/// Marks enterprise attestation as enabled.
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
pub fn enable_enterprise_attestation(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
|
pub fn enable_enterprise_attestation(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
|
||||||
if env
|
if env
|
||||||
.attestation_store()
|
.attestation_store()
|
||||||
@@ -469,6 +477,7 @@ pub fn has_always_uv(env: &mut impl Env) -> Result<bool, Ctap2StatusCode> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Enables alwaysUv, when disabled, and vice versa.
|
/// Enables alwaysUv, when disabled, and vice versa.
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
pub fn toggle_always_uv(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
|
pub fn toggle_always_uv(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
|
||||||
if env.customization().enforce_always_uv() {
|
if env.customization().enforce_always_uv() {
|
||||||
return Err(Ctap2StatusCode::CTAP2_ERR_OPERATION_DENIED);
|
return Err(Ctap2StatusCode::CTAP2_ERR_OPERATION_DENIED);
|
||||||
@@ -588,6 +597,7 @@ fn deserialize_min_pin_length_rp_ids(data: &[u8]) -> Option<Vec<String>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes a list of RP IDs to storage representation.
|
/// Serializes a list of RP IDs to storage representation.
|
||||||
|
#[cfg(feature = "config_command")]
|
||||||
fn serialize_min_pin_length_rp_ids(rp_ids: Vec<String>) -> Result<Vec<u8>, Ctap2StatusCode> {
|
fn serialize_min_pin_length_rp_ids(rp_ids: Vec<String>) -> Result<Vec<u8>, Ctap2StatusCode> {
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
super::cbor_write(cbor_array_vec!(rp_ids), &mut data)?;
|
super::cbor_write(cbor_array_vec!(rp_ids), &mut data)?;
|
||||||
|
|||||||
55
tools/authenticator_config.py
Executable file
55
tools/authenticator_config.py
Executable file
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2023 Google LLC
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
# Lint as: python3
|
||||||
|
"""Tool that sends a config command to OpenSK."""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import colorama
|
||||||
|
from fido2 import hid
|
||||||
|
from fido2.ctap2 import Config
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from tools.configure import fatal, get_opensk_devices, info
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
colorama.init()
|
||||||
|
|
||||||
|
devices = get_opensk_devices(False)
|
||||||
|
if not devices:
|
||||||
|
fatal("No devices found.")
|
||||||
|
|
||||||
|
for authenticator in devices:
|
||||||
|
if authenticator.device.capabilities & hid.CAPABILITY.WINK:
|
||||||
|
authenticator.device.wink()
|
||||||
|
aaguid = uuid.UUID(bytes=authenticator.get_info().aaguid)
|
||||||
|
info(f"Config of device AAGUID {aaguid} ({authenticator.device}).")
|
||||||
|
|
||||||
|
config = Config(authenticator)
|
||||||
|
if args.ep:
|
||||||
|
info("Enable EP...")
|
||||||
|
config.enable_enterprise_attestation()
|
||||||
|
if args.always_uv:
|
||||||
|
info("Toggle AlwaysUv...")
|
||||||
|
config.toggle_always_uv()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--ep", action=argparse.BooleanOptionalAction)
|
||||||
|
parser.add_argument("--always-uv", action=argparse.BooleanOptionalAction)
|
||||||
|
main(parser.parse_args())
|
||||||
Reference in New Issue
Block a user