1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-31 00:33:33 +00:00
This commit is contained in:
Bernd Schoolmann
2025-11-17 11:52:17 +01:00
parent 2ac1c694e0
commit bc8bcf6279
4 changed files with 41 additions and 14 deletions

View File

@@ -5193,6 +5193,7 @@ dependencies = [
"uuid",
"webauthn-rs-core",
"webauthn-rs-proto",
"windows 0.41.0",
]
[[package]]

View File

@@ -14,7 +14,7 @@ serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
secrecy = "0.8.0"
hex.workspace = true
webauthn-authenticator-rs = { version = "0.5.3", features = ["ctap2", "cable", "usb"] }
webauthn-authenticator-rs = { version = "0.5.3", features = ["ctap2", "cable", "usb", "win10"] }
tokio.workspace = true
futures-util = "0.3.31"
webauthn-rs-proto = "0.5.3"

View File

@@ -1,7 +1,6 @@
use base64::{prelude::BASE64_URL_SAFE_NO_PAD, Engine};
use ctap_hid_fido2::{
fidokey::{AssertionExtension, GetAssertionArgsBuilder},
Cfg, FidoKeyHidFactory,
Cfg, FidoKeyHid, FidoKeyHidFactory, fidokey::{AssertionExtension, GetAssertionArgsBuilder, get_assertion::get_assertion_params::GetAssertionArgs}
};
use pinentry::PassphraseInput;
use secrecy::ExposeSecret;
@@ -28,6 +27,24 @@ pub fn available() -> bool {
true
}
fn make_assertion(options: AssertionOptions, client_data_json: String, credential: Option<&[u8]>, pin: Option<String>) -> Result<GetAssertionArgs, Fido2ClientError> {
let mut get_assertion_args =
GetAssertionArgsBuilder::new(options.rpid.as_str(), client_data_json.as_bytes())
.extensions(&[AssertionExtension::HmacSecret(Some(prf_to_hmac(
&options.prf_eval_first,
)))]);
if pin.is_some() {
get_assertion_args = get_assertion_args.pin(pin.as_ref().unwrap());
}
if let Some(cred) = credential {
get_assertion_args = get_assertion_args.credential_id(cred);
}
Ok(get_assertion_args.build())
}
pub fn get(options: AssertionOptions) -> Result<PublicKeyCredential, Fido2ClientError> {
let device = FidoKeyHidFactory::create(&Cfg::init()).map_err(|_| Fido2ClientError::NoDevice)?;
@@ -37,24 +54,32 @@ pub fn get(options: AssertionOptions) -> Result<PublicKeyCredential, Fido2Client
options.rpid
);
let mut get_assertion_args =
GetAssertionArgsBuilder::new(options.rpid.as_str(), client_data_json.as_bytes())
.extensions(&[AssertionExtension::HmacSecret(Some(prf_to_hmac(
&options.prf_eval_first,
)))]);
let mut pin: Option<String> = None;
let pin: Option<String>;
if options.user_verification == crate::UserVerification::Required
|| options.user_verification == crate::UserVerification::Preferred
{
pin = Some(get_pin().ok_or(Fido2ClientError::WrongPin)?);
get_assertion_args = get_assertion_args.pin(pin.as_ref().unwrap());
}
let assertions = device
.get_assertion_with_args(&get_assertion_args.build())
.map_err(|_e| Fido2ClientError::AssertionError)?;
let assertion = assertions.get(0).ok_or(Fido2ClientError::AssertionError)?;
.map_err(|_e| {
Fido2ClientError::AssertionError
})?;
let assertion = if assertions.len() > 1 {
let first_assertion = &assertions[0];
let mut get_assertion_args = get_assertion_args.credential_id(&first_assertion.credential_id);
let assertions = device
.get_assertion_with_args(&get_assertion_args.build())
.map_err(|_e| {
Fido2ClientError::AssertionError
})?;
assertions.get(0).ok_or(Fido2ClientError::AssertionError)?
} else {
assertions.get(0).ok_or(Fido2ClientError::AssertionError)?
};
let prf_extension = assertion
.extensions
@@ -93,7 +118,7 @@ mod tests {
get(AssertionOptions {
challenge: vec![],
timeout: 0,
rpid: "example.com".to_string(),
rpid: "vault.usdev.bitwarden.pw".to_string(),
user_verification: crate::UserVerification::Required,
allow_credentials: vec![],
prf_eval_first: [0u8; 32],

View File

@@ -129,6 +129,7 @@ import { UserVerificationApiService } from "@bitwarden/common/auth/services/user
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
import { WebAuthnLoginApiService } from "@bitwarden/common/auth/services/webauthn-login/webauthn-login-api.service";
import { WebAuthnLoginPrfKeyService } from "@bitwarden/common/auth/services/webauthn-login/webauthn-login-prf-key.service";
import { DefaultTwoFactorApiService, TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
import {
AutofillSettingsService,
AutofillSettingsServiceAbstraction,