From 88030114021e873745b058764fc023a1f1ea22e7 Mon Sep 17 00:00:00 2001 From: Dain Nilsson Date: Tue, 3 Sep 2024 11:41:54 +0200 Subject: [PATCH] WinAPI: Add Enterprise Attestation --- fido2/client.py | 33 ++++++++++++++++++++++++++++----- fido2/win_api.py | 11 ++++++----- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/fido2/client.py b/fido2/client.py index f7f60d6..b921abd 100644 --- a/fido2/client.py +++ b/fido2/client.py @@ -866,7 +866,8 @@ def get_assertion( WinAPI, WebAuthNAuthenticatorAttachment, WebAuthNUserVerificationRequirement, - WebAuthNAttestationConvoyancePreference, + WebAuthNAttestationConveyancePreference, + WebAuthNEnterpriseAttestation, ) except Exception: # nosec # TODO: Make this less generic pass @@ -899,6 +900,9 @@ def __init__( versions=["U2F_V2", "FIDO_2_0"], extensions=[], aaguid=Aaguid.NONE ) + # TODO: Decide how to configure this list. + self._enterprise_rpid_list: Optional[Sequence[str]] = None + @staticmethod def is_available() -> bool: return platform.system().lower() == "windows" and WinAPI.version > 0 @@ -921,6 +925,26 @@ def make_credential(self, options, **kwargs): selection = options.authenticator_selection or AuthenticatorSelectionCriteria() + enterprise_attestation = WebAuthNEnterpriseAttestation.NONE + if options.attestation == AttestationConveyancePreference.ENTERPRISE: + attestation = WebAuthNAttestationConveyancePreference.ANY + if self.info.options.get("ep"): + if self._enterprise_rpid_list is not None: + # Platform facilitated + if options.rp.id in self._enterprise_rpid_list: + enterprise_attestation = ( + WebAuthNEnterpriseAttestation.PLATFORM_MANAGED + ) + else: + # Vendor facilitated + enterprise_attestation = ( + WebAuthNEnterpriseAttestation.VENDOR_FACILITATED + ) + else: + attestation = WebAuthNAttestationConveyancePreference.from_string( + options.attestation or "none" + ) + try: result, extensions = self.api.make_credential( options.rp, @@ -929,18 +953,17 @@ def make_credential(self, options, **kwargs): client_data, options.timeout or 0, selection.resident_key, - WebAuthNAuthenticatorAttachment.from_string( - selection.authenticator_attachment or "any" - ), + attestation, WebAuthNUserVerificationRequirement.from_string( selection.user_verification or "discouraged" ), - WebAuthNAttestationConvoyancePreference.from_string( + WebAuthNAttestationConveyancePreference.from_string( options.attestation or "none" ), options.exclude_credentials, options.extensions, kwargs.get("event"), + enterprise_attestation, ) except OSError as e: raise ClientError.ERR.OTHER_ERROR(e) diff --git a/fido2/win_api.py b/fido2/win_api.py index 82553fd..537b27e 100644 --- a/fido2/win_api.py +++ b/fido2/win_api.py @@ -580,7 +580,7 @@ class WebAuthNMakeCredentialOptions(ctypes.Structure): Authenticators. :param WebAuthNUserVerificationRequirement user_verification_requirement: User Verification Requirement. - :param WebAuthNAttestationConvoyancePreference attestation_convoyence: + :param WebAuthNAttestationConveyancePreference attestation_convoyence: Attestation Conveyance Preference. :param List[Dict[str,Any]] credentials: Credentials used for exclusion. """ @@ -712,7 +712,7 @@ class WebAuthNUserVerificationRequirement(_FromString, IntEnum): @unique -class WebAuthNAttestationConvoyancePreference(_FromString, IntEnum): +class WebAuthNAttestationConveyancePreference(_FromString, IntEnum): """Maps to WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_*. https://github.com/microsoft/webauthn/blob/master/webauthn.h#L340 @@ -975,10 +975,11 @@ def make_credential( resident_key=False, platform_attachment=WebAuthNAuthenticatorAttachment.ANY, user_verification=WebAuthNUserVerificationRequirement.ANY, - attestation=WebAuthNAttestationConvoyancePreference.DIRECT, + attestation=WebAuthNAttestationConveyancePreference.DIRECT, exclude_credentials=None, extensions=None, event=None, + enterprise_attestation=WebAuthNEnterpriseAttestation.NONE, ): """Make credential using Windows WebAuthN API. @@ -993,7 +994,7 @@ def make_credential( Authenticator Attachment, default: any. :param WebAuthNUserVerificationRequirement user_verification: (optional) User Verification Requirement, default: any. - :param WebAuthNAttestationConvoyancePreference attestation: (optional) + :param WebAuthNAttestationConveyancePreference attestation: (optional) Attestation Conveyance Preference, default: direct. :param List[Dict[str,Any]] exclude_credentials: (optional) List of PublicKeyCredentialDescriptor of previously registered credentials. @@ -1063,7 +1064,7 @@ def make_credential( attestation, exclude_credentials or [], ctypes.pointer(t.guid) if event else None, - WebAuthNEnterpriseAttestation.NONE, # TODO + enterprise_attestation, large_blob_support, resident_key == ResidentKeyRequirement.PREFERRED, enable_prf,