Running SOLN_LAB_3_3 with a Husky doesn't yield correct results

Hello,
I am a beginner with ChipWhisperer Husky. I tried running this lab chipwhisperer-jupyter/courses/sca101/Lab 3_3 - DPA on Firmware Implementation of AES (MAIN).ipynb at master · newaetech/chipwhisperer-jupyter · GitHub but could not get the expected 2B key as a result. I ran the full solution file and here is my output (at the very end of the file, so after the ghost peak correction):

Subkey 0 - most likely DE (actual 2B)
    Top 5 guesses:
        DE - Diff = 0.024871
        28 - Diff = 0.023788
        D8 - Diff = 0.021290
        08 - Diff = 0.020513
        1C - Diff = 0.019200

etc. etc. None of the key guesses are correct in relation to the known_key.

Is the solution up-to-date or is there something wrong with my Husky ? I have to say that the Husky also has the ADC and glitch leds blinking red, and that has happened every time I ran prior labs, so I assumed it was not so much of a big deal.

1 Like

I ran my own code with the simulated data instead and the key was guess as expected. I also found this link (Blinking together ADC and Glitch (CW Husky) - #20 by jpthibault) that gave good information on how to find and correct scope errors on the Husky.

The issue is that Husky was clipping all the time. The Husky still has errors even after putting it on scope.gain.mode = 'low' (gain too low). Setting scope.gain.db=9 (I tried 15 as well) worked really well to clear those errors.

So now my Husky does not blink anymore. However, I still don’t have any clear outliers for the key recovery. For instance the following code:

# ###################
# Add your code here

byte_to_check = 0
    
for hypothetical_bit in range (8):
    print("Guessing bit {}".format(hypothetical_bit))
    max_diff_list = [0]*256
    for guess in range(256):

        one_list = []
        zero_list = []

        for trace_index in range(numtraces):

            input_byte = textin_array[trace_index][byte_to_check]
            hypothetical_leakage_bit = get_bit(aes_internal(guess, input_byte), hypothetical_bit)
            #Get a hypothetical leakage list - use aes_internal(guess, input_byte)          

            if hypothetical_leakage_bit == 1:
                one_list.append(trace_array[trace_index])
            else:
                zero_list.append(trace_array[trace_index])

        avg_one_list = np.asarray(one_list).mean(axis=0)
        avg_zero_list = np.asarray(zero_list).mean(axis=0)
        diff = avg_one_list - avg_zero_list
        max_diff_list[guess] = np.max(np.abs(diff))
       
    sorted_list = np.argsort(max_diff_list)[::-1]
    for guess in sorted_list[0:5]:
        print("Guessing {:02X} = {} max difference".format(guess, max_diff_list[guess]))

# ###################
#raise NotImplementedError("Add Your Code Here")

Output:

Guessing bit 0
Guessing 99 = 0.005902638194051749 max difference
Guessing 7A = 0.005651018018613788 max difference
Guessing 03 = 0.005514248138483439 max difference
Guessing F0 = 0.0045560546346249675 max difference
Guessing A2 = 0.004528716593514479 max difference
Guessing bit 1
Guessing 33 = 0.004505359428481234 max difference
Guessing 54 = 0.0044835073738925535 max difference
Guessing EF = 0.004276400725818183 max difference
Guessing 0E = 0.004237268944205896 max difference
Guessing A9 = 0.004094750817250428 max difference
Guessing bit 2
Guessing 44 = 0.004499186393307323 max difference
Guessing D1 = 0.004198045386538934 max difference
Guessing D6 = 0.004053841480777816 max difference
Guessing 83 = 0.0040455373638026045 max difference
Guessing 9C = 0.003885179901513696 max difference
Guessing bit 3
Guessing 83 = 0.005833940307519856 max difference
Guessing 37 = 0.0046457416430466004 max difference
Guessing B0 = 0.004334934195035417 max difference
Guessing 16 = 0.0041111867860526875 max difference
Guessing 84 = 0.003990534049397788 max difference
Guessing bit 4
Guessing ED = 0.0058740444125536945 max difference
Guessing 5A = 0.005001952192327491 max difference
Guessing 2F = 0.004694605105501987 max difference
Guessing A0 = 0.0042323282288084345 max difference
Guessing 80 = 0.0039705824675472096 max difference
Guessing bit 5
Guessing 62 = 0.0053920840119666205 max difference
Guessing EC = 0.005068692860458104 max difference
Guessing 1B = 0.004922486227210338 max difference
Guessing 96 = 0.004566689473281572 max difference
Guessing BB = 0.0041205128408917935 max difference
Guessing bit 6
Guessing CD = 0.005902739682644095 max difference
Guessing 7B = 0.0055705732562989045 max difference
Guessing 31 = 0.005075793975103635 max difference
Guessing 08 = 0.004965798668758303 max difference
Guessing BA = 0.004730152508342213 max difference
Guessing bit 7
Guessing 0B = 0.006503706862239184 max difference
Guessing 27 = 0.005723674687116199 max difference
Guessing AF = 0.005167010000418467 max difference
Guessing 9C = 0.005066483919737769 max difference
Guessing 3B = 0.005016875155058068 max difference

Note how close the differences are and how much they change given the bit of the SBox I study.
I use SAM4S as a target.

Using the simulated data consistently gives me 2B as an answer for byte 0 and all 8 bits so I don’t think my code has an issue but if it does feel free to tell me.

Using the solution code at the end with the ghost peaks correction and windowing does not work either. The key does not even show in the top 5 guesses. What am I doing wrong ?

Edit: tried augmenting samples to 37000 to see all AES rounds, tried windowing, the key is barely in the top 5 and never has dominant peaks compared to other key guesses. I can provide all traces captured with the CWHusky if it is of any help.

My guess is that there’s some amount of non-constant time execution caused by optimizations made by the SAM4S’s core and that that’s throwing things off. This lab is mostly just a demonstration of a different type of attack on AES; the later CPA labs should be much more reliable.

Alex

Unfortunately, this is a problem of Husky’s ADC accuracy although the newae team don’t admit it.
I did many research on this topic and got this conclusion. The CPA attach also won’t work perfectly and you will not able to recover all key bytes.
At the same time the CW Lite is a perfect device.

I respectfully disagree: in investigating the issues you brought up, an issue was found and filed. We haven’t had the time to resolve it yet, but we are planning to.

1 Like

Hello,
Thank you all for your answer. I will try the CPA labs and update accordingly.

Our aim is to use this device in order to perform evaluations following standards for a relatively low-cost compared to other power glitch/side-channel capture devices. We had our eyes on the Husky because of the cost compared to the pro and the amount of functionnalities compared to the lite. Would you advise me to order another CW ?

I read Husky sampling clock phase is not consistent. · Issue #490 · newaetech/chipwhisperer · GitHub and unless i am mistaken this does not apply to me as I did not change scope.clock.adc_mul or scope.clock.clkgen_src, only the gain and samples.

Hello, I am observing that SOLN_LAB_4_2 is not working either on my side. Here is my output:

Key guess:  0xf0
Correlation:  0.6749367615602105

Let's make sure we've recovered the byte correctly:

assert guess == 0x2b

print("✔️ OK to continue!")

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[12], line 1
----> 1 assert guess == 0x2b
      2 print("✔️ OK to continue!")

AssertionError: 

....................

Best Key Guess: f0 a3 7b ab 7a e0 d8 19 13 61 ba fe 3c 4f d9 38 
 [0.6749367615602105, 0.618145240561299, 0.6460080791027013, 0.6355856966984309, 0.6627631907283404, 0.6447053642800781, 0.6147078600161476, 0.6614776816764971, 0.6347127729158851, 0.6349338328063929, 0.6370558896290138, 0.6175947374545362, 0.6682693907034827, 0.6210625967742534, 0.6430698678283723, 0.613795431492052]

If there are issues with the hardware, what do you suggest are the next steps ?

I’d recommend capturing more traces. I do see different behaviour with my older Husky and some of the newer ones I’ve got, so I’ll look more into this.

Alex

This will not help! BTW, what is the difference between old and new revision?
The main problem is jittery ADC output. So it makes noisy traces and makes impossible to run any attack.
This is a real problem I am wonder why folk who works with Husky still didn’t focus on this. Probably, Husky is mostly used for the fault injection attacks.

While the suggestion to capture more traces isn’t perfect, it does in fact improve things. Additionally, saying that it’s impossible to run any attack is also false, as I’m able to reliably get the CPA attack to work. Additionally, I don’t see any evidence of jitter being the cause of this issue.

One additional suggestion that I can make @Shanly is that a small negative scope.clock.adc_phase seems to greatly improve the performance of the CPA attack. I’d recommend trying something around -32. I can reliably break AES in roughly 60-70 traces.

EDIT: I was also able to complete Lab 3_3 by adjusting the adc_phase.

Collecting more traces gives worse result. For example, 10k traces can recover some key bytes. 30k traces recovers less 50% of key. 60k traces makes impossible to recover any key byte. So, more traces give more noise in the total statistics.

I am having precisely the same problem in Lab 3_3, 4_1, and 4_2. Also adjustments of scope.clock.adc_phase did not improve the situation.

@Alex_Dewar: Would it be possible to share your full scope settings for the successful run?
Other than a VCCaux alarm which I get every time the device starts up, I am not able to spot any setting which improves the situation after a full day of testing… With the very similar failure results @Shanly describes I am sure we are chasing some systematic issue here.

I just used the default settings besides changing the phase, but I can post the full settings tonight. This is definitely something we’ll have to look more into.

We’ve only been able to do limited testing so far, but the results I’m seeing are quite different between the V2 Husky I typically use and some V3 Huskies. Interestingly, the changes between V2 and V3 are pretty limited and none of them seem like they would affect this.

Thank you Alex,
I haven’t tried the settings you suggested yet. Are the changes you mention hardware or only software? Is there any way I can retrieve the firmware for the V2 and make the tests work in that case maybe ?
In the meantime we still require a device to perform SCA evaluations, what CW would you recommend?

The changes are just hardware between the V2 and the V3, mostly just fixing a few PCB errors and a different E-Fuse, nothing that should cause this sort of difference. That being said, the V2s may have a lot of substitutions on passives and smaller chips since they were made during heavy parts shortages. All the major chips (ADC, PLL, amplifier, etc.) are the same between my Huskies.

The ChipWhisperer-Lite is the closest thing to the Husky you can currently get.

Alex

What is the frequency of the crypto core of the device being evaluated?
If it is more 100Mhz, CW Lite cannot give you reliable results.
But if it low 100Mhz, CW lite is a perfect choice.

Could you please share the set of traces (~500 traces) collected for the same key and for the static data block by Husky v2 and v3? It is interesting to see the differences and compare jitter.
Is Husky v2 more accurate and reliable to collect the power traces?

Thanks. That would would help ruling out the option of wrong settings.
How can I determine the version of my Husky? I assume it is the latest because the quality report is only three weeks old, but just to be sure.
Any chance that we are searching at the wrong end? Target side boards show NAE-CW313-03 and NAE-CW312T-SAM4S-03

Yup, here you go Dropbox

I do see better CPA performance as well, typically around 30 traces for v2 vs about 60 for the V3 with adjusted adc phase. Seems pretty consistent across the 3 V2s and 2 V3s that I’ve tried.

I believe the back should say HWREV: 1.1C (perhaps A or B) for the V3 and HWREV: 1.0 for the V2 board.

I don’t think it’s the target end of things as I see a difference just swapping out the Husky with no software or other hardware changes.