Ejemplo n.º 1
0
class Fido2Controller(object):
    def __init__(self, ctap_device):
        self.ctap = CTAP2(ctap_device)
        self.pin = ClientPin(self.ctap)
        self._info = self.ctap.get_info()
        self._pin = self._info.options["clientPin"]

    @property
    def has_pin(self):
        return self._pin

    def get_resident_credentials(self, pin):
        _credman = CredentialManagement(
            self.ctap,
            self.pin.protocol,
            self.pin.get_pin_token(pin, ClientPin.PERMISSION.CREDENTIAL_MGMT),
        )

        for rp in _credman.enumerate_rps():
            for cred in _credman.enumerate_creds(
                    rp[CredentialManagement.RESULT.RP_ID_HASH]):
                yield ResidentCredential(cred, rp)

    def delete_resident_credential(self, credential_id, pin):
        _credman = CredentialManagement(
            self.ctap,
            self.pin.protocol,
            self.pin.get_pin_token(pin, ClientPin.PERMISSION.CREDENTIAL_MGMT),
        )

        for cred in self.get_resident_credentials(pin):
            if credential_id == cred.credential_id:
                _credman.delete_cred(credential_id)

    def get_pin_retries(self):
        return self.pin.get_pin_retries()

    def set_pin(self, pin):
        self.pin.set_pin(pin)
        self._pin = True

    def change_pin(self, old_pin, new_pin):
        self.pin.change_pin(old_pin, new_pin)

    def reset(self, touch_callback=None):
        if touch_callback:
            touch_timer = Timer(0.500, touch_callback)
            touch_timer.start()
        try:
            self.ctap.reset()
            self._pin = False
        finally:
            if touch_callback:
                touch_timer.cancel()

    @property
    def is_fips(self):
        return False
Ejemplo n.º 2
0
    def test_change_pin(self):
        prot = ClientPin(mock.MagicMock(), PinProtocolV1())
        prot._get_shared_secret = mock.Mock(return_value=({}, SHARED))

        prot.change_pin("1234", "4321")
        prot.ctap.client_pin.assert_called_with(
            1,
            4,
            key_agreement={},
            new_pin_enc=a2b_hex(
                "4280e14aac4fcbf02dd079985f0c0ffc9ea7d5f9c173fd1a4c843826f7590cb3c2d080c6923e2fe6d7a52c31ea1309d3fcca3dedae8a2ef14b6330cafc79339e"  # noqa E501
            ),
            pin_uv_param=a2b_hex("fb97e92f3724d7c85e001d7f93e6490a"),
            pin_hash_enc=a2b_hex("afe8327ce416da8ee3d057589c2ce1a9"),
        )
Ejemplo n.º 3
0
 def fido_change_pin(self, current_pin, new_pin):
     try:
         with self._open_device([FidoConnection]) as conn:
             ctap2 = Ctap2(conn)
             if len(new_pin) < ctap2.info.min_pin_length:
                 return failure('too short')
             client_pin = ClientPin(ctap2)
             client_pin.change_pin(current_pin, new_pin)
             return success()
     except CtapError as e:
         if e.code == CtapError.ERR.INVALID_LENGTH or \
                 e.code == CtapError.ERR.PIN_POLICY_VIOLATION:
             return failure('too long')
         if e.code == CtapError.ERR.PIN_INVALID:
             return failure('wrong pin')
         if e.code == CtapError.ERR.PIN_AUTH_BLOCKED:
             return failure('currently blocked')
         if e.code == CtapError.ERR.PIN_BLOCKED:
             return failure('blocked')
         raise