Ejemplo n.º 1
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]
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
    def test_make_credential_ctap1(self):
        dev = mock.Mock()
        dev.capabilities = 0  # No CTAP2
        client = Fido2Client(dev, APP_ID)

        client.ctap1 = mock.MagicMock()
        client.ctap1.get_version.return_value = "U2F_V2"
        client.ctap1.register.return_value = REG_DATA

        response = client.make_credential(
            PublicKeyCredentialCreationOptions(rp, user, challenge, [{
                "type": "public-key",
                "alg": -7
            }]))

        self.assertIsInstance(response.attestation_object, AttestationObject)
        self.assertIsInstance(response.client_data, ClientData)
        client_data = response.client_data

        client.ctap1.register.assert_called_with(client_data.hash,
                                                 sha256(rp["id"].encode()))

        self.assertEqual(client_data.get("origin"), APP_ID)
        self.assertEqual(client_data.get("type"), "webauthn.create")
        self.assertEqual(client_data.challenge, challenge)

        self.assertEqual(response.attestation_object.fmt, "fido-u2f")
Ejemplo n.º 4
0
    def test_make_credential_existing_key(self, PatchedCTAP2):
        dev = mock.Mock()
        dev.capabilities = CAPABILITY.CBOR
        ctap2 = mock.MagicMock()
        ctap2.get_info.return_value = Info(_INFO_NO_PIN)
        ctap2.make_credential.side_effect = CtapError(
            CtapError.ERR.CREDENTIAL_EXCLUDED)
        PatchedCTAP2.return_value = ctap2
        client = Fido2Client(dev, APP_ID)

        try:
            client.make_credential(
                PublicKeyCredentialCreationOptions(
                    rp,
                    user,
                    challenge,
                    [{
                        "type": "public-key",
                        "alg": -7
                    }],
                    authenticator_selection={
                        "userVerification": "discouraged"
                    },
                ))
            self.fail("make_credential did not raise error")
        except ClientError as e:
            self.assertEqual(e.code, ClientError.ERR.DEVICE_INELIGIBLE)

        ctap2.get_info.assert_called_with()
        ctap2.make_credential.assert_called_once()
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    def test_make_credential_ctap1(self):
        dev = mock.Mock()
        dev.capabilities = 0  # No CTAP2
        client = Fido2Client(dev, APP_ID)

        client.ctap1 = mock.MagicMock()
        client.ctap1.get_version.return_value = "U2F_V2"
        client.ctap1.register.return_value = REG_DATA

        attestation, client_data = client.make_credential(rp,
                                                          user,
                                                          challenge,
                                                          timeout=1)

        self.assertIsInstance(attestation, AttestationObject)
        self.assertIsInstance(client_data, ClientData)

        client.ctap1.register.assert_called_with(client_data.hash,
                                                 sha256(rp["id"].encode()))

        self.assertEqual(client_data.get("origin"), APP_ID)
        self.assertEqual(client_data.get("type"), "webauthn.create")
        self.assertEqual(client_data.get("challenge"), challenge)

        self.assertEqual(attestation.fmt, "fido-u2f")
Ejemplo n.º 7
0
 def find_device(self,):
     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
Ejemplo n.º 8
0
def get_client():
    global use_prompt
    if WindowsClient.is_available(
    ) and not ctypes.windll.shell32.IsUserAnAdmin():
        # Use the Windows WebAuthn API if available, and we're not running as admin
        client = WindowsClient("https://example.com")
    else:
        # Locate a device
        for dev in enumerate_devices():
            client = Fido2Client(dev, "https://example.com")
            if client.info.options.get("rk"):
                use_prompt = not (CtapPcscDevice
                                  and isinstance(dev, CtapPcscDevice))
                break
        else:
            print("No Authenticator with support for resident key found!")
            sys.exit(1)

        # Prefer UV if supported
        if client.info.options.get("uv"):
            uv = "preferred"
            print("Authenticator supports User Verification")
        elif client.info.options.get("clientPin"):
            # Prompt for PIN if needed
            pin = getpass("Please enter PIN: ")
        else:
            print("PIN not set, won't use")
    return client
Ejemplo n.º 9
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
Ejemplo n.º 10
0
    def test_make_credential_ctap2(self):
        dev = mock.Mock()
        dev.capabilities = CAPABILITY.CBOR
        client = Fido2Client(dev, APP_ID)
        client.ctap = mock.MagicMock()
        client.ctap.get_info.return_value = Info(_INFO_NO_PIN)
        client.ctap.make_credential.return_value = AttestationObject(_MC_RESP)

        attestation, client_data = client.make_credential(rp,
                                                          user,
                                                          challenge,
                                                          timeout=1)

        self.assertIsInstance(attestation, AttestationObject)
        self.assertIsInstance(client_data, ClientData)

        client.ctap.get_info.assert_called_with()
        client.ctap.make_credential.assert_called_with(
            client_data.hash, rp, user, [{
                'type': 'public-key',
                'alg': -7
            }], None, None, None, None, None, 1, None)

        self.assertEqual(client_data.get('origin'), APP_ID)
        self.assertEqual(client_data.get('type'), 'webauthn.create')
        self.assertEqual(client_data.get('challenge'), challenge)
Ejemplo n.º 11
0
    def test_make_credential_ctap1(self):
        dev = mock.Mock()
        dev.capabilities = 0  # No CTAP2
        client = Fido2Client(dev, APP_ID)

        client.ctap = mock.MagicMock()
        client.ctap.get_version.return_value = 'U2F_V2'
        client.ctap.register.return_value = REG_DATA

        attestation, client_data = client.make_credential(rp,
                                                          user,
                                                          challenge,
                                                          timeout=1)

        self.assertIsInstance(attestation, AttestationObject)
        self.assertIsInstance(client_data, ClientData)

        client.ctap.register.assert_called_with(
            client_data.hash,
            sha256(rp['id'].encode()),
        )

        self.assertEqual(client_data.get('origin'), APP_ID)
        self.assertEqual(client_data.get('type'), 'webauthn.create')
        self.assertEqual(client_data.get('challenge'), challenge)

        self.assertEqual(attestation.fmt, 'fido-u2f')
Ejemplo n.º 12
0
 def per_device(dev, cancel_ev=None):
     client = Fido2Client(dev, fidocrypt_origin(rp['id']), verify_origin)
     return client.make_credential(
         create_options['publicKey'],
         on_keepalive=on_keepalive if prompt is not None else None,
         **({} if cancel_ev is None else {
             'event': cancel_ev
         }))
Ejemplo n.º 13
0
 def per_device(dev, cancel_ev=None):
     client = Fido2Client(dev, fidokdf_origin(rp['id']), verify_origin)
     return client.get_assertion(
         request_options['publicKey'],
         on_keepalive=on_keepalive if prompt is not None else None,
         **({} if cancel_ev is None else {
             'event': cancel_ev
         }))
Ejemplo n.º 14
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]
Ejemplo n.º 15
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
Ejemplo n.º 16
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
     self.ctap1 = CTAP1(dev)
Ejemplo n.º 17
0
    def _do_get_assertion(device, challenge, rp_id, allow_credentials,
                          user_verification, extensions, result_queue,
                          stop_event):
        """
        Call get_assertion on an individual authenticator.
        :param device: The device to use
        :param challenge: Websafe encoded challenge by the server
        :param rp_id: Relying Party identifier
        :param allow_credentials: List of acceptable PKCSs
        :param user_verification: Requirements for user verification
        :param extensions: Possible extensions
        :param result_queue: Queue to write result to
        :param stop_event: Stop event for the authenticator
        :return:
        """
        # initialize values
        client = Fido2Client(device, "https://" + rp_id)
        user_interaction = False
        assertions = None
        client_data = None
        filtered_allow_credentials = None
        response = AssertionResponseInformation(assertions, client_data,
                                                device.descriptor,
                                                user_interaction)

        # set user verification/ presence
        user_verification_required = Fido2ClientWrapper._uv_required(
            user_verification, device)
        user_presence_required = not user_verification_required

        # check which of the allow credentials are bound to the authenticator
        if allow_credentials:
            filtered_allow_credentials = \
                Fido2ClientWrapper._filter_allow_credentials(
                    client, challenge, rp_id, allow_credentials)
            if len(allow_credentials) > 0 and \
                    len(filtered_allow_credentials) == 0:
                result_queue.put((CommunicationObject.ASSERTION, response))
                return

        # get the assertion of the authenticator
        try:
            user_interaction = True
            assertions, client_data = client.get_assertion(
                rp_id, challenge, filtered_allow_credentials, extensions,
                user_presence_required, user_verification_required, None,
                stop_event, None)
        except Exception:
            if stop_event.is_set():
                user_interaction = False

        # insert result into the queue
        response = AssertionResponseInformation(assertions, client_data,
                                                device.descriptor,
                                                user_interaction)
        result_queue.put((CommunicationObject.ASSERTION, response))
Ejemplo n.º 18
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)
Ejemplo n.º 19
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)
        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')
Ejemplo n.º 20
0
def _webauthn_get_assertion(
    device,
    webauthn_credential_request_options,
    duo_host,
    sid,
    webauthn_response,
    session,
    ssl_verification_enabled,
    cancel,
    rq,
):
    click.echo(
        "Activate your FIDO U2F / FIDO2 authenticator now: '{}'".format(device),
        err=True,
    )
    client = Fido2Client(device, webauthn_credential_request_options["extensions"]["appid"])
    try:
        assertion = client.get_assertion(
            webauthn_credential_request_options,
            event=cancel,
        )
        authenticator_assertion_response = assertion.get_response(0)
        assertion_response = assertion.get_assertions()[0]

        webauthn_response["id"] = (
            base64.urlsafe_b64encode(assertion_response.credential["id"]).decode("ascii").rstrip("=")
        )  # Strip trailing padding characters
        webauthn_response["rawId"] = webauthn_response["id"]
        webauthn_response["type"] = assertion_response.credential["type"]
        webauthn_response["authenticatorData"] = base64.urlsafe_b64encode(assertion_response.auth_data).decode("ascii")
        webauthn_response["clientDataJSON"] = base64.urlsafe_b64encode(authenticator_assertion_response["clientData"]).decode(
            "ascii"
        )
        webauthn_response["signature"] = binascii.hexlify(assertion_response.signature).decode("ascii")
        webauthn_response["extensionResults"] = authenticator_assertion_response["extensionResults"]
        logging.debug("webauthn_response: {}".format(webauthn_response))

        click.echo(
            "Got response from FIDO U2F / FIDO2 authenticator: '{}'".format(device),
            err=True,
        )
        rq.put(_submit_webauthn_response(duo_host, sid, webauthn_response, session, ssl_verification_enabled))
    except Exception as e:
        logging.debug("Got an exception while waiting for {}: {}".format(device, e))
        if not cancel.is_set():
            raise
    finally:
        # Cancel the other FIDO U2F / FIDO2 prompts
        cancel.set()

        device.close()
Ejemplo n.º 21
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
Ejemplo n.º 22
0
 def test_make_credential_wrong_app_id(self):
     dev = mock.Mock()
     dev.capabilities = CAPABILITY.CBOR
     client = Fido2Client(dev, APP_ID)
     try:
         client.make_credential(
             {
                 'id': 'bar.example.com',
                 'name': 'Invalid RP'
             },
             user,
             challenge,
             timeout=1)
         self.fail('make_credential did not raise error')
     except ClientError as e:
         self.assertEqual(e.code, ClientError.ERR.BAD_REQUEST)
Ejemplo n.º 23
0
    def test_make_credential_ctap2(self, PatchedCtap2):
        dev = mock.Mock()
        dev.capabilities = CAPABILITY.CBOR
        ctap2 = mock.MagicMock()
        ctap2.get_info.return_value = Info.from_dict(cbor.decode(_INFO_NO_PIN))
        ctap2.info = ctap2.get_info()
        ctap2.make_credential.return_value = AttestationResponse.from_dict(
            cbor.decode(_MC_RESP))
        PatchedCtap2.return_value = ctap2
        client = Fido2Client(dev, APP_ID)

        response = client.make_credential(
            PublicKeyCredentialCreationOptions(
                rp,
                user,
                challenge,
                [{
                    "type": "public-key",
                    "alg": -7
                }],
                timeout=1000,
                authenticator_selection={"userVerification": "discouraged"},
            ))

        self.assertIsInstance(response.attestation_object, AttestationObject)
        self.assertIsInstance(response.client_data, CollectedClientData)

        ctap2.make_credential.assert_called_with(
            response.client_data.hash,
            rp,
            user,
            [{
                "type": "public-key",
                "alg": -7
            }],
            None,
            None,
            None,
            None,
            None,
            event=mock.ANY,
            on_keepalive=mock.ANY,
        )

        self.assertEqual(response.client_data.origin, APP_ID)
        self.assertEqual(response.client_data.type, "webauthn.create")
        self.assertEqual(response.client_data.challenge, challenge)
Ejemplo n.º 24
0
    def test_make_credential_ctap2(self, PatchedCTAP2):
        dev = mock.Mock()
        dev.capabilities = CAPABILITY.CBOR
        ctap2 = mock.MagicMock()
        ctap2.get_info.return_value = Info(_INFO_NO_PIN)
        ctap2.make_credential.return_value = AttestationObject(_MC_RESP)
        PatchedCTAP2.return_value = ctap2
        client = Fido2Client(dev, APP_ID)

        attestation, client_data = client.make_credential(
            PublicKeyCredentialCreationOptions(
                rp,
                user,
                challenge,
                [{
                    "type": "public-key",
                    "alg": -7
                }],
                timeout=1000,
                authenticator_selection={"userVerification": "discouraged"},
            ))

        self.assertIsInstance(attestation, AttestationObject)
        self.assertIsInstance(client_data, ClientData)

        ctap2.get_info.assert_called_with()
        ctap2.make_credential.assert_called_with(
            client_data.hash,
            rp,
            user,
            [{
                "type": "public-key",
                "alg": -7
            }],
            None,
            None,
            None,
            None,
            None,
            mock.ANY,
            None,
        )

        self.assertEqual(client_data.get("origin"), APP_ID)
        self.assertEqual(client_data.get("type"), "webauthn.create")
        self.assertEqual(client_data.challenge, challenge)
Ejemplo n.º 25
0
    def test_make_credential_existing_key(self):
        dev = mock.Mock()
        dev.capabilities = CAPABILITY.CBOR
        client = Fido2Client(dev, APP_ID)
        client.ctap = mock.MagicMock()
        client.ctap.get_info.return_value = Info(_INFO_NO_PIN)
        client.ctap.make_credential.side_effect = CtapError(
            CtapError.ERR.CREDENTIAL_EXCLUDED)

        try:
            client.make_credential(rp, user, challenge, timeout=1)
            self.fail('make_credential did not raise error')
        except ClientError as e:
            self.assertEqual(e.code, ClientError.ERR.DEVICE_INELIGIBLE)

        client.ctap.get_info.assert_called_with()
        client.ctap.make_credential.assert_called_once()
Ejemplo n.º 26
0
 def test_make_credential_wrong_app_id(self, PatchedCTAP2):
     dev = mock.Mock()
     dev.capabilities = CAPABILITY.CBOR
     ctap2 = mock.MagicMock()
     ctap2.get_info.return_value = Info(_INFO_NO_PIN)
     PatchedCTAP2.return_value = ctap2
     client = Fido2Client(dev, APP_ID)
     try:
         client.make_credential(
             PublicKeyCredentialCreationOptions(
                 {"id": "bar.example.com", "name": "Invalid RP"},
                 user,
                 challenge,
                 [{"type": "public-key", "alg": -7}],
             )
         )
         self.fail("make_credential did not raise error")
     except ClientError as e:
         self.assertEqual(e.code, ClientError.ERR.BAD_REQUEST)
Ejemplo n.º 27
0
 def test_make_credential_wrong_app_id(self, PatchedCTAP2):
     dev = mock.Mock()
     dev.capabilities = CAPABILITY.CBOR
     ctap2 = mock.MagicMock()
     ctap2.get_info.return_value = Info(_INFO_NO_PIN)
     PatchedCTAP2.return_value = ctap2
     client = Fido2Client(dev, APP_ID)
     try:
         client.make_credential(
             {
                 'id': 'bar.example.com',
                 'name': 'Invalid RP'
             },
             user,
             challenge,
             timeout=1)
         self.fail('make_credential did not raise error')
     except ClientError as e:
         self.assertEqual(e.code, ClientError.ERR.BAD_REQUEST)
Ejemplo n.º 28
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
Ejemplo n.º 29
0
    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)
Ejemplo n.º 30
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