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?"
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)
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])
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
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