Upgrade tests to python-fido2 v2.0.0

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2025-08-29 01:20:31 +02:00
parent d30ebde4f0
commit fdf97f5469
10 changed files with 217 additions and 193 deletions

View File

@@ -20,8 +20,6 @@
from fido2.client import CtapError
from fido2.cose import ES256, ES384, ES512, EdDSA
import fido2.features
fido2.features.webauthn_json_mapping.enabled = False
from utils import ES256K
import pytest
@@ -51,13 +49,13 @@ def test_bad_type_cdh(device):
def test_missing_user(device):
with pytest.raises(CtapError) as e:
device.doMC(user=None)
device.MC(user=None)
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_bad_type_user_user(device):
with pytest.raises(CtapError) as e:
device.doMC(user=b"12345678")
device.MC(user=b"12345678")
def test_missing_rp(device):
with pytest.raises(CtapError) as e:
@@ -71,7 +69,7 @@ def test_bad_type_rp(device):
def test_missing_pubKeyCredParams(device):
with pytest.raises(CtapError) as e:
device.doMC(key_params=None)
device.MC(key_params=None)
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
@@ -93,35 +91,23 @@ def test_bad_type_options(device):
def test_bad_type_rp_name(device):
with pytest.raises(CtapError) as e:
device.doMC(rp={"id": "test.org", "name": 8, "icon": "icon"})
device.MC(rp={"id": "test.org", "name": 8, "icon": "icon"})
def test_bad_type_rp_id(device):
with pytest.raises(CtapError) as e:
device.doMC(rp={"id": 8, "name": "name", "icon": "icon"})
def test_bad_type_rp_icon(device):
with pytest.raises(CtapError) as e:
device.doMC(rp={"id": "test.org", "name": "name", "icon": 8})
device.MC(rp={"id": 8, "name": "name", "icon": "icon"})
def test_bad_type_user_name(device):
with pytest.raises(CtapError) as e:
device.doMC(user={"id": b"user_id", "name": 8})
device.MC(user={"id": b"user_id", "name": 8})
def test_bad_type_user_id(device):
with pytest.raises(CtapError) as e:
device.doMC(user={"id": "user_id", "name": "name"})
device.MC(user={"id": "user_id", "name": "name"})
def test_bad_type_user_displayName(device):
with pytest.raises(CtapError) as e:
device.doMC(user={"id": "user_id", "name": "name", "displayName": 8})
def test_bad_type_user_icon(device):
with pytest.raises(CtapError) as e:
device.doMC(user={"id": "user_id", "name": "name", "icon": 8})
def test_bad_type_pubKeyCredParams(device):
with pytest.raises(CtapError) as e:
device.doMC(key_params=["wrong"])
device.MC(user={"id": "user_id", "name": "name", "displayName": 8})
@pytest.mark.parametrize(
"alg", [ES256.ALGORITHM, ES384.ALGORITHM, ES512.ALGORITHM, ES256K.ALGORITHM, EdDSA.ALGORITHM]
@@ -132,13 +118,13 @@ def test_algorithms(device, info, alg):
def test_missing_pubKeyCredParams_type(device):
with pytest.raises(CtapError) as e:
device.doMC(key_params=[{"alg": ES256.ALGORITHM}])
device.MC(key_params=[{"alg": ES256.ALGORITHM}])
assert e.value.code == CtapError.ERR.INVALID_CBOR
def test_missing_pubKeyCredParams_alg(device):
with pytest.raises(CtapError) as e:
device.doMC(key_params=[{"type": "public-key"}])
device.MC(key_params=[{"type": "public-key"}])
assert e.value.code in [
CtapError.ERR.INVALID_CBOR,
@@ -147,7 +133,7 @@ def test_missing_pubKeyCredParams_alg(device):
def test_bad_type_pubKeyCredParams_alg(device):
with pytest.raises(CtapError) as e:
device.doMC(key_params=[{"alg": "7", "type": "public-key"}])
device.MC(key_params=[{"alg": "7", "type": "public-key"}])
assert e.value.code == CtapError.ERR.CBOR_UNEXPECTED_TYPE
@@ -158,26 +144,26 @@ def test_unsupported_algorithm(device):
assert e.value.code == CtapError.ERR.UNSUPPORTED_ALGORITHM
def test_exclude_list(resetdevice):
resetdevice.doMC(exclude_list=[{"id": b"1234", "type": "rot13"}])
resetdevice.MC(exclude_list=[{"id": b"1234", "type": "rot13"}])
def test_exclude_list2(resetdevice):
resetdevice.doMC(exclude_list=[{"id": b"1234", "type": "mangoPapayaCoconutNotAPublicKey"}])
resetdevice.MC(exclude_list=[{"id": b"1234", "type": "mangoPapayaCoconutNotAPublicKey"}])
def test_bad_type_exclude_list(device):
with pytest.raises(CtapError) as e:
device.doMC(exclude_list=["1234"])
device.MC(exclude_list=["1234"])
def test_missing_exclude_list_type(device):
with pytest.raises(CtapError) as e:
device.doMC(exclude_list=[{"id": b"1234"}])
device.MC(exclude_list=[{"id": b"1234"}])
def test_missing_exclude_list_id(device):
with pytest.raises(CtapError) as e:
device.doMC(exclude_list=[{"type": "public-key"}])
device.MC(exclude_list=[{"type": "public-key"}])
def test_bad_type_exclude_list_id(device):
with pytest.raises(CtapError) as e:
device.doMC(exclude_list=[{"type": "public-key", "id": "1234"}])
device.MC(exclude_list=[{"type": "public-key", "id": "1234"}])
def test_bad_type_exclude_list_type(device):
with pytest.raises(CtapError) as e:

View File

@@ -31,10 +31,10 @@ def test_authenticate(device):
AUTRes = device.authenticate(credentials)
def test_assertion_auth_data(GARes):
assert len(GARes['res'].get_response(0).authenticator_data) == 37
assert len(GARes['res'].get_response(0).response.authenticator_data) == 37
def test_Check_that_AT_flag_is_not_set(GARes):
assert (GARes['res'].get_response(0).authenticator_data.flags & 0xF8) == 0
assert (GARes['res'].get_response(0).response.authenticator_data.flags & 0xF8) == 0
def test_that_user_credential_and_numberOfCredentials_are_not_present(device, MCRes):
res = device.GA(allow_list=[
@@ -63,8 +63,8 @@ def test_get_assertion_allow_list_filtering_and_buffering(device):
""" Check that authenticator filters and stores items in allow list correctly """
allow_list = []
rp1 = {"id": "rp1.com", "name": "rp1.com"}
rp2 = {"id": "rp2.com", "name": "rp2.com"}
rp1 = {"id": "example.com", "name": "rp1.com"}
rp2 = {"id": "example.com", "name": "rp2.com"}
rp1_registrations = []
rp2_registrations = []
@@ -127,7 +127,7 @@ def test_mismatched_rp(device, GARes):
rp_id += ".com"
with pytest.raises(CtapError) as e:
device.doGA(rp_id=rp_id)
device.GA(rp_id=rp_id)
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
def test_missing_rp(device):
@@ -137,7 +137,7 @@ def test_missing_rp(device):
def test_bad_rp(device):
with pytest.raises(CtapError) as e:
device.doGA(rp_id={"id": {"type": "wrong"}})
device.GA(rp_id={"id": {"type": "wrong"}})
def test_missing_cdh(device):
with pytest.raises(CtapError) as e:
@@ -150,11 +150,11 @@ def test_bad_cdh(device):
def test_bad_allow_list(device):
with pytest.raises(CtapError) as e:
device.doGA(allow_list={"type": "wrong"})
device.GA(allow_list={"type": "wrong"})
def test_bad_allow_list_item(device, MCRes):
with pytest.raises(CtapError) as e:
device.doGA(allow_list=["wrong"] + [
device.GA(allow_list=["wrong"] + [
{"id": MCRes['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
]
)
@@ -177,7 +177,7 @@ def test_option_up(device, info, GARes):
assert res.auth_data.flags & (1 << 0)
def test_allow_list_fake_item(device, MCRes):
device.doGA(allow_list=[{"type": "rot13", "id": b"1234"}]
device.GA(allow_list=[{"type": "rot13", "id": b"1234"}]
+ [
{"id": MCRes['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
],
@@ -185,7 +185,7 @@ def test_allow_list_fake_item(device, MCRes):
def test_allow_list_missing_field(device, MCRes):
with pytest.raises(CtapError) as e:
device.doGA(allow_list=[{"id": b"1234"}] + [
device.GA(allow_list=[{"id": b"1234"}] + [
{"id": MCRes['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
]
)
@@ -200,7 +200,7 @@ def test_allow_list_field_wrong_type(device, MCRes):
def test_allow_list_id_wrong_type(device, MCRes):
with pytest.raises(CtapError) as e:
device.doGA(allow_list=[{"type": "public-key", "id": 42}]
device.GA(allow_list=[{"type": "public-key", "id": 42}]
+ [
{"id": MCRes['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
]
@@ -208,7 +208,7 @@ def test_allow_list_id_wrong_type(device, MCRes):
def test_allow_list_missing_id(device, MCRes):
with pytest.raises(CtapError) as e:
device.doGA(allow_list=[{"type": "public-key"}] + [
device.GA(allow_list=[{"type": "public-key"}] + [
{"id": MCRes['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
]
)

View File

@@ -85,7 +85,7 @@ def test_multiple_rk_nodisplay(device, MCRes_DC):
auths = []
regs = []
# Use unique RP to not collide with other credentials
rp = {"id": f"unique-{random.random()}.com", "name": "Example"}
rp = {"id": "example.com", "name": "Example"}
for i in range(0, 3):
res = device.doMC(rp=rp, rk=True, user=generate_random_user())
regs.append(res)
@@ -116,7 +116,7 @@ def test_rk_maximum_size_nodisplay(device):
auths = resGA.get_assertions()
user_max_GA = auths[0]
print(auths)
for y in ("name", "displayName", "id"):
if (y in user_max_GA):
assert user_max_GA.user[y] == user_max[y]
@@ -126,7 +126,7 @@ def test_rk_maximum_list_capacity_per_rp_nodisplay(info, device, MCRes_DC):
"""
Test maximum returned capacity of the RK for the given RP
"""
device.reset()
# 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:
@@ -140,7 +140,7 @@ def test_rk_maximum_list_capacity_per_rp_nodisplay(info, device, MCRes_DC):
return user
# Use unique RP to not collide with other credentials from other tests.
rp = {"id": f"unique-{random.random()}.com", "name": "Example"}
rp = {"id": "example.com", "name": "Example"}
# req = FidoRequest(MCRes_DC, options=None, user=get_user(), rp = rp)
# res = device.sendGA(*req.toGA())
@@ -183,10 +183,10 @@ def test_rk_with_allowlist_of_different_rp(resetdevice):
"""
rk_rp = {"id": "rk-cred.org", "name": "Example"}
rk_res = resetdevice.doMC(rp = rk_rp, rk=True)['res'].attestation_object
rk_res = resetdevice.MC(rp = rk_rp, options={"rk":True})['res']
server_rp = {"id": "server-cred.com", "name": "Example"}
server_res = resetdevice.doMC(rp = server_rp, rk=True)['res'].attestation_object
server_res = resetdevice.MC(rp = server_rp, options={"rk":True})['res']
allow_list_with_different_rp_cred = [
{
@@ -197,7 +197,7 @@ def test_rk_with_allowlist_of_different_rp(resetdevice):
with pytest.raises(CtapError) as e:
res = resetdevice.doGA(rp_id = rk_rp['id'], allow_list = allow_list_with_different_rp_cred)
res = resetdevice.GA(rp_id = rk_rp['id'], allow_list = allow_list_with_different_rp_cred)
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
@@ -208,10 +208,10 @@ def test_same_userId_overwrites_rk(resetdevice):
rp = {"id": "overwrite.org", "name": "Example"}
user = generate_random_user()
mc_res1 = resetdevice.doMC(rp = rp, rk=True, user = user)
mc_res1 = resetdevice.MC(rp = rp, options={"rk":True}, user = user)
# Should overwrite the first credential.
mc_res2 = resetdevice.doMC(rp = rp, rk=True, user = user)
mc_res2 = resetdevice.MC(rp = rp, options={"rk":True}, user = user)
ga_res = resetdevice.GA(rp_id=rp['id'])['res']
@@ -227,7 +227,7 @@ def test_larger_icon_than_128(device):
user = generate_random_user()
user['icon'] = 'https://www.w3.org/TR/webauthn/?icon=' + ("A" * 128)
device.doMC(rp = rp, rk=True, user = user)
device.MC(rp = rp, options={"rk":True}, user = user)
def test_returned_credential(device):

View File

@@ -21,6 +21,7 @@
import pytest
from fido2.ctap import CtapError
from fido2.ctap2.pin import PinProtocolV2, ClientPin
from fido2.utils import websafe_decode
from utils import verify
import os
@@ -46,22 +47,24 @@ def GACredBlob(device, MCCredBlob):
@pytest.fixture(scope="function")
def MCLBK(device):
res = device.doMC(
mc = device.doMC(
rk=True,
extensions={'largeBlob':{'support':'required'}}
)['res']
return res
)
res = mc['res']
ext = mc['client_extension_results']
return {'res': res, 'ext': ext}
@pytest.fixture(scope="function")
def GALBRead(device, MCLBK):
res = device.doGA(
allow_list=[
{"id": MCLBK.attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
{"id": MCLBK['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
],extensions={'largeBlob':{'read': True}}
)
assertions = res['res'].get_assertions()
for a in assertions:
verify(MCLBK.attestation_object, a, res['req']['client_data'].hash)
verify(MCLBK['res'].attestation_object, a, res['req']['client_data'].hash)
return res['res']
@pytest.fixture(scope="function")
@@ -70,18 +73,19 @@ def GALBReadLBK(GALBRead):
@pytest.fixture(scope="function")
def GALBReadLB(GALBRead):
print(GALBRead.get_response(0))
return GALBRead.get_response(0)
@pytest.fixture(scope="function")
def GALBWrite(device, MCLBK):
res = device.doGA(
allow_list=[
{"id": MCLBK.attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
{"id": MCLBK['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
],extensions={'largeBlob':{'write': LARGE_BLOB}}
)
assertions = res['res'].get_assertions()
for a in assertions:
verify(MCLBK.attestation_object, a, res['req']['client_data'].hash)
verify(MCLBK['res'].attestation_object, a, res['req']['client_data'].hash)
return res['res'].get_response(0)
def test_supports_credblob(info):
@@ -136,15 +140,17 @@ def test_supports_largeblobs(info):
assert info.max_large_blob is None or (info.max_large_blob > 1024)
def test_get_largeblobkey_mc(MCLBK):
assert 'supported' in MCLBK.extension_results
assert MCLBK.extension_results['supported'] is True
assert 'largeBlob' in MCLBK['ext']
assert 'supported' in MCLBK['ext']['largeBlob']
assert MCLBK['ext']['largeBlob']['supported'] is True
def test_get_largeblobkey_ga(GALBReadLBK):
assert GALBReadLBK.large_blob_key is not None
def test_get_largeblob_rw(GALBWrite, GALBReadLB):
assert 'written' in GALBWrite.extension_results
assert GALBWrite.extension_results['written'] is True
assert 'largeBlob' in GALBWrite.client_extension_results
assert 'written' in GALBWrite.client_extension_results['largeBlob']
assert GALBWrite.client_extension_results['largeBlob']['written'] is True
assert 'blob' in GALBReadLB.extension_results
assert GALBReadLB.extension_results['blob'] == LARGE_BLOB
assert 'blob' in GALBReadLB.client_extension_results['largeBlob']
assert websafe_decode(GALBReadLB.client_extension_results['largeBlob']['blob']) == LARGE_BLOB

View File

@@ -83,7 +83,7 @@ def test_credprotect_optional_list_excluded(device, MCCredProtectOptionalList):
]
with pytest.raises(CtapError) as e:
device.doMC(rk=True, extensions={'credentialProtectionPolicy': CredProtectExtension.POLICY.OPTIONAL_WITH_LIST}, exclude_list=exclude_list)
device.MC(options={'rk': True}, extensions={'credProtect': CredProtect.UserVerificationOptionalWithCredentialId}, exclude_list=exclude_list)
assert e.value.code == CtapError.ERR.CREDENTIAL_EXCLUDED
@@ -123,10 +123,10 @@ def test_credprotect_optional_and_list_works_no_uv(device, MCCredProtectOptional
},
]
# works
res1 = device.doGA(allow_list=allow_list)['res'].get_assertions()[0]
res1 = device.doGA(allow_list=allow_list, user_verification=False)['res'].get_assertions()[0]
assert res1.number_of_credentials in (None, 2)
results = device.doGA(allow_list=allow_list)['res'].get_assertions()
results = device.doGA(allow_list=allow_list, user_verification=False)['res'].get_assertions()
# the required credProtect is not returned.
for res in results:

View File

@@ -24,6 +24,7 @@ from fido2.ctap2.extensions import HmacSecretExtension
from fido2.utils import hmac_sha256
from fido2.ctap2.pin import PinProtocolV2
from fido2.webauthn import UserVerificationRequirement
from fido2.client import ClientError
from utils import *
salt1 = b"\xa5" * 32
@@ -38,10 +39,6 @@ def MCHmacSecret(resetdevice):
res = resetdevice.doMC(extensions={"hmacCreateSecret": True},rk=True)
return res['res'].attestation_object
@pytest.fixture(scope="class")
def hmac(resetdevice):
return HmacSecretExtension(resetdevice.client()._backend.ctap2, pin_protocol=PinProtocolV2())
def test_hmac_secret_make_credential(MCHmacSecret):
assert MCHmacSecret.auth_data.extensions
assert "hmac-secret" in MCHmacSecret.auth_data.extensions
@@ -55,51 +52,51 @@ def test_fake_extension(device):
@pytest.mark.parametrize("salts", [(salt1,), (salt1, salt2)])
def test_hmac_secret_entropy(device, MCHmacSecret, hmac, salts
def test_hmac_secret_entropy(device, MCHmacSecret, salts
):
hout = {'salt1':salts[0]}
if (len(salts) > 1):
hout['salt2'] = salts[1]
auth = device.doGA(extensions={"hmacGetSecret": hout})['res'].get_response(0)
ext = auth.extension_results
ext = auth.client_extension_results
assert ext
assert "hmacGetSecret" in ext
assert len(auth.authenticator_data.extensions['hmac-secret']) == len(salts) * 32 + 16
assert len(auth.response.authenticator_data.extensions['hmac-secret']) == len(salts) * 32 + 16
#print(shannon_entropy(auth.authenticator_data.extensions['hmac-secret']))
#print(shannon_entropy(auth.response.authenticator_data.extensions['hmac-secret']))
if len(salts) == 1:
assert shannon_entropy(auth.authenticator_data.extensions['hmac-secret']) > 4.5
assert shannon_entropy(ext["hmacGetSecret"]['output1']) > 4.5
assert shannon_entropy(auth.response.authenticator_data.extensions['hmac-secret']) > 4.5
assert shannon_entropy(ext.hmac_get_secret.output1) > 4.5
if len(salts) == 2:
assert shannon_entropy(auth.authenticator_data.extensions['hmac-secret']) > 5.4
assert shannon_entropy(ext["hmacGetSecret"]['output1']) > 4.5
assert shannon_entropy(ext["hmacGetSecret"]['output2']) > 4.5
assert shannon_entropy(auth.response.authenticator_data.extensions['hmac-secret']) > 5.4
assert shannon_entropy(ext.hmac_get_secret.output1) > 4.5
assert shannon_entropy(ext.hmac_get_secret.output2) > 4.5
def get_output(device, MCHmacSecret, hmac, salts):
def get_output(device, MCHmacSecret, salts):
hout = {'salt1':salts[0]}
if (len(salts) > 1):
hout['salt2'] = salts[1]
auth = device.doGA(extensions={"hmacGetSecret": hout})['res'].get_response(0)
ext = auth.extension_results
ext = auth.client_extension_results
assert ext
assert "hmacGetSecret" in ext
assert len(auth.authenticator_data.extensions['hmac-secret']) == len(salts) * 32 + 16
assert len(auth.response.authenticator_data.extensions['hmac-secret']) == len(salts) * 32 + 16
if len(salts) == 2:
return ext["hmacGetSecret"]['output1'], ext["hmacGetSecret"]['output2']
return ext.hmac_get_secret.output1, ext.hmac_get_secret.output2
else:
return ext["hmacGetSecret"]['output1']
return ext.hmac_get_secret.output1
def test_hmac_secret_sanity(device, MCHmacSecret, hmac):
output1 = get_output(device, MCHmacSecret, hmac, (salt1,))
def test_hmac_secret_sanity(device, MCHmacSecret):
output1 = get_output(device, MCHmacSecret, (salt1,))
output12 = get_output(
device, MCHmacSecret, hmac, (salt1, salt2)
device, MCHmacSecret, (salt1, salt2)
)
output21 = get_output(
device, MCHmacSecret, hmac, (salt2, salt1)
device, MCHmacSecret, (salt2, salt1)
)
assert output12[0] == output1
@@ -107,60 +104,60 @@ def test_hmac_secret_sanity(device, MCHmacSecret, hmac):
assert output21[0] == output12[1]
assert output12[0] != output12[1]
def test_missing_keyAgreement(device, hmac):
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salt3}})
def test_missing_keyAgreement(device):
with pytest.raises(CtapError):
device.GA(extensions={"hmac-secret": {2: hout[2], 3: hout[3]}})
device.GA(extensions={"hmac-secret": {2: b'1234', 3: b'1234'}})
def test_missing_saltAuth(device, hmac):
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salt3}})
def test_missing_saltAuth(device):
with pytest.raises(CtapError) as e:
device.GA(extensions={"hmac-secret": {1: hout[1], 2: hout[2]}})
device.GA(extensions={"hmac-secret": {2: b'1234'}})
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_missing_saltEnc(device, hmac):
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salt3}})
def test_missing_saltEnc(device,):
with pytest.raises(CtapError) as e:
device.GA(extensions={"hmac-secret": {1: hout[1], 3: hout[3]}})
device.GA(extensions={"hmac-secret": { 3: b'1234'}})
assert e.value.code == CtapError.ERR.MISSING_PARAMETER
def test_bad_auth(device, hmac, MCHmacSecret):
def test_bad_auth(device, MCHmacSecret):
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salt3}})
bad_auth = list(hout[3][:])
bad_auth[len(bad_auth) // 2] = bad_auth[len(bad_auth) // 2] ^ 1
bad_auth = bytes(bad_auth)
key_agreement = {
1: 2,
3: -25, # Per the spec, "although this is NOT the algorithm actually used"
-1: 1,
-2: b'\x00'*32,
-3: b'\x00'*32,
}
with pytest.raises(CtapError) as e:
device.GA(extensions={"hmac-secret": {1: hout[1], 2: hout[2], 3: bad_auth, 4: 2}})
device.GA(extensions={"hmac-secret": {1: key_agreement, 2: b'\x00'*80, 3: b'\x00'*32, 4: 2}})
assert e.value.code == CtapError.ERR.EXTENSION_FIRST
@pytest.mark.parametrize("salts", [(salt4,), (salt4, salt5)])
def test_invalid_salt_length(device, hmac, salts):
with pytest.raises(ValueError) as e:
def test_invalid_salt_length(device, salts):
with pytest.raises((CtapError,ClientError)) as e:
if (len(salts) == 2):
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salts[0],"salt2":salts[1]}})
hout = {"salt1":salts[0],"salt2":salts[1]}
else:
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salts[0]}})
hout = {"salt1":salts[0]}
device.doGA(extensions={"hmacGetSecret": hout})
@pytest.mark.parametrize("salts", [(salt1,), (salt1, salt2)])
def test_get_next_assertion_has_extension(
device, hmac, salts
device, salts
):
""" Check that get_next_assertion properly returns extension information for multiple accounts. """
if (len(salts) == 2):
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salts[0],"salt2":salts[1]}})
hout = {"salt1":salts[0],"salt2":salts[1]}
else:
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salts[0]}})
hout = {"salt1":salts[0]}
accounts = 3
regs = []
auths = []
rp = {"id": f"example_salts_{len(salts)}.org", "name": "ExampleRP_2"}
rp = {"id": f"example.com", "name": "ExampleRP_2"}
fixed_users = [generate_random_user() for _ in range(accounts)]
for i in range(accounts):
res = device.doMC(extensions={"hmacCreateSecret": True},
@@ -183,21 +180,19 @@ def test_get_next_assertion_has_extension(
assert "hmac-secret" in ext
assert isinstance(ext["hmac-secret"], bytes)
assert len(ext["hmac-secret"]) == len(salts) * 32 + 16
key = hmac.process_get_output(x)
def test_hmac_secret_different_with_uv(device, MCHmacSecret, hmac):
def test_hmac_secret_different_with_uv(device, MCHmacSecret):
salts = [salt1]
if (len(salts) == 2):
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salts[0],"salt2":salts[1]}})
hout = {"salt1":salts[0],"salt2":salts[1]}
else:
hout = hmac.process_get_input({"hmacGetSecret":{"salt1":salts[0]}})
hout = {"salt1":salts[0]}
auth_no_uv = device.GA(extensions={"hmac-secret": hout})['res']
assert (auth_no_uv.auth_data.flags & (1 << 2)) == 0
auth_no_uv = device.doGA(extensions={"hmacGetSecret": hout})['res'].get_response(0)
assert (auth_no_uv.response.authenticator_data.flags & (1 << 2)) == 0
ext_no_uv = auth_no_uv.auth_data.extensions
ext_no_uv = auth_no_uv.response.authenticator_data.extensions
assert ext_no_uv
assert "hmac-secret" in ext_no_uv
assert isinstance(ext_no_uv["hmac-secret"], bytes)
@@ -209,11 +204,11 @@ def test_hmac_secret_different_with_uv(device, MCHmacSecret, hmac):
hout['salt2'] = salts[1]
auth_uv = device.doGA(extensions={"hmacGetSecret": hout}, user_verification=UserVerificationRequirement.REQUIRED)['res'].get_response(0)
assert auth_uv.authenticator_data.flags & (1 << 2)
ext_uv = auth_uv.extension_results
assert auth_uv.response.authenticator_data.flags & (1 << 2)
ext_uv = auth_uv.client_extension_results
assert ext_uv
assert "hmacGetSecret" in ext_uv
assert len(ext_uv["hmacGetSecret"]) == len(salts)
assert len([p for p in ext_uv["hmacGetSecret"] if len(ext_uv["hmacGetSecret"][p]) > 0]) == len(salts)
# Now see if the hmac-secrets are different
assert ext_no_uv["hmac-secret"][:32] != ext_uv["hmacGetSecret"]['output1']

View File

@@ -29,7 +29,7 @@ def test_authenticate_ctap1_through_ctap2(device, RegRes):
res = device.doGA(ctap1=False, allow_list=[
{"id": RegRes['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
])
assert res['res'].get_response(0).credential_id == RegRes['res'].attestation_object.auth_data.credential_data.credential_id
assert res['res'].get_response(0).raw_id == RegRes['res'].attestation_object.auth_data.credential_data.credential_id
# Test FIDO2 register works with U2F auth