As of August 2020 the site you are on (wiki.newae.com) is deprecated, and content is now at rtfm.newae.com.

Difference between revisions of "Adding Modules/Parameters"

From ChipWhisperer Wiki
Jump to: navigation, search
(Changed header levels)
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
=Adding New Modules=
+
==Adding New Modules==
  
 
In the new CW plugin architecture, all modules are scanned during the tool initialization, so new functionalities can be added by just dropping its file inside the respective folder:
 
In the new CW plugin architecture, all modules are scanned during the tool initialization, so new functionalities can be added by just dropping its file inside the respective folder:
Line 33: Line 33:
 
</pre>
 
</pre>
  
=Adding Parameters=
+
==Adding Parameters==
  
 
Parameters are used to allow easy access and manipulation of all object's main attibutes and actions. All parameters can be accessed anywhere in the code throught the Parameter class. It means that if you want to set/get any parameter, you can do it easily adding the follow lines to your code:
 
Parameters are used to allow easy access and manipulation of all object's main attibutes and actions. All parameters can be accessed anywhere in the code throught the Parameter class. It means that if you want to set/get any parameter, you can do it easily adding the follow lines to your code:
Line 96: Line 96:
 
         self._enabled = enabled</pre>
 
         self._enabled = enabled</pre>
  
== What to tweak? ==
+
=== What to tweak? ===
  
=== acq_patterns ===
+
==== acq_patterns ====
 
Has the modules that generate the keys. If you want to generate custom key or plaintext sequences, or read it from a file, this is the place to go.
 
Has the modules that generate the keys. If you want to generate custom key or plaintext sequences, or read it from a file, this is the place to go.
  
=== auxiliary ===
+
==== auxiliary ====
 
Usefull if you want to execute something before, during or after the capture.
 
Usefull if you want to execute something before, during or after the capture.
  
 
Exemple ([http://newae.com/forum/viewtopic.php?f=7&t=202#p1026 provided by GABRIEL_F]):
 
Exemple ([http://newae.com/forum/viewtopic.php?f=7&t=202#p1026 provided by GABRIEL_F]):
  import logging<br>
+
  import logging
  import time<br>
+
  import time
  from chipwhisperer.capture.auxiliary._base import AuxiliaryTemplate<br>
+
  from chipwhisperer.capture.auxiliary._base import AuxiliaryTemplate
  from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI<br>
+
  from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI
  from chipwhisperer.common.utils import util, timer<br>
+
  from chipwhisperer.common.utils import util, timer
  <br>
+
   
  <br>
+
   
  class SerialBeforeArm(AuxiliaryTemplate):<br>
+
  class SerialBeforeArm(AuxiliaryTemplate):
      '''<br>
+
      <nowiki>'''</nowiki> 
      This auxillary module allows for serial data to be sent to the target<br>
+
      This auxillary module allows for serial data to be sent to the target
      during the capture process i.e., before and after arming the scope<br>
+
      during the capture process i.e., before and after arming the scope
      and after the trace has recorded. This enables the ability for the<br>
+
      and after the trace has recorded. This enables the ability for the
      scope to trigger on serial communication that need to start after a<br>
+
      scope to trigger on serial communication that need to start after a
      reset but before the scope is armed and after.<br>
+
      reset but before the scope is armed and after.
 
      
 
      
<br>
+
      Compare to SimpleSerial send Go Command.
      Compare to SimpleSerial send Go Command.<br>
+
 
      
 
      
<br>
+
      TODO:
      TODO:<br>
+
      Parser to chop up multiple commands sent in single string seperated by
      Parser to chop up multiple commands sent in single string seperated by<br>
+
      whitespace. Modify to iterate over returned lists.
      whitespace. Modify to iterate over returned lists.<br>
+
   
  <br>
+
      Uses non-blocking sleep methods poached from ResetCW1173Read.
      Uses non-blocking sleep methods poached from ResetCW1173Read.<br>
+
      <br>   Gabe 25-NOV-16
      
+
      <nowiki>'''</nowiki>   
<br>
+
    Gabe 25-NOV-16<br>
+
      '''<br>
+
<br>
+
 
      _name = "Send Serial During Capture"<br>
 
      _name = "Send Serial During Capture"<br>
<br>
+
      def __init__(self):
      def __init__(self):<br>
+
          AuxiliaryTemplate.__init__(self)
          AuxiliaryTemplate.__init__(self)<br>
+
          self.getParams().addChildren([
          self.getParams().addChildren([<br>
+
              {'name':'Pre-Arm Message', 'type':'str', 'key':'prearmmssg', 'value':''},''
              {'name':'Pre-Arm Message', 'type':'str', 'key':'prearmmssg', 'value':''},<br>
+
              {'name':'Post-Arm Message', 'type':'str', 'key':'postarmmssg', 'value':''},''
              {'name':'Post-Arm Message', 'type':'str', 'key':'postarmmssg', 'value':''},<br>
+
              {'name':'Post-Capture Message', 'type':'str', 'key':'postcapmssg', 'value':''},''
              {'name':'Post-Capture Message', 'type':'str', 'key':'postcapmssg', 'value':''},<br>
+
              {'name':'Delay (Pre-Message)' , 'type':'int',  'key':'predelay',  'limits':(0, 10E3), 'value':0, 'suffix':' ms'},
              {'name':'Delay (Pre-Message)' , 'type':'int',  'key':'predelay',  'limits':(0, 10E3), 'value':0, 'suffix':' ms'},<br>
+
              {'name':'Delay (Post-Message)', 'type':'int',  'key':'postdelay', 'limits':(0, 10E3), 'value':0, 'suffix':' ms'},
              {'name':'Delay (Post-Message)', 'type':'int',  'key':'postdelay', 'limits':(0, 10E3), 'value':0, 'suffix':' ms'},<br>
+
              {'name':'Test Reset', 'type':'action', 'action':self.testSend}
              {'name':'Test Reset', 'type':'action', 'action':self.testSend}<br>
+
          ])
          ])<br>
+
   
  <br>
+
      def traceArm(self):
      def traceArm(self):<br>
+
          """Before arming the scope, send some serial messages and wait"""
          """Before arming the scope, send some serial messages and wait"""<br>
+
          string = self.findParam('prearmmssg').getValue()
          string = self.findParam('prearmmssg').getValue()<br>
+
          self.sendSerial(string)
          self.sendSerial(string)<br>
+
   
  <br>
+
      def traceArmPost(self):
      def traceArmPost(self):<br>
+
          """After arming the scope, send some serial message and wait"""
          """After arming the scope, send some serial message and wait"""<br>
+
          string = self.findParam('postarmmssg').getValue()
          string = self.findParam('postarmmssg').getValue()<br>
+
          self.sendSerial(string)
          self.sendSerial(string)<br>
+
   
  <br>
+
      def traceDone(self):
      def traceDone(self):<br>
+
          """After the trace is captured, send some serial messages and wait"""
          """After the trace is captured, send some serial messages and wait"""<br>
+
          string = self.findParam('postcapmssg').getValue()
          string = self.findParam('postcapmssg').getValue()<br>
+
          self.sendSerial(string)
          self.sendSerial(string)<br>
+
   
  <br>
+
      def sendSerial(self, string):
      def sendSerial(self, string):<br>
+
          """Send a string!"""
          # Send a string!<br>
+
   
  <br>
+
          if string is None or len(string) == 0:
          if string is None or len(string) == 0:<br>
+
              return
              return<br>
+
   
  <br>
+
          dly = self.findParam('predelay').getValue()
          dly = self.findParam('predelay').getValue()<br>
+
          if dly > 0:
          if dly > 0:<br>
+
              self.nonblockingSleep(dly / 1000.0)
              self.nonblockingSleep(dly / 1000.0)<br>
+
   
  <br>
+
          CWCoreAPI.getInstance().getTarget().ser.write(string)
          CWCoreAPI.getInstance().getTarget().ser.write(string)<br>
+
 
          
 
          
<br>
+
          dly = self.findParam('postdelay').getValue()
          dly = self.findParam('postdelay').getValue()<br>
+
          if dly > 0:
          if dly > 0:<br>
+
              self.nonblockingSleep(dly / 1000.0)
              self.nonblockingSleep(dly / 1000.0)<br>
+
   
  <br>
+
      def nonblockingSleep_done(self):
      def nonblockingSleep_done(self):<br>
+
          self._sleeping = False
          self._sleeping = False<br>
+
   
  <br>
+
      def nonblockingSleep(self, stime):
      def nonblockingSleep(self, stime):<br>
+
          """Sleep for given number of seconds (~50mS resolution), but don't block GUI while we do it"""
          """Sleep for given number of seconds (~50mS resolution), but don't block GUI while we do it"""<br>
+
          timer.Timer.singleShot(stime * 1000, self.nonblockingSleep_done)
          timer.Timer.singleShot(stime * 1000, self.nonblockingSleep_done)<br>
+
          self._sleeping = True
          self._sleeping = True<br>
+
          while(self._sleeping):
          while(self._sleeping):<br>
+
              time.sleep(0.01)
              time.sleep(0.01)<br>
+
              util.updateUI()
              util.updateUI()<br>
+
   
  <br>
+
      def testSend(self, _=None):
      def testSend(self, _=None):<br>
+
 
          self.sendSerial('Hello')
 
          self.sendSerial('Hello')

Latest revision as of 05:09, 1 May 2018

Adding New Modules

In the new CW plugin architecture, all modules are scanned during the tool initialization, so new functionalities can be added by just dropping its file inside the respective folder:

  • chipwhisperer/software/chipwhisperer/common/results
  • chipwhisperer/software/chipwhisperer/common/traces
  • chipwhisperer/software/chipwhisperer/capture/acq_patterns
  • chipwhisperer/software/chipwhisperer/capture/auxiliary
  • chipwhisperer/software/chipwhisperer/capture/scopes
  • chipwhisperer/software/chipwhisperer/capture/scripts
  • chipwhisperer/software/chipwhisperer/capture/targets
  • chipwhisperer/software/chipwhisperer/analyzer/attacks
  • chipwhisperer/software/chipwhisperer/analyzer/preprocessing
  • chipwhisperer/software/chipwhisperer/analyzer/scripts
  • and some of the above subfolders.

These paths are checked both inside the tool's root directory (where the tool is installed), and in the Project Folder (default is ~/chipwhisperer_projects), allowing the usage of custom modules without the requirement of being system administer. The CW tools scan these directories looking for classes that inherits from the Plugin class (a marker interface actually) in each public module (that doesn't begin with "_").

IMPORTANT: Accessing "Help->List Enabled/Disabled Plugins" in the tool's menu you'll find a list with all modules it tried to load. In case of any problem, you can check in the table the error message and its details. It should be easier to visuallise if you copy and paste the cell cotent to a text editor (example: notepad).

These folders usually have a file called base.py or _base.py that contains the base class to all plugins in these directories. Ex.:

from .base import PreprocessingBase
from chipwhisperer.common.utils.pluginmanager import Plugin


class AddNoiseRandom(PreprocessingBase, Plugin):
    _name = "Add Noise: Amplitude"
    _description = "Add random noise"
     
...

Adding Parameters

Parameters are used to allow easy access and manipulation of all object's main attibutes and actions. All parameters can be accessed anywhere in the code throught the Parameter class. It means that if you want to set/get any parameter, you can do it easily adding the follow lines to your code:

from chipwhisperer.common.utils.parameter import Parameter
...
Parameter.setParameter([path,..., value])
value = Parameter.getParameter([path,...])

or, if you have access to the api:

api.setParameter([path,..., value])
value = api.getParameter([path,...])

The easiest way to add parameters to your class, is to make it Parameterized (extending this class). It is an abstract class that declares a public interface and implements two manipulation methods to create/get the parameters and find it. As a general rule, you just need to:

  • import the Parameterized class: from chipwhisperer.common.utils.parameter import Parameterized
  • make your class extend it (no construtor call is needed here since the idea is to use it as an interface to avoid the problems with multiple inheritance - i.e.: the diamont one)
  • define a _name and a _description
  • register it if it is not readily accessible through a higher parameter hierarchy: self.getParams().register()
  • call self.getParams().addChildren([...])

The getParams() method does four things:

  • create a new Parameter if it doesn't exist;
  • create a group called _name;
  • create a child description parameter with the specified _description label;
  • return a reference to the parent group parameter.

Search is performed using the findParam([fullpath]) method.

Each parameter stores the data internally or externally, using a set/get pair - usefull to retrieve dynamic data. In this case, the @setupSetParam(nameOrPath) decorator should be used in the set method in order to syncronize the GUI when the method is called directly without using the parameter class.

More information about the Parameterized and the Parameter class can be found in its docstrings.

Basic example:

from chipwhisperer.common.utils.parameter import Parameterized, setupSetParam


class ResultsSave(Parameterized):
    _name = "Save to Files"
    _description = "Save correlation output to files."

    def __init__(self):
        # self.getParams().register()
        self.getParams().addChildren([
            {'name':'Save Raw Results', 'type':'bool', 'get':self.getEnabled, 'set':self.setEnabled},  # With value saved externally
            {'name':'Symbol', 'type':'list', 'values':['o', 's', 't', 'd', '+'], 'value':'o'},         # With value saved internally
        ])

        self.findParam("Symbol").setValue('t')
        s = self.findParam("Symbol").getValue()  # s = 't'

    def getEnabled(self):
        return self._enabled

    @setupSetParam("Save Raw Results")
    def setEnabled(self, enabled):
        self._enabled = enabled

What to tweak?

acq_patterns

Has the modules that generate the keys. If you want to generate custom key or plaintext sequences, or read it from a file, this is the place to go.

auxiliary

Usefull if you want to execute something before, during or after the capture.

Exemple (provided by GABRIEL_F):

import logging
import time
from chipwhisperer.capture.auxiliary._base import AuxiliaryTemplate
from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI
from chipwhisperer.common.utils import util, timer


class SerialBeforeArm(AuxiliaryTemplate):
    ''' 
    This auxillary module allows for serial data to be sent to the target
    during the capture process i.e., before and after arming the scope
    and after the trace has recorded. This enables the ability for the
    scope to trigger on serial communication that need to start after a
    reset but before the scope is armed and after.
    
    Compare to SimpleSerial send Go Command.
    
    TODO:
    Parser to chop up multiple commands sent in single string seperated by
    whitespace. Modify to iterate over returned lists.

    Uses non-blocking sleep methods poached from ResetCW1173Read.
    
Gabe 25-NOV-16     '''        _name = "Send Serial During Capture"
    def __init__(self):         AuxiliaryTemplate.__init__(self)         self.getParams().addChildren([             {'name':'Pre-Arm Message', 'type':'str', 'key':'prearmmssg', 'value':},             {'name':'Post-Arm Message', 'type':'str', 'key':'postarmmssg', 'value':},             {'name':'Post-Capture Message', 'type':'str', 'key':'postcapmssg', 'value':},             {'name':'Delay (Pre-Message)' , 'type':'int',  'key':'predelay',  'limits':(0, 10E3), 'value':0, 'suffix':' ms'},             {'name':'Delay (Post-Message)', 'type':'int',  'key':'postdelay', 'limits':(0, 10E3), 'value':0, 'suffix':' ms'},             {'name':'Test Reset', 'type':'action', 'action':self.testSend}         ])     def traceArm(self):         """Before arming the scope, send some serial messages and wait"""         string = self.findParam('prearmmssg').getValue()         self.sendSerial(string)     def traceArmPost(self):         """After arming the scope, send some serial message and wait"""         string = self.findParam('postarmmssg').getValue()         self.sendSerial(string)     def traceDone(self):         """After the trace is captured, send some serial messages and wait"""         string = self.findParam('postcapmssg').getValue()         self.sendSerial(string)     def sendSerial(self, string):         """Send a string!"""         if string is None or len(string) == 0:             return         dly = self.findParam('predelay').getValue()         if dly > 0:             self.nonblockingSleep(dly / 1000.0)         CWCoreAPI.getInstance().getTarget().ser.write(string)                  dly = self.findParam('postdelay').getValue()         if dly > 0:             self.nonblockingSleep(dly / 1000.0)     def nonblockingSleep_done(self):         self._sleeping = False     def nonblockingSleep(self, stime):         """Sleep for given number of seconds (~50mS resolution), but don't block GUI while we do it"""         timer.Timer.singleShot(stime * 1000, self.nonblockingSleep_done)         self._sleeping = True         while(self._sleeping):             time.sleep(0.01)             util.updateUI()     def testSend(self, _=None):         self.sendSerial('Hello')