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:
frankmorgner
2010-01-08 14:33:52 +00:00
parent 9dd84e5962
commit c535710e13
2 changed files with 86 additions and 41 deletions

View File

@@ -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
# }}}

View File

@@ -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,20 +447,15 @@ 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:
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"])
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)
return r
# }}}