Add black and pre-commit hook

This commit is contained in:
Nicolas Stalder
2019-08-08 03:05:15 +02:00
parent 1da43af14e
commit 87c3fdb8a1
17 changed files with 460 additions and 426 deletions
+6
View File
@@ -0,0 +1,6 @@
repos:
- repo: https://github.com/psf/black
rev: stable
hooks:
- id: black
language_version: python3.7
+14
View File
@@ -11,8 +11,22 @@ venv:
python3 -m venv venv
venv/bin/pip install -U pip
venv/bin/pip install -U -r requirements.txt
venv/bin/pip install -U -r dev-requirements.txt
venv/bin/precommit install
# re-run if dependencies change
update:
venv/bin/pip install -U pip
venv/bin/pip install -U -r requirements.txt
venv/bin/pip install -U -r dev-requirements.txt
# ensure this passes before commiting
check:
venv/bin/black --check tests/
# automatic code fixes
fix: black
black:
venv/bin/black tests/
+2
View File
@@ -0,0 +1,2 @@
black
pre-commit
+30 -34
View File
@@ -32,58 +32,55 @@ def is_simulation(pytestconfig):
def is_nfc(pytestconfig):
return pytestconfig.getoption("nfc")
@pytest.fixture(scope="module")
def info(device):
info = device.ctap2.get_info()
#print("data:", bytes(info))
#print("decoded:", cbor.decode_from(bytes(info)))
# print("data:", bytes(info))
# print("decoded:", cbor.decode_from(bytes(info)))
return info
@pytest.fixture(scope="module")
def MCRes(resetDevice,):
req = FidoRequest()
res = resetDevice.sendMC(
*req.toMC(),
)
setattr(res,'request',req)
res = resetDevice.sendMC(*req.toMC())
setattr(res, "request", req)
return res
@pytest.fixture(scope='class')
def GARes(device,MCRes):
req = FidoRequest(allow_list = [{
"id": MCRes.auth_data.credential_data.credential_id,
"type": "public-key",
}])
res = device.sendGA(
*req.toGA(),
@pytest.fixture(scope="class")
def GARes(device, MCRes):
req = FidoRequest(
allow_list=[
{"id": MCRes.auth_data.credential_data.credential_id, "type": "public-key"}
]
)
setattr(res,'request',req)
res = device.sendGA(*req.toGA())
setattr(res, "request", req)
return res
@pytest.fixture(scope="module")
def RegRes(resetDevice,):
req = FidoRequest()
res = resetDevice.register(
req.challenge, req.appid
)
setattr(res,'request',req)
res = resetDevice.register(req.challenge, req.appid)
setattr(res, "request", req)
return res
@pytest.fixture(scope='class')
@pytest.fixture(scope="class")
def AuthRes(device, RegRes):
req = FidoRequest()
res = device.authenticate(
req.challenge, req.appid, RegRes.key_handle
)
setattr(res,'request',req)
res = device.authenticate(req.challenge, req.appid, RegRes.key_handle)
setattr(res, "request", req)
return res
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def allowListItem(MCRes):
return
return
@pytest.fixture(scope="session")
def device(pytestconfig):
@@ -98,16 +95,19 @@ def device(pytestconfig):
return dev
@pytest.fixture(scope='class')
@pytest.fixture(scope="class")
def rebootedDevice(device):
device.reboot()
return device
@pytest.fixture(scope='module')
@pytest.fixture(scope="module")
def resetDevice(device):
device.reset()
return device
class Packet(object):
def __init__(self, data):
self.data = data
@@ -120,7 +120,6 @@ class Packet(object):
return Packet(data)
class TestDevice:
def __init__(self, tester=None):
self.origin = "https://examplo.org"
@@ -270,9 +269,7 @@ class TestDevice:
self.ctap2.reset()
def sendMC(self, *args, **kwargs):
attestation_object = self.ctap2.make_credential(
*args, **kwargs
)
attestation_object = self.ctap2.make_credential(*args, **kwargs)
if attestation_object:
verifier = Attestation.for_type(attestation_object.fmt)
client_data = args[0]
@@ -292,6 +289,5 @@ class TestDevice:
def sendPP(self, *args, **kwargs):
return self.client.pin_protocol.get_pin_token(*args, **kwargs)
def delay(secs):
time.sleep(secs)
+4 -7
View File
@@ -6,12 +6,12 @@ from fido2.ctap2 import ES256, PinProtocolV1, AttestedCredentialData
from tests.utils import *
def test_lockout(device,resetDevice):
pin = 'TestPin'
def test_lockout(device, resetDevice):
pin = "TestPin"
device.client.pin_protocol.set_pin(pin)
pin_token = device.client.pin_protocol.get_pin_token(pin)
req = FidoRequest(pin_token = pin_token)
req = FidoRequest(pin_token=pin_token)
req.pin_auth = hmac_sha256(pin_token, req.cdh)[:16]
@@ -23,9 +23,7 @@ def test_lockout(device,resetDevice):
err = [CtapError.ERR.PIN_BLOCKED, CtapError.ERR.PIN_INVALID]
with pytest.raises(CtapError) as e:
device.sendPP(
"WrongPin",
)
device.sendPP("WrongPin")
assert e.value.code == err or e.value.code in err
attempts = 8 - i
@@ -46,4 +44,3 @@ def test_lockout(device,resetDevice):
with pytest.raises(CtapError) as e:
device.sendPP(pin)
assert e.value.code == CtapError.ERR.PIN_BLOCKED
+55 -44
View File
@@ -5,11 +5,12 @@ from fido2.ctap2 import ES256, PinProtocolV1, AttestedCredentialData
from tests.utils import *
PIN1 = '123456789A'
PIN2 = 'ABCDEF'
PIN1 = "123456789A"
PIN2 = "ABCDEF"
@pytest.fixture(scope="module", params = [PIN1])
def SetPinRes(request,device):
@pytest.fixture(scope="module", params=[PIN1])
def SetPinRes(request, device):
device.reset()
pin = request.param
@@ -19,44 +20,41 @@ def SetPinRes(request,device):
pin_token = device.client.pin_protocol.get_pin_token(pin)
pin_auth = hmac_sha256(pin_token, req.cdh)[:16]
req = FidoRequest(req, pin_protocol = 1, pin_auth = pin_auth)
req = FidoRequest(req, pin_protocol=1, pin_auth=pin_auth)
res = device.sendMC(
*req.toMC(),
)
setattr(res,'request',req)
setattr(res,'PIN',pin)
res = device.sendMC(*req.toMC())
setattr(res, "request", req)
setattr(res, "PIN", pin)
return res
@pytest.fixture(scope="module")
def CPRes(request,device,SetPinRes):
def CPRes(request, device, SetPinRes):
res = device.sendCP(1, PinProtocolV1.CMD.GET_KEY_AGREEMENT)
return res
@pytest.fixture(scope="module")
def MCPinRes(device,SetPinRes):
def MCPinRes(device, SetPinRes):
req = FidoRequest(SetPinRes)
res = device.sendMC(
*req.toMC(),
)
setattr(res,'request',req)
res = device.sendMC(*req.toMC())
setattr(res, "request", req)
return res
@pytest.fixture(scope='class')
def GAPinRes(device,MCPinRes):
@pytest.fixture(scope="class")
def GAPinRes(device, MCPinRes):
req = FidoRequest(MCPinRes)
res = device.sendGA(
*req.toGA(),
)
setattr(res,'request',req)
res = device.sendGA(*req.toGA())
setattr(res, "request", req)
return res
class TestPin(object):
def test_pin(self,CPRes):
def test_pin(self, CPRes):
pass
def test_get_key_agreement_fields(self,CPRes):
def test_get_key_agreement_fields(self, CPRes):
key = CPRes[1]
assert "Is public key" and key[1] == 2
assert "Is P256" and key[-1] == 1
@@ -68,8 +66,7 @@ class TestPin(object):
reg = device.sendMC(*FidoRequest(SetPinRes).toMC())
assert reg.auth_data.flags & (1 << 2)
def test_change_pin(self, device, SetPinRes, ):
def test_change_pin(self, device, SetPinRes):
device.client.pin_protocol.change_pin(PIN1, PIN2)
pin_token = device.client.pin_protocol.get_pin_token(PIN2)
@@ -81,49 +78,61 @@ class TestPin(object):
reg = device.sendMC(*FidoRequest(SetPinRes).toMC())
auth = device.sendGA(
*FidoRequest(SetPinRes, allow_list = [{'type': 'public-key', 'id': reg.auth_data.credential_data.credential_id}]
).toGA())
*FidoRequest(
SetPinRes,
allow_list=[
{
"type": "public-key",
"id": reg.auth_data.credential_data.credential_id,
}
],
).toGA()
)
assert reg.auth_data.flags & (1 << 2)
assert auth.auth_data.flags & (1 << 2)
verify(reg,auth, cdh = SetPinRes.request.cdh)
verify(reg, auth, cdh=SetPinRes.request.cdh)
def test_get_no_pin_auth(self, device, SetPinRes):
reg = device.sendMC(*FidoRequest(SetPinRes).toMC())
allow_list = [{'type': 'public-key', 'id': reg.auth_data.credential_data.credential_id}]
allow_list = [
{"type": "public-key", "id": reg.auth_data.credential_data.credential_id}
]
auth = device.sendGA(
*FidoRequest(SetPinRes, allow_list = allow_list, pin_auth = None, pin_protocol = None
).toGA())
*FidoRequest(
SetPinRes, allow_list=allow_list, pin_auth=None, pin_protocol=None
).toGA()
)
assert not (auth.auth_data.flags & (1 << 2))
with pytest.raises(CtapError) as e:
reg = device.sendMC(*FidoRequest(SetPinRes, pin_auth = None, pin_protocol = None).toMC())
reg = device.sendMC(
*FidoRequest(SetPinRes, pin_auth=None, pin_protocol=None).toMC()
)
assert(e.value.code == CtapError.ERR.PIN_REQUIRED)
assert e.value.code == CtapError.ERR.PIN_REQUIRED
def test_zero_length_pin_auth(self, device, SetPinRes):
with pytest.raises(CtapError) as e:
reg = device.sendMC(*FidoRequest(SetPinRes, pin_auth = b'',).toMC())
assert(e.value.code == CtapError.ERR.PIN_AUTH_INVALID)
reg = device.sendMC(*FidoRequest(SetPinRes, pin_auth=b"").toMC())
assert e.value.code == CtapError.ERR.PIN_AUTH_INVALID
with pytest.raises(CtapError) as e:
reg = device.sendGA(*FidoRequest(SetPinRes, pin_auth = b'',).toGA())
assert(e.value.code == CtapError.ERR.PIN_AUTH_INVALID)
reg = device.sendGA(*FidoRequest(SetPinRes, pin_auth=b"").toGA())
assert e.value.code == CtapError.ERR.PIN_AUTH_INVALID
def test_make_credential_no_pin(self, device, SetPinRes):
with pytest.raises(CtapError) as e:
reg = device.sendMC(*FidoRequest().toMC())
assert(e.value.code == CtapError.ERR.PIN_REQUIRED)
assert e.value.code == CtapError.ERR.PIN_REQUIRED
def test_get_assertion_no_pin(self, device, SetPinRes):
with pytest.raises(CtapError) as e:
reg = device.sendGA(*FidoRequest().toGA())
assert(e.value.code == CtapError.ERR.NO_CREDENTIALS)
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
def test_pin_attempts(device, SetPinRes):
@@ -152,7 +161,9 @@ def test_pin_attempts(device, SetPinRes):
device.reboot()
SetPinRes.request.pin_token = device.client.pin_protocol.get_pin_token(pin)
SetPinRes.request.pin_auth = hmac_sha256(SetPinRes.request.pin_token, SetPinRes.request.cdh)[:16]
SetPinRes.request.pin_auth = hmac_sha256(
SetPinRes.request.pin_token, SetPinRes.request.cdh
)[:16]
reg = device.sendMC(*FidoRequest(SetPinRes).toMC())
+15 -19
View File
@@ -5,53 +5,49 @@ from fido2.ctap2 import ES256, PinProtocolV1, AttestedCredentialData
from tests.utils import *
class TestSetPin(object):
def test_send_zero_length_pin_auth(self,resetDevice):
def test_send_zero_length_pin_auth(self, resetDevice):
with pytest.raises(CtapError) as e:
reg = resetDevice.sendMC(*FidoRequest(pin_auth = b'',).toMC())
assert(e.value.code == CtapError.ERR.PIN_NOT_SET)
reg = resetDevice.sendMC(*FidoRequest(pin_auth=b"").toMC())
assert e.value.code == CtapError.ERR.PIN_NOT_SET
with pytest.raises(CtapError) as e:
reg = resetDevice.sendGA(*FidoRequest(pin_auth = b'',).toGA())
assert(e.value.code in (CtapError.ERR.PIN_NOT_SET, CtapError.ERR.NO_CREDENTIALS))
reg = resetDevice.sendGA(*FidoRequest(pin_auth=b"").toGA())
assert e.value.code in (CtapError.ERR.PIN_NOT_SET, CtapError.ERR.NO_CREDENTIALS)
def test_set_pin(self,device):
device.client.pin_protocol.set_pin('TestPin')
def test_set_pin(self, device):
device.client.pin_protocol.set_pin("TestPin")
device.reset()
def test_set_pin_too_big(self, device):
with pytest.raises(CtapError) as e:
device.client.pin_protocol.set_pin('A' * 64)
device.client.pin_protocol.set_pin("A" * 64)
assert e.value.code == CtapError.ERR.PIN_POLICY_VIOLATION
def test_get_pin_token_but_no_pin_set(self, device):
with pytest.raises(CtapError) as e:
device.client.pin_protocol.get_pin_token('TestPin')
device.client.pin_protocol.get_pin_token("TestPin")
assert e.value.code == CtapError.ERR.PIN_NOT_SET
def test_change_pin_but_no_pin_set(self, device):
with pytest.raises(CtapError) as e:
device.client.pin_protocol.change_pin('TestPin', "1234")
device.client.pin_protocol.change_pin("TestPin", "1234")
assert e.value.code == CtapError.ERR.PIN_NOT_SET
def test_setting_pin_and_get_info(self, device):
device.client.pin_protocol.set_pin('TestPin')
device.client.pin_protocol.set_pin("TestPin")
with pytest.raises(CtapError) as e:
device.client.pin_protocol.set_pin('TestPin')
device.client.pin_protocol.set_pin("TestPin")
info = device.ctap2.get_info()
assert info.options['clientPin']
assert info.options["clientPin"]
pin_token = device.client.pin_protocol.get_pin_token('TestPin')
pin_token = device.client.pin_protocol.get_pin_token("TestPin")
res = device.sendCP(1, PinProtocolV1.CMD.GET_RETRIES)
assert res[3] == 8
device.reset()
+4 -5
View File
@@ -8,15 +8,16 @@ from tests.utils import FidoRequest
class TestCtap1WithCtap2(object):
def test_ctap1_register(self, RegRes):
RegRes.verify(RegRes.request.appid, RegRes.request.challenge)
def test_ctap1_authenticate(self, RegRes, AuthRes):
AuthRes.verify(AuthRes.request.appid, AuthRes.request.challenge, RegRes.public_key)
AuthRes.verify(
AuthRes.request.appid, AuthRes.request.challenge, RegRes.public_key
)
def test_authenticate_ctap1_through_ctap2(self, device, RegRes):
req = FidoRequest(allow_list = [{"id": RegRes.key_handle, "type": "public-key"}])
req = FidoRequest(allow_list=[{"id": RegRes.key_handle, "type": "public-key"}])
auth = device.sendGA(*req.toGA())
@@ -25,5 +26,3 @@ class TestCtap1WithCtap2(object):
)
auth.verify(req.cdh, credential_data.public_key)
assert auth.credential["id"] == RegRes.key_handle
+59 -69
View File
@@ -7,29 +7,26 @@ from tests.utils import *
class TestGetAssertion(object):
def test_get_assertion(self,device, MCRes, GARes):
def test_get_assertion(self, device, MCRes, GARes):
verify(MCRes, GARes)
def test_assertion_auth_data(self,GARes):
def test_assertion_auth_data(self, GARes):
assert len(GARes.auth_data) == 37
assert sha256(GARes.request.rp["id"].encode()) == GARes.auth_data.rp_id_hash
def test_Check_that_AT_flag_is_not_set(self, GARes):
assert (GARes.auth_data.flags & 0xF8) == 0
def test_that_user_credential_and_numberOfCredentials_are_not_present(self,GARes):
def test_that_user_credential_and_numberOfCredentials_are_not_present(self, GARes):
assert GARes.user == None
assert GARes.number_of_credentials == None
def test_empty_allowList(self,device):
def test_empty_allowList(self, device):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(allow_list = []).toGA()
)
device.sendGA(*FidoRequest(allow_list=[]).toGA())
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
def test_corrupt_credId(self,device,MCRes):
def test_corrupt_credId(self, device, MCRes):
# apply bit flip
badid = list(MCRes.auth_data.credential_data.credential_id[:])
badid[len(badid) // 2] = badid[len(badid) // 2] ^ 1
@@ -38,110 +35,103 @@ class TestGetAssertion(object):
allow_list = [{"id": badid, "type": "public-key"}]
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(allow_list = allow_list).toGA()
)
device.sendGA(*FidoRequest(allow_list=allow_list).toGA())
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
def test_missing_rp(self,device,GARes):
def test_missing_rp(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, rp = None).toGA()
)
device.sendGA(*FidoRequest(GARes, rp=None).toGA())
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_bad_rp(self,device,GARes):
def test_bad_rp(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, rp = {'id':{"type": "wrong"}}).toGA()
)
device.sendGA(*FidoRequest(GARes, rp={"id": {"type": "wrong"}}).toGA())
def test_missing_cdh(self,device,GARes):
def test_missing_cdh(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, cdh = None).toGA()
)
device.sendGA(*FidoRequest(GARes, cdh=None).toGA())
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_bad_cdh(self,device,GARes):
def test_bad_cdh(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(*FidoRequest(GARes, cdh={"type": "wrong"}).toGA())
def test_bad_allow_list(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(*FidoRequest(GARes, allow_list={"type": "wrong"}).toGA())
def test_bad_allow_list_item(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, cdh = {'type':'wrong'}).toGA()
*FidoRequest(
GARes, allow_list=["wrong"] + GARes.request.allow_list
).toGA()
)
def test_bad_allow_list(self,device,GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, allow_list = {'type':'wrong'}).toGA()
)
def test_unknown_option(self, device, GARes):
device.sendGA(*FidoRequest(GARes, options={"unknown": True}).toGA())
def test_bad_allow_list_item(self,device,GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, allow_list = ['wrong'] + GARes.request.allow_list).toGA(),
)
def test_unknown_option(self,device,GARes):
device.sendGA(
*FidoRequest(GARes, options = {'unknown': True}).toGA(),
)
def test_option_uv(self,device,info,GARes):
def test_option_uv(self, device, info, GARes):
if "uv" in info.options:
if info.options["uv"]:
res = device.sendGA(
*FidoRequest(GARes, options = {"uv": True},).toGA()
)
res = device.sendGA(*FidoRequest(GARes, options={"uv": True}).toGA())
assert res.auth_data.flags & (1 << 2)
def test_option_up(self,device,info,GARes):
def test_option_up(self, device, info, GARes):
if "up" in info.options:
if info.options["up"]:
res = device.sendGA(
*FidoRequest(GARes, options = {"up": True},).toGA()
)
res = device.sendGA(*FidoRequest(GARes, options={"up": True}).toGA())
assert res.auth_data.flags & (1 << 0)
def test_allow_list_fake_item(self,device,GARes):
def test_allow_list_fake_item(self, device, GARes):
device.sendGA(
*FidoRequest(GARes, allow_list = [{"type": "rot13", "id": b"1234"}] + GARes.request.allow_list).toGA(),
*FidoRequest(
GARes,
allow_list=[{"type": "rot13", "id": b"1234"}]
+ GARes.request.allow_list,
).toGA()
)
def test_allow_list_missing_field(self,device,GARes):
def test_allow_list_missing_field(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, allow_list = [{"id": b"1234"}] + GARes.request.allow_list).toGA(),
*FidoRequest(
GARes, allow_list=[{"id": b"1234"}] + GARes.request.allow_list
).toGA()
)
def test_allow_list_field_wrong_type(self,device,GARes):
def test_allow_list_field_wrong_type(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, allow_list = [{"type": b"public-key","id": b"1234"}] + GARes.request.allow_list).toGA(),
*FidoRequest(
GARes,
allow_list=[{"type": b"public-key", "id": b"1234"}]
+ GARes.request.allow_list,
).toGA()
)
def test_allow_list_id_wrong_type(self,device,GARes):
def test_allow_list_id_wrong_type(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, allow_list = [{"type": b"public-key","id": 42}] + GARes.request.allow_list).toGA(),
*FidoRequest(
GARes,
allow_list=[{"type": b"public-key", "id": 42}]
+ GARes.request.allow_list,
).toGA()
)
def test_allow_list_missing_id(self,device,GARes):
def test_allow_list_missing_id(self, device, GARes):
with pytest.raises(CtapError) as e:
device.sendGA(
*FidoRequest(GARes, allow_list = [{"type": b"public-key"}] + GARes.request.allow_list).toGA(),
*FidoRequest(
GARes,
allow_list=[{"type": b"public-key"}] + GARes.request.allow_list,
).toGA()
)
class TestGetAssertionAfterBoot(object):
def test_assertion_after_reboot(self,rebootedDevice, MCRes, GARes):
def test_assertion_after_reboot(self, rebootedDevice, MCRes, GARes):
credential_data = AttestedCredentialData(MCRes.auth_data.credential_data)
verify(MCRes, GARes)
+8 -9
View File
@@ -5,6 +5,7 @@ from fido2.ctap import CtapError
from tests.utils import *
def test_get_info(info):
pass
@@ -17,23 +18,21 @@ def test_Check_pin_protocols_field(info):
if len(info.pin_protocols):
assert sum(info.pin_protocols) > 0
def test_Check_options_field(info):
for x in info.options:
assert info.options[x] in [True, False]
def test_Check_uv_option(device, info, ):
def test_Check_uv_option(device, info):
if "uv" in info.options:
if info.options["uv"]:
device.sendMC(
*FidoRequest().toMC(),
options = {"uv": True},
)
device.sendMC(*FidoRequest().toMC(), options={"uv": True})
def test_Check_up_option(device,info,):
def test_Check_up_option(device, info):
if "up" in info.options:
if info.options["up"]:
with pytest.raises(CtapError) as e:
device.sendMC(
*FidoRequest(options = {"up": True}).toMC(),
)
device.sendMC(*FidoRequest(options={"up": True}).toMC())
assert e.value.code == CtapError.ERR.INVALID_OPTION
+89 -94
View File
@@ -8,236 +8,231 @@ from tests.utils import FidoRequest
class TestMakeCredential(object):
def test_make_credential(self,MCRes):
def test_make_credential(self, MCRes):
pass
def test_attestation_format(self,MCRes):
def test_attestation_format(self, MCRes):
assert MCRes.fmt in ["packed", "tpm", "android-key", "adroid-safetynet"]
def test_authdata_length(self,MCRes):
def test_authdata_length(self, MCRes):
assert len(MCRes.auth_data) >= 77
def test_missing_cdh(self,device,MCRes):
req = FidoRequest(MCRes, cdh = None)
def test_missing_cdh(self, device, MCRes):
req = FidoRequest(MCRes, cdh=None)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_bad_type_cdh(self,device,MCRes):
req = FidoRequest(MCRes, cdh = 5)
def test_bad_type_cdh(self, device, MCRes):
req = FidoRequest(MCRes, cdh=5)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_missing_user(self,device,MCRes):
req = FidoRequest(MCRes, user = None)
def test_missing_user(self, device, MCRes):
req = FidoRequest(MCRes, user=None)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_bad_type_user(self,device,MCRes):
req = FidoRequest(MCRes, user = b'1234abcdf')
def test_bad_type_user(self, device, MCRes):
req = FidoRequest(MCRes, user=b"1234abcdf")
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_missing_rp(self,device,MCRes):
req = FidoRequest(MCRes, rp = None)
def test_missing_rp(self, device, MCRes):
req = FidoRequest(MCRes, rp=None)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_bad_type_rp(self,device,MCRes):
req = FidoRequest(MCRes, rp = b'1234abcdef')
def test_bad_type_rp(self, device, MCRes):
req = FidoRequest(MCRes, rp=b"1234abcdef")
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_missing_pubKeyCredParams(self,device,MCRes):
req = FidoRequest(MCRes, key_params = None)
def test_missing_pubKeyCredParams(self, device, MCRes):
req = FidoRequest(MCRes, key_params=None)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_bad_type_pubKeyCredParams(self,device,MCRes):
req = FidoRequest(MCRes, key_params = b'1234a')
def test_bad_type_pubKeyCredParams(self, device, MCRes):
req = FidoRequest(MCRes, key_params=b"1234a")
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_excludeList(self,device,MCRes):
req = FidoRequest(MCRes, exclude_list = 8)
def test_bad_type_excludeList(self, device, MCRes):
req = FidoRequest(MCRes, exclude_list=8)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_extensions(self,device,MCRes):
req = FidoRequest(MCRes, extensions = 8)
def test_bad_type_extensions(self, device, MCRes):
req = FidoRequest(MCRes, extensions=8)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_options(self,device,MCRes):
req = FidoRequest(MCRes, options = 8)
def test_bad_type_options(self, device, MCRes):
req = FidoRequest(MCRes, options=8)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_rp_name(self,device,MCRes):
req = FidoRequest(MCRes, rp = {"id": 'test.org', "name": 8, "icon": "icon"})
def test_bad_type_rp_name(self, device, MCRes):
req = FidoRequest(MCRes, rp={"id": "test.org", "name": 8, "icon": "icon"})
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_rp_id(self,device,MCRes):
req = FidoRequest(MCRes, rp = {"id": 8, "name": "name", "icon": "icon"})
def test_bad_type_rp_id(self, device, MCRes):
req = FidoRequest(MCRes, rp={"id": 8, "name": "name", "icon": "icon"})
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_rp_icon(self,device,MCRes):
req = FidoRequest(MCRes, rp = {"id": "test.org", "name": "name", "icon": 8})
def test_bad_type_rp_icon(self, device, MCRes):
req = FidoRequest(MCRes, rp={"id": "test.org", "name": "name", "icon": 8})
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_user_name(self,device,MCRes):
req = FidoRequest(MCRes, user = {"id": b"user_id", "name": 8})
def test_bad_type_user_name(self, device, MCRes):
req = FidoRequest(MCRes, user={"id": b"user_id", "name": 8})
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_user_id(self,device,MCRes):
req = FidoRequest(MCRes, user = {"id": "user_id", "name": "name"})
def test_bad_type_user_id(self, device, MCRes):
req = FidoRequest(MCRes, user={"id": "user_id", "name": "name"})
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_user_displayName(self,device,MCRes):
req = FidoRequest(MCRes, user = {"id": "user_id", "name": "name", "displayName": 8})
def test_bad_type_user_displayName(self, device, MCRes):
req = FidoRequest(
MCRes, user={"id": "user_id", "name": "name", "displayName": 8}
)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_user_icon(self,device,MCRes):
req = FidoRequest(MCRes, user = {"id": "user_id", "name": "name", "icon": 8})
def test_bad_type_user_icon(self, device, MCRes):
req = FidoRequest(MCRes, user={"id": "user_id", "name": "name", "icon": 8})
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_pubKeyCredParams(self,device,MCRes):
req = FidoRequest(MCRes, key_params = ['wrong'])
def test_bad_type_pubKeyCredParams(self, device, MCRes):
req = FidoRequest(MCRes, key_params=["wrong"])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_missing_pubKeyCredParams_type(self,device,MCRes):
req = FidoRequest(MCRes, key_params = [{"alg": ES256.ALGORITHM}])
def test_missing_pubKeyCredParams_type(self, device, MCRes):
req = FidoRequest(MCRes, key_params=[{"alg": ES256.ALGORITHM}])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_missing_pubKeyCredParams_alg(self,device,MCRes):
req = FidoRequest(MCRes, key_params = [{"type": "public-key"}])
def test_missing_pubKeyCredParams_alg(self, device, MCRes):
req = FidoRequest(MCRes, key_params=[{"type": "public-key"}])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_bad_type_pubKeyCredParams_alg(self,device,MCRes):
req = FidoRequest(MCRes, key_params = [{"alg": "7", "type": "public-key"}])
def test_bad_type_pubKeyCredParams_alg(self, device, MCRes):
req = FidoRequest(MCRes, key_params=[{"alg": "7", "type": "public-key"}])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_unsupported_algorithm(self,device,MCRes):
req = FidoRequest(MCRes, key_params = [{"alg": 1337, "type": "public-key"}])
def test_unsupported_algorithm(self, device, MCRes):
req = FidoRequest(MCRes, key_params=[{"alg": 1337, "type": "public-key"}])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
assert e.value.code == CtapError.ERR.UNSUPPORTED_ALGORITHM
def test_exclude_list(self,device,MCRes):
req = FidoRequest(MCRes, exclude_list= [{"id": b"1234", "type": "rot13"}])
def test_exclude_list(self, device, MCRes):
req = FidoRequest(MCRes, exclude_list=[{"id": b"1234", "type": "rot13"}])
device.sendMC(*req.toMC())
def test_exclude_list2(self,device,MCRes):
req = FidoRequest(MCRes, exclude_list= [{"id": b"1234", "type": "mangoPapayaCoconutNotAPublicKey"}])
def test_exclude_list2(self, device, MCRes):
req = FidoRequest(
MCRes,
exclude_list=[{"id": b"1234", "type": "mangoPapayaCoconutNotAPublicKey"}],
)
device.sendMC(*req.toMC())
def test_bad_type_exclude_list(self,device,MCRes):
req = FidoRequest(MCRes, exclude_list= ['1234'])
def test_bad_type_exclude_list(self, device, MCRes):
req = FidoRequest(MCRes, exclude_list=["1234"])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_missing_exclude_list_type(self,device,MCRes):
req = FidoRequest(MCRes, exclude_list= [{"id": b"1234"}])
def test_missing_exclude_list_type(self, device, MCRes):
req = FidoRequest(MCRes, exclude_list=[{"id": b"1234"}])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_missing_exclude_list_id(self,device,MCRes):
req = FidoRequest(MCRes, exclude_list= [{"type": "public-key"}])
def test_missing_exclude_list_id(self, device, MCRes):
req = FidoRequest(MCRes, exclude_list=[{"type": "public-key"}])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_exclude_list_id(self,device,MCRes):
req = FidoRequest(MCRes, exclude_list= [{"type": "public-key", "id": "1234"}])
def test_bad_type_exclude_list_id(self, device, MCRes):
req = FidoRequest(MCRes, exclude_list=[{"type": "public-key", "id": "1234"}])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_exclude_list_type(self,device,MCRes):
req = FidoRequest(MCRes, exclude_list= [{"type": b"public-key", "id": b"1234"}])
def test_bad_type_exclude_list_type(self, device, MCRes):
req = FidoRequest(MCRes, exclude_list=[{"type": b"public-key", "id": b"1234"}])
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
def test_bad_type_exclude_list_type(self,device,MCRes,GARes):
def test_bad_type_exclude_list_type(self, device, MCRes, GARes):
req = FidoRequest(MCRes, exclude_list=GARes.request.allow_list)
with pytest.raises(CtapError) as e:
device.sendMC(*req.toMC())
assert e.value.code == CtapError.ERR.CREDENTIAL_EXCLUDED
def test_unknown_option(self,device,MCRes):
req = FidoRequest(MCRes, options = {'unknown': False})
print('MC',req.toMC())
def test_unknown_option(self, device, MCRes):
req = FidoRequest(MCRes, options={"unknown": False})
print("MC", req.toMC())
device.sendMC(*req.toMC())
#self.testReset()
# self.testReset()
#self.testGA(
#"Send GA request with reset auth, expect NO_CREDENTIALS",
#rp["id"],
#cdh,
#allow_list,
#expectedError=CtapError.ERR.NO_CREDENTIALS,
#)
# self.testGA(
# "Send GA request with reset auth, expect NO_CREDENTIALS",
# rp["id"],
# cdh,
# allow_list,
# expectedError=CtapError.ERR.NO_CREDENTIALS,
# )
@@ -4,6 +4,7 @@ from fido2.ctap import CtapError
from tests.utils import *
def test_credential_resets(device, MCRes, GARes):
verify(MCRes, GARes)
device.reset()
+30 -39
View File
@@ -4,8 +4,9 @@ from fido2.ctap import CtapError
from tests.utils import *
@pytest.fixture(scope="module", params = ['', '123456'])
def SetPINRes(request,device,):
@pytest.fixture(scope="module", params=["", "123456"])
def SetPINRes(request, device):
device.reset()
@@ -17,66 +18,57 @@ def SetPINRes(request,device,):
pin_token = device.client.pin_protocol.get_pin_token(pin)
pin_auth = hmac_sha256(pin_token, req.cdh)[:16]
req = FidoRequest(req, pin_protocol = 1, pin_auth = pin_auth)
req = FidoRequest(req, pin_protocol=1, pin_auth=pin_auth)
res = device.sendMC(
*req.toMC(),
)
setattr(res,'request',req)
res = device.sendMC(*req.toMC())
setattr(res, "request", req)
return res
@pytest.fixture(scope="module")
def MC_RK_Res(device,SetPINRes):
req = FidoRequest(SetPINRes,options = {"rk": True})
res = device.sendMC(
*req.toMC(),
)
setattr(res,'request',req)
def MC_RK_Res(device, SetPINRes):
req = FidoRequest(SetPINRes, options={"rk": True})
res = device.sendMC(*req.toMC())
setattr(res, "request", req)
return res
@pytest.fixture(scope='class')
def GA_RK_Res(device,MC_RK_Res):
@pytest.fixture(scope="class")
def GA_RK_Res(device, MC_RK_Res):
req = FidoRequest(MC_RK_Res)
res = device.sendGA(
*req.toGA(),
)
setattr(res,'request',req)
res = device.sendGA(*req.toGA())
setattr(res, "request", req)
return res
class TestResidentKey(object):
def test_resident_key(self,MC_RK_Res, info):
def test_resident_key(self, MC_RK_Res, info):
pass
def test_resident_key_auth(self,MC_RK_Res, GA_RK_Res):
def test_resident_key_auth(self, MC_RK_Res, GA_RK_Res):
verify(MC_RK_Res, GA_RK_Res)
def test_user_info_returned(self,MC_RK_Res, GA_RK_Res):
def test_user_info_returned(self, MC_RK_Res, GA_RK_Res):
if not MC_RK_Res.request.pin_protocol:
assert "id" in GA_RK_Res.user.keys() and len(GA_RK_Res.user.keys()) == 1
def test_multiple_rk(self,device, MC_RK_Res,):
def test_multiple_rk(self, device, MC_RK_Res):
auths = []
regs = [MC_RK_Res]
for i in range(0,3):
req = FidoRequest(MC_RK_Res, user = generate_user())
res = device.sendMC( *req.toMC() )
for i in range(0, 3):
req = FidoRequest(MC_RK_Res, user=generate_user())
res = device.sendMC(*req.toMC())
regs.append(res)
req = FidoRequest(MC_RK_Res, user = generate_user())
res = device.sendGA( *req.toGA() )
req = FidoRequest(MC_RK_Res, user=generate_user())
res = device.sendGA(*req.toGA())
assert(res.number_of_credentials == 4)
assert res.number_of_credentials == 4
auths.append(res)
auths.append( device.ctap2.get_next_assertion() )
auths.append( device.ctap2.get_next_assertion() )
auths.append( device.ctap2.get_next_assertion() )
auths.append(device.ctap2.get_next_assertion())
auths.append(device.ctap2.get_next_assertion())
auths.append(device.ctap2.get_next_assertion())
with pytest.raises(CtapError) as e:
device.ctap2.get_next_assertion()
@@ -87,6 +79,5 @@ class TestResidentKey(object):
if y not in x.user.keys():
print("FAIL: %s was not in user: " % y, x.user)
for x,y in zip(regs, auths):
verify(x,y,req.cdh)
for x, y in zip(regs, auths):
verify(x, y, req.cdh)
+10 -14
View File
@@ -6,11 +6,8 @@ from fido2.hid import CTAPHID
from fido2.ctap import CtapError
class TestHID(object):
def test_long_ping(self,device):
def test_long_ping(self, device):
amt = 1000
pingdata = os.urandom(amt)
@@ -19,11 +16,10 @@ class TestHID(object):
t2 = time.time() * 1000
delt = t2 - t1
assert not ( delt > 555 * (amt / 1000) )
assert not (delt > 555 * (amt / 1000))
assert r == pingdata
def test_init(self, device, check_timeouts=False):
if check_timeouts:
with pytest.raises(socket.timeout):
@@ -32,7 +28,7 @@ class TestHID(object):
payload = b"\x11\x11\x11\x11\x11\x11\x11\x11"
r = device.send_data(CTAPHID.INIT, payload)
print(r)
assert(r[:8] == payload)
assert r[:8] == payload
def test_ping(self, device):
@@ -64,7 +60,7 @@ class TestHID(object):
def test_oversize_packet(self, device):
device.send_raw("\x81\x1d\xba\x00")
cmd, resp = device.recv_raw()
assert(resp[0] == CtapError.ERR.INVALID_LENGTH)
assert resp[0] == CtapError.ERR.INVALID_LENGTH
def test_skip_sequence_number(self, device):
r = device.send_data(CTAPHID.PING, "\x44" * 200)
@@ -74,7 +70,7 @@ class TestHID(object):
# skip 2
device.send_raw("\x03")
cmd, resp = device.recv_raw()
assert(resp[0] == CtapError.ERR.INVALID_SEQ)
assert resp[0] == CtapError.ERR.INVALID_SEQ
def test_resync_and_ping(self, device):
r = device.send_data(CTAPHID.INIT, "\x11\x22\x33\x44\x55\x66\x77\x88")
@@ -121,7 +117,7 @@ class TestHID(object):
assert r[0] == CtapError.ERR.TIMEOUT
assert delt < 1000 and delt > 400
def test_not_cont(self, device,check_timeouts=False):
def test_not_cont(self, device, check_timeouts=False):
device.send_data(CTAPHID.INIT, "\x11\x22\x33\x44\x55\x66\x77\x88")
device.send_raw("\x81\x04\x00")
device.send_raw("\x00")
@@ -137,7 +133,7 @@ class TestHID(object):
with pytest.raises(socket.timeout):
cmd, r = device.recv_raw() # timeout response
def test_check_busy(self, device,):
def test_check_busy(self, device):
t1 = time.time() * 1000
device.send_data(CTAPHID.INIT, "\x11\x22\x33\x44\x55\x66\x77\x88")
oldcid = device.cid()
@@ -156,7 +152,7 @@ class TestHID(object):
assert cmd == 0xBF
assert r[0] == CtapError.ERR.TIMEOUT
def test_check_busy_interleaved(self, device,):
def test_check_busy_interleaved(self, device):
cid1 = "\x11\x22\x33\x44"
cid2 = "\x01\x22\x33\x44"
device.set_cid(cid2)
@@ -185,7 +181,7 @@ class TestHID(object):
assert cmd == 0x81
assert len(r) == 0x63
def test_cid_0(self, device,):
def test_cid_0(self, device):
device.set_cid("\x00\x00\x00\x00")
device.send_raw(
"\x86\x00\x08\x11\x22\x33\x44\x55\x66\x77\x88", cid="\x00\x00\x00\x00"
@@ -195,7 +191,7 @@ class TestHID(object):
assert r[0] == CtapError.ERR.INVALID_CHANNEL
device.set_cid("\x05\x04\x03\x02")
def test_cid_ffffffff(self, device,):
def test_cid_ffffffff(self, device):
device.set_cid("\xff\xff\xff\xff")
device.send_raw(
+36 -23
View File
@@ -6,27 +6,33 @@ from tests.utils import verify, FidoRequest
class TestU2F(object):
def test_u2f_reg(self,device,RegRes):
def test_u2f_reg(self, device, RegRes):
RegRes.verify(RegRes.request.appid, RegRes.request.challenge)
def test_u2f_auth(self,device,RegRes,AuthRes):
AuthRes.verify(AuthRes.request.appid, AuthRes.request.challenge, RegRes.public_key)
def test_u2f_auth(self, device, RegRes, AuthRes):
AuthRes.verify(
AuthRes.request.appid, AuthRes.request.challenge, RegRes.public_key
)
def test_u2f_auth_check_only(self,device,RegRes,):
def test_u2f_auth_check_only(self, device, RegRes):
with pytest.raises(ApduError) as e:
device.ctap1.authenticate(RegRes.request.challenge, RegRes.request.appid, RegRes.key_handle, check_only = True)
device.ctap1.authenticate(
RegRes.request.challenge,
RegRes.request.appid,
RegRes.key_handle,
check_only=True,
)
assert e.value.code == APDU.USE_NOT_SATISFIED
def test_version(self,device,):
def test_version(self, device):
assert device.ctap1.get_version() == "U2F_V2"
def test_bad_ins(self,device,):
def test_bad_ins(self, device):
with pytest.raises(ApduError) as e:
device.ctap1.send_apdu(0, 0, 0, 0, b"")
assert e.value.code == 0x6D00
def test_bad_cla(self,device):
def test_bad_cla(self, device):
with pytest.raises(ApduError) as e:
device.ctap1.send_apdu(1, CTAP1.INS.VERSION, 0, 0, b"abc")
assert e.value.code == 0x6E00
@@ -74,29 +80,36 @@ class TestU2F(object):
assert e.value.code == APDU.USE_NOT_SATISFIED
def test_bad_key_handle(self, device, RegRes):
kh = bytearray(RegRes.key_handle)
kh[0] = kh[0] ^ (0x40)
kh = bytearray(RegRes.key_handle)
kh[0] = kh[0] ^ (0x40)
with pytest.raises(ApduError) as e:
device.ctap1.authenticate(RegRes.request.challenge, RegRes.request.appid, kh, check_only=True)
assert e.value.code == APDU.WRONG_DATA
with pytest.raises(ApduError) as e:
device.ctap1.authenticate(
RegRes.request.challenge, RegRes.request.appid, kh, check_only=True
)
assert e.value.code == APDU.WRONG_DATA
with pytest.raises(ApduError) as e:
device.ctap1.authenticate(RegRes.request.challenge, RegRes.request.appid, kh, )
assert e.value.code == APDU.WRONG_DATA
with pytest.raises(ApduError) as e:
device.ctap1.authenticate(
RegRes.request.challenge, RegRes.request.appid, kh
)
assert e.value.code == APDU.WRONG_DATA
def test_bad_key_handle_length(self, device, RegRes):
kh = bytearray(RegRes.key_handle)
with pytest.raises(ApduError) as e:
device.ctap1.authenticate(RegRes.request.challenge, RegRes.request.appid, kh[: len(kh) // 2])
assert e.value.code == APDU.WRONG_DATA
kh = bytearray(RegRes.key_handle)
with pytest.raises(ApduError) as e:
device.ctap1.authenticate(
RegRes.request.challenge, RegRes.request.appid, kh[: len(kh) // 2]
)
assert e.value.code == APDU.WRONG_DATA
def test_incorrect_appid(self, device, RegRes):
badid = bytearray(RegRes.request.appid)
badid[0] = badid[0] ^ (0x40)
with pytest.raises(ApduError) as e:
auth = device.ctap1.authenticate(RegRes.request.challenge, badid, RegRes.key_handle)
auth = device.ctap1.authenticate(
RegRes.request.challenge, badid, RegRes.key_handle
)
assert e.value.code == APDU.WRONG_DATA
+64 -38
View File
@@ -5,81 +5,98 @@ from fido2.ctap2 import ES256, PinProtocolV1, AttestedCredentialData
from fido2.utils import sha256, hmac_sha256
name_list = open('data/first-names.txt').readlines()
name_list = open("data/first-names.txt").readlines()
def verify(reg,auth,cdh = None):
def verify(reg, auth, cdh=None):
credential_data = AttestedCredentialData(reg.auth_data.credential_data)
if cdh is None: cdh = auth.request.cdh
if cdh is None:
cdh = auth.request.cdh
auth.verify(cdh, credential_data.public_key)
assert (
auth.credential["id"] == reg.auth_data.credential_data.credential_id
)
assert auth.credential["id"] == reg.auth_data.credential_data.credential_id
def generate_rp():
return {"id": "example.org", "name": "ExampleRP"}
def generate_user():
# https://www.w3.org/TR/webauthn/#user-handle
user_id_length = random.randint(1,64)
user_id_length = random.randint(1, 64)
user_id = secrets.token_bytes(user_id_length)
# https://www.w3.org/TR/webauthn/#dictionary-pkcredentialentity
name = ' '.join(random.choice(name_list).strip() for i in range(0,3))
icon = 'https://www.w3.org/TR/webauthn/'
name = " ".join(random.choice(name_list).strip() for i in range(0, 3))
icon = "https://www.w3.org/TR/webauthn/"
display_name = "Displayed " + name
return {"id": user_id, "name": name, 'icon': icon, 'displayName': display_name}
return {"id": user_id, "name": name, "icon": icon, "displayName": display_name}
def generate_challenge():
return secrets.token_bytes(32)
def get_key_params():
return [{"type": "public-key", "alg": ES256.ALGORITHM}]
def generate_cdh():
return b"123456789abcdef0123456789abcdef0"
def generate(param):
if param == 'rp':
if param == "rp":
return generate_rp()
if param == 'user':
if param == "user":
return generate_user()
if param == 'challenge':
if param == "challenge":
return generate_challenge()
if param == 'cdh':
if param == "cdh":
return generate_cdh()
if param == 'key_params':
if param == "key_params":
return get_key_params()
if param == 'allow_list':
if param == "allow_list":
return []
return None
class Empty:
pass
class FidoRequest():
def __init__(self, request = None, **kwargs):
class FidoRequest:
def __init__(self, request=None, **kwargs):
if not isinstance(request, FidoRequest) and request is not None:
request = request.request
self.request = request
for i in ('cdh', 'key_params', 'allow_list', 'challenge',
'rp', 'user', 'pin_protocol', 'options', 'appid',
'exclude_list', 'extensions', 'pin_auth'):
for i in (
"cdh",
"key_params",
"allow_list",
"challenge",
"rp",
"user",
"pin_protocol",
"options",
"appid",
"exclude_list",
"extensions",
"pin_auth",
):
self.save_attr(i, kwargs.get(i, Empty), request)
if isinstance(self.rp,dict) and 'id' in self.rp:
if hasattr(self.rp["id"], 'encode'):
if isinstance(self.rp, dict) and "id" in self.rp:
if hasattr(self.rp["id"], "encode"):
self.appid = sha256(self.rp["id"].encode("utf8"))
#self.chal = sha256(self.challenge.encode("utf8"))
# self.chal = sha256(self.challenge.encode("utf8"))
def save_attr(self,attr,value,request):
def save_attr(self, attr, value, request):
"""
Will assign attribute from source, in following priority:
Argument, request object, generated
@@ -87,23 +104,32 @@ class FidoRequest():
if value != Empty:
setattr(self, attr, value)
elif request is not None:
setattr(self, attr, getattr(request,attr))
setattr(self, attr, getattr(request, attr))
else:
setattr(self, attr, generate(attr))
def toGA(self,):
return [None if not self.rp else self.rp['id'],
self.cdh, self.allow_list, self.extensions, self.options,
self.pin_auth, self.pin_protocol]
return [
None if not self.rp else self.rp["id"],
self.cdh,
self.allow_list,
self.extensions,
self.options,
self.pin_auth,
self.pin_protocol,
]
def toMC(self,):
return [self.cdh, self.rp, self.user, self.key_params,
self.exclude_list, self.extensions, self.options,
self.pin_auth, self.pin_protocol]
return [
self.cdh,
self.rp,
self.user,
self.key_params,
self.exclude_list,
self.extensions,
self.options,
self.pin_auth,
self.pin_protocol,
]
return args + self.get_optional_args()
+33 -31
View File
@@ -12,6 +12,7 @@ from fido2.utils import sha256
from fido2.hid import CTAPHID
from fido2.ctap import CtapError
def shannon_entropy(data):
s = 0.0
total = len(data)
@@ -22,21 +23,23 @@ def shannon_entropy(data):
s -= p * math.log2(p)
return s
@pytest.fixture(scope="module", params = ['u2f'])
def solo(request,device):
sc = SoloClient()
sc.find_device(device.dev)
if request.param == 'u2f':
sc.use_u2f()
else:
sc.use_hid()
return sc
@pytest.fixture(scope="module", params=["u2f"])
def solo(request, device):
sc = SoloClient()
sc.find_device(device.dev)
if request.param == "u2f":
sc.use_u2f()
else:
sc.use_hid()
return sc
class TestSolo(object):
def test_solo(self,solo):
def test_solo(self, solo):
pass
def test_rng(self,solo):
def test_rng(self, solo):
total = 1024 * 16
entropy = b""
@@ -47,14 +50,14 @@ class TestSolo(object):
assert s > 7.98
print("Entropy is %.5f bits per byte." % s)
def test_version(self,solo):
def test_version(self, solo):
assert len(solo.solo_version()) == 3
def test_bootloader_not(self,solo):
def test_bootloader_not(self, solo):
with pytest.raises(ApduError) as e:
solo.write_flash(0x0, b"1234")
def test_fido2_bridge(self,solo):
def test_fido2_bridge(self, solo):
exchange = solo.exchange
solo.exchange = solo.exchange_fido2
@@ -72,24 +75,23 @@ class TestSolo(object):
solo.exchange = exchange
# def test_bootloader(self,):
# solo = SoloClient()
# solo.find_device(self.dev)
# solo.use_u2f()
#def test_bootloader(self,):
#solo = SoloClient()
#solo.find_device(self.dev)
#solo.use_u2f()
# memmap = (0x08005000, 0x08005000 + 198 * 1024 - 8)
# data = b"A" * 64
#memmap = (0x08005000, 0x08005000 + 198 * 1024 - 8)
#data = b"A" * 64
# with Test("Test version command"):
# assert len(solo.bootloader_version()) == 3
#with Test("Test version command"):
#assert len(solo.bootloader_version()) == 3
# with Test("Test write command"):
# solo.write_flash(memmap[0], data)
#with Test("Test write command"):
#solo.write_flash(memmap[0], data)
#for addr in (memmap[0] - 8, memmap[0] - 4, memmap[1], memmap[1] - 8):
#with Test("Test out of bounds write command at 0x%04x" % addr):
#try:
#solo.write_flash(addr, data)
#except CtapError as e:
#assert e.code == CtapError.ERR.NOT_ALLOWED
# for addr in (memmap[0] - 8, memmap[0] - 4, memmap[1], memmap[1] - 8):
# with Test("Test out of bounds write command at 0x%04x" % addr):
# try:
# solo.write_flash(addr, data)
# except CtapError as e:
# assert e.code == CtapError.ERR.NOT_ALLOWED