Glitch Attack in CW305

Hello, I want to implement clock glitch attack in CW305. Following this link I have configured j16 switch. my scope looks like following:

    scope = cw.scope()
    scope.gain.db = 25
    scope.clock.clkgen_freq = 10E6
    scope.adc.samples = 500  #500 before
    scope.adc.offset = 0
    scope.adc.basic_mode = "rising_edge"
    scope.trigger.triggers = "tio4"
    scope.io.tio1 = "serial_rx"
    scope.io.tio2 = "serial_tx"
    scope.io.hs2 = "disabled"
    scope.adc.timeout = .5

Then, I did not setup any PLL from target cw305. I have configured ADC clock using scope.clock.adc_src = "clkgen_x4"

then locked ADC using following

import time
for i in range(5):
    scope.clock.reset_adc()
    time.sleep(1)
    if scope.clock.adc_locked:
        break 
assert (scope.clock.adc_locked), "ADC failed to lock"

I think I have done the major parts but still seeing timeout error. The design is working fine if I just set 0 to j16 but does not work if i set 0 there. What could be the issue? Before adding glitch i want to run the design on scope’s clock.

Can you share your complete notebook, and the full error message?

Sure! Here is my notebook, there are two different attempts one I tried to modify another coped from other post (link included).
cw305_glitch.zip (5.7 KB)

Sorry for the lag.

In the future if you can post a minimal reproducible example it’ll make our jobs easier. As it is I need to make some guesses as to what’s going on (I’m assuming your scope is not a Husky?); also I don’t have your bitfile so it’s impossible for me to reproduce.

However I can get the capture working with our stock AES bitfile and J16=1 if I add this:
scope.io.hs2 = 'clkgen'

Without this, the CW clock doesn’t get driven out to the target, which is probably why your target wasn’t responding.

I am also performing a clock glitch attack on the CW305. I took inspiration from the notebook provided by @km22, but I haven’t been able to get it to work. The trigger appears to be detected, but the glitch doesn’t seem to have any effect on the AES execution, as I always get the same ciphertext.

I have set J16 to 1 and K16 to 0, as mentioned in the tutorial: Tutorial CW305-3 Clock Glitching - ChipWhisperer Wiki

Here are the settings I’m using for the scope:

scope = cw.scope()

scope.gain.db = 25
scope.adc.samples = 129
scope.adc.offset = 0
scope.adc.basic_mode = "rising_edge"
scope.clock.clkgen_freq = 20E6
scope.clock.adc_src = "clkgen_x4"
scope.trigger.triggers = "tio4"
scope.io.tio1 = "serial_rx"
scope.io.tio2 = "serial_tx"
scope.io.hs2 = "clkgen"

For the glitch:

scope.glitch.clk_src = "clkgen" 
scope.glitch.output = "clock_xor"
scope.glitch.trigger_src = "ext_single" 
scope.glitch.width = 10
scope.io.hs2 = "glitch"  
scope.io.glitch_lp = False
scope.glitch.ext_offset = 300 
scope.glitch.repeat = 5 

scope.adc.timeout = 2

And the glitch loop:

import struct
import numpy as np
from tqdm import trange

ktp = cw.ktp.Basic()
ktp.fixed_key = True 
ktp.fixed_text = True
key, text = ktp.next()
expected_sum = 2312

print("Expected sum:", expected_sum)
print("Plain-text:", text.hex())
print("Key:", key.hex())

def reboot_flush():
    scope.io.nrst = False
    time.sleep(0.05)
    scope.io.nrst = "high_z"
    time.sleep(0.05)
    target.flush()
    
glitch_values   = [
    (1.0, 0.5),
    (1.0, 1.0),
    (2.0, 5.0),
    (3.0, 8.0),
]

rounds_per_point = 5

glitch_outputs = []
print("Running selected glitches")

for w, off in glitch_values:

    scope.glitch.width = w
    scope.glitch.ext_offset = off

    result = {"width": w, "offset": off, "resets": 0, "successes": []}
    glitch_outputs.append(result)

    for _ in range(rounds_per_point):
        if scope.adc.state:
            result["resets"] += 1
            reboot_flush()
            
        scope.arm()
        
        #trace = cw.capture_trace(scope, target, text, key)
        trace = cw.capture_trace(scope, target, text, key, ack=True, poll_done=False, as_int=False, always_send_key=False )

        #print("Plain-text:", text.hex())
        #print("Key:", key.hex())
        
        cipher = trace.textout  
        print("Ciphertext:", cipher.hex())

        if trace:  
            result["resets"] += 1
            reboot_flush()
        else:
            output_sum = sum(cipher[i] for i in range(16))
            if output_sum != expected_sum:
                result["successes"].append(output_sum)
                print(f"Successful glitch: sum={output_sum}, setting=(w={w}, off={off})")
                print("    Ciphertext:", cipher.hex())

Despite trying various glitch widths and offsets, I always get the correct ciphertext, as if the glitch had no effect. It is important to note that i am using the original AES Vivado project provided by ChipWhisperer without any modifications.

Clock_Glitch_AES_4.zip (3.3 KB)
I’ve also attached the full notebook, which includes the normal AES execution followed by the glitch attempts.

Any help or suggestions would be greatly appreciated!

Thank you in advance.

Do you see any error causing stall or empty trace showing not able to receive done signal?

@Julia_UC3M I was experimenting with another design and thought to see if I can reproduce the issue you have mentioned. In my case with 35t and 10MHz, i was able to get corrupted output using the following setting, no stall:
offset = -5.078125, width = 1.171875 to 1.99, ext_offset = 0