From beb27951d773f4834a015ae4fbdec06c31f6a8d8 Mon Sep 17 00:00:00 2001 From: Isaiah Inuwa Date: Fri, 20 Feb 2026 08:18:27 -0600 Subject: [PATCH] Use standard drop instead of mem::forget during attestation response struct conversion. --- .../win_webauthn/src/plugin/types.rs | 207 ++++++++---------- 1 file changed, 95 insertions(+), 112 deletions(-) diff --git a/apps/desktop/desktop_native/win_webauthn/src/plugin/types.rs b/apps/desktop/desktop_native/win_webauthn/src/plugin/types.rs index 8f0c27df519..71e97148886 100644 --- a/apps/desktop/desktop_native/win_webauthn/src/plugin/types.rs +++ b/apps/desktop/desktop_native/win_webauthn/src/plugin/types.rs @@ -768,7 +768,101 @@ pub struct PluginMakeCredentialResponse { impl PluginMakeCredentialResponse { pub fn to_ctap_response(self) -> Result, 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 for WEBAUTHN_CREDENTIAL_ATTESTATION { - type Error = WinWebAuthnError; - - fn try_from(value: PluginMakeCredentialResponse) -> Result { - // 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.