Esempio n. 1
0
 def test_load_card_from_file(self):
     self.card_generator.generateCard()
     self.card_generator.saveCard(self.filename)
     local_generator = CardGenerator(self.card_type)
     local_generator.password = self.card_generator.password
     local_generator.loadCard(self.filename)
     mf, sam = local_generator.getCard()
     self.assertIsNotNone(mf)
     self.assertIsNotNone(sam)
     os.unlink(self.filename)
Esempio n. 2
0
 def test_load_card_from_file(self):
     self.card_generator.generateCard()
     self.card_generator.saveCard(self.filename)
     local_generator= CardGenerator(self.card_type)
     local_generator.password = self.card_generator.password
     local_generator.loadCard(self.filename)
     mf, sam = local_generator.getCard()
     self.assertIsNotNone(mf)
     self.assertIsNotNone(sam)
     os.unlink(self.filename)
Esempio n. 3
0
class ISO7816GeneratorTest(unittest.TestCase):

    card_type = 'iso7816'

    def setUp(self):
        self.filename = tempfile.mktemp()
        self.card_generator = CardGenerator(self.card_type)
        self.card_generator.password = "******"

    def test_card_creation(self):
        self.card_generator.generateCard()
        self.card_generator.saveCard(self.filename)
        mf, sam = self.card_generator.getCard()
        self.assertIsNotNone(mf)
        self.assertIsNotNone(sam)
        os.unlink(self.filename)

    def test_load_card_from_file(self):
        self.card_generator.generateCard()
        self.card_generator.saveCard(self.filename)
        local_generator = CardGenerator(self.card_type)
        local_generator.password = self.card_generator.password
        local_generator.loadCard(self.filename)
        mf, sam = local_generator.getCard()
        self.assertIsNotNone(mf)
        self.assertIsNotNone(sam)
        os.unlink(self.filename)

    def test_load_nonexistent_file(self):
        with self.assertRaises(anydbm.error):
            self.card_generator.loadCard(self.filename)

    def test_get_and_set_card(self):
        self.card_generator.generateCard()
        mf, sam = self.card_generator.getCard()
        local_generator = CardGenerator(self.card_type)
        local_generator.setCard(mf, sam)
Esempio n. 4
0
class ISO7816GeneratorTest(unittest.TestCase):

    card_type = 'iso7816'

    def setUp(self):
        self.filename = tempfile.mktemp()
        self.card_generator = CardGenerator(self.card_type)
        self.card_generator.password = "******"

    def test_card_creation(self):
        self.card_generator.generateCard()
        self.card_generator.saveCard(self.filename)
        mf, sam = self.card_generator.getCard()
        self.assertIsNotNone(mf)
        self.assertIsNotNone(sam)
        os.unlink(self.filename)

    def test_load_card_from_file(self):
        self.card_generator.generateCard()
        self.card_generator.saveCard(self.filename)
        local_generator= CardGenerator(self.card_type)
        local_generator.password = self.card_generator.password
        local_generator.loadCard(self.filename)
        mf, sam = local_generator.getCard()
        self.assertIsNotNone(mf)
        self.assertIsNotNone(sam)
        os.unlink(self.filename)

    def test_load_nonexistent_file(self):
        with self.assertRaises(anydbm.error):
            self.card_generator.loadCard(self.filename)

    def test_get_and_set_card(self):
        self.card_generator.generateCard()
        mf, sam = self.card_generator.getCard()
        local_generator= CardGenerator(self.card_type)
        local_generator.setCard(mf, sam)
Esempio n. 5
0
class VirtualICC(object): 
    """
    This class is responsible for maintaining the communication of the virtual
    PCD and the emulated smartcard. vpicc and vpcd communicate via a socket.
    The vpcd sends command APDUs (which it receives from an application) to the
    vicc. The vicc passes these CAPDUs on to an emulated smartcard, which
    produces a response APDU. This RAPDU is then passed back by the vicc to
    the vpcd, which forwards it to the application.
    """ 
    
    def __init__(self, filename, card_type, host, port, lenlen=3, readernum=None, ef_cardsecurity=None, ef_cardaccess=None, ca_key=None, cvca=None, disable_checks=False):
        from os.path import exists
        
        logging.basicConfig(level = logging.INFO, 
                            format = "%(asctime)s  [%(levelname)s] %(message)s", 
                            datefmt = "%d.%m.%Y %H:%M:%S") 
        
        self.filename = None
        self.cardGenerator = CardGenerator(card_type)
        
        #If a filename is specified, try to load the card from disk      
        if filename != None:
            self.filename = filename
            if exists(filename):
                self.cardGenerator.loadCard(self.filename)
            else:
                logging.info("Creating new card which will be saved in %s.",
                              self.filename)
        
        MF, SAM = self.cardGenerator.getCard()
        
        #Generate an OS object of the correct card_type
        if card_type == "iso7816" or card_type == "ePass":
            self.os = Iso7816OS(MF, SAM)
        elif card_type == "nPA":
            self.os = NPAOS(MF, SAM, ef_cardsecurity=ef_cardsecurity, ef_cardaccess=ef_cardaccess, ca_key=ca_key, cvca=cvca, disable_checks=disable_checks)
        elif card_type == "cryptoflex":
            self.os = CryptoflexOS(MF, SAM)
        elif card_type == "relay":
            self.os = RelayOS(readernum)
        else:
            logging.warning("Unknown cardtype %s. Will use standard card_type (ISO 7816)",
                            card_type)
            card_type = "iso7816"
            self.os = Iso7816OS(MF, SAM)
        self.type = card_type
            
        #Connect to the VPCD
        try:
            self.sock = self.connectToPort(host, port)
            self.sock.settimeout(None)
        except socket.error as 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)
            sys.exit()
                       
        self.lenlen = lenlen

        logging.info("Connected to virtual PCD at %s:%u", host, port)

        signal.signal(signal.SIGINT, self.signalHandler)
        atexit.register(self.stop)
    
    def signalHandler(self, sig=None, frame=None):
        """Basically this signal handler just surpresses a traceback from being
           printed when the user presses crtl-c"""
        sys.exit()

    @staticmethod
    def connectToPort(host, port):
        """
        Open a connection to a given host on a given port.
        """
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((host, port))
        return sock

    def __sendToVPICC(self, msg):
        """ Send a message to the vpcd """
        #size = inttostring(len(msg), self.lenlen)
        self.sock.send(struct.pack('!H', len(msg)) + msg)

    def __recvFromVPICC(self):
        """ Receive a message from the vpcd """
        # receive message size
        sizestr = self.sock.recv(_Csizeof_short)
        if len(sizestr) == 0:
            logging.info("Virtual PCD shut down")
            sys.exit()
        size = struct.unpack('!H', sizestr)[0]

        # receive and return message
        if size:
            msg = self.sock.recv(size)
            if len(msg) == 0:
                logging.info("Virtual PCD shut down")
        else:
            msg = None

        return size, msg

    def run(self):
        """
        Main loop of the vpicc. Receives command APDUs via a socket from the
        vpcd, dispatches them to the emulated smartcard and sends the resulting
        respsonse APDU back to the vpcd.
        """
        while True :
            (size, msg) = self.__recvFromVPICC()
            if not size:
                logging.warning("Error in communication protocol (missing size parameter)")
            elif size == VPCD_CTRL_LEN:
                if msg == chr(VPCD_CTRL_OFF):
                    logging.info("Power Down")
                    self.os.powerDown()
                elif msg == chr(VPCD_CTRL_ON):
                    logging.info("Power Up")
                    self.os.powerUp()
                elif msg == chr(VPCD_CTRL_RESET):
                    logging.info("Reset")
                    self.os.reset()
                elif msg == chr(VPCD_CTRL_ATR):
                    self.__sendToVPICC(self.os.getATR())
                else:
                    logging.warning("unknown control command")
            else:
                if size != len(msg):
                    logging.warning("Expected %u bytes, but received only %u",
                                    size, len(msg))

                answer = self.os.execute(msg)
                logging.info("Response APDU (%d Bytes):\n%s\n", len(answer),
                             hexdump(answer))
                self.__sendToVPICC(answer)

    def stop(self):
        self.sock.close()
        if self.filename != None:
            self.cardGenerator.setCard(self.os.mf, self.os.SAM)
            self.cardGenerator.saveCard(self.filename)
Esempio n. 6
0
class VirtualICC(object): 
    """
    This class is responsible for maintaining the communication of the virtual
    PCD and the emulated smartcard. vpicc and vpcd communicate via a socket.
    The vpcd sends command APDUs (which it receives from an application) to the
    vicc. The vicc passes these CAPDUs on to an emulated smartcard, which
    produces a response APDU. This RAPDU is then passed back by the vicc to
    the vpcd, which forwards it to the application.
    """ 
    
    def __init__(self, filename, datasetfile, card_type, host, port, readernum=None, ef_cardsecurity=None, ef_cardaccess=None, ca_key=None, cvca=None, disable_checks=False, esign_key=None, esign_ca_cert=None, esign_cert=None, logginglevel=logging.INFO):
        from os.path import exists
        
        logging.basicConfig(level = logginglevel, 
                            format = "%(asctime)s  [%(levelname)s] %(message)s", 
                            datefmt = "%d.%m.%Y %H:%M:%S") 
        
        self.filename = None
        self.cardGenerator = CardGenerator(card_type)
        
        #If a filename is specified, try to load the card from disk      
        if filename != None:
            self.filename = filename
            if exists(filename):
                self.cardGenerator.loadCard(self.filename)
            else:
                logging.info("Creating new card which will be saved in %s.",
                              self.filename)

        #If a dataset file is specified, read the card's data groups from disk
        if datasetfile != None:
            if exists(datasetfile):
                logging.info("Reading Data Groups from file %s.",
                        datasetfile)
                self.cardGenerator.readDatagroups(datasetfile)

        MF, SAM = self.cardGenerator.getCard()
        
        #Generate an OS object of the correct card_type
        if card_type == "iso7816" or card_type == "ePass":
            self.os = Iso7816OS(MF, SAM)
        elif card_type == "nPA":
            from virtualsmartcard.cards.nPA import NPAOS
            self.os = NPAOS(MF, SAM, ef_cardsecurity=ef_cardsecurity, ef_cardaccess=ef_cardaccess, ca_key=ca_key, cvca=cvca, disable_checks=disable_checks, esign_key=esign_key, esign_ca_cert=esign_ca_cert, esign_cert=esign_cert)
        elif card_type == "cryptoflex":
            from virtualsmartcard.cards.cryptoflex import CryptoflexOS
            self.os = CryptoflexOS(MF, SAM)
        elif card_type == "relay":
            from virtualsmartcard.cards.Relay import RelayOS
            self.os = RelayOS(readernum)
        elif card_type == "handler_test":
            from virtualsmartcard.cards.HandlerTest import HandlerTestOS
            self.os = HandlerTestOS()
        else:
            logging.warning("Unknown cardtype %s. Will use standard card_type (ISO 7816)",
                            card_type)
            card_type = "iso7816"
            self.os = Iso7816OS(MF, SAM)
        self.type = card_type
            
        #Connect to the VPCD
        self.host = host
        self.port = port
        if host:
            # use normal connection mode
            try:
                self.sock = self.connectToPort(host, port)
                self.sock.settimeout(None)
                self.server_sock = None
            except socket.error as 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)
                sys.exit()
        else:
            # use reversed connection mode
            try:
                (self.sock, self.server_sock, host) = self.openPort(port)
                self.sock.settimeout(None)
            except socket.error as e:
                logging.error("Failed to open socket: %s", str(e))
                logging.error("Is pcscd running? Is vpcd loaded and in reversed connection mode? Is a firewall blocking port %u?",
                              port)
                sys.exit()

        logging.info("Connected to virtual PCD at %s:%u", host, port)

        signal.signal(signal.SIGINT, self.signalHandler)
        atexit.register(self.stop)
    
    def signalHandler(self, sig=None, frame=None):
        """Basically this signal handler just surpresses a traceback from being
           printed when the user presses crtl-c"""
        sys.exit()

    @staticmethod
    def connectToPort(host, port):
        """
        Open a connection to a given host on a given port.
        """
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((host, port))
        return sock

    @staticmethod
    def openPort(port):
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_socket.bind(('', port))
        server_socket.listen(0)
        logging.info("Waiting for vpcd on port " + str(port))
        (client_socket, address) = server_socket.accept()
        return (client_socket, server_socket, address[0])

    def __sendToVPICC(self, msg):
        """ Send a message to the vpcd """
        self.sock.sendall(struct.pack('!H', len(msg)) + msg)

    def __recvFromVPICC(self):
        """ Receive a message from the vpcd """
        # receive message size
        sizestr = self.sock.recv(_Csizeof_short)
        if len(sizestr) == 0:
            logging.info("Virtual PCD shut down")
            raise socket.error
        size = struct.unpack('!H', sizestr)[0]

        # receive and return message
        if size:
            msg = self.sock.recv(size)
            if len(msg) == 0:
                logging.info("Virtual PCD shut down")
                raise socket.error
        else:
            msg = None

        return size, msg

    def run(self):
        """
        Main loop of the vpicc. Receives command APDUs via a socket from the
        vpcd, dispatches them to the emulated smartcard and sends the resulting
        respsonse APDU back to the vpcd.
        """
        while True :
            try:
                (size, msg) = self.__recvFromVPICC()
            except socket.error as e:
                if not self.host:
                    logging.info("Waiting for vpcd on port " + str(self.port))
                    (self.sock, address) = self.server_sock.accept()
                    continue
                else:
                    sys.exit()

            if not size:
                logging.warning("Error in communication protocol (missing size parameter)")
            elif size == VPCD_CTRL_LEN:
                if msg == chr(VPCD_CTRL_OFF):
                    logging.info("Power Down")
                    self.os.powerDown()
                elif msg == chr(VPCD_CTRL_ON):
                    logging.info("Power Up")
                    self.os.powerUp()
                elif msg == chr(VPCD_CTRL_RESET):
                    logging.info("Reset")
                    self.os.reset()
                elif msg == chr(VPCD_CTRL_ATR):
                    self.__sendToVPICC(self.os.getATR())
                else:
                    logging.warning("unknown control command")
            else:
                if size != len(msg):
                    logging.warning("Expected %u bytes, but received only %u",
                                    size, len(msg))

                answer = self.os.execute(msg)
                logging.info("Response APDU (%d Bytes):\n%s\n", len(answer),
                             hexdump(answer))
                self.__sendToVPICC(answer)

    def stop(self):
        self.sock.close()
        if self.server_sock:
            self.server_sock.close()
        if self.filename != None:
            self.cardGenerator.setCard(self.os.mf, self.os.SAM)
            self.cardGenerator.saveCard(self.filename)
Esempio n. 7
0
class VirtualICC(object):
    """
    This class is responsible for maintaining the communication of the virtual
    PCD and the emulated smartcard. vpicc and vpcd communicate via a socket.
    The vpcd sends command APDUs (which it receives from an application) to the
    vicc. The vicc passes these CAPDUs on to an emulated smartcard, which
    produces a response APDU. This RAPDU is then passed back by the vicc to
    the vpcd, which forwards it to the application.
    """

    def __init__(self, filename, datasetfile, card_type, host, port,
                 readernum=None, ef_cardsecurity=None, ef_cardaccess=None,
                 ca_key=None, cvca=None, disable_checks=False, esign_key=None,
                 esign_ca_cert=None, esign_cert=None,
                 logginglevel=logging.INFO):
        from os.path import exists

        logging.basicConfig(level=logginglevel,
                            format="%(asctime)s  [%(levelname)s] %(message)s",
                            datefmt="%d.%m.%Y %H:%M:%S")

        self.filename = None
        self.cardGenerator = CardGenerator(card_type)

        # If a filename is specified, try to load the card from disk
        if filename is not None:
            self.filename = filename
            if exists(filename):
                self.cardGenerator.loadCard(self.filename)
            else:
                logging.info("Creating new card which will be saved in %s.",
                             self.filename)

        # If a dataset file is specified, read the card's data groups from disk
        if datasetfile is not None:
            if exists(datasetfile):
                logging.info("Reading Data Groups from file %s.",
                             datasetfile)
                self.cardGenerator.readDatagroups(datasetfile)

        MF, SAM = self.cardGenerator.getCard()

        # Generate an OS object of the correct card_type
        if card_type == "iso7816" or card_type == "ePass":
            self.os = Iso7816OS(MF, SAM)
        elif card_type == "nPA":
            from virtualsmartcard.cards.nPA import NPAOS
            self.os = NPAOS(MF, SAM, ef_cardsecurity=ef_cardsecurity,
                            ef_cardaccess=ef_cardaccess, ca_key=ca_key,
                            cvca=cvca, disable_checks=disable_checks,
                            esign_key=esign_key, esign_ca_cert=esign_ca_cert,
                            esign_cert=esign_cert)
        elif card_type == "cryptoflex":
            from virtualsmartcard.cards.cryptoflex import CryptoflexOS
            self.os = CryptoflexOS(MF, SAM)
        elif card_type == "relay":
            from virtualsmartcard.cards.Relay import RelayOS
            self.os = RelayOS(readernum)
        elif card_type == "handler_test":
            from virtualsmartcard.cards.HandlerTest import HandlerTestOS
            self.os = HandlerTestOS()
        else:
            logging.warning("Unknown cardtype %s. Will use standard card_type \
                            (ISO 7816)", card_type)
            card_type = "iso7816"
            self.os = Iso7816OS(MF, SAM)
        self.type = card_type

        # Connect to the VPCD
        self.host = host
        self.port = port
        if host:
            # use normal connection mode
            try:
                self.sock = self.connectToPort(host, port)
                self.sock.settimeout(None)
                self.server_sock = None
            except socket.error as 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)
                sys.exit()
        else:
            # use reversed connection mode
            try:
                local_ip = [(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]
                custom_url = 'vicc://%s:%d' % (local_ip, port)
                print('VICC hostname:  %s' % local_ip);
                print('VICC port:      %d' % port)
                print('On your NFC phone with the Android Smart Card Emulator app scan this code:')
                try:
                    import qrcode
                    qr = qrcode.QRCode()
                    qr.add_data(custom_url)
                    qr.print_ascii()
                except ImportError:
                    print('https://api.qrserver.com/v1/create-qr-code/?data=%s' % custom_url)
                (self.sock, self.server_sock, host) = self.openPort(port)
                self.sock.settimeout(None)
            except socket.error as e:
                logging.error("Failed to open socket: %s", str(e))
                logging.error("Is pcscd running? Is vpcd loaded and in \
                              reversed connection mode? Is a firewall \
                              blocking port %u?", port)
                sys.exit()

        logging.info("Connected to virtual PCD at %s:%u", host, port)

        signal.signal(signal.SIGINT, self.signalHandler)
        atexit.register(self.stop)

    def signalHandler(self, sig=None, frame=None):
        """Basically this signal handler just surpresses a traceback from being
           printed when the user presses crtl-c"""
        sys.exit()

    @staticmethod
    def connectToPort(host, port):
        """
        Open a connection to a given host on a given port.
        """
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((host, port))
        return sock

    @staticmethod
    def openPort(port):
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_socket.bind(('', port))
        server_socket.listen(0)
        logging.info("Waiting for vpcd on port " + str(port))
        (client_socket, address) = server_socket.accept()
        return (client_socket, server_socket, address[0])

    def __sendToVPICC(self, msg):
        """ Send a message to the vpcd """
        self.sock.sendall(struct.pack('!H', len(msg)) + msg)

    def __recvFromVPICC(self):
        """ Receive a message from the vpcd """
        # receive message size
        sizestr = self.sock.recv(_Csizeof_short)
        if len(sizestr) == 0:
            logging.info("Virtual PCD shut down")
            raise socket.error
        size = struct.unpack('!H', sizestr)[0]

        # receive and return message
        if size:
            msg = self.sock.recv(size)
            if len(msg) == 0:
                logging.info("Virtual PCD shut down")
                raise socket.error
        else:
            msg = None

        return size, msg

    def run(self):
        """
        Main loop of the vpicc. Receives command APDUs via a socket from the
        vpcd, dispatches them to the emulated smartcard and sends the resulting
        respsonse APDU back to the vpcd.
        """
        while True:
            try:
                (size, msg) = self.__recvFromVPICC()
            except socket.error as e:
                if not self.host:
                    logging.info("Waiting for vpcd on port " + str(self.port))
                    (self.sock, address) = self.server_sock.accept()
                    continue
                else:
                    sys.exit()

            if not size:
                logging.warning("Error in communication protocol (missing \
                                size parameter)")
            elif size == VPCD_CTRL_LEN:
                if msg == chr(VPCD_CTRL_OFF):
                    logging.info("Power Down")
                    self.os.powerDown()
                elif msg == chr(VPCD_CTRL_ON):
                    logging.info("Power Up")
                    self.os.powerUp()
                elif msg == chr(VPCD_CTRL_RESET):
                    logging.info("Reset")
                    self.os.reset()
                elif msg == chr(VPCD_CTRL_ATR):
                    self.__sendToVPICC(self.os.getATR())
                else:
                    logging.warning("unknown control command")
            else:
                if size != len(msg):
                    logging.warning("Expected %u bytes, but received only %u",
                                    size, len(msg))

                answer = self.os.execute(msg)
                logging.info("Response APDU (%d Bytes):\n%s\n", len(answer),
                             hexdump(answer))
                self.__sendToVPICC(answer)

    def stop(self):
        self.sock.close()
        if self.server_sock:
            self.server_sock.close()
        if self.filename is not None:
            self.cardGenerator.setCard(self.os.mf, self.os.SAM)
            self.cardGenerator.saveCard(self.filename)