Ejemplo n.º 1
0
    def test_hmac_sha256_vectors(self):
        self.assertEqual(hmac_sha256(
            b'\x0b'*20,
            b'Hi There'
        ), a2b_hex(b'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7'))  # noqa

        self.assertEqual(hmac_sha256(
            b'Jefe',
            b'what do ya want for nothing?'
        ), a2b_hex(b'5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843'))  # noqa
Ejemplo n.º 2
0
    def test_hmac_sha256_vectors(self):
        self.assertEqual(
            hmac_sha256(b"\x0b" * 20, b"Hi There"),
            bytes.fromhex(
                "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
            ),
        )

        self.assertEqual(
            hmac_sha256(b"Jefe", b"what do ya want for nothing?"),
            bytes.fromhex(
                "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
            ),
        )
Ejemplo n.º 3
0
 def sign_hash(self, credential_id, dgst, pin):
     ctap2 = CTAP2(self.get_current_hid_device())
     client = self.get_current_fido_client()
     if pin:
         pin_token = client.client_pin.get_pin_token(pin)
         pin_auth = hmac_sha256(pin_token, dgst)[:16]
         return ctap2.send_cbor(
             0x50,
             {
                 1: dgst,
                 2: {
                     "id": credential_id,
                     "type": "public-key"
                 },
                 3: pin_auth
             },
         )
     else:
         return ctap2.send_cbor(0x50, {
             1: dgst,
             2: {
                 "id": credential_id,
                 "type": "public-key"
             }
         })
Ejemplo n.º 4
0
 def _sign_hash(self, cred_id, dgst):
     if self.pin:
         pin_token = self.client.pin_protocol.get_pin_token(self.pin)
         pin_auth = hmac_sha256(pin_token, dgst)[:16]
         ret = self.ctap2.send_cbor(0x50, {
             1: dgst,
             2: {
                 "id": cred_id,
                 "type": "public-key"
             },
             3: pin_auth
         })
     else:
         ret = self.ctap2.send_cbor(0x50, {
             1: dgst,
             2: {
                 "id": cred_id,
                 "type": "public-key"
             }
         })
     der_sig = ret[1]
     # Extract 'r' and 's' from the DER signature as described here:
     # https://crypto.stackexchange.com/questions/1795/how-can-i-convert-a-der-ecdsa-signature-to-asn-1
     r_len = der_sig[3]
     r = der_sig[4:4 + r_len]
     s = der_sig[6 + r_len:]
     if len(r) > 32:
         r = r[-32:]
     if len(s) > 32:
         s = s[-32:]
     return r, s
Ejemplo n.º 5
0
Archivo: fido2.py Proyecto: utzig/solo
        def get_salt_params(salts):
            enc = cipher.encryptor()
            salt_enc = b""
            for salt in salts:
                salt_enc += enc.update(salt)
            salt_enc += enc.finalize()

            salt_auth = hmac_sha256(shared_secret, salt_enc)[:16]
            return salt_enc, salt_auth
Ejemplo n.º 6
0
    def _ctap2_make_credential(
        self,
        client_data,
        rp,
        user,
        key_params,
        exclude_list,
        extensions,
        rk,
        uv,
        pin,
        event,
        on_keepalive,
    ):
        pin_auth = None
        pin_protocol = None
        if pin:
            pin_protocol = self.pin_protocol.VERSION
            pin_token = self.pin_protocol.get_pin_token(pin)
            pin_auth = hmac_sha256(pin_token, client_data.hash)[:16]
        elif self.info.options.get("clientPin") and not uv:
            raise ClientError.ERR.BAD_REQUEST("PIN required but not provided")

        if not (rk or uv):
            options = None
        else:
            options = {}
            if rk:
                options["rk"] = True
            if uv:
                options["uv"] = True

        if exclude_list:
            # Filter out credential IDs which are too long
            max_len = self.info.max_cred_id_length
            if max_len:
                exclude_list = [e for e in exclude_list if len(e) <= max_len]

            # Reject the request if too many credentials remain.
            max_creds = self.info.max_creds_in_list
            if max_creds and len(exclude_list) > max_creds:
                raise ClientError.ERR.BAD_REQUEST("exclude_list too long")

        return self.ctap2.make_credential(
            client_data.hash,
            rp,
            user,
            key_params,
            exclude_list if exclude_list else None,
            extensions,
            options,
            pin_auth,
            pin_protocol,
            event,
            on_keepalive,
        )
Ejemplo n.º 7
0
    def sendGA(self, *args, **kwargs):
        if len(args) > 9:
            # Add additional arg to calculate pin auth on demand
            pin = args[-1]
            args = list(args[:-1])
            if args[5] == None and args[6] == None:
                pin_token = self.client.pin_protocol.get_pin_token(pin)
                pin_auth = hmac_sha256(pin_token, args[1])[:16]
                args[5] = pin_auth
                args[6] = 1

        return self.ctap2.get_assertion(*args, **kwargs)
Ejemplo n.º 8
0
    def test_backup_credential_is_generated_correctly(
        self,
        solo,
        device,
    ):
        import seedweed
        from binascii import hexlify

        key_A = b"A" * 32
        ext_state = b"I'm a dicekey key!"
        version = b"\x01"

        ext_key_cmd = 0x62
        print("Enter user presence THREE times.")
        solo.send_data_hid(ext_key_cmd, version + key_A + ext_state)

        # New credential works.
        mc_A_req = FidoRequest()
        mc_A_res = device.sendMC(*mc_A_req.toMC())

        rpIdHash = sha256(mc_A_req.rp["id"].encode("utf8"))

        credId = mc_A_res.auth_data.credential_data.credential_id

        (
            uniqueId,
            extStateInCredId,
            credMacInCredId,
        ) = seedweed.nonce_extstate_mac_from_credential_id(credId)

        seedweed.validate_credential_id(key_A, credId, rpIdHash)
        credMac = hmac_sha256(key_A, rpIdHash + version + uniqueId + ext_state)

        allow_list = [{
            "id": mc_A_res.auth_data.credential_data.credential_id,
            "type": "public-key",
        }]
        ga_req = FidoRequest(allow_list=allow_list)

        ga_res = device.sendGA(*ga_req.toGA())

        verify(mc_A_res, ga_res, ga_req.cdh)

        # Independently create the key and verify
        _, _, keypair, iterations = seedweed.keypair_from_seed_mac(
            key_A, credMac)
        assert iterations == 1
        keypair.verifying_key.verify(
            ga_res.signature,
            ga_res.auth_data + ga_req.cdh,
            sigdecode=ecdsa.util.sigdecode_der,
            hashfunc=hashlib.sha256,
        )
Ejemplo n.º 9
0
    def test_hmac_secret_different_with_uv(self, device, MCHmacSecret, cipher,
                                           sharedSecret):
        salts = [salt1]
        key_agreement, shared_secret = sharedSecret
        salt_enc, salt_auth = get_salt_params(cipher, shared_secret, salts)
        req = FidoRequest(extensions={
            "hmac-secret": {
                1: key_agreement,
                2: salt_enc,
                3: salt_auth
            }
        })
        auth_no_uv = device.sendGA(*req.toGA())
        assert (auth_no_uv.auth_data.flags & (1 << 2)) == 0

        ext_no_uv = auth_no_uv.auth_data.extensions
        assert ext_no_uv
        assert "hmac-secret" in ext_no_uv
        assert isinstance(ext_no_uv["hmac-secret"], bytes)
        assert len(ext_no_uv["hmac-secret"]) == len(salts) * 32

        verify(MCHmacSecret, auth_no_uv, req.cdh)

        # Now get same auth with UV
        pin = '1234'
        device.client.pin_protocol.set_pin(pin)
        pin_token = device.client.pin_protocol.get_pin_token(pin)
        pin_auth = hmac_sha256(pin_token, req.cdh)[:16]

        req = FidoRequest(req,
                          pin_protocol=1,
                          pin_auth=pin_auth,
                          extensions={
                              "hmac-secret": {
                                  1: key_agreement,
                                  2: salt_enc,
                                  3: salt_auth
                              }
                          })

        auth_uv = device.sendGA(*req.toGA())
        assert auth_uv.auth_data.flags & (1 << 2)
        ext_uv = auth_uv.auth_data.extensions
        assert ext_uv
        assert "hmac-secret" in ext_uv
        assert isinstance(ext_uv["hmac-secret"], bytes)
        assert len(ext_uv["hmac-secret"]) == len(salts) * 32

        verify(MCHmacSecret, auth_uv, req.cdh)

        # Now see if the hmac-secrets are different
        assert ext_no_uv['hmac-secret'] != ext_uv['hmac-secret']
Ejemplo n.º 10
0
    def _ctap2_get_assertion(self, client_data, rp_id, allow_list, extensions,
                             uv, up, pin, event, on_keepalive):
        pin_auth = None
        pin_protocol = None
        if pin:
            pin_protocol = self.pin_protocol.VERSION
            pin_token = self.pin_protocol.get_pin_token(pin)
            pin_auth = hmac_sha256(pin_token, client_data.hash)[:16]
        elif self.info.options.get("clientPin") and not uv:
            raise ClientError.ERR.BAD_REQUEST("PIN required but not provided")

        if uv:
            options = {"uv": True}
            if not up:
                options = {"uv": True, "up": False}
        else:
            options = None
            if not up:
                options = {"up": False}

        if allow_list:
            # Filter out credential IDs which are too long
            max_len = self.info.max_cred_id_length
            if max_len:
                allow_list = [e for e in allow_list if len(e) <= max_len]
            if not allow_list:
                raise CtapError(CtapError.ERR.NO_CREDENTIALS)

            # Reject the request if too many credentials remain.
            max_creds = self.info.max_creds_in_list
            if max_creds and len(allow_list) > max_creds:
                raise ClientError.ERR.BAD_REQUEST("allow_list too long")

        return self.ctap2.get_assertions(
            rp_id,
            client_data.hash,
            allow_list if allow_list else None,
            extensions,
            options,
            pin_auth,
            pin_protocol,
            event,
            on_keepalive,
        )
Ejemplo n.º 11
0
    def sendMC(self, *args, **kwargs):

        if len(args) > 11:
            # Add additional arg to calculate pin auth on demand
            pin = args[-1]
            args = list(args[:-1])
            if args[7] == None and args[8] == None:
                pin_token = self.client.pin_protocol.get_pin_token(pin)
                pin_auth = hmac_sha256(pin_token, args[0])[:16]
                args[7] = pin_auth
                args[8] = 1

        attestation_object = self.ctap2.make_credential(*args, **kwargs)
        if attestation_object:
            verifier = Attestation.for_type(attestation_object.fmt)
            client_data = args[0]
            verifier().verify(
                attestation_object.att_statement,
                attestation_object.auth_data,
                client_data,
            )
        return attestation_object
Ejemplo n.º 12
0
 def sign_hash(self, credential_id, dgst, pin):
     if pin:
         pin_token = self.client.pin_protocol.get_pin_token(pin)
         pin_auth = hmac_sha256(pin_token, dgst)[:16]
         return self.ctap2.send_cbor(
             0x50,
             {
                 1: dgst,
                 2: {
                     "id": credential_id,
                     "type": "public-key"
                 },
                 3: pin_auth
             },
         )
     else:
         return self.ctap2.send_cbor(0x50, {
             1: dgst,
             2: {
                 "id": credential_id,
                 "type": "public-key"
             }
         })
Ejemplo n.º 13
0
Archivo: fido2.py Proyecto: utzig/solo
    def test_extensions(self, ):

        salt1 = b"\x5a" * 32
        salt2 = b"\x96" * 32
        salt3 = b"\x03" * 32

        # self.testReset()

        with Test("Get info has hmac-secret"):
            info = self.ctap.get_info()
            assert "hmac-secret" in info.extensions

        reg = self.testMC(
            "Send MC with hmac-secret ext set to true, expect SUCCESS",
            cdh,
            rp,
            user,
            key_params,
            expectedError=CtapError.ERR.SUCCESS,
            other={
                "extensions": {
                    "hmac-secret": True
                },
                "options": {
                    "rk": True
                }
            },
        )

        with Test(
                "Check 'hmac-secret' is set to true in auth_data extensions"):
            assert reg.auth_data.extensions
            assert "hmac-secret" in reg.auth_data.extensions
            assert reg.auth_data.extensions["hmac-secret"] == True

        reg = self.testMC(
            "Send MC with fake extension set to true, expect SUCCESS",
            cdh,
            rp,
            user,
            key_params,
            expectedError=CtapError.ERR.SUCCESS,
            other={"extensions": {
                "tetris": True
            }},
        )

        with Test("Get shared secret"):
            key_agreement, shared_secret = (
                self.client.pin_protocol._init_shared_secret())
            cipher = Cipher(
                algorithms.AES(shared_secret),
                modes.CBC(b"\x00" * 16),
                default_backend(),
            )

        def get_salt_params(salts):
            enc = cipher.encryptor()
            salt_enc = b""
            for salt in salts:
                salt_enc += enc.update(salt)
            salt_enc += enc.finalize()

            salt_auth = hmac_sha256(shared_secret, salt_enc)[:16]
            return salt_enc, salt_auth

        for salt_list in ((salt1, ), (salt1, salt2)):
            salt_enc, salt_auth = get_salt_params(salt_list)

            auth = self.testGA(
                "Send GA request with %d salts hmac-secret, expect success" %
                len(salt_list),
                rp["id"],
                cdh,
                other={
                    "extensions": {
                        "hmac-secret": {
                            1: key_agreement,
                            2: salt_enc,
                            3: salt_auth
                        }
                    }
                },
                expectedError=CtapError.ERR.SUCCESS,
            )

            with Test(
                    "Check that hmac-secret is in auth_data extensions and has %d bytes"
                    % (len(salt_list) * 32)):
                ext = auth.auth_data.extensions
                assert ext
                assert "hmac-secret" in ext
                assert isinstance(ext["hmac-secret"], bytes)
                assert len(ext["hmac-secret"]) == len(salt_list) * 32

            with Test("Check that shannon_entropy of hmac-secret is good"):
                ext = auth.auth_data.extensions
                dec = cipher.decryptor()
                key = dec.update(ext["hmac-secret"]) + dec.finalize()

                print(shannon_entropy(ext["hmac-secret"]))
                if len(salt_list) == 1:
                    assert shannon_entropy(ext["hmac-secret"]) > 4.6
                    assert shannon_entropy(key) > 4.6
                if len(salt_list) == 2:
                    assert shannon_entropy(ext["hmac-secret"]) > 5.4
                    assert shannon_entropy(key) > 5.4

        salt_enc, salt_auth = get_salt_params((salt3, ))

        auth = self.testGA(
            "Send GA request with hmac-secret missing keyAgreement, expect error",
            rp["id"],
            cdh,
            other={"extensions": {
                "hmac-secret": {
                    2: salt_enc,
                    3: salt_auth
                }
            }},
        )
        auth = self.testGA(
            "Send GA request with hmac-secret missing saltAuth, expect MISSING_PARAMETER",
            rp["id"],
            cdh,
            other={
                "extensions": {
                    "hmac-secret": {
                        1: key_agreement,
                        2: salt_enc
                    }
                }
            },
            expectedError=CtapError.ERR.MISSING_PARAMETER,
        )
        auth = self.testGA(
            "Send GA request with hmac-secret missing saltEnc, expect MISSING_PARAMETER",
            rp["id"],
            cdh,
            other={
                "extensions": {
                    "hmac-secret": {
                        1: key_agreement,
                        3: salt_auth
                    }
                }
            },
            expectedError=CtapError.ERR.MISSING_PARAMETER,
        )

        bad_auth = list(salt_auth[:])
        bad_auth[len(bad_auth) // 2] = bad_auth[len(bad_auth) // 2] ^ 1
        bad_auth = bytes(bad_auth)

        auth = self.testGA(
            "Send GA request with hmac-secret containing bad saltAuth, expect EXTENSION_FIRST",
            rp["id"],
            cdh,
            other={
                "extensions": {
                    "hmac-secret": {
                        1: key_agreement,
                        2: salt_enc,
                        3: bad_auth
                    }
                }
            },
            expectedError=CtapError.ERR.EXTENSION_FIRST,
        )

        salt4 = b"\x5a" * 16
        salt5 = b"\x96" * 64
        for salt_list in ((salt4, ), (salt4, salt5)):
            salt_enc, salt_auth = get_salt_params(salt_list)

            salt_auth = hmac_sha256(shared_secret, salt_enc)[:16]
            auth = self.testGA(
                "Send GA request with incorrect salt length %d, expect INVALID_LENGTH"
                % len(salt_enc),
                rp["id"],
                cdh,
                other={
                    "extensions": {
                        "hmac-secret": {
                            1: key_agreement,
                            2: salt_enc,
                            3: salt_auth
                        }
                    }
                },
                expectedError=CtapError.ERR.INVALID_LENGTH,
            )
Ejemplo n.º 14
0
Archivo: fido2.py Proyecto: utzig/solo
    def test_client_pin(self, ):
        pin1 = "1234567890"
        self.test_rk(pin1)

        # PinProtocolV1
        res = self.testCP(
            "Test getKeyAgreement, expect SUCCESS",
            pin_protocol,
            PinProtocolV1.CMD.GET_KEY_AGREEMENT,
            expectedError=CtapError.ERR.SUCCESS,
        )

        with Test("Test getKeyAgreement has appropriate fields"):
            key = res[1]
            assert "Is public key" and key[1] == 2
            assert "Is P256" and key[-1] == 1
            assert "Is ALG_ECDH_ES_HKDF_256" and key[3] == -25

            assert "Right key" and len(key[-3]) == 32 and isinstance(
                key[-3], bytes)

        with Test("Test setting a new pin"):
            pin2 = "qwertyuiop\x11\x22\x33\x00123"
            self.client.pin_protocol.change_pin(pin1, pin2)

        with Test("Test getting new pin_auth"):
            pin_token = self.client.pin_protocol.get_pin_token(pin2)
            pin_auth = hmac_sha256(pin_token, cdh)[:16]

        res_mc = self.testMC(
            "Send MC request with new pin auth",
            cdh,
            rp,
            user,
            key_params,
            other={
                "pin_auth": pin_auth,
                "pin_protocol": pin_protocol
            },
            expectedError=CtapError.ERR.SUCCESS,
        )

        with Test("Check UV flag is set"):
            assert res_mc.auth_data.flags & (1 << 2)

        res_ga = self.testGA(
            "Send GA request with pinAuth, expect SUCCESS",
            rp["id"],
            cdh,
            [{
                "type": "public-key",
                "id": res_mc.auth_data.credential_data.credential_id,
            }],
            other={
                "pin_auth": pin_auth,
                "pin_protocol": pin_protocol
            },
            expectedError=CtapError.ERR.SUCCESS,
        )

        with Test("Check UV flag is set"):
            assert res_ga.auth_data.flags & (1 << 2)

        res_ga = self.testGA(
            "Send GA request with no pinAuth, expect SUCCESS",
            rp["id"],
            cdh,
            [{
                "type": "public-key",
                "id": res_mc.auth_data.credential_data.credential_id,
            }],
            expectedError=CtapError.ERR.SUCCESS,
        )

        with Test("Check UV flag is NOT set"):
            assert not (res_ga.auth_data.flags & (1 << 2))

        self.testReset()

        with Test("Test sending zero-length pin_auth, expect PIN_NOT_SET"):
            self.testMC(
                "Send MC request with new pin auth",
                cdh,
                rp,
                user,
                key_params,
                other={
                    "pin_auth": b"",
                    "pin_protocol": pin_protocol
                },
                expectedError=CtapError.ERR.PIN_NOT_SET,
            )
            self.testGA(
                "Send MC request with new pin auth",
                rp["id"],
                cdh,
                other={
                    "pin_auth": b"",
                    "pin_protocol": pin_protocol
                },
                expectedError=CtapError.ERR.PIN_NOT_SET,
            )

        with Test("Setting pin code, expect SUCCESS"):
            self.client.pin_protocol.set_pin(pin1)

        with Test("Test sending zero-length pin_auth, expect PIN_INVALID"):
            self.testMC(
                "Send MC request with new pin auth",
                cdh,
                rp,
                user,
                key_params,
                other={
                    "pin_auth": b"",
                    "pin_protocol": pin_protocol
                },
                expectedError=CtapError.ERR.PIN_INVALID,
            )
            self.testGA(
                "Send MC request with new pin auth",
                rp["id"],
                cdh,
                other={
                    "pin_auth": b"",
                    "pin_protocol": pin_protocol
                },
                expectedError=CtapError.ERR.PIN_INVALID,
            )

        self.testReset()
        with Test("Setting pin code >63 bytes, expect POLICY_VIOLATION "):
            try:
                self.client.pin_protocol.set_pin("A" * 64)
                assert 0
            except CtapError as e:
                assert e.code == CtapError.ERR.PIN_POLICY_VIOLATION

        with Test("Get pin token when no pin is set, expect PIN_NOT_SET"):
            try:
                self.client.pin_protocol.get_pin_token(pin1)
                assert 0
            except CtapError as e:
                assert e.code == CtapError.ERR.PIN_NOT_SET

        with Test("Get change pin when no pin is set, expect PIN_NOT_SET"):
            try:
                self.client.pin_protocol.change_pin(pin1, "1234")
                assert 0
            except CtapError as e:
                assert e.code == CtapError.ERR.PIN_NOT_SET

        with Test("Setting pin code and get pin_token, expect SUCCESS"):
            self.client.pin_protocol.set_pin(pin1)
            pin_token = self.client.pin_protocol.get_pin_token(pin1)
            pin_auth = hmac_sha256(pin_token, cdh)[:16]

        with Test("Get info and assert that clientPin is set to true"):
            info = self.ctap.get_info()
            assert info.options["clientPin"]

        with Test("Test setting pin again fails"):
            try:
                self.client.pin_protocol.set_pin(pin1)
                assert 0
            except CtapError as e:
                print(e)

        res_mc = self.testMC(
            "Send MC request with no pin_auth, expect PIN_REQUIRED",
            cdh,
            rp,
            user,
            key_params,
            expectedError=CtapError.ERR.PIN_REQUIRED,
        )

        res_mc = self.testGA(
            "Send GA request with no pin_auth, expect NO_CREDENTIALS",
            rp["id"],
            cdh,
            expectedError=CtapError.ERR.NO_CREDENTIALS,
        )

        res = self.testCP(
            "Test getRetries, expect SUCCESS",
            pin_protocol,
            PinProtocolV1.CMD.GET_RETRIES,
            expectedError=CtapError.ERR.SUCCESS,
        )

        with Test("Check there is 8 pin attempts left"):
            assert res[3] == 8

        # Flip 1 bit
        pin_wrong = list(pin1)
        c = pin1[len(pin1) // 2]

        pin_wrong[len(pin1) // 2] = chr(ord(c) ^ 1)
        pin_wrong = "".join(pin_wrong)

        for i in range(1, 3):
            self.testPP(
                "Get pin_token with wrong pin code, expect PIN_INVALID (%d/2)"
                % i,
                pin_wrong,
                expectedError=CtapError.ERR.PIN_INVALID,
            )
            print("Check there is %d pin attempts left" % (8 - i))
            res = self.ctap.client_pin(pin_protocol,
                                       PinProtocolV1.CMD.GET_RETRIES)
            assert res[3] == (8 - i)
            print("Pass")

        for i in range(1, 3):
            self.testPP(
                "Get pin_token with wrong pin code, expect PIN_AUTH_BLOCKED %d/2"
                % i,
                pin_wrong,
                expectedError=CtapError.ERR.PIN_AUTH_BLOCKED,
            )

        self.reboot()

        with Test("Get pin_token, expect SUCCESS"):
            pin_token = self.client.pin_protocol.get_pin_token(pin1)
            pin_auth = hmac_sha256(pin_token, cdh)[:16]

        res_mc = self.testMC(
            "Send MC request with correct pin_auth",
            cdh,
            rp,
            user,
            key_params,
            other={
                "pin_auth": pin_auth,
                "pin_protocol": pin_protocol
            },
            expectedError=CtapError.ERR.SUCCESS,
        )

        with Test("Test getRetries resets to 8"):
            res = self.ctap.client_pin(pin_protocol,
                                       PinProtocolV1.CMD.GET_RETRIES)
            assert res[3] == (8)

        for i in range(1, 10):
            err = CtapError.ERR.PIN_INVALID
            if i in (3, 6):
                err = CtapError.ERR.PIN_AUTH_BLOCKED
            elif i >= 8:
                err = [CtapError.ERR.PIN_BLOCKED, CtapError.ERR.PIN_INVALID]
            self.testPP(
                "Lock out authentictor and check correct error codes %d/9" % i,
                pin_wrong,
                expectedError=err,
            )

            attempts = 8 - i
            if i > 8:
                attempts = 0

            with Test("Check there is %d pin attempts left" % attempts):
                res = self.ctap.client_pin(pin_protocol,
                                           PinProtocolV1.CMD.GET_RETRIES)
                assert res[3] == attempts

            if err == CtapError.ERR.PIN_AUTH_BLOCKED:
                self.reboot()

        res_mc = self.testMC(
            "Send MC request with correct pin_auth, expect error",
            cdh,
            rp,
            user,
            key_params,
            other={
                "pin_auth": pin_auth,
                "pin_protocol": pin_protocol
            },
        )

        self.reboot()

        self.testPP(
            "Get pin_token with correct pin code, expect PIN_BLOCKED",
            pin1,
            expectedError=CtapError.ERR.PIN_BLOCKED,
        )
Ejemplo n.º 15
0
Archivo: fido2.py Proyecto: utzig/solo
    def test_rk(self, pin_code=None):

        pin_auth = None
        if pin_code:
            pin_protocol = 1
        else:
            pin_protocol = None
        if pin_code:
            with Test("Set pin code"):
                self.client.pin_protocol.set_pin(pin_code)
                pin_token = self.client.pin_protocol.get_pin_token(pin_code)
                pin_auth = hmac_sha256(pin_token, cdh)[:16]

        self.testMC(
            "Send MC request with rk option set to true, expect SUCCESS",
            cdh,
            rp,
            user,
            key_params,
            other={
                "options": {
                    "rk": True
                },
                "pin_auth": pin_auth,
                "pin_protocol": pin_protocol,
            },
            expectedError=CtapError.ERR.SUCCESS,
        )

        with Test("Get info"):
            info = self.ctap.get_info()

        options = {"rk": True}
        if "uv" in info.options and info.options["uv"]:
            options["uv"] = False

        for i, x in enumerate([user1, user2, user3]):
            self.testMC(
                "Send MC request with rk option set to true, expect SUCCESS %d/3"
                % (i + 1),
                cdh,
                rp2,
                x,
                key_params,
                other={
                    "options": options,
                    "pin_auth": pin_auth,
                    "pin_protocol": pin_protocol,
                },
                expectedError=CtapError.ERR.SUCCESS,
            )

        auth1 = self.testGA(
            "Send GA request with no allow_list, expect SUCCESS",
            rp2["id"],
            cdh,
            other={
                "pin_auth": pin_auth,
                "pin_protocol": pin_protocol
            },
            expectedError=CtapError.ERR.SUCCESS,
        )

        with Test("Check that there are 3 credentials returned"):
            assert auth1.number_of_credentials == 3

        with Test("Get the next 2 assertions"):
            auth2 = self.ctap.get_next_assertion()
            auth3 = self.ctap.get_next_assertion()

        if not pin_code:
            with Test("Check only the user ID was returned"):
                assert "id" in auth1.user.keys() and len(
                    auth1.user.keys()) == 1
                assert "id" in auth2.user.keys() and len(
                    auth2.user.keys()) == 1
                assert "id" in auth3.user.keys() and len(
                    auth3.user.keys()) == 1
        else:
            with Test("Check that all user info was returned"):
                for x in (auth1, auth2, auth3):
                    for y in ("name", "icon", "displayName", "id"):
                        if y not in x.user.keys():
                            print("FAIL: %s was not in user: "******"Send an extra getNextAssertion request, expect error"):
            try:
                self.ctap.get_next_assertion()
                assert 0
            except CtapError as e:
                print(e)