def new_model(self, model): """Makes a new leakage model for use with analyzer Usage:: class AES256_Round13_Model(cwa.AESLeakageHelper): def leakage(self, pt, ct, guess, bnum): # You must put YOUR recovered 14th round key here. # This example may not be accurate! calc_round_key = [0xea, 0x79, 0x79, 0x20, 0xc8, 0x71, 0x44, 0x7d, 0x46, 0x62, 0x5f, 0x51, 0x85, 0xc1, 0x3b, 0xcb] xored = [calc_round_key[i] ^ pt[i] for i in range(0, 16)] block = xored block = self.inv_shiftrows(block) block = self.inv_subbytes(block) block = self.inv_mixcolumns(block) block = self.inv_shiftrows(block) result = block return self.inv_sbox((result[bnum] ^ guess[bnum])) leak_model = cwa.leakage_models.new_model(AES256_Round13_Model) Args: model (AESLeakageHelper): New leakage model to create Returns: Leakage model made from model """ return AES128_8bit(model)
def getPartitionNum(self, trace, tnum): key = trace.getKnownKey(tnum) text = trace.getTextin(tnum) guess = [0] * 16 for i in range(0, 16): guess[i] = AES128_8bit.getHW(sbox(text[i] ^ key[i])) return guess
def getPartitionNum(self, trace, tnum): key = trace.getKnownKey(tnum) ct = trace.getTextout(tnum) #Convert from initial key to final-round key, currently #this assumes AES if len(key) == 16: rounds = 10 else: raise ValueError("Need to implement for selected AES") key = keyScheduleRounds(key, 0, rounds) guess = [0] * 16 for i in range(0, 16): st10 = ct[AES128_8bit.INVSHIFT[i]] st9 = inv_sbox(ct[i] ^ key[i]) guess[i] = AES128_8bit.getHW(st9 ^ st10) return guess
def round_1_2_state_diff_text(self): """Hamming distance between AES input and mix columns output""" return AES128_8bit(aes128_leakage.Round1Round2StateDiff_Text)
def round_1_2_state_diff_key_mix(self): """Hamming distance between initial key mix and round 1 key mix""" return AES128_8bit(aes128_leakage.Round1Round2StateDiff_KeyMix)
def round_1_2_state_diff_sbox(self): """Hamming distance between round 1 and 2 state during sbox lookup operation. """ return AES128_8bit(aes128_leakage.Round1Round2StateDiff_SBox)
def sbox_output_successive(self): """Hamming distance between 2 AES sbox outputs""" return AES128_8bit(aes128_leakage.SBoxOutputSuccessive)
def shift_rows_output(self): """Hamming weight of shift rows output""" return AES128_8bit(aes128_leakage.ShiftColumns_output)
def __init__(self, parent=None): super(AesKeyScheduleDialog, self).__init__(parent) self.model = AES128_8bit() layout = QVBoxLayout() self.setLayout(layout) self.outmode = QComboBox() self.outmode.addItem("AABBCC...EEFF", ["", ""]) self.outmode.addItem("AA:BB:CC...EE:FF", ["", ":"]) self.outmode.addItem("AA BB CC...EE FF", ["", " "]) self.outmode.addItem("AA,BB,CC...EE,FF", ["", ","]) self.outmode.addItem("0xAA, 0xBB, 0xCC... 0xEE, 0xFF", ["0x", ", "]) self.outmode.currentIndexChanged.connect(self.inTextChanged) self.indata = QtFixes.QLineEdit("") self.indata.setFont(QFont("Courier")) self.keysched = QTextEdit("") self.keysched.setFont(QFont("Courier")) self.outkey = QtFixes.QLineEdit("") self.outkey.setReadOnly(True) self.outkey.setFont(QFont("Courier")) outmodeL = QHBoxLayout() outmodeL.addWidget(QLabel("Format:")) outmodeL.addWidget(self.outmode) outmodeL.addStretch() self.inprnd = QComboBox() self.inprnd.currentIndexChanged.connect(self.inTextChanged) self.setKeyLength(128) indataL = QHBoxLayout() indataL.addWidget(QLabel("Key:")) indataL.addWidget(self.indata) indataL.addWidget(self.inprnd) self.indata.textChanged.connect(self.inTextChanged) outdataL = QHBoxLayout() outdataL.addWidget(QLabel("Key:")) outdataL.addWidget(self.outkey) gbIndata = QGroupBox("Input Known Key") gbIndata.setLayout(indataL) layout.addWidget(gbIndata) gbOutdata = QGroupBox("Output Desired Key") outdataTotalL = QVBoxLayout() outdataTotalL.addLayout(outmodeL) outdataTotalL.addLayout(outdataL) gbOutdata.setLayout(outdataTotalL) layout.addWidget(gbOutdata) gbKeySched = QGroupBox("Full Key Schedule") keyschedL = QVBoxLayout() keyschedL.addWidget(self.keysched) gbKeySched.setLayout(keyschedL) layout.addWidget(gbKeySched) self.setWindowTitle("AES-128/AES-256 Key Schedule Calculator") self.setObjectName("AES Key Schedule") self.setWindowIcon(QIcon(":/images/cwiconA.png")) self.setMinimumSize(800, 400)
def inverse_sbox_output(self): """Hamming weight of 1st round InvSBox (for decryption)""" return AES128_8bit(aes128_leakage.InvSBox_output)
def sbox_output(self): """SBox Output.""" return AES128_8bit(aes128_leakage.SBox_output)
def mix_columns_output(self): """Output of the mix columns operation.""" return AES128_8bit(aes128_leakage.Mixcolumns_output)
def plaintext_key_xor(self): """Hamming weight of 1st round key mix (pt ^ key)""" return AES128_8bit(aes128_leakage.PtKey_XOR)
def after_key_mix(self): """After key mix operation.""" return AES128_8bit(aes128_leakage.AfterKeyMixin)
def last_round_state(self): """Last round state.""" return AES128_8bit(aes128_leakage.LastroundHW)
def inverse_sbox_output(self): """Inverse Sbox output.""" return AES128_8bit(aes128_leakage.InvSBox_output)
def round_1_2_state_diff_sbox(self): """Hamming distance between round 1 and round 2 sbox output""" return AES128_8bit(aes128_leakage.Round1Round2StateDiff_SBox)
def after_key_mix(self): """Hamming weight of 1st round key mix (pt ^ key)""" return AES128_8bit(aes128_leakage.AfterKeyMixin)
def shift_columns_output(self): """Output of the shift columns operation.""" return AES128_8bit(aes128_leakage.ShiftColumns_output)
def plaintext_key_xor(self): """Plain text key XOR.""" return AES128_8bit(aes128_leakage.PtKey_XOR)
def sbox_output(self): """Hamming weight of 1st round SBox output""" return AES128_8bit(aes128_leakage.SBox_output)
def last_round_state_diff_alternate(self): """Last round state using hamming distance, alternate.""" return AES128_8bit(aes128_leakage.LastroundStateDiffAlternate)
def last_round_state(self): """Hamming weight of 9th round state (InvSBox output)""" return AES128_8bit(aes128_leakage.LastroundHW)
def sbox_input_successive(self): """Successive Sbox input.""" return AES128_8bit(aes128_leakage.SBoxInputSuccessive)
def mix_columns_output(self): """Hamming weight of 1st round mix columns""" return AES128_8bit(aes128_leakage.Mixcolumns_output)
"""CPA attack script. Assumes that a project with XMEGA software AES traces is already open. """ import chipwhisperer as cw from chipwhisperer.analyzer.attacks.cpa import CPA from chipwhisperer.analyzer.attacks.cpa_algorithms.progressive import CPAProgressive from chipwhisperer.analyzer.attacks.models.AES128_8bit import AES128_8bit, InvSBox_output from chipwhisperer.analyzer.preprocessing.add_noise_random import AddNoiseRandom #self.project = cw.openProject("2017-mar23-xmega-aes.cwp") traces = self.project.traceManager() attack = CPA() leak_model = AES128_8bit(InvSBox_output) attack.setAnalysisAlgorithm(CPAProgressive, leak_model) attack.setTraceSource(traces) attack.setTraceStart(0) attack.setTracesPerAttack(-1) attack.setIterations(1) attack.setReportingInterval(10) attack.setTargetSubkeys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) attack.setPointRange((0, -1)) self.results_table.setAnalysisSource(attack) self.correlation_plot.setAnalysisSource(attack) self.output_plot.setAnalysisSource(attack) self.pge_plot.setAnalysisSource(attack) attack.processTraces()
def last_round_state_diff(self): """Hamming distance between rounds 9 and 10""" return AES128_8bit(aes128_leakage.LastroundStateDiff)
def last_round_state_diff_alternate(self): """Hamming distance between rounds 9 and 10 (alternate calculation)""" return AES128_8bit(aes128_leakage.LastroundStateDiffAlternate)
def __init__(self, trace_manager, bnum, model, bmask=0xff): self.tm = trace_manager self._bnum = bnum self._bmask = bmask self.num_parts = bin(bmask).count('1') + 1 self.aes = AES128_8bit(model, bmask)
def sbox_in_out_diff(self): """Hamming distance between SBox input and output.""" return AES128_8bit(aes128_leakage.SBoxInOutDiff)