- Move CryptoflexMF to cards.cryptoflex

- A little bit of code cleanup in SmartcardFilesystem.py


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@501 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
oepen
2011-08-23 10:49:35 +00:00
parent 4694e1fd1a
commit f04529b1f1
3 changed files with 145 additions and 145 deletions

View File

@@ -25,7 +25,7 @@ from virtualsmartcard.SmartcardFilesystem import MF, DF, TransparentStructureEF
from virtualsmartcard.ConstantDefinitions import FDB from virtualsmartcard.ConstantDefinitions import FDB
from virtualsmartcard.CryptoUtils import protect_string, read_protected_string from virtualsmartcard.CryptoUtils import protect_string, read_protected_string
import virtualsmartcard.SmartcardSAM import virtualsmartcard.SmartcardSAM
from virtualsmartcard.cards.cryptoflex import CryptoflexSAM from virtualsmartcard.cards.cryptoflex import CryptoflexSAM, CryptoflexMF
from virtualsmartcard.cards.ePass import PassportSAM from virtualsmartcard.cards.ePass import PassportSAM
# pgp directory # pgp directory
@@ -132,8 +132,6 @@ class CardGenerator(object):
self.sam = PassportSAM(self.mf) self.sam = PassportSAM(self.mf)
def __generate_cryptoflex(self): def __generate_cryptoflex(self):
from virtualsmartcard.SmartcardFilesystem import CryptoflexMF
self.mf = CryptoflexMF() self.mf = CryptoflexMF()
self.mf.append(TransparentStructureEF(parent=self.mf, fid=0x0002, self.mf.append(TransparentStructureEF(parent=self.mf, fid=0x0002,
filedescriptor=0x01, filedescriptor=0x01,

View File

@@ -22,9 +22,9 @@
""" """
from pickle import dumps, loads from pickle import dumps, loads
import logging import logging
from virtualsmartcard.ConstantDefinitions import * from virtualsmartcard.ConstantDefinitions import DCB, FDB, FID, LCB, REF
from virtualsmartcard.TLVutils import * from virtualsmartcard.TLVutils import *
from virtualsmartcard.SWutils import * from virtualsmartcard.SWutils import SW, SwError
from virtualsmartcard.utils import stringtoint, inttostring from virtualsmartcard.utils import stringtoint, inttostring
def isEqual(list): # {{{ def isEqual(list): # {{{
@@ -100,7 +100,7 @@ def getfile_byrefdataobj(mf, refdataobjs): # {{{
# }}} # }}}
def write(old, newlist, offsets, datacoding, maxsize=None): # {{{ def write(old, newlist, offsets, datacoding, maxsize=None): # {{{
"""Returns the status bytes and the result of a writeoperation according to """Returns the status bytes and the result of a write operation according to
the given data coding. the given data coding.
@param old: string of old data @param old: string of old data
@@ -169,7 +169,7 @@ def get_indexes(items, reference=REF["IDENTIFIER_FIRST"], index_current=0): # {{
if (reference in [REF["IDENTIFIER_FIRST"], if (reference in [REF["IDENTIFIER_FIRST"],
REF["IDENTIFIER_LAST"]] REF["IDENTIFIER_LAST"]]
or index_current == -1): or index_current == -1):
# Read first occurence OR # Read first occurrence OR
# Read last occurrence OR # Read last occurrence OR
# No current record (and next/previous occurrence) # No current record (and next/previous occurrence)
indexes = range(0, len(items)) indexes = range(0, len(items))
@@ -355,39 +355,39 @@ class File(object): # {{{
tlv_data.append(tag, newlength, newvalue) tlv_data.append(tag, newlength, newvalue)
self.setdec(attribute, tlv_data) self.setdec(attribute, tlv_data)
def readbinary(*argz, **args): def readbinary(self, *argz, **args):
"""Only a template, will raise an error.""" """Only a template, will raise an error."""
raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"]) raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"])
def writebinary(*argz, **args): def writebinary(self, *argz, **args):
"""Only a template, will raise an error.""" """Only a template, will raise an error."""
raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"]) raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"])
def updatebinary(*argz, **args): def updatebinary(self, *argz, **args):
"""Only a template, will raise an error.""" """Only a template, will raise an error."""
raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"]) raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"])
def erasebinary(*argz, **args): def erasebinary(self, *argz, **args):
"""Only a template, will raise an error.""" """Only a template, will raise an error."""
raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"]) raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"])
def readrecord(*argz, **args): def readrecord(self, *argz, **args):
"""Only a template, will raise an error.""" """Only a template, will raise an error."""
raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"]) raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"])
def writerecord(*argz, **args): def writerecord(self, *argz, **args):
"""Only a template, will raise an error.""" """Only a template, will raise an error."""
raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"]) raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"])
def appendrecord(*argz, **args): def appendrecord(self, *argz, **args):
"""Only a template, will raise an error.""" """Only a template, will raise an error."""
raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"]) raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"])
def updaterecord(*argz, **args): def updaterecord(self, *argz, **args):
"""Only a template, will raise an error.""" """Only a template, will raise an error."""
raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"]) raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"])
def select(*argz, **args): def select(self, *argz, **args):
"""Only a template, will raise an error.""" """Only a template, will raise an error."""
raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"]) raise SwError(SW["ERR_INCOMPATIBLEWITHFILE"])
# }}} # }}}
@@ -1631,130 +1631,3 @@ class RecordStructureEF(EF): # {{{
r.identifier = None r.identifier = None
return SW["NORMAL"] return SW["NORMAL"]
# }}} # }}}
class CryptoflexMF(MF): # {{{
@staticmethod
def create(p1, p2, data):
if data[0:2] != "\xff\xff":
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
args = {
"parent": None,
"filedescriptor": 0,
"fid": stringtoint(data[4:6]),
}
if data[6] == "\x01":
args["data"] = chr(0)*stringtoint(data[2:4])
args["filedescriptor"] = FDB["EFSTRUCTURE_TRANSPARENT"]
file = TransparentStructureEF(**args)
elif data[6] == "\x02":
if len(data)>16:
args["maxrecordsize"] = stringtoint(data[16])
elif p2:
# if given a number of records
args["maxrecordsize"] = (stringtoint(data[2:4])/p2)
args["filedescriptor"] = FDB["EFSTRUCTURE_LINEAR_FIXED_NOFURTHERINFO"]
file = RecordStructureEF(**args)
elif data[6] == "\x03":
args["filedescriptor"] = FDB["EFSTRUCTURE_LINEAR_VARIABLE_NOFURTHERINFO"]
file = RecordStructureEF(**args)
elif data[6] == "\x04":
args["filedescriptor"] = FDB["EFSTRUCTURE_CYCLIC_NOFURTHERINFO"]
file = RecordStructureEF(**args)
elif data[6] == "\x38":
if data[12] != "\x03":
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
file = DF(**args)
else:
logging.error("unknown type: 0x%x" % ord(data[6]))
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
return [file]
def recordHandlingDecode(self, p1, p2):
if p2 < 4:
p1 = 0
return MF.recordHandlingDecode(self, p1, p2)
def dataUnitsDecodePlain(self, p1, p2, data):
ef = self.currentEF()
# FIXME: Cyberflex Access TM Software Development Kit Release 3C
# enforces the following:
# offsets = [(p2 << 8) + p1]
# but smartcard_login-0.1.1 requires:
offsets = [(p1 << 8) + p2]
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

@@ -19,9 +19,13 @@
from virtualsmartcard.SmartcardSAM import SAM from virtualsmartcard.SmartcardSAM import SAM
from virtualsmartcard.SEutils import Security_Environment from virtualsmartcard.SEutils import Security_Environment
from virtualsmartcard.SWutils import SwError, SW from virtualsmartcard.SWutils import SwError, SW
from virtualsmartcard.utils import inttostring from virtualsmartcard.utils import inttostring, stringtoint
from virtualsmartcard import TLVutils from virtualsmartcard import TLVutils
from virtualsmartcard.SmartcardFilesystem import MF, TransparentStructureEF, \
RecordStructureEF, DF, EF
from virtualsmartcard.ConstantDefinitions import FDB
import struct, logging import struct, logging
class CryptoflexSE(Security_Environment): class CryptoflexSE(Security_Environment):
@@ -118,4 +122,129 @@ class CryptoflexSAM(SAM):
sw, data = SAM.internal_authenticate(self, p1, p2, data) sw, data = SAM.internal_authenticate(self, p1, p2, data)
if data != "": if data != "":
data = data[::-1] data = data[::-1]
return sw, data return sw, data
class CryptoflexMF(MF): # {{{
@staticmethod
def create(p1, p2, data):
if data[0:2] != "\xff\xff":
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
args = {
"parent": None,
"filedescriptor": 0,
"fid": stringtoint(data[4:6]),
}
if data[6] == "\x01":
args["data"] = chr(0)*stringtoint(data[2:4])
args["filedescriptor"] = FDB["EFSTRUCTURE_TRANSPARENT"]
file = TransparentStructureEF(**args)
elif data[6] == "\x02":
if len(data)>16:
args["maxrecordsize"] = stringtoint(data[16])
elif p2:
# if given a number of records
args["maxrecordsize"] = (stringtoint(data[2:4])/p2)
args["filedescriptor"] = FDB["EFSTRUCTURE_LINEAR_FIXED_NOFURTHERINFO"]
file = RecordStructureEF(**args)
elif data[6] == "\x03":
args["filedescriptor"] = FDB["EFSTRUCTURE_LINEAR_VARIABLE_NOFURTHERINFO"]
file = RecordStructureEF(**args)
elif data[6] == "\x04":
args["filedescriptor"] = FDB["EFSTRUCTURE_CYCLIC_NOFURTHERINFO"]
file = RecordStructureEF(**args)
elif data[6] == "\x38":
if data[12] != "\x03":
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
file = DF(**args)
else:
logging.error("unknown type: 0x%x" % ord(data[6]))
raise SwError(SW["ERR_INCORRECTPARAMETERS"])
return [file]
def recordHandlingDecode(self, p1, p2):
if p2 < 4:
p1 = 0
return MF.recordHandlingDecode(self, p1, p2)
def dataUnitsDecodePlain(self, p1, p2, data):
ef = self.currentEF()
# FIXME: Cyberflex Access TM Software Development Kit Release 3C
# enforces the following:
# offsets = [(p2 << 8) + p1]
# but smartcard_login-0.1.1 requires:
offsets = [(p1 << 8) + p2]
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
# }}}