mirror of
https://github.com/bitwarden/browser
synced 2026-02-07 04:03:29 +00:00
squash use request hash
This commit is contained in:
@@ -436,6 +436,9 @@ unsafe fn verify_operation_request(
|
||||
tracing::debug!("Verifying request");
|
||||
let request_data =
|
||||
std::slice::from_raw_parts(request.pbEncodedRequest, request.cbEncodedRequest as usize);
|
||||
let request_hash = crypto::hash_sha256(request_data).map_err(|err| {
|
||||
WinWebAuthnError::with_cause(ErrorKind::WindowsInternal, "failed to hash request", err)
|
||||
})?;
|
||||
let signature = std::slice::from_raw_parts(
|
||||
request.pbRequestSignature,
|
||||
request.cbRequestSignature as usize,
|
||||
@@ -449,5 +452,5 @@ unsafe fn verify_operation_request(
|
||||
)
|
||||
})?;
|
||||
tracing::debug!("Verifying signature");
|
||||
op_pub_key.verify_signature(request_data, signature)
|
||||
op_pub_key.verify_signature(&request_hash, signature)
|
||||
}
|
||||
|
||||
@@ -90,9 +90,10 @@ pub(super) fn get_user_verification_public_key(
|
||||
|
||||
fn verify_signature(
|
||||
public_key: &SigningKey,
|
||||
data: &[u8],
|
||||
hash: &[u8],
|
||||
signature: &[u8],
|
||||
) -> Result<(), windows::core::Error> {
|
||||
// Verify the signature over the hash of dataBuffer using the hKey
|
||||
unsafe {
|
||||
tracing::debug!("Getting provider");
|
||||
// Get the provider
|
||||
@@ -115,8 +116,41 @@ fn verify_signature(
|
||||
)?;
|
||||
let key_handle = key_handle.assume_init();
|
||||
|
||||
// Verify the signature over the hash of dataBuffer using the hKey
|
||||
tracing::debug!("Trying to read public key slice as key blob");
|
||||
let public_key = public_key.as_ref();
|
||||
if public_key.len() < size_of::<BCRYPT_KEY_BLOB>() {
|
||||
return Err(windows::core::Error::from_hresult(E_INVALIDARG));
|
||||
}
|
||||
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 {
|
||||
tracing::debug!("Detected RSA key, adding PKCS1 padding");
|
||||
let padding_info = BCRYPT_PKCS1_PADDING_INFO {
|
||||
pszAlgId: BCRYPT_SHA256_ALGORITHM,
|
||||
};
|
||||
(Some(padding_info), NCRYPT_PAD_PKCS1_FLAG)
|
||||
} else {
|
||||
tracing::debug!("Non-RSA key, no PKCS1 padding added");
|
||||
(None, NCRYPT_FLAGS(0))
|
||||
};
|
||||
|
||||
tracing::debug!("Verifying signature");
|
||||
NCryptVerifySignature(
|
||||
key_handle,
|
||||
padding_info
|
||||
.as_ref()
|
||||
.map(|padding: &BCRYPT_PKCS1_PADDING_INFO| std::ptr::from_ref(padding).cast()),
|
||||
hash,
|
||||
signature,
|
||||
cng_flags,
|
||||
)?;
|
||||
tracing::debug!("Verified");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn hash_sha256(data: &[u8]) -> Result<Vec<u8>, windows::core::Error> {
|
||||
unsafe {
|
||||
tracing::debug!("Getting length of hash buffer object");
|
||||
// Get length of SHA-256 buffer
|
||||
let mut len_size_buf = [0; size_of::<u32>()];
|
||||
@@ -174,37 +208,7 @@ fn verify_signature(
|
||||
hash_buffer.set_len(hash_output_len);
|
||||
BCryptFinishHash(hash_handle, hash_buffer.as_mut_slice(), 0).ok()?;
|
||||
tracing::debug!(" Hash: {hash_buffer:?}");
|
||||
|
||||
tracing::debug!("Trying to read public key slice as key blob");
|
||||
let public_key = public_key.as_ref();
|
||||
if public_key.len() < size_of::<BCRYPT_KEY_BLOB>() {
|
||||
return Err(windows::core::Error::from_hresult(E_INVALIDARG));
|
||||
}
|
||||
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 {
|
||||
tracing::debug!("Detected RSA key, adding PKCS1 padding");
|
||||
let padding_info = BCRYPT_PKCS1_PADDING_INFO {
|
||||
pszAlgId: BCRYPT_SHA256_ALGORITHM,
|
||||
};
|
||||
(Some(padding_info), NCRYPT_PAD_PKCS1_FLAG)
|
||||
} else {
|
||||
tracing::debug!("Non-RSA key, no PKCS1 padding added");
|
||||
(None, NCRYPT_FLAGS(0))
|
||||
};
|
||||
|
||||
tracing::debug!("Verifying signature");
|
||||
NCryptVerifySignature(
|
||||
key_handle,
|
||||
padding_info
|
||||
.as_ref()
|
||||
.map(|padding: &BCRYPT_PKCS1_PADDING_INFO| std::ptr::from_ref(padding).cast()),
|
||||
hash_buffer.as_slice(),
|
||||
signature,
|
||||
cng_flags,
|
||||
)?;
|
||||
tracing::debug!("Verified");
|
||||
Ok(())
|
||||
Ok(hash_buffer)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ use windows::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
plugin::crypto,
|
||||
types::UserId,
|
||||
util::{webauthn_call, WindowsString},
|
||||
CredentialId, ErrorKind, WinWebAuthnError,
|
||||
@@ -391,6 +392,8 @@ pub struct PluginMakeCredentialRequest {
|
||||
pub window_handle: HWND,
|
||||
pub transaction_id: GUID,
|
||||
pub request_signature: Vec<u8>,
|
||||
/// SHA-256 hash of the request.
|
||||
pub request_hash: Vec<u8>,
|
||||
}
|
||||
|
||||
impl PluginMakeCredentialRequest {
|
||||
@@ -483,6 +486,17 @@ impl TryFrom<NonNull<WEBAUTHN_PLUGIN_OPERATION_REQUEST>> for PluginMakeCredentia
|
||||
"Unknown plugin operation request type",
|
||||
));
|
||||
}
|
||||
let request_slice = std::slice::from_raw_parts(
|
||||
request.pbEncodedRequest,
|
||||
request.cbEncodedRequest as usize,
|
||||
);
|
||||
let request_hash = crypto::hash_sha256(request_slice).map_err(|err| {
|
||||
WinWebAuthnError::with_cause(
|
||||
ErrorKind::WindowsInternal,
|
||||
"failed to hash request",
|
||||
err,
|
||||
)
|
||||
})?;
|
||||
let mut registration_request = MaybeUninit::uninit();
|
||||
webauthn_decode_make_credential_request(
|
||||
request.cbEncodedRequest,
|
||||
@@ -508,6 +522,7 @@ impl TryFrom<NonNull<WEBAUTHN_PLUGIN_OPERATION_REQUEST>> for PluginMakeCredentia
|
||||
request.cbEncodedRequest as usize,
|
||||
)
|
||||
.to_vec(),
|
||||
request_hash,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -775,6 +790,7 @@ pub struct PluginGetAssertionRequest {
|
||||
pub window_handle: HWND,
|
||||
pub transaction_id: GUID,
|
||||
pub request_signature: Vec<u8>,
|
||||
pub request_hash: Vec<u8>,
|
||||
}
|
||||
|
||||
impl PluginGetAssertionRequest {
|
||||
@@ -839,6 +855,17 @@ impl TryFrom<NonNull<WEBAUTHN_PLUGIN_OPERATION_REQUEST>> for PluginGetAssertionR
|
||||
"Unknown plugin operation request type",
|
||||
));
|
||||
}
|
||||
let request_slice = std::slice::from_raw_parts(
|
||||
request.pbEncodedRequest,
|
||||
request.cbEncodedRequest as usize,
|
||||
);
|
||||
let request_hash = crypto::hash_sha256(request_slice).map_err(|err| {
|
||||
WinWebAuthnError::with_cause(
|
||||
ErrorKind::WindowsInternal,
|
||||
"failed to hash request",
|
||||
err,
|
||||
)
|
||||
})?;
|
||||
let mut assertion_request: *mut WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST =
|
||||
std::ptr::null_mut();
|
||||
webauthn_decode_get_assertion_request(
|
||||
@@ -863,6 +890,7 @@ impl TryFrom<NonNull<WEBAUTHN_PLUGIN_OPERATION_REQUEST>> for PluginGetAssertionR
|
||||
request.cbEncodedRequest as usize,
|
||||
)
|
||||
.to_vec(),
|
||||
request_hash,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ pub fn get_assertion(
|
||||
rp_id,
|
||||
allowed_credential_ids
|
||||
);
|
||||
let context = create_context_string(request.transaction_id);
|
||||
let context = create_context_string(request.transaction_id, &request.request_hash);
|
||||
|
||||
// Send assertion request
|
||||
let assertion_request = PasskeyAssertionRequest {
|
||||
|
||||
@@ -92,7 +92,7 @@ pub fn make_credential(
|
||||
.center_position()
|
||||
.unwrap_or((640, 480));
|
||||
|
||||
let context = create_context_string(request.transaction_id);
|
||||
let context = create_context_string(request.transaction_id, &request.request_hash);
|
||||
|
||||
// Create Windows registration request
|
||||
let registration_request = PasskeyRegistrationRequest {
|
||||
|
||||
@@ -49,8 +49,9 @@ impl HwndExt for HWND {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_context_string(transaction_id: GUID) -> String {
|
||||
STANDARD.encode(transaction_id.to_u128().to_le_bytes().to_vec())
|
||||
pub fn create_context_string(transaction_id: GUID, request_hash: &[u8]) -> String {
|
||||
let context = [&transaction_id.to_u128().to_le_bytes(), request_hash].concat();
|
||||
STANDARD.encode(context)
|
||||
}
|
||||
|
||||
pub fn deserialize_b64<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
|
||||
|
||||
Reference in New Issue
Block a user