- Object orientated refactoring of CardGenerator

- PassportOS class in VirtualSmartcard.py is no longer needed, because all the functionallity is now in CardGenerator
- Removed hard coded image
- Added version number and type to file format


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@38 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
oepen
2010-02-01 16:40:27 +00:00
parent 638e5301d0
commit 5e9a299eaa
3 changed files with 172 additions and 178 deletions

View File

@@ -17,11 +17,11 @@
# virtualsmartcard. If not, see <http://www.gnu.org/licenses/>.
#
import sys, getpass, anydbm
import sys, getpass, anydbm, readline, os, dircache
from pickle import loads, dumps
from TLVutils import pack
from utils import inttostring
from SmartcardFilesystem import MF, TransparentStructureEF
from SmartcardFilesystem import *
# pgp directory
#self.mf.append(DF(parent=self.mf,
@@ -34,27 +34,42 @@ from SmartcardFilesystem import MF, TransparentStructureEF
#self.mf.append(DF(parent=self.mf,
#fid=3, dfname='\xa0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00'))
def generate_iso_card():
class CardGenerator(object):
def __init__(self, type='iso7816', sam=None, mf=None):
types = ['iso7816', 'ePass', 'cryptoflex']
if not type in types:
raise ValueError, "Unsupported type " % type
self.type = type
self.mf = None
self.sam = None
def __generate_iso_card(self):
from SmartcardSAM import SAM
print "Using default SAM. Insecure!!!"
sam = SAM("1234", "1234567890") #FIXME: Use user provided data
self.sam = SAM("1234", "1234567890") #FIXME: Use user provided data
mf = MF(filedescriptor=FDB["DF"], lifecycle=LCB["ACTIVATED"], dfname=None)
self.SAM.set_MF(self.mf)
self.mf = MF(filedescriptor=FDB["DF"], lifecycle=LCB["ACTIVATED"], dfname=None)
self.sam.set_MF(self.mf)
return mf, sam
def generate_ePass():
def __generate_ePass(self):
from PIL import Image
from SmartcardFilesystem import DF
from SmartcardSAM import PassportSAM
MRZ1 = "P<UTOERIKSSON<<ANNA<MARIX<<<<<<<<<<<<<<<<<<<"
MRZ2 = "L898902C<3UTO6908061F9406236ZE184226B<<<<<14"
MRZ = MRZ1 + MRZ2
MRZ = raw_input("Please enter the MRZ as one string: ") #TODO: Sanity checks
readline.set_completer_delims("")
readline.parse_and_bind("tab: complete")
picturepath = raw_input("Please enter the path to an image: ")
picturepath = picturepath.rstrip() #FIXME
#MRZ1 = "P<UTOERIKSSON<<ANNA<MARIX<<<<<<<<<<<<<<<<<<<"
#MRZ2 = "L898902C<3UTO6908061F9406236ZE184226B<<<<<14"
#MRZ = MRZ1 + MRZ2
picturepath = "jp2.jpg"
try:
im = Image.open(picturepath)
pic_width, pic_height = im.size
@@ -62,7 +77,7 @@ def generate_ePass():
picture = fd.read()
fd.close()
except IOError:
print "Could not find picture %s" % picturepath
print "Failed to open file: " + picturepath
pic_width = 0
pic_height = 0
picture = None
@@ -99,21 +114,40 @@ def generate_ePass():
fid = df.select("fid",0x0102)
fid.writebinary([0],[DG2])
sam = PassportSAM(mf)
return mf, sam
self.mf = mf
self.sam = PassportSAM(self.mf)
def generate_cryptoflex():
from SmartcardFilesystem import CryptoflexMF
def __generate_cryptoflex(self):
from SmartcardSAM import CryptoflexSAM
mf = CryptoflexMF()
mf.append(TransparentStructureEF(parent=mf, fid=0x0002, filedescriptor=0x01,
self.mf = CryptoflexMF()
self.mf.append(TransparentStructureEF(parent=self.mf, fid=0x0002, filedescriptor=0x01,
data="\x00\x00\x00\x01\x00\x01\x00\x00")) #EF.ICCSN
sam = CryptoflexSAM(mf)
self.sam = CryptoflexSAM(self.mf)
return mf, sam
def generateCard(self):
if self.type == 'iso7816':
self.__generate_iso_card()
elif self.type == 'ePass':
self.__generate_ePass()
elif self.type == 'cryptoflex':
self.__generate_cryptoflex()
else:
raise ValueError, "Unsupported card type " % self.type
def loadCard(filename, password=None):
def getCard(self):
if self.sam is None or self.mf is None:
self.generateCard()
return self.mf, self.sam
def setCard(self, mf=None, sam=None):
if mf != None:
self.mf = mf
if sam != None:
self.sam = sam
def loadCard(self, filename, password=None):
from CryptoUtils import read_protected_string
try:
@@ -126,20 +160,13 @@ def loadCard(filename, password=None):
serializedMF = read_protected_string(db["mf"], password)
serializedSAM = read_protected_string(db["sam"], password)
SAM = loads(serializedSAM)
MF = loads(serializedMF)
#self.type = db["type"]
self.sam = loads(serializedSAM)
self.mf = loads(serializedMF)
self.type = db["type"]
return SAM, MF
def saveCard(mf, sam, filename, password=None):
def saveCard(self, filename, password=None):
from CryptoUtils import protect_string
if filename != None:
print "Saving smartcard configuration to %s" % filename
else: #TODO: Ask user for filename
pass
if password is None:
passwd1 = getpass.getpass("Please enter a password.")
passwd2 = getpass.getpass("Please retype your password.")
@@ -148,8 +175,11 @@ def saveCard(mf, sam, filename, password=None):
else:
password = passwd1
mf_string = dumps(mf)
sam_string = dumps(sam)
if self.mf == None or self.sam == None: #TODO: Sanity checks
raise ValueError, "Card Generator was not set up properly (missing mf or sam)"
mf_string = dumps(self.mf)
sam_string = dumps(self.sam)
protectedMF = protect_string(mf_string, password)
protectedSAM = protect_string(sam_string, password)
@@ -157,7 +187,8 @@ def saveCard(mf, sam, filename, password=None):
db = anydbm.open(filename, 'c')
db["mf"] = protectedMF
db["sam"] = protectedSAM
#db["type"] = self.type
db["type"] = self.type
db["version"] = "0.1"
db.close()
except anydbm.error:
print "Failed to write data to disk"
@@ -178,11 +209,7 @@ if __name__ == "__main__":
print "You have to provide a filename using the -f option"
sys.exit()
if options.type == 'iso7816':
mf, sam = generate_iso_card()
elif options.type == 'ePass':
mf, sam = generate_ePass()
elif options.type == 'cryptoflex':
mf, sam = generate_cryptoflex()
generator = CardGenerator(options.type)
generator.generateCard()
generator.saveCard(options.filename)
saveCard(mf, sam, options.filename)

View File

@@ -21,21 +21,21 @@ from TLVutils import *
from SWutils import SwError, SW
from SmartcardFilesystem import prettyprint_anything, MF, DF, CryptoflexMF, TransparentStructureEF
from utils import C_APDU, R_APDU, hexdump, inttostring
from SmartcardSAM import CardContainer, SAM, PassportSAM, CryptoflexSAM
from SmartcardSAM import SAM, PassportSAM, CryptoflexSAM
import CardGenerator
from pickle import dumps, loads
import socket, struct, sys, signal, atexit, traceback
import struct
import getpass
import shelve, anydbm
import struct, getpass, anydbm
class SmartcardOS(object): # {{{
def __init__(self, mf=None, sam=None, ins2handler=None, maxle=MAX_SHORT_LE):
from CardGenerator import generate_iso_card
def __init__(self, mf, sam, ins2handler=None, maxle=MAX_SHORT_LE):
self.mf = mf
self.SAM = sam
if self.mf == None and self.SAM == None:
self.mf, self.SAM = generate_iso_card()
#if self.mf == None and self.SAM == None:
# self.mf, self.SAM = generate_iso_card()
if not ins2handler:
self.ins2handler = {
@@ -295,39 +295,8 @@ class SmartcardOS(object): # {{{
return answer
# }}}
class PassportOS(SmartcardOS):
"""
The PassportOS emulates a Passport Application according to ICAO MRTD standard.
It generates a data structure ...
It also integrates a SAM derived from the standard SmartcardSAM, providing the
Basic Access Control (BAC) mechanisms.
"""
def __init__(self, mf=None, sam=None, ins2handler=None, maxle=MAX_SHORT_LE):
from CardGenerator import generate_ePass
if mf == None and sam == None:
mf, sam = generate_ePass()
else: #TODO: Sanity check if mf or sam are provided
if mf == None:
mf, tmp = generate_ePass()
if sam == None:
sam = PassportSAM(mf)
SmartcardOS.__init__(self, mf=mf, sam=sam, ins2handler=ins2handler, maxle=maxle)
class CryptoflexOS(SmartcardOS): # {{{
def __init__(self, mf=None, sam=None, ins2handler=None, maxle=MAX_SHORT_LE):
from GenerateCard import generate_cryptoflex
if mf == None and sam == None:
mf, sam = generate_cryptoflex()
else:
if mf == None:
mf, tmp = generate_cryptoflex()
del tmp
if sam == None:
sam = CryptoflexSAM(mf)
def __init__(self, mf, sam, ins2handler=None, maxle=MAX_SHORT_LE):
SmartcardOS.__init__(self, mf, sam, ins2handler, maxle)
self.atr = '\x3B\xE2\x00\x00\x40\x20\x49\x06'
@@ -387,11 +356,9 @@ class VirtualICC(object): # {{{
def __init__(self, filename, type, lenlen=3, host="localhost", port=35963):
from os.path import exists
from CardGenerator import loadCard
self.filename = None
SAM = None
MF = None
self.cardGenerator = CardGenerator.CardGenerator(type)
#If a filename is specified, try to load the card from disk
if filename == None:
@@ -399,16 +366,15 @@ class VirtualICC(object): # {{{
else:
self.filename = filename
if exists(filename):
print "Found existing card " + filename + ". Will try to open it"
SAM, MF = loadCard(filename)
self.cardGenerator.loadCard(self.filename)
else:
print "No file " + filename + " found. Will create new file at termination of program."
print "No file " + self.filename + " found. Will create new file at termination of program."
MF, SAM = self.cardGenerator.getCard()
#Generate an OS object of the correct type
if type == "iso7816":
if type == "iso7816" or type == "ePass":
self.os = SmartcardOS(MF, SAM)
elif type == "ePass":
self.os = PassportOS(MF, SAM)
elif type == "cryptoflex":
self.os = CryptoflexOS(MF, SAM)
else:
@@ -431,9 +397,10 @@ class VirtualICC(object): # {{{
#atexit.register(saveCard)
def signalHandler(self, signal=None, frame=None):
from CardGenerator import saveCard
self.sock.close()
saveCard(self.os.mf, self.os.SAM, self.filename)
if self.filename != None:
self.cardGenerator.setCard(self.os.mf, self.os.SAM)
self.cardGenerator.saveCard(self.filename)
sys.exit()
@staticmethod

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB