class OpenADCInterface_Serial(Parameterized, Plugin):
    _name = "Serial Port (LX9)"

    def __init__(self, parentParam, oadcInstance):
        self.portName = ''
        self.ser = None

        self.params = Parameter(name=self.getName(), type='group')
        self.params.addChildren([
            {'name':'Refresh List', 'type':'action', 'action':lambda _: self.serialRefresh()},
            {'name':'Selected Port', 'type':'list', 'values':[''], 'get':self.getPortName, 'set':self.setPortName},
        ])

        if (openadc_qt is None) or (serial is None):
            raise ImportError("Needed imports for serial missing")
        else:
            self.scope = oadcInstance

    def getPortName(self):
        return self.portName

    @setupSetParam("Selected Port")
    def setPortName(self, snum):
        self.portName = snum

    def __del__(self):
        if self.ser != None:
            self.ser.close()

    def con(self):
        if self.ser == None:
            self.ser = serial.Serial()
            self.ser.port     = self.portName
            self.ser.baudrate = 512000
            self.ser.timeout  = 2     # 2 second timeout

            attempts = 4
            while attempts > 0:
                try:
                    self.ser.open()
                    attempts = 0
                except serial.SerialException as e:
                    attempts = attempts - 1
                    self.ser = None
                    if attempts == 0:
                        raise IOError("Could not open %s" % self.ser.name)

        try:
            self.scope.con(self.ser)
            print("OpenADC Found, Connecting")
        except IOError as e:
            exctype, value = sys.exc_info()[:2]
            raise IOError("OpenADC Error (Serial Port): %s" % (str(exctype) + str(value)))

    def dis(self):
        if self.ser != None:
            self.ser.close()
            self.ser = None

    def serialRefresh(self):
        serialnames = scan.scan()
        if serialnames == None or len(serialnames) == 0:
            serialnames = [" "]

        p = self.params.getChild('Selected Port')
        p.setLimits(serialnames)
        p.setValue(serialnames[0])

    def getTextName(self):
        try:
            return self.ser.name
        except:
            return "None?"
Beispiel #2
0
class CWCoreAPI(Parameterized):
    """
    ChipWisperer API Class.
    Provides access to the most important parts of the tool.
    It has a singleton method called CWCoreAPI.getInstance() that returns a reference to the API instance.
    """

    __name__ = "ChipWhisperer"
    __organization__ = "NewAE Technology Inc."
    __version__ = "V3.1.9"
    _name = 'Generic Settings'
    instance = None

    def __init__(self):
        CWCoreAPI.instance = self
        self.sigNewProject = util.Signal()
        self.sigNewScopeData = util.Signal()
        self.sigConnectStatus = util.Signal()
        self.sigAttackChanged = util.Signal()
        self.sigNewInputData = util.Signal()
        self.sigNewTextResponse = util.Signal()
        self.sigTraceDone = util.Signal()
        self.sigCampaignStart = util.Signal()
        self.sigCampaignDone = util.Signal()
        self.sigTracesChanged = util.Signal()
        self.executingScripts = util.Observable(False)

        self.valid_scopes = pluginmanager.getPluginsInDictFromPackage("chipwhisperer.capture.scopes", True, True)
        self.valid_targets =  pluginmanager.getPluginsInDictFromPackage("chipwhisperer.capture.targets", True, True)
        self.valid_traces = pluginmanager.getPluginsInDictFromPackage("chipwhisperer.common.traces", True, True)
        self.valid_aux = pluginmanager.getPluginsInDictFromPackage("chipwhisperer.capture.auxiliary", True, True)
        self.valid_acqPatterns =  pluginmanager.getPluginsInDictFromPackage("chipwhisperer.capture.acq_patterns", True, False)
        self.valid_attacks = pluginmanager.getPluginsInDictFromPackage("chipwhisperer.analyzer.attacks", True, False)
        self.valid_preprocessingModules = pluginmanager.getPluginsInDictFromPackage("chipwhisperer.analyzer.preprocessing", False, True)

        self.settings = Settings()

        # Initialize default values
        self._project = self._scope = self._target = self._attack =  self._traceFormat = self._acqPattern = None
        self._attack = self.valid_attacks.get("CPA", None)
        self._acqPattern = self.valid_acqPatterns["Basic"]
        self._auxList = [None]  # TODO: implement it as a list in the whole class
        self._numTraces = 50
        self._numTraceSets = 1

        self.params = Parameter(name='Generic Settings', type='group', addLoadSave=True).register()
        self.params.addChildren([
            {'name':'Scope Module', 'key':'scopeMod', 'type':'list', 'values':self.valid_scopes, 'get':self.getScope, 'set':self.setScope},
            {'name':'Target Module', 'key':'targetMod', 'type':'list', 'values':self.valid_targets, 'get':self.getTarget, 'set':self.setTarget},
            {'name':'Trace Format', 'type':'list', 'values':self.valid_traces, 'get':self.getTraceFormat, 'set':self.setTraceFormat},
            {'name':'Auxiliary Module', 'type':'list', 'values':self.valid_aux, 'get':self.getAuxModule, 'set':self.setAux},
            {'name':'Acquisition Settings', 'type':'group', 'children':[
                    {'name':'Number of Traces', 'type':'int', 'limits':(1, 1E9), 'get':self.getNumTraces, 'set':self.setNumTraces, 'linked':['Traces per Set']},
                    {'name':'Number of Sets', 'type':'int', 'limits':(1, 1E6), 'get':self.getNumTraceSets, 'set':self.setNumTraceSets, 'linked':['Traces per Set'], 'tip': 'Break acquisition into N sets, '
                     'which may cause data to be saved more frequently. The default capture driver requires that NTraces/NSets is small enough to avoid running out of system memory '
                     'as each segment is buffered into RAM before being written to disk.'},
                    {'name':'Traces per Set', 'type':'int', 'readonly':True, 'get':self.tracesPerSet},
                    {'name':'Key/Text Pattern', 'type':'list', 'values':self.valid_acqPatterns, 'get':self.getAcqPattern, 'set':self.setAcqPattern},
            ]},
        ])
        self.scopeParam = Parameter(name="Scope Settings", type='group', addLoadSave=True).register()
        self.params.getChild('Scope Module').stealDynamicParameters(self.scopeParam)

        self.targetParam = Parameter(name="Target Settings", type='group', addLoadSave=True).register()
        self.params.getChild('Target Module').stealDynamicParameters(self.targetParam)

        self.traceParam = Parameter(name="Trace Settings", type='group', addLoadSave=True).register()
        self.params.getChild('Trace Format').stealDynamicParameters(self.traceParam)

        self.auxParam = Parameter(name="Aux Settings", type='group', addLoadSave=True).register()
        self.params.getChild('Auxiliary Module').stealDynamicParameters(self.auxParam)

        # self.attackParam = Parameter(name="Attack Settings", type='group')
        # self.params.getChild('Attack Module').getDynamicParameters(self.attackParam)

        self.newProject()

    def getResults(self, name):
        """Return the requested result widget. It should be registered."""
        return ResultsBase.registeredObjects[name]

    def getScope(self):
        """Return the current scope module object."""
        return self._scope

    @setupSetParam("Scope Module")
    def setScope(self, driver):
        """Set the current scope module object."""
        if self.getScope():
            self.getScope().dis()
        self._scope = driver
        if self.getScope():
            self.getScope().dataUpdated.connect(self.sigNewScopeData.emit)
            self.getScope().connectStatus.connect(self.sigConnectStatus.emit)

    def getTarget(self):
        """Return the current target module object."""
        return self._target

    @setupSetParam("Target Module")
    def setTarget(self, driver):
        """Set the current target module object."""
        if self.getTarget(): self.getTarget().dis()
        self._target = driver
        if self.getTarget():
            self.getTarget().newInputData.connect(self.sigNewInputData.emit)
            self.getTarget().connectStatus.connect(self.sigConnectStatus.emit)

    def getAuxModule(self):
        """Return a list with the auxiliary modules."""
        return self._auxList[0]

    def getAuxList(self):
        """Return a list with the auxiliary modules."""
        return self._auxList

    @setupSetParam("Auxiliary Module")
    def setAux(self, aux):
        """Set the first aux module. Will be updated to support more modules."""
        self._auxList = [aux]

    def getAcqPattern(self):
        """Return the selected acquisition pattern."""
        return self._acqPattern

    @setupSetParam("Key/Text Pattern")
    def setAcqPattern(self, pat):
        """Set the current acquisition pattern."""
        self._acqPattern = pat
        if self._acqPattern is not None:
            self._acqPattern.getParams().remove()
        self.getParams().append(self._acqPattern.getParams())

    def getNewTrace(self, format):
        """Return a new trace object for the specified format."""
        if format is None:
            raise Warning("No trace format selected.")
        tmp = copy.copy(format)
        tmp.clear()
        starttime = datetime.now()
        prefix = starttime.strftime('%Y.%m.%d-%H.%M.%S') + "_"
        tmp.config.setConfigFilename(CWCoreAPI.getInstance().project().datadirectory + "traces/config_" + prefix + ".cfg")
        tmp.config.setAttr("prefix", prefix)
        tmp.config.setAttr("date", starttime.strftime('%Y-%m-%d %H:%M:%S'))
        return tmp

    def getTraceFormat(self):
        """Return the selected trace format."""
        return self._traceFormat

    @setupSetParam("Trace Format")
    def setTraceFormat(self, format):
        """Set the current trace format for acquisition."""
        self._traceFormat = format

    def getAttack(self):
        """Return the current attack module. NOT BEING USED AT THE MOMENT"""
        return self._attack

    def setAttack(self, attack):
        """Set the current attack module. NOT BEING USED AT THE MOMENT"""
        self._attack = attack
        if self.getAttack():
            self.getAttack().setTraceLimits(self.project().traceManager().numTraces(), self.project().traceManager().numPoints())
        self.sigAttackChanged.emit()

    def project(self):
        """Return the current opened project"""
        return self._project

    def setProject(self, proj):
        """Set the current opened project"""
        self._project = proj
        self.sigNewProject.emit()

    def newProject(self):
        """Create a new project"""
        self.setProject(ProjectFormat())
        self.project().setProgramName(self.__name__)
        self.project().setProgramVersion(self.__version__)
        self.project().traceManager().sigTracesChanged.connect(self.sigTracesChanged.emit)

    def openProject(self, fname):
        """Open project file"""
        self.newProject()
        self.project().load(fname)
        try:
            ResultsBase.registeredObjects["Trace Output Plot"].setTraceSource(TraceSource.registeredObjects["Trace Management"])
        except KeyError:
            pass

    def saveProject(self, fname=None):
        """Save the current opened project to file"""
        if fname is not None:
            self.project().setFilename(fname)
        self.project().save()

    def connectScope(self):
        """Connect to the selected scope"""
        try:
            if self.getScope():
                self.getScope().con()
                try:
                    # Sets the Plot Widget input (if it exists) to the last added TraceSource
                    ResultsBase.registeredObjects["Trace Output Plot"].setTraceSource(
                        TraceSource.registeredObjects[next(reversed(TraceSource.registeredObjects))])
                except KeyError:
                    pass

        except Warning:
            sys.excepthook(*sys.exc_info())
            return False
        return True

    def disconnectScope(self):
        """Disconnect the current scope"""
        self.getScope().dis()

    def connectTarget(self):
        """Connect to the selected target"""
        try:
            if self.getTarget():
                self.getTarget().con(scope=self.getScope())
        except Warning:
            sys.excepthook(*sys.exc_info())
            return False
        return True

    def disconnectTarget(self):
        """Disconnect the current target"""
        self.getTarget().dis()

    def doConDis(self):
        """DEPRECATED: It is here just for compatibility reasons"""
        print "Method doConDis() is deprecated... use connect() or disconnect() instead"
        return self.connect()

    def connect(self):
        """Connect both: scope and target"""
        return self.connectScope() and self.connectTarget()

    def disconnect(self):
        """Disconnect both: scope and target"""
        self.disconnectScope()
        self.disconnectTarget()

    def getNumTraces(self):
        """Return the total number or traces for acquisition purposes"""
        return self._numTraces

    @setupSetParam("Number of Traces")
    def setNumTraces(self, n):
        """Set the total number or traces for acquisition purposes"""
        self._numTraces = n

    def getNumTraceSets(self):
        """Return the number of sets/segments"""
        return self._numTraceSets

    @setupSetParam("Number of Sets")
    def setNumTraceSets(self, s):
        """Set the number of sets/segments"""
        self._numTraceSets = s

    def tracesPerSet(self):
        """Return the number of traces in each set/segment"""
        return int(self._numTraces / self._numTraceSets)

    def capture1(self):
        """Capture one trace"""
        try:
            ac = AcquisitionController(self.getScope(), self.getTarget(), writer=None, auxList=self._auxList, keyTextPattern=self.getAcqPattern())
            ac.sigNewTextResponse.connect(self.sigNewTextResponse.emit)
            return ac.doSingleReading()
        except Warning:
            sys.excepthook(*sys.exc_info())
            return False

    def captureM(self, progressBar = None):
        """Capture multiple traces and save its result"""
        if not progressBar: progressBar = ProgressBarText()

        with progressBar:
            progressBar.setStatusMask("Current Segment = %d Current Trace = %d", (0,0))
            progressBar.setMaximum(self._numTraces)

            waveBuffer = None
            tcnt = 0
            setSize = self.tracesPerSet()
            for i in range(0, self._numTraceSets):
                if progressBar.wasAborted(): break
                if self.getTraceFormat() is not None:
                    currentTrace = self.getNewTrace(self.getTraceFormat())
                    # Load trace writer information
                    prefix = currentTrace.config.attr("prefix")[:-1]
                    currentTrace.config.setAttr("targetHW", self.getTarget().getName() if self.getTarget() is not None else "None")
                    currentTrace.config.setAttr("targetSW", os.path.split(Programmer.lastFlashedFile)[1])
                    currentTrace.config.setAttr("scopeName", self.getScope().getName() if self.getScope() is not None else "None")
                    currentTrace.config.setAttr("scopeSampleRate", 0)
                    currentTrace.config.setAttr("notes", "AckPattern: " + str(self.getAcqPattern()) + "; Aux: " + ', '.join(item.getName() for item in self._auxList if item))
                    currentTrace.setTraceHint(setSize)

                    if waveBuffer is not None:
                        currentTrace.setTraceBuffer(waveBuffer)
                else:
                    currentTrace = None
                    prefix = datetime.now().strftime('%Y.%m.%d-%H.%M.%S')

                for aux in self._auxList:
                    if aux:
                        aux.setPrefix(prefix)

                ac = AcquisitionController(self.getScope(), self.getTarget(), currentTrace, self._auxList, self.getAcqPattern())
                ac.setMaxtraces(setSize)
                ac.sigNewTextResponse.connect(self.sigNewTextResponse.emit)
                ac.sigTraceDone.connect(self.sigTraceDone.emit)
                __pb = lambda: progressBar.updateStatus(i*setSize + ac.currentTrace + 1, (i, ac.currentTrace))
                ac.sigTraceDone.connect(__pb)
                self.sigCampaignStart.emit(prefix)
                ac.doReadings(tracesDestination=self.project().traceManager(), progressBar=progressBar)
                self.sigCampaignDone.emit()
                self.project().saveAllSettings(os.path.dirname(currentTrace.config.configFilename()) + "/%s_settings.cwset" % prefix, onlyVisibles=True)
                tcnt += setSize

                if currentTrace is not None:
                    waveBuffer = currentTrace.traces  # Re-use the wave buffer to avoid memory reallocation

                if progressBar.wasAborted():
                    break

            if currentTrace is not None:
                currentTrace.unloadAllTraces()  # Required in order to make the GC work properly :(
                self._traceFormat.unloadAllTraces()

    def runScriptModule(self, mod, funcName="run"):
        """Execute the function in the Plugin classes of the specified module"""
        try:
            classes = pluginmanager.getPluginClassesFromModules([mod])
            if len(classes) == 0:
                raise Warning("No UserScriptBase class found")
            for c in classes:
                self.runScriptClass(c, funcName)
        except Exception as e:
            sys.excepthook(Warning, "Could not execute Script Module %s: '%s'" %
                             (str(mod),
                              "".join(traceback.format_exception_only(sys.exc_info()[0], e.message)).rstrip("\n ")
                              ), sys.exc_info()[2])

    def runScriptClass(self, scriptClass, funcName="run"):
        """Execute the funcName function in the specified class."""
        try:
            self.executingScripts.setValue(True)
            m = scriptClass(self)
            if funcName is not None:
                eval('m.%s()' % funcName)
        except Exception as e:
                sys.excepthook(Warning, "Could not execute method %s in script class %s: '%s'" %
                               (funcName,
                                scriptClass.__name__,
                                "".join(traceback.format_exception_only(sys.exc_info()[0], e.message)).rstrip("\n ")
                                ), sys.exc_info()[2])
        finally:
            self.executingScripts.setValue(False)

    def getParameter(self, path):
        """Return the value of a registered parameter"""
        return Parameter.getParameter(path)

    def setParameter(self, pathAndValue):
        """Set the parameter value, given its path. It should be registered in Parameter.registeredParameters"""
        Parameter.setParameter(pathAndValue)

    @staticmethod
    def getInstance():
        """Implements the singleton pattern/anti-pattern. Returns a reference to the API instance."""
        return CWCoreAPI.instance
class AttackScriptGen(Parameterized):
    _name = "Attack Script Generator"

    def __init__(self, cwGUI):
        self.cwGUI = cwGUI

        self.locked = False
        self.utilList = []
        self.scriptList = []
        self.scriptList.append({'widget':MainScriptEditor(self.cwGUI)})
        self.scriptList[0]['filename'] = self.scriptList[0]['widget'].filename
        self.scriptList[0]['dockname'] = 'Auto-Generated'
        self.defaultEditor = self.scriptList[0]
        autogen = (self.defaultEditor['dockname'], self.defaultEditor['filename'])
        self.preprocessingListGUI = [None, None, None, None]
        self.setAttack(self.cwGUI.api.valid_attacks.get("CPA", None), blockSignal=True)

        self.getParams().addChildren([
            {'name':'Attack Script', 'type':'group', 'children':[
                {'name':'Filename', 'key':'attackfilelist', 'type':'filelist', 'values':{autogen:0}, 'value':0, 'editor':self.editorControl,},
            ]},
            {'name':'Pre-Processing', 'type':'group', 'children':[
                {'name':'Module #%d' % step, 'type':'list', 'values':self.cwGUI.api.valid_preprocessingModules, 'get':partial(self.getPreprocessing, step), 'set':partial(self.setPreprocessing, step)} for step in range(0, len(self.preprocessingListGUI))
            ]},
            {'name':'Attack', 'type':'group', 'children':[
                {'name':'Module', 'type':'list', 'values':self.cwGUI.api.valid_attacks, 'get':self.getAttack, 'set':self.setAttack},
            ]},
        ])
        self.params.init()
        self.preprocessingParams = Parameter(name="Preprocessing", type='group')

        self.attackParams = Parameter(name="Attack", type='group')
        self.params.getChild(['Attack','Module']).stealDynamicParameters(self.attackParams)

        self.cwGUI.api.sigTracesChanged.connect(self.updateAttackTraceLimits)

    def flushTimer(self):
        """Flush all pending script updates"""
        [p.updateDelayTimer.flush() for p in self.preprocessingListGUI if p is not None]
        self.attack.updateDelayTimer.flush()

    def updateAttackTraceLimits(self):
        self.attack.setTraceLimits(self.cwGUI.api.project().traceManager().numTraces(), self.cwGUI.api.project().traceManager().numPoints())

    def editorControl(self, filename, filedesc, default=False, bringToFront=True):
        """This is the call-back from the script editor file list, which opens editors"""

        # Find filename
        thisEditor = None
        for e in self.scriptList:
            if e['filename'] == filename:
                thisEditor = e
                break

        if thisEditor is None:
            thisEditor = {'widget':MainScriptEditor(parent=self.cwGUI, filename=filename)}
            thisEditor['filename'] = filename
            thisEditor['dockname'] = filedesc
            self.scriptList.append(thisEditor)

        # Update all docks if required
        thisEditor['dockname'] = filedesc
        self.editorDocks()

        if bringToFront:
            thisEditor['dock'].show()
            thisEditor['dock'].raise_()

        if default:
            # Set as default for attacks etc
            self.defaultEditor = thisEditor

    def editorDocks(self):
        """Ensure we have a script editor window for each referenced analyzer script file"""

        for script in self.scriptList:
            dockname = "Analysis Script: %s" % script['dockname']

            # No previous dock, do setup
            if 'dock' not in script.keys():
                self.__runScriptConverter = partial(self.runScriptFunction, filename=script['filename'])
                script['widget'].editWindow.runFunction.connect(self.__runScriptConverter)
                script['dock'] = self.cwGUI.addDock(script['widget'], name=dockname, area=Qt.BottomDockWidgetArea)

            script['dock'].setWindowTitle(dockname)

    def getPreprocessing(self, num):
        return self.preprocessingListGUI[num]

    @setupSetParam("")
    def setPreprocessing(self, num, module):
        """Insert the preprocessing module selected from the GUI into the list of active modules.

        This ensures that the options for that module are then displayed in the GUI, along with
        writing the auto-generated script.
        """

        #Walk backwards to find previous trace source
        last_trace_src = self.cwGUI.api.project().traceManager()
        for i in range(num, 0, -1):
            if self.preprocessingListGUI[i] is not None:
                last_trace_src = self.preprocessingListGUI[i]
                break

        if self.preprocessingListGUI[num] is not None:
            self.preprocessingListGUI[num].deregister()
            self.preprocessingParams.getChild('Pre-Processing Mod. #%d'% num).delete()
        if module:
            self.preprocessingListGUI[num] = module(traceSource=last_trace_src)
            self.preprocessingListGUI[num].scriptsUpdated.connect(self.reloadScripts)
            par = Parameter(name = 'Pre-Processing Mod. #%d'% num, type = "group")
            par.append(self.preprocessingListGUI[num].getParams())
            self.preprocessingParams.append(par)
        else:
            self.preprocessingListGUI[num] = None

        self.reloadScripts()

    def getAttack(self):
        return self.attack

    @setupSetParam(["Attack","Module"])
    def setAttack(self, module):
        self.attack = module
        if module:
            self.updateAttackTraceLimits()
            self.reloadScripts()
            self.attack.scriptsUpdated.connect(self.reloadScripts)
            self.attack.runScriptFunction.connect(self.runScriptFunction)

    def runScriptFunction(self, funcName, filename=None):
        """Loads a given script and runs a specific function within it."""
        mod = self.setupScriptModule(filename)
        self.cwGUI.api.runScriptModule(mod, funcName)

    def setupScriptModule(self, filename=None):
        """Loads a given script as a module for dynamic run-time insertion.

        Args:
            filename (str): The full filename to open. If None it opens the
                            auto-generated script instead.
        """

        if filename and filename != self.defaultEditor['filename']:
            raise Warning("Script Error: Cannot run script from non-default function")

        return self.defaultEditor['widget'].loadModule()

    def reloadScripts(self):
        """Rewrite the auto-generated analyzer script, using settings from the GUI"""
        if self.cwGUI.api.executingScripts.value():
            self.cwGUI.api.executingScripts.connect(self.reloadScripts)
            return

        self.cwGUI.api.executingScripts.disconnect(self.reloadScripts)

        # Auto-Generated is always first
        mse = self.scriptList[0]['widget']

        mse.saveSliderPosition()
        mse.editWindow.clear()

        mse.append("# Date Auto-Generated: %s" % datetime.now().strftime('%Y.%m.%d-%H.%M.%S'), 0)
        mse.append("from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI", 0)
        mse.append("from chipwhisperer.common.scripts.base import UserScriptBase", 0)
        # Get imports from preprocessing
        mse.append("# Imports from Preprocessing", 0)
        mse.append("import chipwhisperer.analyzer.preprocessing as preprocessing", 0)

        for p in self.preprocessingListGUI:
            if p:
                imports = p.getImportStatements()
                for i in imports: mse.append(i, 0)

        # Get imports from attack
        mse.append("# Imports from Attack", 0)
        if self.attack:
            for i in self.attack.getImportStatements():
                mse.append(i, 0)

        # Some other imports
        mse.append("# Imports from utilList", 0)
        for index, util in enumerate(self.utilList):
            if util.findParam("enabled").getValue():
                for i in util.getImportStatements(): mse.append(i, 0)

        mse.append("", 0)

        # Add main class
        mse.append("class UserScript(UserScriptBase):", 0)
        mse.append("name = \"Auto-generated\"",1)
        mse.append("description = \"Auto-generated Attack Script\"",1)

        mse.append("def __init__(self, api):", 1)
        mse.append("UserScriptBase.__init__(self, api)")
        mse.append("self.initProject()")
        mse.append("self.initPreprocessing()")
        mse.append("self.initAnalysis()")
        mse.append("self.initReporting()")

        mse.append("def initProject(self):", 1)
        mse.append("pass")

        mse.append("def initPreprocessing(self):", 1)

        # Get init from preprocessing
        lastOutput = "self.api.project().traceManager()"
        for i, p in enumerate(self.preprocessingListGUI):
            if p and p.getName() != "None":
                classname = type(p).__name__
                instname = "ppMod%d" % i
                mse.append("%s = preprocessing.%s.%s(%s)" % (instname, classname, classname, lastOutput))
                for s in p.getStatements('init'):
                    mse.append(s.replace("self.", instname + ".").replace("UserScript.", "self."))
                mse.append("%s.init()" % (instname))
                lastOutput = instname
        mse.append("self.traces = %s" % lastOutput)

        # Get init from analysis
        mse.append("def initAnalysis(self):", 1)
        if self.attack:
            mse.append('self.attack = %s()' % type(self.attack).__name__)
            for s in self.attack.getStatements('init'):
                mse.append(s.replace("self.", "self.attack.").replace("UserScript.", "self."))
        else:
            mse.append('pass')

        # Get init from reporting
        mse.append("def initReporting(self):", 1)
        mse.append("# Configures the attack observers (usually a set of GUI widgets)")
        if len(ResultsBase.registeredObjects)>0:
            for k, v in ResultsBase.registeredObjects.iteritems():
                if hasattr(v,"setTraceSource"):
                    mse.append("self.api.getResults(\"%s\").setTraceSource(self.traces)" % k)
                if hasattr(v,"setAnalysisSource"):
                    mse.append("self.api.getResults(\"%s\").setAnalysisSource(self.attack)" % k)
        else:
            mse.append("pass")

        # Do the attack
        mse.append("def run(self):", 1)
        mse.append("self.attack.processTraces()")

        # Get other commands from attack module
        if self.attack:
            for k in self.attack._smartstatements:
                if k == 'init' or k == 'go' or k == 'done':
                    pass
                else:
                    mse.append("def %s(self):" % k, 1)
                    for s in self.attack.getStatements(k):
                        mse.append(s.replace("self.", "self.attack.").replace("UserScript.", "self."))

        # Get other commands from other utilities
        for index, util in enumerate(self.utilList):
            if util.findParam("enabled").getValue():
                for k in util._smartstatements:
                    util._smartstatements[k].addSelfReplacement("utilList[%d]." % index)
                    util._smartstatements[k].addSelfReplacement("cwagui.attackScriptGen.") #TODO-temp hack
                    statements = util.getStatements(k)

                    if len(statements) > 0:
                        mse.append("def %s_%s(self):" % (util.__class__.__name__, k), 1)
                        mse.append("self.cwagui = CWAnalyzerGUI.getInstance()") #TODO - temp hack
                        for s in statements:
                            mse.append(s.replace("UserScript.", "self."))

        mse.append("if __name__ == '__main__':\n"
                    "    import chipwhisperer.analyzer.ui.CWAnalyzerGUI as cwa\n"
                    "    from chipwhisperer.common.utils.parameter import Parameter\n"
                    "    Parameter.usePyQtGraph = True            # Comment if you don't need the GUI\n"
                    "    api = CWCoreAPI()                        # Instantiate the API\n"
                    "    app = cwa.makeApplication(\"Analyzer\")    # Comment if you don't need the GUI\n"
                    "    gui = cwa.CWAnalyzerGUI(api)             # Comment if you don't need the GUI\n"
                    "    gui.show()                               # Comment if you don't need the GUI\n"
                    "    api.runScriptClass(UserScript)           # Run UserScript through the API\n"
                    "    app.exec_()                              # Comment if you don't need the GUI\n", 0)

        mse.restoreSliderPosition()
        self.cwGUI.api.runScriptModule(self.setupScriptModule(), None)
class AttackScriptGen(Parameterized):
    _name = "Attack Script Generator"

    def __init__(self, cwGUI):
        self.cwGUI = cwGUI

        self.locked = False
        self.utilList = []
        self.scriptList = []
        self.scriptList.append({'widget': MainScriptEditor(self.cwGUI)})
        self.scriptList[0]['filename'] = self.scriptList[0]['widget'].filename
        self.scriptList[0]['dockname'] = 'Auto-Generated'
        self.defaultEditor = self.scriptList[0]
        autogen = (self.defaultEditor['dockname'],
                   self.defaultEditor['filename'])
        self.preprocessingListGUI = [None, None, None, None]
        self.setAttack(self.cwGUI.api.valid_attacks.get("CPA", None),
                       blockSignal=True)

        self.getParams().addChildren([
            {
                'name':
                'Attack Script',
                'type':
                'group',
                'children': [
                    {
                        'name': 'Filename',
                        'key': 'attackfilelist',
                        'type': 'filelist',
                        'values': {
                            autogen: 0
                        },
                        'value': 0,
                        'editor': self.editorControl,
                    },
                ]
            },
            {
                'name':
                'Pre-Processing',
                'type':
                'group',
                'children': [{
                    'name': 'Module #%d' % step,
                    'type': 'list',
                    'values': self.cwGUI.api.valid_preprocessingModules,
                    'get': partial(self.getPreprocessing, step),
                    'set': partial(self.setPreprocessing, step)
                } for step in range(0, len(self.preprocessingListGUI))]
            },
            {
                'name':
                'Attack',
                'type':
                'group',
                'children': [
                    {
                        'name': 'Module',
                        'type': 'list',
                        'values': self.cwGUI.api.valid_attacks,
                        'get': self.getAttack,
                        'set': self.setAttack
                    },
                ]
            },
        ])
        self.params.init()
        self.preprocessingParams = Parameter(name="Preprocessing",
                                             type='group')

        self.attackParams = Parameter(name="Attack", type='group')
        self.params.getChild(['Attack', 'Module'
                              ]).stealDynamicParameters(self.attackParams)

    def projectChanged(self):
        if self.attack:
            self.attack.findParam('input').setValue(
                TraceSource.registeredObjects["Trace Management"])

    def flushTimer(self):
        """Flush all pending script updates"""
        [
            p.updateDelayTimer.flush() for p in self.preprocessingListGUI
            if p is not None
        ]
        self.attack.updateDelayTimer.flush()

    def editorControl(self,
                      filename,
                      filedesc,
                      default=False,
                      bringToFront=True):
        """This is the call-back from the script editor file list, which opens editors"""

        # Find filename
        thisEditor = None
        for e in self.scriptList:
            if e['filename'] == filename:
                thisEditor = e
                break

        if thisEditor is None:
            thisEditor = {
                'widget': MainScriptEditor(parent=self.cwGUI,
                                           filename=filename)
            }
            thisEditor['filename'] = filename
            thisEditor['dockname'] = filedesc
            self.scriptList.append(thisEditor)

        # Update all docks if required
        thisEditor['dockname'] = filedesc
        self.editorDocks()

        if bringToFront:
            thisEditor['dock'].show()
            thisEditor['dock'].raise_()

        if default:
            # Set as default for attacks etc
            self.defaultEditor = thisEditor

    def editorDocks(self):
        """Ensure we have a script editor window for each referenced analyzer script file"""

        for script in self.scriptList:
            dockname = "Analysis Script: %s" % script['dockname']

            # No previous dock, do setup
            if 'dock' not in script.keys():
                self.__runScriptConverter = partial(
                    self.runScriptFunction, filename=script['filename'])
                script['widget'].editWindow.runFunction.connect(
                    self.__runScriptConverter)
                script['dock'] = self.cwGUI.addDock(
                    script['widget'],
                    name=dockname,
                    area=Qt.BottomDockWidgetArea)

            script['dock'].setWindowTitle(dockname)

    def getPreprocessing(self, num):
        return self.preprocessingListGUI[num]

    @setupSetParam("")
    def setPreprocessing(self, num, module):
        """Insert the preprocessing module selected from the GUI into the list of active modules.

        This ensures that the options for that module are then displayed in the GUI, along with
        writing the auto-generated script.
        """

        #Walk backwards to find previous trace source
        last_trace_src = self.cwGUI.api.project().traceManager()
        for i in range(num, 0, -1):
            if self.preprocessingListGUI[i] is not None:
                last_trace_src = self.preprocessingListGUI[i]
                break

        if self.preprocessingListGUI[num] is not None:
            self.preprocessingListGUI[num].deregister()
            self.preprocessingParams.getChild('Pre-Processing Mod. #%d' %
                                              num).delete()
        if module:
            self.preprocessingListGUI[num] = module(traceSource=last_trace_src)
            self.preprocessingListGUI[num].scriptsUpdated.connect(
                self.reloadScripts)
            par = Parameter(name='Pre-Processing Mod. #%d' % num, type="group")
            par.append(self.preprocessingListGUI[num].getParams())
            self.preprocessingParams.append(par)
        else:
            self.preprocessingListGUI[num] = None

        self.reloadScripts()

    def getAttack(self):
        return self.attack

    @setupSetParam(["Attack", "Module"])
    def setAttack(self, module):
        self.attack = module
        if module:
            self.reloadScripts()
            self.attack.scriptsUpdated.connect(self.reloadScripts)
            self.attack.runScriptFunction.connect(self.runScriptFunction)
            self.attack.findParam('input').setValue(
                TraceSource.registeredObjects["Trace Management"])

    def runScriptFunction(self, funcName, filename=None):
        """Loads a given script and runs a specific function within it."""
        mod = self.setupScriptModule(filename)
        self.cwGUI.api.runScriptModule(mod, funcName)

    def setupScriptModule(self, filename=None):
        """Loads a given script as a module for dynamic run-time insertion.

        Args:
            filename (str): The full filename to open. If None it opens the
                            auto-generated script instead.
        """

        if filename and filename != self.defaultEditor['filename']:
            raise Warning(
                "Script Error: Cannot run script from non-default function")

        return self.defaultEditor['widget'].loadModule()

    def reloadScripts(self):
        """Rewrite the auto-generated analyzer script, using settings from the GUI"""
        if self.cwGUI.api.executingScripts.value():
            self.cwGUI.api.executingScripts.connect(self.reloadScripts)
            return

        self.cwGUI.api.executingScripts.disconnect(self.reloadScripts)

        # Auto-Generated is always first
        mse = self.scriptList[0]['widget']

        mse.saveSliderPosition()
        mse.editWindow.clear()

        mse.append(
            "# Date Auto-Generated: %s" %
            datetime.now().strftime('%Y.%m.%d-%H.%M.%S'), 0)
        mse.append("from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI",
                   0)
        mse.append(
            "from chipwhisperer.common.scripts.base import UserScriptBase", 0)
        # Get imports from preprocessing
        mse.append("# Imports from Preprocessing", 0)
        for p in self.preprocessingListGUI:
            if p:
                imports = p.getImportStatements()
                for i in imports:
                    mse.append(i, 0)

        # Get imports from attack
        mse.append("# Imports from Attack", 0)
        if self.attack:
            for i in self.attack.getImportStatements():
                mse.append(i, 0)

        # Some other imports
        mse.append("# Imports from utilList", 0)
        for index, util in enumerate(self.utilList):
            if util.findParam("enabled").getValue():
                for i in util.getImportStatements():
                    mse.append(i, 0)

        mse.append("", 0)

        # Add main class
        mse.append("class UserScript(UserScriptBase):", 0)
        mse.append("_name = \"Auto-generated\"", 1)
        mse.append("_description = \"Auto-generated Attack Script\"", 1)

        mse.append("def __init__(self, api):", 1)
        mse.append("UserScriptBase.__init__(self, api)")
        mse.append("self.initProject()")
        mse.append("self.initPreprocessing()")
        mse.append("self.initAnalysis()")
        mse.append("self.initReporting()")

        mse.append("def initProject(self):", 1)
        mse.append("pass")

        mse.append("def initPreprocessing(self):", 1)

        # Get init from preprocessing
        lastOutput = "self.api.project().traceManager()"
        for i, p in enumerate(self.preprocessingListGUI):
            if p and p.getName() != "None":
                classname = type(p).__name__
                instname = "ppMod%d" % i
                mse.append(
                    "%s = %s.%s(%s)" %
                    (instname, sys.modules[p.__class__.__module__].__name__,
                     classname, lastOutput))
                for s in p.getStatements('init'):
                    mse.append(
                        s.replace("self.", instname + ".").replace(
                            "UserScript.", "self."))
                mse.append("%s.init()" % (instname))
                lastOutput = instname
        mse.append("self.traces = %s" % lastOutput)

        # Get init from analysis
        mse.append("def initAnalysis(self):", 1)
        if self.attack:
            mse.append('self.attack = %s()' % type(self.attack).__name__)
            for s in self.attack.getStatements('init'):
                mse.append(
                    s.replace("self.",
                              "self.attack.").replace("UserScript.", "self."))
        else:
            mse.append('pass')

        # Get init from reporting
        mse.append("def initReporting(self):", 1)
        mse.append(
            "# Configures the attack observers (usually a set of GUI widgets)")
        if len(ResultsBase.registeredObjects) > 0:
            for k, v in ResultsBase.registeredObjects.iteritems():
                if hasattr(v, "setTraceSource"):
                    mse.append(
                        "self.api.getResults(\"%s\").setTraceSource(self.traces)"
                        % k)
                if hasattr(v, "setAnalysisSource"):
                    mse.append(
                        "self.api.getResults(\"%s\").setAnalysisSource(self.attack)"
                        % k)
        else:
            mse.append("pass")

        # Do the attack
        mse.append("def run(self):", 1)
        mse.append("self.attack.processTraces()")

        # Get other commands from attack module
        if self.attack:
            for k in self.attack._smartstatements:
                if k == 'init' or k == 'go' or k == 'done':
                    pass
                else:
                    mse.append("def %s(self):" % k, 1)
                    for s in self.attack.getStatements(k):
                        mse.append(
                            s.replace("self.", "self.attack.").replace(
                                "UserScript.", "self."))

        # Get other commands from other utilities
        for index, util in enumerate(self.utilList):
            if util.findParam("enabled").getValue():
                for k in util._smartstatements:
                    util._smartstatements[k].addSelfReplacement(
                        "utilList[%d]." % index)
                    util._smartstatements[k].addSelfReplacement(
                        "cwagui.attackScriptGen.")  #TODO-temp hack
                    statements = util.getStatements(k)

                    if len(statements) > 0:
                        mse.append(
                            "def %s_%s(self):" % (util.__class__.__name__, k),
                            1)
                        mse.append("self.cwagui = CWAnalyzerGUI.getInstance()"
                                   )  #TODO - temp hack
                        for s in statements:
                            mse.append(s.replace("UserScript.", "self."))

        mse.append(
            "if __name__ == '__main__':\n"
            "    import chipwhisperer.analyzer.ui.CWAnalyzerGUI as cwa\n"
            "    from chipwhisperer.common.utils.parameter import Parameter\n"
            "    Parameter.usePyQtGraph = True            # Comment if you don't need the GUI\n"
            "    api = CWCoreAPI()                        # Instantiate the API\n"
            "    app = cwa.makeApplication(\"Analyzer\")    # Comment if you don't need the GUI\n"
            "    gui = cwa.CWAnalyzerGUI(api)             # Comment if you don't need the GUI\n"
            "    api.runScriptClass(UserScript)           # Run UserScript through the API\n"
            "    app.exec_()                              # Comment if you don't need the GUI\n",
            0)

        mse.restoreSliderPosition()
        self.cwGUI.api.runScriptModule(self.setupScriptModule(), None)
Beispiel #5
0
class OpenADCInterface_Serial(Parameterized):
    _name = "Serial Port (LX9)"

    def __init__(self, oadcInstance):
        self.portName = ''
        self.ser = None

        self.params = Parameter(name=self.getName(), type='group')
        self.params.addChildren([
            {
                'name': 'Refresh List',
                'type': 'action',
                'action': self.serialRefresh
            },
            {
                'name': 'Selected Port',
                'type': 'list',
                'values': [''],
                'get': self.getPortName,
                'set': self.setPortName
            },
        ])
        self.scope = oadcInstance

    def getPortName(self):
        return self.portName

    @setupSetParam("Selected Port")
    def setPortName(self, snum):
        self.portName = snum

    def con(self):
        if self.ser is None:
            self.ser = serial.Serial()
            self.ser.port = self.portName
            self.ser.baudrate = 512000
            self.ser.timeout = 2  # 2 second timeout

            attempts = 4
            while attempts > 0:
                try:
                    self.ser.open()
                    attempts = 0
                except serial.SerialException as e:
                    attempts -= 1
                    self.ser = None
                    if attempts == 0:
                        raise IOError("Could not open %s" % self.ser.name)

        try:
            self.scope.con(self.ser)
            logging.info('OpenADC Found, Connecting')
        except IOError as e:
            exctype, value = sys.exc_info()[:2]
            raise IOError("OpenADC Error (Serial Port): %s" %
                          (str(exctype) + str(value)))

    def dis(self):
        if self.ser is not None:
            self.ser.close()
            self.ser = None

    def __del__(self):
        if self.ser is not None:
            self.ser.close()

    def serialRefresh(self, _=None):
        serialnames = scan.scan()
        if serialnames is None or len(serialnames) == 0:
            serialnames = [" "]

        p = self.params.getChild('Selected Port')
        p.setLimits(serialnames)
        p.setValue(serialnames[0])
Beispiel #6
0
class CWCoreAPI(Parameterized):
    """
    ChipWisperer API Class.
    Provides access to the most important parts of the tool.
    It has a singleton method called CWCoreAPI.getInstance() that returns a reference to the API instance.
    """

    __name__ = "ChipWhisperer"
    __organization__ = "NewAE Technology Inc."
    __version__ = "V4.0.2"
    _name = 'Generic Settings'
    instance = None

    def __init__(self):
        logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
        CWCoreAPI.instance = self
        self.sigNewProject = util.Signal()
        self.sigConnectStatus = util.Signal()
        self.sigAttackChanged = util.Signal()
        self.sigNewInputData = util.Signal()
        self.sigNewTextResponse = util.Signal()
        self.sigTraceDone = util.Signal()
        self.sigCampaignStart = util.Signal()
        self.sigCampaignDone = util.Signal()
        self.executingScripts = util.Observable(False)

        self.valid_scopes = pluginmanager.getPluginsInDictFromPackage("chipwhisperer.capture.scopes", True, True)
        self.valid_targets =  pluginmanager.getPluginsInDictFromPackage("chipwhisperer.capture.targets", True, True)
        self.valid_traces = pluginmanager.getPluginsInDictFromPackage("chipwhisperer.common.traces", True, True)
        self.valid_aux = pluginmanager.getPluginsInDictFromPackage("chipwhisperer.capture.auxiliary", True, True)
        self.valid_acqPatterns =  pluginmanager.getPluginsInDictFromPackage("chipwhisperer.capture.acq_patterns", True, False)

        self.settings = Settings()

        # Initialize default values
        self._project = self._scope = self._target = self._traceFormat = self._acqPattern = self._attack = None
        self._acqPattern = self.valid_acqPatterns["Basic"]
        self._auxList = AuxList()
        self._numTraces = 50
        self._numTraceSets = 1


        # Storage for last key/plaintext/ciphertext
        self._lastKey = None
        self._lastTextin = None
        self._lastTextout = None
        self._lastExpected = None

        self.params = Parameter(name='Generic Settings', type='group', addLoadSave=True).register()
        self.params.addChildren([
            {'name':'Scope Module', 'key':'scopeMod', 'type':'list', 'values':self.valid_scopes, 'get':self.getScope, 'set':self.setScope},
            {'name':'Target Module', 'key':'targetMod', 'type':'list', 'values':self.valid_targets, 'get':self.getTarget, 'set':self.setTarget},
            {'name':'Acquisition Settings', 'type':'group', 'children':[
                    {'name':'Number of Traces', 'type':'int', 'limits':(1, 1E9), 'get':self.getNumTraces, 'set':self.setNumTraces, 'linked':['Traces per Set']},
                    {'name':'Number of Sets', 'type':'int', 'limits':(1, 1E6), 'get':self.getNumTraceSets, 'set':self.setNumTraceSets, 'linked':['Traces per Set'], 'tip': 'Break acquisition into N sets, '
                     'which may cause data to be saved more frequently. The default capture driver requires that NTraces/NSets is small enough to avoid running out of system memory '
                     'as each segment is buffered into RAM before being written to disk.'},
                    {'name':'Traces per Set', 'type':'int', 'readonly':True, 'get':self.tracesPerSet},
                    {'name':'Key/Text Pattern', 'type':'list', 'values':self.valid_acqPatterns, 'get':self.getAcqPattern, 'set':self.setAcqPattern},
            ]},
        ])
        self.scopeParam = Parameter(name="Scope Settings", type='group', addLoadSave=True).register()
        self.params.getChild('Scope Module').stealDynamicParameters(self.scopeParam)

        self.targetParam = Parameter(name="Target Settings", type='group', addLoadSave=True).register()
        self.params.getChild('Target Module').stealDynamicParameters(self.targetParam)

        # Aux settings
        self.auxParam = self._auxList.getParams().register()

        # Note: Project settings are set up in setProject()

        self.newProject()

    def updateLastKeyText(self, key, textin, textout, exp):
        """Callback for acq controller signal - update key/textin/textout
        """
        self._lastKey = key
        self._lastTextin = textin
        self._lastTextout = textout
        self._lastExpected = exp

        self.sigNewTextResponse.emit(key, textin, textout, exp)

    def getResults(self, name):
        """Return the requested result widget. It should be registered."""
        return ResultsBase.registeredObjects[name]

    def getScope(self):
        """Return the current scope module object."""
        return self._scope

    @setupSetParam("Scope Module")
    def setScope(self, driver):
        """Set the current scope module object."""
        if self.getScope():
            # Don't do anything if we're not changing scopes
            if self.getScope() is driver:
                return
            else:
                self.getScope().dis()
        self._scope = driver
        if self.getScope():
            self.getScope().connectStatus.connect(self.sigConnectStatus.emit)
            self.scopeParam.append(self.getScope().params)
            try:
                ResultsBase.registeredObjects["Trace Output Plot"].setTraceSource(
                    TraceSource.registeredObjects[next(reversed(TraceSource.registeredObjects))])
            except KeyError:
                pass
            if self.getScope().getStatus():
                self.getScope().connectStatus.emit()

    def getTarget(self):
        """Return the current target module object."""
        return self._target

    @setupSetParam("Target Module")
    def setTarget(self, driver):
        """Set the current target module object."""
        if self.getTarget():
            # Don't do anything if we're not changing targets
            if self.getTarget() is driver:
                return
            self.getTarget().dis()
        self._target = driver
        if self.getTarget():
            self.targetParam.append(self.getTarget().params)
            self.getTarget().newInputData.connect(self.sigNewInputData.emit)
            self.getTarget().connectStatus.connect(self.sigConnectStatus.emit)
            if self.getTarget().getStatus():
                self.getTarget().connectStatus.emit()


    def getAuxList(self):
        return self._auxList

    def setAuxList(self, new_list):
        self._auxList = new_list

    def getAuxFunctions(self, only_enabled):
        """TODO: doc
        """
        return self._auxList.getDict(only_enabled)

    def getAcqPattern(self):
        """Return the selected acquisition pattern."""
        return self._acqPattern

    def getAttack(self):
        return self._attack

    @setupSetParam(["Attack Settings", "Attack"])
    def setAttack(self, atk):
        self._attack = atk
        #if self._attack is not None:
        #    self.attackParam.append(self._attack.params)

    @setupSetParam(["Acquisition Settings", "Key/Text Pattern"])
    def setAcqPattern(self, pat):
        """Set the current acquisition pattern."""
        self._acqPattern = pat
        if self._acqPattern is not None:
            self._acqPattern.getParams().remove()
        self.getParams().append(self._acqPattern.getParams())

    def getNewTrace(self, format):
        """Return a new trace object for the specified format."""
        if format is None:
            raise Warning("No trace format selected.")
        tmp = copy.copy(format)
        tmp.clear()
        starttime = datetime.now()
        prefix = starttime.strftime('%Y.%m.%d-%H.%M.%S') + "_"
        tmp.config.setConfigFilename(CWCoreAPI.getInstance().project().datadirectory + "traces/config_" + prefix + ".cfg")
        tmp.config.setAttr("prefix", prefix)
        tmp.config.setAttr("date", starttime.strftime('%Y-%m-%d %H:%M:%S'))
        return tmp

    def getTraceFormat(self):
        """Return the selected trace format."""
        if self._project is not None:
            return self._project.getTraceFormat()
        else:
            return None

    def setTraceFormat(self, format):
        """Set the current trace format for acquisition."""
        if self._project is not None:
            self._project.setTraceFormat(format)

    def project(self):
        """Return the current opened project"""
        return self._project

    def setProject(self, proj):
        """Set the current opened project"""
        self._project = proj
        self.params.append(proj.getParams())
        self.sigNewProject.emit()

    def newProject(self):
        """Create a new project"""
        self.setProject(ProjectFormat(self.__name__, self.__version__))

    def openProject(self, fname):
        """Open project file"""
        self.newProject()
        self.project().load(fname)
        try:
            ResultsBase.registeredObjects["Trace Output Plot"].setTraceSource(TraceSource.registeredObjects["Trace Management"])
        except KeyError:
            pass

    def saveProject(self, fname=None):
        """Save the current opened project to file"""
        if fname is not None:
            self.project().setFilename(fname)
        self.project().save()

    def connectScope(self):
        """Connect to the selected scope"""
        try:
            if self.getScope():
                self.getScope().con()
                try:
                    # Sets the Plot Widget input (if it exists) to the last added TraceSource
                    ResultsBase.registeredObjects["Trace Output Plot"].setTraceSource(
                        TraceSource.registeredObjects[next(reversed(TraceSource.registeredObjects))])
                except KeyError:
                    pass

        except Warning:
            sys.excepthook(*sys.exc_info())
            return False
        return True

    def disconnectScope(self):
        """Disconnect the current scope"""
        self.getScope().dis()

    def connectTarget(self):
        """Connect to the selected target"""
        try:
            if self.getTarget():
                self.getTarget().con(scope=self.getScope())
        except Warning:
            sys.excepthook(*sys.exc_info())
            return False
        return True

    def disconnectTarget(self):
        """Disconnect the current target"""
        self.getTarget().dis()

    def doConDis(self):
        """DEPRECATED: It is here just for compatibility reasons"""
        logging.warning('Method doConDis() is deprecated... use connect() or disconnect() instead')
        return self.connect()

    def connect(self):
        """Connect both: scope and target"""
        return self.connectScope() and self.connectTarget()

    def disconnect(self):
        """Disconnect both: scope and target"""
        self.disconnectScope()
        self.disconnectTarget()

    def getNumTraces(self):
        """Return the total number or traces for acquisition purposes"""
        return self._numTraces

    @setupSetParam(["Acquisition Settings", "Number of Traces"])
    def setNumTraces(self, n):
        """Set the total number or traces for acquisition purposes"""
        self._numTraces = n

    def getNumTraceSets(self):
        """Return the number of sets/segments"""
        return self._numTraceSets

    @setupSetParam(["Acquisition Settings", "Number of Sets"])
    def setNumTraceSets(self, s):
        """Set the number of sets/segments"""
        self._numTraceSets = s

    def tracesPerSet(self):
        """Return the number of traces in each set/segment"""
        return int(self._numTraces / self._numTraceSets)

    def capture1(self):
        """Capture one trace"""
        try:
            aux_dict = self.getAuxFunctions(True)
            ac = AcquisitionController(self.getScope(), self.getTarget(), writer=None, aux=aux_dict, keyTextPattern=self.getAcqPattern())
            ac.sigNewTextResponse.connect(self.updateLastKeyText)
            if self.getTarget():
                self.getTarget().init()
            return ac.doSingleReading()
        except Warning:
            sys.excepthook(*sys.exc_info())
            return False

    def captureM(self, progressBar=None, scope=None, target=None, project=None, aux_list=None, ktp=None, N=1, seg_size=None):
        """Capture multiple traces and save its result"""
        if not progressBar:
            progressBar = ProgressBarText()

        if seg_size is None:
            seg_size = 1000
        trace_mgr = project.traceManager() if project is not None else None
        trace_fmt = project.getTraceFormat() if project is not None else None
        aux_dict = aux_list.getDict(True) if aux_list is not None else None
        segments = int(math.ceil(N / float(seg_size)))

        with progressBar:
            progressBar.setStatusMask("Current Segment = %d Current Trace = %d", (0,0))
            progressBar.setMaximum(N)

            waveBuffer = None
            tcnt = 0
            for i in range(0, segments):
                if progressBar.wasAborted(): break

                this_seg_size = min(seg_size, N - i*seg_size)
                if trace_fmt is not None:
                    currentTrace = self.getNewTrace(trace_fmt)
                    # Load trace writer information
                    prefix = currentTrace.config.attr("prefix")[:-1]
                    currentTrace.config.setAttr("targetHW", target.getName() if target is not None else "None")
                    currentTrace.config.setAttr("targetSW", os.path.split(Programmer.lastFlashedFile)[1])
                    currentTrace.config.setAttr("scopeName", scope.getName() if scope is not None else "None")
                    notes_str = "AckPattern: " + str(ktp) + "; "
                    notes_str += "Aux: "
                    if aux_dict is not None:
                        for t in aux_dict.keys():
                            notes_str += "%s" % t + ", ".join([str(item) for item in aux_dict[t] if item])
                    currentTrace.config.setAttr("notes", notes_str)
                    currentTrace.setTraceHint(this_seg_size)

                    if waveBuffer is not None:
                        currentTrace.setTraceBuffer(waveBuffer)
                else:
                    currentTrace = None
                    prefix = datetime.now().strftime('%Y.%m.%d-%H.%M.%S')

                if aux_dict is not None:
                    for func in aux_dict['set_prefix']:
                        func(prefix)

                ac = AcquisitionController(scope, target, currentTrace, aux_dict, ktp)
                ac.setMaxtraces(this_seg_size)
                ac.sigNewTextResponse.connect(self.updateLastKeyText)
                ac.sigTraceDone.connect(self.sigTraceDone.emit)
                __pb = lambda: progressBar.updateStatus(i*seg_size + ac.currentTrace + 1, (i, ac.currentTrace))
                ac.sigTraceDone.connect(__pb)
                self.sigCampaignStart.emit(prefix)
                ac.doReadings(tracesDestination=trace_mgr, progressBar=progressBar)

                if currentTrace is not None:
                    project.saveAllSettings(os.path.dirname(currentTrace.config.configFilename()) + "/%s_settings.cwset" % prefix, onlyVisibles=True)
                    waveBuffer = currentTrace.traces  # Re-use the wave buffer to avoid memory reallocation
                self.sigCampaignDone.emit()
                tcnt += seg_size

                if progressBar.wasAborted():
                    break

            if currentTrace is not None:
                currentTrace.unloadAllTraces()  # Required in order to make the GC work properly :(
                trace_fmt.unloadAllTraces()
        return True

    def runScriptModule(self, mod, funcName="run"):
        """Execute the function in the Plugin classes of the specified module"""
        try:
            classes = pluginmanager.getPluginClassesFromModules([mod])
            if len(classes) == 0:
                raise Warning("No UserScriptBase class found")
            return [self.runScriptClass(c, funcName) for c in classes]
        except Exception as e:
            sys.excepthook(Warning, "Could not execute Script Module %s: '%s:%s'" %
                             (str(mod),
                              "".join(traceback.format_exception_only(sys.exc_info()[0], e.message)).rstrip("\n "),
                              str(e).rstrip("\n ")
                              ), sys.exc_info()[2])

    def runScriptClass(self, scriptClass, funcName="run"):
        """Execute the funcName function in the specified class."""
        try:
            self.executingScripts.setValue(True)
            m = scriptClass(self)
            if funcName is not None:
                return eval('m.%s()' % funcName)
        except Exception as e:
                sys.excepthook(Warning, "Could not execute method %s in script class %s: '%s:%s'" %
                               (funcName,
                                scriptClass.__name__,
                                "".join(traceback.format_exception_only(sys.exc_info()[0], e.message)).rstrip("\n "),
                                str(e).rstrip("\n ")
                                ), sys.exc_info()[2])
        finally:
            self.executingScripts.setValue(False)

    def getParameter(self, path):
        """Return the value of a registered parameter"""
        return Parameter.getParameter(path)

    def setParameter(self, pathAndValue):
        """Set the parameter value, given its path. It should be registered in Parameter.registeredParameters"""
        Parameter.setParameter(pathAndValue)

    @staticmethod
    def getInstance():
        """Implements the singleton pattern/anti-pattern. Returns a reference to the API instance."""
        return CWCoreAPI.instance

    def getLastKey(self):
        return self._lastKey

    def getLastTextin(self):
        return self._lastTextin

    def getLastTextout(self):
        return self._lastTextout

    def getLastExpected(self):
        return self._lastExpected
Beispiel #7
0
class AttackKeeloqParameters(Parameterized, AutoScript):
    _name= 'Attack Settings'

    def __init__(self, hasHardwareModel=True, hasMultipleRuns=True):

        self.hasHardwareModel = hasHardwareModel
        self.hasMultipleRuns  = hasMultipleRuns

        self.maxSubKeys = 32
        AutoScript.__init__(self)
        self.useAbs = True

        #TODO: Where to get this from?
        self.numsubkeys = 16

        self.allPointsSame = True
        self.startPoint = [0]*self.numsubkeys
        self.endPoint = [0]*self.numsubkeys
        self.traceMax = 0

        self.traceLimitsChanged = util.Signal()

        self.setupTraceParam()
        self.setupPointsParam()

        if self.hasHardwareModel:
            self.getParams().addChildren([
                {'name':'Hardware Model', 'type':'group', 'children':[
                    {'name':'Crypto Algorithm', 'key':'hw_algo', 'type':'list', 'values':{'Keeloq':models_keeloq}, 'value':models_keeloq, 'action':self.updateScript},
                    {'name':'Leakage Model', 'key':'hw_leak', 'type':'list', 'values':models_keeloq.leakagemodels, 'value':"LEAK_HW_CIPHERTEXT_BIT", 'action':self.updateScript},
                ]},
                {'name':'Take Absolute', 'type':'bool', 'get':self.getAbsoluteMode, 'set':self.setAbsoluteMode},
#               #TODO: Should be called from the AES module to figure out # of bytes
#                {'name':'Attacked Bytes', 'type':'group', 'children': self.getByteList()},
            ])

        #self.params.append(self.pointsParams)
        #self.params.append(self.traceParams)

        self.updateBytesVisible()


    def updateScript(self, _=None):
        pass

    def getAbsoluteMode(self):
        return self.useAbs

    @setupSetParam("Take Absolute")
    def setAbsoluteMode(self, mode):
        self.useAbs = mode

    def getByteList(self):
        init = [dict(name='Byte %d' % bnum, type='bool', key='bnumenabled%d' % bnum, value=True, bytenum=bnum, action=self.updateScriptBytesEnabled) for bnum in range(0, self.maxSubKeys)]
        init.insert(0,{'name':'All On', 'type':'action', 'action':self.allBytesOn})
        init.insert(0,{'name':'All Off', 'type':'action', 'action':self.allBytesOff})
        return init

    def updateScriptBytesEnabled(self, _=None):
        blist = []
        for i,t in enumerate(self.bytesParameters()):
            if i < self.numsubkeys:
                if t.getValue() == True:
                    blist.append(t.opts['bytenum'])
        self.addFunction("init", "setTargetBytes", str(blist))

    def updateBytesVisible(self):
        for i,t in enumerate(self.bytesParameters()):
            if i < self.numsubkeys:
                t.show()
            else:
                t.hide()
        self.updateScriptBytesEnabled()

    def allBytesOn(self, _=None):
        for t in self.bytesParameters():
            t.setValue(True)

    def allBytesOff(self, _=None):
       for t in self.bytesParameters():
            t.setValue(False)

    def bytesParameters(self):
        blist = []
        for i in range(0, 64):
            p = self.findParam(['Attacked Bytes','bnumenabled%d' % i])
            if p:
                blist.append(p)
        return blist

############ Trace-Specific

    def setupTraceParam(self):

        #--- find or create group (attack can pre-create the group to influence parameter order)

        try:
            self.traceParams = self.findParam('tracesetup')
        except KeyError:
            self.traceParams = Parameter(self, name='Trace Setup', key='tracesetup', type='group')
            self.params.append(self.traceParams)

        #--- update children

        self.traceParams.clearChildren()

        self.traceParams.addChildren([
            {'name':'Starting Trace', 'key':'strace', 'type':'int', 'value':0, 'action':self.updateGenericScript},
            {'name':'Traces per Attack', 'key':'atraces', 'type':'int', 'limits':(1, 1E6), 'value':1, 'action':self.updateGenericScript},
            {'name':'Attack Runs', 'key':'runs', 'type':'int', 'limits':(1, 1E6), 'value':1, 'action':self.updateGenericScript},
            {'name':'Reporting Interval', 'key':'reportinterval', 'type':'int', 'value':10, 'action':self.updateGenericScript},
        ])

# TODO:
#        if self.hasMultipleRuns:
#        else:
#        if not self.hasMultipleRuns:
#            self.traceParams.addChildren([
#                {'name':'First Trace', 'key':'trace_first', 'type':'int', 'value':0, 'action':self.updateGenericScript},
#                {'name':'Last  Trace',   'key':'trace_last', 'type':'int', 'value':-1, 'action':self.updateGenericScript},
#            ])

        self.addFunction("init", "setTraceStart", "0")
        self.addFunction("init", "setTracesPerAttack", "1")
        self.addFunction("init", "setIterations", "1")
        self.addFunction("init", "setReportingInterval", "10")

    def updateGenericScript(self, _=None):
        runs = self.traceParams.getChild('runs')
        atraces = self.traceParams.getChild('atraces')
        strace = self.traceParams.getChild('strace')
        ri = self.traceParams.getChild('reportinterval')

        #print "runs = %d\natraces= %d\nstrace = %d\n"%(runs.value(), atraces.value(), strace.value())

        if (runs.getValue() * atraces.getValue() + strace.getValue()) > (self.traceMax) or atraces.getValue()<=0:
            solv = (self.traceMax - strace.getValue()) / runs.getValue()
            solv = int(solv)
            atraces.setValue(1, blockAction = True)
            atraces.setLimits((1, solv))
            atraces.setValue(solv, blockAction = True)
        else:
            atraces.setLimits((1, self.traceMax))

        pointrng = (self.pointsParams.getChild('startpoint').getValue(), self.pointsParams.getChild('endpoint').getValue())

        self.addFunction("init", "setTraceStart", "%d" % strace.getValue())
        self.addFunction("init", "setTracesPerAttack", "%d" % atraces.getValue())
        self.addFunction("init", "setIterations", "%d" % runs.getValue())
        self.addFunction("init", "setReportingInterval", "%d" % ri.getValue())
        self.addFunction("init", "setPointRange", "(%d,%d)" % (pointrng[0], pointrng[1]))

############# Points-Specific

    def setupPointsParam(self):

        #--- find or create group (attack can pre-create the group to influence parameter order)

        try:
            self.pointsParams = self.findParam('pointsetup')
        except KeyError:
            self.pointsParams = Parameter(self, name='Point Setup', key='pointsetup', type='group')
            self.params.append(self.pointsParams)

        #--- update children

        self.pointsParams.clearChildren()
        self.pointsParams.addChildren(self.getPointList())


    def getPointList(self):
    #   init = [{'name':'Point Range', 'key':'pointrng', 'type':'rangegraph', 'value':(0,0), 'limits':(self.startPoint[0], self.endPoint[0]), 'default':(0, 0), 'set':self.updateGenericScript, 'graphwidget':ResultsBase.registeredObjects["Trace Output Plot"]},
        init = [{'name':'Starting Point', 'key':'startpoint', 'type':'int', 'value':self.startPoint[0], 'limits':(self.startPoint[0], self.endPoint[0]), 'action':self.updateGenericScript},
                    {'name':'Ending Point', 'key':'endpoint', 'type':'int', 'value':self.endPoint[0], 'limits':(self.startPoint[0], self.endPoint[0]), 'action':self.updateGenericScript},
                    ]
    #
    #    #NOT ACTUALLY SUPPORTED
    #    init.insert(0,{'name':'Points Same across Subkeys', 'type':'bool', 'value':self.allPointsSame, 'set':self.setAllPointsSame, 'readonly':True})
        return init

    # def updatePointRange(self, bnum):
    #    (startparam, endparam) = self.findPointParam(self.pointsParams, bnum)
    #
    #    if (startparam is None) & (bnum is not None):
    #        #We don't have per-byte difference actually, just get regular
    #        (startparam, endparam) = self.findPointParam(self.pointsParams)
    #
    #    val = (startparam.value(), endparam.value())
    #    return val

    # def copyPointsFromOutput(self, bnum=None):
    #    if self.MainWindow is not None:
    #        xran = self.MainWindow.results.graphoutput.xRange()
    #        self.setPointRange(xran[0],xran[1], bnum)

    # def copyPointsFromTrace(self, bnum=None):
    #    if self.MainWindow is not None:
    #        xran = self.MainWindow.waveformDock.widget().xRange()
    #        self.setPointRange(xran[0],xran[1], bnum)

    def setTraceLimits(self, traces, points):
        self.setGenericPointRange(0, points, setlimits=True)
        self.traceMax = traces

        self.addFunction("init", "setPointRange", "(%d,%d)" % (0, points))

        strace =  self.traceParams.getChild('strace')
        self.traceParams.getChild('runs').setValue(1)
        atrace = self.traceParams.getChild('atraces')

        strace.setLimits((0, self.traceMax-1))
        atrace.setValue(1, blockAction=True)
        atrace.setLimits((1, traces))
        atrace.setValue(traces, blockAction=True)

        self.traceLimitsChanged.emit(traces, points)

    def setGenericPointRange(self, start, end, bnum=None, setlimits=False):
        start = int(start)
        end = int(end)-1

        startparam = self.pointsParams.getChild('startpoint')
        endparam = self.pointsParams.getChild('endpoint')

        if startparam:
            if setlimits:
                startparam.setLimits((start, end))
                startparam.setDefault(start)
                self.startPointLimits = (start, end)

            start = enforceLimits(start, self.startPointLimits)
            startparam.setValue(start)

        if endparam:
            if setlimits:
                endparam.setLimits((start, end))
                endparam.setDefault(end)
                self.endPointLimits = (start, end)
            end = enforceLimits(end, self.endPointLimits)
            endparam.setValue(end)

        if bnum is None:
            self.startPoint[:] = [start] * len(self.startPoint)
            self.endPoint[:] = [end] * len(self.endPoint)
        else:
            self.startPoint[bnum] = start
            self.endPoint[bnum] = end
class AttackGenericParameters(Parameterized, AutoScript):
    _name= 'Attack Settings'

    def __init__(self):
        self.maxSubKeys = 32
        AutoScript.__init__(self)
        self.useAbs = True

        #TODO: Where to get this from?
        self.numsubkeys = 16

        self.allPointsSame = True
        self.startPoint = [0]*self.numsubkeys
        self.endPoint = [0]*self.numsubkeys
        self.traceMax = 0

        self.traceLimitsChanged = util.Signal()

        self.setupTraceParam()
        self.setupPointsParam()
        self.getParams().addChildren([
            {'name':'Hardware Model', 'type':'group', 'children':[
                {'name':'Crypto Algorithm', 'key':'hw_algo', 'type':'list', 'values':{'AES-128 (8-bit)':models_AES128_8bit}, 'value':models_AES128_8bit, 'action':lambda _:self.updateScript()},
                {'name':'Leakage Model', 'key':'hw_leak', 'type':'list', 'values':models_AES128_8bit.leakagemodels, 'value':'LEAK_HW_SBOXOUT_FIRSTROUND', 'action':lambda _:self.updateScript()},
            ]},
            {'name':'Take Absolute', 'type':'bool', 'get':self.getAbsoluteMode, 'set':self.setAbsoluteMode},
           #TODO: Should be called from the AES module to figure out # of bytes
            {'name':'Attacked Bytes', 'type':'group', 'children': self.getByteList()},
        ])
        self.params.append(self.pointsParams)
        self.params.append(self.traceParams)

        self.updateBytesVisible()

    def updateScript(self):
        pass

    def getAbsoluteMode(self):
        return self.useAbs

    @setupSetParam("Take Absolute")
    def setAbsoluteMode(self, mode):
        self.useAbs = mode

    def getByteList(self):
        init = [dict(name='Byte %d' % bnum, type='bool', key='bnumenabled%d' % bnum, value=True, bytenum=bnum, action=lambda _:self.updateScriptBytesEnabled()) for bnum in range(0, self.maxSubKeys)]
        init.insert(0,{'name':'All On', 'type':'action', 'action':lambda _:self.allBytesOn()})
        init.insert(0,{'name':'All Off', 'type':'action', 'action':lambda _:self.allBytesOff()})
        return init

    def updateScriptBytesEnabled(self):
        blist = []
        for i,t in enumerate(self.bytesParameters()):
            if i < self.numsubkeys:
                if t.getValue() == True:
                    blist.append(t.opts['bytenum'])
        self.addFunction("init", "setTargetBytes", str(blist))

    def updateBytesVisible(self):
        for i,t in enumerate(self.bytesParameters()):
            if i < self.numsubkeys:
                t.show()
            else:
                t.hide()
        self.updateScriptBytesEnabled()

    def allBytesOn(self):
        for t in self.bytesParameters():
            t.setValue(True)

    def allBytesOff(self):
        for t in self.bytesParameters():
            t.setValue(False)

    def bytesParameters(self):
        blist = []
        for i in range(0, 64):
            p = self.findParam(['Attacked Bytes','bnumenabled%d' % i])
            if p:
                blist.append(p)
        return blist

############ Trace-Specific
    def setupTraceParam(self):
        self.traceParams = Parameter(self, name='Trace Setup', type='group', children=[
            {'name':'Starting Trace', 'key':'strace', 'type':'int', 'value':0, 'action':lambda _:self.updateGenericScript()},
            {'name':'Traces per Attack', 'key':'atraces', 'type':'int', 'limits':(1, 1E6), 'value':1, 'action':lambda _:self.updateGenericScript()},
            {'name':'Attack Runs', 'key':'runs', 'type':'int', 'limits':(1, 1E6), 'value':1, 'action':lambda _:self.updateGenericScript()},
            {'name':'Reporting Interval', 'key':'reportinterval', 'type':'int', 'value':10, 'action':lambda _:self.updateGenericScript()},
        ])

        self.addFunction("init", "setTraceStart", "0")
        self.addFunction("init", "setTracesPerAttack", "1")
        self.addFunction("init", "setIterations", "1")
        self.addFunction("init", "setReportingInterval", "10")

    def updateGenericScript(self, ignored=None):
        runs = self.traceParams.getChild('runs')
        atraces = self.traceParams.getChild('atraces')
        strace = self.traceParams.getChild('strace')
        ri = self.traceParams.getChild('reportinterval')

        #print "runs = %d\natraces= %d\nstrace = %d\n"%(runs.value(), atraces.value(), strace.value())

        if (runs.getValue() * atraces.getValue() + strace.getValue()) > (self.traceMax) or atraces.getValue()<=0:
            solv = (self.traceMax - strace.getValue()) / runs.getValue()
            solv = int(solv)
            atraces.setValue(1, blockAction = True)
            atraces.setLimits((1, solv))
            atraces.setValue(solv, blockAction = True)
        else:
            atraces.setLimits((1, self.traceMax))

        pointrng = (self.pointsParams.getChild('startpoint').getValue(), self.pointsParams.getChild('endpoint').getValue())

        self.addFunction("init", "setTraceStart", "%d" % strace.getValue())
        self.addFunction("init", "setTracesPerAttack", "%d" % atraces.getValue())
        self.addFunction("init", "setIterations", "%d" % runs.getValue())
        self.addFunction("init", "setReportingInterval", "%d" % ri.getValue())
        self.addFunction("init", "setPointRange", "(%d,%d)" % (pointrng[0], pointrng[1]))

############# Points-Specific
    def setupPointsParam(self):
        self.pointsParams = Parameter(self, name='Point Setup', type='group', children=self.getPointList())

    def getPointList(self):
    #   init = [{'name':'Point Range', 'key':'pointrng', 'type':'rangegraph', 'value':(0,0), 'limits':(self.startPoint[0], self.endPoint[0]), 'default':(0, 0), 'set':self.updateGenericScript, 'graphwidget':ResultsBase.registeredObjects["Trace Output Plot"]},
        init = [{'name':'Starting Point', 'key':'startpoint', 'type':'int', 'value':self.startPoint[0], 'limits':(self.startPoint[0], self.endPoint[0]), 'action':lambda _:self.updateGenericScript()},
                    {'name':'Ending Point', 'key':'endpoint', 'type':'int', 'value':self.endPoint[0], 'limits':(self.startPoint[0], self.endPoint[0]), 'action':lambda _:self.updateGenericScript()},
                    ]
    #
    #    #NOT ACTUALLY SUPPORTED
    #    init.insert(0,{'name':'Points Same across Subkeys', 'type':'bool', 'value':self.allPointsSame, 'set':self.setAllPointsSame, 'readonly':True})
        return init

    # def updatePointRange(self, bnum):
    #    (startparam, endparam) = self.findPointParam(self.pointsParams, bnum)
    #
    #    if (startparam is None) & (bnum is not None):
    #        #We don't have per-byte difference actually, just get regular
    #        (startparam, endparam) = self.findPointParam(self.pointsParams)
    #
    #    val = (startparam.value(), endparam.value())
    #    return val

    # def copyPointsFromOutput(self, bnum=None):
    #    if self.MainWindow is not None:
    #        xran = self.MainWindow.results.graphoutput.xRange()
    #        self.setPointRange(xran[0],xran[1], bnum)

    # def copyPointsFromTrace(self, bnum=None):
    #    if self.MainWindow is not None:
    #        xran = self.MainWindow.waveformDock.widget().xRange()
    #        self.setPointRange(xran[0],xran[1], bnum)

    def setTraceLimits(self, traces, points):
        self.setGenericPointRange(0, points, setlimits=True)
        self.traceMax = traces

        self.addFunction("init", "setPointRange", "(%d,%d)" % (0, points))

        strace =  self.traceParams.getChild('strace')
        self.traceParams.getChild('runs').setValue(1)
        atrace = self.traceParams.getChild('atraces')

        strace.setLimits((0, self.traceMax-1))
        atrace.setValue(1, blockAction=True)
        atrace.setLimits((1, traces))
        atrace.setValue(traces, blockAction=True)

        self.traceLimitsChanged.emit(traces, points)

    def setGenericPointRange(self, start, end, bnum=None, setlimits=False):
        start = int(start)
        end = int(end)-1

        startparam = self.pointsParams.getChild('startpoint')
        endparam = self.pointsParams.getChild('endpoint')

        if startparam:
            if setlimits:
                startparam.setLimits((start, end))
                startparam.setDefault(start)
                self.startPointLimits = (start, end)

            start = enforceLimits(start, self.startPointLimits)
            startparam.setValue(start)

        if endparam:
            if setlimits:
                endparam.setLimits((start, end))
                endparam.setDefault(end)
                self.endPointLimits = (start, end)
            end = enforceLimits(end, self.endPointLimits)
            endparam.setValue(end)

        if bnum is None:
            self.startPoint[:] = [start] * len(self.startPoint)
            self.endPoint[:] = [end] * len(self.endPoint)
        else:
            self.startPoint[bnum] = start
            self.endPoint[bnum] = end