Code cleanup

git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@505 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
oepen
2011-08-23 13:18:52 +00:00
parent b8306d2a40
commit 63f3f3809c

View File

@@ -21,7 +21,7 @@ from virtualsmartcard.ConstantDefinitions import MAX_EXTENDED_LE, MAX_SHORT_LE
from virtualsmartcard.SWutils import SwError, SW from virtualsmartcard.SWutils import SwError, SW
from virtualsmartcard.SmartcardFilesystem import make_property from virtualsmartcard.SmartcardFilesystem import make_property
from virtualsmartcard.utils import C_APDU, R_APDU, hexdump, inttostring from virtualsmartcard.utils import C_APDU, R_APDU, hexdump, inttostring
import CardGenerator from virtualsmartcard.CardGenerator import CardGenerator
import socket, struct, sys, signal, atexit, smartcard, logging import socket, struct, sys, signal, atexit, smartcard, logging
@@ -123,10 +123,19 @@ class Iso7816OS(SmartcardOS): # {{{
def makeATR(**args): # {{{ def makeATR(**args): # {{{
"""Calculate Answer to Reset (ATR) and returns the bitstring. """Calculate Answer to Reset (ATR) and returns the bitstring.
directConvention -- Bool. Whether to use direct convention or inverse convention. directConvention -- Bool. Whether to use direct convention or inverse
TAi, TBi, TCi -- (optional) Value between 0 and 0xff. Interface Characters (for meaning see ISO 7816-3). Note that if no transmission protocol is given, it is automatically selected with T=max{j-1|TAj in args OR TBj in args OR TCj in args}. convention.
T -- (optional) Value between 0 and 15. Transmission Protocol. Note that if T is set, TAi/TBi/TCi for i>T are omitted. TAi, TBi, TCi -- (optional) Value between 0 and 0xff. Interface
histChars -- (optional) Bitstring with 0 <= len(histChars) <= 15. Historical Characters T1 to T15 (for meaning see ISO 7816-4). Characters (for meaning see ISO 7816-3). Note that
if no transmission protocol is given, it is
automatically selected with T=max{j-1|TAj in args
OR TBj in args OR TCj in args}.
T -- (optional) Value between 0 and 15. Transmission
Protocol. Note that if T is set, TAi/TBi/TCi for
i>T are omitted.
histChars -- (optional) Bitstring with 0 <= len(histChars) <= 15.
Historical Characters T1 to T15 (for meaning see
ISO 7816-4).
T0, TDi and TCK are automatically calculated. T0, TDi and TCK are automatically calculated.
""" """
@@ -241,6 +250,12 @@ class Iso7816OS(SmartcardOS): # {{{
def execute(self, msg): def execute(self, msg):
def notImplemented(*argz, **args): def notImplemented(*argz, **args):
"""
If an application tries to use a function which is not implemented
by the currently emulated smartcard we raise an exception which
should result in an appropriate response APDU being passed to the
application.
"""
raise SwError(SW["ERR_INSNOTSUPPORTED"]) raise SwError(SW["ERR_INSNOTSUPPORTED"])
try: try:
@@ -271,7 +286,7 @@ class Iso7816OS(SmartcardOS): # {{{
if (secure_messaging == 0x00): if (secure_messaging == 0x00):
SM_STATUS = "No SM" SM_STATUS = "No SM"
elif (secure_messaging == 0x01): elif (secure_messaging == 0x01):
SM_STATUS = "Propietary SM" # Not supported ? SM_STATUS = "Proprietary SM" # Not supported ?
elif (secure_messaging == 0x02): elif (secure_messaging == 0x02):
SM_STATUS = "Standard SM" SM_STATUS = "Standard SM"
elif (secure_messaging == 0x03): elif (secure_messaging == 0x03):
@@ -279,7 +294,8 @@ class Iso7816OS(SmartcardOS): # {{{
header_authentication = 1 header_authentication = 1
#If Bit 8,7 == 01 then further industry values are used #If Bit 8,7 == 01 then further industry values are used
elif (class_byte & 0x0C == 0x0C): elif (class_byte & 0x0C == 0x0C):
#Bit 1 to 4 specify logical channel. 4 is added, value range is from four to nineteen #Bit 1 to 4 specify logical channel. 4 is added, value range is from
#four to nineteen
logical_channel = class_byte & 0x0f logical_channel = class_byte & 0x0f
logical_channel += 4 logical_channel += 4
#Bit 6 indicates secure messaging #Bit 6 indicates secure messaging
@@ -289,7 +305,7 @@ class Iso7816OS(SmartcardOS): # {{{
SM_STATUS = "No SM" SM_STATUS = "No SM"
elif (secure_messaging == 0x01): elif (secure_messaging == 0x01):
SM_STATUS = "Standard SM" SM_STATUS = "Standard SM"
#In both cases Bit 5 specifiys command chaining #In both cases Bit 5 specifies command chaining
command_chaining = class_byte >> 5 command_chaining = class_byte >> 5
command_chaining &= 0x01 command_chaining &= 0x01
#}}} #}}}
@@ -297,7 +313,7 @@ class Iso7816OS(SmartcardOS): # {{{
try: try:
if SM_STATUS == "Standard SM": if SM_STATUS == "Standard SM":
c = self.SAM.parse_SM_CAPDU(c, header_authentication) c = self.SAM.parse_SM_CAPDU(c, header_authentication)
elif SM_STATUS == "Propietary SM": elif SM_STATUS == "Proprietary SM":
raise SwError("ERR_SECMESSNOTSUPPORTED") raise SwError("ERR_SECMESSNOTSUPPORTED")
sw, result = self.ins2handler.get(c.ins, notImplemented)(c.p1, c.p2, c.data) sw, result = self.ins2handler.get(c.ins, notImplemented)(c.p1, c.p2, c.data)
if SM_STATUS == "Standard SM": if SM_STATUS == "Standard SM":
@@ -362,12 +378,20 @@ class CryptoflexOS(Iso7816OS): # {{{
# }}} # }}}
class RelayOS(SmartcardOS): # {{{ class RelayOS(SmartcardOS): # {{{
"""
This class implements relaying of a (physical) smartcard. The RelayOS
forwards the command APDUs received from the vpcd to the real smartcard via
an actual smartcard reader and sends the responses back to the vpcd.
This class can be used to implement relay or MITM attacks.
"""
def __init__(self, readernum): def __init__(self, readernum):
"""
Initialize the connection to the (physical) smartcard via a given reader
"""
readers = smartcard.System.listReaders() readers = smartcard.System.listReaders()
if len(readers) <= readernum: if len(readers) <= readernum:
logging.error("Invalid number of reader '%u' (only %u available)" logging.error("Invalid number of reader '%u' (only %u available)",
% (readernum, len(readers))) readernum, len(readers))
sys.exit() sys.exit()
# XXX this is a workaround, see on sourceforge bug #3083254 # XXX this is a workaround, see on sourceforge bug #3083254
# should better use # should better use
@@ -386,6 +410,9 @@ class RelayOS(SmartcardOS): # {{{
atexit.register(self.cleanup) atexit.register(self.cleanup)
def cleanup(self): def cleanup(self):
"""
Close the connection to the physical card
"""
try: try:
self.session.close() self.session.close()
except smartcard.Exceptions.CardConnectionException, e: except smartcard.Exceptions.CardConnectionException, e:
@@ -468,7 +495,7 @@ class VirtualICC(object): # {{{
the vpcd, which forwards it to the application. the vpcd, which forwards it to the application.
""" """
def __init__(self, filename, type, host, port, lenlen=3, readernum=None): def __init__(self, filename, card_type, host, port, lenlen=3, readernum=None):
from os.path import exists from os.path import exists
logging.basicConfig(level = logging.INFO, logging.basicConfig(level = logging.INFO,
@@ -476,7 +503,7 @@ class VirtualICC(object): # {{{
datefmt = "%d.%m.%Y %H:%M:%S") datefmt = "%d.%m.%Y %H:%M:%S")
self.filename = None self.filename = None
self.cardGenerator = CardGenerator.CardGenerator(type) self.cardGenerator = CardGenerator(card_type)
#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:
@@ -489,19 +516,19 @@ class VirtualICC(object): # {{{
MF, SAM = self.cardGenerator.getCard() MF, SAM = self.cardGenerator.getCard()
#Generate an OS object of the correct type #Generate an OS object of the correct card_type
if type == "iso7816" or type == "ePass": if card_type == "iso7816" or card_type == "ePass":
self.os = Iso7816OS(MF, SAM) self.os = Iso7816OS(MF, SAM)
elif type == "cryptoflex": elif card_type == "cryptoflex":
self.os = CryptoflexOS(MF, SAM) self.os = CryptoflexOS(MF, SAM)
elif type == "relay": elif card_type == "relay":
self.os = RelayOS(readernum) self.os = RelayOS(readernum)
else: else:
logging.warning("Unknown cardtype %s. Will use standard type (ISO 7816)", logging.warning("Unknown cardtype %s. Will use standard card_type (ISO 7816)",
type) card_type)
type = "iso7816" card_type = "iso7816"
self.os = Iso7816OS(MF, SAM) self.os = Iso7816OS(MF, SAM)
self.type = type self.type = card_type
#Connect to the VPCD #Connect to the VPCD
try: try:
@@ -509,12 +536,13 @@ class VirtualICC(object): # {{{
self.sock.settimeout(None) self.sock.settimeout(None)
except socket.error, e: except socket.error, e:
logging.error("Failed to open socket: %s", str(e)) logging.error("Failed to open socket: %s", str(e))
logging.error("Is pcscd running at %s? Is vpcd loaded? Is a firewall blocking port %u?" % (host, port)) logging.error("Is pcscd running at %s? Is vpcd loaded? Is a firewall blocking port %u?",
host, port)
sys.exit() sys.exit()
self.lenlen = lenlen self.lenlen = lenlen
logging.info("Connected to virtual PCD at %s:%u" % (host, port)) logging.info("Connected to virtual PCD at %s:%u", host, port)
signal.signal(signal.SIGINT, self.signalHandler) signal.signal(signal.SIGINT, self.signalHandler)
atexit.register(self.stop) atexit.register(self.stop)
@@ -583,11 +611,14 @@ class VirtualICC(object): # {{{
logging.warning("unknown control command") logging.warning("unknown control command")
else: else:
if size != len(msg): if size != len(msg):
logging.warning("Expected APDU of %u bytes, but received only %u" % (size, len(msg))) logging.warning("Expected %u bytes, but received only %u",
size, len(msg))
logging.info("APDU (%d Bytes):\n%s" % (len(msg), hexdump(msg, short=True))) logging.info("APDU (%d Bytes):\n%s", len(msg),
hexdump(msg, short=True))
answer = self.os.execute(msg) answer = self.os.execute(msg)
logging.info("RESP (%d Bytes):\n%s\n" % (len(answer), hexdump(answer, short=True))) logging.info("RESP (%d Bytes):\n%s\n", len(answer),
hexdump(answer, short=True))
self.__sendToVPICC(answer) self.__sendToVPICC(answer)
def stop(self): def stop(self):