mirror of
https://github.com/bitwarden/browser
synced 2026-02-21 11:54:02 +00:00
Add documentation to webauthn.dll functions
This commit is contained in:
@@ -20,21 +20,51 @@ use windows::{
|
||||
|
||||
use crate::{util::webauthn_call, ErrorKind, WinWebAuthnError};
|
||||
|
||||
webauthn_call!("WebAuthNPluginGetUserVerificationPublicKey" as fn webauthn_plugin_get_user_verification_public_key(
|
||||
rclsid: *const GUID,
|
||||
pcbPublicKey: *mut u32,
|
||||
ppbPublicKey: *mut *mut u8) -> HRESULT); // Free using WebAuthNPluginFreePublicKeyResponse
|
||||
webauthn_call!("WebAuthNPluginGetUserVerificationPublicKey" as
|
||||
/// Retrieve the public key used to verify user verification responses from the OS.
|
||||
///
|
||||
/// Returns [S_OK](windows::Win32::Foundation::S_OK) on success.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `rclsid`: The CLSID corresponding to this plugin's COM server.
|
||||
/// - `pcbPublicKey`: A pointer to an unsigned integer, which will be filled in with the length of the buffer at `ppbPublicKey`.
|
||||
/// - `ppbPublicKey`: A pointer to a [BCRYPT_PUBLIC_KEY_BLOB], which will be written to on success.
|
||||
/// On success, this must be freed by a call to [webauthn_plugin_free_public_key_response].
|
||||
fn webauthn_plugin_get_user_verification_public_key(
|
||||
rclsid: *const GUID,
|
||||
pcbPublicKey: *mut u32,
|
||||
ppbPublicKey: *mut *mut u8
|
||||
) -> HRESULT); // Free using WebAuthNPluginFreePublicKeyResponse
|
||||
|
||||
webauthn_call!("WebAuthNPluginGetOperationSigningPublicKey" as fn webauthn_plugin_get_operation_signing_public_key(
|
||||
rclsid: *const GUID,
|
||||
pcbOpSignPubKey: *mut u32,
|
||||
ppbOpSignPubKey: *mut *mut u8
|
||||
) -> HRESULT); // Free using WebAuthNPluginFreePublicKeyResponse
|
||||
webauthn_call!("WebAuthNPluginGetOperationSigningPublicKey" as
|
||||
/// Retrieve the public key used to verify plugin operation reqeusts from the OS.
|
||||
///
|
||||
/// Returns [S_OK](windows::Win32::Foundation::S_OK) on success.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `rclsid`: The CLSID corresponding to this plugin's COM server.
|
||||
/// - `pcbOpSignPubKey`: A pointer to an unsigned integer, which will be filled in with the length of the buffer at `ppbOpSignPubKey`.
|
||||
/// - `ppbOpSignPubKey`: An indirect pointer to a [BCRYPT_PUBLIC_KEY_BLOB], which will be written to on success.
|
||||
/// On success, this must be freed by a call to [webauthn_plugin_free_public_key_response].
|
||||
fn webauthn_plugin_get_operation_signing_public_key(
|
||||
rclsid: *const GUID,
|
||||
pcbOpSignPubKey: *mut u32,
|
||||
ppbOpSignPubKey: *mut *mut u8
|
||||
) -> HRESULT); // Free using WebAuthNPluginFreePublicKeyResponse
|
||||
|
||||
webauthn_call!("WebAuthNPluginFreePublicKeyResponse" as fn webauthn_plugin_free_public_key_response(
|
||||
webauthn_call!("WebAuthNPluginFreePublicKeyResponse" as
|
||||
/// Free public key memory retrieved from the OS.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `pbOpSignPubKey`: A pointer to a [BCRYPT_PUBLIC_KEY_BLOB] retrieved from a method in this library.
|
||||
fn webauthn_plugin_free_public_key_response(
|
||||
pbOpSignPubKey: *mut u8
|
||||
) -> ());
|
||||
|
||||
/// Retrieve the public key used to verify plugin operation reqeusts from the OS.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `clsid`: The CLSID corresponding to this plugin's COM server.
|
||||
pub(super) fn get_operation_signing_public_key(
|
||||
clsid: &GUID,
|
||||
) -> Result<SigningKey, WinWebAuthnError> {
|
||||
@@ -66,6 +96,10 @@ pub(super) fn get_operation_signing_public_key(
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the public key used to verify user verification responses from the OS.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `clsid`: The CLSID corresponding to this plugin's COM server.
|
||||
pub(super) fn get_user_verification_public_key(
|
||||
clsid: &GUID,
|
||||
) -> Result<SigningKey, WinWebAuthnError> {
|
||||
@@ -95,6 +129,7 @@ pub(super) fn get_user_verification_public_key(
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify a public key signature over a hash using Windows Crypto APIs.
|
||||
fn verify_signature(
|
||||
public_key: &SigningKey,
|
||||
hash: &[u8],
|
||||
@@ -128,6 +163,18 @@ fn verify_signature(
|
||||
if public_key.len() < size_of::<BCRYPT_KEY_BLOB>() {
|
||||
return Err(windows::core::Error::from_hresult(E_INVALIDARG));
|
||||
}
|
||||
|
||||
// BCRYPT_KEY_BLOB is a base structure for all types of keys used in the BCRYPT API.
|
||||
// Cf. https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/ns-bcrypt-bcrypt_key_blob.
|
||||
//
|
||||
// The first field is a "magic" field that denotes the algorithm (RSA,
|
||||
// P-256, P-384, etc.) and subtype (public, private; RSA also has a
|
||||
// "full private" key that includes the key exponents and coefficients).
|
||||
//
|
||||
// The exact key types which the OS can return from webauthn.dll
|
||||
// operations is not documented, but we have observed at least RSA
|
||||
// public keys being used. For forward compatibility, we'll implement
|
||||
// RSA, P-256, P-384 and P-512.
|
||||
let key_blob: &BCRYPT_KEY_BLOB = &*public_key.as_ptr().cast();
|
||||
tracing::debug!(" got key magic: {}", key_blob.Magic);
|
||||
let (padding_info, cng_flags) = if key_blob.Magic == BCRYPT_RSAPUBLIC_MAGIC.0 {
|
||||
@@ -156,6 +203,7 @@ fn verify_signature(
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate a SHA-256 hash over some data.
|
||||
pub(super) fn hash_sha256(data: &[u8]) -> Result<Vec<u8>, windows::core::Error> {
|
||||
unsafe {
|
||||
// Hash data
|
||||
@@ -256,7 +304,9 @@ impl Drop for BcryptHash {
|
||||
|
||||
/// Signing key for an operation request or user verification response buffer.
|
||||
pub struct SigningKey {
|
||||
/// Length of buffer
|
||||
cbPublicKey: u32,
|
||||
/// Pointer to a [BCRYPT_KEY_BLOB]
|
||||
pbPublicKey: NonNull<u8>,
|
||||
}
|
||||
|
||||
@@ -272,6 +322,7 @@ impl SigningKey {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SigningKey {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
@@ -279,6 +330,7 @@ impl Drop for SigningKey {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for SigningKey {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
// SAFETY: We only support platforms where usize >= 32-bts
|
||||
|
||||
@@ -166,7 +166,9 @@ impl PluginAddAuthenticatorOptions {
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(super) struct WebAuthnPluginAddAuthenticatorResponse {
|
||||
/// Size in bytes of the public key pointed to by `pbOpSignPubKey`.
|
||||
cbOpSignPubKey: u32,
|
||||
/// Pointer to a [BCRYPT_KEY_BLOB](windows::Win32::Security::Cryptography::BCRYPT_KEY_BLOB).
|
||||
pbOpSignPubKey: *mut u8,
|
||||
}
|
||||
|
||||
@@ -217,14 +219,27 @@ impl Drop for PluginAddAuthenticatorResponse {
|
||||
}
|
||||
|
||||
webauthn_call!("WebAuthNPluginAddAuthenticator" as
|
||||
/// Register authenticator info for a plugin COM server.
|
||||
///
|
||||
/// Returns [S_OK](windows::Win32::Foundation::S_OK) on success.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `pPluginAddAuthenticatorOptions`: Details about the authenticator to set.
|
||||
/// - `ppPluginAddAuthenticatorResponse`:
|
||||
/// An indirect pointer to a [WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE], which will be written to on success.
|
||||
/// If the request succeeds, the data must be freed by a call to [webauthn_plugin_free_add_authenticator_response].
|
||||
fn webauthn_plugin_add_authenticator(
|
||||
pPluginAddAuthenticatorOptions: *const WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS,
|
||||
ppPluginAddAuthenticatorResponse: *mut *mut WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE
|
||||
) -> HRESULT);
|
||||
|
||||
webauthn_call!("WebAuthNPluginFreeAddAuthenticatorResponse" as
|
||||
/// Free memory from a [WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE].
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `pPluginAddAuthenticatorResponse`: An pointer to a [WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE] to be freed.
|
||||
fn webauthn_plugin_free_add_authenticator_response(
|
||||
pPluginAddAuthenticatorOptions: *mut WebAuthnPluginAddAuthenticatorResponse
|
||||
pPluginAddAuthenticatorResponse: *mut WebAuthnPluginAddAuthenticatorResponse
|
||||
) -> ());
|
||||
|
||||
// Credential syncing types
|
||||
@@ -271,15 +286,34 @@ pub struct PluginCredentialDetails {
|
||||
pub user_display_name: String,
|
||||
}
|
||||
|
||||
webauthn_call!("WebAuthNPluginAuthenticatorAddCredentials" as fn webauthn_plugin_authenticator_add_credentials(
|
||||
webauthn_call!("WebAuthNPluginAuthenticatorAddCredentials" as
|
||||
/// Add metadata for a list of WebAuthn credentials to the autofill store for
|
||||
/// this plugin authenticator.
|
||||
///
|
||||
/// This will make the credentials available for discovery in Windows Hello
|
||||
/// WebAuthn autofill dialogs.
|
||||
///
|
||||
/// Returns [S_OK](windows::Win32::Foundation::S_OK) on success.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `rclsid`: The CLSID corresponding to this plugin's COM server.
|
||||
/// - `cCredentialDetails`: The number of credentials in the array pointed to by `pCredentialDetails`.
|
||||
/// - `pCredentialDetails`: An array of credential metadata.
|
||||
fn webauthn_plugin_authenticator_add_credentials(
|
||||
rclsid: *const GUID,
|
||||
cCredentialDetails: u32,
|
||||
pCredentialDetails: *const WEBAUTHN_PLUGIN_CREDENTIAL_DETAILS
|
||||
) -> HRESULT);
|
||||
|
||||
webauthn_call!("WebAuthNPluginAuthenticatorRemoveAllCredentials" as fn webauthn_plugin_authenticator_remove_all_credentials(
|
||||
rclsid: *const GUID
|
||||
) -> HRESULT);
|
||||
webauthn_call!("WebAuthNPluginAuthenticatorRemoveAllCredentials" as
|
||||
/// Removes metadata for all credentials currently stored in the autofill store
|
||||
/// for this plugin authenticator.
|
||||
///
|
||||
/// Returns [S_OK](windows::Win32::Foundation::S_OK) on success.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `rclsid`: The CLSID corresponding to this plugin's COM server.
|
||||
fn webauthn_plugin_authenticator_remove_all_credentials(rclsid: *const GUID) -> HRESULT);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
@@ -323,13 +357,34 @@ pub struct PluginUserVerificationResponse {
|
||||
pub signature: Vec<u8>,
|
||||
}
|
||||
|
||||
webauthn_call!("WebAuthNPluginPerformUserVerification" as fn webauthn_plugin_perform_user_verification(
|
||||
webauthn_call!("WebAuthNPluginPerformUserVerification" as
|
||||
/// Request user verification for a WebAuthn operation.
|
||||
///
|
||||
/// The OS will prompt the user for verification, and if the user is
|
||||
/// successfully verified, will write a signature to `ppbResponse`, which must
|
||||
/// be freed by a call to [webauthn_plugin_free_user_verification_response].
|
||||
///
|
||||
/// The signature is over the SHA-256 hash of the original WebAuthn operation request buffer
|
||||
/// corresponding to `pPluginUserVerification.rguidTransactionId`. It can be
|
||||
/// verified using the user verification public key, which can be retrieved
|
||||
/// using
|
||||
/// [webauthn_plugin_get_user_verification_public_key][crate::plugin::crypto::webauthn_plugin_get_user_verification_public_key].
|
||||
///
|
||||
/// This request will block while the user interacts with the dialog.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `pPluginUserVerification`: The user verification prompt and transaction context for the request.
|
||||
/// - `pcbResponse`: Length in bytes of the signature.
|
||||
/// - `ppbResponse`: The signature of the request.
|
||||
fn webauthn_plugin_perform_user_verification(
|
||||
pPluginUserVerification: *const WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST,
|
||||
pcbResponse: *mut u32,
|
||||
ppbResponse: *mut *mut u8
|
||||
) -> HRESULT);
|
||||
|
||||
webauthn_call!("WebAuthNPluginFreeUserVerificationResponse" as fn webauthn_plugin_free_user_verification_response(
|
||||
webauthn_call!("WebAuthNPluginFreeUserVerificationResponse" as
|
||||
/// Free a user verification response received from a call to [webauthn_plugin_perform_user_verification].
|
||||
fn webauthn_plugin_free_user_verification_response(
|
||||
pbResponse: *mut u8
|
||||
) -> ());
|
||||
|
||||
@@ -594,13 +649,32 @@ impl Drop for PluginMakeCredentialRequest {
|
||||
}
|
||||
|
||||
// Windows API function signatures for decoding make credential requests
|
||||
webauthn_call!("WebAuthNDecodeMakeCredentialRequest" as fn webauthn_decode_make_credential_request(
|
||||
webauthn_call!("WebAuthNDecodeMakeCredentialRequest" as
|
||||
/// Decodes a CTAP CBOR `authenticatorMakeCredential` request.
|
||||
///
|
||||
/// On success, a [WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST] will be written to
|
||||
/// `ppMakeCredentialRequest`, which must be freed by a call to
|
||||
/// [webauthn_free_decoded_make_credential_request].
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `pbEncoded`: a COM-allocated buffer pointing to a CTAP CBOR make credential request.
|
||||
/// - `ppMakeCredentialRequest`: An indirect pointer to a [WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST].
|
||||
///
|
||||
/// # Safety
|
||||
/// - `pbEncoded` must have been allocated by Windows COM.
|
||||
/// - `pbEncoded` must be non-null and have the length specified in cbEncoded.
|
||||
fn webauthn_decode_make_credential_request(
|
||||
cbEncoded: u32,
|
||||
pbEncoded: *const u8,
|
||||
ppMakeCredentialRequest: *mut *mut WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST
|
||||
) -> HRESULT);
|
||||
|
||||
webauthn_call!("WebAuthNFreeDecodedMakeCredentialRequest" as fn webauthn_free_decoded_make_credential_request(
|
||||
webauthn_call!("WebAuthNFreeDecodedMakeCredentialRequest" as
|
||||
/// Frees a decoded make credential request from [webauthn_free_decoded_make_credential_request].
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `pMakeCredentialRequest`: An pointer to a [WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST] to be freed.
|
||||
fn webauthn_free_decoded_make_credential_request(
|
||||
pMakeCredentialRequest: *mut WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST
|
||||
) -> ());
|
||||
|
||||
@@ -823,10 +897,20 @@ impl TryFrom<PluginMakeCredentialResponse> for WEBAUTHN_CREDENTIAL_ATTESTATION {
|
||||
}
|
||||
}
|
||||
|
||||
webauthn_call!("WebAuthNEncodeMakeCredentialResponse" as fn webauthn_encode_make_credential_response(
|
||||
cbEncoded: *const WEBAUTHN_CREDENTIAL_ATTESTATION,
|
||||
pbEncoded: *mut u32,
|
||||
response_bytes: *mut *mut u8
|
||||
webauthn_call!("WebAuthNEncodeMakeCredentialResponse" as
|
||||
/// Encode a credential attestation response to a COM-allocated byte buffer
|
||||
/// containing a CTAP CBOR `authenticatorMakeCredential` response structure.
|
||||
///
|
||||
/// Returns [S_OK](windows::Win32::Foundation::S_OK) on success.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `pCredentialAttestation`: A pointer to [WEBAUTHN_CREDENTIAL_ATTESTATION] to encode.
|
||||
/// - `pcbResp`: A pointer to a u32, which will be filled with the length of the response buffer.
|
||||
/// - `ppbResponse`: An indirect pointer to a byte buffer, which will be written to on succces.
|
||||
fn webauthn_encode_make_credential_response(
|
||||
pCredentialAttestation: *const WEBAUTHN_CREDENTIAL_ATTESTATION,
|
||||
pcbResp: *mut u32,
|
||||
ppbResponse: *mut *mut u8
|
||||
) -> HRESULT);
|
||||
|
||||
// GetAssertion types
|
||||
@@ -1044,13 +1128,32 @@ impl Drop for PluginGetAssertionRequest {
|
||||
}
|
||||
|
||||
// Windows API function signatures for decoding get assertion requests
|
||||
webauthn_call!("WebAuthNDecodeGetAssertionRequest" as fn webauthn_decode_get_assertion_request(
|
||||
webauthn_call!("WebAuthNDecodeGetAssertionRequest" as
|
||||
/// Decodes a CTAP GetAssertion request.
|
||||
///
|
||||
/// On success, a [WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST] will be written to
|
||||
/// `ppGetAssertionRequest`, which must be freed by a call to
|
||||
/// [webauthn_free_decoded_get_assertion_request].
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `pbEncoded`: a COM-allocated buffer pointing to a CTAP CBOR get assertion request.
|
||||
/// - `ppGetAssertionRequest`: An indirect pointer to a [WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST].
|
||||
///
|
||||
/// # Safety
|
||||
/// - `pbEncoded` must have been allocated by Windows COM.
|
||||
/// - `pbEncoded` must be non-null and have the length specified in cbEncoded.
|
||||
fn webauthn_decode_get_assertion_request(
|
||||
cbEncoded: u32,
|
||||
pbEncoded: *const u8,
|
||||
ppGetAssertionRequest: *mut *mut WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST
|
||||
) -> HRESULT);
|
||||
|
||||
webauthn_call!("WebAuthNFreeDecodedGetAssertionRequest" as fn webauthn_free_decoded_get_assertion_request(
|
||||
webauthn_call!("WebAuthNFreeDecodedGetAssertionRequest" as
|
||||
/// Frees a decoded get assertion request from [webauthn_free_decoded_get_assertion_request].
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `pGetAssertionRequest`: An pointer to a [WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST] to be freed.
|
||||
fn webauthn_free_decoded_get_assertion_request(
|
||||
pGetAssertionRequest: *mut WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST
|
||||
) -> ());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user