From 5076af1be4f0ddfefcec80123e5ca99238711d09 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Fri, 22 Mar 2019 01:22:55 -0400 Subject: [PATCH] works with yubikey5 --- tools/testing/main.py | 9 --- tools/testing/tests/fido2.py | 139 +++++++++++----------------------- tools/testing/tests/hid.py | 7 ++ tools/testing/tests/tester.py | 9 ++- 4 files changed, 60 insertions(+), 104 deletions(-) diff --git a/tools/testing/main.py b/tools/testing/main.py index 37c1e06..7e105e0 100644 --- a/tools/testing/main.py +++ b/tools/testing/main.py @@ -43,15 +43,6 @@ if __name__ == "__main__": # t.test_fido2() FIDO2Tests(t).run() - if "fido2-ext" in sys.argv: - pass - - if "rk" in sys.argv: - pass - - if "ping" in sys.argv: - pass - # hid tests are a bit invasive and should be done last if "hid" in sys.argv: HIDTests(t).run() diff --git a/tools/testing/tests/fido2.py b/tools/testing/tests/fido2.py index 2838e78..ac50378 100644 --- a/tools/testing/tests/fido2.py +++ b/tools/testing/tests/fido2.py @@ -8,7 +8,7 @@ import array, struct, socket from fido2.ctap import CtapError from fido2.ctap2 import ES256, PinProtocolV1 -from fido2.utils import Timeout, sha256, hmac_sha256 +from fido2.utils import sha256, hmac_sha256 from fido2.attestation import Attestation from cryptography.hazmat.backends import default_backend @@ -825,6 +825,10 @@ class FIDO2Tests(Tester): 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) @@ -837,7 +841,11 @@ class FIDO2Tests(Tester): rp, user, key_params, - other={"options": {"rk": True}, "pin_auth": pin_auth}, + other={ + "options": {"rk": True}, + "pin_auth": pin_auth, + "pin_protocol": pin_protocol, + }, expectedError=CtapError.ERR.SUCCESS, ) @@ -856,7 +864,11 @@ class FIDO2Tests(Tester): rp2, x, key_params, - other={"options": options, "pin_auth": pin_auth}, + other={ + "options": options, + "pin_auth": pin_auth, + "pin_protocol": pin_protocol, + }, expectedError=CtapError.ERR.SUCCESS, ) @@ -864,7 +876,7 @@ class FIDO2Tests(Tester): "Send GA request with no allow_list, expect SUCCESS", rp2["id"], cdh, - other={"options": options, "pin_auth": pin_auth}, + other={"pin_auth": pin_auth, "pin_protocol": pin_protocol}, expectedError=CtapError.ERR.SUCCESS, ) @@ -884,8 +896,8 @@ class FIDO2Tests(Tester): with Test("Check that all user info was returned"): for x in (auth1, auth2, auth3): for y in ("name", "icon", "displayName", "id"): - assert y in x.user.keys() - assert len(x.user.keys()) == 4 + if y not in x.user.keys(): + print("FAIL: %s was not in user: " % y, x.user) with Test("Send an extra getNextAssertion request, expect error"): try: @@ -910,7 +922,8 @@ class FIDO2Tests(Tester): key = res[1] assert "Is public key" and key[1] == 2 assert "Is P256" and key[-1] == 1 - assert "Is right alg" and key[3] == -7 + if key[3] != -7: + print("WARNING: algorithm returned is not for ES256 (-7): ", key[3]) assert "Right key" and len(key[-3]) == 32 and type(key[-3]) == type(bytes()) with Test("Test setting a new pin"): @@ -927,7 +940,7 @@ class FIDO2Tests(Tester): rp, user, key_params, - other={"pin_auth": pin_auth}, + other={"pin_auth": pin_auth, "pin_protocol": pin_protocol}, expectedError=CtapError.ERR.SUCCESS, ) @@ -935,7 +948,21 @@ class FIDO2Tests(Tester): assert res_mc.auth_data.flags & (1 << 2) res_ga = self.testGA( - "Send GA request with no allow_list, expect SUCCESS", + "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, + ) + + self.testGA( + "Send GA request with no pinAuth, expect SUCCESS", rp["id"], cdh, [ @@ -944,7 +971,6 @@ class FIDO2Tests(Tester): "id": res_mc.auth_data.credential_data.credential_id, } ], - other={"pin_auth": pin_auth}, expectedError=CtapError.ERR.SUCCESS, ) @@ -1004,10 +1030,10 @@ class FIDO2Tests(Tester): ) res_mc = self.testGA( - "Send GA request with no pin_auth, expect PIN_REQUIRED", + "Send GA request with no pin_auth, expect NO_CREDENTIALS", rp["id"], cdh, - expectedError=CtapError.ERR.PIN_REQUIRED, + expectedError=CtapError.ERR.NO_CREDENTIALS, ) res = self.testCP( @@ -1057,7 +1083,7 @@ class FIDO2Tests(Tester): rp, user, key_params, - other={"pin_auth": pin_auth}, + other={"pin_auth": pin_auth, "pin_protocol": pin_protocol}, expectedError=CtapError.ERR.SUCCESS, ) @@ -1069,8 +1095,8 @@ class FIDO2Tests(Tester): err = CtapError.ERR.PIN_INVALID if i in (3, 6): err = CtapError.ERR.PIN_AUTH_BLOCKED - elif i >= 9: - err = CtapError.ERR.PIN_BLOCKED + elif i >= 8: + err = [CtapError.ERR.PIN_BLOCKED, CtapError.ERR.PIN_AUTH_BLOCKED] self.testPP( "Lock out authentictor and check correct error codes %d/9" % i, pin_wrong, @@ -1089,13 +1115,12 @@ class FIDO2Tests(Tester): self.reboot() res_mc = self.testMC( - "Send MC request with correct pin_auth, expect PIN_BLOCKED", + "Send MC request with correct pin_auth, expect error", cdh, rp, user, key_params, - other={"pin_auth": pin_auth}, - expectedError=CtapError.ERR.PIN_BLOCKED, + other={"pin_auth": pin_auth, "pin_protocol": pin_protocol}, ) self.reboot() @@ -1108,8 +1133,7 @@ class FIDO2Tests(Tester): def test_fido2(self,): - creds = [] - exclude_list = [] + self.testReset() self.test_get_info() @@ -1123,77 +1147,6 @@ class FIDO2Tests(Tester): self.testReset() - print("Done") + self.test_extensions() - # def test_rk(self,): - # creds = [] - # rp = {"id": self.host, "name": "ExaRP"} - # - # users = [ - # {"id": b"user" + os.urandom(16), "name": "Username%d" % i} - # for i in range(0, self.user_count) - # ] - # challenge = "Y2hhbGxlbmdl" - # PIN = None - # self.ctap.reset() - # # if PIN: self.client.pin_protocol.set_pin(PIN) - # - # with Test("registering 1 user with RK"): - # t1 = time.time() * 1000 - # attest, data = self.client.make_credential( - # rp, users[-1], challenge, pin=PIN, exclude_list=[], rk=True - # ) - # t2 = time.time() * 1000 - # VerifyAttestation(attest, data) - # creds.append(attest.auth_data.credential_data) - # - # with Test("1 assertion"): - # t1 = time.time() * 1000 - # assertions, client_data = self.client.get_assertion( - # rp["id"], challenge, pin=PIN - # ) - # t2 = time.time() * 1000 - # assertions[0].verify(client_data.hash, creds[0].public_key) - # - # with Test("registering %d users with RK" % len(users)): - # for i in range(0, len(users) - 1): - # t1 = time.time() * 1000 - # attest, data = self.client.make_credential( - # rp, users[i], challenge, pin=PIN, exclude_list=[], rk=True - # ) - # t2 = time.time() * 1000 - # VerifyAttestation(attest, data) - # creds.append(attest.auth_data.credential_data) - # - # t1 = time.time() * 1000 - # assertions, client_data = self.client.get_assertion( - # rp["id"], challenge, pin=PIN - # ) - # t2 = time.time() * 1000 - # - # print("Got %d assertions for %d users" % (len(assertions), len(users))) - # assert len(assertions) == len(users) - # - # for x, y in zip(assertions, creds): - # x.verify(client_data.hash, y.public_key) - # - # print("Assertion(s) valid (%d ms)" % (t2 - t1)) - # - # with Test("register a duplicate user "): - # t1 = time.time() * 1000 - # attest, data = self.client.make_credential( - # rp, users[1], challenge, pin=PIN, exclude_list=[], rk=True - # ) - # t2 = time.time() * 1000 - # VerifyAttestation(attest, data) - # creds = creds[:2] + creds[3:] + [attest.auth_data.credential_data] - # - # t1 = time.time() * 1000 - # assertions, client_data = self.client.get_assertion( - # rp["id"], challenge, pin=PIN - # ) - # t2 = time.time() * 1000 - # with Test("check %d assertions, %d users" % (len(assertions), len(users))): - # assert len(assertions) == len(users) - # for x, y in zip(assertions, creds): - # x.verify(client_data.hash, y.public_key) + print("Done") diff --git a/tools/testing/tests/hid.py b/tools/testing/tests/hid.py index 89a9e70..4ad3f6c 100644 --- a/tools/testing/tests/hid.py +++ b/tools/testing/tests/hid.py @@ -1,3 +1,9 @@ +import sys, struct, os, time +from binascii import hexlify + +from fido2.hid import CtapHidDevice, CTAPHID +from fido2.ctap import CtapError + from .tester import Tester, Test @@ -10,6 +16,7 @@ class HIDTests(Tester): self.check_timeouts = en def run(self,): + self.test_long_ping() self.test_hid(self.check_timeouts) def test_long_ping(self): diff --git a/tools/testing/tests/tester.py b/tools/testing/tests/tester.py index 271f657..0cce014 100644 --- a/tools/testing/tests/tester.py +++ b/tools/testing/tests/tester.py @@ -1,8 +1,10 @@ -import time +import time, struct from fido2.hid import CtapHidDevice, CTAPHID from fido2.client import Fido2Client, ClientError from fido2.ctap1 import CTAP1, ApduError, APDU +from fido2.utils import Timeout + from fido2.ctap import CtapError @@ -153,7 +155,10 @@ class Tester: raise RuntimeError("Expected error to occur for test: %s" % test) except CtapError as e: if expectedError is not None: - if e.code != expectedError: + cond = e.code != expectedError + if type(expectedError) == type([]): + cond = e.code not in expectedError + if cond: raise RuntimeError( "Got error code 0x%x, expected %x" % (e.code, expectedError) )