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 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 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 main(): parser = argparse.ArgumentParser( description= 'Load OpenTitan Bitstream & Software to ChipWhisperer CW310 FPGA Board' ) parser.add_argument('--bitstream', '-b', metavar='bitstream', type=str, help='Path to the FPGA .bit file to load', default=None) parser.add_argument('--firmware', '-f', metavar='firmware', type=str, help='Path to the software .bin file to load', default=None) parser.add_argument('--set-pll-defaults', action='store_true', help='Program on-board PLL with defaults', default=False) args = parser.parse_args() print("CW310 Loader: Attemping to find CW310 FPGA Board:") if args.bitstream: print(" Using bitstream :{}".format(args.bitstream)) else: print(" No bitstream specified") target = cw.target(None, CW310, bsfile=args.bitstream, slurp=False) print("CW310 Board Found:") if args.set_pll_defaults: print("Configuring PLL, setting as default") target.pll.pll_enable_set(True) target.pll.pll_outenable_set(False, 0) # Note: 1 and 2 seem to be reversed. target.pll.pll_outenable_set(True, 1) target.pll.pll_outenable_set(False, 2) # Note: both 1 and 2 need to be set, even if only 1 is enabled. target.pll.pll_outfreq_set(100E6, 1) target.pll.pll_outfreq_set(100E6, 2) target.pll.pll_writedefaults() if args.firmware: print("INFO: Programming firmware file: {}".format(args.firmware)) prog = cw_spiflash.SPIProgrammer(args.firmware, "CW310") prog.run(target) print("Loading done.")
def initialize_target(self, scope, fw_programmer, baudrate): """Loads firmware image and initializes test target.""" fw_programmer.run(self.fpga) time.sleep(0.5) target = cw.target(scope) target.output_len = 16 target.baud = baudrate target.flush() return 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 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 __init__(self, target, scope, defines_files=None, bs='', force_bitfile=False): """ Args: target: SimpleSerial target scope: CW scope naeusb: NewAE USB interface platform (string): CW305 or CW610 (PhyWhisperer) defines_files (list of 2 strings): path to defines_trace.v and defines_pw.v """ super().__init__() self._trace_port_width = 4 self._base_target_clock = 7.384e6 self._base_baud = 38400 self._usb_clock = 96e6 self._uart_clock = self._usb_clock * 2 self.expected_verilog_defines = 107 self.swo_mode = False self.board_rev = 4 self._scope = scope # Detect whether we exist on CW305 or CW610 based on the target we're given: if target._name == 'Simple Serial': self.platform = 'CW610' self._ss = target self._naeusb = NAEUSB() self._naeusb.con(idProduct=[0xC610]) # we're using the CW NAEUSB, which has no knowledge of PW firmware, so let's manually # check the FW version here: fw_latest = [1, 1] if self._naeusb.readFwVersion()[0] < fw_latest[0]: logging.warning( 'Your PhyWhisperer firmware is outdated - latest is %d.%d' % (fw_latest[0], fw_latest[1]) + '. Suggested to update firmware, as you may experience errors.' ) self._fpga = FPGA(self._naeusb) if not self._fpga.isFPGAProgrammed() or force_bitfile: if not bs: bs = pkg_resources.resource_filename( 'chipwhisperer', 'hardware/firmware/tracewhisperer_top.bit') self._fpga.FPGAProgram(open(bs, 'rb'), exceptOnDoneFailure=False) else: self.platform = 'CW305' self._ss = cw.target(scope) self._naeusb = target._naeusb self.slurp_defines(defines_files) self._set_defaults()
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 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 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 cw_set_params(scope, ftarget, frequency=20E6): # Disable all the clocks on the FPGA ftarget.vccint_set(1.0) ftarget.pll.pll_enable_set(True) ftarget.pll.pll_outenable_set(False, 0) ftarget.pll.pll_outenable_set(True, 1) ftarget.pll.pll_outenable_set(False, 2) ftarget.pll.pll_outfreq_set(frequency, 1) # 1ms is plenty of idling time ftarget.clkusbautooff = False ftarget.clksleeptime = 1 # ensure ADC is locked: scope.clock.reset_adc() assert (scope.clock.adc_locked), "ADC failed to lock" fpga_io = ftarget.gpio_mode() scope.gain.gain = 25 scope.adc.basic_mode = "rising_edge" scope.adc.timeout = 0.1 scope.clock.clkgen_src = "system" scope.clock.adc_src = "clkgen_x4" scope.clock.extclk_freq = frequency scope.clock.clkgen_freq = frequency scope.io.hs2 = "clkgen" # Clock glitching is disabled by default scope.io.tio1 = "serial_rx" scope.io.tio2 = "serial_tx" scope.trigger.triggers = "tio4" scope.io.glitch_lp = False scope.glitch.clk_src = "clkgen" # set glitch input clock scope.glitch.output = "clock_xor" # glitch_out = clk ^ glitch scope.glitch.trigger_src = "ext_single" # glitch only after scope.arm() called target = cw.target(scope) return (target, fpga_io)
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 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)
import numpy as np import chipwhisperer as cw # Setup our capture and target boards. ######################################## scope = cw.scope() scope.default_setup() target = cw.target(scope, cw.targets.SimpleSerial2, flush_on_err=False) ######################################## # Reprogram the target ######################################## import os from chipwhisperer.capture.api.programmers import STM32FProgrammer # Initiate a new STM32F Program # STM32 being the ARM microcontroller that we are using # https://en.wikipedia.org/wiki/STM32#STM32_F3 program = STM32FProgrammer # Get the path to the current folder # Adjust accordingly aes_firmware_dir = os.path.dirname(os.path.realpath(__file__)) aes_hex_path = os.path.join(aes_firmware_dir, r"simpleserial-target-CWLITEARM.hex") # Apply the program to the actual target # This allows us to run the hex code on the microcontroller cw.program_target(scope, program, aes_hex_path) ######################################## # Capture a trace of our binary
RESTARTED = 6 CW_SYSCLK_FREQ = 96000000 VITA_CLK_FREQ = 12000000 MIN_OFFSET = 40780 MAX_OFFSET = 40880 MIN_WIDTH = 55 MAX_WIDTH = 65 VITA_UART0_BAUD = 115200 TIME_RESET_HOLD = 0 OFFSET_STEP = 1 WIDTH_STEP = 1 logging.basicConfig(level=logging.WARN) scope = cw.scope() target = cw.target(scope, cwtarget) # setup parameters needed for glitch the stm32f scope.glitch.clk_src = 'clkgen' scope.clock.clkgen_freq = VITA_CLK_FREQ scope.io.tio1 = "serial_rx" scope.io.tio2 = "serial_tx" # setup MMC trigger to look for READ_SINGLE_BLOCK of 0x0 response mmctrigger = scope.mmcTrigger mmctrigger.setMatchCmd(True) mmctrigger.setCmdIndex(MMCPacket.Cmd.READ_SINGLE_BLOCK.value) mmctrigger.setDirection(2) mmctrigger.setDataCompareOp(1)
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()
def __init__(self): super().__init__() self.platformname = "cw" self.scope = cw.scope() self.target = cw.target(self.scope) self.scope.default_setup()
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 target.go_cmd = ""
PINS_TRIGGER = PINS_NRST PINS_TRIGGER_MODE = "rising_edge" # 0.39*6 is powerful? #width_range = Range(-40, 40, 0.39) #offset_range = Range(10, 39+0.39, 0.39*5) width_range = Range(0.39, 0.39 * 2, 0.39) #-10.9375+0.39 offset_range = Range(10, 10 + 0.39, 0.39 * 5) ext_offset_range = Range( 13, 20, 1 ) # 166000 - 168300 is ~30pages, 20000 is ~2 pages, 10000 is ~1. 13-20 is consistent, 3280, 4768, 4827? 221000 idk, 303000 might be 9, 1210000 is about 42, 1240000 is too far? 1240000, 1240000+30000 repeat_range = Range(1, 15, 1) # Set up scope scope = cw.scope() target = cw.target(scope, cw.targets.SimpleSerial) target.baud = 115200 scope.default_setup() # Glitch triggering init scope.glitch.clk_src = "clkgen" scope.glitch.output = "glitch_only" scope.glitch.trigger_src = "ext_single" scope.glitch.width = width_range.min scope.glitch.offset = offset_range.min scope.glitch.repeat = repeat_range.min scope.glitch.ext_offset = ext_offset_range.min scope.glitch.width_fine = -20 scope.glitch.arm_timing = "before_scope"
def cw_lite_firmware_update_automatically(): scope = cw.scope() _ = cw.target(scope) programmer = cw.SAMFWLoader(scope=scope) programmer.auto_program() pass
def setUp(self): logging.basicConfig(level=logging.INFO) self.scope = cw.scope() self.target = cw.target(self.scope)