scope.io.tio2 = "serial_tx"
scope.io.hs2 = "clkgen"
scope.glitch.output = "glitch_only"
scope.io.glitch_lp = False
scope.io.glitch_hp = True
print(scope.io.glitch_lp)
print(scope.io.glitch_hp)
target.go_cmd = ""
target.key_cmd = ""

print("Erase target...")

# program the XMEGA with the built hex file
# programmer = AVRProgrammer()
programmer = XMEGAProgrammer()
programmer.scope = scope
programmer._logging = None
programmer.find()
programmer.erase()

print("Programming...")

# programmer.program("~/software/chipwhisperer/hardware/victims/firmware/glitch-simple/glitchsimple-CW304.hex", memtype="flash")
programmer.program("glitchsimple.hex", memtype="flash", verify=False)
programmer.close()

scope.glitch.trigger_src = 'ext_single'

traces = []
outputs = []
widths = []
    def test_tutorial_B6(self):
        scope = self.scope
        target = self.target

        programmer = XMEGAProgrammer()
        programmer.scope = scope
        programmer._logging = None
        programmer.find()
        programmer.erase()
        aes_firmware_dir = os.path.join(FIRMWARE_DIR, 'simpleserial-aes')
        aes_hex = os.path.join(aes_firmware_dir, r"simpleserial-aes-CW303.hex")
        programmer.program(aes_hex, memtype="flash", verify=True)
        programmer.close()

        # setup scope parameters
        scope.gain.gain = 45
        scope.adc.samples = 3000
        scope.adc.offset = 1250
        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"

        ktp = AcqKeyTextPattern_Basic(target=target)

        traces = []
        textin = []
        N = 100 # Number of traces
        print('Capturing traces...')
        target.init()
        for i in tqdm(range(N)):
            key, text = ktp.newPair() # manual creation of a key, text pair can be substituted here
            textin.append(text)

            target.reinit()

            target.setModeEncrypt() # only does something for targets that support it
            target.loadEncryptionKey(key)
            target.loadInput(text)

            # run aux stuff that should run before the scope arms here

            scope.arm()

            # run aux stuff that should run after the scope arms here

            target.go()
            timeout=50
            # wait for target to finish
            while target.isDone() is False and timeout:
                timeout -= 1
                time.sleep(0.01)

            try:
                ret = scope.capture()
                if ret:
                    logging.warning('Timeout happened during acquisition')
            except IOError as e:
                logging.error('IOError: %s' % str(e))

            # run aux stuff that should happen after trace here
            _ = target.readOutput() # for keep the v1.1 protocol working
            traces.append(scope.getLastTrace())

        knownkey = key
        pt = np.asarray(textin)
        traces = np.asarray(traces)
        numtraces = np.shape(traces)[0]
        numpoint = np.shape(traces)[1]

        bestguess = [0] * 16
        pge = [256] * 16
        print("Attacking subkeys...")
        for bnum in tqdm(range(0, 16)):
            cpaoutput = [0] * 256
            maxcpa = [0] * 256
            for kguess in range(0, 256):
                #print("Subkey %2d, hyp = %02x: " % (bnum, kguess), end='')

                # Initialize arrays & variables to zero
                sumnum = np.zeros(numpoint)
                sumden1 = np.zeros(numpoint)
                sumden2 = np.zeros(numpoint)

                hyp = np.zeros(numtraces)
                for tnum in range(0, numtraces):
                    hyp[tnum] = self.HW[self.intermediate(pt[tnum][bnum], kguess)]

                # Mean of hypothesis
                meanh = np.mean(hyp, dtype=np.float64)

                # Mean of all points in trace
                meant = np.mean(traces, axis=0, dtype=np.float64)

                # For each trace, do the following
                for tnum in range(0, numtraces):
                    hdiff = (hyp[tnum] - meanh)
                    tdiff = traces[tnum, :] - meant

                    sumnum = sumnum + (hdiff * tdiff)
                    sumden1 = sumden1 + hdiff * hdiff
                    sumden2 = sumden2 + tdiff * tdiff

                cpaoutput[kguess] = sumnum / np.sqrt(sumden1 * sumden2)
                maxcpa[kguess] = max(abs(cpaoutput[kguess]))

                #print(maxcpa[kguess])

            bestguess[bnum] = np.argmax(maxcpa)

            cparefs = np.argsort(maxcpa)[::-1]

            # Find PGE
            pge[bnum] = list(cparefs).index(knownkey[bnum])

        print("Best Key Guess: ", end="")
        for b in bestguess: print("%02x " % b, end="")

        print("")
        print("PGE: ", end="")
        for b in pge: print("%02d " % b, end="")
        self.assertLess(sum(pge), 5)
Exemple #3
0
    def test_TutorialB5(self):
        self.aes_firmware_dir = os.path.join(FIRMWARE_DIR, "simpleserial-aes")

        # Build firmware
        logging.info('Building firmware from make file')
        call = ["make", "--directory", self.aes_firmware_dir, "PLATFORM=CW303"]
        logging.info(call)
        exit_code = subprocess.check_call(call)
        if exit_code == 0:
            logging.info('Finished building firmware')
        else:
            logging.error('Build Failed with exit code {}'.format(exit_code))

        # create capture gui
        self.auto_ui = test_tools.FakeUI()
        self.auto_ui.create_capture()
        capture_gui = self.auto_ui.capture.gui

        # TODO use the created project (currently cause PyQtGraph error)

        # connect scope and target
        logging.info('Executing "connect_cwlite_simpleserial.py"')
        connect_cwlite_simpleserial = os.path.join(
            CAPTURE_SCRIPTS_DIR, "connect_cwlite_simpleserial.py")
        capture_gui.execute(script_path=connect_cwlite_simpleserial)
        self.auto_ui.updateUI()
        logging.info('Finished executing "connect_cwlite_simpleserial.py"')

        # program the target with the built firmware
        programmer = XMEGAProgrammer()
        programmer.scope = capture_gui.scope
        programmer._logging = None
        programmer.find()
        programmer.erase()
        aes_hex = os.path.join(self.aes_firmware_dir,
                               r"simpleserial-aes-CW303.hex")
        programmer.program(aes_hex, memtype="flash", verify=True)
        programmer.close()

        # Execute the setup script for simple serial aes
        logging.info('Executing "setup_cwlite_xmega_aes.py"')
        setup_cwlite_xmega_aes = os.path.join(CAPTURE_SCRIPTS_DIR,
                                              "setup_cwlite_xmega_aes.py")
        capture_gui.execute(script_path=setup_cwlite_xmega_aes)
        self.auto_ui.updateUI()
        logging.info('Finished executing "setup_cwlite_xmega.py"')

        # Create a basic key text pattern
        logging.info('Creating key text pattern')
        ktp = AcqKeyTextPattern_Basic()
        logging.info('Finished creating key text pattern')

        # Capture traces
        logging.info('Capturing traces')
        capture_gui.execute(string='self.api.setNumTraces(60)')
        capture_gui.doCapture(capture_gui.captureM)
        self.auto_ui.updateUI()
        logging.info('Finished capturing traces')

        # Close the capture gui and open the analyzer gui
        logging.info('Closing capture and opening analyzer')
        self.auto_ui.close_capture()
        self.auto_ui.create_analyzer()
        analyzer_gui = self.auto_ui.analyzer.gui
        logging.info('Finished closing capture and opening analyzer')

        # TODO Open the project in the analyzer gui
        #logging.info('Opening project')
        #analyzer_gui.project = self.project
        #logging.info('Finished opening project')

        # Perform the attack
        attack_cpa_script = os.path.join(ANALYZER_SCRIPTS_DIR, "attack_cpa.py")
        logging.info('Executing attack script {}'.format(attack_cpa_script))
        analyzer_gui.execute(script_path=attack_cpa_script)
        self.auto_ui.updateUI()
        logging.info('Finished executing attack script')

        # check if the key is the expected key
        result_subkeys = self.auto_ui.analyzer.gui.results_table.sub_key_row(1)
        result_key = u' '.join(result_subkeys)
        actual_key = ktp.initkey

        logging.info('Actual Key: {}'.format(actual_key))
        logging.info('Result Key: {}'.format(result_key))

        if result_key == actual_key:
            logging.info('Sucess, keys match')
        else:
            logging.error('Keys do not match')
        self.assertEqual(result_key, actual_key)

        # close the analayzer
        self.auto_ui.close_analyzer()
    def test_tutorial_A2(self):
        # build the firmware
        self.glitch_simple_firmware_dir = os.path.join(FIRMWARE_DIR, "glitch-simple")

        # Build firmware
        logging.info('Building firmware from make file')
        call = ["make", "--directory", self.glitch_simple_firmware_dir, "PLATFORM=CW303"]
        logging.info(call)
        exit_code = subprocess.check_call(call)
        if exit_code == 0:
            logging.info('Finished building firmware')
        else:
            logging.error('Build Failed with exit code {}'.format(exit_code))

        # connect the scope and target
        scope = self.scope
        target = self.target

        # program the XMEGA with the built hex file
        programmer = XMEGAProgrammer()
        programmer.scope = scope
        programmer._logging = None
        programmer.find()
        programmer.erase()
        glitch_simple_hex = os.path.join(self.glitch_simple_firmware_dir, r"glitchsimple-CW303.hex")
        programmer.program(glitch_simple_hex, memtype="flash", verify=True)
        programmer.close()

        # setup parameters needed for glitch the XMEGA
        scope.glitch.clk_src = 'clkgen'

        scope.gain.gain = 45
        scope.adc.samples = 3000
        scope.adc.offset = 0
        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 = "glitch"

        target.go_cmd = ""
        target.key_cmd = ""

        # set glitch parameters
        # trigger glitches with external trigger
        scope.glitch.trigger_src = 'ext_single'
        scope.glitch.repeat = 105

        traces = []
        outputs = []

        # named tuples to make it easier to change the scope of the test
        Range = namedtuple('Range', ['min', 'max', 'step'])
        width_range = Range(-10, 10, 1.7)
        offset_range = Range(-10, 10, 1.7)

        # glitch cycle
        scope.glitch.width = width_range.min
        success = False
        target.init()
        while scope.glitch.width < width_range.max and not success:
            scope.glitch.offset = offset_range.min
            while scope.glitch.offset < offset_range.max and not success:
                # call before trace things here
                # flush the garbage from the computer's target read buffer
                target.ser.flush()

                # target enters reset mode
                scope.io.pdic = 'low'

                # run aux stuff that should run before the scope arms here

                scope.arm()

                # run aux stuff that should run after the scope arms here

                # target exits reset mode
                scope.io.pdic = 'high'

                timeout = 50
                # wait for target to finish
                while target.isDone() is False and timeout:
                    timeout -= 1
                    time.sleep(0.01)

                try:
                    ret = scope.capture()
                    if ret:
                        logging.warning('Timeout happened during acquisition')
                except IOError as e:
                    logging.error('IOError: %s' % str(e))

                #textout = target.readOutput() # raises invalid literal for int base 16

                # get the results
                trace = scope.getLastTrace()
                output = target.ser.read(target.output_len * 2, timeout=10)
                traces.append(trace)
                outputs.append(output)
                if '1234' in repr(output):
                    success = True

                # run aux stuff that should happen after trace here
                scope.glitch.offset += offset_range.step
            scope.glitch.width += width_range.step
        self.assertTrue(success, 'There is no "1234" in the outputs, maybe glitch1() in c file is not active')