implement TPDU card reader

This commit is contained in:
NIIBE Yutaka
2016-10-05 20:00:22 +09:00
parent c1cc75f5b0
commit a73f8cf4fd

View File

@@ -36,6 +36,49 @@ def ccid_compose(msg_type, seq, slot=0, rsv=0, param=0, data=b""):
IFSC=254 IFSC=254
def compute_edc(pcb, info):
edc = pcb
edc ^= len(info)
for i in range(len(info)):
edc ^= info[i]
return edc
def compose_i_block(ns, info, more):
pcb = 0x00
if ns:
pcb |= 0x40
if more:
pcb |= 0x20
edc = compute_edc(pcb, info)
return bytes([0, pcb, len(info)]) + info + bytes([edc])
def compose_r_block(nr, edc_error=0):
pcb = 0x80
if nr:
pcb |= 0x10
if edc_error:
pcb |= 0x01
return bytes([0, pcb, 0, pcb])
def is_r_block_no_error(blk):
return ((blk[1] & 0xC0) == 0x80 and (blk[1] & 0x2f) == 0x00)
def is_s_block_time_ext(blk):
return (blk[1] == 0xC3)
def is_i_block_last(blk):
return ((blk[1] & 0x80) == 0 and (blk[1] & 0x20) == 0)
def is_i_block_more(blk):
return ((blk[1] & 0x80) == 0 and (blk[1] & 0x20) == 0x20)
def is_edc_error(blk):
# to be implemented
return 0
def i_block_content(blk)
return blk[3:-1]
class CardReader(object): class CardReader(object):
def __init__(self, dev): def __init__(self, dev):
""" """
@@ -130,18 +173,20 @@ class CardReader(object):
# #
if self.__use_APDU == False: if self.__use_APDU == False:
# TPDU reader configuration # TPDU reader configuration
self.ns = 0
self.nr = 0
pps = b"\xFF\x11\x18\xF6" pps = b"\xFF\x11\x18\xF6"
ret_pps = self.ccid_send_data_block(pps) status, chain, ret_pps = self.ccid_send_data_block(pps)
# #
param = b"\x18\x10\xFF\x75\x00\xFE\x00" param = b"\x18\x10\xFF\x75\x00\xFE\x00"
# ^--- This shoud be adapted by ATR string, see update_param_by_atr # ^--- This shoud be adapted by ATR string, see update_param_by_atr
msg = ccid_compose(0x6d, self.__seq, rsv=0x1, data=param) msg = ccid_compose(0x6d, self.__seq, rsv=0x1, data=param)
self.__dev.write(self.__bulkout, msg, self.__timeout) self.__dev.write(self.__bulkout, msg, self.__timeout)
self.increment_seq() self.increment_seq()
ret_param = self.ccid_get_result() status, chain, ret_param = self.ccid_get_result()
# Send an S-block # Send an S-block of changing IFSD=254
sblk = b"\x00\xC1\x01\xFE\x3E" sblk = b"\x00\xC1\x01\xFE\x3E"
ret_sblk = self.ccid_send_data_block(sblk) status, chain, ret_sblk = self.ccid_send_data_block(sblk)
return self.atr return self.atr
def ccid_power_off(self): def ccid_power_off(self):
@@ -183,11 +228,66 @@ class CardReader(object):
else: else:
raise ValueError("ccid_send_cmd") raise ValueError("ccid_send_cmd")
def send_tpdu(self, info=None, more=0, response_time_ext=0,
edc_error=0, no_error=0):
if info:
data = compose_i_block(self.ns, info, more)
elif response_time_ext:
# compose S-block
data = b"\x00\xE3\x00\xE3"
elif edc_error:
data = compose_r_block(self.nr, edc_error=1)
elif no_error:
data = compose_r_block(self.nr)
msg = ccid_compose(0x6f, self.__seq, data=data)
self.__dev.write(self.__bulkout, msg, self.__timeout)
self.increment_seq()
def recv_tpdu(self):
status, chain, data = self.ccid_get_result()
return data
def send_cmd(self, cmd): def send_cmd(self, cmd):
# Simple APDU case
if self.__use_APDU: if self.__use_APDU:
return self.ccid_send_cmd(cmd) return self.ccid_send_cmd(cmd)
# TPDU # TPDU case
raise ValueError("TPDU not implemented yet") while len(cmd) > 254:
blk = cmd[0:253]
cmd = cmd[254:]
while True:
self.send_tpdu(info=blk,more=1)
rblk = self.recv_tpdu()
if is_r_block_no_error(rblk):
break
self.ns = self.ns ^ 1
while True:
self.send_tpdu(info=cmd)
blk = self.recv_tpdu()
if is_r_block_no_error(blk):
break
self.ns = self.ns ^ 1
res = b""
while True:
if is_s_block_time_ext(blk):
self.send_tpdu(response_time_ext=1)
elif is_i_block_last(blk):
self.nr = self.nr ^ 1
if is_edc_error(blk):
self.send_tpdu(edc_error=1)
else:
res += i_block_content(blk)
break
elif is_i_block_more(blk):
self.nr = self.nr ^ 1
if is_edc_error(blk):
self.send_tpdu(edc_error=1)
else:
res += i_block_content(blk)
self.send_tpdu(no_error=1)
blk = self.recv_tpdu()
return res
class find_class(object): class find_class(object):
def __init__(self, usb_class): def __init__(self, usb_class):