def test_parse_bytes(self):
        info = Info(_INFO)

        self.assertEqual(info.versions, ['U2F_V2', 'FIDO_2_0'])
        self.assertEqual(info.extensions, ['uvm', 'hmac-secret'])
        self.assertEqual(info.aaguid, _AAGUID)
        self.assertEqual(info.options, {
            'rk': True,
            'up': True,
            'plat': False,
            'clientPin': False
        })
        self.assertEqual(info.max_msg_size, 1200)
        self.assertEqual(info.pin_protocols, [1])
        self.assertEqual(
            info.data, {
                Info.KEY.VERSIONS: ['U2F_V2', 'FIDO_2_0'],
                Info.KEY.EXTENSIONS: ['uvm', 'hmac-secret'],
                Info.KEY.AAGUID: _AAGUID,
                Info.KEY.OPTIONS: {
                    'clientPin': False,
                    'plat': False,
                    'rk': True,
                    'up': True
                },
                Info.KEY.MAX_MSG_SIZE: 1200,
                Info.KEY.PIN_PROTOCOLS: [1]
            })
Beispiel #2
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)
Beispiel #3
0
    def test_parse_bytes(self):
        info = Info(_INFO)

        self.assertEqual(info.versions, ["U2F_V2", "FIDO_2_0"])
        self.assertEqual(info.extensions, ["uvm", "hmac-secret"])
        self.assertEqual(info.aaguid, _AAGUID)
        self.assertEqual(info.options, {
            "rk": True,
            "up": True,
            "plat": False,
            "clientPin": False
        })
        self.assertEqual(info.max_msg_size, 1200)
        self.assertEqual(info.pin_uv_protocols, [1])
        self.assertEqual(
            info.data,
            {
                Info.KEY.VERSIONS: ["U2F_V2", "FIDO_2_0"],
                Info.KEY.EXTENSIONS: ["uvm", "hmac-secret"],
                Info.KEY.AAGUID: _AAGUID,
                Info.KEY.OPTIONS: {
                    "clientPin": False,
                    "plat": False,
                    "rk": True,
                    "up": True,
                },
                Info.KEY.MAX_MSG_SIZE: 1200,
                Info.KEY.PIN_UV_PROTOCOLS: [1],
            },
        )
Beispiel #4
0
    def test_parse_bytes(self):
        info = Info.from_dict(cbor.decode(_INFO))

        self.assertEqual(info.versions, ["U2F_V2", "FIDO_2_0"])
        self.assertEqual(info.extensions, ["uvm", "hmac-secret"])
        self.assertEqual(info.aaguid, _AAGUID)
        self.assertEqual(info.options, {
            "rk": True,
            "up": True,
            "plat": False,
            "clientPin": False
        })
        self.assertEqual(info.max_msg_size, 1200)
        self.assertEqual(info.pin_uv_protocols, [1])
        assert info[0x01] == ["U2F_V2", "FIDO_2_0"]
        assert info[0x02] == ["uvm", "hmac-secret"]
        assert info[0x03] == _AAGUID
        assert info[0x04] == {
            "clientPin": False,
            "plat": False,
            "rk": True,
            "up": True,
        }
        assert info[0x05] == 1200
        assert info[0x06] == [1]
Beispiel #5
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()
Beispiel #6
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)
Beispiel #7
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()
Beispiel #8
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)
Beispiel #9
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)
Beispiel #10
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)
Beispiel #11
0
 def test_info_with_extra_field(self):
     info = Info(_INFO_EXTRA_KEY)
     self.assertEqual(info.versions, ['U2F_V2', 'FIDO_2_0'])
     self.assertEqual(info.data[7], 8)
Beispiel #12
0
 def test_info_with_extra_field(self):
     info = Info.from_dict(cbor.decode(_INFO_EXTRA_KEY))
     self.assertEqual(info.versions, ["U2F_V2", "FIDO_2_0"])
            try:
                auth_resp = _call_polling(
                    self.ctap1_poll_delay,
                    event,
                    on_keepalive,
                    self.ctap1.authenticate,
                    client_param,
                    app_param,
                    cred["id"],
                )
                return [
                    AssertionResponse.from_ctap1(app_param, cred, auth_resp)
                ]
            except ClientError as e:
                if e.code == ClientError.ERR.TIMEOUT:
                    raise  # Other errors are ignored so we move to the next.
        raise ClientError.ERR.DEVICE_INELIGIBLE()


_WIN_INFO = Info.create(["U2F_V2", "FIDO_2_0"])

if platform.system().lower() == "windows":
    try:
        from .win_api import (
            WinAPI,
            WebAuthNAuthenticatorAttachment,
            WebAuthNUserVerificationRequirement,
            WebAuthNAttestationConvoyancePreference,
        )
    except Exception:  # nosec # TODO: Make this less generic
        pass