示例#1
0
    def test_call_keepalive(self):
        dev = mock.Mock()
        hid_dev = CtapHidDevice(None, dev)
        on_keepalive = mock.MagicMock()

        dev.InternalRecv = mock.Mock(side_effect=[
            (0xbb, bytearray([0])),
            (0xbb, bytearray([0])),
            (0xbb, bytearray([0])),
            (0xbb, bytearray([0])),
            (0x81, bytearray(b'done'))
        ])

        self.assertEqual(hid_dev.call(0x01, on_keepalive=on_keepalive), b'done')
        on_keepalive.assert_called_once_with(0)

        dev.InternalRecv.side_effect = [
            (0xbb, bytearray([1])),
            (0xbb, bytearray([0])),
            (0xbb, bytearray([0])),
            (0xbb, bytearray([1])),
            (0xbb, bytearray([1])),
            (0xbb, bytearray([1])),
            (0xbb, bytearray([1])),
            (0xbb, bytearray([0])),
            (0x81, bytearray(b'done'))
        ]
        on_keepalive.reset_mock()
        self.assertEqual(hid_dev.call(0x01, on_keepalive=on_keepalive), b'done')
        self.assertEqual(
            on_keepalive.call_args_list,
            [mock.call(1), mock.call(0), mock.call(1), mock.call(0)]
        )
示例#2
0
    def find_device(self, nfcInterfaceOnly=False):
        dev = None
        self.nfc_interface_only = nfcInterfaceOnly
        if not nfcInterfaceOnly:
            print("--- HID ---")
            print(list(CtapHidDevice.list_devices()))
            dev = next(CtapHidDevice.list_devices(), None)

        else:
            from fido2.pcsc import CtapPcscDevice

            print("--- NFC ---")
            dev = next(MoreRobustPcscDevice.list_devices(), None)

            if dev:
                self.is_nfc = True
                # For ACR1252 readers, with drivers installed
                # https://www.acs.com.hk/en/products/342/acr1252u-usb-nfc-reader-iii-nfc-forum-certified-reader
                # disable auto pps, always use 106kbps
                # dev.control_exchange(SCARD_CTL_CODE(0x3500), b"\xE0\x00\x00\x24\x02\x00\x00")

        if not dev:
            raise RuntimeError("No FIDO device found")
        self.dev = dev
        self.client = Fido2Client(dev, self.origin)
        self.ctap2 = self.client.ctap2
        self.ctap1 = CTAP1(dev)
示例#3
0
 def find_device(self, ):
     print(list(CtapHidDevice.list_devices()))
     dev = next(CtapHidDevice.list_devices(), None)
     if not dev:
         raise RuntimeError('No FIDO device found')
     self.dev = dev
     self.client = Fido2Client(dev, self.origin)
     self.ctap = self.client.ctap2
示例#4
0
 def test_call_error(self):
     dev = mock.Mock()
     hid_dev = CtapHidDevice(None, dev)
     dev.InternalRecv = mock.Mock(return_value=(0xbf, bytearray([7])))
     try:
         hid_dev.call(0x01)
         self.fail('call did not raise exception')
     except CtapError as e:
         self.assertEqual(e.code, 7)
示例#5
0
    def find_device(self, dev=None, solo_serial=None):
        if dev is None:
            devices = list(CtapHidDevice.list_devices())
            if solo_serial is not None:
                devices = [
                    d for d in devices
                    if d.descriptor["serial_number"] == solo_serial
                ]
            if len(devices) > 1:
                raise solo.exceptions.NonUniqueDeviceError
            if len(devices) == 0:
                raise RuntimeError("No FIDO device found")
            dev = devices[0]
        self.dev = dev

        self.ctap1 = CTAP1(dev)
        self.ctap2 = CTAP2(dev)
        try:
            self.client = Fido2Client(dev, self.origin)
        except CtapError:
            print("Not using FIDO2 interface.")
            self.client = None

        if self.exchange == self.exchange_hid:
            self.send_data_hid(CTAPHID.INIT,
                               "\x11\x11\x11\x11\x11\x11\x11\x11")

        return self.dev
示例#6
0
 def get_device(self):
     try:
         devs = list(CtapHidDevice.list_devices())
         assert len(devs) == 1
         return devs[0]
     except Exception:
         self.skipTest('Tests require a single FIDO HID device')
示例#7
0
    def locate_device(self):
        # Locate a device
        devs = list(CtapHidDevice.list_devices())
        if not devs:
            devs = CtapKeyringDevice.list_devices()

        self._clients = [Fido2Client(d, self._okta_org_url) for d in devs]
示例#8
0
    def _discover_devices(communication_queue, abort_event):
        """
        Discover FIDO2 authenticators
        :param communication_queue: Queue to put newly discovered
                authenticator in
        :param abort_event: Event to abort discovery with
        :return:
        """
        discovered = []

        # look for new devices until abort
        while not abort_event.is_set():
            new_devices = []
            for d in hidtransport.hid.Enumerate():
                if hidtransport.HidUsageSelector(d) and \
                        d not in [e.descriptor for e in discovered]:
                    # new device found
                    dev = hidtransport.hid.Open(d['path'])
                    dev = CtapHidDevice(d, hidtransport.UsbHidTransport(dev))
                    new_devices.append(dev)
                    discovered.append(dev)
            # notify main thread
            if new_devices:
                communication_queue.put(
                    (CommunicationObject.DEVICE, new_devices))
            # slow down busy wait
            time.sleep(0.1)

        # on abort put an empty list in the queue to stop the main thread
        # from waiting for results
        communication_queue.put((CommunicationObject.DEVICE, []))
示例#9
0
    def find_device(self, nfcInterfaceOnly=False):
        if self.dev is not None:
            return
        dev = None
        self.nfc_interface_only = nfcInterfaceOnly
        if not nfcInterfaceOnly:
            # print("--- HID ---")
            # print(list(CtapHidDevice.list_devices()))
            dev = next(CtapHidDevice.list_devices(), None)

        if not dev:
            from fido2.pcsc import CtapPcscDevice

            # print("--- NFC ---")
            # print(list(CtapPcscDevice.list_devices()))
            dev = next(CtapPcscDevice.list_devices(), None)
            if dev:
                self.is_nfc = True

        if not dev:
            raise RuntimeError("No FIDO device found")
        self.dev = dev
        self.client = Fido2Client(dev, self.origin)
        self.ctap2 = self.client.ctap2
        self.ctap1 = CTAP1(dev)
示例#10
0
def iterdevs(per_device):
    lock = threading.Lock()
    cancel_ev = threading.Event()
    result = [None]
    ok = [False]

    def go(dev):
        try:
            r = per_device(dev, cancel_ev)
        except ClientError as e:
            if e.code != ClientError.ERR.TIMEOUT:
                raise
        with lock:
            if not ok[0]:
                result[0] = r
                ok[0] = True
                cancel_ev.set()

    threads = []
    for dev in CtapHidDevice.list_devices():
        t = threading.Thread(target=go, args=(dev, ))
        t.start()
        threads.append(t)
    for t in threads:
        t.join()
    if not ok[0]:
        raise FileNotFoundError
    return result[0]
示例#11
0
def u2f_authenticate(authenticateRequests):
    # type: (List[dict]) -> Optional[dict]

    global should_cancel_u2f
    global u2f_response

    if not authenticateRequests:
        return None

    devices = list(CtapHidDevice.list_devices())
    if not devices:
        return None

    to_auth = []
    for i in range(len(devices)):
        u2f_client = CTAP1(devices[i])
        u2f_version = u2f_client.get_version()
        for request in authenticateRequests:
            try:
                version = request['version']
                if version == u2f_version:
                    app_id = request['appId']
                    challenge = request['challenge']
                    key_handle = base64.urlsafe_b64decode(
                        request['keyHandle'] + '==')
                    app_id_hash = sha256(app_id.encode('ascii')).digest()
                    cl_data = {
                        'typ': U2F_TYPE.SIGN,
                        'challenge': challenge,
                        'origin': app_id
                    }
                    client_data = json.dumps(cl_data)
                    try:
                        client_param = sha256(
                            client_data.encode('utf8')).digest()
                        u2f_client.authenticate(client_param,
                                                app_id_hash,
                                                key_handle,
                                                check_only=True)
                    except ApduError as e:
                        if e.code == APDU.USE_NOT_SATISFIED:
                            to_auth.append((u2f_client, client_data,
                                            app_id_hash, key_handle))
            except:
                pass

    if to_auth:
        u2f_thread = threading.Thread(target=thread_function,
                                      args=((to_auth, )))
        u2f_thread.start()
        try:
            get_input_interrupted(
                '\nTouch the flashing U2F device to authenticate or press Enter to resume with the primary two factor authentication...\n'
            )
            should_cancel_u2f = True
            u2f_thread.join()
        except KeyboardInterrupt:
            pass
    return u2f_response
示例#12
0
    def locate_device(self):
        # Locate a device
        devs = list(CtapHidDevice.list_devices())
        if not devs:
            self.ui.info("No FIDO device found")
            raise NoFIDODeviceFoundError

        self._clients = [CTAP1(d) for d in devs]
示例#13
0
    def locate_device(self):
        # Locate a device
        devs = list(CtapHidDevice.list_devices())
        if not devs:
            self.ui.info('No FIDO device found')
            raise NoFIDODeviceFoundError

        self._clients = [Fido2Client(d, self._okta_org_url) for d in devs]
示例#14
0
def okta_mfa_webauthn(conf, s, factor, state_token):
    # type: (Conf, requests.Session, Dict[str, str], str) -> Optional[Dict[str, Any]]
    if not have_fido:
        err('Need fido2 package(s) for webauthn. Consider doing `pip install fido2` (or similar)'
            )
    devices = list(CtapHidDevice.list_devices())
    if not devices:
        err('webauthn configured, but no U2F devices found')
    provider = factor.get('provider', '')
    log('mfa {0} challenge request [okta_url]'.format(provider))
    data = {'stateToken': state_token}
    _, _h, j = send_json_req(conf,
                             s,
                             'webauthn mfa challenge',
                             factor.get('url', ''),
                             data,
                             expected_url=conf.okta_url,
                             verify=conf.get_cert('okta_url', True))
    rfactor = j['_embedded']['factor']
    profile = rfactor['profile']
    purl = parse_url(conf.okta_url)
    origin = '{0}://{1}'.format(purl[0], purl[1])
    challenge = rfactor['_embedded']['challenge']['challenge']
    credentialId = websafe_decode(profile['credentialId'])
    allow_list = [{'type': 'public-key', 'id': credentialId}]
    for dev in devices:
        client = Fido2Client(dev, origin)
        print('!!! Touch the flashing U2F device to authenticate... !!!')
        try:
            result = client.get_assertion(purl[1], challenge, allow_list)
            dbg(conf.debug, 'assertion.result', result)
            break
        except Exception:
            traceback.print_exc(file=sys.stderr)
            result = None
    if not result:
        return None
    assertion, client_data = result[0][0], result[
        1]  # only one cred in allowList, so only one response.
    data = {
        'stateToken':
        state_token,
        'clientData':
        to_n((base64.b64encode(client_data)).decode('ascii')),
        'signatureData':
        to_n((base64.b64encode(assertion.signature)).decode('ascii')),
        'authenticatorData':
        to_n((base64.b64encode(assertion.auth_data)).decode('ascii'))
    }
    log('mfa {0} signature request [okta_url]'.format(provider))
    _, _h, j = send_json_req(conf,
                             s,
                             'uf2 mfa signature',
                             j['_links']['next']['href'],
                             data,
                             expected_url=conf.okta_url,
                             verify=conf.get_cert('okta_url', True))
    return j
示例#15
0
def log_devices() -> None:
    from fido2.hid import CtapHidDevice

    ctap_devices = [device for device in CtapHidDevice.list_devices()]
    logger.info(f"Found {len(ctap_devices)} CTAPHID devices:")
    for device in ctap_devices:
        descriptor = device.descriptor
        path = device_path_to_str(descriptor.path)
        logger.info(f"- {path} ({descriptor.vid:x}:{descriptor.pid:x})")
def get_dev():
    dev = next(CtapHidDevice.list_devices(), None)
    if dev is not None:
        print("Use USB HID channel.")
    else:
        print("No FIDO device found")
        sys.exit(1)

    return dev
示例#17
0
 def list() -> List["Nitrokey3Device"]:
     devices = []
     for device in CtapHidDevice.list_devices():
         try:
             devices.append(Nitrokey3Device(device))
         except ValueError:
             # not a Nitrokey 3 device, skip
             pass
     return devices
示例#18
0
    def find_device(self, ):
        dev = next(CtapHidDevice.list_devices(), None)
        if not dev:
            raise RuntimeError('No FIDO device found')
        self.dev = dev
        self.ctap1 = CTAP1(dev)

        if self.exchange == self.exchange_hid:
            self.send_data_hid(CTAPHID.INIT,
                               '\x11\x11\x11\x11\x11\x11\x11\x11')
示例#19
0
def find_all():
    hid_devices = list(CtapHidDevice.list_devices())
    solo_devices = [
        d for d in hid_devices if all((
            d.descriptor["vendor_id"] == 1155,
            d.descriptor["product_id"] == 41674,
            # "Solo" in d.descriptor["product_string"],
        ))
    ]
    return [find(raw_device=device) for device in solo_devices]
示例#20
0
def connect(domain="https://localhost", aaguid=None):
    for dev in CtapHidDevice.list_devices():
        client = Fido2Client(dev, domain)
        if not aaguid or aaguid == client.info.aaguid.hex():
          if "hmac-secret" in client.info.extensions:
            return client

        client.close()
    else:
        print("No Authenticator with the HmacSecret extension found!")
        sys.exit(-1)
示例#21
0
    def find_device(self, dev=None, solo_serial: str = None):
        devices = []
        if dev is None:
            if solo_serial is not None:
                if solo_serial.startswith("device="):
                    solo_serial = solo_serial.split("=")[1]
                    dev = open_device(solo_serial)
                else:
                    devices = list(CtapHidDevice.list_devices())
                    devices = [
                        d for d in devices
                        if d.descriptor.serial_number == solo_serial
                    ]
            else:
                devices = list(CtapHidDevice.list_devices())
            if len(devices) > 1:
                raise pynitrokey.exceptions.NonUniqueDeviceError
            if len(devices) > 0:
                dev = devices[0]
        if dev is None:
            raise RuntimeError("No FIDO device found")
        self.dev = dev

        self.ctap1 = CTAP1(dev)

        try:
            self.ctap2: Optional[CTAP2] = CTAP2(dev)
        except CtapError as e:
            self.ctap2 = None

        try:
            self.client: Optional[Fido2Client] = Fido2Client(dev, self.origin)
        except CtapError:
            print("Not using FIDO2 interface.")
            self.client = None

        if self.exchange == self.exchange_hid:
            self.send_data_hid(CTAPHID.INIT,
                               "\x11\x11\x11\x11\x11\x11\x11\x11")

        return self.dev
示例#22
0
def find_all():
    hid_devices = list(CtapHidDevice.list_devices())
    solo_devices = [
        d
        for d in hid_devices
        if (d.descriptor["vendor_id"], d.descriptor["product_id"]) in [
                    (1155, 41674),
                    (0x20A0, 0x42B3),
                    (0x20A0, 0x42B1),
        ]
    ]
    return [find(raw_device=device) for device in solo_devices]
示例#23
0
文件: solotool.py 项目: zenobik/solo
    def find_device(self, ):
        dev = next(CtapHidDevice.list_devices(), None)
        if not dev:
            raise RuntimeError("No FIDO device found")
        self.dev = dev
        self.ctap1 = CTAP1(dev)
        self.ctap2 = CTAP2(dev)
        self.client = Fido2Client(dev, self.origin)

        if self.exchange == self.exchange_hid:
            self.send_data_hid(CTAPHID.INIT,
                               "\x11\x11\x11\x11\x11\x11\x11\x11")
示例#24
0
def find_all():
    from fido2.hid import CtapHidDevice

    hid_devices = list(CtapHidDevice.list_devices())
    solo_devices = [d for d in hid_devices
        if (d.descriptor["vendor_id"], d.descriptor["product_id"]) in [
            ## @FIXME: move magic numbers
            (1155, 41674),
            (0x20A0, 0x42B3),
            (0x20A0, 0x42B1),
        ]
    ]
    return [find(raw_device=device) for device in solo_devices]
示例#25
0
文件: tester.py 项目: cuongnv/solo
    def find_device(self, nfcInterfaceOnly=False):
        dev = None
        if not nfcInterfaceOnly:
            print("--- HID ---")
            print(list(CtapHidDevice.list_devices()))
            dev = next(CtapHidDevice.list_devices(), None)

        if not dev:
            try:
                from fido2.pcsc import CtapPcscDevice

                print("--- NFC ---")
                print(list(CtapPcscDevice.list_devices()))
                dev = next(CtapPcscDevice.list_devices(), None)
            except (ModuleNotFoundError, ImportError):
                print("One of NFC library is not installed properly.")
        if not dev:
            raise RuntimeError("No FIDO device found")
        self.dev = dev
        self.client = Fido2Client(dev, self.origin)
        self.ctap = self.client.ctap2
        self.ctap1 = CTAP1(dev)
示例#26
0
def do_register_user(user, rp_id, resident_key=False):
    """
    FIDO2 registration process
    :param user: The user to register
    :param rp_id: Relying Party identifier
    :param resident_key: Boolean indicating whether or not to store a
    resident key
    :return: Newly created credentials
    """
    # begin registration
    relying_part = RelyingParty(rp_id)
    server = Fido2Server(relying_part)

    registration_data, state = server.register_begin(user)

    # make credential
    dev = next(CtapHidDevice.list_devices(), None)
    if not dev:
        print('No FIDO device found')
        sys.exit(1)

    client = Fido2Client(dev, 'https://' + rp_id)
    rp = {'id': rp_id, 'name': rp_id}
    challenge = websafe_encode(registration_data['publicKey']['challenge'])

    if resident_key:
        user['name'] = "."
        user_string = "(id: {0})".format(user['id'].hex())
    else:
        user_string = "(name: {0}, display name: {1})".format(
            user['name'], user['displayName'])

    print("\nRegistration request for user: "******"From service: (Address: {0}, Name: {1})".format(rp['id'],
                                                           rp['name']))
    print('Touch your authenticator device now to consent to registration...\n')
    try:
        attestation_object, client_data = client.make_credential(
            rp, user, challenge, rk=resident_key)
    except Exception as e:
        print("Registration failed")
        raise e

    # complete registration
    registration_data = server.register_complete(state, client_data,
                                                 attestation_object)
    credential = registration_data.credential_data
    print("Registration complete")

    return credential
示例#27
0
    def find_device(self, dev=None, solo_serial=None):
        if dev is None:
            devices = list(CtapHidDevice.list_devices())
            if solo_serial is not None:
                for d in devices:
                    if not hasattr(d, "serial_number"):
                        print(
                            "Currently serial numbers are not supported with current fido2 library.  Please upgrade: pip3 install fido2 --upgrade"
                        )
                        sys.exit(1)
                devices = [
                    d for d in devices
                    if d.descriptor.serial_number == solo_serial
                ]
            if len(devices) > 1:
                raise solo.exceptions.NonUniqueDeviceError
            if len(devices) == 0:
                raise RuntimeError("No FIDO device found")
            dev = devices[0]
        self.dev = dev

        self.ctap1 = CTAP1(dev)
        try:
            self.ctap2 = CTAP2(dev)
        except CtapError:
            self.ctap2 = None

        try:
            self.client = Fido2Client(dev, self.origin)
        except CtapError:
            print("Not using FIDO2 interface.")
            self.client = None

        if self.exchange == self.exchange_hid:
            self.send_data_hid(CTAPHID.INIT,
                               "\x11\x11\x11\x11\x11\x11\x11\x11")

        return self.dev
示例#28
0
httpport = 8080
udpport = 8111

HEX_FILE = '../efm32/GNU ARM v7.2.1 - Debug/EFM32.hex'

def ForceU2F(client,device):
    client.ctap = CTAP1(device)
    client.pin_protocol = None
    client._do_make_credential = client._ctap1_make_credential
    client._do_get_assertion = client._ctap1_get_assertion


if __name__ == '__main__':
    try:
        dev = next(CtapHidDevice.list_devices(), None)
        print(dev)
        if not dev:
            raise RuntimeError('No FIDO device found')
        client = Fido2Client(dev, 'https://example.com')
        ForceU2F(client, dev)
        ctap = client.ctap
    except Exception as e:
        print(e)




def write(data):
    msg = from_websafe(data)
    msg = base64.b64decode(msg)
示例#29
0
def open_devices():
    for dev in CtapHidDevice.list_devices(descriptor_filter):
        try:
            yield FidoDriver(dev)
        except Exception as e:
            logger.debug('Failed opening FIDO device', exc_info=e)
示例#30
0
 def open_connection(self, connection_type):
     if self.supports_connection(connection_type):
         return CtapHidDevice(self.descriptor, open_connection(self.descriptor))
     return super(OtpYubiKeyDevice, self).open_connection(connection_type)
示例#31
0
def enumerate_devices():
    for dev in CtapHidDevice.list_devices():
        yield dev
    if CtapPcscDevice:
        for dev in CtapPcscDevice.list_devices():
            yield dev