RF testing for NFC
This commit is contained in:
parent
9ddb8a7f57
commit
17ff54b0d4
@ -1137,23 +1137,99 @@ def only_mk3(dev):
|
||||
if v[4] != 'mk3':
|
||||
raise pytest.skip("Mk3 only")
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def rf_interface(only_mk4, sim_exec):
|
||||
# provide a read/write connection over NFC
|
||||
# - requires pyscard module and NFC-V reader like HID OMNIKEY 5022CL
|
||||
class RFHandler:
|
||||
def __init__(self, want_atr=None):
|
||||
from smartcard.System import readers as get_readers
|
||||
from smartcard.Exceptions import CardConnectionException, NoCardException
|
||||
|
||||
readers = get_readers()
|
||||
if not readers:
|
||||
raise pytest.fail("no card readers found")
|
||||
|
||||
# search for our card
|
||||
for r in readers:
|
||||
try:
|
||||
conn = r.createConnection()
|
||||
except:
|
||||
print(f"Fail: {r}");
|
||||
continue
|
||||
|
||||
try:
|
||||
conn.connect()
|
||||
atr = conn.getATR()
|
||||
except (CardConnectionException, NoCardException):
|
||||
print(f"Empty reader: {r}")
|
||||
continue
|
||||
|
||||
if want_atr and atr != want_atr:
|
||||
continue
|
||||
|
||||
# accept first suitable "card"
|
||||
break
|
||||
else:
|
||||
raise pytest.fail("did not find NFC target")
|
||||
|
||||
self.conn = conn
|
||||
|
||||
def apdu(self, cls, ins, data=b'', p1=0, p2=0):
|
||||
# send APDU
|
||||
lst = [ cls, ins, p1, p2, len(data)] + list(data)
|
||||
resp, sw1, sw2 = self.conn.transmit(lst)
|
||||
resp = bytes(resp)
|
||||
return hex((sw1 << 8) | sw2), resp
|
||||
|
||||
# XXX not simple; Omnikey wants secure channel (AES) for this
|
||||
def read_nfc(self):
|
||||
return b'helllo'
|
||||
def write_nfc(self, ccfile):
|
||||
pass
|
||||
|
||||
# get the CC into NFC tap mode (but no UX)
|
||||
sim_exec('glob.NFC.set_rf_disable(0)')
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
yield RFHandler()
|
||||
|
||||
sim_exec('glob.NFC.set_rf_disable(1)')
|
||||
|
||||
@pytest.fixture()
|
||||
def nfc_read(sim_exec):
|
||||
def nfc_read(request, only_mk4):
|
||||
# READ data from NFC chip
|
||||
def doit():
|
||||
# - perfer to do over NFC reader, but can work over USB too
|
||||
def doit_usb():
|
||||
sim_exec = request.getfixturevalue('sim_exec')
|
||||
rv = sim_exec('RV.write(glob.NFC.dump_ndef() if glob.NFC else b"")', binary=True)
|
||||
if b'Traceback' in rv: raise pytest.fail(rv.decode('utf-8'))
|
||||
return rv
|
||||
return doit
|
||||
|
||||
try:
|
||||
raise NotImplementedError
|
||||
rf = request.getfixturevalue('rf_interface')
|
||||
return rf.read_nfc
|
||||
except:
|
||||
return doit_usb
|
||||
|
||||
@pytest.fixture()
|
||||
def nfc_write(sim_exec, need_keypress):
|
||||
def nfc_write(request, only_mk4):
|
||||
# WRITE data into NFC "chip"
|
||||
def doit(ccfile):
|
||||
def doit_usb(ccfile):
|
||||
sim_exec = request.getfixturevalue('sim_exec')
|
||||
need_keypress = request.getfixturevalue('need_keypress')
|
||||
rv = sim_exec('list(glob.NFC.big_write(%r))' % ccfile)
|
||||
if 'Traceback' in rv: raise pytest.fail(rv)
|
||||
need_keypress('y') # to end the animation and have it check value immediately
|
||||
return doit
|
||||
|
||||
try:
|
||||
raise NotImplementedError
|
||||
rf = request.getfixturevalue('rf_interface')
|
||||
return rf.write_nfc
|
||||
except:
|
||||
return doit_usb
|
||||
|
||||
@pytest.fixture()
|
||||
def nfc_read_text(nfc_read):
|
||||
|
||||
@ -14,3 +14,7 @@ zbar-py==1.0.4
|
||||
# NFC and NDEF handling
|
||||
nfcpy==1.0.3
|
||||
ndef==0.2
|
||||
|
||||
# optional, and only helpful if you have a desktop NFC-V capable reader
|
||||
pyscard==2.0.2
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#
|
||||
# Mk4 NFC feature related tests.
|
||||
#
|
||||
import pytest, glob
|
||||
import pytest, glob, pdb
|
||||
from helpers import B2A
|
||||
from binascii import b2a_hex, a2b_hex
|
||||
from struct import pack, unpack
|
||||
@ -378,4 +378,23 @@ def test_nfc_after(num_outs, fake_txn, try_sign, nfc_read, need_keypress, cap_st
|
||||
else:
|
||||
raise ValueError(got.type)
|
||||
|
||||
def test_rf_uid(rf_interface, cap_story, goto_home, pick_menu_item):
|
||||
# read UID of NFC chip over the air
|
||||
sw, ident = rf_interface.apdu(0xff, 0xca) # PAPDU_GET_UID
|
||||
assert sw == '0x9000'
|
||||
assert ident[-2:] == b'\x02\xe0' # ST vendor
|
||||
assert len(ident) == 8
|
||||
uid = ''.join('%02x'%i for i in reversed(ident))
|
||||
|
||||
# check UI is reporting same value
|
||||
goto_home()
|
||||
pick_menu_item('Advanced')
|
||||
pick_menu_item('Upgrade')
|
||||
pick_menu_item('Show Version')
|
||||
_, story = cap_story()
|
||||
|
||||
assert uid in story
|
||||
print(uid)
|
||||
|
||||
|
||||
# EOF
|
||||
|
||||
Loading…
Reference in New Issue
Block a user