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:
John Schanck 2023-02-10 00:15:43 +00:00
Родитель ed2a0660f9
Коммит 7ec1da7ce5
38 изменённых файлов: 187 добавлений и 148 удалений

4
Cargo.lock сгенерированный
Просмотреть файл

@ -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]]

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

54
third_party/rust/authenticator/Cargo.lock сгенерированный поставляемый
Просмотреть файл

@ -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",

2
third_party/rust/authenticator/Cargo.toml поставляемый
Просмотреть файл

@ -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,
};

15
third_party/rust/authenticator/src/errors.rs поставляемый
Просмотреть файл

@ -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" }