breakup test_fido2

This commit is contained in:
Conor Patrick 2019-03-22 00:45:28 -04:00
parent c4262b0f5b
commit 0a7845459c
2 changed files with 275 additions and 417 deletions

View File

@ -17,6 +17,17 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from .tester import Tester, Test from .tester import Tester, Test
from .util import shannon_entropy from .util import shannon_entropy
rp = {"id": "examplo.org", "name": "ExaRP"}
rp2 = {"id": "solokeys.com", "name": "ExaRP"}
user = {"id": b"usee_od", "name": "AB User"}
user1 = {"id": b"1234567890", "name": "Conor Patrick"}
user2 = {"id": b"oiewhfoi", "name": "Han Solo"}
user3 = {"id": b"23ohfpjwo@@", "name": "John Smith"}
challenge = "Y2hhbGxlbmdl"
pin_protocol = 1
key_params = [{"type": "public-key", "alg": ES256.ALGORITHM}]
cdh = b"123456789abcdef0123456789abcdef0"
def VerifyAttestation(attest, data): def VerifyAttestation(attest, data):
verifier = Attestation.for_type(attest.fmt) verifier = Attestation.for_type(attest.fmt)
@ -28,14 +39,11 @@ class FIDO2Tests(Tester):
super().__init__(tester) super().__init__(tester)
def run(self,): def run(self,):
self.test_fido2_other() self.test_fido2()
def test_fido2_simple(self, pin_token=None): def test_fido2_simple(self, pin_token=None):
creds = [] creds = []
exclude_list = [] exclude_list = []
rp = {"id": self.host, "name": "ExaRP"}
user = {"id": b"usee_od", "name": "AB User"}
challenge = "Y2hhbGxlbmdl"
PIN = pin_token PIN = pin_token
fake_id1 = array.array("B", [randint(0, 255) for i in range(0, 150)]).tobytes() fake_id1 = array.array("B", [randint(0, 255) for i in range(0, 150)]).tobytes()
@ -68,8 +76,6 @@ class FIDO2Tests(Tester):
def test_fido2_brute_force(self): def test_fido2_brute_force(self):
creds = [] creds = []
exclude_list = [] exclude_list = []
rp = {"id": self.host, "name": "ExaRP"}
user = {"id": b"usee_od", "name": "AB User"}
PIN = None PIN = None
abc = "abcdefghijklnmopqrstuvwxyz" abc = "abcdefghijklnmopqrstuvwxyz"
abc += abc.upper() abc += abc.upper()
@ -120,172 +126,9 @@ class FIDO2Tests(Tester):
print("Assertion valid (%d ms)" % (t2 - t1)) print("Assertion valid (%d ms)" % (t2 - t1))
sys.stdout.flush() sys.stdout.flush()
def test_fido2(self):
def test(self, pincode=None):
creds = []
exclude_list = []
rp = {"id": self.host, "name": "ExaRP"}
user = {"id": b"usee_od", "name": "AB User"}
challenge = "Y2hhbGxlbmdl"
PIN = pincode
fake_id1 = array.array(
"B", [randint(0, 255) for i in range(0, 150)]
).tobytes()
fake_id2 = array.array(
"B", [randint(0, 255) for i in range(0, 73)]
).tobytes()
exclude_list.append({"id": fake_id1, "type": "public-key"})
exclude_list.append({"id": fake_id2, "type": "public-key"})
# test make credential
with Test("make %d credentials" % self.user_count):
lastc = 0
for i in range(0, self.user_count):
attest, data = self.client.make_credential(
rp, user, challenge, pin=PIN, exclude_list=[]
)
VerifyAttestation(attest, data)
# verify counter is correct
if lastc > 0:
assert attest.auth_data.counter - lastc < 10
assert attest.auth_data.counter - lastc > 0
assert attest.auth_data.counter < 0x10000
lastc = attest.auth_data.counter
cred = attest.auth_data.credential_data
creds.append(cred)
print(cred)
if PIN is not None:
with Test("make credential with wrong pin code"):
try:
attest, data = self.client.make_credential(
rp, user, challenge, pin=PIN + " ", exclude_list=[]
)
except CtapError as e:
assert e.code == CtapError.ERR.PIN_INVALID
except ClientError as e:
assert e.cause.code == CtapError.ERR.PIN_INVALID
with Test("make credential with exclude list"):
attest, data = self.client.make_credential(
rp, user, challenge, pin=PIN, exclude_list=exclude_list
)
VerifyAttestation(attest, data)
cred = attest.auth_data.credential_data
creds.append(cred)
with Test("make credential with exclude list including real credential"):
real_excl = [{"id": cred.credential_id, "type": "public-key"}]
try:
attest, data = self.client.make_credential(
rp,
user,
challenge,
pin=PIN,
exclude_list=exclude_list + real_excl,
)
raise RuntimeError("Exclude list did not return expected error")
except CtapError as e:
assert e.code == CtapError.ERR.CREDENTIAL_EXCLUDED
except ClientError as e:
assert e.cause.code == CtapError.ERR.CREDENTIAL_EXCLUDED
for i, x in enumerate(creds):
with Test("get assertion %d" % i):
allow_list = [{"id": x.credential_id, "type": "public-key"}]
assertions, client_data = self.client.get_assertion(
rp["id"], challenge, allow_list, pin=PIN
)
assertions[0].verify(client_data.hash, x.public_key)
if PIN is not None:
with Test("get assertion with wrong pin code"):
try:
assertions, client_data = self.client.get_assertion(
rp["id"], challenge, allow_list, pin=PIN + " "
)
except CtapError as e:
assert e.code == CtapError.ERR.PIN_INVALID
except ClientError as e:
assert e.cause.code == CtapError.ERR.PIN_INVALID
with Test("get multiple assertions"):
allow_list = [
{"id": x.credential_id, "type": "public-key"} for x in creds
]
assertions, client_data = self.client.get_assertion(
rp["id"], challenge, allow_list, pin=PIN
)
for ass, cred in zip(assertions, creds):
i += 1
ass.verify(client_data.hash, cred.public_key)
print("%d verified" % i)
with Test("Reset device"):
try:
self.ctap.reset()
except CtapError as e:
print("Warning, reset failed: ", e)
pass
test(self, None)
with Test("Set a pin code"):
PIN = "1122aabbwfg0h9g !@#=="
self.client.pin_protocol.set_pin(PIN)
with Test("Illegally set pin code again"):
try:
self.client.pin_protocol.set_pin(PIN)
except CtapError as e:
assert e.code == CtapError.ERR.NOT_ALLOWED
with Test("Change pin code"):
PIN2 = PIN + "_pin2"
self.client.pin_protocol.change_pin(PIN, PIN2)
PIN = PIN2
with Test("Change pin code using wrong pin"):
try:
self.client.pin_protocol.change_pin(PIN.replace("a", "b"), "1234")
except CtapError as e:
assert e.code == CtapError.ERR.PIN_INVALID
with Test("MC using wrong pin"):
try:
self.test_fido2_simple("abcd3")
except ClientError as e:
assert e.cause.code == CtapError.ERR.PIN_INVALID
with Test("get info"):
inf = self.ctap.get_info()
self.test_fido2_simple(PIN)
with Test("Re-run make_credential and get_assertion tests with pin code"):
test(self, PIN)
with Test("Reset device"):
try:
self.ctap.reset()
except CtapError as e:
print("Warning, reset failed: ", e)
def test_extensions(self,): def test_extensions(self,):
creds = [] creds = []
exclude_list = [] exclude_list = []
rp = {"id": self.host, "name": "ExaRP"}
user = {"id": b"usee_od", "name": "AB User"}
challenge = "Y2hhbGxlbmdl"
pin_protocol = 1
key_params = [{"type": "public-key", "alg": ES256.ALGORITHM}]
cdh = b"123456789abcdef0123456789abcdef0"
salt1 = b"\x5a" * 32 salt1 = b"\x5a" * 32
salt2 = b"\x96" * 32 salt2 = b"\x96" * 32
@ -439,33 +282,7 @@ class FIDO2Tests(Tester):
expectedError=CtapError.ERR.INVALID_LENGTH, expectedError=CtapError.ERR.INVALID_LENGTH,
) )
def test_fido2_other(self,): def test_get_info(self,):
creds = []
exclude_list = []
rp = {"id": self.host, "name": "ExaRP"}
rp2 = {"id": "solokeys.com", "name": "ExaRP"}
user = {"id": b"usee_od", "name": "AB User"}
user1 = {"id": b"1234567890", "name": "Conor Patrick"}
user2 = {"id": b"oiewhfoi", "name": "Han Solo"}
user3 = {"id": b"23ohfpjwo@@", "name": "John Smith"}
challenge = "Y2hhbGxlbmdl"
pin_protocol = 1
key_params = [{"type": "public-key", "alg": ES256.ALGORITHM}]
cdh = b"123456789abcdef0123456789abcdef0"
def reboot():
if self.is_sim:
print("Sending restart command...")
self.send_magic_reboot()
self.delay(0.25)
else:
print("Please reboot authentictor and hit enter")
input()
self.find_device()
self.testReset()
with Test("Get info"): with Test("Get info"):
info = self.ctap.get_info() info = self.ctap.get_info()
@ -480,6 +297,31 @@ class FIDO2Tests(Tester):
for x in info.options: for x in info.options:
assert info.options[x] in [True, False] assert info.options[x] in [True, False]
if "uv" in info.options:
if info.options["uv"]:
self.testMC(
"Send MC request with uv set to true, expect SUCCESS",
cdh,
rp,
user,
key_params,
other={"options": {"uv": True}},
expectedError=CtapError.ERR.SUCCESS,
)
if "up" in info.options:
if info.options["up"]:
self.testMC(
"Send MC request with up set to true, expect INVALID_OPTION",
cdh,
rp,
user,
key_params,
other={"options": {"up": True}},
expectedError=CtapError.ERR.INVALID_OPTION,
)
def test_make_credential(self,):
prev_reg = self.testMC( prev_reg = self.testMC(
"Send MC request, expect success", "Send MC request, expect success",
cdh, cdh,
@ -488,61 +330,17 @@ class FIDO2Tests(Tester):
key_params, key_params,
expectedError=CtapError.ERR.SUCCESS, expectedError=CtapError.ERR.SUCCESS,
) )
with Test("Check attestation format is correct"):
assert prev_reg.fmt in ["packed", "tpm", "android-key", "adroid-safetynet"]
with Test("Check auth_data is at least 77 bytes"):
assert len(prev_reg.auth_data) >= 77
allow_list = [ allow_list = [
{ {
"id": prev_reg.auth_data.credential_data.credential_id, "id": prev_reg.auth_data.credential_data.credential_id,
"type": "public-key", "type": "public-key",
} }
] ]
with Test("Check attestation format is correct"):
assert prev_reg.fmt in ["packed", "tpm", "android-key", "adroid-safetynet"]
prev_auth = self.testGA( with Test("Check auth_data is at least 77 bytes"):
"Send GA request, expect success", assert len(prev_reg.auth_data) >= 77
rp["id"],
cdh,
allow_list,
expectedError=CtapError.ERR.SUCCESS,
)
with Test("Test auth_data is 37 bytes"):
assert len(prev_auth.auth_data) == 37
with Test("Test that auth_data.rpIdHash is correct"):
assert sha256(rp["id"].encode()) == prev_auth.auth_data.rp_id_hash
with Test("Check that AT flag is not set"):
assert (prev_auth.auth_data.flags & 0xF8) == 0
with Test("Test that user, credential and numberOfCredentials are not present"):
assert prev_auth.user == None
assert prev_auth.number_of_credentials == None
self.testGA(
"Send GA request with empty allow_list, expect NO_CREDENTIALS",
rp["id"],
cdh,
[],
expectedError=CtapError.ERR.NO_CREDENTIALS,
)
# apply bit flip
badid = list(prev_reg.auth_data.credential_data.credential_id[:])
badid[len(badid) // 2] = badid[len(badid) // 2] ^ 1
badid = bytes(badid)
self.testGA(
"Send GA request with corrupt credId in allow_list, expect NO_CREDENTIALS",
rp["id"],
cdh,
[{"id": badid, "type": "public-key"}],
expectedError=CtapError.ERR.NO_CREDENTIALS,
)
self.testMC( self.testMC(
"Send MC request with missing clientDataHash, expect error", "Send MC request with missing clientDataHash, expect error",
@ -836,28 +634,77 @@ class FIDO2Tests(Tester):
expectedError=CtapError.ERR.SUCCESS, expectedError=CtapError.ERR.SUCCESS,
) )
if "uv" in info.options: self.testReset()
if info.options["uv"]:
self.testMC( self.testGA(
"Send MC request with uv set to true, expect SUCCESS", "Send GA request with reset auth, expect NO_CREDENTIALS",
cdh, rp["id"],
rp, cdh,
user, allow_list,
key_params, expectedError=CtapError.ERR.NO_CREDENTIALS,
other={"options": {"uv": True}}, )
expectedError=CtapError.ERR.SUCCESS,
) def test_get_assertion(self,):
if "up" in info.options:
if info.options["up"]: self.testReset()
self.testMC(
"Send MC request with up set to true, expect INVALID_OPTION", prev_reg = self.testMC(
cdh, "Send MC request, expect success",
rp, cdh,
user, rp,
key_params, user,
other={"options": {"up": True}}, key_params,
expectedError=CtapError.ERR.INVALID_OPTION, expectedError=CtapError.ERR.SUCCESS,
) )
allow_list = [
{
"id": prev_reg.auth_data.credential_data.credential_id,
"type": "public-key",
}
]
prev_auth = self.testGA(
"Send GA request, expect success",
rp["id"],
cdh,
allow_list,
expectedError=CtapError.ERR.SUCCESS,
)
with Test("Test auth_data is 37 bytes"):
assert len(prev_auth.auth_data) == 37
with Test("Test that auth_data.rpIdHash is correct"):
assert sha256(rp["id"].encode()) == prev_auth.auth_data.rp_id_hash
with Test("Check that AT flag is not set"):
assert (prev_auth.auth_data.flags & 0xF8) == 0
with Test("Test that user, credential and numberOfCredentials are not present"):
assert prev_auth.user == None
assert prev_auth.number_of_credentials == None
self.testGA(
"Send GA request with empty allow_list, expect NO_CREDENTIALS",
rp["id"],
cdh,
[],
expectedError=CtapError.ERR.NO_CREDENTIALS,
)
# apply bit flip
badid = list(prev_reg.auth_data.credential_data.credential_id[:])
badid[len(badid) // 2] = badid[len(badid) // 2] ^ 1
badid = bytes(badid)
self.testGA(
"Send GA request with corrupt credId in allow_list, expect NO_CREDENTIALS",
rp["id"],
cdh,
[{"id": badid, "type": "public-key"}],
expectedError=CtapError.ERR.NO_CREDENTIALS,
)
self.testGA( self.testGA(
"Send GA request with missing RPID, expect MISSING_PARAMETER", "Send GA request with missing RPID, expect MISSING_PARAMETER",
@ -911,6 +758,8 @@ class FIDO2Tests(Tester):
other={"options": {"unknown": True}}, other={"options": {"unknown": True}},
expectedError=CtapError.ERR.SUCCESS, expectedError=CtapError.ERR.SUCCESS,
) )
with Test("Get info"):
info = self.ctap.get_info()
if "uv" in info.options: if "uv" in info.options:
if info.options["uv"]: if info.options["uv"]:
@ -973,89 +822,81 @@ class FIDO2Tests(Tester):
allow_list + [{"type": b"public-key"}], allow_list + [{"type": b"public-key"}],
) )
self.testReset() def test_rk(self, pin_code=None):
def testRk(pin_code=None): pin_auth = None
self.testGA( if pin_code:
"Send GA request with reset auth, expect NO_CREDENTIALS", with Test("Set pin code"):
rp["id"], self.client.pin_protocol.set_pin(pin_code)
cdh, pin_token = self.client.pin_protocol.get_pin_token(pin_code)
allow_list, pin_auth = hmac_sha256(pin_token, cdh)[:16]
expectedError=CtapError.ERR.NO_CREDENTIALS,
)
pin_auth = None self.testMC(
if pin_code: "Send MC request with rk option set to true, expect SUCCESS",
with Test("Set pin code"): cdh,
self.client.pin_protocol.set_pin(pin_code) rp,
pin_token = self.client.pin_protocol.get_pin_token(pin_code) user,
pin_auth = hmac_sha256(pin_token, cdh)[:16] key_params,
other={"options": {"rk": True}, "pin_auth": pin_auth},
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( self.testMC(
"Send MC request with rk option set to true, expect SUCCESS", "Send MC request with rk option set to true, expect SUCCESS %d/3"
% (i + 1),
cdh, cdh,
rp, rp2,
user, x,
key_params, key_params,
other={"options": {"rk": True}, "pin_auth": pin_auth},
expectedError=CtapError.ERR.SUCCESS,
)
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},
expectedError=CtapError.ERR.SUCCESS,
)
auth1 = self.testGA(
"Send GA request with no allow_list, expect SUCCESS",
rp2["id"],
cdh,
other={"options": options, "pin_auth": pin_auth}, other={"options": options, "pin_auth": pin_auth},
expectedError=CtapError.ERR.SUCCESS, expectedError=CtapError.ERR.SUCCESS,
) )
with Test("Check that there are 3 credentials returned"): auth1 = self.testGA(
assert auth1.number_of_credentials == 3 "Send GA request with no allow_list, expect SUCCESS",
rp2["id"],
cdh,
other={"options": options, "pin_auth": pin_auth},
expectedError=CtapError.ERR.SUCCESS,
)
with Test("Get the next 2 assertions"): with Test("Check that there are 3 credentials returned"):
auth2 = self.ctap.get_next_assertion() assert auth1.number_of_credentials == 3
auth3 = self.ctap.get_next_assertion()
if not pin_code: with Test("Get the next 2 assertions"):
with Test("Check only the user ID was returned"): auth2 = self.ctap.get_next_assertion()
assert "id" in auth1.user.keys() and len(auth1.user.keys()) == 1 auth3 = self.ctap.get_next_assertion()
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"):
assert y in x.user.keys()
assert len(x.user.keys()) == 4
with Test("Send an extra getNextAssertion request, expect error"): if not pin_code:
try: with Test("Check only the user ID was returned"):
auth4 = self.ctap.get_next_assertion() assert "id" in auth1.user.keys() and len(auth1.user.keys()) == 1
assert 0 assert "id" in auth2.user.keys() and len(auth2.user.keys()) == 1
except CtapError as e: assert "id" in auth3.user.keys() and len(auth3.user.keys()) == 1
print(e) else:
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
testRk(None) with Test("Send an extra getNextAssertion request, expect error"):
# try:
# print("Assuming authenticator does NOT have a display.") auth4 = self.ctap.get_next_assertion()
assert 0
except CtapError as e:
print(e)
def test_client_pin(self,):
pin1 = "1234567890" pin1 = "1234567890"
testRk("1234567890") self.test_rk(pin1)
# PinProtocolV1 # PinProtocolV1
res = self.testCP( res = self.testCP(
@ -1116,14 +957,6 @@ class FIDO2Tests(Tester):
self.client.pin_protocol.set_pin(pin1) self.client.pin_protocol.set_pin(pin1)
self.testReset() self.testReset()
# print("Setting pin code <4 bytes, expect POLICY_VIOLATION ")
# try:
# self.client.pin_protocol.set_pin("123")
# except CtapError as e:
# assert e.code == CtapError.ERR.POLICY_VIOLATION
# print("Pass")
with Test("Setting pin code >63 bytes, expect POLICY_VIOLATION "): with Test("Setting pin code >63 bytes, expect POLICY_VIOLATION "):
try: try:
self.client.pin_protocol.set_pin("A" * 64) self.client.pin_protocol.set_pin("A" * 64)
@ -1212,7 +1045,7 @@ class FIDO2Tests(Tester):
expectedError=CtapError.ERR.PIN_AUTH_BLOCKED, expectedError=CtapError.ERR.PIN_AUTH_BLOCKED,
) )
reboot() self.reboot()
with Test("Get pin_token, expect SUCCESS"): with Test("Get pin_token, expect SUCCESS"):
pin_token = self.client.pin_protocol.get_pin_token(pin1) pin_token = self.client.pin_protocol.get_pin_token(pin1)
@ -1253,7 +1086,7 @@ class FIDO2Tests(Tester):
assert res[3] == attempts assert res[3] == attempts
if err == CtapError.ERR.PIN_AUTH_BLOCKED: if err == CtapError.ERR.PIN_AUTH_BLOCKED:
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 PIN_BLOCKED",
@ -1265,7 +1098,7 @@ class FIDO2Tests(Tester):
expectedError=CtapError.ERR.PIN_BLOCKED, expectedError=CtapError.ERR.PIN_BLOCKED,
) )
reboot() self.reboot()
self.testPP( self.testPP(
"Get pin_token with correct pin code, expect PIN_BLOCKED", "Get pin_token with correct pin code, expect PIN_BLOCKED",
@ -1273,79 +1106,94 @@ class FIDO2Tests(Tester):
expectedError=CtapError.ERR.PIN_BLOCKED, expectedError=CtapError.ERR.PIN_BLOCKED,
) )
def test_fido2(self,):
creds = []
exclude_list = []
self.test_get_info()
self.test_get_assertion()
self.test_make_credential()
self.test_rk(None)
self.test_client_pin()
self.testReset() self.testReset()
print("Done") print("Done")
def test_rk(self,): # def test_rk(self,):
creds = [] # creds = []
rp = {"id": self.host, "name": "ExaRP"} # rp = {"id": self.host, "name": "ExaRP"}
#
users = [ # users = [
{"id": b"user" + os.urandom(16), "name": "Username%d" % i} # {"id": b"user" + os.urandom(16), "name": "Username%d" % i}
for i in range(0, self.user_count) # for i in range(0, self.user_count)
] # ]
challenge = "Y2hhbGxlbmdl" # challenge = "Y2hhbGxlbmdl"
PIN = None # PIN = None
self.ctap.reset() # self.ctap.reset()
# if PIN: self.client.pin_protocol.set_pin(PIN) # # if PIN: self.client.pin_protocol.set_pin(PIN)
#
with Test("registering 1 user with RK"): # with Test("registering 1 user with RK"):
t1 = time.time() * 1000 # t1 = time.time() * 1000
attest, data = self.client.make_credential( # attest, data = self.client.make_credential(
rp, users[-1], challenge, pin=PIN, exclude_list=[], rk=True # rp, users[-1], challenge, pin=PIN, exclude_list=[], rk=True
) # )
t2 = time.time() * 1000 # t2 = time.time() * 1000
VerifyAttestation(attest, data) # VerifyAttestation(attest, data)
creds.append(attest.auth_data.credential_data) # creds.append(attest.auth_data.credential_data)
#
with Test("1 assertion"): # with Test("1 assertion"):
t1 = time.time() * 1000 # t1 = time.time() * 1000
assertions, client_data = self.client.get_assertion( # assertions, client_data = self.client.get_assertion(
rp["id"], challenge, pin=PIN # rp["id"], challenge, pin=PIN
) # )
t2 = time.time() * 1000 # t2 = time.time() * 1000
assertions[0].verify(client_data.hash, creds[0].public_key) # assertions[0].verify(client_data.hash, creds[0].public_key)
#
with Test("registering %d users with RK" % len(users)): # with Test("registering %d users with RK" % len(users)):
for i in range(0, len(users) - 1): # for i in range(0, len(users) - 1):
t1 = time.time() * 1000 # t1 = time.time() * 1000
attest, data = self.client.make_credential( # attest, data = self.client.make_credential(
rp, users[i], challenge, pin=PIN, exclude_list=[], rk=True # rp, users[i], challenge, pin=PIN, exclude_list=[], rk=True
) # )
t2 = time.time() * 1000 # t2 = time.time() * 1000
VerifyAttestation(attest, data) # VerifyAttestation(attest, data)
creds.append(attest.auth_data.credential_data) # creds.append(attest.auth_data.credential_data)
#
t1 = time.time() * 1000 # t1 = time.time() * 1000
assertions, client_data = self.client.get_assertion( # assertions, client_data = self.client.get_assertion(
rp["id"], challenge, pin=PIN # rp["id"], challenge, pin=PIN
) # )
t2 = time.time() * 1000 # t2 = time.time() * 1000
#
print("Got %d assertions for %d users" % (len(assertions), len(users))) # print("Got %d assertions for %d users" % (len(assertions), len(users)))
assert len(assertions) == len(users) # assert len(assertions) == len(users)
#
for x, y in zip(assertions, creds): # for x, y in zip(assertions, creds):
x.verify(client_data.hash, y.public_key) # x.verify(client_data.hash, y.public_key)
#
print("Assertion(s) valid (%d ms)" % (t2 - t1)) # print("Assertion(s) valid (%d ms)" % (t2 - t1))
#
with Test("register a duplicate user "): # with Test("register a duplicate user "):
t1 = time.time() * 1000 # t1 = time.time() * 1000
attest, data = self.client.make_credential( # attest, data = self.client.make_credential(
rp, users[1], challenge, pin=PIN, exclude_list=[], rk=True # rp, users[1], challenge, pin=PIN, exclude_list=[], rk=True
) # )
t2 = time.time() * 1000 # t2 = time.time() * 1000
VerifyAttestation(attest, data) # VerifyAttestation(attest, data)
creds = creds[:2] + creds[3:] + [attest.auth_data.credential_data] # creds = creds[:2] + creds[3:] + [attest.auth_data.credential_data]
#
t1 = time.time() * 1000 # t1 = time.time() * 1000
assertions, client_data = self.client.get_assertion( # assertions, client_data = self.client.get_assertion(
rp["id"], challenge, pin=PIN # rp["id"], challenge, pin=PIN
) # )
t2 = time.time() * 1000 # t2 = time.time() * 1000
with Test("check %d assertions, %d users" % (len(assertions), len(users))): # with Test("check %d assertions, %d users" % (len(assertions), len(users))):
assert len(assertions) == len(users) # assert len(assertions) == len(users)
for x, y in zip(assertions, creds): # for x, y in zip(assertions, creds):
x.verify(client_data.hash, y.public_key) # x.verify(client_data.hash, y.public_key)

View File

@ -73,6 +73,16 @@ class Tester:
def set_sim(self, b): def set_sim(self, b):
self.is_sim = b self.is_sim = b
def reboot(self,):
if self.is_sim:
print("Sending restart command...")
self.send_magic_reboot()
self.delay(0.25)
else:
print("Please reboot authentictor and hit enter")
input()
self.find_device()
def send_data(self, cmd, data): def send_data(self, cmd, data):
if type(data) != type(b""): if type(data) != type(b""):
data = struct.pack("%dB" % len(data), *[ord(x) for x in data]) data = struct.pack("%dB" % len(data), *[ord(x) for x in data])