mirror of
https://github.com/trussed-dev/fido2-tests.git
synced 2026-06-20 04:16:30 -07:00
run black format on everything
This commit is contained in:
+44
-17
@@ -13,7 +13,7 @@ from fido2.utils import hmac_sha256, sha256
|
||||
|
||||
from tests.utils import *
|
||||
|
||||
if 'trezor' in sys.argv:
|
||||
if "trezor" in sys.argv:
|
||||
from .vendor.trezor.udp_backend import force_udp_backend
|
||||
else:
|
||||
from solo.fido2 import force_udp_backend
|
||||
@@ -45,7 +45,9 @@ def info(device):
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def MCRes(resetDevice,):
|
||||
def MCRes(
|
||||
resetDevice,
|
||||
):
|
||||
req = FidoRequest()
|
||||
res = resetDevice.sendMC(*req.toMC())
|
||||
setattr(res, "request", req)
|
||||
@@ -65,7 +67,9 @@ def GARes(device, MCRes):
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def RegRes(resetDevice,):
|
||||
def RegRes(
|
||||
resetDevice,
|
||||
):
|
||||
req = FidoRequest()
|
||||
res = resetDevice.register(req.challenge, req.appid)
|
||||
setattr(res, "request", req)
|
||||
@@ -115,7 +119,9 @@ class Packet(object):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
def ToWireFormat(self,):
|
||||
def ToWireFormat(
|
||||
self,
|
||||
):
|
||||
return self.data
|
||||
|
||||
@staticmethod
|
||||
@@ -177,7 +183,9 @@ class TestDevice:
|
||||
def set_sim(self, b):
|
||||
self.is_sim = b
|
||||
|
||||
def reboot(self,):
|
||||
def reboot(
|
||||
self,
|
||||
):
|
||||
if self.is_sim:
|
||||
print("Sending restart command...")
|
||||
self.send_magic_reboot()
|
||||
@@ -190,14 +198,14 @@ class TestDevice:
|
||||
self.find_device(self.nfc_interface_only)
|
||||
return
|
||||
|
||||
if 'solokeys' in sys.argv or 'solobee' in sys.argv:
|
||||
if "solokeys" in sys.argv or "solobee" in sys.argv:
|
||||
try:
|
||||
self.dev.call(0x53 ^ 0x80,b'')
|
||||
self.dev.call(0x53 ^ 0x80, b"")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
print('Rebooting..')
|
||||
for _ in range(0,8):
|
||||
print("Rebooting..")
|
||||
for _ in range(0, 8):
|
||||
time.sleep(0.1)
|
||||
try:
|
||||
self.find_device(self.nfc_interface_only)
|
||||
@@ -233,7 +241,9 @@ class TestDevice:
|
||||
assert len(data) == 64
|
||||
self.dev._dev.InternalSendPacket(Packet(data))
|
||||
|
||||
def send_magic_reboot(self,):
|
||||
def send_magic_reboot(
|
||||
self,
|
||||
):
|
||||
"""
|
||||
For use in simulation and testing. Random bytes that authenticator should detect
|
||||
and then restart itself.
|
||||
@@ -248,16 +258,20 @@ class TestDevice:
|
||||
)
|
||||
self.dev._dev.InternalSendPacket(Packet(magic_cmd))
|
||||
|
||||
def send_nfc_reboot(self,):
|
||||
def send_nfc_reboot(
|
||||
self,
|
||||
):
|
||||
"""
|
||||
Send magic nfc reboot sequence for solokey
|
||||
"""
|
||||
data = b"\x12\x56\xab\xf0"
|
||||
header = struct.pack('!BBBBB', 0x00, 0xee, 0x00, 0x00, len(data))
|
||||
header = struct.pack("!BBBBB", 0x00, 0xEE, 0x00, 0x00, len(data))
|
||||
resp, sw1, sw2 = self.dev.apdu_exchange(header + data)
|
||||
return sw1 == 0x90 and sw2 == 0x00
|
||||
|
||||
def cid(self,):
|
||||
def cid(
|
||||
self,
|
||||
):
|
||||
return self.dev._dev.cid
|
||||
|
||||
def set_cid(self, cid):
|
||||
@@ -265,7 +279,9 @@ class TestDevice:
|
||||
cid = struct.pack("%dB" % len(cid), *[ord(x) for x in cid])
|
||||
self.dev._dev.cid = cid
|
||||
|
||||
def recv_raw(self,):
|
||||
def recv_raw(
|
||||
self,
|
||||
):
|
||||
with Timeout(1.0):
|
||||
cmd, payload = self.dev._dev.InternalRecv()
|
||||
return cmd, payload
|
||||
@@ -279,10 +295,19 @@ class TestDevice:
|
||||
raise ValueError("Unexpected error: %02x" % data[0])
|
||||
|
||||
def register(self, chal, appid, on_keepalive=DeviceSelectCredential(1)):
|
||||
reg_data = _call_polling(0.25, None, on_keepalive, self.ctap1.register, chal, appid)
|
||||
reg_data = _call_polling(
|
||||
0.25, None, on_keepalive, self.ctap1.register, chal, appid
|
||||
)
|
||||
return reg_data
|
||||
|
||||
def authenticate(self, chal, appid, key_handle, check_only=False, on_keepalive=DeviceSelectCredential(1)):
|
||||
def authenticate(
|
||||
self,
|
||||
chal,
|
||||
appid,
|
||||
key_handle,
|
||||
check_only=False,
|
||||
on_keepalive=DeviceSelectCredential(1),
|
||||
):
|
||||
auth_data = _call_polling(
|
||||
0.25,
|
||||
None,
|
||||
@@ -295,7 +320,9 @@ class TestDevice:
|
||||
)
|
||||
return auth_data
|
||||
|
||||
def reset(self,):
|
||||
def reset(
|
||||
self,
|
||||
):
|
||||
print("Resetting Authenticator...")
|
||||
try:
|
||||
self.ctap2.reset(on_keepalive=DeviceSelectCredential(1))
|
||||
|
||||
@@ -6,7 +6,9 @@ from fido2.ctap2 import ES256, AttestedCredentialData, PinProtocolV1
|
||||
from tests.utils import *
|
||||
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="ClientPin is not supported on Trezor.")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv, reason="ClientPin is not supported on Trezor."
|
||||
)
|
||||
def test_lockout(device, resetDevice):
|
||||
pin = "TestPin"
|
||||
device.client.pin_protocol.set_pin(pin)
|
||||
|
||||
@@ -50,7 +50,9 @@ def GAPinRes(device, MCPinRes):
|
||||
return res
|
||||
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="ClientPin is not supported on Trezor.")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv, reason="ClientPin is not supported on Trezor."
|
||||
)
|
||||
class TestPin(object):
|
||||
def test_pin(self, CPRes):
|
||||
pass
|
||||
@@ -136,7 +138,9 @@ class TestPin(object):
|
||||
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
|
||||
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="ClientPin is not supported on Trezor.")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv, reason="ClientPin is not supported on Trezor."
|
||||
)
|
||||
def test_pin_attempts(device, SetPinRes):
|
||||
# Flip 1 bit
|
||||
pin = SetPinRes.PIN
|
||||
|
||||
@@ -6,7 +6,9 @@ from fido2.ctap2 import ES256, AttestedCredentialData, PinProtocolV1
|
||||
from tests.utils import *
|
||||
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="ClientPin is not supported on Trezor.")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv, reason="ClientPin is not supported on Trezor."
|
||||
)
|
||||
class TestSetPin(object):
|
||||
def test_send_zero_length_pin_auth(self, resetDevice):
|
||||
with pytest.raises(CtapError) as e:
|
||||
|
||||
@@ -27,6 +27,7 @@ class TestCtap1WithCtap2(object):
|
||||
auth.verify(req.cdh, credential_data.public_key)
|
||||
assert auth.credential["id"] == RegRes.key_handle
|
||||
|
||||
|
||||
# Test FIDO2 register works with U2F auth
|
||||
class TestCtap2WithCtap1(object):
|
||||
def test_ctap1_authenticate(self, MCRes, device):
|
||||
@@ -36,10 +37,12 @@ class TestCtap2WithCtap1(object):
|
||||
res = device.authenticate(req.challenge, req.appid, key_handle)
|
||||
|
||||
credential_data = AttestedCredentialData(MCRes.auth_data.credential_data)
|
||||
pubkey_string = b'\x04' + credential_data.public_key[-2] + credential_data.public_key[-3]
|
||||
|
||||
res.verify(
|
||||
req.appid, req.challenge, pubkey_string
|
||||
pubkey_string = (
|
||||
b"\x04"
|
||||
+ credential_data.public_key[-2]
|
||||
+ credential_data.public_key[-3]
|
||||
)
|
||||
|
||||
res.verify(req.appid, req.challenge, pubkey_string)
|
||||
else:
|
||||
print("ctap2 credId is longer than 255 bytes, cannot use with U2F.")
|
||||
print("ctap2 credId is longer than 255 bytes, cannot use with U2F.")
|
||||
|
||||
@@ -39,17 +39,16 @@ class TestGetAssertion(object):
|
||||
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
|
||||
|
||||
def test_mismatched_rp(self, device, GARes):
|
||||
rp_id = GARes.request.rp['id'][:]
|
||||
rp_name = GARes.request.rp['name'][:]
|
||||
rp_id += '.com'
|
||||
rp_id = GARes.request.rp["id"][:]
|
||||
rp_name = GARes.request.rp["name"][:]
|
||||
rp_id += ".com"
|
||||
|
||||
mismatch_rp = {'id': rp_id, 'name': rp_name}
|
||||
mismatch_rp = {"id": rp_id, "name": rp_name}
|
||||
|
||||
with pytest.raises(CtapError) as e:
|
||||
device.sendGA(*FidoRequest(GARes, rp=mismatch_rp).toGA())
|
||||
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
|
||||
|
||||
|
||||
def test_missing_rp(self, device, GARes):
|
||||
with pytest.raises(CtapError) as e:
|
||||
device.sendGA(*FidoRequest(GARes, rp=None).toGA())
|
||||
@@ -84,7 +83,10 @@ class TestGetAssertion(object):
|
||||
def test_unknown_option(self, device, GARes):
|
||||
device.sendGA(*FidoRequest(GARes, options={"unknown": True}).toGA())
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="User verification flag is intentionally set to true on Trezor even when user verification is not configured. (Otherwise some services refuse registration without giving a reason.)")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv,
|
||||
reason="User verification flag is intentionally set to true on Trezor even when user verification is not configured. (Otherwise some services refuse registration without giving a reason.)",
|
||||
)
|
||||
def test_option_uv(self, device, info, GARes):
|
||||
if "uv" in info.options:
|
||||
if info.options["uv"]:
|
||||
@@ -145,19 +147,20 @@ class TestGetAssertion(object):
|
||||
|
||||
def test_user_presence_option_false(self, device, MCRes, GARes):
|
||||
from cryptography.exceptions import InvalidSignature
|
||||
res = device.sendGA(*FidoRequest(GARes, options = {'up': False}).toGA())
|
||||
|
||||
res = device.sendGA(*FidoRequest(GARes, options={"up": False}).toGA())
|
||||
|
||||
try:
|
||||
verify(MCRes, res, GARes.request.cdh)
|
||||
except InvalidSignature:
|
||||
if 'trezor' not in sys.argv:
|
||||
if "trezor" not in sys.argv:
|
||||
raise
|
||||
|
||||
if '--nfc' not in sys.argv:
|
||||
assert((res.auth_data.flags & 1) == 0)
|
||||
if "--nfc" not in sys.argv:
|
||||
assert (res.auth_data.flags & 1) == 0
|
||||
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="Reboot is not supported on Trezor.")
|
||||
@pytest.mark.skipif("trezor" in sys.argv, reason="Reboot is not supported on Trezor.")
|
||||
class TestGetAssertionAfterBoot(object):
|
||||
def test_assertion_after_reboot(self, rebootedDevice, MCRes, GARes):
|
||||
credential_data = AttestedCredentialData(MCRes.auth_data.credential_data)
|
||||
|
||||
@@ -25,7 +25,10 @@ def test_Check_options_field(info):
|
||||
assert info.options[x] in [True, False]
|
||||
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="User verification flag is intentionally set to true on Trezor even when user verification is not configured. (Otherwise some services refuse registration without giving a reason.)")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv,
|
||||
reason="User verification flag is intentionally set to true on Trezor even when user verification is not configured. (Otherwise some services refuse registration without giving a reason.)",
|
||||
)
|
||||
def test_Check_uv_option(device, info):
|
||||
if "uv" in info.options:
|
||||
if info.options["uv"]:
|
||||
@@ -39,6 +42,7 @@ def test_Check_up_option(device, info):
|
||||
device.sendMC(*FidoRequest(options={"up": True}).toMC())
|
||||
assert e.value.code == CtapError.ERR.INVALID_OPTION
|
||||
|
||||
|
||||
def test_self_cbor_sorting():
|
||||
cbor_key_list_sorted = [
|
||||
0,
|
||||
@@ -58,18 +62,22 @@ def test_self_cbor_sorting():
|
||||
]
|
||||
TestCborKeysSorted(cbor_key_list_sorted)
|
||||
|
||||
|
||||
def test_self_cbor_integers():
|
||||
with pytest.raises(ValueError) as e:
|
||||
TestCborKeysSorted([1, 0])
|
||||
|
||||
|
||||
def test_self_cbor_major_type():
|
||||
with pytest.raises(ValueError) as e:
|
||||
TestCborKeysSorted([-1, 0])
|
||||
|
||||
|
||||
def test_self_cbor_strings():
|
||||
with pytest.raises(ValueError) as e:
|
||||
TestCborKeysSorted(["bb", "a"])
|
||||
|
||||
|
||||
def test_self_cbor_same_length_strings():
|
||||
with pytest.raises(ValueError) as e:
|
||||
TestCborKeysSorted(["ab", "aa"])
|
||||
TestCborKeysSorted(["ab", "aa"])
|
||||
|
||||
@@ -155,7 +155,10 @@ class TestMakeCredential(object):
|
||||
with pytest.raises(CtapError) as e:
|
||||
device.sendMC(*req.toMC())
|
||||
|
||||
assert e.value.code in [CtapError.ERR.MISSING_PARAMETER, CtapError.ERR.UNSUPPORTED_ALGORITHM]
|
||||
assert e.value.code in [
|
||||
CtapError.ERR.MISSING_PARAMETER,
|
||||
CtapError.ERR.UNSUPPORTED_ALGORITHM,
|
||||
]
|
||||
|
||||
def test_bad_type_pubKeyCredParams_alg(self, device, MCRes):
|
||||
req = FidoRequest(MCRes, key_params=[{"alg": "7", "type": "public-key"}])
|
||||
@@ -228,7 +231,9 @@ class TestMakeCredential(object):
|
||||
device.sendMC(*req.toMC())
|
||||
|
||||
def test_eddsa(self, device):
|
||||
mc_req = FidoRequest(key_params=[{"type": "public-key", "alg": EdDSA.ALGORITHM}])
|
||||
mc_req = FidoRequest(
|
||||
key_params=[{"type": "public-key", "alg": EdDSA.ALGORITHM}]
|
||||
)
|
||||
try:
|
||||
mc_res = device.sendMC(*mc_req.toMC())
|
||||
except CtapError as e:
|
||||
@@ -238,7 +243,12 @@ class TestMakeCredential(object):
|
||||
|
||||
setattr(mc_res, "request", mc_req)
|
||||
|
||||
allow_list = [{"id": mc_res.auth_data.credential_data.credential_id[:], "type": "public-key"}]
|
||||
allow_list = [
|
||||
{
|
||||
"id": mc_res.auth_data.credential_data.credential_id[:],
|
||||
"type": "public-key",
|
||||
}
|
||||
]
|
||||
|
||||
ga_req = FidoRequest(allow_list=allow_list)
|
||||
ga_res = device.sendGA(*ga_req.toGA())
|
||||
@@ -249,10 +259,12 @@ class TestMakeCredential(object):
|
||||
except:
|
||||
# Print out extra details on failure
|
||||
from binascii import hexlify
|
||||
print('authdata', hexlify(ga_res.auth_data))
|
||||
print('cdh', hexlify(ga_res.request.cdh))
|
||||
print('sig', hexlify(ga_res.signature))
|
||||
from fido2.ctap2 import AttestedCredentialData
|
||||
|
||||
print("authdata", hexlify(ga_res.auth_data))
|
||||
print("cdh", hexlify(ga_res.request.cdh))
|
||||
print("sig", hexlify(ga_res.signature))
|
||||
from fido2.ctap2 import AttestedCredentialData
|
||||
|
||||
credential_data = AttestedCredentialData(mc_res.auth_data.credential_data)
|
||||
print('public key:', hexlify(credential_data.public_key[-2]))
|
||||
print("public key:", hexlify(credential_data.public_key[-2]))
|
||||
verify(mc_res, ga_res)
|
||||
|
||||
@@ -5,7 +5,10 @@ from fido2.ctap import CtapError
|
||||
from tests.utils import *
|
||||
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="Trezor does not invalidate server-resident credentials.")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv,
|
||||
reason="Trezor does not invalidate server-resident credentials.",
|
||||
)
|
||||
def test_credential_resets(device, MCRes, GARes):
|
||||
verify(MCRes, GARes)
|
||||
device.reset()
|
||||
|
||||
@@ -51,14 +51,20 @@ class TestResidentKey(object):
|
||||
|
||||
def test_user_info_returned(self, MC_RK_Res, GA_RK_Res):
|
||||
assert "id" in GA_RK_Res.user.keys()
|
||||
assert MC_RK_Res.auth_data.credential_data.credential_id == GA_RK_Res.credential['id']
|
||||
assert MC_RK_Res.request.user['id'] == GA_RK_Res.user['id']
|
||||
assert (
|
||||
MC_RK_Res.auth_data.credential_data.credential_id
|
||||
== GA_RK_Res.credential["id"]
|
||||
)
|
||||
assert MC_RK_Res.request.user["id"] == GA_RK_Res.user["id"]
|
||||
if not MC_RK_Res.request.pin_protocol or not GA_RK_Res.number_of_credentials:
|
||||
assert "id" in GA_RK_Res.user.keys() and len(GA_RK_Res.user.keys()) == 1
|
||||
else:
|
||||
assert MC_RK_Res.request.user == GA_RK_Res.user
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="Trezor does not support get_next_assertion() because it has a display.")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv,
|
||||
reason="Trezor does not support get_next_assertion() because it has a display.",
|
||||
)
|
||||
def test_multiple_rk_nodisplay(self, device, MC_RK_Res):
|
||||
auths = []
|
||||
regs = [MC_RK_Res]
|
||||
@@ -92,7 +98,7 @@ class TestResidentKey(object):
|
||||
for x, y in zip(regs, auths[::-1]):
|
||||
verify(x, y, req.cdh)
|
||||
|
||||
@pytest.mark.skipif('trezor' not in sys.argv, reason="Only Trezor has a display.")
|
||||
@pytest.mark.skipif("trezor" not in sys.argv, reason="Only Trezor has a display.")
|
||||
def test_multiple_rk_display(self, device, MC_RK_Res):
|
||||
regs = [MC_RK_Res]
|
||||
for i in range(0, 3):
|
||||
@@ -102,7 +108,9 @@ class TestResidentKey(object):
|
||||
regs.append(res)
|
||||
|
||||
for i, reg in enumerate(reversed(regs)):
|
||||
req = FidoRequest(MC_RK_Res, options=None, on_keepalive=DeviceSelectCredential(i + 1))
|
||||
req = FidoRequest(
|
||||
MC_RK_Res, options=None, on_keepalive=DeviceSelectCredential(i + 1)
|
||||
)
|
||||
res = device.sendGA(*req.toGA())
|
||||
assert res.number_of_credentials is None
|
||||
|
||||
@@ -113,7 +121,7 @@ class TestResidentKey(object):
|
||||
assert res.user["id"] == reg.request.user["id"]
|
||||
verify(reg, res, req.cdh)
|
||||
|
||||
@pytest.mark.skipif('trezor' not in sys.argv, reason="Only Trezor has a display.")
|
||||
@pytest.mark.skipif("trezor" not in sys.argv, reason="Only Trezor has a display.")
|
||||
def test_replace_rk_display(self, device):
|
||||
"""
|
||||
Test replacing resident keys.
|
||||
@@ -126,7 +134,12 @@ class TestResidentKey(object):
|
||||
# Registration data is a list of (rp, user, number), where number is
|
||||
# the expected position of the credential after all registrations are
|
||||
# complete.
|
||||
reg_data = [(rp1, user1, 2), (rp1, user2, None), (rp1, user2, 1), (rp2, user2, 1)]
|
||||
reg_data = [
|
||||
(rp1, user1, 2),
|
||||
(rp1, user2, None),
|
||||
(rp1, user2, 1),
|
||||
(rp2, user2, 1),
|
||||
]
|
||||
regs = []
|
||||
for rp, user, number in reg_data:
|
||||
req = FidoRequest(options={"rk": True}, rp=rp, user=user)
|
||||
@@ -138,13 +151,22 @@ class TestResidentKey(object):
|
||||
# Check.
|
||||
for reg in regs:
|
||||
if reg.number is not None:
|
||||
req = FidoRequest(rp=reg.request.rp, options=None, on_keepalive=DeviceSelectCredential(reg.number))
|
||||
req = FidoRequest(
|
||||
rp=reg.request.rp,
|
||||
options=None,
|
||||
on_keepalive=DeviceSelectCredential(reg.number),
|
||||
)
|
||||
res = device.sendGA(*req.toGA())
|
||||
assert res.user["id"] == reg.request.user["id"]
|
||||
verify(reg, res, req.cdh)
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="Trezor does not support get_next_assertion() because it has a display.")
|
||||
@pytest.mark.skipif('solokeys' in sys.argv, reason="Initial SoloKeys model truncates displayName")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv,
|
||||
reason="Trezor does not support get_next_assertion() because it has a display.",
|
||||
)
|
||||
@pytest.mark.skipif(
|
||||
"solokeys" in sys.argv, reason="Initial SoloKeys model truncates displayName"
|
||||
)
|
||||
def test_rk_maximum_size_nodisplay(self, device, MC_RK_Res):
|
||||
"""
|
||||
Check the lengths of the fields according to the FIDO2 spec
|
||||
@@ -155,7 +177,7 @@ class TestResidentKey(object):
|
||||
user_max = generate_user_maximum()
|
||||
req = FidoRequest(MC_RK_Res, user=user_max)
|
||||
resMC = device.sendMC(*req.toMC())
|
||||
req.options={}
|
||||
req.options = {}
|
||||
resGA = device.sendGA(*req.toGA())
|
||||
credentials = resGA.number_of_credentials
|
||||
assert credentials == 5
|
||||
@@ -171,7 +193,7 @@ class TestResidentKey(object):
|
||||
for y in ("name", "icon", "displayName", "id"):
|
||||
assert user_max_GA.user[y] == user_max[y]
|
||||
|
||||
@pytest.mark.skipif('trezor' not in sys.argv, reason="Only Trezor has a display.")
|
||||
@pytest.mark.skipif("trezor" not in sys.argv, reason="Only Trezor has a display.")
|
||||
def test_rk_maximum_size_display(self, device, MC_RK_Res):
|
||||
"""
|
||||
Check the lengths of the fields according to the FIDO2 spec
|
||||
@@ -186,16 +208,22 @@ class TestResidentKey(object):
|
||||
assert resGA.number_of_credentials is None
|
||||
verify(resMC, resGA, req.cdh)
|
||||
|
||||
@pytest.mark.skipif('trezor' in sys.argv, reason="Trezor does not support get_next_assertion() because it has a display.")
|
||||
@pytest.mark.skipif('solokeys' in sys.argv, reason="Initial SoloKeys model truncates displayName")
|
||||
@pytest.mark.skipif(
|
||||
"trezor" in sys.argv,
|
||||
reason="Trezor does not support get_next_assertion() because it has a display.",
|
||||
)
|
||||
@pytest.mark.skipif(
|
||||
"solokeys" in sys.argv, reason="Initial SoloKeys model truncates displayName"
|
||||
)
|
||||
def test_rk_maximum_list_capacity_per_rp_nodisplay(self, info, device, MC_RK_Res):
|
||||
"""
|
||||
Test maximum returned capacity of the RK for the given RP
|
||||
"""
|
||||
|
||||
# Try to determine from get_info, or default to 19.
|
||||
RK_CAPACITY_PER_RP = info.max_creds_in_list
|
||||
if not RK_CAPACITY_PER_RP: RK_CAPACITY_PER_RP = 19
|
||||
RK_CAPACITY_PER_RP = info.max_creds_in_list
|
||||
if not RK_CAPACITY_PER_RP:
|
||||
RK_CAPACITY_PER_RP = 19
|
||||
|
||||
users = []
|
||||
|
||||
@@ -243,7 +271,7 @@ class TestResidentKey(object):
|
||||
for x, y in zip(regs, auths):
|
||||
verify(x, y, req.cdh)
|
||||
|
||||
@pytest.mark.skipif('trezor' not in sys.argv, reason="Only Trezor has a display.")
|
||||
@pytest.mark.skipif("trezor" not in sys.argv, reason="Only Trezor has a display.")
|
||||
def test_rk_maximum_list_capacity_per_rp_display(self, device):
|
||||
"""
|
||||
Test maximum capacity of resident keys.
|
||||
@@ -267,7 +295,9 @@ class TestResidentKey(object):
|
||||
for i, reg in enumerate(reversed(regs)):
|
||||
if i not in (0, 1, 7, 14, 15):
|
||||
continue
|
||||
req = FidoRequest(req, options=None, on_keepalive=DeviceSelectCredential(i + 1))
|
||||
req = FidoRequest(
|
||||
req, options=None, on_keepalive=DeviceSelectCredential(i + 1)
|
||||
)
|
||||
res = device.sendGA(*req.toGA())
|
||||
assert res.user["id"] == reg.request.user["id"]
|
||||
verify(reg, res, req.cdh)
|
||||
|
||||
@@ -8,8 +8,8 @@ from tests.utils import *
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
("--sim" in sys.argv or '--nfc' in sys.argv) and not 'trezor' in sys.argv,
|
||||
reason="Simulation doesn't care about user presence"
|
||||
("--sim" in sys.argv or "--nfc" in sys.argv) and not "trezor" in sys.argv,
|
||||
reason="Simulation doesn't care about user presence",
|
||||
)
|
||||
class TestUserPresence(object):
|
||||
def test_user_presence_instructions(self, MCRes, GARes):
|
||||
@@ -31,40 +31,53 @@ class TestUserPresence(object):
|
||||
print("DO NOT ACTIVATE UP")
|
||||
with pytest.raises(CtapError) as e:
|
||||
with Timeout(2.0) as event:
|
||||
device.sendGA(*FidoRequest(GARes, timeout=event, on_keepalive=None).toGA())
|
||||
device.sendGA(
|
||||
*FidoRequest(GARes, timeout=event, on_keepalive=None).toGA()
|
||||
)
|
||||
assert e.value.code == CtapError.ERR.KEEPALIVE_CANCEL
|
||||
|
||||
@pytest.mark.skipif(not 'trezor' in sys.argv, reason="Only Trezor supports decline.")
|
||||
@pytest.mark.skipif(
|
||||
not "trezor" in sys.argv, reason="Only Trezor supports decline."
|
||||
)
|
||||
def test_user_decline(self, device, MCRes, GARes):
|
||||
print("PRESS DECLINE")
|
||||
with pytest.raises(CtapError) as e:
|
||||
device.sendGA(*FidoRequest(GARes, on_keepalive=DeviceSelectCredential(0)).toGA())
|
||||
device.sendGA(
|
||||
*FidoRequest(GARes, on_keepalive=DeviceSelectCredential(0)).toGA()
|
||||
)
|
||||
assert e.value.code == CtapError.ERR.OPERATION_DENIED
|
||||
|
||||
def test_user_presence_option_false_on_get_assertion(self, device, MCRes, GARes):
|
||||
print("DO NOT ACTIVATE UP")
|
||||
time.sleep(1)
|
||||
with Timeout(2.0) as event:
|
||||
device.sendGA(*FidoRequest(GARes, options = {'up': False}, timeout=event).toGA())
|
||||
device.sendGA(
|
||||
*FidoRequest(GARes, options={"up": False}, timeout=event).toGA()
|
||||
)
|
||||
|
||||
def test_user_presence_option_false_on_make_credential(self, device, MCRes):
|
||||
print("DO NOT ACTIVATE UP")
|
||||
time.sleep(1)
|
||||
with pytest.raises(CtapError) as e:
|
||||
with Timeout(1.0) as event:
|
||||
device.sendMC(*FidoRequest(MCRes, options = {'up': False}, timeout=event).toMC())
|
||||
device.sendMC(
|
||||
*FidoRequest(MCRes, options={"up": False}, timeout=event).toMC()
|
||||
)
|
||||
assert e.value.code == CtapError.ERR.INVALID_OPTION
|
||||
with pytest.raises(CtapError) as e:
|
||||
with Timeout(1.0) as event:
|
||||
device.sendMC(*FidoRequest(MCRes, options = {'up': True}, timeout=event).toMC())
|
||||
device.sendMC(
|
||||
*FidoRequest(MCRes, options={"up": True}, timeout=event).toMC()
|
||||
)
|
||||
assert e.value.code == CtapError.ERR.INVALID_OPTION
|
||||
|
||||
|
||||
def test_user_presence_permits_only_one_request(self, device, MCRes, GARes):
|
||||
print("ACTIVATE UP ONCE")
|
||||
device.sendGA(*FidoRequest(GARes).toGA())
|
||||
|
||||
with pytest.raises(CtapError) as e:
|
||||
with Timeout(1.0) as event:
|
||||
device.sendGA(*FidoRequest(GARes, timeout=event, on_keepalive=None).toGA())
|
||||
device.sendGA(
|
||||
*FidoRequest(GARes, timeout=event, on_keepalive=None).toGA()
|
||||
)
|
||||
assert e.value.code == CtapError.ERR.KEEPALIVE_CANCEL
|
||||
|
||||
@@ -8,10 +8,8 @@ import pytest
|
||||
from fido2.ctap import CtapError
|
||||
from fido2.hid import CTAPHID
|
||||
|
||||
@pytest.mark.skipif(
|
||||
'--nfc' in sys.argv,
|
||||
reason="Wrong transport"
|
||||
)
|
||||
|
||||
@pytest.mark.skipif("--nfc" in sys.argv, reason="Wrong transport")
|
||||
class TestHID(object):
|
||||
def test_long_ping(self, device):
|
||||
amt = 1000
|
||||
@@ -50,14 +48,13 @@ class TestHID(object):
|
||||
r = device.send_data(CTAPHID.INIT, payload)
|
||||
capabilities = r[16]
|
||||
|
||||
|
||||
if (capabilities ^ 0x04) != 0:
|
||||
print('Implements CBOR.')
|
||||
print("Implements CBOR.")
|
||||
with pytest.raises(CtapError) as e:
|
||||
r = device.send_data(CTAPHID.CBOR, "")
|
||||
assert e.value.code == CtapError.ERR.INVALID_LENGTH
|
||||
else:
|
||||
print('CBOR is not implemented.')
|
||||
print("CBOR is not implemented.")
|
||||
|
||||
def test_no_data_in_u2f_msg(self, device):
|
||||
payload = b"\x11\x11\x11\x11\x11\x11\x11\x11"
|
||||
|
||||
@@ -4,10 +4,7 @@ import pytest
|
||||
from tests.utils import FidoRequest
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not ('--nfc' in sys.argv),
|
||||
reason="NFC transport only"
|
||||
)
|
||||
@pytest.mark.skipif(not ("--nfc" in sys.argv), reason="NFC transport only")
|
||||
class TestMakeCredential(object):
|
||||
def test_big_request_response(self, device, MCRes):
|
||||
req = FidoRequest(
|
||||
@@ -15,12 +12,16 @@ class TestMakeCredential(object):
|
||||
exclude_list=[
|
||||
{
|
||||
"id": b"0123456789012345678901234567890123456789012345678901234567890123456789",
|
||||
"type": "public-key"},
|
||||
"type": "public-key",
|
||||
},
|
||||
{
|
||||
"id": b"1123456789012345678901234567890123456789012345678901234567890123456789",
|
||||
"type": "public-key"},
|
||||
"type": "public-key",
|
||||
},
|
||||
{
|
||||
"id": b"2123456789012345678901234567890123456789012345678901234567890123456789",
|
||||
"type": "public-key"}],
|
||||
"type": "public-key",
|
||||
},
|
||||
],
|
||||
)
|
||||
device.sendMC(*req.toMC())
|
||||
|
||||
+13
-7
@@ -8,7 +8,7 @@ from numbers import Number
|
||||
from fido2.ctap2 import ES256, AttestedCredentialData, PinProtocolV1
|
||||
from fido2.utils import hmac_sha256, sha256
|
||||
|
||||
if 'trezor' in sys.argv:
|
||||
if "trezor" in sys.argv:
|
||||
from .vendor.trezor.utils import DeviceSelectCredential
|
||||
else:
|
||||
from .vendor.solo.utils import DeviceSelectCredential
|
||||
@@ -57,6 +57,7 @@ def generate_user():
|
||||
|
||||
counter = 1
|
||||
|
||||
|
||||
def generate_user_maximum():
|
||||
"""
|
||||
Generate RK with the maximum lengths of the fields, according to the minimal requirements of the FIDO2 spec
|
||||
@@ -69,8 +70,8 @@ def generate_user_maximum():
|
||||
|
||||
# https://www.w3.org/TR/webauthn/#dictionary-pkcredentialentity
|
||||
name = " ".join(random.choice(name_list).strip() for i in range(0, 30))
|
||||
name = f'{counter}: {name}'
|
||||
icon = "https://www.w3.org/TR/webauthn/" + 'A'*128
|
||||
name = f"{counter}: {name}"
|
||||
icon = "https://www.w3.org/TR/webauthn/" + "A" * 128
|
||||
display_name = "Displayed " + name
|
||||
|
||||
name = name[:64]
|
||||
@@ -150,8 +151,8 @@ class FidoRequest:
|
||||
|
||||
def save_attr(self, attr, value, request):
|
||||
"""
|
||||
Will assign attribute from source, in following priority:
|
||||
Argument, request object, generated
|
||||
Will assign attribute from source, in following priority:
|
||||
Argument, request object, generated
|
||||
"""
|
||||
if value != Empty:
|
||||
setattr(self, attr, value)
|
||||
@@ -160,7 +161,9 @@ class FidoRequest:
|
||||
else:
|
||||
setattr(self, attr, generate(attr))
|
||||
|
||||
def toGA(self,):
|
||||
def toGA(
|
||||
self,
|
||||
):
|
||||
return [
|
||||
None if not self.rp else self.rp["id"],
|
||||
self.cdh,
|
||||
@@ -173,7 +176,9 @@ class FidoRequest:
|
||||
self.on_keepalive,
|
||||
]
|
||||
|
||||
def toMC(self,):
|
||||
def toMC(
|
||||
self,
|
||||
):
|
||||
return [
|
||||
self.cdh,
|
||||
self.rp,
|
||||
@@ -220,6 +225,7 @@ class FidoRequest:
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
class Timeout(object):
|
||||
"""Utility class for adding a timeout to an event.
|
||||
:param time_or_event: A number, in seconds, or a threading.Event object.
|
||||
|
||||
Vendored
+126
-78
@@ -8,6 +8,7 @@ from binascii import hexlify
|
||||
|
||||
PIN = "123456"
|
||||
|
||||
|
||||
@pytest.fixture(params=[PIN])
|
||||
def PinToken(request, device):
|
||||
device.reboot()
|
||||
@@ -17,15 +18,17 @@ def PinToken(request, device):
|
||||
return device.client.pin_protocol.get_pin_token(pin)
|
||||
|
||||
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def MC_RK_Res(device, PinToken):
|
||||
req = FidoRequest()
|
||||
pin_auth = hmac_sha256(PinToken, req.cdh)[:16]
|
||||
rp = {"id": "ssh:", "name": "Bate Goiko"}
|
||||
req = FidoRequest(
|
||||
request=None, pin_protocol=1, pin_auth=pin_auth, rp=rp, options={"rk": True},
|
||||
request=None,
|
||||
pin_protocol=1,
|
||||
pin_auth=pin_auth,
|
||||
rp=rp,
|
||||
options={"rk": True},
|
||||
)
|
||||
device.sendMC(*req.toMC())
|
||||
|
||||
@@ -33,7 +36,11 @@ def MC_RK_Res(device, PinToken):
|
||||
pin_auth = hmac_sha256(PinToken, req.cdh)[:16]
|
||||
rp = {"id": "xakcop.com", "name": "John Doe"}
|
||||
req = FidoRequest(
|
||||
request=None, pin_protocol=1, pin_auth=pin_auth, rp=rp, options={"rk": True},
|
||||
request=None,
|
||||
pin_protocol=1,
|
||||
pin_auth=pin_auth,
|
||||
rp=rp,
|
||||
options={"rk": True},
|
||||
)
|
||||
device.sendMC(*req.toMC())
|
||||
|
||||
@@ -50,8 +57,9 @@ def _test_enumeration(CredMgmt, rp_map):
|
||||
assert len(rp_map.keys()) == len(res)
|
||||
|
||||
for rp in res:
|
||||
creds = CredMgmt.enumerate_creds(sha256( rp[3]['id'].encode('utf8') ))
|
||||
assert len(creds) == rp_map[rp[3]['id']]
|
||||
creds = CredMgmt.enumerate_creds(sha256(rp[3]["id"].encode("utf8")))
|
||||
assert len(creds) == rp_map[rp[3]["id"]]
|
||||
|
||||
|
||||
def _test_enumeration_interleaved(CredMgmt, rp_map):
|
||||
"Enumerate credentials using DFS"
|
||||
@@ -59,24 +67,25 @@ def _test_enumeration_interleaved(CredMgmt, rp_map):
|
||||
assert len(rp_map.keys()) == first_rp[CredentialManagement.RESULT.TOTAL_RPS]
|
||||
|
||||
rk_count = 1
|
||||
first_rk = CredMgmt.enumerate_creds_begin( sha256( first_rp[3]['id'].encode('utf8') ) )
|
||||
first_rk = CredMgmt.enumerate_creds_begin(sha256(first_rp[3]["id"].encode("utf8")))
|
||||
for i in range(1, first_rk[CredentialManagement.RESULT.TOTAL_CREDENTIALS]):
|
||||
c = CredMgmt.enumerate_creds_next()
|
||||
rk_count += 1
|
||||
|
||||
assert rk_count == rp_map[first_rp[3]['id']]
|
||||
|
||||
assert rk_count == rp_map[first_rp[3]["id"]]
|
||||
|
||||
for i in range(1, first_rp[CredentialManagement.RESULT.TOTAL_RPS]):
|
||||
next_rp = CredMgmt.enumerate_rps_next()
|
||||
|
||||
rk_count = 1
|
||||
first_rk = CredMgmt.enumerate_creds_begin( sha256( next_rp[3]['id'].encode('utf8') ) )
|
||||
first_rk = CredMgmt.enumerate_creds_begin(
|
||||
sha256(next_rp[3]["id"].encode("utf8"))
|
||||
)
|
||||
for i in range(1, first_rk[CredentialManagement.RESULT.TOTAL_CREDENTIALS]):
|
||||
c = CredMgmt.enumerate_creds_next()
|
||||
rk_count += 1
|
||||
|
||||
assert rk_count == rp_map[next_rp[3]['id']]
|
||||
|
||||
assert rk_count == rp_map[next_rp[3]["id"]]
|
||||
|
||||
|
||||
def CredMgmtWrongPinAuth(device, pin_token):
|
||||
@@ -85,6 +94,7 @@ def CredMgmtWrongPinAuth(device, pin_token):
|
||||
wrong_pt[0] = (wrong_pt[0] + 1) % 256
|
||||
return CredentialManagement(device.ctap2, pin_protocol, bytes(wrong_pt))
|
||||
|
||||
|
||||
def assert_cred_response_has_all_fields(cred_res):
|
||||
for i in (
|
||||
CredentialManagement.RESULT.USER,
|
||||
@@ -92,17 +102,18 @@ def assert_cred_response_has_all_fields(cred_res):
|
||||
CredentialManagement.RESULT.PUBLIC_KEY,
|
||||
CredentialManagement.RESULT.TOTAL_CREDENTIALS,
|
||||
CredentialManagement.RESULT.CRED_PROTECT,
|
||||
):
|
||||
assert( i in cred_res )
|
||||
):
|
||||
assert i in cred_res
|
||||
|
||||
|
||||
class TestCredentialManagement(object):
|
||||
def test_get_info(self, info):
|
||||
assert('credMgmt' in info.options)
|
||||
assert(info.options['credMgmt'] == True)
|
||||
assert(0x7 in info)
|
||||
assert(info[0x7] > 1)
|
||||
assert(0x8 in info)
|
||||
assert(info[0x8] > 1)
|
||||
assert "credMgmt" in info.options
|
||||
assert info.options["credMgmt"] == True
|
||||
assert 0x7 in info
|
||||
assert info[0x7] > 1
|
||||
assert 0x8 in info
|
||||
assert info[0x8] > 1
|
||||
|
||||
def test_get_metadata(self, CredMgmt, MC_RK_Res):
|
||||
metadata = CredMgmt.get_metadata()
|
||||
@@ -159,12 +170,15 @@ class TestCredentialManagement(object):
|
||||
pin_auth = hmac_sha256(PinToken, req.cdh)[:16]
|
||||
rp = {"id": "example_3.com", "name": "John Doe 2"}
|
||||
req = FidoRequest(
|
||||
pin_protocol=1, pin_auth=pin_auth, options={"rk": True}, rp = rp,
|
||||
pin_protocol=1,
|
||||
pin_auth=pin_auth,
|
||||
options={"rk": True},
|
||||
rp=rp,
|
||||
)
|
||||
reg = device.sendMC(*req.toMC())
|
||||
|
||||
# make sure it works
|
||||
req = FidoRequest(rp = rp)
|
||||
req = FidoRequest(rp=rp)
|
||||
auth = device.sendGA(*req.toGA())
|
||||
|
||||
verify(reg, auth, req.cdh)
|
||||
@@ -172,15 +186,15 @@ class TestCredentialManagement(object):
|
||||
# get the ID from enumeration
|
||||
creds = CredMgmt.enumerate_creds(reg.auth_data.rp_id_hash)
|
||||
for cred in creds:
|
||||
if cred[7]['id'] == reg.auth_data.credential_data.credential_id:
|
||||
if cred[7]["id"] == reg.auth_data.credential_data.credential_id:
|
||||
break
|
||||
|
||||
# delete it
|
||||
cred = {"id": cred[7]['id'], "type": "public-key"}
|
||||
CredMgmt.delete_cred( cred )
|
||||
cred = {"id": cred[7]["id"], "type": "public-key"}
|
||||
CredMgmt.delete_cred(cred)
|
||||
|
||||
# make sure it doesn't work
|
||||
req = FidoRequest(rp = rp)
|
||||
req = FidoRequest(rp=rp)
|
||||
with pytest.raises(CtapError) as e:
|
||||
auth = device.sendGA(*req.toGA())
|
||||
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
|
||||
@@ -192,11 +206,14 @@ class TestCredentialManagement(object):
|
||||
regs = []
|
||||
|
||||
# create 3 new RK's
|
||||
for i in range(0,3):
|
||||
for i in range(0, 3):
|
||||
req = FidoRequest()
|
||||
pin_auth = hmac_sha256(PinToken, req.cdh)[:16]
|
||||
req = FidoRequest(
|
||||
pin_protocol=1, pin_auth=pin_auth, options={"rk": True}, rp = rp,
|
||||
pin_protocol=1,
|
||||
pin_auth=pin_auth,
|
||||
options={"rk": True},
|
||||
rp=rp,
|
||||
)
|
||||
reg = device.sendMC(*req.toMC())
|
||||
regs.append(reg)
|
||||
@@ -208,19 +225,21 @@ class TestCredentialManagement(object):
|
||||
# delete the middle one
|
||||
creds = CredMgmt.enumerate_creds(reg.auth_data.rp_id_hash)
|
||||
for cred in creds:
|
||||
if cred[7]['id'] == regs[1].auth_data.credential_data.credential_id:
|
||||
if cred[7]["id"] == regs[1].auth_data.credential_data.credential_id:
|
||||
break
|
||||
|
||||
assert cred[7]['id'] == regs[1].auth_data.credential_data.credential_id
|
||||
assert cred[7]["id"] == regs[1].auth_data.credential_data.credential_id
|
||||
|
||||
cred = {"id": cred[7]['id'], "type": "public-key"}
|
||||
CredMgmt.delete_cred( cred )
|
||||
cred = {"id": cred[7]["id"], "type": "public-key"}
|
||||
CredMgmt.delete_cred(cred)
|
||||
|
||||
# Check one less enumerates
|
||||
res = CredMgmt.enumerate_creds(regs[0].auth_data.rp_id_hash)
|
||||
assert len(res) == 2
|
||||
|
||||
def test_multiple_creds_per_multiple_rps(self, device, PinToken, CredMgmt, MC_RK_Res):
|
||||
def test_multiple_creds_per_multiple_rps(
|
||||
self, device, PinToken, CredMgmt, MC_RK_Res
|
||||
):
|
||||
res = CredMgmt.enumerate_rps()
|
||||
assert len(res) == 2
|
||||
|
||||
@@ -232,11 +251,14 @@ class TestCredentialManagement(object):
|
||||
|
||||
# create 3 new credentials per RP
|
||||
for rp in new_rps:
|
||||
for i in range(0,3):
|
||||
for i in range(0, 3):
|
||||
req = FidoRequest()
|
||||
pin_auth = hmac_sha256(PinToken, req.cdh)[:16]
|
||||
req = FidoRequest(
|
||||
pin_protocol=1, pin_auth=pin_auth, options={"rk": True}, rp = rp,
|
||||
pin_protocol=1,
|
||||
pin_auth=pin_auth,
|
||||
options={"rk": True},
|
||||
rp=rp,
|
||||
)
|
||||
reg = device.sendMC(*req.toMC())
|
||||
|
||||
@@ -244,12 +266,16 @@ class TestCredentialManagement(object):
|
||||
assert len(res) == 5
|
||||
|
||||
for rp in res:
|
||||
if rp[3]['id'][:12] == 'new_example_':
|
||||
creds = CredMgmt.enumerate_creds(sha256( rp[3]['id'].encode('utf8') ))
|
||||
if rp[3]["id"][:12] == "new_example_":
|
||||
creds = CredMgmt.enumerate_creds(sha256(rp[3]["id"].encode("utf8")))
|
||||
assert len(creds) == 3
|
||||
|
||||
@pytest.mark.parametrize("enumeration_test", [_test_enumeration, _test_enumeration_interleaved])
|
||||
def test_multiple_enumeration(self, device, PinToken, MC_RK_Res, CredMgmt, enumeration_test):
|
||||
@pytest.mark.parametrize(
|
||||
"enumeration_test", [_test_enumeration, _test_enumeration_interleaved]
|
||||
)
|
||||
def test_multiple_enumeration(
|
||||
self, device, PinToken, MC_RK_Res, CredMgmt, enumeration_test
|
||||
):
|
||||
""" Test enumerate still works after different commands """
|
||||
|
||||
res = CredMgmt.enumerate_rps()
|
||||
@@ -266,18 +292,19 @@ class TestCredentialManagement(object):
|
||||
|
||||
# create 3 new credentials per RP
|
||||
for rp in new_rps:
|
||||
for i in range(0,rp['count']):
|
||||
for i in range(0, rp["count"]):
|
||||
req = FidoRequest()
|
||||
pin_auth = hmac_sha256(PinToken, req.cdh)[:16]
|
||||
req = FidoRequest(
|
||||
pin_protocol=1, pin_auth=pin_auth, options={"rk": True}, rp = {
|
||||
"id": rp["id"], "name": rp["name"]
|
||||
},
|
||||
pin_protocol=1,
|
||||
pin_auth=pin_auth,
|
||||
options={"rk": True},
|
||||
rp={"id": rp["id"], "name": rp["name"]},
|
||||
)
|
||||
reg = device.sendMC(*req.toMC())
|
||||
|
||||
# Now expect creds from this RP
|
||||
expected_enumeration[rp['id']] = rp['count']
|
||||
expected_enumeration[rp["id"]] = rp["count"]
|
||||
|
||||
enumeration_test(CredMgmt, expected_enumeration)
|
||||
enumeration_test(CredMgmt, expected_enumeration)
|
||||
@@ -287,9 +314,12 @@ class TestCredentialManagement(object):
|
||||
enumeration_test(CredMgmt, expected_enumeration)
|
||||
enumeration_test(CredMgmt, expected_enumeration)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("enumeration_test", [_test_enumeration, _test_enumeration_interleaved])
|
||||
def test_multiple_enumeration_with_deletions(self, device, PinToken, MC_RK_Res, CredMgmt, enumeration_test):
|
||||
@pytest.mark.parametrize(
|
||||
"enumeration_test", [_test_enumeration, _test_enumeration_interleaved]
|
||||
)
|
||||
def test_multiple_enumeration_with_deletions(
|
||||
self, device, PinToken, MC_RK_Res, CredMgmt, enumeration_test
|
||||
):
|
||||
""" Create each credential in random order. Test enumerate still works after randomly deleting each credential"""
|
||||
|
||||
res = CredMgmt.enumerate_rps()
|
||||
@@ -308,14 +338,15 @@ class TestCredentialManagement(object):
|
||||
|
||||
# create new credentials per RP in random order
|
||||
for rp in new_rps:
|
||||
for i in range(0,rp['count']):
|
||||
for i in range(0, rp["count"]):
|
||||
req = FidoRequest()
|
||||
pin_auth = hmac_sha256(PinToken, req.cdh)[:16]
|
||||
req = FidoRequest(
|
||||
pin_protocol=1, pin_auth=pin_auth, options={"rk": True}, rp = {
|
||||
"id": rp["id"], "name": rp["name"]
|
||||
},
|
||||
user = generate_user_maximum(),
|
||||
pin_protocol=1,
|
||||
pin_auth=pin_auth,
|
||||
options={"rk": True},
|
||||
rp={"id": rp["id"], "name": rp["name"]},
|
||||
user=generate_user_maximum(),
|
||||
)
|
||||
reg_requests.append(req)
|
||||
|
||||
@@ -324,10 +355,10 @@ class TestCredentialManagement(object):
|
||||
reg_requests.remove(req)
|
||||
device.sendMC(*req.toMC())
|
||||
|
||||
if req.rp['id'] not in expected_enumeration:
|
||||
expected_enumeration[req.rp['id']] = 1
|
||||
if req.rp["id"] not in expected_enumeration:
|
||||
expected_enumeration[req.rp["id"]] = 1
|
||||
else:
|
||||
expected_enumeration[req.rp['id']] += 1
|
||||
expected_enumeration[req.rp["id"]] += 1
|
||||
|
||||
enumeration_test(CredMgmt, expected_enumeration)
|
||||
|
||||
@@ -338,13 +369,13 @@ class TestCredentialManagement(object):
|
||||
|
||||
num = expected_enumeration[rp]
|
||||
|
||||
index = 0 if num == 1 else random.randint(0,num - 1)
|
||||
cred = CredMgmt.enumerate_creds(sha256( rp.encode('utf8') ))[index]
|
||||
index = 0 if num == 1 else random.randint(0, num - 1)
|
||||
cred = CredMgmt.enumerate_creds(sha256(rp.encode("utf8")))[index]
|
||||
|
||||
# print('Delete %d index (%d total) cred of %s' % (index, expected_enumeration[rp], rp))
|
||||
CredMgmt.delete_cred( {"id": cred[7]['id'], "type": "public-key"} )
|
||||
CredMgmt.delete_cred({"id": cred[7]["id"], "type": "public-key"})
|
||||
|
||||
expected_enumeration[rp] -=1
|
||||
expected_enumeration[rp] -= 1
|
||||
if expected_enumeration[rp] == 0:
|
||||
del expected_enumeration[rp]
|
||||
|
||||
@@ -353,7 +384,6 @@ class TestCredentialManagement(object):
|
||||
|
||||
enumeration_test(CredMgmt, expected_enumeration)
|
||||
|
||||
|
||||
def _test_wrong_pinauth(self, device, cmd, PinToken):
|
||||
|
||||
credMgmt = CredMgmtWrongPinAuth(device, PinToken)
|
||||
@@ -371,7 +401,7 @@ class TestCredentialManagement(object):
|
||||
credMgmt = CredMgmtWrongPinAuth(device, PinToken)
|
||||
|
||||
for i in range(2):
|
||||
time.sleep(.2)
|
||||
time.sleep(0.2)
|
||||
with pytest.raises(CtapError) as e:
|
||||
cmd(credMgmt)
|
||||
assert e.value.code == CtapError.ERR.PIN_AUTH_INVALID
|
||||
@@ -384,7 +414,7 @@ class TestCredentialManagement(object):
|
||||
credMgmt = CredMgmtWrongPinAuth(device, PinToken)
|
||||
|
||||
for i in range(2):
|
||||
time.sleep(.2)
|
||||
time.sleep(0.2)
|
||||
with pytest.raises(CtapError) as e:
|
||||
cmd(credMgmt)
|
||||
assert e.value.code == CtapError.ERR.PIN_AUTH_INVALID
|
||||
@@ -393,15 +423,16 @@ class TestCredentialManagement(object):
|
||||
cmd(credMgmt)
|
||||
assert e.value.code == CtapError.ERR.PIN_BLOCKED
|
||||
|
||||
|
||||
class TestCredProtect(object):
|
||||
def test_credProtect_0(self,resetDevice):
|
||||
def test_credProtect_0(self, resetDevice):
|
||||
req = FidoRequest(extensions={"credProtect": 0}, options={"rk": True})
|
||||
res = resetDevice.sendMC(*req.toMC())
|
||||
|
||||
if res.auth_data.extensions:
|
||||
assert "credProtect" not in res.auth_data.extensions
|
||||
|
||||
def test_credProtect_1(self,device):
|
||||
def test_credProtect_1(self, device):
|
||||
req = FidoRequest(extensions={"credProtect": 1}, options={"rk": True})
|
||||
MCRes = device.sendMC(*req.toMC())
|
||||
|
||||
@@ -410,7 +441,10 @@ class TestCredProtect(object):
|
||||
|
||||
req = FidoRequest(
|
||||
allow_list=[
|
||||
{"id": MCRes.auth_data.credential_data.credential_id, "type": "public-key"}
|
||||
{
|
||||
"id": MCRes.auth_data.credential_data.credential_id,
|
||||
"type": "public-key",
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
@@ -418,7 +452,7 @@ class TestCredProtect(object):
|
||||
verify(MCRes, GARes, req.cdh)
|
||||
assert (GARes.auth_data.flags & (1 << 2)) == 0
|
||||
|
||||
def test_credProtect_2_allow_list(self,device):
|
||||
def test_credProtect_2_allow_list(self, device):
|
||||
""" credProtect level 2 shouldn't need UV if allow_list is specified """
|
||||
req = FidoRequest(extensions={"credProtect": 2}, options={"rk": True})
|
||||
MCRes = device.sendMC(*req.toMC())
|
||||
@@ -428,7 +462,10 @@ class TestCredProtect(object):
|
||||
|
||||
req = FidoRequest(
|
||||
allow_list=[
|
||||
{"id": MCRes.auth_data.credential_data.credential_id, "type": "public-key"}
|
||||
{
|
||||
"id": MCRes.auth_data.credential_data.credential_id,
|
||||
"type": "public-key",
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
@@ -436,7 +473,7 @@ class TestCredProtect(object):
|
||||
verify(MCRes, GARes, req.cdh)
|
||||
assert (GARes.auth_data.flags & (1 << 2)) == 0
|
||||
|
||||
def test_credProtect_2_no_allow_list(self,device):
|
||||
def test_credProtect_2_no_allow_list(self, device):
|
||||
device.reset()
|
||||
req = FidoRequest(extensions={"credProtect": 2}, options={"rk": True})
|
||||
MCRes = device.sendMC(*req.toMC())
|
||||
@@ -450,7 +487,7 @@ class TestCredProtect(object):
|
||||
GARes = device.sendGA(*req.toGA())
|
||||
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
|
||||
|
||||
def test_credProtect_3_allow_list_and_no_allow_list(self,device):
|
||||
def test_credProtect_3_allow_list_and_no_allow_list(self, device):
|
||||
""" credProtect level 3 requires UV """
|
||||
device.reset()
|
||||
req = FidoRequest(extensions={"credProtect": 3}, options={"rk": True})
|
||||
@@ -461,7 +498,10 @@ class TestCredProtect(object):
|
||||
|
||||
req = FidoRequest(
|
||||
allow_list=[
|
||||
{"id": MCRes.auth_data.credential_data.credential_id, "type": "public-key"}
|
||||
{
|
||||
"id": MCRes.auth_data.credential_data.credential_id,
|
||||
"type": "public-key",
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
@@ -475,16 +515,22 @@ class TestCredProtect(object):
|
||||
GARes = device.sendGA(*req.toGA())
|
||||
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
|
||||
|
||||
def test_credProtect_3_success(self,device):
|
||||
def test_credProtect_3_success(self, device):
|
||||
device.reset()
|
||||
|
||||
# Set a PIN
|
||||
pin = '1234'
|
||||
pin = "1234"
|
||||
device.client.pin_protocol.set_pin(pin)
|
||||
pin_token = device.client.pin_protocol.get_pin_token(pin)
|
||||
req = FidoRequest()
|
||||
pin_auth = hmac_sha256(pin_token, req.cdh)[:16]
|
||||
req = FidoRequest(req, pin_auth = pin_auth, pin_protocol = 1, extensions={"credProtect": 3}, options={"rk": True})
|
||||
req = FidoRequest(
|
||||
req,
|
||||
pin_auth=pin_auth,
|
||||
pin_protocol=1,
|
||||
extensions={"credProtect": 3},
|
||||
options={"rk": True},
|
||||
)
|
||||
|
||||
MCRes = device.sendMC(*req.toMC())
|
||||
|
||||
@@ -492,14 +538,16 @@ class TestCredProtect(object):
|
||||
assert (MCRes.auth_data.flags & (1 << 2)) != 0
|
||||
|
||||
req = FidoRequest(
|
||||
pin = pin,
|
||||
pin_auth = pin_auth,
|
||||
pin=pin,
|
||||
pin_auth=pin_auth,
|
||||
allow_list=[
|
||||
{"id": MCRes.auth_data.credential_data.credential_id, "type": "public-key"}
|
||||
]
|
||||
{
|
||||
"id": MCRes.auth_data.credential_data.credential_id,
|
||||
"type": "public-key",
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
GARes = device.sendGA(*req.toGA())
|
||||
assert (GARes.auth_data.flags & (1 << 2)) != 0
|
||||
verify(MCRes, GARes, req.cdh)
|
||||
|
||||
|
||||
Vendored
+94
-60
@@ -6,6 +6,7 @@ import hashlib
|
||||
from fido2.ctap1 import ApduError
|
||||
from fido2.ctap2 import CtapError
|
||||
from fido2.utils import hmac_sha256, sha256, int2bytes
|
||||
|
||||
try:
|
||||
from solo.client import SoloClient
|
||||
except:
|
||||
@@ -15,13 +16,14 @@ from solo.commands import SoloExtension
|
||||
|
||||
from tests.utils import shannon_entropy, verify, FidoRequest
|
||||
|
||||
|
||||
def convert_der_sig_to_padded_binary(der):
|
||||
r,s = ecdsa.util.sigdecode_der(der,None)
|
||||
r, s = ecdsa.util.sigdecode_der(der, None)
|
||||
r = int2bytes(r)
|
||||
s = int2bytes(s)
|
||||
|
||||
r = (b'\x00' * (32 - len(r))) + r
|
||||
s = (b'\x00' * (32 - len(s))) + s
|
||||
r = (b"\x00" * (32 - len(r))) + r
|
||||
s = (b"\x00" * (32 - len(s))) + s
|
||||
return r + s
|
||||
|
||||
|
||||
@@ -35,13 +37,12 @@ def solo(request, device):
|
||||
sc.use_hid()
|
||||
return sc
|
||||
|
||||
IS_EXPERIMENTAL = '--experimental' in sys.argv
|
||||
IS_NFC = '--nfc' in sys.argv
|
||||
|
||||
@pytest.mark.skipif(
|
||||
IS_NFC,
|
||||
reason="Wrong transport"
|
||||
)
|
||||
IS_EXPERIMENTAL = "--experimental" in sys.argv
|
||||
IS_NFC = "--nfc" in sys.argv
|
||||
|
||||
|
||||
@pytest.mark.skipif(IS_NFC, reason="Wrong transport")
|
||||
class TestSolo(object):
|
||||
def test_solo(self, solo):
|
||||
pass
|
||||
@@ -61,10 +62,9 @@ class TestSolo(object):
|
||||
assert len(solo.solo_version()) == 4
|
||||
|
||||
def test_version_hid(self, solo):
|
||||
data = solo.send_data_hid(0x61, b'')
|
||||
data = solo.send_data_hid(0x61, b"")
|
||||
assert len(data) == 4
|
||||
print(f'Version is {data[0]}.{data[1]}.{data[2]} locked?=={data[3]}')
|
||||
|
||||
print(f"Version is {data[0]}.{data[1]}.{data[2]} locked?=={data[3]}")
|
||||
|
||||
def test_bootloader_not(self, solo):
|
||||
with pytest.raises(ApduError) as e:
|
||||
@@ -88,71 +88,85 @@ class TestSolo(object):
|
||||
solo.exchange = exchange
|
||||
|
||||
@pytest.mark.skipif(not IS_EXPERIMENTAL, reason="Experimental")
|
||||
def test_load_external_key_wrong_length(self,solo, ):
|
||||
def test_load_external_key_wrong_length(
|
||||
self,
|
||||
solo,
|
||||
):
|
||||
ext_key_cmd = 0x62
|
||||
with pytest.raises(CtapError) as e:
|
||||
solo.send_data_hid(ext_key_cmd, b'\x01' + b'wrong length'*2)
|
||||
assert(e.value.code == CtapError.ERR.INVALID_LENGTH)
|
||||
solo.send_data_hid(ext_key_cmd, b"\x01" + b"wrong length" * 2)
|
||||
assert e.value.code == CtapError.ERR.INVALID_LENGTH
|
||||
|
||||
@pytest.mark.skipif(not IS_EXPERIMENTAL, reason="Experimental")
|
||||
def test_load_external_key_invalidate_old_cred(self,solo, device, MCRes, GARes):
|
||||
def test_load_external_key_invalidate_old_cred(self, solo, device, MCRes, GARes):
|
||||
ext_key_cmd = 0x62
|
||||
verify(MCRes, GARes)
|
||||
print ('Enter user presence THREE times.')
|
||||
solo.send_data_hid(ext_key_cmd, b'\x01' + b'Z' * 32 + b'dicekeys key')
|
||||
print("Enter user presence THREE times.")
|
||||
solo.send_data_hid(ext_key_cmd, b"\x01" + b"Z" * 32 + b"dicekeys key")
|
||||
|
||||
# Old credential should not exist now.
|
||||
with pytest.raises(CtapError) as e:
|
||||
ga_bad_req = FidoRequest(GARes)
|
||||
device.sendGA(*ga_bad_req.toGA())
|
||||
assert(e.value.code == CtapError.ERR.NO_CREDENTIALS)
|
||||
|
||||
|
||||
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
|
||||
|
||||
@pytest.mark.skipif(not IS_EXPERIMENTAL, reason="Experimental")
|
||||
def test_load_external_key(self,solo, device,):
|
||||
def test_load_external_key(
|
||||
self,
|
||||
solo,
|
||||
device,
|
||||
):
|
||||
|
||||
key_A = b'A' * 32
|
||||
key_B = b'B' * 32
|
||||
key_A = b"A" * 32
|
||||
key_B = b"B" * 32
|
||||
ext_state = b"I'm a dicekey key"
|
||||
version = b'\x01'
|
||||
version = b"\x01"
|
||||
|
||||
ext_key_cmd = 0x62
|
||||
print ('Enter user presence THREE times.')
|
||||
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())
|
||||
|
||||
allow_list = [{"id":mc_A_res.auth_data.credential_data.credential_id, "type":"public-key"}]
|
||||
allow_list = [
|
||||
{
|
||||
"id": mc_A_res.auth_data.credential_data.credential_id,
|
||||
"type": "public-key",
|
||||
}
|
||||
]
|
||||
ga_A_req = FidoRequest(mc_A_req, allow_list=allow_list)
|
||||
ga_A_res = device.sendGA(*FidoRequest(ga_A_req).toGA())
|
||||
|
||||
verify(mc_A_res, ga_A_res, ga_A_req.cdh)
|
||||
|
||||
# Load up Key B and verify cred A doesn't exist.
|
||||
print ('Enter user presence THREE times.')
|
||||
print("Enter user presence THREE times.")
|
||||
solo.send_data_hid(ext_key_cmd, version + key_B + ext_state)
|
||||
with pytest.raises(CtapError) as e:
|
||||
ga_A_res = device.sendGA(*FidoRequest(ga_A_req).toGA())
|
||||
assert(e.value.code == CtapError.ERR.NO_CREDENTIALS)
|
||||
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
|
||||
|
||||
# Load up Key A and verify cred A is back.
|
||||
print ('Enter user presence THREE times.')
|
||||
print("Enter user presence THREE times.")
|
||||
solo.send_data_hid(ext_key_cmd, version + key_A + ext_state)
|
||||
ga_A_res = device.sendGA(*FidoRequest(ga_A_req).toGA())
|
||||
verify(mc_A_res, ga_A_res, ga_A_req.cdh)
|
||||
|
||||
@pytest.mark.skipif(not IS_EXPERIMENTAL, reason="Experimental")
|
||||
def test_ext_state_in_credential_id(self,solo, device,):
|
||||
def test_ext_state_in_credential_id(
|
||||
self,
|
||||
solo,
|
||||
device,
|
||||
):
|
||||
|
||||
key_A = b'A' * 32
|
||||
key_A = b"A" * 32
|
||||
ext_state = b"I'm a dicekey key abc1234!!@@##"
|
||||
version = b'\x01'
|
||||
version = b"\x01"
|
||||
|
||||
ext_key_cmd = 0x62
|
||||
print ('Enter user presence THREE times.')
|
||||
print("Enter user presence THREE times.")
|
||||
solo.send_data_hid(ext_key_cmd, version + key_A + ext_state)
|
||||
|
||||
# New credential works.
|
||||
@@ -162,15 +176,20 @@ class TestSolo(object):
|
||||
assert ext_state in mc_A_res.auth_data.credential_data.credential_id
|
||||
|
||||
@pytest.mark.skipif(not IS_EXPERIMENTAL, reason="Experimental")
|
||||
def test_backup_credential_is_generated_correctly(self,solo, device,):
|
||||
def test_backup_credential_is_generated_correctly(
|
||||
self,
|
||||
solo,
|
||||
device,
|
||||
):
|
||||
import seedweed
|
||||
from binascii import hexlify
|
||||
key_A = b'A' * 32
|
||||
|
||||
key_A = b"A" * 32
|
||||
ext_state = b"I'm a dicekey key!"
|
||||
version = b'\x01'
|
||||
version = b"\x01"
|
||||
|
||||
ext_key_cmd = 0x62
|
||||
print ('Enter user presence THREE times.')
|
||||
print("Enter user presence THREE times.")
|
||||
solo.send_data_hid(ext_key_cmd, version + key_A + ext_state)
|
||||
|
||||
# New credential works.
|
||||
@@ -190,65 +209,80 @@ class TestSolo(object):
|
||||
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)
|
||||
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
|
||||
)
|
||||
_, _, 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
|
||||
hashfunc=hashlib.sha256,
|
||||
)
|
||||
|
||||
# @pytest.mark.skipif(False, reason="Experimental")
|
||||
@pytest.mark.skipif(not IS_EXPERIMENTAL, reason="Experimental")
|
||||
def test_seedweed_vectors_make_credential(self,solo, device,):
|
||||
def test_seedweed_vectors_make_credential(
|
||||
self,
|
||||
solo,
|
||||
device,
|
||||
):
|
||||
import seedweed
|
||||
from binascii import hexlify
|
||||
version = b'\x01'
|
||||
|
||||
for i,v in enumerate(seedweed.load_test_vectors(shortlist=True)):
|
||||
print (f'{i}) Enter user presence THREE times.')
|
||||
version = b"\x01"
|
||||
|
||||
for i, v in enumerate(seedweed.load_test_vectors(shortlist=True)):
|
||||
print(f"{i}) Enter user presence THREE times.")
|
||||
ext_key_cmd = 0x62
|
||||
solo.send_data_hid(ext_key_cmd, version + v['seed'] + b'')
|
||||
solo.send_data_hid(ext_key_cmd, version + v["seed"] + b"")
|
||||
|
||||
mc_req = FidoRequest(rp = {"id": v['rp_id'], "name": "seedweed"})
|
||||
mc_req = FidoRequest(rp={"id": v["rp_id"], "name": "seedweed"})
|
||||
mc_res = device.sendMC(*mc_req.toMC())
|
||||
seedweed.conformance.verify_make_credential(
|
||||
v,
|
||||
mc_res.auth_data.credential_data.credential_id,
|
||||
mc_res.auth_data.credential_data.public_key[-2] +
|
||||
mc_res.auth_data.credential_data.public_key[-3]
|
||||
mc_res.auth_data.credential_data.public_key[-2]
|
||||
+ mc_res.auth_data.credential_data.public_key[-3],
|
||||
)
|
||||
|
||||
@pytest.mark.skipif(not IS_EXPERIMENTAL, reason="Experimental")
|
||||
def test_seedweed_vectors_get_assertion(self,solo, device,):
|
||||
def test_seedweed_vectors_get_assertion(
|
||||
self,
|
||||
solo,
|
||||
device,
|
||||
):
|
||||
import seedweed
|
||||
from binascii import hexlify
|
||||
version = b'\x01'
|
||||
|
||||
for i,v in enumerate(seedweed.load_test_vectors(shortlist=True)):
|
||||
print (f'{i}) Enter user presence THREE times.')
|
||||
version = b"\x01"
|
||||
|
||||
for i, v in enumerate(seedweed.load_test_vectors(shortlist=True)):
|
||||
print(f"{i}) Enter user presence THREE times.")
|
||||
ext_key_cmd = 0x62
|
||||
solo.send_data_hid(ext_key_cmd, version + v['seed'] + b'')
|
||||
solo.send_data_hid(ext_key_cmd, version + v["seed"] + b"")
|
||||
|
||||
allow_list = [{"id": v['credential_id'], "type": "public-key"}]
|
||||
ga_req = FidoRequest(rp = {"id": v['rp_id'], "name": "seedweed"}, allow_list = allow_list)
|
||||
allow_list = [{"id": v["credential_id"], "type": "public-key"}]
|
||||
ga_req = FidoRequest(
|
||||
rp={"id": v["rp_id"], "name": "seedweed"}, allow_list=allow_list
|
||||
)
|
||||
ga_res = device.sendGA(*ga_req.toGA())
|
||||
# print(v)
|
||||
# print(ga_res.auth_data + ga_req.cdh)
|
||||
|
||||
# assert ga_res.auth_data.rp_id_hash == reg.auth_data.rp_id_hash
|
||||
assert ga_res.credential["id"] == v['credential_id']
|
||||
assert ga_res.credential["id"] == v["credential_id"]
|
||||
# reg.auth_data.credential_data.credential_id
|
||||
|
||||
seedweed.conformance.verify_get_assertion(
|
||||
|
||||
Reference in New Issue
Block a user