diff --git a/pynitrokey/cli/fido2.py b/pynitrokey/cli/fido2.py index 2e39ef9f..3e381f9a 100644 --- a/pynitrokey/cli/fido2.py +++ b/pynitrokey/cli/fido2.py @@ -411,12 +411,31 @@ def feedkernel(count: int, serial: Optional[str]) -> None: local_print(f"entropy after: 0x{open(entropy_info_file).read().strip()}") +REQUIREMENT_CHOICE = click.Choice(["discouraged", "preferred", "required"]) + + @click.command() @click.option( "--host", help="Relying party's host", default="nitrokeys.dev", show_default=True ) @click.option("--user", help="User ID", default="they", show_default=True) -def make_credential(host: str, user: str) -> None: +@click.option( + "--resident-key", + help="Whether to create a resident key", + type=REQUIREMENT_CHOICE, + default="discouraged", + show_default=True, +) +@click.option( + "--user-verification", + help="Whether to perform user verification (PIN query)", + type=REQUIREMENT_CHOICE, + default="preferred", + show_default=True, +) +def make_credential( + host: str, user: str, resident_key: str, user_verification: str +) -> None: """Generate a credential. Pass `--prompt ""` to output only the `credential_id` as hex. @@ -426,6 +445,8 @@ def make_credential(host: str, user: str) -> None: host=host, user_id=user, output=True, + resident_key=resident_key, + user_verification=user_verification, ) diff --git a/pynitrokey/fido2/client.py b/pynitrokey/fido2/client.py index d068d751..3db8d6bb 100644 --- a/pynitrokey/fido2/client.py +++ b/pynitrokey/fido2/client.py @@ -28,11 +28,14 @@ from fido2.ctap2.pin import ClientPin from fido2.hid import CTAPHID, CtapHidDevice, open_device from fido2.webauthn import ( + AuthenticatorSelectionCriteria, PublicKeyCredentialCreationOptions, PublicKeyCredentialParameters, PublicKeyCredentialRpEntity, PublicKeyCredentialType, PublicKeyCredentialUserEntity, + ResidentKeyRequirement, + UserVerificationRequirement, ) from intelhex import IntelHex @@ -248,6 +251,8 @@ def make_credential( self, host: str = "nitrokeys.dev", user_id: str = "they", + resident_key: str = "", + user_verification: str = "", output: bool = True, fingerprint_only: bool = False, ) -> str: @@ -272,6 +277,10 @@ def make_credential( ), ], extensions={"hmacCreateSecret": True}, + authenticator_selection=AuthenticatorSelectionCriteria( + resident_key=ResidentKeyRequirement(resident_key), + user_verification=UserVerificationRequirement(user_verification), + ), ) self.client.origin = f"https://{host}" attestation_object = self.client.make_credential(options).attestation_object