1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-21 20:04:02 +00:00

Use standard drop instead of mem::forget during attestation response struct conversion.

This commit is contained in:
Isaiah Inuwa
2026-02-20 08:18:27 -06:00
parent 713110f20a
commit beb27951d7

View File

@@ -768,7 +768,101 @@ pub struct PluginMakeCredentialResponse {
impl PluginMakeCredentialResponse {
pub fn to_ctap_response(self) -> Result<Vec<u8>, WinWebAuthnError> {
let attestation = self.try_into()?;
// Convert format type to UTF-16
let format_type_utf16 = self.format_type.to_utf16();
let pwszFormatType = format_type_utf16.as_ptr();
// Get authenticator data pointer and length
let pbAuthenticatorData = self.authenticator_data.as_ptr();
let cbAuthenticatorData = self.authenticator_data.len() as u32;
// Get optional attestation statement pointer and length
let (pbAttestation, cbAttestation) = match self.attestation_statement.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
// Get optional attestation object pointer and length
let (pbAttestationObject, cbAttestationObject) = match self.attestation_object.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
// Get optional credential ID pointer and length
let (pbCredentialId, cbCredentialId) = match self.credential_id.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
// Convert extensions (TODO: implement proper extension conversion)
let extensions = WEBAUTHN_EXTENSIONS {
cExtensions: 0,
pExtensions: std::ptr::null(),
};
// Convert used transport enum to bitmask
let dwUsedTransport = self.used_transport as u32;
// Get optional unsigned extension outputs pointer and length
let (pbUnsignedExtensionOutputs, cbUnsignedExtensionOutputs) =
match self.unsigned_extension_outputs.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
// Convert optional HMAC secret (TODO: implement proper conversion)
let pHmacSecret = std::ptr::null();
// Convert optional transports to bitmask
let dwTransports = self
.transports
.as_ref()
.map_or(0, |t| t.iter().map(|transport| *transport as u32).sum());
// Get optional client data JSON pointer and length
let (pbClientDataJSON, cbClientDataJSON) = match self.client_data_json.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
// Get optional registration response JSON pointer and length
let (pbRegistrationResponseJSON, cbRegistrationResponseJSON) =
match self.registration_response_json.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
let attestation = WEBAUTHN_CREDENTIAL_ATTESTATION {
// Use version 8 to include all fields
dwVersion: 8,
pwszFormatType,
cbAuthenticatorData,
pbAuthenticatorData,
cbAttestation,
pbAttestation,
// TODO: Support decode type. Just using WEBAUTHN_ATTESTATION_DECODE_NONE (0) for now.
dwAttestationDecodeType: 0,
pvAttestationDecode: std::ptr::null(),
cbAttestationObject,
pbAttestationObject,
cbCredentialId,
pbCredentialId,
Extensions: extensions,
dwUsedTransport,
bEpAtt: self.ep_att,
bLargeBlobSupported: self.large_blob_supported,
bResidentKey: self.resident_key,
bPrfEnabled: self.prf_enabled,
cbUnsignedExtensionOutputs,
pbUnsignedExtensionOutputs,
pHmacSecret,
bThirdPartyPayment: self.third_party_payment,
dwTransports,
cbClientDataJSON,
pbClientDataJSON,
cbRegistrationResponseJSON,
pbRegistrationResponseJSON,
};
let mut response_len = 0;
let mut response_ptr = std::ptr::null_mut();
// SAFETY: we construct valid input and check the OS error code before using the returned
@@ -804,117 +898,6 @@ impl PluginMakeCredentialResponse {
}
}
impl TryFrom<PluginMakeCredentialResponse> for WEBAUTHN_CREDENTIAL_ATTESTATION {
type Error = WinWebAuthnError;
fn try_from(value: PluginMakeCredentialResponse) -> Result<Self, Self::Error> {
// Convert format type to UTF-16
let format_type_utf16 = value.format_type.to_utf16();
let pwszFormatType = format_type_utf16.as_ptr();
std::mem::forget(format_type_utf16);
// Get authenticator data pointer and length
let pbAuthenticatorData = value.authenticator_data.as_ptr();
let cbAuthenticatorData = value.authenticator_data.len() as u32;
std::mem::forget(value.authenticator_data);
// Get optional attestation statement pointer and length
let (pbAttestation, cbAttestation) = match value.attestation_statement.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
std::mem::forget(value.attestation_statement);
// Get optional attestation object pointer and length
let (pbAttestationObject, cbAttestationObject) = match value.attestation_object.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
std::mem::forget(value.attestation_object);
// Get optional credential ID pointer and length
let (pbCredentialId, cbCredentialId) = match value.credential_id.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
std::mem::forget(value.credential_id);
// Convert extensions (TODO: implement proper extension conversion)
let extensions = WEBAUTHN_EXTENSIONS {
cExtensions: 0,
pExtensions: std::ptr::null(),
};
// Convert used transport enum to bitmask
let dwUsedTransport = value.used_transport as u32;
// Get optional unsigned extension outputs pointer and length
let (pbUnsignedExtensionOutputs, cbUnsignedExtensionOutputs) =
match value.unsigned_extension_outputs.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
std::mem::forget(value.unsigned_extension_outputs);
// Convert optional HMAC secret (TODO: implement proper conversion)
let pHmacSecret = std::ptr::null();
// Convert optional transports to bitmask
let dwTransports = value
.transports
.as_ref()
.map_or(0, |t| t.iter().map(|transport| *transport as u32).sum());
// Get optional client data JSON pointer and length
let (pbClientDataJSON, cbClientDataJSON) = match value.client_data_json.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
std::mem::forget(value.client_data_json);
// Get optional registration response JSON pointer and length
let (pbRegistrationResponseJSON, cbRegistrationResponseJSON) =
match value.registration_response_json.as_ref() {
Some(data) => (data.as_ptr(), data.len() as u32),
None => (std::ptr::null(), 0),
};
std::mem::forget(value.registration_response_json);
let attestation = WEBAUTHN_CREDENTIAL_ATTESTATION {
// Use version 8 to include all fields
dwVersion: 8,
pwszFormatType,
cbAuthenticatorData,
pbAuthenticatorData,
cbAttestation,
pbAttestation,
// TODO: Support decode type. Just using WEBAUTHN_ATTESTATION_DECODE_NONE (0) for now.
dwAttestationDecodeType: 0,
pvAttestationDecode: std::ptr::null(),
cbAttestationObject,
pbAttestationObject,
cbCredentialId,
pbCredentialId,
Extensions: extensions,
dwUsedTransport,
bEpAtt: value.ep_att,
bLargeBlobSupported: value.large_blob_supported,
bResidentKey: value.resident_key,
bPrfEnabled: value.prf_enabled,
cbUnsignedExtensionOutputs,
pbUnsignedExtensionOutputs,
pHmacSecret,
bThirdPartyPayment: value.third_party_payment,
dwTransports,
cbClientDataJSON,
pbClientDataJSON,
cbRegistrationResponseJSON,
pbRegistrationResponseJSON,
};
Ok(attestation)
}
}
webauthn_call!("WebAuthNEncodeMakeCredentialResponse" as
/// Encode a credential attestation response to a COM-allocated byte buffer
/// containing a CTAP CBOR `authenticatorMakeCredential` response structure.