added serial number to cryptoflex. opensc can read it.
git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@14 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -219,7 +219,6 @@ def make_property(prop, doc): # {{{
|
||||
# }}}
|
||||
|
||||
|
||||
|
||||
class File(object): # {{{
|
||||
"""Template class for a smartcard file."""
|
||||
bertlv_data = make_property("bertlv_data", "list of (tag, length, value)-tuples of BER-TLV coded data objects (encrypted)")
|
||||
@@ -398,16 +397,13 @@ class DF(File): # {{{
|
||||
data = make_property("data", "unknown")
|
||||
content = make_property("content", "list of files of the DF")
|
||||
dfname = make_property("dfname", "string with up to 16 bytes. DF name, which can also be used as application identifier.")
|
||||
def __init__(self, parent, fid, filedescriptor=FDB["NOTSHAREABLEFILE"],
|
||||
def __init__(self, parent, fid, filedescriptor=FDB["NOTSHAREABLEFILE"]|FDB["DF"],
|
||||
lifecycle=LCB["ACTIVATED"],
|
||||
simpletlv_data=None, bertlv_data=None, dfname=None, data=""):
|
||||
"""
|
||||
The flag FDB["DF"] is automatically added to the file descriptor byte
|
||||
filedescriptor.
|
||||
|
||||
See File for more.
|
||||
"""
|
||||
File.__init__(self, parent, fid, filedescriptor|FDB["DF"], lifecycle,
|
||||
File.__init__(self, parent, fid, filedescriptor, lifecycle,
|
||||
simpletlv_data, bertlv_data)
|
||||
if dfname:
|
||||
if len(dfname)>16:
|
||||
@@ -501,16 +497,14 @@ class MF(DF): # {{{
|
||||
current = make_property("current", "the currently selected file")
|
||||
firstSFT = make_property("firstSFT", "string of length 1. The first software function table from the historical bytes.")
|
||||
secondSFT = make_property("secondSFT", "string of length 1. The second software function table from the historical bytes.")
|
||||
def __init__(self, filedescriptor=FDB["NOTSHAREABLEFILE"],
|
||||
def __init__(self, filedescriptor=FDB["NOTSHAREABLEFILE"]|FDB["DF"],
|
||||
lifecycle=LCB["ACTIVATED"],
|
||||
simpletlv_data=None, bertlv_data=None, dfname=None):
|
||||
"""The flag FDB["DF"] is automatically added to the file descriptor
|
||||
bytey filedescriptor. The file identifier FID["MF"] is automatically
|
||||
added.
|
||||
"""The file identifier FID["MF"] is automatically added.
|
||||
|
||||
See DF for more.
|
||||
"""
|
||||
DF.__init__(self, None, FID["MF"], filedescriptor|FDB["DF"], lifecycle,
|
||||
DF.__init__(self, None, FID["MF"], filedescriptor, lifecycle,
|
||||
simpletlv_data, bertlv_data, dfname)
|
||||
self.current = self
|
||||
self.firstSFT = inttostring(MF.makeFirstSoftwareFunctionTable(), 1)
|
||||
@@ -635,7 +629,7 @@ class MF(DF): # {{{
|
||||
|
||||
return "".join(fdm)
|
||||
|
||||
def __selectFile(self, p1, p2, data):
|
||||
def _selectFile(self, p1, p2, data):
|
||||
"""
|
||||
Returns the file specified by 'p1' and 'data' from the select
|
||||
file command APDU.
|
||||
@@ -698,7 +692,7 @@ class MF(DF): # {{{
|
||||
P2_FCP = 1<<2
|
||||
P2_FMD = 2<<2
|
||||
P2_NONE = 3<<2
|
||||
file = self.__selectFile(p1, p2, data)
|
||||
file = self._selectFile(p1, p2, data)
|
||||
|
||||
if p2 == P2_NONE:
|
||||
data = ""
|
||||
@@ -1107,7 +1101,7 @@ class MF(DF): # {{{
|
||||
tlv_data = []
|
||||
isSimpleTlv = True
|
||||
else:
|
||||
raise SwError(SW["ERR_INCORRECTP1P2"])
|
||||
raise SwError(SW["ERR_NOTSUPPORTED"])
|
||||
|
||||
return file, isSimpleTlv, tlv_data
|
||||
|
||||
@@ -1295,7 +1289,7 @@ class MF(DF): # {{{
|
||||
integers and 'data' as binary string. Returns the status bytes as two
|
||||
byte long integer and the response data as binary string.
|
||||
"""
|
||||
file = self.__selectFile(p1, p2, data)
|
||||
file = self._selectFile(p1, p2, data)
|
||||
file.parent.content.remove(file)
|
||||
# FIXME: free memory of file and remove its content from the security device
|
||||
|
||||
@@ -1334,18 +1328,15 @@ class EF(File): # {{{
|
||||
class TransparentStructureEF(EF): # {{{
|
||||
"""Class for an elementary file with transparent structure."""
|
||||
data = make_property("data", "string (encrypted). The file's data.")
|
||||
def __init__(self, parent, fid, filedescriptor,
|
||||
def __init__(self, parent, fid, filedescriptor=FDB["EFSTRUCTURE_TRANSPARENT"],
|
||||
lifecycle=LCB["ACTIVATED"],
|
||||
simpletlv_data=None, bertlv_data=None,
|
||||
datacoding=DCB["ONETIMEWRITE"], shortfid=0, data=""):
|
||||
"""
|
||||
The flag FDB["EFSTRUCTURE_TRANSPARENT"] is automatically added to
|
||||
'filedescriptor'.
|
||||
|
||||
See EF for more.
|
||||
"""
|
||||
EF.__init__(self, parent, fid,
|
||||
filedescriptor|FDB["EFSTRUCTURE_TRANSPARENT"], lifecycle,
|
||||
filedescriptor, lifecycle,
|
||||
simpletlv_data, bertlv_data,
|
||||
datacoding, shortfid)
|
||||
self.setdec('data', data)
|
||||
@@ -1701,4 +1692,68 @@ class CryptoflexMF(MF): # {{{
|
||||
|
||||
datalist = [data]
|
||||
return ef, offsets, datalist
|
||||
|
||||
def selectFile(self, p1, p2, data):
|
||||
"""
|
||||
Function for instruction 0xa4. Takes the parameter bytes 'p1', 'p2' as
|
||||
integers and 'data' as binary string. Returns the status bytes as two
|
||||
byte long integer and the response data as binary string.
|
||||
"""
|
||||
P2_FCI = 0
|
||||
P2_FCP = 1<<2
|
||||
P2_FMD = 2<<2
|
||||
P2_NONE = 3<<2
|
||||
file = self._selectFile(p1, p2, data)
|
||||
|
||||
if isinstance(file, EF):
|
||||
size = inttostring(min(0xffff, len(file.getenc('data'))), 2) # File size (body only)
|
||||
extra = chr(0) # RFU
|
||||
if isinstance(file, RecordStructureEF) and file.hasFixedRecordSize() and not file.isCyclic():
|
||||
extra += chr(0) + chr(min(file.records, 0xff)) # Length of records
|
||||
elif isinstance(file, DF):
|
||||
size = inttostring(0xffff, 2) # Number of unused EEPROM bytes available in the DF
|
||||
efcount = 0
|
||||
dfcount = 0
|
||||
chv1 = None
|
||||
chv2 = None
|
||||
chv1lifecycle = 0
|
||||
chv2lifecycle = 0
|
||||
for f in self.content:
|
||||
if f.fid == 0x0000:
|
||||
chv1 = f
|
||||
chv1lifecycle = f.lifecycle & 1
|
||||
if f.fid == 0x0100:
|
||||
chv2 = f
|
||||
chv2lifecycle = f.lifecycle & 1
|
||||
if isinstance(f, EF):
|
||||
efcount += 1
|
||||
if isinstance(f, DF):
|
||||
dfcount += 1
|
||||
if chv1:
|
||||
extra = chr(1) # TODO LSB correct?
|
||||
else:
|
||||
extra = chr(0) # TODO LSB correct?
|
||||
extra += chr(efcount)
|
||||
extra += chr(dfcount)
|
||||
extra += chr(0) # TODO Number of PINs and unblock CHV PINs
|
||||
extra += chr(0) # RFU
|
||||
if chv1:
|
||||
extra += chr(0) # TODO Number of remaining CHV1 attempts
|
||||
extra += chr(0) # TODO Number of remaining unblock CHV1 attempts
|
||||
if chv2:
|
||||
extra += chr(0) # TODO CHV2 key status
|
||||
extra += chr(0) # TODO CHV2 unblocking key status
|
||||
|
||||
data = inttostring(0, 2) # RFU
|
||||
data += size
|
||||
data += inttostring(file.fid, 2)
|
||||
data += inttostring(file.filedescriptor) # File type
|
||||
data += inttostring(0, 4) # ACs TODO
|
||||
data += chr(file.lifecycle & 1) # File status
|
||||
data += chr(len(extra))
|
||||
data += extra
|
||||
|
||||
self.current = file
|
||||
|
||||
return SW["NORMAL"], data
|
||||
# }}}
|
||||
|
||||
@@ -418,17 +418,12 @@ class CryptoflexOS(SmartcardOS): # {{{
|
||||
def __init__(self, filename, mf=None, ins2handler=None, maxle=MAX_SHORT_LE):
|
||||
if filename == None and mf == None:
|
||||
mf = CryptoflexMF()
|
||||
mf.append(TransparentStructureEF(parent=mf, fid=0x0002, filedescriptor=0x01,
|
||||
data="\x00\x00\x00\x01\x00\x01\x00\x00"))#EF.ICCSN
|
||||
#TODO: Load objects from disk
|
||||
self.firstrun = True
|
||||
SmartcardOS.__init__(self, None,mf=mf, ins2handler=ins2handler, maxle=maxle,
|
||||
sam=CryptoflexSAM("testconfig.sam","DUMMYKEYDUMMYKEY"))
|
||||
card_capabilities = self.mf.firstSFT + self.mf.secondSFT + SmartcardOS.makeThirdSoftwareFunctionTable()
|
||||
SmartcardOS.atr = SmartcardOS.makeATR(T=0, directConvention = True, TA1=0x13,
|
||||
histChars = chr(0x80) + chr(0x70 + len(card_capabilities)) +
|
||||
card_capabilities)
|
||||
|
||||
def powerUp(self):
|
||||
self.firstrun = True
|
||||
self.atr = '\x3B\xE2\x00\x00\x40\x20\x49\x06'
|
||||
|
||||
def execute(self, msg):
|
||||
def notImplemented(*argz, **args):
|
||||
@@ -452,21 +447,16 @@ class CryptoflexOS(SmartcardOS): # {{{
|
||||
# cryptoflex does not inpterpret le==0 as maxle
|
||||
self.lastCommandSW = sw
|
||||
self.lastCommandOffcut = data
|
||||
return inttostring(SW["ERR_WRONGLENGTH"]|min(0xff,len(data)))
|
||||
r = R_APDU(inttostring(SW["ERR_WRONGLENGTH"] + min(0xff,len(data)))).render()
|
||||
else:
|
||||
if ins == 0xa4 and len(data):
|
||||
# get response should be followed by select file
|
||||
self.lastCommandSW = sw
|
||||
self.lastCommandOffcut = data
|
||||
r = R_APDU(inttostring(SW["NORMAL_REST"] + min(0xff, len(data)))).render()
|
||||
else:
|
||||
r = SmartcardOS.formatResult(self, le, data, sw, False)
|
||||
|
||||
if self.firstrun:
|
||||
# FIXME: other than Cryptoflex Access TM Software Development Kit
|
||||
# Release 3C, smartcard_login-0.1.1 requires:
|
||||
self.firstrun = False
|
||||
if ord(r[0]) == SW["NORMAL_REST"]>>8:
|
||||
r = inttostring(SW["NORMAL"])
|
||||
|
||||
# be fully successfull if at least one databyte has been returned
|
||||
if len(r) > 2 and r[-2] == chr(SW["NORMAL_REST"]>>8):
|
||||
return r[:-2] + inttostring(SW["NORMAL"])
|
||||
|
||||
return r
|
||||
# }}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user