works with yubikey5

This commit is contained in:
Conor Patrick 2019-03-22 01:22:55 -04:00
parent 0a7845459c
commit 5076af1be4
4 changed files with 60 additions and 104 deletions

View File

@ -43,15 +43,6 @@ if __name__ == "__main__":
# t.test_fido2() # t.test_fido2()
FIDO2Tests(t).run() 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 # hid tests are a bit invasive and should be done last
if "hid" in sys.argv: if "hid" in sys.argv:
HIDTests(t).run() HIDTests(t).run()

View File

@ -8,7 +8,7 @@ import array, struct, socket
from fido2.ctap import CtapError from fido2.ctap import CtapError
from fido2.ctap2 import ES256, PinProtocolV1 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 fido2.attestation import Attestation
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
@ -825,6 +825,10 @@ class FIDO2Tests(Tester):
def test_rk(self, pin_code=None): def test_rk(self, pin_code=None):
pin_auth = None pin_auth = None
if pin_code:
pin_protocol = 1
else:
pin_protocol = None
if pin_code: if pin_code:
with Test("Set pin code"): with Test("Set pin code"):
self.client.pin_protocol.set_pin(pin_code) self.client.pin_protocol.set_pin(pin_code)
@ -837,7 +841,11 @@ class FIDO2Tests(Tester):
rp, rp,
user, user,
key_params, 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, expectedError=CtapError.ERR.SUCCESS,
) )
@ -856,7 +864,11 @@ class FIDO2Tests(Tester):
rp2, rp2,
x, x,
key_params, key_params,
other={"options": options, "pin_auth": pin_auth}, other={
"options": options,
"pin_auth": pin_auth,
"pin_protocol": pin_protocol,
},
expectedError=CtapError.ERR.SUCCESS, expectedError=CtapError.ERR.SUCCESS,
) )
@ -864,7 +876,7 @@ class FIDO2Tests(Tester):
"Send GA request with no allow_list, expect SUCCESS", "Send GA request with no allow_list, expect SUCCESS",
rp2["id"], rp2["id"],
cdh, cdh,
other={"options": options, "pin_auth": pin_auth}, other={"pin_auth": pin_auth, "pin_protocol": pin_protocol},
expectedError=CtapError.ERR.SUCCESS, expectedError=CtapError.ERR.SUCCESS,
) )
@ -884,8 +896,8 @@ class FIDO2Tests(Tester):
with Test("Check that all user info was returned"): with Test("Check that all user info was returned"):
for x in (auth1, auth2, auth3): for x in (auth1, auth2, auth3):
for y in ("name", "icon", "displayName", "id"): for y in ("name", "icon", "displayName", "id"):
assert y in x.user.keys() if y not in x.user.keys():
assert len(x.user.keys()) == 4 print("FAIL: %s was not in user: " % y, x.user)
with Test("Send an extra getNextAssertion request, expect error"): with Test("Send an extra getNextAssertion request, expect error"):
try: try:
@ -910,7 +922,8 @@ class FIDO2Tests(Tester):
key = res[1] key = res[1]
assert "Is public key" and key[1] == 2 assert "Is public key" and key[1] == 2
assert "Is P256" and key[-1] == 1 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()) assert "Right key" and len(key[-3]) == 32 and type(key[-3]) == type(bytes())
with Test("Test setting a new pin"): with Test("Test setting a new pin"):
@ -927,7 +940,7 @@ class FIDO2Tests(Tester):
rp, rp,
user, user,
key_params, key_params,
other={"pin_auth": pin_auth}, other={"pin_auth": pin_auth, "pin_protocol": pin_protocol},
expectedError=CtapError.ERR.SUCCESS, expectedError=CtapError.ERR.SUCCESS,
) )
@ -935,7 +948,21 @@ class FIDO2Tests(Tester):
assert res_mc.auth_data.flags & (1 << 2) assert res_mc.auth_data.flags & (1 << 2)
res_ga = self.testGA( 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"], rp["id"],
cdh, cdh,
[ [
@ -944,7 +971,6 @@ class FIDO2Tests(Tester):
"id": res_mc.auth_data.credential_data.credential_id, "id": res_mc.auth_data.credential_data.credential_id,
} }
], ],
other={"pin_auth": pin_auth},
expectedError=CtapError.ERR.SUCCESS, expectedError=CtapError.ERR.SUCCESS,
) )
@ -1004,10 +1030,10 @@ class FIDO2Tests(Tester):
) )
res_mc = self.testGA( 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"], rp["id"],
cdh, cdh,
expectedError=CtapError.ERR.PIN_REQUIRED, expectedError=CtapError.ERR.NO_CREDENTIALS,
) )
res = self.testCP( res = self.testCP(
@ -1057,7 +1083,7 @@ class FIDO2Tests(Tester):
rp, rp,
user, user,
key_params, key_params,
other={"pin_auth": pin_auth}, other={"pin_auth": pin_auth, "pin_protocol": pin_protocol},
expectedError=CtapError.ERR.SUCCESS, expectedError=CtapError.ERR.SUCCESS,
) )
@ -1069,8 +1095,8 @@ class FIDO2Tests(Tester):
err = CtapError.ERR.PIN_INVALID err = CtapError.ERR.PIN_INVALID
if i in (3, 6): if i in (3, 6):
err = CtapError.ERR.PIN_AUTH_BLOCKED err = CtapError.ERR.PIN_AUTH_BLOCKED
elif i >= 9: elif i >= 8:
err = CtapError.ERR.PIN_BLOCKED err = [CtapError.ERR.PIN_BLOCKED, CtapError.ERR.PIN_AUTH_BLOCKED]
self.testPP( self.testPP(
"Lock out authentictor and check correct error codes %d/9" % i, "Lock out authentictor and check correct error codes %d/9" % i,
pin_wrong, pin_wrong,
@ -1089,13 +1115,12 @@ class FIDO2Tests(Tester):
self.reboot() self.reboot()
res_mc = self.testMC( res_mc = self.testMC(
"Send MC request with correct pin_auth, expect PIN_BLOCKED", "Send MC request with correct pin_auth, expect error",
cdh, cdh,
rp, rp,
user, user,
key_params, key_params,
other={"pin_auth": pin_auth}, other={"pin_auth": pin_auth, "pin_protocol": pin_protocol},
expectedError=CtapError.ERR.PIN_BLOCKED,
) )
self.reboot() self.reboot()
@ -1108,8 +1133,7 @@ class FIDO2Tests(Tester):
def test_fido2(self,): def test_fido2(self,):
creds = [] self.testReset()
exclude_list = []
self.test_get_info() self.test_get_info()
@ -1123,77 +1147,6 @@ class FIDO2Tests(Tester):
self.testReset() self.testReset()
print("Done") self.test_extensions()
# def test_rk(self,): print("Done")
# 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)

View File

@ -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 from .tester import Tester, Test
@ -10,6 +16,7 @@ class HIDTests(Tester):
self.check_timeouts = en self.check_timeouts = en
def run(self,): def run(self,):
self.test_long_ping()
self.test_hid(self.check_timeouts) self.test_hid(self.check_timeouts)
def test_long_ping(self): def test_long_ping(self):

View File

@ -1,8 +1,10 @@
import time import time, struct
from fido2.hid import CtapHidDevice, CTAPHID from fido2.hid import CtapHidDevice, CTAPHID
from fido2.client import Fido2Client, ClientError from fido2.client import Fido2Client, ClientError
from fido2.ctap1 import CTAP1, ApduError, APDU from fido2.ctap1 import CTAP1, ApduError, APDU
from fido2.utils import Timeout
from fido2.ctap import CtapError from fido2.ctap import CtapError
@ -153,7 +155,10 @@ class Tester:
raise RuntimeError("Expected error to occur for test: %s" % test) raise RuntimeError("Expected error to occur for test: %s" % test)
except CtapError as e: except CtapError as e:
if expectedError is not None: 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( raise RuntimeError(
"Got error code 0x%x, expected %x" % (e.code, expectedError) "Got error code 0x%x, expected %x" % (e.code, expectedError)
) )