diff --git a/ykman/_cli/fido.py b/ykman/_cli/fido.py index 129dbf60..434ee146 100755 --- a/ykman/_cli/fido.py +++ b/ykman/_cli/fido.py @@ -37,6 +37,7 @@ ) from fido2.pcsc import CtapPcscDevice from yubikit.management import CAPABILITY +from yubikit.core import TRANSPORT from yubikit.core.fido import FidoConnection from yubikit.core.smartcard import SW from time import sleep @@ -325,7 +326,8 @@ def change_pin(ctx, pin, new_pin, u2f): 6 characters long. """ - is_fips = is_yk4_fips(ctx.obj["info"]) + info = ctx.obj["info"] + is_fips = is_yk4_fips(info) if is_fips and not u2f: raise CliFail( @@ -348,7 +350,13 @@ def change_pin(ctx, pin, new_pin, u2f): raise CliFail("PIN is not supported on this YubiKey.") client_pin = ClientPin(ctap2) min_len = ctap2.info.min_pin_length - max_len = 63 + if ( + info._is_bio + and CAPABILITY.PIV in info.config.enabled_capabilities[TRANSPORT.USB] + ): + max_len = 8 + else: + max_len = 63 def _fail_if_not_valid_pin(pin=None, name="PIN"): if not pin or len(pin) < min_len: @@ -395,7 +403,6 @@ def change_pin(pin, new_pin): raise CliFail(f"Failed to change PIN: SW={e.code:04x}.") def set_pin(new_pin): - _fail_if_not_valid_pin(new_pin) try: client_pin.set_pin(new_pin) except CtapError as e: @@ -541,6 +548,14 @@ def set_min_pin_length(ctx, pin, rp_id, length): if length < min_len: raise CliFail(f"Cannot set a minimum length that is shorter than {min_len}.") + dev_info = ctx.obj["info"] + if ( + dev_info._is_bio + and CAPABILITY.PIV in dev_info.config.enabled_capabilities[TRANSPORT.USB] + and length > 8 + ): + raise CliFail("Cannot set a minimum length that is longer than 8.") + config = _init_config(ctx, pin) if rp_id: ctap2 = ctx.obj.get("ctap2") diff --git a/yubikit/management.py b/yubikit/management.py index fa97adff..7c626878 100644 --- a/yubikit/management.py +++ b/yubikit/management.py @@ -279,6 +279,10 @@ class DeviceInfo: fps_version: Optional[Version] = None stm_version: Optional[Version] = None + @property + def _is_bio(self) -> bool: + return self.form_factor in (FORM_FACTOR.USB_A_BIO, FORM_FACTOR.USB_C_BIO) + def has_transport(self, transport: TRANSPORT) -> bool: return transport in self.supported_capabilities diff --git a/yubikit/support.py b/yubikit/support.py index 75315ba9..7d96b8ad 100644 --- a/yubikit/support.py +++ b/yubikit/support.py @@ -417,7 +417,7 @@ def get_name(info: DeviceInfo, key_type: Optional[YUBIKEY]) -> str: FORM_FACTOR.USB_A_NANO, FORM_FACTOR.USB_C_NANO, ) - is_bio = info.form_factor in (FORM_FACTOR.USB_A_BIO, FORM_FACTOR.USB_C_BIO) + is_bio = info._is_bio is_c = info.form_factor in ( # Does NOT include Ci FORM_FACTOR.USB_C_KEYCHAIN, FORM_FACTOR.USB_C_NANO,