moved RelayOS into separate file

This commit is contained in:
Frank Morgner
2015-05-18 17:52:36 +02:00
parent 3f74291dc2
commit 3277da7824
3 changed files with 129 additions and 106 deletions

View File

@@ -23,6 +23,7 @@ vpicc_PYTHON = virtualsmartcard/CardGenerator.py \
vpicccards_PYTHON = virtualsmartcard/cards/__init__.py \
virtualsmartcard/cards/ePass.py \
virtualsmartcard/cards/nPA.py \
virtualsmartcard/cards/Relay.py \
virtualsmartcard/cards/cryptoflex.py
do_subst = $(SED) \

View File

@@ -23,7 +23,7 @@ from virtualsmartcard.SmartcardFilesystem import make_property
from virtualsmartcard.utils import C_APDU, R_APDU, hexdump, inttostring
from virtualsmartcard.CardGenerator import CardGenerator
import socket, struct, sys, signal, atexit, smartcard, logging
import socket, struct, sys, signal, atexit, logging
class SmartcardOS(object):
@@ -397,111 +397,6 @@ class CryptoflexOS(Iso7816OS):
return r
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 smart card reader and sends the responses back to the vpcd.
This class can be used to implement relay or MitM attacks.
"""
def __init__(self, readernum):
"""
Initialize the connection to the (physical) smart card via a given reader
"""
# See which readers are available
readers = smartcard.System.listReaders()
if len(readers) <= readernum:
logging.error("Invalid number of reader '%u' (only %u available)",
readernum, len(readers))
sys.exit()
# Connect to the reader and its card
# XXX this is a workaround, see on sourceforge bug #3083254
# should better use
# self.reader = smartcard.System.readers()[readernum]
self.reader = readers[readernum]
try:
self.session = smartcard.Session(self.reader)
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error connecting to card: %s", e.message)
sys.exit()
logging.info("Connected to card in '%s'", self.reader)
atexit.register(self.cleanup)
def cleanup(self):
"""
Close the connection to the physical card
"""
try:
self.session.close()
except smartcard.Exceptions.CardConnectionException as e:
logging.warning("Error disconnecting from card: %s", e.message)
def getATR(self):
# when powerDown has been called, fetching the ATR will throw an error.
# In this case we must try to reconnect (and then get the ATR).
try:
atr = self.session.getATR()
except smartcard.Exceptions.CardConnectionException as e:
try:
# Try to reconnect to the card
self.session.close()
self.session = smartcard.Session(self.reader)
atr = self.session.getATR()
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error getting ATR: %s", e.message)
sys.exit()
return "".join([chr(b) for b in atr])
def powerUp(self):
# When powerUp is called multiple times the session is valid (and the
# card is implicitly powered) we can check for an ATR. But when
# powerDown has been called, the session gets lost. In this case we
# must try to reconnect (and power the card).
try:
self.session.getATR()
except smartcard.Exceptions.CardConnectionException as e:
try:
self.session = smartcard.Session(self.reader)
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error connecting to card: %s", e.message)
sys.exit()
def powerDown(self):
# There is no power down in the session context so we simply
# disconnect, which should implicitly power down the card.
try:
self.session.close()
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error disconnecting from card: %s", str(e))
sys.exit()
def execute(self, msg):
# sendCommandAPDU() expects a list of APDU bytes
apdu = map(ord, msg)
try:
rapdu, sw1, sw2 = self.session.sendCommandAPDU(apdu)
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error transmitting APDU: %s", str(e))
sys.exit()
# XXX this is a workaround, see on sourceforge bug #3083586
# should better use
# rapdu = rapdu + [sw1, sw2]
if rapdu[-2:] == [sw1, sw2]:
pass
else:
rapdu = rapdu + [sw1, sw2]
# return the response APDU as string
return "".join([chr(b) for b in rapdu])
class NPAOS(Iso7816OS):
def __init__(self, mf, sam, ins2handler=None, maxle=MAX_EXTENDED_LE, ef_cardsecurity=None, ef_cardaccess=None, ca_key=None, cvca=None, disable_checks=False, esign_key=None, esign_ca_cert=None, esign_cert=None):
Iso7816OS.__init__(self, mf, sam, ins2handler, maxle)
@@ -685,6 +580,7 @@ class VirtualICC(object):
elif card_type == "cryptoflex":
self.os = CryptoflexOS(MF, SAM)
elif card_type == "relay":
from virtualsmartcard.cards.Relay import RelayOS
self.os = RelayOS(readernum)
elif card_type == "handler_test":
self.os = HandlerTestOS()

View File

@@ -0,0 +1,126 @@
#
# Copyright (C) 2015 Frank Morgner
#
# This file is part of virtualsmartcard.
#
# virtualsmartcard is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# virtualsmartcard is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# virtualsmartcard. If not, see <http://www.gnu.org/licenses/>.
#
from virtualsmartcard.VirtualSmartcard import SmartcardOS
import smartcard, logging
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 smart card reader and sends the responses back to the vpcd.
This class can be used to implement relay or MitM attacks.
"""
def __init__(self, readernum):
"""
Initialize the connection to the (physical) smart card via a given reader
"""
# See which readers are available
readers = smartcard.System.listReaders()
if len(readers) <= readernum:
logging.error("Invalid number of reader '%u' (only %u available)",
readernum, len(readers))
sys.exit()
# Connect to the reader and its card
# XXX this is a workaround, see on sourceforge bug #3083254
# should better use
# self.reader = smartcard.System.readers()[readernum]
self.reader = readers[readernum]
try:
self.session = smartcard.Session(self.reader)
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error connecting to card: %s", e.message)
sys.exit()
logging.info("Connected to card in '%s'", self.reader)
atexit.register(self.cleanup)
def cleanup(self):
"""
Close the connection to the physical card
"""
try:
self.session.close()
except smartcard.Exceptions.CardConnectionException as e:
logging.warning("Error disconnecting from card: %s", e.message)
def getATR(self):
# when powerDown has been called, fetching the ATR will throw an error.
# In this case we must try to reconnect (and then get the ATR).
try:
atr = self.session.getATR()
except smartcard.Exceptions.CardConnectionException as e:
try:
# Try to reconnect to the card
self.session.close()
self.session = smartcard.Session(self.reader)
atr = self.session.getATR()
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error getting ATR: %s", e.message)
sys.exit()
return "".join([chr(b) for b in atr])
def powerUp(self):
# When powerUp is called multiple times the session is valid (and the
# card is implicitly powered) we can check for an ATR. But when
# powerDown has been called, the session gets lost. In this case we
# must try to reconnect (and power the card).
try:
self.session.getATR()
except smartcard.Exceptions.CardConnectionException as e:
try:
self.session = smartcard.Session(self.reader)
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error connecting to card: %s", e.message)
sys.exit()
def powerDown(self):
# There is no power down in the session context so we simply
# disconnect, which should implicitly power down the card.
try:
self.session.close()
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error disconnecting from card: %s", str(e))
sys.exit()
def execute(self, msg):
# sendCommandAPDU() expects a list of APDU bytes
apdu = map(ord, msg)
try:
rapdu, sw1, sw2 = self.session.sendCommandAPDU(apdu)
except smartcard.Exceptions.CardConnectionException as e:
logging.error("Error transmitting APDU: %s", str(e))
sys.exit()
# XXX this is a workaround, see on sourceforge bug #3083586
# should better use
# rapdu = rapdu + [sw1, sw2]
if rapdu[-2:] == [sw1, sw2]:
pass
else:
rapdu = rapdu + [sw1, sw2]
# return the response APDU as string
return "".join([chr(b) for b in rapdu])