1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-01 09:13:54 +00:00
This commit is contained in:
Bernd Schoolmann
2025-11-17 02:39:45 +01:00
parent 2ac1c694e0
commit ae534a3128
5 changed files with 116 additions and 778 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -11,12 +11,13 @@ ctap-hid-fido2 = "3.5.1"
pinentry = "0.5.0"
home = "=0.5.0"
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
serde_json = { workspace = true }
secrecy = "0.8.0"
hex.workspace = true
webauthn-authenticator-rs = { version = "0.5.3", features = ["ctap2", "cable", "usb"] }
hex = { workspace = true }
webauthn-authenticator-rs = { path = "../../../../../webauthn-rs/webauthn-authenticator-rs/", features = ["win10"] }
tokio.workspace = true
futures-util = "0.3.31"
webauthn-rs-proto = "0.5.3"
sha2.workspace = true
sha2 = { workspace = true }
webauthn-rs-proto = { path = "../../../../../webauthn-rs/webauthn-rs-proto" }
base64urlsafedata = { path= "../../../../../webauthn-rs/base64urlsafedata" }

View File

@@ -3,11 +3,13 @@ mod ctap_hid_fido2;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use ctap_hid_fido2::*;
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
mod unimplemented;
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
use unimplemented::*;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(target_os = "windows")]
use windows::*;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
/// Depending on the platform API, the platform MAY do this for you, or may require you to do it manually.
fn prf_to_hmac(prf_salt: &[u8]) -> [u8; 32] {
use sha2::Digest;
sha2::Sha256::digest(&[b"WebAuthn PRF".as_slice(), &[0], prf_salt].concat()).into()
@@ -31,6 +33,7 @@ pub struct AssertionOptions {
pub prf_eval_second: Option<[u8; 32]>,
}
#[derive(Debug)]
pub struct AuthenticatorAssertionResponse {
pub authenticator_data: Vec<u8>,
pub client_data_json: Vec<u8>,
@@ -38,6 +41,7 @@ pub struct AuthenticatorAssertionResponse {
pub user_handle: Vec<u8>,
}
#[derive(Debug)]
pub struct PublicKeyCredential {
pub authenticator_attachment: String,
pub id: String,
@@ -60,7 +64,13 @@ pub mod fido2_client {
pub fn get(
assertion_options: super::AssertionOptions,
) -> Result<super::PublicKeyCredential, super::Fido2ClientError> {
super::get(assertion_options)
println!("Calling Windows FIDO2 client get()");
// run in new thread
std::thread::spawn(move || {
super::get(assertion_options)
})
.join()
.unwrap()
}
pub fn available() -> bool {

View File

@@ -0,0 +1,81 @@
use webauthn_authenticator_rs::{AuthenticatorBackend, prelude::Url, win10::Win10};
use webauthn_rs_proto::{HmacGetSecretInput, PublicKeyCredentialRequestOptions, RequestAuthenticationExtensions};
use crate::{AssertionOptions, Fido2ClientError, PublicKeyCredential};
pub fn get(options: AssertionOptions) -> Result<PublicKeyCredential, Fido2ClientError> {
let uv = match options.user_verification {
crate::UserVerification::Required => webauthn_rs_proto::UserVerificationPolicy::Required,
crate::UserVerification::Preferred => webauthn_rs_proto::UserVerificationPolicy::Preferred,
crate::UserVerification::Discouraged => webauthn_rs_proto::UserVerificationPolicy::Discouraged_DO_NOT_USE,
};
println!("User verification policy: {:?}", uv);
let opts = PublicKeyCredentialRequestOptions {
challenge: base64urlsafedata::Base64UrlSafeData::from(options.challenge),
timeout: Some(options.timeout as u32),
rp_id: options.rpid,
allow_credentials: vec![],
user_verification: uv,
hints: None,
extensions: Some(RequestAuthenticationExtensions {
hmac_get_secret: Some(HmacGetSecretInput {
output1: base64urlsafedata::Base64UrlSafeData::from(&options.prf_eval_first),
output2: None,
}),
appid: None,
uvm: None,
})
};
println!("Prepared PublicKeyCredentialRequestOptions: {:?}", opts);
let public_key_credential = Win10::default().perform_auth(Url::parse(
"https://vault.usdev.bitwarden.pw",
).unwrap(), opts, 60000)
.map_err(|_e| Fido2ClientError::AssertionError)?;
println!("PublicKeyCredential: {:?}", public_key_credential);
Ok(PublicKeyCredential {
id: public_key_credential.id,
raw_id: public_key_credential.raw_id.to_vec(),
response: crate::AuthenticatorAssertionResponse {
authenticator_data: public_key_credential.response.authenticator_data.to_vec(),
client_data_json: public_key_credential.response.client_data_json.to_vec(),
signature: public_key_credential.response.signature.to_vec(),
user_handle: public_key_credential.response.user_handle.map(|h| h.to_vec()).unwrap_or_default(),
},
prf: public_key_credential.extensions.hmac_get_secret.map(|hmac| {
let mut prf_bytes = [0u8; 32];
prf_bytes.copy_from_slice(&hmac.output1.to_vec().as_slice()[..32]);
prf_bytes
}),
authenticator_attachment: "cross-platform".to_string(),
r#type: public_key_credential.type_,
})
}
pub fn available() -> bool {
false
}
#[cfg(test)]
mod tests {
use crate::AssertionOptions;
use super::*;
#[test]
fn test_get() {
let options =
AssertionOptions {
challenge: vec![0u8; 32],
timeout: 0,
rpid: "vault.usdev.bitwarden.pw".to_string(),
user_verification: crate::UserVerification::Required,
allow_credentials: vec![],
prf_eval_first: [0u8; 32],
prf_eval_second: None,
};
let result = get(options);
println!("{:?}", result.unwrap());
}
}

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,