diff --git a/Cargo.lock b/Cargo.lock index ac154cf..782efa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -286,9 +286,9 @@ dependencies = [ [[package]] name = "ctap_hmac" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ccc28f298181e943187fa63805e652bc4806ad43708beebd22c230fbe0baa3" +checksum = "c83f25a6970eb60fd32754c99ffb0b89ff464d70bf8dea147805497c7fb7eb5e" dependencies = [ "byteorder", "cbor-codec", diff --git a/Cargo.toml b/Cargo.toml index 97ba046..9546d26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ categories = ["command-line-utilities"] license = "MPL-2.0" [dependencies] -ctap_hmac = { version="0.4.2", features = ["request_multiple"] } +ctap_hmac = { version="0.4.4", features = ["request_multiple"] } hex = "0.3.2" ring = "0.13.5" failure = "0.1.5" @@ -26,7 +26,7 @@ serde_derive = "1.0.116" serde = "1.0.116" [build-dependencies] -ctap_hmac = { version="0.4.2", features = ["request_multiple"] } +ctap_hmac = { version="0.4.4", features = ["request_multiple"] } hex = "0.3.2" ring = "0.13.5" failure = "0.1.5" diff --git a/src/cli.rs b/src/cli.rs index 75fbc7c..11fd9c8 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -94,7 +94,7 @@ pub fn get_input( let salt = &secret.salt; Ok(if interactive { ( - if authenticator.pin { + if authenticator.pin && may_require_pin()? { Some(read_pin()?) } else { None @@ -102,7 +102,10 @@ pub fn get_input( salt.obtain_sha256(Some(|| util::read_password_tty(q, verify)))?, ) } else { - match (authenticator.pin, authenticator.pin_prefixed) { + match ( + authenticator.pin && may_require_pin()?, + authenticator.pin_prefixed, + ) { (true, false) => (Some(read_pin()?), salt.obtain_sha256(password_helper)?), (true, true) => read_password_pin_prefixed(|| { salt.obtain(password_helper).and_then(|secret| { @@ -157,7 +160,7 @@ pub fn run_cli() -> Fido2LuksResult<()> { let args = parse_cmdline(); let log = |message: &dyn Fn() -> String| { if args.verbose { - eprintln!("{}", message()); + eprintln!("{}", &*message()); } }; match &args.command { @@ -166,7 +169,7 @@ pub fn run_cli() -> Fido2LuksResult<()> { name, } => { let pin_string; - let pin = if authenticator.pin { + let pin = if authenticator.pin && may_require_pin()? { pin_string = read_pin()?; Some(pin_string.as_ref()) } else { @@ -319,7 +322,7 @@ pub fn run_cli() -> Fido2LuksResult<()> { let (new_secret, cred) = if *auto_credential && luks2 { let cred = make_credential_id( Some(derive_credential_name(luks.device.as_path()).as_str()), - (if authenticator.pin { + (if authenticator.pin && may_require_pin()? { //TODO: not ideal since it ignores pin-prefixed Some(read_pin()?) } else { diff --git a/src/cli_args/mod.rs b/src/cli_args/mod.rs index d79088f..ac5744f 100644 --- a/src/cli_args/mod.rs +++ b/src/cli_args/mod.rs @@ -76,7 +76,7 @@ pub struct Credentials { #[derive(Debug, StructOpt)] pub struct AuthenticatorParameters { - /// Request a PIN to unlock the authenticator + /// Request a PIN to unlock the authenticator if required #[structopt(short = "P", long = "pin")] pub pin: bool, diff --git a/src/device.rs b/src/device.rs index 99ac2a7..e735165 100644 --- a/src/device.rs +++ b/src/device.rs @@ -19,7 +19,7 @@ pub fn make_credential_id( } let request = request.build().unwrap(); let make_credential = |device: &mut FidoDevice| { - if let Some(pin) = pin { + if let Some(pin) = pin.filter(|_| device.needs_pin()) { device.unlock(pin)?; } device.make_hmac_credential(&request) @@ -44,7 +44,7 @@ pub fn perform_challenge<'a>( .build() .unwrap(); let get_assertion = |device: &mut FidoDevice| { - if let Some(pin) = pin { + if let Some(pin) = pin.filter(|_| device.needs_pin()) { device.unlock(pin)?; } device.get_hmac_assertion(&request, &util::sha256(&[&salt[..]]), None) @@ -58,6 +58,17 @@ pub fn perform_challenge<'a>( Ok((secret, credential)) } +pub fn may_require_pin() -> Fido2LuksResult { + for di in ctap::get_devices()? { + if let Ok(dev) = FidoDevice::new(&di) { + if dev.needs_pin() { + return Ok(true); + } + } + } + Ok(false) +} + pub fn get_devices() -> Fido2LuksResult> { let mut devices = Vec::with_capacity(2); for di in ctap::get_devices()? {