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.