1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 14:23:32 +00:00

[PM-20451] Refactor Windows PA Types (#14366)

* PM-20451: Rename and organize Windows types

* PM-20451: Add comments
This commit is contained in:
Colton Hurst
2025-04-25 14:42:11 -04:00
committed by GitHub
parent fd0db40f79
commit 24786a08df
3 changed files with 161 additions and 145 deletions

View File

@@ -9,58 +9,14 @@ use windows::Win32::System::Com::*;
use windows::Win32::System::LibraryLoader::*;
use windows_core::*;
mod pluginauthenticator;
mod webauthn;
const AUTHENTICATOR_NAME: &str = "Bitwarden Desktop Authenticator";
//const AAGUID: &str = "d548826e-79b4-db40-a3d8-11116f7e8349";
const CLSID: &str = "0f7dc5d9-69ce-4652-8572-6877fd695062";
const RPID: &str = "bitwarden.com";
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EXPERIMENTAL_WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST {
pub transactionId: GUID,
pub cbRequestSignature: Dword,
pub pbRequestSignature: *mut byte,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_REQUEST {
pub hWnd: HWND,
pub transactionId: GUID,
pub cbRequestSignature: Dword,
pub pbRequestSignature: *mut byte,
pub cbEncodedRequest: Dword,
pub pbEncodedRequest: *mut byte,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE {
pub cbOpSignPubKey: Dword,
pub pbOpSignPubKey: PByte,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_RESPONSE {
pub cbEncodedResponse: Dword,
pub pbEncodedResponse: *mut byte,
}
type Dword = u32;
type Byte = u8;
type byte = u8;
pub type PByte = *mut Byte;
type EXPERIMENTAL_PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST =
*const EXPERIMENTAL_WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST;
pub type EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST =
*const EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_REQUEST;
pub type EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE =
*mut EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_RESPONSE;
pub type EXPERIMENTAL_PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE =
*mut EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE;
/// Handles initialization and registration for the Bitwarden desktop app as a
/// plugin authenticator with Windows.
/// For now, also adds the authenticator
@@ -109,7 +65,8 @@ fn initialize_com_library() -> std::result::Result<(), String> {
/// Registers the Bitwarden Plugin Authenticator COM library with Windows.
fn register_com_library() -> std::result::Result<(), String> {
static FACTORY: windows_core::StaticComObject<Factory> = Factory().into_static();
static FACTORY: windows_core::StaticComObject<pluginauthenticator::Factory> =
pluginauthenticator::Factory().into_static();
let clsid: *const GUID = &GUID::from_u128(0xa98925d161f640de9327dc418fcb2ff4);
match unsafe {
@@ -146,25 +103,25 @@ fn add_authenticator() -> std::result::Result<(), String> {
let cbor_authenticator_info = "A60182684649444F5F325F30684649444F5F325F310282637072666B686D61632D7365637265740350D548826E79B4DB40A3D811116F7E834904A362726BF5627570F5627576F5098168696E7465726E616C0A81A263616C672664747970656A7075626C69632D6B6579";
let mut authenticator_info_bytes = hex::decode(cbor_authenticator_info).unwrap();
let add_authenticator_options = EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS {
pwszAuthenticatorName: authenticator_name_ptr,
pwszPluginClsId: clsid_ptr,
pwszPluginRpId: relying_party_id_ptr,
pwszLightThemeLogo: ptr::null(), // unused by Windows
pwszDarkThemeLogo: ptr::null(), // unused by Windows
cbAuthenticatorInfo: authenticator_info_bytes.len() as u32,
pbAuthenticatorInfo: authenticator_info_bytes.as_mut_ptr(),
let add_authenticator_options = webauthn::ExperimentalWebAuthnPluginAddAuthenticatorOptions {
authenticator_name: authenticator_name_ptr,
com_clsid: clsid_ptr,
rpid: relying_party_id_ptr,
light_theme_logo: ptr::null(), // unused by Windows
dark_theme_logo: ptr::null(), // unused by Windows
cbor_authenticator_info_byte_count: authenticator_info_bytes.len() as u32,
cbor_authenticator_info: authenticator_info_bytes.as_mut_ptr(),
};
let plugin_signing_public_key_byte_count: Dword = 0;
let plugin_signing_public_key_byte_count: u32 = 0;
let mut plugin_signing_public_key: c_uchar = 0;
let plugin_signing_public_key_ptr: PByte = &mut plugin_signing_public_key;
let plugin_signing_public_key_ptr = &mut plugin_signing_public_key;
let mut add_response = EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE {
cbOpSignPubKey: plugin_signing_public_key_byte_count,
pbOpSignPubKey: plugin_signing_public_key_ptr,
let mut add_response = webauthn::ExperimentalWebAuthnPluginAddAuthenticatorResponse {
plugin_operation_signing_key_byte_count: plugin_signing_public_key_byte_count,
plugin_operation_signing_key: plugin_signing_public_key_ptr,
};
let mut add_response_ptr: *mut EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE =
let mut add_response_ptr: *mut webauthn::ExperimentalWebAuthnPluginAddAuthenticatorResponse =
&mut add_response;
let result = unsafe {
@@ -193,23 +150,10 @@ fn add_authenticator() -> std::result::Result<(), String> {
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS {
pub pwszAuthenticatorName: *const u16,
pub pwszPluginClsId: *const u16,
pub pwszPluginRpId: *const u16,
pub pwszLightThemeLogo: *const u16,
pub pwszDarkThemeLogo: *const u16,
pub cbAuthenticatorInfo: u32,
pub pbAuthenticatorInfo: *const u8,
}
type EXPERIMENTAL_WebAuthNPluginAddAuthenticatorFnDeclaration = unsafe extern "cdecl" fn(
pPluginAddAuthenticatorOptions: *const EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS,
ppPluginAddAuthenticatorResponse: *mut EXPERIMENTAL_PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE,
)
-> HRESULT;
pPluginAddAuthenticatorOptions: *const webauthn::ExperimentalWebAuthnPluginAddAuthenticatorOptions,
ppPluginAddAuthenticatorResponse: *mut *mut webauthn::ExperimentalWebAuthnPluginAddAuthenticatorResponse,
) -> HRESULT;
unsafe fn delay_load<T>(library: PCSTR, function: PCSTR) -> Option<T> {
let library = LoadLibraryExA(library, None, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
@@ -228,70 +172,3 @@ unsafe fn delay_load<T>(library: PCSTR, function: PCSTR) -> Option<T> {
None
}
#[interface("e6466e9a-b2f3-47c5-b88d-89bc14a8d998")]
unsafe trait EXPERIMENTAL_IPluginAuthenticator: IUnknown {
fn EXPERIMENTAL_PluginMakeCredential(
&self,
request: EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST,
response: *mut EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE,
) -> HRESULT;
fn EXPERIMENTAL_PluginGetAssertion(
&self,
request: EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST,
response: *mut EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE,
) -> HRESULT;
fn EXPERIMENTAL_PluginCancelOperation(
&self,
request: EXPERIMENTAL_PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST,
) -> HRESULT;
}
#[implement(EXPERIMENTAL_IPluginAuthenticator)]
struct PACOMObject;
impl EXPERIMENTAL_IPluginAuthenticator_Impl for PACOMObject_Impl {
unsafe fn EXPERIMENTAL_PluginMakeCredential(
&self,
_request: EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST,
_response: *mut EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE,
) -> HRESULT {
HRESULT(0)
}
unsafe fn EXPERIMENTAL_PluginGetAssertion(
&self,
_request: EXPERIMENTAL_PCWEBAUTHN_PLUGIN_OPERATION_REQUEST,
_response: *mut EXPERIMENTAL_PWEBAUTHN_PLUGIN_OPERATION_RESPONSE,
) -> HRESULT {
HRESULT(0)
}
unsafe fn EXPERIMENTAL_PluginCancelOperation(
&self,
_request: EXPERIMENTAL_PCWEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST,
) -> HRESULT {
HRESULT(0)
}
}
#[implement(IClassFactory)]
struct Factory();
impl IClassFactory_Impl for Factory_Impl {
fn CreateInstance(
&self,
outer: Ref<IUnknown>,
iid: *const GUID,
object: *mut *mut core::ffi::c_void,
) -> Result<()> {
assert!(outer.is_null());
let unknown: IInspectable = PACOMObject.into();
unsafe { unknown.query(iid, object).ok() }
}
fn LockServer(&self, lock: BOOL) -> Result<()> {
assert!(lock.as_bool());
Ok(())
}
}

View File

@@ -0,0 +1,110 @@
/*
This file exposes the functions and types defined here: https://github.com/microsoft/webauthn/blob/master/experimental/pluginauthenticator.h
*/
use windows::Win32::System::Com::*;
use windows_core::*;
/// Used when creating and asserting credentials.
/// Header File Name: _EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_REQUEST
/// Header File Usage: EXPERIMENTAL_PluginMakeCredential()
/// EXPERIMENTAL_PluginGetAssertion()
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ExperimentalWebAuthnPluginOperationRequest {
pub window_handle: windows::Win32::Foundation::HWND,
pub transaction_id: windows_core::GUID,
pub request_signature_byte_count: u32,
pub request_signature_pointer: *mut u8,
pub encoded_request_byte_count: u32,
pub encoded_request_pointer: *mut u8,
}
/// Used as a response when creating and asserting credentials.
/// Header File Name: _EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_RESPONSE
/// Header File Usage: EXPERIMENTAL_PluginMakeCredential()
/// EXPERIMENTAL_PluginGetAssertion()
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ExperimentalWebAuthnPluginOperationResponse {
pub encoded_response_byte_count: u32,
pub encoded_response_pointer: *mut u8,
}
/// Used to cancel an operation.
/// Header File Name: _EXPERIMENTAL_WEBAUTHN_PLUGIN_CANCEL_OPERATION_REQUEST
/// Header File Usage: EXPERIMENTAL_PluginCancelOperation()
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ExperimentalWebAuthnPluginCancelOperationRequest {
pub transaction_id: windows_core::GUID,
pub request_signature_byte_count: u32,
pub request_signature_pointer: *mut u8,
}
#[interface("e6466e9a-b2f3-47c5-b88d-89bc14a8d998")]
pub unsafe trait EXPERIMENTAL_IPluginAuthenticator: IUnknown {
fn EXPERIMENTAL_PluginMakeCredential(
&self,
request: *const ExperimentalWebAuthnPluginOperationRequest,
response: *mut ExperimentalWebAuthnPluginOperationResponse,
) -> HRESULT;
fn EXPERIMENTAL_PluginGetAssertion(
&self,
request: *const ExperimentalWebAuthnPluginOperationRequest,
response: *mut ExperimentalWebAuthnPluginOperationResponse,
) -> HRESULT;
fn EXPERIMENTAL_PluginCancelOperation(
&self,
request: *const ExperimentalWebAuthnPluginCancelOperationRequest,
) -> HRESULT;
}
#[implement(EXPERIMENTAL_IPluginAuthenticator)]
pub struct PluginAuthenticatorComObject;
#[implement(IClassFactory)]
pub struct Factory();
impl EXPERIMENTAL_IPluginAuthenticator_Impl for PluginAuthenticatorComObject_Impl {
unsafe fn EXPERIMENTAL_PluginMakeCredential(
&self,
_request: *const ExperimentalWebAuthnPluginOperationRequest,
_response: *mut ExperimentalWebAuthnPluginOperationResponse,
) -> HRESULT {
HRESULT(0)
}
unsafe fn EXPERIMENTAL_PluginGetAssertion(
&self,
_request: *const ExperimentalWebAuthnPluginOperationRequest,
_response: *mut ExperimentalWebAuthnPluginOperationResponse,
) -> HRESULT {
HRESULT(0)
}
unsafe fn EXPERIMENTAL_PluginCancelOperation(
&self,
_request: *const ExperimentalWebAuthnPluginCancelOperationRequest,
) -> HRESULT {
HRESULT(0)
}
}
impl IClassFactory_Impl for Factory_Impl {
fn CreateInstance(
&self,
outer: Ref<IUnknown>,
iid: *const GUID,
object: *mut *mut core::ffi::c_void,
) -> Result<()> {
assert!(outer.is_null());
let unknown: IInspectable = PluginAuthenticatorComObject.into();
unsafe { unknown.query(iid, object).ok() }
}
fn LockServer(&self, lock: BOOL) -> Result<()> {
assert!(lock.as_bool());
Ok(())
}
}

View File

@@ -0,0 +1,29 @@
/*
This file exposes the functions and types defined here: https://github.com/microsoft/webauthn/blob/master/experimental/webauthn.h
*/
/// Used when adding a Windows plugin authenticator.
/// Header File Name: _EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS
/// Header File Usage: EXPERIMENTAL_WebAuthNPluginAddAuthenticator()
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ExperimentalWebAuthnPluginAddAuthenticatorOptions {
pub authenticator_name: *const u16,
pub com_clsid: *const u16,
pub rpid: *const u16,
pub light_theme_logo: *const u16,
pub dark_theme_logo: *const u16,
pub cbor_authenticator_info_byte_count: u32,
pub cbor_authenticator_info: *const u8,
}
/// Used as a response type when adding a Windows plugin authenticator.
/// Header File Name: _EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE
/// Header File Usage: EXPERIMENTAL_WebAuthNPluginAddAuthenticator()
/// EXPERIMENTAL_WebAuthNPluginFreeAddAuthenticatorResponse()
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct ExperimentalWebAuthnPluginAddAuthenticatorResponse {
pub plugin_operation_signing_key_byte_count: u32,
pub plugin_operation_signing_key: *mut u8,
}