Power Analysis against Secure CAN

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?