- 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/>. # 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 pickle import loads, dumps
from TLVutils import pack from TLVutils import pack
from utils import inttostring from utils import inttostring
from SmartcardFilesystem import MF, TransparentStructureEF from SmartcardFilesystem import *
# pgp directory # pgp directory
#self.mf.append(DF(parent=self.mf, #self.mf.append(DF(parent=self.mf,
@@ -34,27 +34,42 @@ from SmartcardFilesystem import MF, TransparentStructureEF
#self.mf.append(DF(parent=self.mf, #self.mf.append(DF(parent=self.mf,
#fid=3, dfname='\xa0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00')) #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 from SmartcardSAM import SAM
print "Using default SAM. Insecure!!!" 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.mf = MF(filedescriptor=FDB["DF"], lifecycle=LCB["ACTIVATED"], dfname=None)
self.SAM.set_MF(self.mf) self.sam.set_MF(self.mf)
return mf, sam def __generate_ePass(self):
def generate_ePass():
from PIL import Image from PIL import Image
from SmartcardFilesystem import DF
from SmartcardSAM import PassportSAM from SmartcardSAM import PassportSAM
MRZ1 = "P<UTOERIKSSON<<ANNA<MARIX<<<<<<<<<<<<<<<<<<<" MRZ = raw_input("Please enter the MRZ as one string: ") #TODO: Sanity checks
MRZ2 = "L898902C<3UTO6908061F9406236ZE184226B<<<<<14"
MRZ = MRZ1 + MRZ2 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: try:
im = Image.open(picturepath) im = Image.open(picturepath)
pic_width, pic_height = im.size pic_width, pic_height = im.size
@@ -62,7 +77,7 @@ def generate_ePass():
picture = fd.read() picture = fd.read()
fd.close() fd.close()
except IOError: except IOError:
print "Could not find picture %s" % picturepath print "Failed to open file: " + picturepath
pic_width = 0 pic_width = 0
pic_height = 0 pic_height = 0
picture = None picture = None
@@ -99,21 +114,40 @@ def generate_ePass():
fid = df.select("fid",0x0102) fid = df.select("fid",0x0102)
fid.writebinary([0],[DG2]) fid.writebinary([0],[DG2])
sam = PassportSAM(mf) self.mf = mf
return mf, sam self.sam = PassportSAM(self.mf)
def generate_cryptoflex(): def __generate_cryptoflex(self):
from SmartcardFilesystem import CryptoflexMF
from SmartcardSAM import CryptoflexSAM from SmartcardSAM import CryptoflexSAM
mf = CryptoflexMF() self.mf = CryptoflexMF()
mf.append(TransparentStructureEF(parent=mf, fid=0x0002, filedescriptor=0x01, self.mf.append(TransparentStructureEF(parent=self.mf, fid=0x0002, filedescriptor=0x01,
data="\x00\x00\x00\x01\x00\x01\x00\x00")) #EF.ICCSN 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 from CryptoUtils import read_protected_string
try: try:
@@ -126,20 +160,13 @@ def loadCard(filename, password=None):
serializedMF = read_protected_string(db["mf"], password) serializedMF = read_protected_string(db["mf"], password)
serializedSAM = read_protected_string(db["sam"], password) serializedSAM = read_protected_string(db["sam"], password)
SAM = loads(serializedSAM) self.sam = loads(serializedSAM)
MF = loads(serializedMF) self.mf = loads(serializedMF)
#self.type = db["type"] self.type = db["type"]
return SAM, MF def saveCard(self, filename, password=None):
def saveCard(mf, sam, filename, password=None):
from CryptoUtils import protect_string 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: if password is None:
passwd1 = getpass.getpass("Please enter a password.") passwd1 = getpass.getpass("Please enter a password.")
passwd2 = getpass.getpass("Please retype your password.") passwd2 = getpass.getpass("Please retype your password.")
@@ -148,8 +175,11 @@ def saveCard(mf, sam, filename, password=None):
else: else:
password = passwd1 password = passwd1
mf_string = dumps(mf) if self.mf == None or self.sam == None: #TODO: Sanity checks
sam_string = dumps(sam) 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) protectedMF = protect_string(mf_string, password)
protectedSAM = protect_string(sam_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 = anydbm.open(filename, 'c')
db["mf"] = protectedMF db["mf"] = protectedMF
db["sam"] = protectedSAM db["sam"] = protectedSAM
#db["type"] = self.type db["type"] = self.type
db["version"] = "0.1"
db.close() db.close()
except anydbm.error: except anydbm.error:
print "Failed to write data to disk" 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" print "You have to provide a filename using the -f option"
sys.exit() sys.exit()
if options.type == 'iso7816': generator = CardGenerator(options.type)
mf, sam = generate_iso_card() generator.generateCard()
elif options.type == 'ePass': generator.saveCard(options.filename)
mf, sam = generate_ePass()
elif options.type == 'cryptoflex':
mf, sam = generate_cryptoflex()
saveCard(mf, sam, options.filename)

View File

@@ -21,21 +21,21 @@ from TLVutils import *
from SWutils import SwError, SW from SWutils import SwError, SW
from SmartcardFilesystem import prettyprint_anything, MF, DF, CryptoflexMF, TransparentStructureEF from SmartcardFilesystem import prettyprint_anything, MF, DF, CryptoflexMF, TransparentStructureEF
from utils import C_APDU, R_APDU, hexdump, inttostring 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 from pickle import dumps, loads
import socket, struct, sys, signal, atexit, traceback import socket, struct, sys, signal, atexit, traceback
import struct import struct, getpass, anydbm
import getpass
import shelve, anydbm
class SmartcardOS(object): # {{{ class SmartcardOS(object): # {{{
def __init__(self, mf=None, sam=None, ins2handler=None, maxle=MAX_SHORT_LE): def __init__(self, mf, sam, ins2handler=None, maxle=MAX_SHORT_LE):
from CardGenerator import generate_iso_card
self.mf = mf self.mf = mf
self.SAM = sam self.SAM = sam
if self.mf == None and self.SAM == None: #if self.mf == None and self.SAM == None:
self.mf, self.SAM = generate_iso_card() # self.mf, self.SAM = generate_iso_card()
if not ins2handler: if not ins2handler:
self.ins2handler = { self.ins2handler = {
@@ -295,39 +295,8 @@ class SmartcardOS(object): # {{{
return answer 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): # {{{ class CryptoflexOS(SmartcardOS): # {{{
def __init__(self, mf=None, sam=None, ins2handler=None, maxle=MAX_SHORT_LE): def __init__(self, mf, sam, 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)
SmartcardOS.__init__(self, mf, sam, ins2handler, maxle) SmartcardOS.__init__(self, mf, sam, ins2handler, maxle)
self.atr = '\x3B\xE2\x00\x00\x40\x20\x49\x06' 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): def __init__(self, filename, type, lenlen=3, host="localhost", port=35963):
from os.path import exists from os.path import exists
from CardGenerator import loadCard
self.filename = None self.filename = None
SAM = None self.cardGenerator = CardGenerator.CardGenerator(type)
MF = None
#If a filename is specified, try to load the card from disk #If a filename is specified, try to load the card from disk
if filename == None: if filename == None:
@@ -399,16 +366,15 @@ class VirtualICC(object): # {{{
else: else:
self.filename = filename self.filename = filename
if exists(filename): if exists(filename):
print "Found existing card " + filename + ". Will try to open it" self.cardGenerator.loadCard(self.filename)
SAM, MF = loadCard(filename)
else: 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 #Generate an OS object of the correct type
if type == "iso7816": if type == "iso7816" or type == "ePass":
self.os = SmartcardOS(MF, SAM) self.os = SmartcardOS(MF, SAM)
elif type == "ePass":
self.os = PassportOS(MF, SAM)
elif type == "cryptoflex": elif type == "cryptoflex":
self.os = CryptoflexOS(MF, SAM) self.os = CryptoflexOS(MF, SAM)
else: else:
@@ -431,9 +397,10 @@ class VirtualICC(object): # {{{
#atexit.register(saveCard) #atexit.register(saveCard)
def signalHandler(self, signal=None, frame=None): def signalHandler(self, signal=None, frame=None):
from CardGenerator import saveCard
self.sock.close() 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() sys.exit()
@staticmethod @staticmethod

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB