Hi, thanks for the paper. I have implemented the attack based on the Lab 4.2 solution notebook:
import chipwhisperer.analyzer as cwa
### Attack subbyte 1 and 2, as there is enough variation here due to the counter
### Code from SOLN_Lab 4_2 - CPA on Firmware Implementation of AES.ipynb
t_bar = np.sum(trace_array, axis=0)/len(trace_array)
o_t = np.sqrt(np.sum((trace_array - t_bar)**2, axis=0))
cparefs = [0] * 16
bestguess = [0] * 16
for bnum in trange(1, 3):
maxcpa = [0] * 256
for kguess in range(0, 256):
hws = np.array([[HW[aes_internal(textin[bnum],kguess)] for textin in textin_array]]).transpose()
hws_bar = mean(hws)
o_hws = std_dev(hws, hws_bar)
correlation = cov(trace_array, t_bar, hws, hws_bar)
cpaoutput = correlation/(o_t*o_hws)
maxcpa[kguess] = max(abs(cpaoutput))
bestguess[bnum] = np.argmax(maxcpa)
cparefs[bnum] = max(maxcpa)
print("Best Key Guess: ", end="")
for b in bestguess: print("%02x " % b, end="")
print("\nBest Key Proba: ", end="")
for b in cparefs: print(f"{round(b*100,1)}% ", end="")
print("\nReal Key: ", end="")
for b in key: print("%02x " % b, end="")
bestguess[0] = 0
# Simulate next round based on https://eprint.iacr.org/2015/529.pdf
textin_round2_array = []
for text in textin_array:
state = [0] * 16
state[1] = text[1] ^ bestguess[1]
state[2] = text[2] ^ bestguess[2]
state = cwa.attacks.models.aes.funcs.subbytes(state)
state = cwa.attacks.models.aes.funcs.shiftrows(state)
state = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, state[10], 0, 0, state[13], 0, 0]
state = cwa.attacks.models.aes.funcs.mixcolumns(state)
textin_round2_array.append(state)
# Using the CPA code again but with the output of round 1 mixcolumns
cparefs = [0] * 16 #put your key byte guess correlations here
bestguess = [0] * 16 #put your key byte guesses here
for bnum in trange(0, 16):
maxcpa = [0] * 256
for kguess in range(0, 256):
hws = np.array([[HW[aes_internal(textin[bnum],kguess)] for textin in textin_round2_array]]).transpose()
hws_bar = mean(hws)
o_hws = std_dev(hws, hws_bar)
correlation = cov(trace_array, t_bar, hws, hws_bar)
cpaoutput = correlation/(o_t*o_hws)
maxcpa[kguess] = max(abs(cpaoutput))
bestguess[bnum] = np.argmax(maxcpa)
cparefs[bnum] = max(maxcpa)
print("Best Key Guess: ", end="")
for b in bestguess: print("%02x " % b, end="")
print("\nBest Key Proba: ", end="")
for b in cparefs: print(f"{round(b*100,1)}% ", end="")
# Compare with the first Round key
first_round_key = cwa.attacks.models.aes.key_schedule.key_schedule_rounds(key, 0, 1)
print("\nFirst Round Key: ", end="")
for b in first_round_key: print("%02x " % b, end="")
With the help of this code I am able to get subbyte 1 and 2 correctly. Unfortunately, the output of the attack on round 2 does not seem to work. Here is the output for the first and the second attack:
I hope I’m not asking for too much, but do you have any ideas what might go wrong?