Code cleanup
git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@505 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -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):
|
||||||
|
|||||||
Reference in New Issue
Block a user