Skip to content

Commit e0c69de

Browse files
committed
Add test for OTP
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
1 parent 847ab03 commit e0c69de

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

tests/pico-fido/test_071_otp.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import pytest
2+
3+
from utils import APDUResponse, send_apdu
4+
5+
6+
OTP_AID = [0xA0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01]
7+
INS_OTP = 0x01
8+
SLOT_CONFIGURE = 0x01
9+
SLOT_SWAP = 0x06
10+
ACCESS_CODE_SIZE = 6
11+
OTP_CONFIG_SIZE = 52
12+
13+
14+
def _crc16(data):
15+
crc = 0xFFFF
16+
for value in data:
17+
crc ^= value
18+
for _ in range(8):
19+
crc = (crc >> 1) ^ (0x8408 if crc & 1 else 0)
20+
return crc & 0xFFFF
21+
22+
23+
def _protected_config(access_code):
24+
config = bytearray(OTP_CONFIG_SIZE)
25+
config[22:38] = bytes(range(1, 17))
26+
config[38:44] = access_code
27+
crc = _crc16(config[:-2])
28+
config[-2:] = ((~crc) & 0xFFFF).to_bytes(2, "little")
29+
assert _crc16(config) == 0xF0B8
30+
return list(config)
31+
32+
33+
def test_slot_swap_requires_access_code_and_bounds_offsets(ccid_card):
34+
send_apdu(ccid_card, 0xA4, p1=0x04, p2=0x00, data=OTP_AID)
35+
access_code = bytes.fromhex("010203040506")
36+
config = _protected_config(access_code)
37+
38+
with pytest.raises(APDUResponse) as e:
39+
send_apdu(
40+
ccid_card,
41+
INS_OTP,
42+
p1=SLOT_SWAP,
43+
p2=0,
44+
data=[4, 0] + [0] * ACCESS_CODE_SIZE,
45+
)
46+
assert [e.value.sw1, e.value.sw2] == [0x6A, 0x86]
47+
48+
send_apdu(ccid_card, INS_OTP, p1=SLOT_CONFIGURE, p2=0, data=config)
49+
try:
50+
with pytest.raises(APDUResponse) as e:
51+
send_apdu(ccid_card, INS_OTP, p1=SLOT_SWAP, p2=0)
52+
assert [e.value.sw1, e.value.sw2] == [0x69, 0x82]
53+
54+
status = send_apdu(
55+
ccid_card,
56+
INS_OTP,
57+
p1=SLOT_SWAP,
58+
p2=0,
59+
data=[0, 0] + list(access_code),
60+
)
61+
assert status[4] & 0x02
62+
assert not status[4] & 0x01
63+
64+
send_apdu(
65+
ccid_card,
66+
INS_OTP,
67+
p1=SLOT_SWAP,
68+
p2=0,
69+
data=[0, 0] + list(access_code),
70+
)
71+
finally:
72+
send_apdu(
73+
ccid_card,
74+
INS_OTP,
75+
p1=SLOT_CONFIGURE,
76+
p2=0,
77+
data=[0] * OTP_CONFIG_SIZE + list(access_code),
78+
)

0 commit comments

Comments
 (0)