Add tests to demonstrate broken user presence timeouts (#520)

* Add tests to demonstrate broken user presence timeouts

* fix up some formatting

* apply auto-formatting
This commit is contained in:
Liam Murphy
2022-08-01 17:13:14 +10:00
committed by GitHub
parent 2bc405165e
commit 253d27d612

View File

@@ -1,7 +1,12 @@
"""These tests verify the functionality of the VendorHID interface.""" """These tests verify the functionality of the VendorHID interface."""
from typing import Dict, Iterable from fido2 import ctap
from fido2.hid import CtapHidDevice
from fido2.hid.base import CtapHidConnection
from fido2.client import Fido2Client, UserInteraction, ClientError
from fido2.server import Fido2Server
import hid import hid
import time import time
from typing import Dict, Iterable
import unittest import unittest
_OPENSK_VID = 0x1915 _OPENSK_VID = 0x1915
@@ -12,6 +17,7 @@ _PACKETS = 4
_PACKET_SIZE = 64 _PACKET_SIZE = 64
_SEND_DATA_SIZE = _PACKET_SIZE + 1 _SEND_DATA_SIZE = _PACKET_SIZE + 1
_BROADCAST_CID = bytes([0xFF, 0xFF, 0xFF, 0xFF]) _BROADCAST_CID = bytes([0xFF, 0xFF, 0xFF, 0xFF])
_TEST_USER = {'id': b'user_id', 'name': 'Foo User'}
def sleep(): def sleep():
@@ -265,5 +271,87 @@ class HidInterfaces(unittest.TestCase):
self.fido_hid) self.fido_hid)
def get_fido_device() -> CtapHidDevice:
for d in CtapHidDevice.list_devices():
if d.descriptor.vid == _OPENSK_VID and d.descriptor.pid == _OPENSK_PID:
return d
raise Exception('Unable to find Fido device')
class CliInteraction(UserInteraction):
"""Sends cancel messages while prompting user."""
def __init__(self, cid=None, connection: CtapHidConnection = None):
super(CliInteraction).__init__()
self.cid = cid
self.connection = connection
def prompt_up(self) -> None:
print('\n Don\'t touch your authenticator device now...\n')
# Send cancel messages to the specified device.
if self.connection and self.cid:
cancel_packet = (
self.cid.to_bytes(4, byteorder='big') + b'\x91' +
b''.join([b'\x00'] * 59))
assert len(cancel_packet) == _PACKET_SIZE, (
f'Expected packet to be {_PACKET_SIZE} '
'but was {len(cancel_packet)}')
self.connection.write_packet(cancel_packet)
class CancelTests(unittest.TestCase):
"""Tests for the canceling while waiting for user touch."""
@classmethod
def setUpClass(cls):
cls.fido = get_fido_device()
def setUp(self) -> None:
super().setUp()
server = Fido2Server({
'id': 'example.com',
'name': 'Example RP'
},
attestation='direct')
self.create_options, _ = server.register_begin(
_TEST_USER,
user_verification='foo',
authenticator_attachment='cross-platform')
def test_cancel_works(self):
cid = self.fido._channel_id # pylint: disable=protected-access
connection = self.fido._connection # pylint: disable=protected-access
client = Fido2Client(
self.fido,
'https://example.com',
user_interaction=CliInteraction(cid, connection))
with self.assertRaises(ClientError) as context:
client.make_credential(self.create_options['publicKey'])
self.assertEqual(context.exception.code, ClientError.ERR.TIMEOUT)
self.assertEqual(context.exception.cause.code,
ctap.CtapError.ERR.KEEPALIVE_CANCEL)
def test_cancel_ignores_wrong_cid(self):
cid = self.fido._channel_id # pylint: disable=protected-access
connection = self.fido._connection # pylint: disable=protected-access
client = Fido2Client(
self.fido,
'https://example.com',
user_interaction=CliInteraction(cid + 1, connection))
# TODO(https://github.com/google/OpenSK/issues/519): This should be an
# exception
client.make_credential(self.create_options['publicKey'])
def test_timeout(self):
client = Fido2Client(
self.fido, 'https://example.com', user_interaction=CliInteraction())
# TODO(https://github.com/google/OpenSK/issues/519): This should be an
# exception
client.make_credential(self.create_options['publicKey'])
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()