Beispiel #1
0
class CPAProgressive(AutoScript, QObject):
    """
    CPA Attack done as a loop, but using an algorithm which can progressively add traces & give output stats
    """
    paramListUpdated = Signal(list)

    def __init__(self, targetModel, leakageFunction, showScriptParameter=None, parent=None):
        super(CPAProgressive, self).__init__()

        resultsParams = [{'name':'Iteration Mode', 'key':'itmode', 'type':'list', 'values':{'Depth-First':'df', 'Breadth-First':'bf'}, 'value':'bf'},
                         {'name':'Skip when PGE=0', 'key':'checkpge', 'type':'bool', 'value':False},
                         ]
        self.params = Parameter.create(name='Progressive CPA', type='group', children=resultsParams)
        if showScriptParameter is not None:
            self.showScriptParameter = showScriptParameter
            # print self.showScriptParameter
        ExtendedParameter.setupExtended(self.params, self)

        self.model = targetModel
        self.leakage = leakageFunction
        self.sr = None

        self.stats = DataTypeDiffs()
        self.updateScript()

    def updateScript(self, ignored=None):
        # self.addFunction('init', 'setReportingInterval', '%d' % self.findParam('reportinterval').value())
        pass

    def paramList(self):
        return [self.params]

    def setTargetBytes(self, brange):
        self.brange = brange

    def setReportingInterval(self, ri):
        self._reportingInterval = ri

    def addTraces(self, tracedata, tracerange, progressBar=None, pointRange=None):
        brange=self.brange

        self.all_diffs = range(0,16)

        numtraces = tracerange[1] - tracerange[0]

        if progressBar:
            pbcnt = 0
            progressBar.setMinimum(0)
            progressBar.setMaximum(len(brange) * 256 * (numtraces / self._reportingInterval + 1))

        pbcnt = 0
        cpa = [None]*(max(brange)+1)
        for bnum in brange:
            cpa[bnum] = CPAProgressiveOneSubkey()

        brangeMap = [None]*(max(brange)+1)
        i = 1
        for bnum in brange:
            brangeMap[bnum] = i
            i += 1

        skipPGE = False  # self.findParam('checkpge').value()
        bf = True  # self.findParam('itmode').value() == 'bf'

        #bf specifies a 'breadth-first' search. bf means we search across each
        #subkey by only the amount of traces specified. Depth-First means we
        #search each subkey completely, then move onto the next.
        if bf:
            brange_df = [0]
            brange_bf = brange
        else:
            brange_bf = [0]
            brange_df = brange


        for bnum_df in brange_df:
            tstart = 0
            tend = self._reportingInterval

            while tstart < numtraces:
                if tend > numtraces:
                    tend = numtraces

                if tstart > numtraces:
                    tstart = numtraces


                data = []
                textins = []
                textouts = []
                knownkeys = []
                for i in range(tstart, tend):

                    # Handle Offset
                    tnum = i + tracerange[0]

                    d = tracedata.getTrace(tnum)

                    if d is None:
                        continue

                    data.append(d)
                    textins.append(tracedata.getTextin(tnum))
                    textouts.append(tracedata.getTextout(tnum))
                    knownkeys.append(tracedata.getKnownKey(tnum))

                traces = np.array(data)
                textins = np.array(textins)
                textouts = np.array(textouts)
                # knownkeys = np.array(knownkeys)

                for bnum_bf in brange_bf:

                    if bf:
                        bnum = bnum_bf
                    else:
                        bnum = bnum_df


                    skip = False
                    if (self.stats.simplePGE(bnum) != 0) or (skipPGE == False):
                        if isinstance(pointRange, list):
                            bptrange = pointRange[bnum]
                        else:
                            bptrange = pointRange
                        (data, pbcnt) = cpa[bnum].oneSubkey(bnum, bptrange, traces, tend - tstart, textins, textouts, knownkeys, progressBar, self.model, self.leakage, cpa[bnum].modelstate, pbcnt)
                        self.stats.updateSubkey(bnum, data, tnum=tend)
                    else:
                        skip = True

                    if progressBar.wasSkipped() or skip:
                        progressBar.clearSkipped()
                        pbcnt = brangeMap[bnum] * 256 * (numtraces / self._reportingInterval + 1)

                        if bf is False:
                            tstart = numtraces

                tend += self._reportingInterval
                tstart += self._reportingInterval

                if self.sr is not None:
                    self.sr()

    def getStatistics(self):
        return self.stats

    def setStatsReadyCallback(self, sr):
        self.sr = sr

    def processKnownKey(self, inpkey):
        if hasattr(self.model, 'processKnownKey'):
            return self.model.processKnownKey(self.leakage, inpkey)
        else:
            return inpkey
class CPAProgressive(AutoScript, QObject):
    """
    CPA Attack done as a loop, but using an algorithm which can progressively add traces & give output stats
    """
    paramListUpdated = Signal(list)

    def __init__(self, targetModel, leakageFunction, showScriptParameter=None, parent=None):
        super(CPAProgressive, self).__init__()

        resultsParams = [{'name':'Iteration Mode', 'key':'itmode', 'type':'list', 'values':{'Depth-First':'df', 'Breadth-First':'bf'}, 'value':'bf'},
                         {'name':'Skip when PGE=0', 'key':'checkpge', 'type':'bool', 'value':False},
                         ]
        self.params = Parameter.create(name='Progressive CPA', type='group', children=resultsParams)
        if showScriptParameter is not None:
            self.showScriptParameter = showScriptParameter
            # print self.showScriptParameter
        ExtendedParameter.setupExtended(self.params, self)

        self.model = targetModel
        self.leakage = leakageFunction
        self.sr = None

        self.stats = DataTypeDiffs()
        self.updateScript()

    def updateScript(self, ignored=None):
        # self.addFunction('init', 'setReportingInterval', '%d' % self.findParam('reportinterval').value())
        pass

    def paramList(self):
        return [self.params]

    def setTargetBytes(self, brange):
        self.brange = brange

    def setKeyround(self, keyround):
        self.keyround = keyround

    def setDirection(self, dir):
        self._direction = dir

    def setModeltype(self, modeltype):
        self.modeltype = modeltype

    def setReportingInterval(self, ri):
        self._reportingInterval = ri

    def addTraces(self, traces, plaintexts, ciphertexts, knownkeys=None, progressBar=None, pointRange=None):
        keyround=self.keyround
        brange=self.brange

        traces_all = np.array(traces)
        plaintexts =np.array(plaintexts)
        ciphertexts =np.array(ciphertexts)

        foundkey = []

        self.all_diffs = range(0,16)

        numtraces = len(traces_all[:,0])

        if progressBar:
            pbcnt = 0
            progressBar.setMinimum(0)
            progressBar.setMaximum(len(brange) * 256 * (numtraces / self._reportingInterval + 1))

        pbcnt = 0
        #r = Parallel(n_jobs=4)(delayed(traceOneSubkey)(bnum, pointRange, traces_all, numtraces, plaintexts, ciphertexts, keyround, modeltype, progressBar, self.model, pbcnt) for bnum in brange)
        #self.all_diffs, pb = zip(*r)
        #pbcnt = 0
        cpa = [None]*(max(brange)+1)
        for bnum in brange:
            cpa[bnum] = CPAProgressiveOneSubkey()

        brangeMap = [None]*(max(brange)+1)
        i = 1
        for bnum in brange:
            brangeMap[bnum] = i
            i += 1

        skipPGE = False  # self.findParam('checkpge').value()
        bf = True  # self.findParam('itmode').value() == 'bf'

        #bf specifies a 'breadth-first' search. bf means we search across each
        #subkey by only the amount of traces specified. Depth-First means we
        #search each subkey completely, then move onto the next.
        if bf:
            brange_df = [0]
            brange_bf = brange
        else:
            brange_bf = [0]
            brange_df = brange


        for bnum_df in brange_df:
            #CPAMemoryOneSubkey
            #CPASimpleOneSubkey
            #(self.all_diffs[bnum], pbcnt) = sCPAMemoryOneSubkey(bnum, pointRange, traces_all, numtraces, plaintexts, ciphertexts, keyround, modeltype, progressBar, self.model, pbcnt)

            tstart = 0
            tend = self._reportingInterval

            while tstart < numtraces:
                if tend > numtraces:
                    tend = numtraces

                if tstart > numtraces:
                    tstart = numtraces


                for bnum_bf in brange_bf:

                    if bf:
                        bnum = bnum_bf
                    else:
                        bnum = bnum_df


                    skip = False
                    if (self.stats.simplePGE(bnum) != 0) or (skipPGE == False):
                        (data, pbcnt) = cpa[bnum].oneSubkey(bnum, pointRange, traces_all[tstart:tend], tend - tstart, plaintexts[tstart:tend], ciphertexts[tstart:tend], keyround, self.leakage, progressBar, self.model, pbcnt, self._direction, knownkeys)
                        self.stats.updateSubkey(bnum, data, tnum=tend)
                    else:
                        skip = True

                    if progressBar.wasSkipped() or skip:
                        progressBar.clearSkipped()
                        pbcnt = brangeMap[bnum] * 256 * (numtraces / self._reportingInterval + 1)

                        if bf is False:
                            tstart = numtraces

                tend += self._reportingInterval
                tstart += self._reportingInterval

                if self.sr is not None:
                    self.sr()

    def getStatistics(self):
        return self.stats

    def setStatsReadyCallback(self, sr):
        self.sr = sr
class ProfilingTemplate(AutoScript, QObject):
    """
    Template Attack done as a loop, but using an algorithm which can progressively add traces & give output stats
    """
    paramListUpdated = Signal(list)
    notifyUser = Signal(str, str)

    def __init__(self, parent, showScriptParameter=None, tmanager=None, console=None):
        super(ProfilingTemplate, self).__init__()
        if console:
            self.console = console
        self.setParent(parent)
        self._tmanager = None
        self._project = None

        resultsParams = [{'name':'Load Template', 'type':'group', 'children':[
                            ]},
                         {'name':'Generate New Template', 'type':'group', 'children':[
                            {'name':'Trace Start', 'key':'tgenstart', 'value':0, 'type':'int', 'set':self.updateScript},
                            {'name':'Trace End', 'key':'tgenstop', 'value':self.parent().traceMax, 'type':'int', 'set':self.updateScript},
                            {'name':'POI Selection', 'key':'poimode', 'type':'list', 'values':{'TraceExplorer Table':0, 'Read from Project File':1}, 'value':0, 'set':self.updateScript},
                            {'name':'Read POI', 'type':'action', 'action':self.updateScript},
                            {'name':'Generate Templates', 'type':'action', 'action': lambda:self.runScriptFunction.emit("generateTemplates")}
                            ]},
                         ]
        self.params = Parameter.create(name='Template Attack', type='group', children=resultsParams)
        if showScriptParameter is not None:
            self.showScriptParameter = showScriptParameter
            # print self.showScriptParameter
        ExtendedParameter.setupExtended(self.params, self)

        self.addGroup("generateTemplates")

        self.sr = None

        self.stats = DataTypeDiffs()
        self.setProfileAlgorithm(TemplateBasic)

        # Not needed as setProfileAlgorithm calls this
        # self.updateScript()

    def log(self, s):
        if hasattr(self, 'console') and self.console:
            self.console.append(s)

    def setProfileAlgorithm(self, algo):
        self.profiling = algo()
        self.profiling.setTraceManager(self._tmanager)
        self.profiling.setProject(self._project)
        self.profiling.scriptsUpdated.connect(self.updateScript)
        self.updateScript()

    def updateScript(self, ignored=None):
       # self.addFunction('init', 'setReportingInterval', '%d' % self.findParam('reportinterval').value())

        ted = self.parent().parent().utilList[0].exampleScripts[0]

        self.addFunction('generateTemplates', 'initAnalysis', '', obj='userScript')
        self.addVariable('generateTemplates', 'tRange', '(%d, %d)' % (self.findParam('tgenstart').value(), self.findParam('tgenstop').value()))

        if self.findParam('poimode').value() == 0:
            self.addVariable('generateTemplates', 'poiList', '%s' % ted.poi.poiArray)
            self.addVariable('generateTemplates', 'partMethod', '%s()' % ted.partObject.partMethod.__class__.__name__)
            self.importsAppend("from chipwhisperer.analyzer.utils.Partition import %s" % ted.partObject.partMethod.__class__.__name__)
        else:
            poidata = self.loadPOIs()[-1]
            self.addVariable('generateTemplates', 'poiList', '%s' % poidata["poi"])
            self.addVariable('generateTemplates', 'partMethod', '%s()' % poidata["partitiontype"])
            self.importsAppend("from chipwhisperer.analyzer.utils.Partition import %s" % poidata["partitiontype"])

        self.addFunction('generateTemplates', 'profiling.generate', 'tRange, poiList, partMethod', 'templatedata')

        #Save template data to project
        self.addFunction('generateTemplates', 'saveTemplatesToProject', 'tRange, templatedata', 'tfname')

        self.scriptsUpdated.emit()

    def paramList(self):
        return [self.params]

    def traceLimitsChanged(self, traces, points):
        tstart = self.findParam('tgenstart')
        tend = self.findParam('tgenstop')
        tstart.setLimits((0, traces))
        tend.setValue(traces)
        tend.setLimits((1, traces))


    def setByteList(self, brange):
        self.brange = brange

    def setKeyround(self, keyround):
        self.keyround = keyround

    def setReportingInterval(self, intv):
        self._reportinginterval = intv

    def traceManager(self):
        return self._tmanager

    def setTraceManager(self, tmanager):
        self._tmanager = tmanager
        # Set for children
        self.profiling.setTraceManager(tmanager)

    def setProject(self, proj):
        self._project = proj
        # Set for children
        self.profiling.setProject(proj)

    def project(self):
        if self._project is None:
            self.setProject(self.parent().project())
        return self._project

    def saveTemplatesToProject(self, trange, templatedata):
        cfgsec = self.project().addDataConfig(sectionName="Template Data", subsectionName="Templates")
        cfgsec["tracestart"] = trange[0]
        cfgsec["traceend"] = trange[1]
        cfgsec["poi"] = templatedata["poi"]
        cfgsec["partitiontype"] = templatedata["partitiontype"]

        fname = self.project().getDataFilepath('templates-%s-%d-%d.npz' % (cfgsec["partitiontype"], trange[0], trange[1]), 'analysis')

        # Save template file
        np.savez(fname["abs"], **templatedata)  # mean=self.profiling.templateMeans, cov=self.profiling.templateCovs)
        cfgsec["filename"] = fname["rel"]

        print "Saved template to: %s" % fname["abs"]

        return fname["abs"]

    def loadTemplatesFromProject(self):
        # Load Template
        foundsecs = self.parent().project().getDataConfig(sectionName="Template Data", subsectionName="Templates")
        templates = []

        for f in foundsecs:
            fname = self.parent().project().convertDataFilepathAbs(f["filename"])
            t = np.load(fname)
            templates.append(t)

            # Validate in case someone tries to change via project file
            if f["partitiontype"] != t["partitiontype"]:
                print "WARNING: PartitionType for template from .npz file (%s) differs from project file (%s). npz file being used."

            if (strListToList(str(f["poi"])) != t["poi"]).any():
                print "WARNING: POI for template from .npz file (%s) differs from project file (%s). npz file being used."

        return templates

    def loadPOIs(self):
        section = self.project().getDataConfig("Template Data", "Points of Interest")

        poiList = []

        for s in section:
            poistr = str(s["poi"])
            poieval = strListToList(poistr)
            poiList.append(s.copy())
            poiList[-1]["poi"] = poieval

        return poiList

    def addTraces(self, traces, plaintexts, ciphertexts, knownkeys=None, progressBar=None, pointRange=None):

        if multivariate_normal is None:
            print "ERROR: Version of SciPy too old, require > 0.14, have %s" % (scipy.version.version)
            print "       Please update your version of SciPy to support this attack"
            return

        # Hack for now - just use last template found
        template = self.loadTemplatesFromProject()[-1]
        pois = template["poi"]
        numparts = len(template['mean'][0])
        results = np.zeros((16, 256))

        tdiff = self._reportinginterval

        if progressBar:
            progressBar.setMinimum(0)
            progressBar.setMaximum(16 * len(traces))
            pcnt = 0

        for tnum in range(0, len(traces)):
            for bnum in range(0, 16):
                newresultsint = [multivariate_normal.logpdf(traces[tnum][pois[bnum]], mean=template['mean'][bnum][i], cov=np.diag(template['cov'][bnum][i])) for i in range(0, numparts)]

                ptype = template["partitiontype"]

                if ptype == "PartitionHWIntermediate":
                    newresults = []
                    # Map to key guess format
                    for i in range(0, 256):
                        # Get hypothetical hamming weight
                        # hypint = HypHW(plaintexts[tnum], None, i, bnum)
                        hypint = AESModel.leakage(plaintexts[tnum], ciphertexts[tnum], i, bnum, AESModel.LEAK_HW_SBOXOUT_FIRSTROUND, None)
                        newresults.append(newresultsint[ hypint ])
                elif ptype == "PartitionHDLastRound":
                    newresults = []
                    # Map to key guess format
                    for i in range(0, 256):
                        # Get hypothetical hamming distance
                        # hypint = HypHD(plaintexts[tnum], None, i, bnum)
                        # hypint = HypHD(None, ciphertexts[tnum], i, bnum)
                        hypint = AESModel.leakage(plaintexts[tnum], ciphertexts[tnum], i, bnum, AESModel.LEAK_HD_LASTROUND_STATE, None)
                        newresults.append(newresultsint[ hypint ])

                # TODO Temp
                elif ptype == "PartitionHDRounds":
                    newresults = []
                    # Map to key guess format
                    for i in range(0, 256):
                        # Get hypothetical hamming distance
                        # hypint = HypHD(plaintexts[tnum], None, i, bnum)
                        if bnum == 0:
                            hypint = getHW(plaintexts[tnum][bnum] ^ i)
                        else:
                            knownkey = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c]
                            s1 = plaintexts[tnum][bnum - 1] ^ knownkey[bnum - 1]
                            s2 = plaintexts[tnum][bnum] ^ i
                            hypint = getHW(s1 ^ s2)

                        newresults.append(newresultsint[ hypint ])
                else:
                    newresults = newresultsint

                results[bnum] += newresults
                self.stats.updateSubkey(bnum, results[bnum], tnum=(tnum + 1))

                if progressBar:
                    progressBar.setValue(pcnt)
                    progressBar.updateStatus((tnum, len(traces)), bnum)
                    pcnt += 1

                    if progressBar.wasCanceled():
                        raise KeyboardInterrupt


            # Do plotting if required
            if (tnum % tdiff) == 0 and self.sr:
                self.sr()

    def getStatistics(self):
        return self.stats

    def setStatsReadyCallback(self, sr):
        self.sr = sr
class ProfilingTemplate(AutoScript, QObject):
    """
    Template Attack done as a loop, but using an algorithm which can progressively add traces & give output stats
    """
    paramListUpdated = Signal(list)
    notifyUser = Signal(str, str)

    def __init__(self, parent, showScriptParameter=None, tmanager=None, console=None):
        super(ProfilingTemplate, self).__init__()
        if console:
            self.console = console
        self.setParent(parent)
        self._tmanager = None
        self._project = None

        resultsParams = [{'name':'Load Template', 'type':'group', 'children':[
                            ]},
                         {'name':'Generate New Template', 'type':'group', 'children':[
                            {'name':'Trace Start', 'key':'tgenstart', 'value':0, 'type':'int', 'set':self.updateScript},
                            {'name':'Trace End', 'key':'tgenstop', 'value':self.parent().traceMax, 'type':'int', 'set':self.updateScript},
                            {'name':'POI Selection', 'key':'poimode', 'type':'list', 'values':{'TraceExplorer Table':0, 'Read from Project File':1}, 'value':0, 'set':self.updateScript},
                            {'name':'Read POI', 'type':'action', 'action':self.updateScript},
                            {'name':'Generate Templates', 'type':'action', 'action': lambda:self.runScriptFunction.emit("generateTemplates")}
                            ]},
                         ]
        self.params = Parameter.create(name='Template Attack', type='group', children=resultsParams)
        if showScriptParameter is not None:
            self.showScriptParameter = showScriptParameter
            # print self.showScriptParameter
        ExtendedParameter.setupExtended(self.params, self)

        self.addGroup("generateTemplates")

        self.sr = None

        self.stats = DataTypeDiffs()
        self.setProfileAlgorithm(TemplateBasic)

        # Not needed as setProfileAlgorithm calls this
        # self.updateScript()

    def log(self, s):
        if hasattr(self, 'console') and self.console:
            self.console.append(s)

    def setProfileAlgorithm(self, algo):
        self.profiling = algo()
        self.profiling.setTraceManager(self._tmanager)
        self.profiling.setProject(self._project)
        self.profiling.scriptsUpdated.connect(self.updateScript)
        self.updateScript()

    def updateScript(self, ignored=None):
       # self.addFunction('init', 'setReportingInterval', '%d' % self.findParam('reportinterval').value())

        ted = self.parent().parent().utilList[0].exampleScripts[0]

        self.addFunction('generateTemplates', 'initAnalysis', '', obj='userScript')
        self.addVariable('generateTemplates', 'tRange', '(%d, %d)' % (self.findParam('tgenstart').value(), self.findParam('tgenstop').value()))

        if self.findParam('poimode').value() == 0:
            self.addVariable('generateTemplates', 'poiList', '%s' % ted.poi.poiArray)
            self.addVariable('generateTemplates', 'partMethod', '%s()' % ted.partObject.partMethod.__class__.__name__)
            self.importsAppend("from chipwhisperer.analyzer.utils.Partition import %s" % ted.partObject.partMethod.__class__.__name__)
        else:
            poidata = self.loadPOIs()[-1]
            self.addVariable('generateTemplates', 'poiList', '%s' % poidata["poi"])
            self.addVariable('generateTemplates', 'partMethod', '%s()' % poidata["partitiontype"])
            self.importsAppend("from chipwhisperer.analyzer.utils.Partition import %s" % poidata["partitiontype"])

        self.addFunction('generateTemplates', 'profiling.generate', 'tRange, poiList, partMethod', 'templatedata')

        #Save template data to project
        self.addFunction('generateTemplates', 'saveTemplatesToProject', 'tRange, templatedata', 'tfname')

        self.scriptsUpdated.emit()

    def paramList(self):
        return [self.params]

    def traceLimitsChanged(self, traces, points):
        tstart = self.findParam('tgenstart')
        tend = self.findParam('tgenstop')
        tstart.setLimits((0, traces))
        tend.setValue(traces)
        tend.setLimits((1, traces))


    def setByteList(self, brange):
        self.brange = brange

    def setKeyround(self, keyround):
        self.keyround = keyround

    def setReportingInterval(self, intv):
        self._reportinginterval = intv

    def setModeltype(self, modeltype):
        self.modeltype = modeltype

    def traceManager(self):
        return self._tmanager

    def setTraceManager(self, tmanager):
        self._tmanager = tmanager
        # Set for children
        self.profiling.setTraceManager(tmanager)

    def setProject(self, proj):
        self._project = proj
        # Set for children
        self.profiling.setProject(proj)

    def project(self):
        if self._project is None:
            self.setProject(self.parent().project())
        return self._project

    def saveTemplatesToProject(self, trange, templatedata):
        cfgsec = self.project().addDataConfig(sectionName="Template Data", subsectionName="Templates")
        cfgsec["tracestart"] = trange[0]
        cfgsec["traceend"] = trange[1]
        cfgsec["poi"] = templatedata["poi"]
        cfgsec["partitiontype"] = templatedata["partitiontype"]

        fname = self.project().getDataFilepath('templates-%s-%d-%d.npz' % (cfgsec["partitiontype"], trange[0], trange[1]), 'analysis')

        # Save template file
        np.savez(fname["abs"], **templatedata)  # mean=self.profiling.templateMeans, cov=self.profiling.templateCovs)
        cfgsec["filename"] = fname["rel"]

        print "Saved template to: %s" % fname["abs"]

        return fname["abs"]

    def loadTemplatesFromProject(self):
        # Load Template
        foundsecs = self.parent().project().getDataConfig(sectionName="Template Data", subsectionName="Templates")
        templates = []

        for f in foundsecs:
            fname = self.parent().project().convertDataFilepathAbs(f["filename"])
            t = np.load(fname)
            templates.append(t)

            # Validate in case someone tries to change via project file
            if f["partitiontype"] != t["partitiontype"]:
                print "WARNING: PartitionType for template from .npz file (%s) differs from project file (%s). npz file being used."

            if (strListToList(str(f["poi"])) != t["poi"]).any():
                print "WARNING: POI for template from .npz file (%s) differs from project file (%s). npz file being used."

        return templates

    def loadPOIs(self):
        section = self.project().getDataConfig("Template Data", "Points of Interest")

        poiList = []

        for s in section:
            poistr = str(s["poi"])
            poieval = strListToList(poistr)
            poiList.append(s.copy())
            poiList[-1]["poi"] = poieval

        return poiList

    def addTraces(self, traces, plaintexts, ciphertexts, knownkeys=None, progressBar=None, pointRange=None):

        # Hack for now - just use last template found
        template = self.loadTemplatesFromProject()[-1]
        pois = template["poi"]
        numparts = len(template['mean'][0])
        results = np.zeros((16, 256))

        tdiff = self._reportinginterval

        if progressBar:
            progressBar.setMinimum(0)
            progressBar.setMaximum(16 * len(traces))
            pcnt = 0

        for tnum in range(0, len(traces)):
            for bnum in range(0, 16):
                newresultsint = [multivariate_normal.logpdf(traces[tnum][pois[bnum]], mean=template['mean'][bnum][i], cov=np.diag(template['cov'][bnum][i])) for i in range(0, numparts)]

                ptype = template["partitiontype"]

                if ptype == "PartitionHWIntermediate":
                    newresults = []
                    # Map to key guess format
                    for i in range(0, 256):
                        # Get hypothetical hamming weight
                        hypint = HypHW(plaintexts[tnum], None, i, bnum)
                        newresults.append(newresultsint[ hypint ])
                elif ptype == "PartitionHDLastRound":
                    newresults = []
                    # Map to key guess format
                    for i in range(0, 256):
                        # Get hypothetical hamming distance
                        # hypint = HypHD(plaintexts[tnum], None, i, bnum)
                        hypint = HypHD(None, ciphertexts[tnum], i, bnum)
                        newresults.append(newresultsint[ hypint ])
                else:
                    newresults = newresultsint

                results[bnum] += newresults
                self.stats.updateSubkey(bnum, results[bnum], tnum=(tnum + 1))

                if progressBar:
                    progressBar.setValue(pcnt)
                    progressBar.updateStatus((tnum, len(traces)), bnum)
                    pcnt += 1

                    if progressBar.wasCanceled():
                        raise KeyboardInterrupt


            # Do plotting if required
            if (tnum % tdiff) == 0 and self.sr:
                self.sr()

    def getStatistics(self):
        return self.stats

    def setStatsReadyCallback(self, sr):
        self.sr = sr
class CPASimpleLoop(QObject):
    """
    CPA Attack done as a loop - the 'classic' attack provided for familiarity to textbook samples.
    This attack does not provide trace-by-trace statistics however, you can only gather results once
    all the traces have been run through the attack.
    """

    def __init__(self, targetModel, leakageFunction, showScriptParameter=None, parent=None):
        super(CPASimpleLoop, self).__init__()
        self.model = targetModel
        self.leakage = leakageFunction
        self.stats = DataTypeDiffs()
        self.modelstate = {"knownkey": None}

    def oneSubkey(
        self,
        bnum,
        pointRange,
        traces_all,
        numtraces,
        plaintexts,
        ciphertexts,
        knownkeys,
        progressBar,
        model,
        leakagetype,
        state,
        pbcnt,
    ):
        diffs = [0] * 256

        if pointRange == None:
            traces = traces_all
            # padbefore = 0
            # padafter = 0
        else:
            traces = np.array(traces_all[:, pointRange[0] : pointRange[1]])
            # padbefore = pointRange[0]
            # padafter = len(traces_all[0, :]) - pointRange[1]
            # print "%d - %d (%d %d)"%( pointRange[0],  pointRange[1], padbefore, padafter)

        # For each 0..0xFF possible value of the key byte
        for key in range(0, 256):
            # Initialize arrays & variables to zero
            sumnum = np.zeros(len(traces[0, :]))
            sumden1 = np.zeros(len(traces[0, :]))
            sumden2 = np.zeros(len(traces[0, :]))

            hyp = [0] * numtraces

            # Formula for CPA & description found in "Power Analysis Attacks"
            # by Mangard et al, page 124, formula 6.2.

            # Generate hypotheticals
            for tnum in range(numtraces):

                if len(plaintexts) > 0:
                    pt = plaintexts[tnum]
                else:
                    pt = []

                if len(ciphertexts) > 0:
                    ct = ciphertexts[tnum]
                else:
                    ct = []

                if knownkeys and len(knownkeys) > 0:
                    nk = knownkeys[tnum]
                else:
                    nk = None

                state["knownkey"] = nk

                hypint = model.leakage(pt, ct, key, bnum, leakagetype, state)

                hyp[tnum] = hypint

            hyp = np.array(hyp)

            # 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(numtraces):
                hdiff = hyp[tnum] - meanh
                tdiff = traces[tnum, :] - meant

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

            if progressBar:
                progressBar.setValue(pbcnt)
                # progressBar.setLabelText("Byte %02d: Hyp=%02x"%(bnum, key))
                pbcnt = pbcnt + 1
                if progressBar.wasCanceled():
                    raise KeyboardInterrupt

            diffs[key] = sumnum / np.sqrt(sumden1 * sumden2)

            # if padafter > 0:
            #    diffs[key] = np.concatenate([diffs[key], np.zeros(padafter)])

            # if padbefore > 0:
            #    diffs[key] = np.concatenate([np.zeros(padbefore), diffs[key]])

        return (diffs, pbcnt)

    def setTargetBytes(self, brange):
        self.brange = brange

    def setReportingInterval(self, ri):
        # Not used for simpleloop
        pass

    def addTraces(self, tracedata, tracerange, progressBar=None, pointRange=None, tracesLoop=None):
        brange = self.brange

        self.all_diffs = range(0, 16)

        if progressBar:
            pbcnt = 0
            progressBar.setMinimum(0)
            progressBar.setMaximum(len(brange) * 256)

        numtraces = tracerange[1] - tracerange[0]

        # Load all traces
        data = []
        textins = []
        textouts = []
        knownkeys = []
        for i in range(tracerange[0], tracerange[1]):

            # Handle Offset
            tnum = i + tracerange[0]

            d = tracedata.getTrace(tnum)

            if d is None:
                continue

            data.append(d)
            textins.append(tracedata.getTextin(tnum))
            textouts.append(tracedata.getTextout(tnum))
            knownkeys.append(tracedata.getKnownKey(tnum))

        traces = np.array(data)
        textins = np.array(textins)
        textouts = np.array(textouts)

        pbcnt = 0
        for bnum in brange:
            (data, pbcnt) = self.oneSubkey(
                bnum,
                pointRange,
                traces,
                numtraces,
                textins,
                textouts,
                knownkeys,
                progressBar,
                self.model,
                self.leakage,
                self.modelstate,
                pbcnt,
            )
            self.stats.updateSubkey(bnum, data)

    def getStatistics(self):
        return self.stats

    def setStatsReadyCallback(self, sr):
        pass

    def processKnownKey(self, inpkey):
        if hasattr(self.model, "processKnownKey"):
            return self.model.processKnownKey(self.leakage, inpkey)
        else:
            return inpkey
class CPAExperimentalChannelinfo(QObject):
    """
    CPA Attack done as a loop, but using an algorithm which can progressively add traces & give output stats
    """
    paramListUpdated = Signal(list)

    def __init__(self, model, showScriptParameter=None, parent=None):
        super(CPAExperimentalChannelinfo, self).__init__()

        resultsParams = [
            {
                'name': 'Reporting Interval',
                'key': 'reportinterval',
                'type': 'int',
                'value': 100
            },
            {
                'name': 'Iteration Mode',
                'key': 'itmode',
                'type': 'list',
                'values': {
                    'Depth-First': 'df',
                    'Breadth-First': 'bf'
                },
                'value': 'bf'
            },
            {
                'name': 'Skip when PGE=0',
                'key': 'checkpge',
                'type': 'bool',
                'value': False
            },
        ]
        self.params = Parameter.create(name='Progressive CPA',
                                       type='group',
                                       children=resultsParams)
        ExtendedParameter.setupExtended(self.params, self)

        self.model = model
        self.sr = None
        self._parent = parent

        # print self._parent.parent

        self.stats = DataTypeDiffs()

    def paramList(self):
        return [self.params]

    def setByteList(self, brange):
        self.brange = brange

    def addTraces(self,
                  tracedata,
                  tracerange,
                  progressBar=None,
                  pointRange=None):
        keyround = self.keyround
        modeltype = self.modeltype
        brange = self.brange

        foundkey = []

        self.all_diffs = range(0, 16)

        tdiff = self.findParam('reportinterval').value()

        numtraces = tracerange[1] - tracerange[0]

        if progressBar:
            pbcnt = 0
            progressBar.setMinimum(0)
            progressBar.setMaximum(len(brange) * 256 * (numtraces / tdiff + 1))

        pbcnt = 0
        #r = Parallel(n_jobs=4)(delayed(traceOneSubkey)(bnum, pointRange, traces_all, numtraces, plaintexts, ciphertexts, keyround, modeltype, progressBar, self.model, pbcnt) for bnum in brange)
        #self.all_diffs, pb = zip(*r)
        #pbcnt = 0
        cpa = [None] * (max(brange) + 1)
        for bnum in brange:
            cpa[bnum] = CPAProgressiveOneSubkey()
            # cpa[bnum] = MinDistOneSubkey()
            # cpa[bnum] = TemplateOneSubkey()

        brangeMap = [None] * (max(brange) + 1)
        i = 1
        for bnum in brange:
            brangeMap[bnum] = i
            i += 1

        skipPGE = self.findParam('checkpge').value()
        bf = self.findParam('itmode').value() == 'bf'

        #bf specifies a 'breadth-first' search. bf means we search across each
        #subkey by only the amount of traces specified. Depth-First means we
        #search each subkey completely, then move onto the next.
        if bf:
            brange_df = [0]
            brange_bf = brange
        else:
            brange_bf = [0]
            brange_df = brange

        #H = np.load('channelinfo-masked.npy')
        #H = np.load('csi-masked-newkey.npy')
        #H = np.load('channelinfo.npy')
        #mio = sio.loadmat('equalizer.mat')
        #H = mio['equaltotal']
        # H = np.load('equalization.npy')
        # self.project() ?
        project = self._parent.parent().proj
        section = project.getDataConfig("Template Data", "Equalization Matrix")
        # section = project.getDataConfig("Template Data", "AOF Matrix")
        fname = project.convertDataFilepathAbs(section[0]["filename"])
        H = np.load(fname)

        #for j in range(0, 16):
        #4 = 500-800
        #test = H.copy()
        #for i in range(0, 5):
        #    threshold = max(abs(test[j]))
        #    test[j, abs(test[j,:]) >= threshold ] = 0

        #print "%f %d"%(threshold, (abs(H[j,:]) > threshold).sum())

        #H[j, abs(H[j,:]) < threshold] = 0

        for bnum_df in brange_df:

            #CPAMemoryOneSubkey
            #CPASimpleOneSubkey
            #(self.all_diffs[bnum], pbcnt) = sCPAMemoryOneSubkey(bnum, pointRange, traces_all, numtraces, plaintexts, ciphertexts, keyround, modeltype, progressBar, self.model, pbcnt)

            tstart = 0
            tend = tdiff

            while tstart < numtraces:
                if tend > numtraces:
                    tend = numtraces

                if tstart > numtraces:
                    tstart = numtraces

                data = []
                textins = []
                textouts = []
                knownkeys = []
                for i in range(tstart, tend):

                    # Handle Offset
                    tnum = i + tracerange[0]

                    d = tracedata.getTrace(tnum)

                    if d is None:
                        continue

                    data.append(d)
                    textins.append(tracedata.getTextin(tnum))
                    textouts.append(tracedata.getTextout(tnum))
                    knownkeys.append(tracedata.getKnownKey(tnum))

                traces = np.array(data)
                textins = np.array(textins)
                textouts = np.array(textouts)

                for bnum_bf in brange_bf:

                    if bf:
                        bnum = bnum_bf
                    else:
                        bnum = bnum_df

                    traces_fixed = np.dot(traces - traces.mean(axis=0),
                                          H[bnum]) + 4
                    skip = False
                    if (self.stats.simplePGE(bnum) != 0) or (skipPGE == False):
                        (data, pbcnt) = cpa[bnum].oneSubkey(
                            bnum, pointRange, traces_fixed, tend - tstart,
                            textins, textouts, keyround, modeltype,
                            progressBar, self.model, pbcnt)
                        self.stats.updateSubkey(bnum, data, tnum=tend)
                    else:
                        skip = True

                    if progressBar.wasSkipped() or skip:
                        progressBar.clearSkipped()
                        pbcnt = brangeMap[bnum] * 256 * (numtraces / tdiff + 1)

                        if bf is False:
                            tstart = numtraces

                tend += tdiff
                tstart += tdiff

                if self.sr is not None:
                    self.sr()

            if progressBar is not None:
                pbcnt = 0

    def getStatistics(self):
        return self.stats

    def setStatsReadyCallback(self, sr):
        self.sr = sr
class CPASimpleLoop(QObject):
    """
    CPA Attack done as a loop - the 'classic' attack provided for familiarity to textbook samples.
    This attack does not provide trace-by-trace statistics however, you can only gather results once
    all the traces have been run through the attack.
    """

    def __init__(self, hardwareModel, leakageModel, showScriptParameter=None, parent=None):
        super(CPASimpleLoop, self).__init__()
        self.hardwareModel = hardwareModel
        self.leakageModel = leakageModel
        self.stats = DataTypeDiffs()

    def oneSubkey(self, bnum, pointRange, traces_all, numtraces, plaintexts, ciphertexts, keyround, progressBar, model, pbcnt):
        diffs = [0]*256

        if pointRange == None:
            traces = traces_all
            padbefore = 0
            padafter = 0
        else:
            traces = np.array(traces_all[:, pointRange[bnum][0] : pointRange[bnum][1]])
            padbefore = pointRange[bnum][0]
            padafter = len(traces_all[0,:]) - pointRange[bnum][1]
            #print "%d - %d (%d %d)"%( pointRange[bnum][0],  pointRange[bnum][1], padbefore, padafter)

        #For each 0..0xFF possible value of the key byte
        for key in range(0, 256):
            #Initialize arrays & variables to zero
            sumnum = np.zeros(len(traces[0,:]))
            sumden1 = np.zeros(len(traces[0,:]))
            sumden2 = np.zeros(len(traces[0,:]))

            hyp = [0] * numtraces

            #Formula for CPA & description found in "Power Analysis Attacks"
            # by Mangard et al, page 124, formula 6.2.

            #Generate hypotheticals
            for tnum in range(numtraces):

                if len(plaintexts) > 0:
                    pt = plaintexts[tnum]

                if len(ciphertexts) > 0:
                    ct = ciphertexts[tnum]

                if keyround == "first" or keyround == 0:
                    ct = None
                elif keyround == "last" or keyround == -1:
                    pt = None
                else:
                    raise ValueError("keyround invalid")

                #Generate the output of the SBOX
                # if modeltype == "Hamming Weight":
                #    hypint = model.HypHW(pt, ct, key, bnum);
                # elif modeltype == "Hamming Distance":
                #    hypint = model.HypHD(pt, ct, key, bnum);
                # else:
                #    raise ValueError("modeltype invalid")
                hypint = model(pt, ct, key, bnum)
                hyp[tnum] = hypint

            hyp = np.array(hyp)

            #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(numtraces):
                hdiff = (hyp[tnum] - meanh)
                tdiff = traces[tnum,:] - meant

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

            if progressBar:
                progressBar.setValue(pbcnt)
                #progressBar.setLabelText("Byte %02d: Hyp=%02x"%(bnum, key))
                pbcnt = pbcnt + 1
                if progressBar.wasCanceled():
                    raise KeyboardInterrupt

            diffs[key] = sumnum / np.sqrt( sumden1 * sumden2 )

            if padafter > 0:
                diffs[key] = np.concatenate([diffs[key], np.zeros(padafter)])

            if padbefore > 0:
                diffs[key] = np.concatenate([np.zeros(padbefore), diffs[key]])

        return (diffs, pbcnt)

    def setTargetBytes(self, brange):
        self.brange = brange

    def setKeyround(self, keyround):
        self.keyround = keyround

    def addTraces(self, traces, plaintexts, ciphertexts, knownkeys=None, progressBar=None, pointRange=None, tracesLoop=None):
        keyround=self.keyround
        brange=self.brange

        traces_all = np.array(traces)
        plaintexts =np.array(plaintexts)
        ciphertexts =np.array(ciphertexts)

        foundkey = []

        self.all_diffs = range(0,16)

        if progressBar:
            pbcnt = 0
            progressBar.setMinimum(0)
            progressBar.setMaximum(len(brange) * 256)

        numtraces = len(traces_all[:,0])

        pbcnt = 0
        for bnum in brange:
            (data, pbcnt) = self.oneSubkey(bnum, pointRange, traces_all, numtraces, plaintexts, ciphertexts, keyround, progressBar, self.leakageModel, pbcnt)
            self.stats.updateSubkey(bnum, data)

    def getStatistics(self):
        return self.stats

    def setStatsReadyCallback(self, sr):
        pass
Beispiel #8
0
class CPASimpleLoop(QObject):
    """
    CPA Attack done as a loop - the 'classic' attack provided for familiarity to textbook samples.
    This attack does not provide trace-by-trace statistics however, you can only gather results once
    all the traces have been run through the attack.
    """
    def __init__(self,
                 targetModel,
                 leakageFunction,
                 showScriptParameter=None,
                 parent=None):
        super(CPASimpleLoop, self).__init__()
        self.model = targetModel
        self.leakage = leakageFunction
        self.stats = DataTypeDiffs()
        self.modelstate = {'knownkey': None}

    def oneSubkey(self, bnum, pointRange, traces_all, numtraces, plaintexts,
                  ciphertexts, knownkeys, progressBar, model, leakagetype,
                  state, pbcnt):
        diffs = [0] * 256

        if pointRange == None:
            traces = traces_all
            # padbefore = 0
            # padafter = 0
        else:
            traces = np.array(traces_all[:, pointRange[0]:pointRange[1]])
            # padbefore = pointRange[0]
            # padafter = len(traces_all[0, :]) - pointRange[1]
            # print "%d - %d (%d %d)"%( pointRange[0],  pointRange[1], padbefore, padafter)

        #For each 0..0xFF possible value of the key byte
        for key in range(0, 256):
            #Initialize arrays & variables to zero
            sumnum = np.zeros(len(traces[0, :]))
            sumden1 = np.zeros(len(traces[0, :]))
            sumden2 = np.zeros(len(traces[0, :]))

            hyp = [0] * numtraces

            #Formula for CPA & description found in "Power Analysis Attacks"
            # by Mangard et al, page 124, formula 6.2.

            #Generate hypotheticals
            for tnum in range(numtraces):

                if len(plaintexts) > 0:
                    pt = plaintexts[tnum]
                else:
                    pt = []

                if len(ciphertexts) > 0:
                    ct = ciphertexts[tnum]
                else:
                    ct = []

                if knownkeys and len(knownkeys) > 0:
                    nk = knownkeys[tnum]
                else:
                    nk = None

                state['knownkey'] = nk

                hypint = model.leakage(pt, ct, key, bnum, leakagetype, state)

                hyp[tnum] = hypint

            hyp = np.array(hyp)

            #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(numtraces):
                hdiff = (hyp[tnum] - meanh)
                tdiff = traces[tnum, :] - meant

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

            if progressBar:
                progressBar.setValue(pbcnt)
                #progressBar.setLabelText("Byte %02d: Hyp=%02x"%(bnum, key))
                pbcnt = pbcnt + 1
                if progressBar.wasCanceled():
                    raise KeyboardInterrupt

            diffs[key] = sumnum / np.sqrt(sumden1 * sumden2)

            # if padafter > 0:
            #    diffs[key] = np.concatenate([diffs[key], np.zeros(padafter)])

            # if padbefore > 0:
            #    diffs[key] = np.concatenate([np.zeros(padbefore), diffs[key]])

        return (diffs, pbcnt)

    def setTargetBytes(self, brange):
        self.brange = brange

    def setReportingInterval(self, ri):
        # Not used for simpleloop
        pass

    def addTraces(self,
                  tracedata,
                  tracerange,
                  progressBar=None,
                  pointRange=None,
                  tracesLoop=None):
        brange = self.brange

        self.all_diffs = range(0, 16)

        if progressBar:
            pbcnt = 0
            progressBar.setMinimum(0)
            progressBar.setMaximum(len(brange) * 256)

        numtraces = tracerange[1] - tracerange[0]

        # Load all traces
        data = []
        textins = []
        textouts = []
        knownkeys = []
        for i in range(tracerange[0], tracerange[1]):

            # Handle Offset
            tnum = i + tracerange[0]

            d = tracedata.getTrace(tnum)

            if d is None:
                continue

            data.append(d)
            textins.append(tracedata.getTextin(tnum))
            textouts.append(tracedata.getTextout(tnum))
            knownkeys.append(tracedata.getKnownKey(tnum))

        traces = np.array(data)
        textins = np.array(textins)
        textouts = np.array(textouts)

        pbcnt = 0
        for bnum in brange:
            (data, pbcnt) = self.oneSubkey(bnum, pointRange, traces, numtraces,
                                           textins, textouts, knownkeys,
                                           progressBar, self.model,
                                           self.leakage, self.modelstate,
                                           pbcnt)
            self.stats.updateSubkey(bnum, data)

    def getStatistics(self):
        return self.stats

    def setStatsReadyCallback(self, sr):
        pass

    def processKnownKey(self, inpkey):
        if hasattr(self.model, 'processKnownKey'):
            return self.model.processKnownKey(self.leakage, inpkey)
        else:
            return inpkey
class CPAExperimentalChannelinfo(QObject):
    """
    CPA Attack done as a loop, but using an algorithm which can progressively add traces & give output stats
    """
    paramListUpdated = Signal(list)

    def __init__(self, model, showScriptParameter=None, parent=None):
        super(CPAExperimentalChannelinfo, self).__init__()

        resultsParams = [{'name':'Reporting Interval', 'key':'reportinterval', 'type':'int', 'value':100},
                         {'name':'Iteration Mode', 'key':'itmode', 'type':'list', 'values':{'Depth-First':'df', 'Breadth-First':'bf'}, 'value':'bf'},
                         {'name':'Skip when PGE=0', 'key':'checkpge', 'type':'bool', 'value':False},
                         ]
        self.params = Parameter.create(name='Progressive CPA', type='group', children=resultsParams)
        ExtendedParameter.setupExtended(self.params, self)

        self.model = model
        self.sr = None
        self._parent = parent

        # print self._parent.parent

        self.stats = DataTypeDiffs()

    def paramList(self):
        return [self.params]

    def setByteList(self, brange):
        self.brange = brange

    def addTraces(self, tracedata, tracerange, progressBar=None, pointRange=None):
        keyround=self.keyround
        modeltype=self.modeltype
        brange=self.brange

        foundkey = []

        self.all_diffs = range(0,16)


        tdiff = self.findParam('reportinterval').value()

        numtraces = tracerange[1] - tracerange[0]

        if progressBar:
            pbcnt = 0
            progressBar.setMinimum(0)
            progressBar.setMaximum(len(brange) * 256 * (numtraces/tdiff + 1))

        pbcnt = 0
        #r = Parallel(n_jobs=4)(delayed(traceOneSubkey)(bnum, pointRange, traces_all, numtraces, plaintexts, ciphertexts, keyround, modeltype, progressBar, self.model, pbcnt) for bnum in brange)
        #self.all_diffs, pb = zip(*r)
        #pbcnt = 0
        cpa = [None]*(max(brange)+1)
        for bnum in brange:
            cpa[bnum] = CPAProgressiveOneSubkey()
            # cpa[bnum] = MinDistOneSubkey()
            # cpa[bnum] = TemplateOneSubkey()

        brangeMap = [None]*(max(brange)+1)
        i = 1
        for bnum in brange:
            brangeMap[bnum] = i
            i += 1

        skipPGE = self.findParam('checkpge').value()
        bf = self.findParam('itmode').value() == 'bf'

        #bf specifies a 'breadth-first' search. bf means we search across each
        #subkey by only the amount of traces specified. Depth-First means we
        #search each subkey completely, then move onto the next.
        if bf:
            brange_df = [0]
            brange_bf = brange
        else:
            brange_bf = [0]
            brange_df = brange


        #H = np.load('channelinfo-masked.npy')
        #H = np.load('csi-masked-newkey.npy')
        #H = np.load('channelinfo.npy')
        #mio = sio.loadmat('equalizer.mat')
        #H = mio['equaltotal']
        # H = np.load('equalization.npy')
        # self.project() ?
        project = self._parent.parent().proj
        section = project.getDataConfig("Template Data", "Equalization Matrix")
       # section = project.getDataConfig("Template Data", "AOF Matrix")
        fname = project.convertDataFilepathAbs(section[0]["filename"])
        H = np.load(fname)

        #for j in range(0, 16):
            #4 = 500-800
            #test = H.copy()
            #for i in range(0, 5):
            #    threshold = max(abs(test[j]))
            #    test[j, abs(test[j,:]) >= threshold ] = 0

            #print "%f %d"%(threshold, (abs(H[j,:]) > threshold).sum())

            #H[j, abs(H[j,:]) < threshold] = 0

        for bnum_df in brange_df:

            #CPAMemoryOneSubkey
            #CPASimpleOneSubkey
            #(self.all_diffs[bnum], pbcnt) = sCPAMemoryOneSubkey(bnum, pointRange, traces_all, numtraces, plaintexts, ciphertexts, keyround, modeltype, progressBar, self.model, pbcnt)

            tstart = 0
            tend = tdiff


            while tstart < numtraces:
                if tend > numtraces:
                    tend = numtraces

                if tstart > numtraces:
                    tstart = numtraces

                data = []
                textins = []
                textouts = []
                knownkeys = []
                for i in range(tstart, tend):

                    # Handle Offset
                    tnum = i + tracerange[0]

                    d = tracedata.getTrace(tnum)

                    if d is None:
                        continue

                    data.append(d)
                    textins.append(tracedata.getTextin(tnum))
                    textouts.append(tracedata.getTextout(tnum))
                    knownkeys.append(tracedata.getKnownKey(tnum))

                traces = np.array(data)
                textins = np.array(textins)
                textouts = np.array(textouts)


                for bnum_bf in brange_bf:

                    if bf:
                        bnum = bnum_bf
                    else:
                        bnum = bnum_df

                    traces_fixed = np.dot(traces - traces.mean(axis=0), H[bnum]) + 4
                    skip = False
                    if (self.stats.simplePGE(bnum) != 0) or (skipPGE == False):
                        (data, pbcnt) = cpa[bnum].oneSubkey(bnum, pointRange, traces_fixed, tend - tstart, textins, textouts, keyround, modeltype, progressBar, self.model, pbcnt)
                        self.stats.updateSubkey(bnum, data, tnum=tend)
                    else:
                        skip = True

                    if progressBar.wasSkipped() or skip:
                        progressBar.clearSkipped()
                        pbcnt = brangeMap[bnum] * 256 * (numtraces/tdiff + 1)

                        if bf is False:
                            tstart = numtraces

                tend += tdiff
                tstart += tdiff

                if self.sr is not None:
                    self.sr()

            if progressBar is not None:
                pbcnt = 0

    def getStatistics(self):
        return self.stats

    def setStatsReadyCallback(self, sr):
        self.sr = sr