зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1814722 - Handle FIDO AppID extension in CTAPHIDTokenManager. r=keeler,supply-chain-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D169020
This commit is contained in:
Родитель
ed2a0660f9
Коммит
7ec1da7ce5
|
@ -379,9 +379,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "authenticator"
|
||||
version = "0.4.0-alpha.7"
|
||||
version = "0.4.0-alpha.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "178ca28a8c8b156a4f7aa70e789d87a598fa71a2a66094ed92dee513b3cdf868"
|
||||
checksum = "6e8f8b1ede732a8535be3d622011b25ae6f15bf2090468feaf6cb4e21097fdf8"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bitflags",
|
||||
|
|
|
@ -268,6 +268,7 @@ RefPtr<U2FSignPromise> CTAPHIDTokenManager::Sign(
|
|||
appIds.AppendElement(rpIdHash.InfallibleClone());
|
||||
|
||||
Maybe<nsTArray<uint8_t>> appIdHashExt = Nothing();
|
||||
nsCString appId;
|
||||
|
||||
if (aInfo.Extra().isSome()) {
|
||||
const auto& extra = aInfo.Extra().ref();
|
||||
|
@ -281,6 +282,8 @@ RefPtr<U2FSignPromise> CTAPHIDTokenManager::Sign(
|
|||
// Process extensions.
|
||||
for (const WebAuthnExtension& ext : extra.Extensions()) {
|
||||
if (ext.type() == WebAuthnExtension::TWebAuthnExtensionAppId) {
|
||||
appId = NS_ConvertUTF16toUTF8(
|
||||
ext.get_WebAuthnExtensionAppId().appIdentifier());
|
||||
appIdHashExt = Some(ext.get_WebAuthnExtensionAppId().AppId().Clone());
|
||||
appIds.AppendElement(appIdHashExt->Clone());
|
||||
}
|
||||
|
@ -302,7 +305,7 @@ RefPtr<U2FSignPromise> CTAPHIDTokenManager::Sign(
|
|||
};
|
||||
tid = rust_ctap2_mgr_sign(
|
||||
mCTAPManager, (uint64_t)aInfo.TimeoutMS(), ctap2_sign_callback,
|
||||
status_callback, challenge, rpId.get(),
|
||||
status_callback, challenge, rpId.get(), appId.get(),
|
||||
NS_ConvertUTF16toUTF8(aInfo.Origin()).get(),
|
||||
Ctap2PubKeyCredentialDescriptor(aInfo.AllowList()).Get(), options,
|
||||
nullptr);
|
||||
|
@ -632,7 +635,18 @@ CTAPHIDTokenManager::HandleSelectedSignResultCtap2(
|
|||
return mozilla::Nothing();
|
||||
}
|
||||
|
||||
nsTArray<uint8_t> effectiveRpIdHash;
|
||||
if (!aResult->Ctap2CopyRpIdHash(effectiveRpIdHash, index)) {
|
||||
mSignPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
|
||||
return mozilla::Nothing();
|
||||
}
|
||||
|
||||
nsTArray<WebAuthnExtensionResult> extensions;
|
||||
if (mTransaction.ref().mAppIdHash.isSome()) {
|
||||
bool usedAppId = (effectiveRpIdHash == mTransaction.ref().mAppIdHash.ref());
|
||||
extensions.AppendElement(WebAuthnExtensionResultAppId(usedAppId));
|
||||
}
|
||||
|
||||
WebAuthnGetAssertionResult assertion(clientData, pubKeyCred, signatureBuf,
|
||||
authData, extensions, signature, userID);
|
||||
mozilla::Maybe<nsCString> username;
|
||||
|
|
|
@ -221,6 +221,10 @@ class CTAPResult {
|
|||
return Ctap2SignResCopyBuffer(index, CTAP2_SIGN_RESULT_AUTH_DATA, aBuffer);
|
||||
}
|
||||
|
||||
bool Ctap2CopyRpIdHash(nsTArray<uint8_t>& aBuffer, size_t index) {
|
||||
return Ctap2SignResCopyBuffer(index, CTAP2_SIGN_RESULT_RP_ID_HASH, aBuffer);
|
||||
}
|
||||
|
||||
bool Ctap2HasPubKeyCredential(size_t index) {
|
||||
return Ctap2SignResContains(index, CTAP2_SIGN_RESULT_PUBKEY_CRED_ID);
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ notes = "I maintain this crate and have reviewed every line."
|
|||
[[audits.authenticator]]
|
||||
who = "John M. Schanck <jschanck@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "0.4.0-alpha.7"
|
||||
version = "0.4.0-alpha.8"
|
||||
notes = "Maintained by the CryptoEng team at Mozilla."
|
||||
|
||||
[[audits.autocfg]]
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -39,7 +39,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "authenticator"
|
||||
version = "0.4.0-alpha.7"
|
||||
version = "0.4.0-alpha.8"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"base64",
|
||||
|
@ -183,9 +183,9 @@ checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.74"
|
||||
version = "1.0.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574"
|
||||
checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
|
@ -551,9 +551,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
|||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.23"
|
||||
version = "0.14.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
|
||||
checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
|
||||
dependencies = [
|
||||
"bytes 1.2.1",
|
||||
"futures-channel",
|
||||
|
@ -631,15 +631,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.137"
|
||||
version = "0.2.136"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
checksum = "55edcf6c0bb319052dea84732cf99db461780fd5e8d3eb46ab6ff312ab31f197"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
|
@ -784,9 +784,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.14.0"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
|
@ -794,9 +794,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
|
@ -892,15 +892,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.26"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
|
@ -967,9 +967,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.0"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -978,9 +978,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.28"
|
||||
version = "0.6.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
|
@ -1051,9 +1051,9 @@ checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
|
|||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
|
@ -1119,9 +1119,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.10.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
|
||||
checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
|
@ -1285,9 +1285,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.8.2"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
|
||||
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "authenticator"
|
||||
version = "0.4.0-alpha.7"
|
||||
version = "0.4.0-alpha.8"
|
||||
authors = [
|
||||
"J.C. Jones <jc@mozilla.com>",
|
||||
"Tim Taubert <ttaubert@mozilla.com>",
|
||||
|
|
|
@ -30,7 +30,7 @@ fn u2f_get_key_handle_from_register_response(register_response: &[u8]) -> io::Re
|
|||
}
|
||||
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let brief = format!("Usage: {} [options]", program);
|
||||
let brief = format!("Usage: {program} [options]");
|
||||
print!("{}", opts.usage(&brief));
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ fn main() {
|
|||
timeout_s * 1_000
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
println!("{e}");
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
|
@ -108,13 +108,13 @@ fn main() {
|
|||
thread::spawn(move || loop {
|
||||
match status_rx.recv() {
|
||||
Ok(StatusUpdate::DeviceAvailable { dev_info }) => {
|
||||
println!("STATUS: device available: {}", dev_info)
|
||||
println!("STATUS: device available: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::DeviceUnavailable { dev_info }) => {
|
||||
println!("STATUS: device unavailable: {}", dev_info)
|
||||
println!("STATUS: device unavailable: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::Success { dev_info }) => {
|
||||
println!("STATUS: success using device: {}", dev_info);
|
||||
println!("STATUS: success using device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::PinError(..))
|
||||
| Ok(StatusUpdate::SelectDeviceNotice)
|
||||
|
|
|
@ -21,7 +21,7 @@ use std::sync::mpsc::{channel, RecvError};
|
|||
use std::{env, thread};
|
||||
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let brief = format!("Usage: {} [options]", program);
|
||||
let brief = format!("Usage: {program} [options]");
|
||||
print!("{}", opts.usage(&brief));
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ fn main() {
|
|||
timeout_s * 1_000
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
println!("{e}");
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
|
@ -86,19 +86,19 @@ fn main() {
|
|||
thread::spawn(move || loop {
|
||||
match status_rx.recv() {
|
||||
Ok(StatusUpdate::DeviceAvailable { dev_info }) => {
|
||||
println!("STATUS: device available: {}", dev_info)
|
||||
println!("STATUS: device available: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::DeviceUnavailable { dev_info }) => {
|
||||
println!("STATUS: device unavailable: {}", dev_info)
|
||||
println!("STATUS: device unavailable: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::Success { dev_info }) => {
|
||||
println!("STATUS: success using device: {}", dev_info);
|
||||
println!("STATUS: success using device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::SelectDeviceNotice) => {
|
||||
println!("STATUS: Please select a device by touching one of them.");
|
||||
}
|
||||
Ok(StatusUpdate::DeviceSelected(dev_info)) => {
|
||||
println!("STATUS: Continuing with device: {}", dev_info);
|
||||
println!("STATUS: Continuing with device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::PinError(error, sender)) => match error {
|
||||
PinError::PinRequired => {
|
||||
|
@ -111,8 +111,7 @@ fn main() {
|
|||
println!(
|
||||
"Wrong PIN! {}",
|
||||
attempts.map_or("Try again.".to_string(), |a| format!(
|
||||
"You have {} attempts left.",
|
||||
a
|
||||
"You have {a} attempts left."
|
||||
))
|
||||
);
|
||||
let raw_pin = rpassword::prompt_password_stderr("Enter PIN: ")
|
||||
|
@ -255,6 +254,7 @@ fn main() {
|
|||
},
|
||||
},
|
||||
pin: None,
|
||||
alternate_rp_id: None,
|
||||
};
|
||||
|
||||
loop {
|
||||
|
@ -280,7 +280,7 @@ fn main() {
|
|||
match sign_result {
|
||||
Ok(SignResult::CTAP1(..)) => panic!("Requested CTAP2, but got CTAP1 sign results!"),
|
||||
Ok(SignResult::CTAP2(assertion_object, _client_data)) => {
|
||||
println!("Assertion Object: {:?}", assertion_object);
|
||||
println!("Assertion Object: {assertion_object:?}");
|
||||
println!("Done.");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ fn print_usage(program: &str, opts: Options) {
|
|||
println!("requests 'discoverable credentials' for them.");
|
||||
println!("After that, we try to log in to that origin and list all credentials found.");
|
||||
println!("------------------------------------------------------------------------");
|
||||
let brief = format!("Usage: {} [options]", program);
|
||||
let brief = format!("Usage: {program} [options]");
|
||||
print!("{}", opts.usage(&brief));
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,7 @@ fn register_user(manager: &mut AuthenticatorService, username: &str, timeout_ms:
|
|||
println!();
|
||||
println!("*********************************************************************");
|
||||
println!(
|
||||
"Asking a security key to register now with user: {}",
|
||||
username
|
||||
"Asking a security key to register now with user: {username}"
|
||||
);
|
||||
println!("*********************************************************************");
|
||||
|
||||
|
@ -57,19 +56,19 @@ fn register_user(manager: &mut AuthenticatorService, username: &str, timeout_ms:
|
|||
thread::spawn(move || loop {
|
||||
match status_rx.recv() {
|
||||
Ok(StatusUpdate::DeviceAvailable { dev_info }) => {
|
||||
println!("STATUS: device available: {}", dev_info)
|
||||
println!("STATUS: device available: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::DeviceUnavailable { dev_info }) => {
|
||||
println!("STATUS: device unavailable: {}", dev_info)
|
||||
println!("STATUS: device unavailable: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::Success { dev_info }) => {
|
||||
println!("STATUS: success using device: {}", dev_info);
|
||||
println!("STATUS: success using device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::SelectDeviceNotice) => {
|
||||
println!("STATUS: Please select a device by touching one of them.");
|
||||
}
|
||||
Ok(StatusUpdate::DeviceSelected(dev_info)) => {
|
||||
println!("STATUS: Continuing with device: {}", dev_info);
|
||||
println!("STATUS: Continuing with device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::PinError(error, sender)) => match error {
|
||||
PinError::PinRequired => {
|
||||
|
@ -82,8 +81,7 @@ fn register_user(manager: &mut AuthenticatorService, username: &str, timeout_ms:
|
|||
println!(
|
||||
"Wrong PIN! {}",
|
||||
attempts.map_or("Try again.".to_string(), |a| format!(
|
||||
"You have {} attempts left.",
|
||||
a
|
||||
"You have {a} attempts left."
|
||||
))
|
||||
);
|
||||
let raw_pin = rpassword::prompt_password_stderr("Enter PIN: ")
|
||||
|
@ -218,7 +216,7 @@ fn main() {
|
|||
timeout_s * 1_000
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
println!("{e}");
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
|
@ -246,19 +244,19 @@ fn main() {
|
|||
thread::spawn(move || loop {
|
||||
match status_rx.recv() {
|
||||
Ok(StatusUpdate::DeviceAvailable { dev_info }) => {
|
||||
println!("STATUS: device available: {}", dev_info)
|
||||
println!("STATUS: device available: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::DeviceUnavailable { dev_info }) => {
|
||||
println!("STATUS: device unavailable: {}", dev_info)
|
||||
println!("STATUS: device unavailable: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::Success { dev_info }) => {
|
||||
println!("STATUS: success using device: {}", dev_info);
|
||||
println!("STATUS: success using device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::SelectDeviceNotice) => {
|
||||
println!("STATUS: Please select a device by touching one of them.");
|
||||
}
|
||||
Ok(StatusUpdate::DeviceSelected(dev_info)) => {
|
||||
println!("STATUS: Continuing with device: {}", dev_info);
|
||||
println!("STATUS: Continuing with device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::PinError(error, sender)) => match error {
|
||||
PinError::PinRequired => {
|
||||
|
@ -271,8 +269,7 @@ fn main() {
|
|||
println!(
|
||||
"Wrong PIN! {}",
|
||||
attempts.map_or("Try again.".to_string(), |a| format!(
|
||||
"You have {} attempts left.",
|
||||
a
|
||||
"You have {a} attempts left."
|
||||
))
|
||||
);
|
||||
let raw_pin = rpassword::prompt_password_stderr("Enter PIN: ")
|
||||
|
@ -308,6 +305,7 @@ fn main() {
|
|||
options: GetAssertionOptions::default(),
|
||||
extensions: Default::default(),
|
||||
pin: None,
|
||||
alternate_rp_id: None,
|
||||
};
|
||||
|
||||
loop {
|
||||
|
@ -333,7 +331,7 @@ fn main() {
|
|||
match sign_result {
|
||||
Ok(SignResult::CTAP1(..)) => panic!("Requested CTAP2, but got CTAP1 sign results!"),
|
||||
Ok(SignResult::CTAP2(assertion_object, _client_data)) => {
|
||||
println!("Assertion Object: {:?}", assertion_object);
|
||||
println!("Assertion Object: {assertion_object:?}");
|
||||
println!("-----------------------------------------------------------------");
|
||||
println!("Found credentials:");
|
||||
println!(
|
||||
|
|
|
@ -30,7 +30,7 @@ fn u2f_get_key_handle_from_register_response(register_response: &[u8]) -> io::Re
|
|||
}
|
||||
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let brief = format!("Usage: {} [options]", program);
|
||||
let brief = format!("Usage: {program} [options]");
|
||||
print!("{}", opts.usage(&brief));
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ fn main() {
|
|||
timeout_s * 1_000
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
println!("{e}");
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
|
@ -108,13 +108,13 @@ fn main() {
|
|||
thread::spawn(move || loop {
|
||||
match status_rx.recv() {
|
||||
Ok(StatusUpdate::DeviceAvailable { dev_info }) => {
|
||||
println!("STATUS: device available: {}", dev_info)
|
||||
println!("STATUS: device available: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::DeviceUnavailable { dev_info }) => {
|
||||
println!("STATUS: device unavailable: {}", dev_info)
|
||||
println!("STATUS: device unavailable: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::Success { dev_info }) => {
|
||||
println!("STATUS: success using device: {}", dev_info);
|
||||
println!("STATUS: success using device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::PinError(..))
|
||||
| Ok(StatusUpdate::SelectDeviceNotice)
|
||||
|
|
|
@ -14,7 +14,7 @@ use std::env;
|
|||
use std::sync::mpsc::{channel, RecvError};
|
||||
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let brief = format!("Usage: {} [options]", program);
|
||||
let brief = format!("Usage: {program} [options]");
|
||||
print!("{}", opts.usage(&brief));
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ fn main() {
|
|||
timeout_s * 1_000
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
println!("{e}");
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ fn main() {
|
|||
return;
|
||||
}
|
||||
Ok(StatusUpdate::DeviceSelected(dev_info)) => {
|
||||
println!("STATUS: Continuing with device: {}", dev_info);
|
||||
println!("STATUS: Continuing with device: {dev_info}");
|
||||
break;
|
||||
}
|
||||
Ok(StatusUpdate::PinError(..)) => panic!("Reset should never ask for a PIN!"),
|
||||
|
|
|
@ -12,7 +12,7 @@ use std::sync::mpsc::{channel, RecvError};
|
|||
use std::{env, thread};
|
||||
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let brief = format!("Usage: {} [options]", program);
|
||||
let brief = format!("Usage: {program} [options]");
|
||||
print!("{}", opts.usage(&brief));
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ fn main() {
|
|||
timeout_s * 1_000
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
println!("{e}");
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
|
@ -71,19 +71,19 @@ fn main() {
|
|||
thread::spawn(move || loop {
|
||||
match status_rx.recv() {
|
||||
Ok(StatusUpdate::DeviceAvailable { dev_info }) => {
|
||||
println!("STATUS: device available: {}", dev_info)
|
||||
println!("STATUS: device available: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::DeviceUnavailable { dev_info }) => {
|
||||
println!("STATUS: device unavailable: {}", dev_info)
|
||||
println!("STATUS: device unavailable: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::Success { dev_info }) => {
|
||||
println!("STATUS: success using device: {}", dev_info);
|
||||
println!("STATUS: success using device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::SelectDeviceNotice) => {
|
||||
println!("STATUS: Please select a device by touching one of them.");
|
||||
}
|
||||
Ok(StatusUpdate::DeviceSelected(dev_info)) => {
|
||||
println!("STATUS: Continuing with device: {}", dev_info);
|
||||
println!("STATUS: Continuing with device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::PinError(error, sender)) => match error {
|
||||
PinError::PinRequired => {
|
||||
|
@ -96,8 +96,7 @@ fn main() {
|
|||
println!(
|
||||
"Wrong PIN! {}",
|
||||
attempts.map_or("Try again.".to_string(), |a| format!(
|
||||
"You have {} attempts left.",
|
||||
a
|
||||
"You have {a} attempts left."
|
||||
))
|
||||
);
|
||||
let raw_pin = rpassword::prompt_password_stderr("Enter current PIN: ")
|
||||
|
|
|
@ -21,7 +21,7 @@ use std::sync::mpsc::{channel, RecvError};
|
|||
use std::{env, thread};
|
||||
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let brief = format!("Usage: {} [options]", program);
|
||||
let brief = format!("Usage: {program} [options]");
|
||||
print!("{}", opts.usage(&brief));
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ fn main() {
|
|||
timeout_s * 1_000
|
||||
}
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
println!("{e}");
|
||||
print_usage(&program, opts);
|
||||
return;
|
||||
}
|
||||
|
@ -82,19 +82,19 @@ fn main() {
|
|||
thread::spawn(move || loop {
|
||||
match status_rx.recv() {
|
||||
Ok(StatusUpdate::DeviceAvailable { dev_info }) => {
|
||||
println!("STATUS: device available: {}", dev_info)
|
||||
println!("STATUS: device available: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::DeviceUnavailable { dev_info }) => {
|
||||
println!("STATUS: device unavailable: {}", dev_info)
|
||||
println!("STATUS: device unavailable: {dev_info}")
|
||||
}
|
||||
Ok(StatusUpdate::Success { dev_info }) => {
|
||||
println!("STATUS: success using device: {}", dev_info);
|
||||
println!("STATUS: success using device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::SelectDeviceNotice) => {
|
||||
println!("STATUS: Please select a device by touching one of them.");
|
||||
}
|
||||
Ok(StatusUpdate::DeviceSelected(dev_info)) => {
|
||||
println!("STATUS: Continuing with device: {}", dev_info);
|
||||
println!("STATUS: Continuing with device: {dev_info}");
|
||||
}
|
||||
Ok(StatusUpdate::PinError(error, sender)) => match error {
|
||||
PinError::PinRequired => {
|
||||
|
@ -107,8 +107,7 @@ fn main() {
|
|||
println!(
|
||||
"Wrong PIN! {}",
|
||||
attempts.map_or("Try again.".to_string(), |a| format!(
|
||||
"You have {} attempts left.",
|
||||
a
|
||||
"You have {a} attempts left."
|
||||
))
|
||||
);
|
||||
let raw_pin = rpassword::prompt_password_stderr("Enter PIN: ")
|
||||
|
|
|
@ -81,6 +81,7 @@ pub struct SignArgsCtap2 {
|
|||
pub options: GetAssertionOptions,
|
||||
pub extensions: GetAssertionExtensions,
|
||||
pub pin: Option<Pin>,
|
||||
pub alternate_rp_id: Option<String>,
|
||||
// Todo: Extensions
|
||||
}
|
||||
|
||||
|
@ -839,6 +840,7 @@ mod tests {
|
|||
options: Default::default(),
|
||||
extensions: Default::default(),
|
||||
pin: None,
|
||||
alternate_rp_id: None,
|
||||
};
|
||||
assert!(s
|
||||
.sign(
|
||||
|
|
|
@ -490,7 +490,7 @@ impl<'de> Deserialize<'de> for COSEKey {
|
|||
}
|
||||
let value: u64 = map.next_value()?;
|
||||
let val = COSEKeyTypeId::try_from(value).map_err(|_| {
|
||||
SerdeError::custom(format!("unsupported key_type {}", value))
|
||||
SerdeError::custom(format!("unsupported key_type {value}"))
|
||||
})?;
|
||||
key_type = Some(val);
|
||||
// key_type = Some(map.next_value()?);
|
||||
|
@ -510,7 +510,7 @@ impl<'de> Deserialize<'de> for COSEKey {
|
|||
}
|
||||
let value: u64 = map.next_value()?;
|
||||
let val = ECDSACurve::try_from(value).map_err(|_| {
|
||||
SerdeError::custom(format!("unsupported curve {}", value))
|
||||
SerdeError::custom(format!("unsupported curve {value}"))
|
||||
})?;
|
||||
curve = Some(val);
|
||||
// curve = Some(map.next_value()?);
|
||||
|
@ -536,7 +536,7 @@ impl<'de> Deserialize<'de> for COSEKey {
|
|||
}
|
||||
let value: i64 = map.next_value()?;
|
||||
let val = COSEAlgorithm::try_from(value).map_err(|_| {
|
||||
SerdeError::custom(format!("unsupported algorithm {}", value))
|
||||
SerdeError::custom(format!("unsupported algorithm {value}"))
|
||||
})?;
|
||||
alg = Some(val);
|
||||
// alg = map.next_value()?;
|
||||
|
|
|
@ -33,7 +33,7 @@ pub enum BackendError {
|
|||
|
||||
impl From<NSSError> for BackendError {
|
||||
fn from(e: NSSError) -> Self {
|
||||
BackendError::NSSError(format!("{}", e))
|
||||
BackendError::NSSError(format!("{e}"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ const uint8_t CTAP2_SIGN_RESULT_AUTH_DATA = 2;
|
|||
const uint8_t CTAP2_SIGN_RESULT_SIGNATURE = 3;
|
||||
const uint8_t CTAP2_SIGN_RESULT_USER_ID = 4;
|
||||
const uint8_t CTAP2_SIGN_RESULT_USER_NAME = 5;
|
||||
const uint8_t CTAP2_SIGN_RESULT_RP_ID_HASH = 6;
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *id_ptr;
|
||||
|
@ -93,7 +94,7 @@ uint64_t rust_ctap2_mgr_register(
|
|||
uint64_t rust_ctap2_mgr_sign(
|
||||
rust_ctap_manager* mgr, uint64_t timeout, rust_ctap2_sign_callback, rust_ctap2_status_update_callback,
|
||||
AuthenticatorArgsChallenge challenge,
|
||||
const char* relying_party_id, const char *origin_ptr,
|
||||
const char* relying_party_id, const char* alternate_relying_party_id, const char *origin_ptr,
|
||||
const rust_ctap2_pub_key_cred_descriptors* allow_list, AuthenticatorArgsOptions options,
|
||||
const char *pin
|
||||
);
|
||||
|
|
|
@ -321,7 +321,7 @@ pub struct Signature(#[serde(with = "serde_bytes")] pub(crate) ByteBuf);
|
|||
impl fmt::Debug for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let value = base64::encode_config(&self.0, base64::URL_SAFE_NO_PAD);
|
||||
write!(f, "Signature({})", value)
|
||||
write!(f, "Signature({value})")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,7 +494,7 @@ impl<'de> Deserialize<'de> for AttestationObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
k => return Err(M::Error::custom(format!("unexpected key: {:?}", k))),
|
||||
k => return Err(M::Error::custom(format!("unexpected key: {k:?}"))),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -748,7 +748,7 @@ mod test {
|
|||
#[test]
|
||||
fn parse_attestation_object() {
|
||||
let value: AttestationObject = from_slice(&SAMPLE_ATTESTATION).unwrap();
|
||||
println!("{:?}", value);
|
||||
println!("{value:?}");
|
||||
|
||||
//assert_eq!(true, false);
|
||||
}
|
||||
|
@ -795,7 +795,7 @@ mod test {
|
|||
];
|
||||
let expected = "AAGuid(cb69481e-8ff0-0039-93ec-0a2729a154a8)";
|
||||
let result = AAGuid::from(&input).expect("Failed to parse AAGuid");
|
||||
let res_str = format!("{:?}", result);
|
||||
let res_str = format!("{result:?}");
|
||||
assert_eq!(expected, &res_str);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ impl<'de> Deserialize<'de> for TokenBinding {
|
|||
id = Some(map.next_value()?);
|
||||
}
|
||||
k => {
|
||||
return Err(M::Error::custom(format!("unexpected key: {:?}", k)));
|
||||
return Err(M::Error::custom(format!("unexpected key: {k:?}")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ impl<'de> Deserialize<'de> for TokenBinding {
|
|||
}
|
||||
}
|
||||
"supported" => Ok(TokenBinding::Supported),
|
||||
k => Err(M::Error::custom(format!("unexpected status key: {:?}", k))),
|
||||
k => Err(M::Error::custom(format!("unexpected status key: {k:?}"))),
|
||||
}
|
||||
} else {
|
||||
Err(SerdeError::missing_field("status"))
|
||||
|
|
|
@ -751,12 +751,12 @@ impl fmt::Display for PinError {
|
|||
match *self {
|
||||
PinError::PinRequired => write!(f, "PinError: Pin required."),
|
||||
PinError::PinIsTooShort => write!(f, "PinError: pin is too short"),
|
||||
PinError::PinIsTooLong(len) => write!(f, "PinError: pin is too long ({})", len),
|
||||
PinError::PinIsTooLong(len) => write!(f, "PinError: pin is too long ({len})"),
|
||||
PinError::InvalidKeyLen => write!(f, "PinError: invalid key len"),
|
||||
PinError::InvalidPin(ref e) => {
|
||||
let mut res = write!(f, "PinError: Invalid Pin.");
|
||||
if let Some(pin_retries) = e {
|
||||
res = write!(f, " Retries left: {:?}", pin_retries)
|
||||
res = write!(f, " Retries left: {pin_retries:?}")
|
||||
}
|
||||
res
|
||||
}
|
||||
|
@ -769,7 +769,7 @@ impl fmt::Display for PinError {
|
|||
"PinError: No retries left. Pin blocked. Device needs reset."
|
||||
),
|
||||
PinError::PinNotSet => write!(f, "PinError: Pin needed but not set on device."),
|
||||
PinError::Backend(ref e) => write!(f, "PinError: Crypto backend error: {:?}", e),
|
||||
PinError::Backend(ref e) => write!(f, "PinError: Crypto backend error: {e:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,6 +190,9 @@ pub struct GetAssertion {
|
|||
pub(crate) options: GetAssertionOptions,
|
||||
pub(crate) pin: Option<Pin>,
|
||||
pub(crate) pin_auth: Option<PinAuth>,
|
||||
|
||||
// This is used to implement the FIDO AppID extension.
|
||||
pub(crate) alternate_rp_id: Option<String>,
|
||||
//TODO(MS): pinProtocol
|
||||
}
|
||||
|
||||
|
@ -201,6 +204,7 @@ impl GetAssertion {
|
|||
options: GetAssertionOptions,
|
||||
extensions: GetAssertionExtensions,
|
||||
pin: Option<Pin>,
|
||||
alternate_rp_id: Option<String>,
|
||||
) -> Result<Self, HIDError> {
|
||||
let client_data_wrapper = CollectedClientDataWrapper::new(client_data_wrapper)?;
|
||||
Ok(Self {
|
||||
|
@ -211,6 +215,7 @@ impl GetAssertion {
|
|||
options,
|
||||
pin,
|
||||
pin_auth: None,
|
||||
alternate_rp_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -642,7 +647,7 @@ impl<'de> Deserialize<'de> for GetAssertionResponse {
|
|||
}
|
||||
number_of_credentials = Some(map.next_value()?);
|
||||
}
|
||||
k => return Err(M::Error::custom(format!("unexpected key: {:?}", k))),
|
||||
k => return Err(M::Error::custom(format!("unexpected key: {k:?}"))),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,6 +725,7 @@ pub mod test {
|
|||
},
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.expect("Failed to create GetAssertion");
|
||||
let mut device = Device::new("commands/get_assertion").unwrap();
|
||||
|
@ -929,6 +935,7 @@ pub mod test {
|
|||
},
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.expect("Failed to create GetAssertion");
|
||||
let mut device = Device::new("commands/get_assertion").unwrap(); // not really used (all functions ignore it)
|
||||
|
@ -1022,6 +1029,7 @@ pub mod test {
|
|||
},
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.expect("Failed to create GetAssertion");
|
||||
|
||||
|
|
|
@ -681,8 +681,7 @@ pub mod test {
|
|||
.expect("Failed to serialize MakeCredentials request");
|
||||
assert_eq!(
|
||||
req_serialized, MAKE_CREDENTIALS_SAMPLE_REQUEST_CTAP1,
|
||||
"\nGot: {:X?}\nExpected: {:X?}",
|
||||
req_serialized, MAKE_CREDENTIALS_SAMPLE_REQUEST_CTAP1
|
||||
"\nGot: {req_serialized:X?}\nExpected: {MAKE_CREDENTIALS_SAMPLE_REQUEST_CTAP1:X?}"
|
||||
);
|
||||
let (attestation_object, _collected_client_data) = match req
|
||||
.handle_response_ctap1(Ok(()), &MAKE_CREDENTIALS_SAMPLE_RESPONSE_CTAP1, &())
|
||||
|
|
|
@ -400,19 +400,19 @@ impl fmt::Display for CommandError {
|
|||
match *self {
|
||||
CommandError::InputTooSmall => write!(f, "CommandError: Input is too small"),
|
||||
CommandError::MissingRequiredField(field) => {
|
||||
write!(f, "CommandError: Missing required field {}", field)
|
||||
write!(f, "CommandError: Missing required field {field}")
|
||||
}
|
||||
CommandError::Deserializing(ref e) => {
|
||||
write!(f, "CommandError: Error while parsing: {}", e)
|
||||
write!(f, "CommandError: Error while parsing: {e}")
|
||||
}
|
||||
CommandError::Serializing(ref e) => {
|
||||
write!(f, "CommandError: Error while serializing: {}", e)
|
||||
write!(f, "CommandError: Error while serializing: {e}")
|
||||
}
|
||||
CommandError::StatusCode(ref code, ref value) => {
|
||||
write!(f, "CommandError: Unexpected code: {:?} ({:?})", code, value)
|
||||
write!(f, "CommandError: Unexpected code: {code:?} ({value:?})")
|
||||
}
|
||||
CommandError::Json(ref e) => write!(f, "CommandError: Json serializing error: {}", e),
|
||||
CommandError::Crypto(ref e) => write!(f, "CommandError: Crypto error: {:?}", e),
|
||||
CommandError::Json(ref e) => write!(f, "CommandError: Json serializing error: {e}"),
|
||||
CommandError::Crypto(ref e) => write!(f, "CommandError: Crypto error: {e:?}"),
|
||||
CommandError::UnsupportedPinProtocol => {
|
||||
write!(f, "CommandError: Pin protocol is not supported")
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ pub struct RpIdHash(pub [u8; 32]);
|
|||
impl fmt::Debug for RpIdHash {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let value = base64::encode_config(self.0, base64::URL_SAFE_NO_PAD);
|
||||
write!(f, "RpIdHash({})", value)
|
||||
write!(f, "RpIdHash({value})")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ impl<'de> Deserialize<'de> for PublicKeyCredentialParameters {
|
|||
|
||||
let v: &str = map.next_value()?;
|
||||
if v != "public-key" {
|
||||
return Err(SerdeError::custom(format!("invalid value: {}", v)));
|
||||
return Err(SerdeError::custom(format!("invalid value: {v}")));
|
||||
}
|
||||
found_type = true;
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ impl<'de> Deserialize<'de> for PublicKeyCredentialDescriptor {
|
|||
}
|
||||
let v: &str = map.next_value()?;
|
||||
if v != "public-key" {
|
||||
return Err(SerdeError::custom(format!("invalid value: {}", v)));
|
||||
return Err(SerdeError::custom(format!("invalid value: {v}")));
|
||||
}
|
||||
found_type = true;
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ mod test {
|
|||
};
|
||||
|
||||
let payload = ser::to_vec(&user).unwrap();
|
||||
println!("payload = {:?}", payload);
|
||||
println!("payload = {payload:?}");
|
||||
assert_eq!(
|
||||
payload,
|
||||
vec![
|
||||
|
@ -394,7 +394,7 @@ mod test {
|
|||
};
|
||||
|
||||
let payload = ser::to_vec(&user).unwrap();
|
||||
println!("payload = {:?}", payload);
|
||||
println!("payload = {payload:?}");
|
||||
assert_eq!(
|
||||
payload,
|
||||
vec![
|
||||
|
@ -431,7 +431,7 @@ mod test {
|
|||
];
|
||||
|
||||
let payload = ser::to_vec(&keys);
|
||||
println!("payload = {:?}", payload);
|
||||
println!("payload = {payload:?}");
|
||||
let payload = payload.unwrap();
|
||||
assert_eq!(
|
||||
payload,
|
||||
|
@ -471,7 +471,7 @@ mod test {
|
|||
};
|
||||
|
||||
let payload = ser::to_vec(&key);
|
||||
println!("payload = {:?}", payload);
|
||||
println!("payload = {payload:?}");
|
||||
let payload = payload.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
|
|
|
@ -36,6 +36,7 @@ const SIGN_RESULT_AUTH_DATA: u8 = 2;
|
|||
const SIGN_RESULT_SIGNATURE: u8 = 3;
|
||||
const SIGN_RESULT_USER_ID: u8 = 4;
|
||||
const SIGN_RESULT_USER_NAME: u8 = 5;
|
||||
const SIGN_RESULT_RP_ID_HASH: u8 = 6;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct AuthenticatorArgsUser {
|
||||
|
@ -307,6 +308,7 @@ pub unsafe extern "C" fn rust_ctap2_mgr_sign(
|
|||
status_callback: Ctap2StatusUpdateCallback,
|
||||
challenge: AuthenticatorArgsChallenge,
|
||||
relying_party_id: *const c_char,
|
||||
alternate_relying_party_id: *const c_char,
|
||||
origin_ptr: *const c_char,
|
||||
allow_list: *const Ctap2PubKeyCredDescriptors,
|
||||
options: AuthenticatorArgsOptions,
|
||||
|
@ -333,6 +335,11 @@ pub unsafe extern "C" fn rust_ctap2_mgr_sign(
|
|||
let rpid = CStr::from_ptr(relying_party_id)
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
let alternate_rp_id = if alternate_relying_party_id.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CStr::from_ptr(alternate_relying_party_id).to_string_lossy().to_string())
|
||||
};
|
||||
let origin = CStr::from_ptr(origin_ptr).to_string_lossy().to_string();
|
||||
let challenge = from_raw(challenge.ptr, challenge.len);
|
||||
let allow_list: Vec<_> = (*allow_list).clone();
|
||||
|
@ -382,6 +389,7 @@ pub unsafe extern "C" fn rust_ctap2_mgr_sign(
|
|||
challenge,
|
||||
origin,
|
||||
relying_party_id: rpid,
|
||||
alternate_rp_id,
|
||||
allow_list,
|
||||
options: GetAssertionOptions {
|
||||
user_presence: options.user_presence.then_some(true),
|
||||
|
@ -672,6 +680,7 @@ fn sign_result_item_len(assertion: &Assertion, item_idx: u8) -> Option<usize> {
|
|||
.or(u.name.as_ref())
|
||||
.map(|n| n.as_bytes().len())
|
||||
}),
|
||||
SIGN_RESULT_RP_ID_HASH => Some(assertion.auth_data.rp_id_hash.0.len()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -756,6 +765,7 @@ unsafe fn sign_result_item_copy(assertion: &Assertion, item_idx: u8, dst: *mut u
|
|||
.or(u.name.as_ref())
|
||||
.map(|n| n.as_bytes())
|
||||
}),
|
||||
SIGN_RESULT_RP_ID_HASH => Some(assertion.auth_data.rp_id_hash.0.as_ref()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
|
|
@ -64,23 +64,22 @@ impl fmt::Display for AuthenticatorError {
|
|||
"no transports were configured in the authenticator service"
|
||||
),
|
||||
AuthenticatorError::Platform => write!(f, "unknown platform error"),
|
||||
AuthenticatorError::InternalError(ref err) => write!(f, "internal error: {}", err),
|
||||
AuthenticatorError::InternalError(ref err) => write!(f, "internal error: {err}"),
|
||||
AuthenticatorError::U2FToken(ref err) => {
|
||||
write!(f, "A u2f token error occurred {:?}", err)
|
||||
write!(f, "A u2f token error occurred {err:?}")
|
||||
}
|
||||
AuthenticatorError::Custom(ref err) => write!(f, "A custom error occurred {:?}", err),
|
||||
AuthenticatorError::Custom(ref err) => write!(f, "A custom error occurred {err:?}"),
|
||||
AuthenticatorError::VersionMismatch(manager, version) => write!(
|
||||
f,
|
||||
"{} expected arguments of version CTAP{}",
|
||||
manager, version
|
||||
"{manager} expected arguments of version CTAP{version}"
|
||||
),
|
||||
AuthenticatorError::HIDError(ref e) => write!(f, "Device error: {}", e),
|
||||
AuthenticatorError::HIDError(ref e) => write!(f, "Device error: {e}"),
|
||||
AuthenticatorError::CryptoError => {
|
||||
write!(f, "The cryptography implementation encountered an error")
|
||||
}
|
||||
AuthenticatorError::PinError(ref e) => write!(f, "PIN Error: {}", e),
|
||||
AuthenticatorError::PinError(ref e) => write!(f, "PIN Error: {e}"),
|
||||
AuthenticatorError::UnsupportedOption(ref e) => {
|
||||
write!(f, "Unsupported option: {:?}", e)
|
||||
write!(f, "Unsupported option: {e:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -495,6 +495,7 @@ impl AuthenticatorTransport for Manager {
|
|||
options,
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
|
||||
let action = QueueAction::SignCtap2 {
|
||||
|
@ -528,6 +529,7 @@ impl AuthenticatorTransport for Manager {
|
|||
args.options,
|
||||
args.extensions,
|
||||
args.pin,
|
||||
args.alternate_rp_id,
|
||||
)?;
|
||||
|
||||
let action = QueueAction::SignCtap2 {
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::ctap2::commands::reset::Reset;
|
|||
use crate::ctap2::commands::{
|
||||
repackage_pin_errors, CommandError, PinAuthCommand, Request, StatusCode,
|
||||
};
|
||||
use crate::ctap2::server::{RelyingParty, RelyingPartyWrapper};
|
||||
use crate::errors::{self, AuthenticatorError, UnsupportedOption};
|
||||
use crate::statecallback::StateCallback;
|
||||
use crate::transport::device_selector::{
|
||||
|
@ -606,7 +607,16 @@ impl StateMachineCtap2 {
|
|||
debug!("{:?}", getassertion);
|
||||
debug!("------------------------------------------------------------------");
|
||||
|
||||
let resp = dev.send_msg(&getassertion);
|
||||
let mut resp = dev.send_msg(&getassertion);
|
||||
if resp.is_err() {
|
||||
// Retry with a different RP ID if one was supplied. This is intended to be
|
||||
// used with the AppID provided in the WebAuthn FIDO AppID extension.
|
||||
if let Some(alternate_rp_id) = getassertion.alternate_rp_id {
|
||||
getassertion.rp = RelyingPartyWrapper::Data(RelyingParty{id: alternate_rp_id, ..Default::default()});
|
||||
getassertion.alternate_rp_id = None;
|
||||
resp = dev.send_msg(&getassertion);
|
||||
}
|
||||
}
|
||||
if resp.is_ok() {
|
||||
send_status(
|
||||
&status,
|
||||
|
|
|
@ -325,7 +325,7 @@ pub mod tests {
|
|||
add_devices(devices.iter(), &selector);
|
||||
devices.iter_mut().for_each(|d| {
|
||||
if !d.is_u2f() {
|
||||
send_no_token(&d, &selector);
|
||||
send_no_token(d, &selector);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ impl fmt::Display for ApduErrorStatus {
|
|||
ApduErrorStatus::ConditionsNotSatisfied => write!(f, "Apdu: condition not satisfied"),
|
||||
ApduErrorStatus::WrongData => write!(f, "Apdu: wrong data"),
|
||||
ApduErrorStatus::WrongLength => write!(f, "Apdu: wrong length"),
|
||||
ApduErrorStatus::Unknown(ref u) => write!(f, "Apdu: unknown error: {:?}", u),
|
||||
ApduErrorStatus::Unknown(ref u) => write!(f, "Apdu: unknown error: {u:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,11 +87,11 @@ impl fmt::Display for HIDError {
|
|||
HIDError::UnsupportedCommand => {
|
||||
write!(f, "Error: command is not supported on this device")
|
||||
}
|
||||
HIDError::IO(ref p, ref e) => write!(f, "Error: Ioerror({:?}): {}", p, e),
|
||||
HIDError::Command(ref e) => write!(f, "Error: Error issuing command: {}", e),
|
||||
HIDError::UnexpectedCmd(s) => write!(f, "Error: Unexpected status: {}", s),
|
||||
HIDError::IO(ref p, ref e) => write!(f, "Error: Ioerror({p:?}): {e}"),
|
||||
HIDError::Command(ref e) => write!(f, "Error: Error issuing command: {e}"),
|
||||
HIDError::UnexpectedCmd(s) => write!(f, "Error: Unexpected status: {s}"),
|
||||
HIDError::ApduStatus(ref status) => {
|
||||
write!(f, "Error: Unexpected apdu status: {:?}", status)
|
||||
write!(f, "Error: Unexpected apdu status: {status:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,20 +39,14 @@ impl Device {
|
|||
if prop_ref.is_null() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!(
|
||||
"IOHIDDeviceGetProperty received nullptr for property {}",
|
||||
prop_name
|
||||
),
|
||||
format!("IOHIDDeviceGetProperty received nullptr for property {prop_name}"),
|
||||
));
|
||||
}
|
||||
|
||||
if CFGetTypeID(prop_ref) != CFStringGetTypeID() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
format!(
|
||||
"IOHIDDeviceGetProperty returned non-string type for property {}",
|
||||
prop_name
|
||||
),
|
||||
format!("IOHIDDeviceGetProperty returned non-string type for property {prop_name}"),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ where
|
|||
if rv == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io_err(&format!("Couldn't open HID Manager, rv={}", rv)))
|
||||
Err(io_err(&format!("Couldn't open HID Manager, rv={rv}")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ where
|
|||
let mut send_failed = false;
|
||||
|
||||
// Ignore the report if we can't find a device for it.
|
||||
if let Some(&DeviceData { ref tx, .. }) = this.map.get(&device_ref) {
|
||||
if let Some(DeviceData { tx, .. }) = this.map.get(&device_ref) {
|
||||
let data = unsafe { slice::from_raw_parts(report, report_len as usize).to_vec() };
|
||||
send_failed = tx.send(data).is_err();
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ impl U2FDevice for Device {
|
|||
}
|
||||
|
||||
fn get_property(&self, prop_name: &str) -> io::Result<String> {
|
||||
Ok(format!("{} not implemented", prop_name))
|
||||
Ok(format!("{prop_name} not implemented"))
|
||||
}
|
||||
fn get_device_info(&self) -> U2FDeviceInfo {
|
||||
self.dev_info.clone().unwrap()
|
||||
|
|
|
@ -66,7 +66,7 @@ where
|
|||
// Loop until we're stopped by the controlling thread, or fail.
|
||||
while alive() {
|
||||
for n in 0..100 {
|
||||
let uhidpath = OsString::from(format!("/dev/uhid{}", n));
|
||||
let uhidpath = OsString::from(format!("/dev/uhid{n}"));
|
||||
match Fd::open(&uhidpath, libc::O_RDWR | libc::O_CLOEXEC) {
|
||||
Ok(uhid) => {
|
||||
// The device is available if it can be opened.
|
||||
|
|
|
@ -175,7 +175,7 @@ fn status_word_to_result<T>(status: [u8; 2], val: T) -> io::Result<T> {
|
|||
SW_WRONG_DATA => Err(io::Error::new(InvalidData, "wrong data")),
|
||||
SW_WRONG_LENGTH => Err(io::Error::new(InvalidInput, "wrong length")),
|
||||
SW_CONDITIONS_NOT_SATISFIED => Err(io_err("conditions not satisfied")),
|
||||
_ => Err(io_err(&format!("failed with status {:?}", status))),
|
||||
_ => Err(io_err(&format!("failed with status {status:?}"))),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use serde::Serialize;
|
|||
use std::{cmp, fmt, io, str};
|
||||
|
||||
pub fn to_hex(data: &[u8], joiner: &str) -> String {
|
||||
let parts: Vec<String> = data.iter().map(|byte| format!("{:02x}", byte)).collect();
|
||||
let parts: Vec<String> = data.iter().map(|byte| format!("{byte:02x}")).collect();
|
||||
parts.join(joiner)
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ tokio-reactor = { version = "=0.1.3", optional = true }
|
|||
# audioipc2-client and audioipc2-server.
|
||||
tokio-threadpool = { version = "=0.1.17", optional = true }
|
||||
encoding_glue = { path = "../../../../intl/encoding_glue" }
|
||||
authenticator = { version = "0.4.0-alpha.7", features = ["gecko"] }
|
||||
authenticator = { version = "0.4.0-alpha.8", features = ["gecko"] }
|
||||
gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
|
||||
gecko_logger = { path = "../../../../xpcom/rust/gecko_logger" }
|
||||
rsdparsa_capi = { path = "../../../../dom/media/webrtc/sdp/rsdparsa_capi" }
|
||||
|
|
Загрузка…
Ссылка в новой задаче