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): # {{{ class File(object): # {{{
"""Template class for a smartcard file.""" """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)") 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") data = make_property("data", "unknown")
content = make_property("content", "list of files of the DF") 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.") 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"], lifecycle=LCB["ACTIVATED"],
simpletlv_data=None, bertlv_data=None, dfname=None, data=""): 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. See File for more.
""" """
File.__init__(self, parent, fid, filedescriptor|FDB["DF"], lifecycle, File.__init__(self, parent, fid, filedescriptor, lifecycle,
simpletlv_data, bertlv_data) simpletlv_data, bertlv_data)
if dfname: if dfname:
if len(dfname)>16: if len(dfname)>16:
@@ -501,16 +497,14 @@ class MF(DF): # {{{
current = make_property("current", "the currently selected file") 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.") 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.") 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"], lifecycle=LCB["ACTIVATED"],
simpletlv_data=None, bertlv_data=None, dfname=None): simpletlv_data=None, bertlv_data=None, dfname=None):
"""The flag FDB["DF"] is automatically added to the file descriptor """The file identifier FID["MF"] is automatically added.
bytey filedescriptor. The file identifier FID["MF"] is automatically
added.
See DF for more. 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) simpletlv_data, bertlv_data, dfname)
self.current = self self.current = self
self.firstSFT = inttostring(MF.makeFirstSoftwareFunctionTable(), 1) self.firstSFT = inttostring(MF.makeFirstSoftwareFunctionTable(), 1)
@@ -635,7 +629,7 @@ class MF(DF): # {{{
return "".join(fdm) 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 Returns the file specified by 'p1' and 'data' from the select
file command APDU. file command APDU.
@@ -698,7 +692,7 @@ class MF(DF): # {{{
P2_FCP = 1<<2 P2_FCP = 1<<2
P2_FMD = 2<<2 P2_FMD = 2<<2
P2_NONE = 3<<2 P2_NONE = 3<<2
file = self.__selectFile(p1, p2, data) file = self._selectFile(p1, p2, data)
if p2 == P2_NONE: if p2 == P2_NONE:
data = "" data = ""
@@ -1107,7 +1101,7 @@ class MF(DF): # {{{
tlv_data = [] tlv_data = []
isSimpleTlv = True isSimpleTlv = True
else: else:
raise SwError(SW["ERR_INCORRECTP1P2"]) raise SwError(SW["ERR_NOTSUPPORTED"])
return file, isSimpleTlv, tlv_data return file, isSimpleTlv, tlv_data
@@ -1295,7 +1289,7 @@ class MF(DF): # {{{
integers and 'data' as binary string. Returns the status bytes as two integers and 'data' as binary string. Returns the status bytes as two
byte long integer and the response data as binary string. 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) file.parent.content.remove(file)
# FIXME: free memory of file and remove its content from the security device # FIXME: free memory of file and remove its content from the security device
@@ -1334,18 +1328,15 @@ class EF(File): # {{{
class TransparentStructureEF(EF): # {{{ class TransparentStructureEF(EF): # {{{
"""Class for an elementary file with transparent structure.""" """Class for an elementary file with transparent structure."""
data = make_property("data", "string (encrypted). The file's data.") 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"], lifecycle=LCB["ACTIVATED"],
simpletlv_data=None, bertlv_data=None, simpletlv_data=None, bertlv_data=None,
datacoding=DCB["ONETIMEWRITE"], shortfid=0, data=""): datacoding=DCB["ONETIMEWRITE"], shortfid=0, data=""):
""" """
The flag FDB["EFSTRUCTURE_TRANSPARENT"] is automatically added to
'filedescriptor'.
See EF for more. See EF for more.
""" """
EF.__init__(self, parent, fid, EF.__init__(self, parent, fid,
filedescriptor|FDB["EFSTRUCTURE_TRANSPARENT"], lifecycle, filedescriptor, lifecycle,
simpletlv_data, bertlv_data, simpletlv_data, bertlv_data,
datacoding, shortfid) datacoding, shortfid)
self.setdec('data', data) self.setdec('data', data)
@@ -1701,4 +1692,68 @@ class CryptoflexMF(MF): # {{{
datalist = [data] datalist = [data]
return ef, offsets, datalist 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): def __init__(self, filename, mf=None, ins2handler=None, maxle=MAX_SHORT_LE):
if filename == None and mf == None: if filename == None and mf == None:
mf = CryptoflexMF() 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 #TODO: Load objects from disk
self.firstrun = True
SmartcardOS.__init__(self, None,mf=mf, ins2handler=ins2handler, maxle=maxle, SmartcardOS.__init__(self, None,mf=mf, ins2handler=ins2handler, maxle=maxle,
sam=CryptoflexSAM("testconfig.sam","DUMMYKEYDUMMYKEY")) sam=CryptoflexSAM("testconfig.sam","DUMMYKEYDUMMYKEY"))
card_capabilities = self.mf.firstSFT + self.mf.secondSFT + SmartcardOS.makeThirdSoftwareFunctionTable() self.atr = '\x3B\xE2\x00\x00\x40\x20\x49\x06'
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
def execute(self, msg): def execute(self, msg):
def notImplemented(*argz, **args): def notImplemented(*argz, **args):
@@ -452,21 +447,16 @@ class CryptoflexOS(SmartcardOS): # {{{
# cryptoflex does not inpterpret le==0 as maxle # cryptoflex does not inpterpret le==0 as maxle
self.lastCommandSW = sw self.lastCommandSW = sw
self.lastCommandOffcut = data 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: else:
r = SmartcardOS.formatResult(self, le, data, sw, False) 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 return r
# }}} # }}}