def initAll(): print("Configuring ChipWhisperer") global scope, target,cs,jlink scope = cw.scope() target = cw.target(scope) scope.adc.samples = 5000 scope.adc.offset = 0 scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 8000000 # 120000000 # 737060 scope.clock.adc_src = "clkgen_x1" scope.trigger.triggers = "tio4" scope.io.hs2 = "glitch" scope.glitch.clk_src = "clkgen" scope.glitch.output = "glitch_only" scope.io.glitch_lp = False scope.io.glitch_hp = True scope.glitch.trigger_src = 'ext_single' print("Configuring JLink") if len(sys.argv) > 1: lib = pylink.library.Library(sys.argv[1]) jlink = pylink.JLink(lib) else: jlink = pylink.JLink() jlink.open() print("Configuring ChipShouter") cs = chipshouter.ChipSHOUTER("/dev/ttyUSB0") if cs.armed == True: cs.armed = False cs.reset_config = True cs.voltage = 250 cs.clr_armed = True
def reconnect(self, verbose: bool = True, preserve_scope_setting: bool = True) -> None: self.disconnect() self._scope = cw.scope(scope_type=scopes.OpenADC) self._scope.default_setup() self._target = cw.target(self._scope, target_type=cw.targets.SimpleSerial) if preserve_scope_setting: self.set_scope_detail( samples=self._prev_setting["samples"] if "samples" in self._prev_setting else None, trigger_mode=self._prev_setting["trigger_mode"] if "trigger_mode" in self._prev_setting else None, offset=self._prev_setting["offset"] if "offset" in self._prev_setting else None, pre_samples=self._prev_setting["pre_samples"] if "pre_samples" in self._prev_setting else None, scale=self._prev_setting["scale"] if "scale" in self._prev_setting else None) else: self._scope.adc.samples = 24400 self._prev_setting["samples"] = 24400 if verbose: print("Reconnected successfully.") pass
def __init__(self, num_samples=740, scope_gain=23, scope=None): """Inits a CwSegmented. Args: num_samples: Number of samples per segment, must be in [``num_samples_min``, ``num_samples_max``]. """ if scope: self._scope = scope else: self._scope = cw.scope() if hasattr(self._scope, '_is_husky'): self._is_husky = self._scope._is_husky else: self._is_husky = False if self._is_husky: if version.parse(cw.__version__) < version.parse("5.6.1"): raise IOError( "ChipWhisperer Version must be 5.6.1 or later for Husky Support" ) else: if version.parse(cw.__version__) != version.parse("5.5.0"): raise IOError( "ChipWhisperer Version must be 5.5.0 (from commit 099807207f3351d16e7988d8f0cccf6d570f306a) for CW-Lite with Segmenting" ) self._configure_scope(scope_gain) self.num_segments = 1 self.num_samples = num_samples self._print_device_info()
def initialize_scope(self, scope_gain, num_samples): """Initializes chipwhisperer scope.""" scope = cw.scope() scope.gain.db = scope_gain scope.adc.samples = num_samples scope.adc.offset = 0 scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 100000000 # We sample using the target clock (100 MHz). if hasattr(scope, '_is_husky') and scope._is_husky: scope.clock.clkgen_src = 'extclk' scope.clock.adc_mul = 1 husky = True else: scope.clock.adc_src = 'extclk_dir' husky = False scope.trigger.triggers = "tio4" scope.io.tio1 = "serial_tx" scope.io.tio2 = "serial_rx" scope.io.hs2 = "disabled" # TODO: Need to update error handling. if not husky: scope.clock.reset_adc() time.sleep(0.5) assert (scope.clock.adc_locked), "ADC failed to lock" return scope
def Setup(PLATFORM): try: if not scope.connectStatus: scope.con() except NameError: scope = cw.scope() try: target = cw.target(scope) except IOError: print( "INFO: Caught exception on reconnecting to target - attempting to reconnect to scope first." ) print( "INFO: This is a work-around when USB has died without Python knowing. Ignore errors above this line." ) scope = cw.scope() target = cw.target(scope) print("INFO: Found ChipWhisperer😍") if "STM" in PLATFORM or PLATFORM == "CWLITEARM" or PLATFORM == "CWNANO": prog = cw.programmers.STM32FProgrammer elif PLATFORM == "CW303" or PLATFORM == "CWLITEXMEGA": prog = cw.programmers.XMEGAProgrammer else: prog = None import time time.sleep(0.05) scope.default_setup() def reset_target(scope): if PLATFORM == "CW303" or PLATFORM == "CWLITEXMEGA": scope.io.pdic = 'low' time.sleep(0.05) scope.io.pdic = 'high_z' #XMEGA doesn't like pdic driven high time.sleep(0.05) else: scope.io.nrst = 'low' time.sleep(0.05) scope.io.nrst = 'high' time.sleep(0.05) return scope, prog, target
def __init__(self): super().__init__() self.config = {} self.config["trigger"] = None print("Using cw-power driver: good hunting") self.cw = cw.scope() self.target = cw.target(self.cw) self.cw.default_setup() # don't care self.cw.io.target_pwr = False
def cw_connect(bitfile_path=default_bitfile, force=False): scope = cw.scope() ftarget = cw.target(scope, CW305, bsfile=bitfile_path, fpga_id='100t', force=force) return (scope, ftarget)
def setup_device(name): """Convience function for setting up and programing a CW/Target pair Args: name (str): String representing the target configuration. Currently supports 'STM32F3', 'CW305', 'XMEGA', 'STM32F3-mbed', 'K82F', 'STM32F4' returns: Setup scope and target objects """ scope = cw.scope() if name == "CW305": scope.gain.db = 25 scope.adc.samples = 129 scope.adc.offset = 0 scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 7370000 scope.clock.adc_src = "extclk_x4" scope.trigger.triggers = "tio4" scope.io.tio1 = "serial_rx" scope.io.tio2 = "serial_tx" scope.io.hs2 = "disabled" target = cw.target(scope, cw.targets.CW305, bsfile="cw305_top.bit", force=False) target.vccint_set(1.0) # we only need PLL1: target.pll.pll_enable_set(True) target.pll.pll_outenable_set(False, 0) target.pll.pll_outenable_set(True, 1) target.pll.pll_outenable_set(False, 2) # run at 10 MHz: target.pll.pll_outfreq_set(10E6, 1) # 1ms is plenty of idling time target.clkusbautooff = True target.clksleeptime = 1 else: target = cw.target(scope) scope.default_setup() scope.adc.samples = 24400 if name == "XMEGA": cw.program_target(scope, cw.programmers.XMEGAProgrammer, "AES-xmega.hex") elif name == "STM32F3": cw.program_target(scope, cw.programmers.STM32FProgrammer, "AES.hex") elif name == "STM32F3-mbed": cw.program_target(scope, cw.programmers.STM32FProgrammer, "AES-mbed.hex") elif name == "K82F": scope.adc.samples=3500 elif name == "STM32F4": cw.program_target(scope, cw.programmers.STM32FProgrammer, "AES-f4.hex") scope.adc.samples=5000 return scope,target
def __init__(self, model: CurveModel, coords: CoordinateModel, platform: Platform, **kwargs): scope = cw.scope() scope.default_setup() target = SimpleSerial() if platform in (Platform.STM32F0, Platform.STM32F3): programmer = STM32FProgrammer elif platform == Platform.XMEGA: programmer = XMEGAProgrammer else: raise ValueError super().__init__(model, coords, target=target, scope=scope, programmer=programmer, **kwargs)
def __init__(self, num_samples=740): """Inits a CwLiteSegmented. Args: num_samples: Number of samples per segment, must be in [``num_samples_min``, ``num_samples_max``]. """ self._scope = cw.scope() self._configure_scope() self.num_segments = 1 self.num_samples = num_samples self._print_device_info()
def init_scope(): scope = cw.scope() target = cw.target(scope) prog = cw.programmers.STM32FProgrammer time.sleep(0.05) scope.default_setup() reset_target(scope) time.sleep(0.05) return scope, target, prog
def connect(self, verbose: bool = True) -> None: self._scope = cw.scope(scope_type=scopes.OpenADC) self._scope.default_setup() self._scope.adc.samples = 24400 self._prev_setting["samples"] = 24400 self._target = cw.target(self._scope, target_type=cw.targets.SimpleSerial) self._ktp = cw.ktp.Basic() self._ktp.setInitialKey( "00112233445566778899AABBCCDDEEFF") # initial key (128bit, 16byte) if verbose: print(f"{self._scope.get_name()} Connected!") print( f"Default mode is '128-bit fixed key and 128-bit variable textin'. " f"Please Change key & textin mode appropriately.") pass
def initAll(): global scope, target scope = cw.scope() target = cw.target(scope) scope.adc.samples = 5000 scope.adc.offset = 0 scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 64000000 # 120000000 # 7370000 scope.clock.adc_src = "clkgen_x4" scope.trigger.triggers = "tio4" scope.glitch.clk_src = "clkgen" # scope.glitch.output = "enable_only" scope.glitch.output = "glitch_only" scope.io.glitch_lp = False scope.io.glitch_hp = True scope.glitch.trigger_src = 'ext_single' scope.adc.basic_mode = "rising_edge"
def initialize(): # ChipWhisperer Lite setup scope = cw.scope() scope.default_setup() # Program the target board target = cw.target(scope) prog = cw.programmers.XMEGAProgrammer cw.program_target(scope, prog, fw_path) # Prepare scope for capturing scope.gain.db = 34 # works best with this gain for some reason scope.adc.samples = 1700 - 170 scope.adc.offset = 500 + 700 + 170 # Return the scope and target handles return scope, target
def setup_device(name): scope = cw.scope() if name == "CW305": scope.gain.db = 25 scope.adc.samples = 129 scope.adc.offset = 0 scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 7370000 scope.clock.adc_src = "extclk_x4" scope.trigger.triggers = "tio4" scope.io.tio1 = "serial_rx" scope.io.tio2 = "serial_tx" scope.io.hs2 = "disabled" target = cw.target(scope, cw.targets.CW305, bsfile="cw305_top.bit", force=False) target.vccint_set(1.0) # we only need PLL1: target.pll.pll_enable_set(True) target.pll.pll_outenable_set(False, 0) target.pll.pll_outenable_set(True, 1) target.pll.pll_outenable_set(False, 2) # run at 10 MHz: target.pll.pll_outfreq_set(10E6, 1) # 1ms is plenty of idling time target.clkusbautooff = True target.clksleeptime = 1 else: target = cw.target(scope) scope.default_setup() scope.adc.samples = 24400 if name == "XMEGA": cw.program_target(scope, cw.programmers.XMEGAProgrammer, "AES-xmega.hex") elif name == "STM32F3": cw.program_target(scope, cw.programmers.STM32FProgrammer, "AES.hex") elif name == "STM32F3-mbed": cw.program_target(scope, cw.programmers.STM32FProgrammer, "AES-mbed.hex") elif name == "K82F": scope.adc.samples=3500 elif name == "STM32F4": cw.program_target(scope, cw.programmers.STM32FProgrammer, "AES-f4.hex") scope.adc.samples=5000 return scope,target
def initCw(): global scope, target print("Configuring ChipWhisperer") scope = cw.scope() target = cw.target(scope) # scope.default_setup() scope.adc.samples = 5000 scope.adc.offset = 0 scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 8000000 # 120000000 # 737060 scope.clock.clkgen_src = "system" scope.clock.adc_src = "clkgen_x1" scope.trigger.triggers = "tio4" scope.glitch.clk_src = "clkgen" scope.glitch.output = "enable_only" scope.io.glitch_lp = False scope.io.glitch_hp = True print(scope.adc.state) scope.io.hs2 = "glitch" scope.glitch.trigger_src = 'ext_single'
def initAll(): print("Configuring CW") global scope, target, cs scope = cw.scope() target = cw.target(scope) scope.adc.samples = 5000 scope.adc.offset = 0 scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 8000000 # 120000000 # 737060 scope.clock.adc_src = "clkgen_x1" scope.trigger.triggers = "tio4" scope.io.hs2 = "glitch" scope.glitch.clk_src = "clkgen" scope.glitch.output = "enable_only" scope.io.glitch_lp = False scope.io.glitch_hp = True scope.glitch.trigger_src = 'ext_single' print("Configuring CS") cs = chipshouter.ChipSHOUTER("/dev/ttyUSB0") cs.reset_config = True cs.voltage = 350 cs.clr_armed = True
def initialize_scope(self): """Initializes chipwhisperer scope.""" scope = cw.scope() scope.gain.db = 23 # Samples per trace - We oversample by 10x and AES with DOM is doing # ~56/72 cycles per encryption (AES-128/256). scope.adc.samples = 740 scope.adc.offset = 0 scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 100000000 # We sample using the target clock (100 MHz). scope.clock.adc_src = "extclk_dir" scope.trigger.triggers = "tio4" scope.io.tio1 = "serial_tx" scope.io.tio2 = "serial_rx" scope.io.hs2 = "disabled" # TODO: Need to update error handling. scope.clock.reset_adc() time.sleep(0.5) assert (scope.clock.adc_locked), "ADC failed to lock" return scope
def cwconnect(offset=1250, totalsamples=3000): scope = cw.scope() target = cw.target(scope) # setup scope parameters scope.gain.gain = 45 scope.adc.samples = int(totalsamples) scope.adc.offset = int(offset) scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 7370000 scope.clock.adc_src = "clkgen_x4" scope.trigger.triggers = "tio4" scope.io.tio1 = "serial_rx" scope.io.tio2 = "serial_tx" scope.io.hs2 = "clkgen" target.baud = 38400 target.protver = '1.0' target.key_cmd = 'k$KEY$\n' target.go_cmd = 'p$TEXT$\n' target.output_cmd = 'r$RESPONSE$\n' return (cw, scope, target)
def setUp(self): logging.basicConfig(level=logging.INFO) self.scope = cw.scope() self.target = cw.target(self.scope) self.HW = [bin(n).count("1") for n in range(0, 256)] self.sbox = ( 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16)
Module: chipwhisperer glitch maker Rivision History: 0.1 - 20200101 - Initial version // using: >>python glitch.py glitch_width glitch_offset repeat(clock cycles) frequency """ import chipwhisperer as cw ## To use the chipwhisperers funtions import time ## To calculate the excecutions times import sys ## To use the arguments [width,offset,repeat,freq] = [float(sys.argv[1]), float(sys.argv[2]), float(sys.argv[3]),int(float(sys.argv[4]))] try: scope = cw.scope() ## Create the chipwhisperer object except NameError: pass scope.clock.clkgen_src = "extclk" ## Select the clock source scope.clock.extclk_freq = freq ## External clock frequency scope.clock.adc_src = "clkgen_x4" ## FPGA ADC clock source scope.trigger.triggers = "tio4" ## FPGA trigger pin scope.io.tio1 = "serial_rx" ## FPGA gpio1 scope.io.tio2 = "serial_tx" ## FPGA gpio2 scope.io.hs2 = "disabled" ## FPGA extra pin, could be pinout for clock scope.io.tio3 = "gpio_low" ## FPGA gpio3, high to reset the edge detector scope.io.tio3 = "gpio_high" scope.io.tio3 = "gpio_low"
r, sw1, sw2 = self.c.transmit([0x00, 0xA4, 0x04, 0x04] + list(r[3:4 + r[3]])) scope.arm() r, sw1, sw2 = self.c.transmit([0x00, 0xC0, 0x00, 0x00] + [sw2]) if rand is None and autn is None: authcmd = [0x00, 0x88, 0x00, 0x81, 0x22, 0x10 ] + [0xaa] * 16 + [0x10] + [0xbb] * 16 else: authcmd = [0x00, 0x88, 0x00, 0x81, 0x22, 0x10] + rand + [0x10 ] + autn r, sw1, sw2 = self.c.transmit(authcmd) sc = SIMController() print("Initializing ChipWhisperer") scope = cw.scope(scope_type=cw.scopes.OpenADC) scope.default_setup() scope.gain = 25 scope.adc.samples = 24000 scope.adc.basic_mode = "rising_edge" scope.trigger.triggers = "tio4" CONFIG_TRACECOUNT = 2 CONFIG_SAMPLECOUNT = 24000 print("Setting up structures") traces = np.zeros((CONFIG_TRACECOUNT, CONFIG_SAMPLECOUNT), np.float32) data = np.zeros((CONFIG_TRACECOUNT, 16), np.uint8) # RAND data_out = np.zeros((CONFIG_TRACECOUNT, 16), np.uint8) # AUTN print("Begin main capture loop")
def __init__(self): super().__init__() self.platformname = "cw" self.scope = cw.scope() self.target = cw.target(self.scope) self.scope.default_setup()
def setup(): scope = cw.scope() time.sleep(0.05) scope.default_setup() helper.reset_target(scope)
def main(argv): if (len(argv) != 3): print( "\nplease specify the path, type and numer of trials\npython CSIDH_glitch.py [path] [type] [ntrials]\ne.g. python CSIDH_glitch.py /home/me/chipwhisperer/hardware/victims/firmware/csidh_trace/ ATTACK1 100" ) sys.exit() else: random.seed(13) PATH = argv[0] TYPE = argv[1] # ATTACK1 or ATTACK2 NTRIAL = int(argv[2]) FULLPATH = PATH + BIN # Setup_Generic ################################################################## scope = cw.scope() target = cw.target(scope) if "STM" in PLATFORM or PLATFORM == "CWLITEARM" or PLATFORM == "CWNANO": prog = cw.programmers.STM32FProgrammer elif PLATFORM == "CW303" or PLATFORM == "CWLITEXMEGA": prog = cw.programmers.XMEGAProgrammer else: prog = None import time time.sleep(0.05) scope.default_setup() def reset_target(scope): if PLATFORM == "CW303" or PLATFORM == "CWLITEXMEGA": scope.io.pdic = 'low' time.sleep(0.05) scope.io.pdic = 'high_z' # XMEGA doesn't like pdic driven high time.sleep(0.05) else: scope.io.nrst = 'low' time.sleep(0.05) scope.io.nrst = 'high' time.sleep(0.05) # Setup_Generic ################################################################## # create firmware os.chdir(PATH) #os.system('make clean PLATFORM=CWLITEARM CRYPTO_TARGET=NONE') #os.system("make PLATFORM=CWLITEARM CRYPTO_TARGET=NONE FUNC_SEL=TEST OPT=0") if ((TYPE == "ATTACK1") or (TYPE == "ATTACK1_D")): if (TYPE == "ATTACK1"): os.system( "make PLATFORM=CWLITEARM CRYPTO_TARGET=NONE FUNC_SEL=ATTACK1 OPT=3" ) else: os.system( "make PLATFORM=CWLITEARM CRYPTO_TARGET=NONE FUNC_SEL=ATTACK1_D OPT=3" ) #os.system("make PLATFORM=CWLITEARM CRYPTO_TARGET=NONE FUNC_SEL=ATTACK1_D OPT=3 TYPE=CM") # Sets up sane capture defaults for this scope # 45dB gain # 5000 capture samples # 0 sample offset # rising edge trigger # 7.37MHz clock output on hs2 # 4*7.37MHz ADC clock # tio1 = serial rx # tio2 = serial tx scope.default_setup() scope.clock.adc_src = 'clkgen_x1' fw_path = FULLPATH.format(PLATFORM) print(fw_path) reset_target(scope) target.flush() cw.program_target(scope, prog, fw_path) glitches = [] glitches.append([ "[scope.glitch.width", "scope.glitch.offset", "scope.glitch.repeat", "scope.glitch.ext_offset", "good/bad/crash]" ]) if (GLITCH): setGlitch(scope) # The response took 1086919328 cycles # -O3 ext_offset = 222534093 wrong = 0 crashes = 0 for i in range(0, NTRIAL): if (GLITCH): # scope.glitch.width = random.randint(-49, 49) # scope.glitch.offset = random.randint(-49, 49) # The width of a single glitch pulse, as a percentage of one period. # One pulse can range from -49.8% to roughly 49.8% of a period. # The system may not be reliable at 0%. Note that negative widths are allowed; # these act as if they are positive widths on the other half of the clock cycle. # scope.glitch.width = random.randint(-49, 49) scope.glitch.width = -9 # The offset from a rising clock edge to a glitch pulse rising edge, # as a percentage of one period. # A pulse may begin anywhere from -49.8% to 49.8% away from a rising edge, # allowing glitches to be swept over the entire clock cycle. # scope.glitch.offset = random.randint(-49, 49) scope.glitch.offset = -38.3 # How long the glitch module waits between a trigger and a glitch. # After the glitch module is triggered, it waits for a number of clock cycles # before generating glitch pulses. This delay allows the glitch to be inserted # at a precise moment during the target’s execution to glitch specific instructions. scope.glitch.ext_offset = random.randint(0, ext_offset) # scope.glitch.ext_offset = 108466842 # The number of glitch pulses to generate per trigger. # When the glitch module is triggered, it produces a number of pulses # that can be combined with the clock signal. This setting allows for # the glitch module to produce stronger glitches (especially during voltage glitching). # Repeat counter must be in the range [1, 255]. # scope.glitch.repeat = random.randint(1, 4) scope.glitch.repeat = 3 reset_target(scope) target.flush() print("\n--------------------------------\nstarting capture " + str(i) + " : " + datetime.datetime.now().strftime("%H:%M:%S")) #scope.adc.timeout = 210 scope.arm() #scope.adc.timeout = 210 target.write("s") time.sleep(0.1) ret = scope.capture() if ret: print('Timeout happened during acquisition') time.sleep(40) if SCOPETYPE == "OPENADC": response_time = scope.adc.trig_count print("The response took {} cycles".format(response_time)) response = target.read(timeout=0) print("<output>\n" + response + "\n</output>") if (GLITCH): if "good" not in response: # Something abnormal happened if len(response) > 0: # Possible glitch! print( "\nBad shared secret\nGlitch at offset {} and repeat = {}" .format(scope.glitch.ext_offset, scope.glitch.repeat)) wrong = wrong + 1 glitches.append([ scope.glitch.width, scope.glitch.offset, scope.glitch.repeat, scope.glitch.ext_offset, "bad" ]) else: # Crash, reset and try again print("\nProbably crashed at {} and repeat = {}". format(scope.glitch.ext_offset, scope.glitch.repeat)) crashes = crashes + 1 glitches.append([ scope.glitch.width, scope.glitch.offset, scope.glitch.repeat, scope.glitch.ext_offset, "crash" ]) else: print( "\nGood shared secret\nGlitch at offset {} and repeat = {}" .format(scope.glitch.ext_offset, scope.glitch.repeat)) glitches.append([ scope.glitch.width, scope.glitch.offset, scope.glitch.repeat, scope.glitch.ext_offset, "good" ]) print("end of capture " + str(i) + " : " + datetime.datetime.now().strftime("%H:%M:%S") + "\n--------------------------------") glitches.append(["-----------------------------"]) glitches.append(["ntrial, wrong, crashes"]) glitches.append([NTRIAL, wrong, crashes]) if (TYPE == "ATTACK1"): PATH = "attack1_" + datetime.datetime.now().strftime( "%d%m%Y_%H%M") + ".csv" else: PATH = "attack1_D_" + datetime.datetime.now().strftime( "%d%m%Y_%H%M") + ".csv" # save raw data as csv with open(PATH, mode='w') as csv_file: csv_writer = csv.writer(csv_file) for entry in glitches: csv_writer.writerow(entry) elif (TYPE == "ATTACK2"): os.system( "make PLATFORM=CWLITEARM CRYPTO_TARGET=NONE FUNC_SEL=ATTACK2 OPT=3" ) # Sets up sane capture defaults for this scope # 45dB gain # 5000 capture samples # 0 sample offset # rising edge trigger # 7.37MHz clock output on hs2 # 4*7.37MHz ADC clock # tio1 = serial rx # tio2 = serial tx scope.default_setup() scope.clock.adc_src = 'clkgen_x1' fw_path = FULLPATH.format(PLATFORM) print(fw_path) reset_target(scope) target.flush() cw.program_target(scope, prog, fw_path) glitches = [] glitches.append([ "[isogeny", "scope.glitch.width", "scope.glitch.offset", "scope.glitch.repeat", "scope.glitch.ext_offset", "good/bad/crash]" ]) # The response took 4846257 cycles : 1. isogeny computation # -O0 # ext_offset = 4846257 # -O3 ext_offset = 83289 wrong = 0 crashes = 0 setDefault(scope) for i in range(0, NTRIAL): if (GLITCH): #isogeny = random.randint(1, 2) isogeny = 2 if (isogeny == 1): setGlitch(scope) # The width of a single glitch pulse, as a percentage of one period. # One pulse can range from -49.8% to roughly 49.8% of a period. # The system may not be reliable at 0%. Note that negative widths are allowed; # these act as if they are positive widths on the other half of the clock cycle. # scope.glitch.width = random.randint(-49, 49) # The offset from a rising clock edge to a glitch pulse rising edge, # as a percentage of one period. # A pulse may begin anywhere from -49.8% to 49.8% away from a rising edge, # allowing glitches to be swept over the entire clock cycle. # scope.glitch.offset = random.randint(-49, 49) # How long the glitch module waits between a trigger and a glitch. # After the glitch module is triggered, it waits for a number of clock cycles # before generating glitch pulses. This delay allows the glitch to be inserted # at a precise moment during the target’s execution to glitch specific instructions. scope.glitch.ext_offset = random.randint(0, ext_offset) # scope.glitch.ext_offset = 108466842 # The number of glitch pulses to generate per trigger. # When the glitch module is triggered, it produces a number of pulses # that can be combined with the clock signal. This setting allows for # the glitch module to produce stronger glitches (especially during voltage glitching). # Repeat counter must be in the range [1, 255]. scope.glitch.repeat = random.randint(1, 4) #scope.glitch.repeat = 1 reset_target(scope) target.flush() print( "\n--------------------------------\nstarting capture " + str(i) + "\n--------------------------------\ncapture of 1. isogeny : " + datetime.datetime.now().strftime("%H:%M:%S")) scope.adc.timeout = 180 scope.arm() scope.adc.timeout = 180 target.write("s") time.sleep(0.1) ret = scope.capture() if ret: print('Timeout happened during acquisition') #time.sleep(60) if SCOPETYPE == "OPENADC": response_time = scope.adc.trig_count print("The response took {} cycles".format(response_time)) response = target.read(timeout=0) print("<output>\n" + response + "\n</output>") print("end of 1. isogeny : " + datetime.datetime.now().strftime("%H:%M:%S") + "\n--------------------------------") setDefault(scope) # The response took 3436390 cycles : 2. isogeny computation # -O0 # ext_offset = 3436390 # -O3 ext_offset = 8580178 if (GLITCH): if (isogeny == 2): setGlitch(scope) # The width of a single glitch pulse, as a percentage of one period. # One pulse can range from -49.8% to roughly 49.8% of a period. # The system may not be reliable at 0%. Note that negative widths are allowed; # these act as if they are positive widths on the other half of the clock cycle. # scope.glitch.width = random.randint(-49, 49) # The offset from a rising clock edge to a glitch pulse rising edge, # as a percentage of one period. # A pulse may begin anywhere from -49.8% to 49.8% away from a rising edge, # allowing glitches to be swept over the entire clock cycle. # scope.glitch.offset = random.randint(-49, 49) # How long the glitch module waits between a trigger and a glitch. # After the glitch module is triggered, it waits for a number of clock cycles # before generating glitch pulses. This delay allows the glitch to be inserted # at a precise moment during the target’s execution to glitch specific instructions. scope.glitch.ext_offset = random.randint(1, ext_offset) # scope.glitch.ext_offset = 108466842 # The number of glitch pulses to generate per trigger. # When the glitch module is triggered, it produces a number of pulses # that can be combined with the clock signal. This setting allows for # the glitch module to produce stronger glitches (especially during voltage glitching). # Repeat counter must be in the range [1, 255]. scope.glitch.repeat = random.randint(1, 4) #scope.glitch.repeat = 1 print( "\n--------------------------------\ncapture of 2. isogeny : " + datetime.datetime.now().strftime("%H:%M:%S")) scope.adc.timeout = 60 scope.arm() scope.adc.timeout = 60 target.write("n") time.sleep(0.1) ret = scope.capture() if ret: print('Timeout happened during acquisition') #time.sleep(10) if SCOPETYPE == "OPENADC": response_time = scope.adc.trig_count print("The response took {} cycles".format(response_time)) response = target.read(timeout=0) print("<output>\n" + response + "\n</output>") print("end of 2. isogeny : " + datetime.datetime.now().strftime("%H:%M:%S") + "\n--------------------------------") setDefault(scope) print( "\n--------------------------------\nstarting capture of result : " + datetime.datetime.now().strftime("%H:%M:%S")) scope.adc.timeout = 30 scope.arm() scope.adc.timeout = 30 target.write("n") time.sleep(0.1) ret = scope.capture() if ret: print('Timeout happened during acquisition') #time.sleep(10) if SCOPETYPE == "OPENADC": response_time = scope.adc.trig_count print("The response took {} cycles".format(response_time)) response = target.read(timeout=0) print("<output>\n" + response + "\n</output>") print("end of capture " + str(i) + " : " + datetime.datetime.now().strftime("%H:%M:%S") + "\n--------------------------------") if (GLITCH): if "good" not in response: # Something abnormal happened if len(response) > 0: # Possible glitch! print( "\nBad shared secret\nGlitching isogeny {} at offset {} and repeat = {}" .format(isogeny, scope.glitch.ext_offset, scope.glitch.repeat)) wrong = wrong + 1 glitches.append([ isogeny, scope.glitch.width, scope.glitch.offset, scope.glitch.repeat, scope.glitch.ext_offset, "bad" ]) else: # Crash, reset and try again print( "\nProbably crashed at isogeny {} at {} and repeat = {}" .format(isogeny, scope.glitch.ext_offset, scope.glitch.repeat)) crashes = crashes + 1 glitches.append([ isogeny, scope.glitch.width, scope.glitch.offset, scope.glitch.repeat, scope.glitch.ext_offset, "crash" ]) else: print( "\nGood shared secret\nGlitching isogeny {} at offset {} and repeat = {}" .format(isogeny, scope.glitch.ext_offset, scope.glitch.repeat)) glitches.append([ isogeny, scope.glitch.width, scope.glitch.offset, scope.glitch.repeat, scope.glitch.ext_offset, "good" ]) glitches.append(["-----------------------------"]) glitches.append(["ntrial, wrong, crashes"]) glitches.append([NTRIAL, wrong, crashes]) PATH = "attack2_" + datetime.datetime.now().strftime( "%d%m%Y_%H%M") + ".csv" # save raw data as csv with open(PATH, mode='w') as csv_file: csv_writer = csv.writer(csv_file) for entry in glitches: csv_writer.writerow(entry) elif (TYPE == "ATTACK2_D"): #os.system("make PLATFORM=CWLITEARM CRYPTO_TARGET=NONE FUNC_SEL=ATTACK2_D OPT=2 TYPE=CM") os.system( "make PLATFORM=CWLITEARM CRYPTO_TARGET=NONE FUNC_SEL=ATTACK2_D OPT=3" ) # Sets up sane capture defaults for this scope # 45dB gain # 5000 capture samples # 0 sample offset # rising edge trigger # 7.37MHz clock output on hs2 # 4*7.37MHz ADC clock # tio1 = serial rx # tio2 = serial tx scope.default_setup() scope.clock.adc_src = 'clkgen_x1' fw_path = FULLPATH.format(PLATFORM) print(fw_path) reset_target(scope) target.flush() cw.program_target(scope, prog, fw_path) glitches = [] glitches.append([ "[isogeny", "scope.glitch.width", "scope.glitch.offset", "scope.glitch.repeat", "scope.glitch.ext_offset", "good/bad/crash]" ]) # The response took 4846257 cycles : 1. isogeny computation # -O0 # ext_offset = 4846257 # -O3 ext_offset = 90082 wrong = 0 crashes = 0 setDefault(scope) test = 5639046 - 10 width = -49 for i in range(0, NTRIAL): test = test + 1 width = width + 3 reset_target(scope) target.flush() # The response took 4846257 cycles : 1. isogeny computation # -O0 # ext_offset = 4846257 # -O3 ext_offset = 90082 if (GLITCH): #isogeny = random.randint(1, 2) isogeny = 1 if (isogeny == 1): setGlitch(scope) # The width of a single glitch pulse, as a percentage of one period. # One pulse can range from -49.firmware/csidh/attack2_D_14052020_2028_m1_1.csv8% to roughly 49.8% of a period. # The system may not be reliable at 0%. Note that negative widths are allowed; # these act as if they are positive widths on the other half of the clock cycle. # scope.glitch.width = random.randint(-49, 49) scope.glitch.width = -9 # The offset from a rising clock edge to a glitch pulse rising edge, # as a percentage of one period. # A pulse may begin anywhere from -49.8% to 49.8% away from a rising edge, # allowing glitches to be swept over the entire clock cycle. # scope.glitch.offset = random.randint(-49, 49) scope.glitch.offset = -38.3 # How long the glitch module waits between a trigger and a glitch. # After the glitch module is triggered, it waits for a number of clock cycles # before generating glitch pulses. This delay allows the glitch to be inserted # at a precise moment during the target’s execution to glitch specific instructions. scope.glitch.ext_offset = random.randint(1, ext_offset) #scope.glitch.ext_offset = 57248 # The number of glitch pulses to generate per trigger. # When the glitch module is triggered, it produces a number of pulses # that can be combined with the clock signal. This setting allows for # the glitch module to produce stronger glitches (especially during voltage glitching). # Repeat counter must be in the range [1, 255]. #scope.glitch.repeat = random.randint(1, 5) scope.glitch.repeat = 3 print( "\n--------------------------------\nstarting capture " + str(i) + "\n--------------------------------\ncapture of 1. isogeny : " + datetime.datetime.now().strftime("%H:%M:%S")) scope.adc.timeout = 10 scope.arm() scope.adc.timeout = 10 target.write("s") #time.sleep(0.1) ret = scope.capture() if ret: print('Timeout happened during acquisition') #time.sleep(5) if SCOPETYPE == "OPENADC": response_time = scope.adc.trig_count print("The response took {} cycles".format(response_time)) response = target.read(timeout=0) #print("<output>\n" + response + "\n</output>") print("end of 1. isogeny : " + datetime.datetime.now().strftime("%H:%M:%S") + "\n--------------------------------") setDefault(scope) # The response took 3436390 cycles : 2. isogeny computation # -O0 # response_time = 3436390 # -O380392 ext_offset = 60817547 if (GLITCH): if (isogeny == 2): setGlitch(scope) # The width of a single glitch pulse, as a percentage of one period. # One pulse can range from -49.8% to roughly 49.8% of a period. # The system may not be reliable at 0%. Note that negative widths are allowed; # these act as if they are positive widths on the other half of the clock cycle. # scope.glitch.width = random.randint(-49, 49) scope.glitch.width = -9 # The offset from a rising clock edge to a glitch pulse rising edge, # as a percentage of one period. # A pulse may begin anywhere from -49.8% to 49.8% away from a rising edge, # allowing glitches to be swept over the entire clock cycle. # scope.glitch.offset = random.randint(-49, 49) scope.glitch.offset = -38.3 # How long the glitch module waits between a trigger and a glitch. # After the glitch module is triggered, it waits for a number of clock cycles # before generating glitch pulses. This delay allows the glitch to be inserted # at a precise moment during the target’s execution to glitch specific instructions. scope.glitch.ext_offset = random.randint(1, ext_offset) #scope.glitch.ext_offset = 5393209 + (i*2) #scope.glitch.ext_offset = 8050242 # The number of glitch pulses to generate per trigger. # When the glitch module is triggered, it produces a number of pulses # that can be combined with the clock signal. This setting allows for # the glitch module to produce stronger glitches (especially during voltage glitching). # Repeat counter must be in the range [1, 255]. #scope.glitch.repeat = random.randint(1, 5) scope.glitch.repeat = 3 #scope.glitch.repeat = 1 print( "\n--------------------------------\ncapture of 2. isogeny : " + datetime.datetime.now().strftime("%H:%M:%S")) scope.adc.timeout = 10 scope.arm() scope.adc.timeout = 10 target.write("n") #time.sleep(0.1) ret = scope.capture() if ret: print('Timeout happened during acquisition') time.sleep(1) if SCOPETYPE == "OPENADC": response_time = scope.adc.trig_count print("The response took {} cycles".format(response_time)) response = target.read(timeout=0) #print("<output>\n" + response + "\n</output>") print("end of 2. isogeny : " + datetime.datetime.now().strftime("%H:%M:%S") + "\n--------------------------------") setDefault(scope) print( "\n--------------------------------\nstarting capture of result : " + datetime.datetime.now().strftime("%H:%M:%S")) scope.adc.timeout = 10 scope.arm() scope.adc.timeout = 10 target.write("n") time.sleep(0.1) ret = scope.capture() if ret: print('Timeout happened during acquisition') #time.sleep(10) if SCOPETYPE == "OPENADC": response_time = scope.adc.trig_count print("The response took {} cycles".format(response_time)) response = target.read(timeout=0) print("<output>\n" + response + "\n</output>") print("end of capture " + str(i) + " : " + datetime.datetime.now().strftime("%H:%M:%S") + "\n--------------------------------") if (GLITCH): if "good" not in response: # Something abnormal happened if len(response) > 0: # Possible glitch! print( "\nBad shared secret\nGlitching isogeny {} at offset {} and repeat = {}" .format(isogeny, scope.glitch.ext_offset, scope.glitch.repeat)) wrong = wrong + 1 glitches.append([ isogeny, scope.glitch.width, scope.glitch.offset, scope.glitch.repeat, scope.glitch.ext_offset, "bad" ]) else: # Crash, reset and try again print( "\nProbably crashed at isogeny {} at {} and repeat = {}" .format(isogeny, scope.glitch.ext_offset, scope.glitch.repeat)) crashes = crashes + 1 glitches.append([ isogeny, scope.glitch.width, scope.glitch.offset, scope.glitch.repeat, scope.glitch.ext_offset, "crash" ]) else: print( "\nGood shared secret\nGlitching isogeny {} at offset {} and repeat = {}" .format(isogeny, scope.glitch.ext_offset, scope.glitch.repeat)) glitches.append([ isogeny, scope.glitch.width, scope.glitch.offset, scope.glitch.repeat, scope.glitch.ext_offset, "good" ]) glitches.append(["-----------------------------"]) glitches.append(["ntrial, wrong, crashes"]) glitches.append([NTRIAL, wrong, crashes]) PATH = "attack2_D_" + datetime.datetime.now().strftime( "%d%m%Y_%H%M") + ".csv" # save raw data as csv with open(PATH, mode='w') as csv_file: csv_writer = csv.writer(csv_file) for entry in glitches: csv_writer.writerow(entry) scope.dis() target.dis()
print "Delay: %s" % repr(ext_offset_range) print "Glitch Offset: %s" % repr(offset_range) print "Glitch Width: %s (%% of clk)" % repr(width_range) print "Glitch Repeat: %s" % repr(repeat_range) print "Save prefix: %s" % save_prefix totalAttempts = countAttempts(ext_offset_range) * countAttempts( offset_range) * countAttempts(width_range) * countAttempts(repeat_range) print "(Est) Total attempts: %d" % totalAttempts # sys.exit(0) print "-- CONNECT TO HW --" scope = cw.scope() target = cw.target(scope) scope.glitch.clk_src = 'clkgen' scope.gain.gain = 45 scope.adc.samples = 15000 scope.adc.offset = 0 scope.adc.basic_mode = "rising_edge" scope.clock.clkgen_freq = 16000000 scope.clock.adc_src = "clkgen_x4" scope.io.tio2 = "serial_tx" scope.io.tio1 = "serial_rx" scope.io.hs2 = "glitch" scope.glitch.offset = 4
def setUp(self): logging.basicConfig(level=logging.INFO) self.scope = cw.scope() self.target = cw.target(self.scope)
def cw_lite_firmware_update_automatically(): scope = cw.scope() _ = cw.target(scope) programmer = cw.SAMFWLoader(scope=scope) programmer.auto_program() pass
def run_tests(cw_dir, config, results_path=None): from concurrent.futures import ProcessPoolExecutor, as_completed if not results_path: results_path = "./" results_handler = logging.FileHandler(results_path + "/testing.log") test_logger.addHandler(results_handler) tutorials, connected_hardware = load_configuration(config) num_hardware = len(connected_hardware) hw_locations = [] loggers = [] handlers = [] for i in range(num_hardware): handlers.append( logging.FileHandler(results_path + "/test_{}.log".format(i))) loggers.append(logging.getLogger("Test Logger {}".format(i))) cur = loggers[i] cur.setLevel(logging.DEBUG) cur.addHandler(handlers[i]) if connected_hardware[i].get('serial number') is None: hw_locations.append(None) continue scope = cw.scope(sn=str(connected_hardware[i]['serial number'])) if scope.latest_fw_str > scope.fw_version_str: scope.upgrade_firmware() time.sleep(5) scope = cw.scope(sn=str(connected_hardware[i]['serial number'])) test_logger.info("Upgraded firmware for device {}".format(i)) else: test_logger.info("Device {} up to date") hw_locations.append((scope._getNAEUSB().usbtx.device.getBusNumber(),\ scope._getNAEUSB().usbtx.device.getDeviceAddress())) test_logger.info("Found device {} at {}".format(i, hw_locations[i])) scope.dis() #hw_locations.appe nb_dir = os.path.join(cw_dir, 'jupyter') output_dir = os.path.join(cw_dir, 'tutorials') # copy the images from input to output directory # keeping them in the same relative directory image_input_dir = os.path.join(nb_dir, 'img') image_output_dir = os.path.join(output_dir, 'img') if not os.path.isdir(image_output_dir): os.mkdir(image_output_dir) test_logger.info('Copying over image files...') for image_path in glob(os.path.join(image_input_dir, '*')): _, image_name = os.path.split(image_path) shutil.copyfile(image_path, os.path.join(image_output_dir, image_name)) test_logger.info('Done') # Run each on of the tutorials with each supported hardware # configuration for that tutorial and export the output # to the output directory. # to keep track of test name and output for email tests = {} # to keep track of number of fails/run summary = {} summary['all'] = {} summary['all']['failed'] = 0 summary['all']['run'] = 0 results = [] test_logger.info("num hw: {}".format(num_hardware)) with ProcessPoolExecutor(max_workers=num_hardware) as nb_pool: test_future = { nb_pool.submit(run_test_hw_config, i, cw_dir, config, hw_locations[i], loggers[i]): i for i in range(num_hardware) } for future in as_completed(test_future): hw_summary, hw_tests = future.result() summary['all']['failed'] += hw_summary['failed'] summary['all']['run'] += hw_summary['run'] index = test_future[future] summary[str(index)] = { 'failed': hw_summary['failed'], 'run': hw_summary['run'] } # summary[str(index)]['failed'] += hw_summary['failed'] # summary[str(index)]['run'] += hw_summary['run'] tests.update(hw_tests) with open("config_{}_log.txt".format(index), 'w') as f: for header in hw_tests: f.write("Test {}, output:\n{}".format( header, hw_tests[header])) # for i in range(num_hardware): # test_logger.debug("Running hw") # results.append(nb_pool.apply_async(run_test_hw_config, args=(i, config))) # try: # for index, result in enumerate(results): # hw_summary, hw_tests = result.get() # summary['all']['failed'] += hw_summary['failed'] # summary['all']['run'] += hw_summary['run'] # summary[str(index)] = {'failed': hw_summary['failed'], 'run': hw_summary['run']} # # summary[str(index)]['failed'] += hw_summary['failed'] # # summary[str(index)]['run'] += hw_summary['run'] # tests.update(hw_tests) # with open("config_{}_log.txt".format(index), 'w') as f: # for header in hw_tests: # f.write("Test {}, output:\n{}".format(header, hw_tests[header])) # except Exception as e: # nb_pool.terminate() # test_logger.error(e) try: shutil.rmtree('projects') except FileNotFoundError: pass return summary, tests