From 866d69a82dc3aba4a5015877ad39ebf325575bb8 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Fri, 9 Dec 2022 18:42:59 +0100 Subject: [PATCH] CredMgmt must be redeclared everytime, since PinToken might be changed due to underlaying doMC. Signed-off-by: Pol Henarejos --- tests/pico-fido/test_cred_mgmt.py | 153 +++++++++++++++--------------- 1 file changed, 74 insertions(+), 79 deletions(-) diff --git a/tests/pico-fido/test_cred_mgmt.py b/tests/pico-fido/test_cred_mgmt.py index f99b537..36c3c71 100644 --- a/tests/pico-fido/test_cred_mgmt.py +++ b/tests/pico-fido/test_cred_mgmt.py @@ -17,14 +17,6 @@ def client_pin_set(request, device, client_pin): pin = request.param client_pin.set_pin(pin) -@pytest.fixture(params=[PIN], scope = 'function') -def PinToken(request, device, client_pin): - pin = request.param - token = client_pin.get_pin_token(pin, permissions=ClientPin.PERMISSION.MAKE_CREDENTIAL | ClientPin.PERMISSION.CREDENTIAL_MGMT) - print(f"GET TOKEN {hexlify(token)}") - return token - - @pytest.fixture(scope = 'function') def MC_RK_Res(device, client_pin_set): rp = {"id": "ssh:", "name": "Bate Goiko"} @@ -33,51 +25,54 @@ def MC_RK_Res(device, client_pin_set): rp = {"id": "xakcop.com", "name": "John Doe"} device.doMC(rp=rp, rk=True) +def PinToken(device): + return ClientPin(device.client()._backend.ctap2).get_pin_token(PIN, permissions=ClientPin.PERMISSION.MAKE_CREDENTIAL | ClientPin.PERMISSION.CREDENTIAL_MGMT) -@pytest.fixture(scope = 'function') -def CredMgmt(device, PinToken): +def CredMgmt(device): + pt = PinToken(device) pin_protocol = PinProtocolV2() - return CredentialManagement(device.client()._backend.ctap2, pin_protocol, PinToken) + return CredentialManagement(device.client()._backend.ctap2, pin_protocol, pt) -def _test_enumeration(CredMgmt, rp_map): +def _test_enumeration(device, rp_map): "Enumerate credentials using BFS" - res = CredMgmt.enumerate_rps() + res = CredMgmt(device).enumerate_rps() assert len(rp_map.keys()) == len(res) for rp in res: - creds = CredMgmt.enumerate_creds(sha256(rp[3]["id"])) - assert len(creds) == rp_map[rp[3]["id"].decode()] + creds = CredMgmt(device).enumerate_creds(sha256(rp[3]["id"].encode())) + assert len(creds) == rp_map[rp[3]["id"]] -def _test_enumeration_interleaved(CredMgmt, rp_map): +def _test_enumeration_interleaved(device, rp_map): "Enumerate credentials using DFS" - first_rp = CredMgmt.enumerate_rps_begin() + first_rp = CredMgmt(device).enumerate_rps_begin() 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"])) + first_rk = CredMgmt(device).enumerate_creds_begin(sha256(first_rp[3]["id"].encode())) for i in range(1, first_rk[CredentialManagement.RESULT.TOTAL_CREDENTIALS]): - c = CredMgmt.enumerate_creds_next() + c = CredMgmt(device).enumerate_creds_next() rk_count += 1 - assert rk_count == rp_map[first_rp[3]["id"].decode()] + 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() + next_rp = CredMgmt(device).enumerate_rps_next() rk_count = 1 - first_rk = CredMgmt.enumerate_creds_begin( - sha256(next_rp[3]["id"]) + first_rk = CredMgmt(device).enumerate_creds_begin( + sha256(next_rp[3]["id"].encode()) ) for i in range(1, first_rk[CredentialManagement.RESULT.TOTAL_CREDENTIALS]): - c = CredMgmt.enumerate_creds_next() + c = CredMgmt(device).enumerate_creds_next() rk_count += 1 - assert rk_count == rp_map[next_rp[3]["id"].decode()] + assert rk_count == rp_map[next_rp[3]["id"]] -def CredMgmtWrongPinAuth(device, pin_token): +def CredMgmtWrongPinAuth(device): + pin_token = PinToken(device) pin_protocol = PinProtocolV2() wrong_pt = bytearray(pin_token) wrong_pt[0] = (wrong_pt[0] + 1) % 256 @@ -103,13 +98,13 @@ def test_get_info(info): assert 0x8 in info assert info[0x8] > 1 -def test_get_metadata_ok(MC_RK_Res, CredMgmt): - metadata = CredMgmt.get_metadata() +def test_get_metadata_ok(MC_RK_Res, device): + metadata = CredMgmt(device).get_metadata() assert metadata[CredentialManagement.RESULT.EXISTING_CRED_COUNT] == 2 assert metadata[CredentialManagement.RESULT.MAX_REMAINING_COUNT] >= 48 -def test_enumerate_rps(MC_RK_Res, CredMgmt): - res = CredMgmt.enumerate_rps() +def test_enumerate_rps(MC_RK_Res, device): + res = CredMgmt(device).enumerate_rps() assert len(res) == 2 assert res[0][CredentialManagement.RESULT.RP]["id"] == "ssh:" assert res[0][CredentialManagement.RESULT.RP_ID_HASH] == sha256(b"ssh:") @@ -117,41 +112,41 @@ def test_enumerate_rps(MC_RK_Res, CredMgmt): assert res[1][CredentialManagement.RESULT.RP]["id"] == "xakcop.com" assert res[1][CredentialManagement.RESULT.RP_ID_HASH] == sha256(b"xakcop.com") -def test_enumarate_creds(MC_RK_Res, CredMgmt): - res = CredMgmt.enumerate_creds(sha256(b"ssh:")) +def test_enumarate_creds(MC_RK_Res, device): + res = CredMgmt(device).enumerate_creds(sha256(b"ssh:")) assert len(res) == 1 assert_cred_response_has_all_fields(res[0]) - res = CredMgmt.enumerate_creds(sha256(b"xakcop.com")) + res = CredMgmt(device).enumerate_creds(sha256(b"xakcop.com")) assert len(res) == 1 assert_cred_response_has_all_fields(res[0]) - res = CredMgmt.enumerate_creds(sha256(b"missing.com")) + res = CredMgmt(device).enumerate_creds(sha256(b"missing.com")) assert not res -def test_get_metadata_wrong_pinauth(device, MC_RK_Res, PinToken): +def test_get_metadata_wrong_pinauth(device, MC_RK_Res): cmd = lambda credMgmt: credMgmt.get_metadata() - _test_wrong_pinauth(device, cmd, PinToken) + _test_wrong_pinauth(device, cmd) -def test_rpbegin_wrong_pinauth(device, MC_RK_Res, PinToken): +def test_rpbegin_wrong_pinauth(device, MC_RK_Res): cmd = lambda credMgmt: credMgmt.enumerate_rps_begin() - _test_wrong_pinauth(device, cmd, PinToken) + _test_wrong_pinauth(device, cmd) -def test_rkbegin_wrong_pinauth(device, MC_RK_Res, PinToken): +def test_rkbegin_wrong_pinauth(device, MC_RK_Res): cmd = lambda credMgmt: credMgmt.enumerate_creds_begin(sha256(b"ssh:")) - _test_wrong_pinauth(device, cmd, PinToken) + _test_wrong_pinauth(device, cmd) -def test_rpnext_without_rpbegin(device, MC_RK_Res, CredMgmt): - CredMgmt.enumerate_creds_begin(sha256(b"ssh:")) +def test_rpnext_without_rpbegin(device, MC_RK_Res): + CredMgmt(device).enumerate_creds_begin(sha256(b"ssh:")) with pytest.raises(CtapError) as e: - CredMgmt.enumerate_rps_next() + CredMgmt(device).enumerate_rps_next() assert e.value.code == CtapError.ERR.NOT_ALLOWED -def test_rknext_without_rkbegin(device, MC_RK_Res, CredMgmt): - CredMgmt.enumerate_rps_begin() +def test_rknext_without_rkbegin(device, MC_RK_Res): + CredMgmt(device).enumerate_rps_begin() with pytest.raises(CtapError) as e: - CredMgmt.enumerate_creds_next() + CredMgmt(device).enumerate_creds_next() assert e.value.code == CtapError.ERR.NOT_ALLOWED -def test_delete(device, PinToken, CredMgmt): +def test_delete(device): # create a new RK rp = {"id": "example_3.com", "name": "John Doe 2"} @@ -161,21 +156,21 @@ def test_delete(device, PinToken, CredMgmt): auth = device.doGA(rp_id=rp['id']) # get the ID from enumeration - creds = CredMgmt.enumerate_creds(reg.auth_data.rp_id_hash) + creds = CredMgmt(device).enumerate_creds(reg.auth_data.rp_id_hash) for cred in creds: 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) + CredMgmt(device).delete_cred(cred) # make sure it doesn't work with pytest.raises(CtapError) as e: auth = device.doGA(rp_id=rp['id']) assert e.value.code == CtapError.ERR.NO_CREDENTIALS -def test_add_delete(device, PinToken, CredMgmt): +def test_add_delete(device): """ Delete a credential in the 'middle' and ensure other credentials are not affected. """ rp = {"id": "example_4.com", "name": "John Doe 3"} @@ -187,11 +182,11 @@ def test_add_delete(device, PinToken, CredMgmt): regs.append(reg) # Check they all enumerate - res = CredMgmt.enumerate_creds(regs[1].auth_data.rp_id_hash) + res = CredMgmt(device).enumerate_creds(regs[1].auth_data.rp_id_hash) assert len(res) == 3 # delete the middle one - creds = CredMgmt.enumerate_creds(reg.auth_data.rp_id_hash) + creds = CredMgmt(device).enumerate_creds(reg.auth_data.rp_id_hash) for cred in creds: if cred[7]["id"] == regs[1].auth_data.credential_data.credential_id: break @@ -199,16 +194,16 @@ def test_add_delete(device, PinToken, CredMgmt): assert cred[7]["id"] == regs[1].auth_data.credential_data.credential_id cred = {"id": cred[7]["id"], "type": "public-key"} - CredMgmt.delete_cred(cred) + CredMgmt(device).delete_cred(cred) # Check one less enumerates - res = CredMgmt.enumerate_creds(regs[0].auth_data.rp_id_hash) + res = CredMgmt(device).enumerate_creds(regs[0].auth_data.rp_id_hash) assert len(res) == 2 def test_multiple_creds_per_multiple_rps( - device, MC_RK_Res, CredMgmt + device, MC_RK_Res ): - res = CredMgmt.enumerate_rps() + res = CredMgmt(device).enumerate_rps() assert len(res) == 2 new_rps = [ @@ -222,27 +217,27 @@ def test_multiple_creds_per_multiple_rps( for i in range(0, 3): reg = device.doMC(rp=rp, rk=True, user=generate_random_user()) - res = CredMgmt.enumerate_rps() + res = CredMgmt(device).enumerate_rps() 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"))) + creds = CredMgmt(device).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( - device, MC_RK_Res, CredMgmt, enumeration_test + device, MC_RK_Res, enumeration_test ): """ Test enumerate still works after different commands """ - res = CredMgmt.enumerate_rps() + res = CredMgmt(device).enumerate_rps() expected_enumeration = {"xakcop.com": 1, "ssh:": 1} - enumeration_test(CredMgmt, expected_enumeration) + enumeration_test(device, expected_enumeration) new_rps = [ {"id": "example-2.com", "name": "Example-2-creds", "count": 2}, @@ -258,27 +253,27 @@ def test_multiple_enumeration( # Now expect creds from this RP expected_enumeration[rp["id"]] = rp["count"] - enumeration_test(CredMgmt, expected_enumeration) - enumeration_test(CredMgmt, expected_enumeration) + enumeration_test(device, expected_enumeration) + enumeration_test(device, expected_enumeration) - metadata = CredMgmt.get_metadata() + metadata = CredMgmt(device).get_metadata() - enumeration_test(CredMgmt, expected_enumeration) - enumeration_test(CredMgmt, expected_enumeration) + enumeration_test(device, expected_enumeration) + enumeration_test(device, expected_enumeration) @pytest.mark.parametrize( "enumeration_test", [_test_enumeration, _test_enumeration_interleaved] ) def test_multiple_enumeration_with_deletions( - device, MC_RK_Res, CredMgmt, enumeration_test + device, MC_RK_Res, enumeration_test ): """ Create each credential in random order. Test enumerate still works after randomly deleting each credential""" - res = CredMgmt.enumerate_rps() + res = CredMgmt(device).enumerate_rps() expected_enumeration = {"xakcop.com": 1, "ssh:": 1} - enumeration_test(CredMgmt, expected_enumeration) + enumeration_test(device, expected_enumeration) new_rps = [ {"id": "example-1.com", "name": "Example-1-creds"}, @@ -299,7 +294,7 @@ def test_multiple_enumeration_with_deletions( else: expected_enumeration[rp["id"]] += 1 - enumeration_test(CredMgmt, expected_enumeration) + enumeration_test(device, expected_enumeration) total_creds = len(new_rps) @@ -309,10 +304,10 @@ def test_multiple_enumeration_with_deletions( num = expected_enumeration[rp] index = 0 if num == 1 else random.randint(0, num - 1) - cred = CredMgmt.enumerate_creds(sha256(rp.encode("utf8")))[index] + cred = CredMgmt(device).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(device).delete_cred({"id": cred[7]["id"], "type": "public-key"}) expected_enumeration[rp] -= 1 if expected_enumeration[rp] == 0: @@ -321,11 +316,11 @@ def test_multiple_enumeration_with_deletions( if len(list(expected_enumeration.keys())) == 0: break - enumeration_test(CredMgmt, expected_enumeration) + enumeration_test(device, expected_enumeration) -def _test_wrong_pinauth(device, cmd, PinToken): +def _test_wrong_pinauth(device, cmd): - credMgmt = CredMgmtWrongPinAuth(device, PinToken) + credMgmt = CredMgmtWrongPinAuth(device) for i in range(2): with pytest.raises(CtapError) as e: @@ -336,8 +331,8 @@ def _test_wrong_pinauth(device, cmd, PinToken): cmd(credMgmt) assert e.value.code == CtapError.ERR.PIN_AUTH_BLOCKED - #device.reboot() - credMgmt = CredMgmtWrongPinAuth(device, PinToken) + device.reboot() + credMgmt = CredMgmtWrongPinAuth(device) for i in range(2): time.sleep(0.2) @@ -349,8 +344,8 @@ def _test_wrong_pinauth(device, cmd, PinToken): cmd(credMgmt) assert e.value.code == CtapError.ERR.PIN_AUTH_BLOCKED - #device.reboot() - credMgmt = CredMgmtWrongPinAuth(device, PinToken) + device.reboot() + credMgmt = CredMgmtWrongPinAuth(device) for i in range(1): time.sleep(0.2)