add cbor sorting from old tests

This commit is contained in:
Conor Patrick
2019-08-29 23:34:10 +08:00
parent 89a0cc3ab6
commit 5f3ab95ab7
2 changed files with 111 additions and 12 deletions
+75 -12
View File
@@ -1,17 +1,80 @@
import time
from functools import cmp_to_key
import tests
from fido2 import cbor
def cbor_key_to_representative(key):
if isinstance(key, int):
if key >= 0:
return (0, key)
return (1, -key)
elif isinstance(key, bytes):
return (2, key)
elif isinstance(key, str):
return (3, key)
else:
raise ValueError(key)
def reset():
print("Resetting Authenticator...")
dev = tests.get_device()
try:
dev.ctap2.reset()
except CtapError:
# Some authenticators need a power cycle
print("You must power cycle authentictor. Hit enter when done.")
input()
time.sleep(0.2)
dev = tests.get_device(refresh=True)
dev.ctap2.reset()
def cbor_str_cmp(a, b):
if isinstance(a, str) or isinstance(b, str):
a = a.encode("utf8")
b = b.encode("utf8")
if len(a) == len(b):
for x, y in zip(a, b):
if x != y:
return x - y
return 0
else:
return len(a) - len(b)
def cmp_cbor_keys(a, b):
a = cbor_key_to_representative(a)
b = cbor_key_to_representative(b)
if a[0] != b[0]:
return a[0] - b[0]
if a[0] in (2, 3):
return cbor_str_cmp(a[1], b[1])
else:
return (a[1] > b[1]) - (a[1] < b[1])
def TestCborKeysSorted(cbor_obj):
# Cbor canonical ordering of keys.
# https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#ctap2-canonical-cbor-encoding-form
if isinstance(cbor_obj, bytes):
cbor_obj = cbor.loads(cbor_obj)[0]
if isinstance(cbor_obj, dict):
l = [x for x in cbor_obj]
else:
l = cbor_obj
l_sorted = sorted(l[:], key=cmp_to_key(cmp_cbor_keys))
for i in range(len(l)):
if not isinstance(l[i], (str, int)):
raise ValueError(f"Cbor map key {l[i]} must be int or str for CTAP2")
if l[i] != l_sorted[i]:
raise ValueError(f"Cbor map item {i}: {l[i]} is out of order")
return l
# hot patch cbor map parsing to test the order of keys in map
_load_map_old = cbor.load_map
def _load_map_new(ai, data):
values, data = _load_map_old(ai, data)
TestCborKeysSorted(values)
return values, data
cbor.load_map = _load_map_new
cbor._DESERIALIZERS[5] = _load_map_new
+36
View File
@@ -3,6 +3,7 @@ from fido2 import cbor
from fido2.ctap import CtapError
from tests.utils import *
from tests.standard.fido2 import TestCborKeysSorted
def test_get_info(info):
@@ -35,3 +36,38 @@ def test_Check_up_option(device, info):
with pytest.raises(CtapError) as e:
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,
1,
1,
2,
3,
-1,
-2,
"b",
"c",
"aa",
"aaa",
"aab",
"baa",
"bbb",
]
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"])