The Plan That Sounded Simple
Here’s what I wanted to do: Extract AES encryption keys from an STM32 microcontroller by watching its power consumption.
Not by hacking the software. Not by brute-forcing the key. But by literally measuring how much electricity the chip uses while it encrypts data.
Sounds wild, right? But it’s a real attack. It’s called Side Channel Analysis (SCA).
And if that didn’t work, I had a backup plan: Voltage Glitching - where you mess with the chip’s power supply at exactly the right moment to make it skip security checks.
Spoiler: Neither worked. But I learned exactly why they didn’t work, and that’s actually more valuable than if they had.
Why Even Try This?
You know how we assume cryptography is secure? We think: “My device uses AES-128 encryption. The key is 128 bits. No one can crack that.”
And mathematically, you’re right. Brute-forcing AES-128 would take longer than the age of the universe.
But here’s the thing: Math doesn’t account for physics.
When your chip encrypts data, it consumes power. And that power consumption changes based on what data it’s processing. Those tiny fluctuations? They leak information about the secret key.
This isn’t theoretical. It’s how real attacks happen.
STM32 microcontrollers are everywhere:
-
Smart home devices
-
Car electronics
-
Industrial sensors
-
Medical devices
-
IoT gadgets you use every day
If someone with physical access can extract keys from a development board, they can do it to production devices too.
So I wanted to see: How hard is it, really?
The Target: STM32 Nucleo F303RE
I used an STM32 Nucleo F303RE development board. It’s cheap, widely available, and runs an ARM Cortex-M4 processor.
I programmed it with AES-128 encryption firmware. And I enabled Readout Protection (RDP) - the built-in security feature that’s supposed to prevent exactly what I was trying to do.
The goal:
-
Capture power traces while the chip encrypts data
-
Use Correlation Power Analysis (CPA) to extract the AES key
-
If that fails, try voltage glitching to bypass the protection
Sounds straightforward. It wasn’t.
The Tool: ChipWhisperer Lite
For this kind of attack, you need specialized hardware. I used the ChipWhisperer Lite.
Think of it as an oscilloscope specifically designed for side-channel attacks. It can:
-
Provide power to the target board
-
Capture high-speed power measurements
-
Trigger captures at precise moments
-
Inject voltage glitches
It’s essentially the standard tool for hardware security research.
Step 1: Destroying the Board (On Purpose)
Development boards are designed for convenience, not side-channel analysis. They have:
-
Voltage regulators that smooth out power
-
Decoupling capacitors that filter noise
-
Multiple power domains running in parallel
All of these things hide the signal I’m trying to measure.
So I had to modify the board. Aggressively.
Modification 1: Power Domain Isolation
The STM32 Nucleo has a solder bridge called SB2 that connects the onboard voltage regulator to the MCU’s power rail.
This is a problem because:
-
The regulator draws its own current, contaminating my measurements
-
It dampens voltage glitches before they reach the chip
Solution: Cut the solder bridge.
I carefully removed the solder connecting SB2, physically separating the ST-Link programmer’s power domain from the microcontroller’s power domain.
Now the ChipWhisperer is the only power source for the MCU.
Modification 2: Ripping Out Capacitors
Next target: Decoupling capacitors.
These are the tiny components soldered near the MCU that filter out high-frequency noise. Normally, they’re essential for stable operation.
But for side-channel analysis, they’re the enemy.
Why? Because the “noise” they filter out is exactly the signal I need. When AES runs, the chip’s logic gates switch states, causing tiny spikes in current draw. Those spikes carry information about the key.
Decoupling capacitors smooth out those spikes. They turn a sharp, information-rich signal into a flat, useless blur.
So I desoldered them. All of them.
The board became less stable. It might crash more easily. But the power traces became clean.
Modification 3: Current Measurement Path
The Nucleo board has a jumper called JP6 for current measurement. I removed the jumper cap, creating a break in the VDD supply line.
Then I inserted a 10-ohm shunt resistor between the two pins.
Here’s how this works: Current flows through the resistor. Voltage drop across the resistor = Current × Resistance (Ohm’s law). The ChipWhisperer measures that voltage drop to reconstruct the current draw.
It’s like putting a glass window in the power line so you can see what’s flowing through it.
The Wiring
Here’s how everything connects:
-
ChipWhisperer 3.3V → JP6 right pin (power supply)
-
ChipWhisperer GND → STM32 GND (common ground)
-
ChipWhisperer TIO4 → STM32 PA5 (trigger signal)
-
ChipWhisperer measurement probe → JP6 left pin (voltage measurement across shunt)
Critical detail: Remove ALL other jumpers. No ST-Link power. No USB power. Nothing.
If you leave anything else connected, it injects noise into your traces and ruins everything.
The Software Side
Programming the Target
I flashed simple AES firmware onto the STM32. The code looks like this:
// Trigger HIGH
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
// AES operation
AES_encrypt(input, key, state);
// Trigger LOW
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
The trigger pin (PA5) goes HIGH right before AES starts and LOW right after it finishes.
This tells the ChipWhisperer: “Start recording NOW.”
Without this timing signal, the ChipWhisperer would be blindly recording random power consumption with no idea when the interesting part happens.
Configuring the ChipWhisperer
I set up the capture parameters:
scope = cw.scope()
scope.clock.clkgen_freq = 8E6 # 8 MHz clock
scope.clock.adc_src = "clkgen_x4" # ADC samples at 4x = 32 MHz
scope.adc.samples = 3000 # Capture 3000 data points
scope.adc.offset = 200 # Start 200 samples after trigger
scope.adc.basic_mode = "rising_edge" # Trigger on rising edge
Translation:
-
The chip runs at 8 MHz
-
The ADC (Analog-to-Digital Converter) samples at 32 MHz
-
Each capture records 3000 samples
-
Triggering happens on the rising edge of the trigger signal
This configuration is critical for synchronization. If your traces aren’t aligned, correlation analysis fails.
First Capture: “What Am I Even Looking At?”
I ran the capture script. The ChipWhisperer recorded a trace.
I plotted it.
It looked like complete noise.
No clear pattern. No distinguishable structure. Just random voltage fluctuations.
“Maybe I need more traces,” I thought.
Attempt 2: Overlay 300+ Traces
In side-channel analysis, you capture hundreds or thousands of traces and average them together. The random noise cancels out, and the signal emerges.
So I captured 300+ traces and overlaid them.
Still nothing.
A proper AES trace should show:
-
Clear, repeating patterns (the 10 AES rounds)
-
Bursts of activity at specific intervals
-
Traces that align perfectly when overlaid
Mine showed none of that. Just a mess of colored lines that didn’t converge.
Attempt 3: Filtering and Processing
Maybe the signal is buried in noise? Let me try signal processing.
I applied:
-
High-pass filtering - to remove low-frequency drift
-
Differentiation - to highlight rapid changes
-
Averaging - to reduce random noise
Still nothing useful. No AES rounds. No structure. Just processed noise.
Attempt 4: Offset Sweep
Maybe I’m capturing the wrong time window? Maybe AES is happening somewhere else?
I ran an offset sweep - capturing traces at different time offsets to scan through the entire execution window.
Results:
-
Big spike at sample 0 (that’s the trigger pulse)
-
Flat, low-amplitude signal everywhere else
-
No sudden bursts of activity
-
No region showing AES-like patterns
Conclusion: I’m not capturing AES at all.
The Moment of Truth: Trigger Verification
I went back to basics. Is the trigger even working?
I monitored the trigger pin states in real-time:
Monitoring TIO states...
Toggle your trigger pin in firmware!
(1, 0, 0, 0)
(1, 0, 0, 0)
(1, 0, 0, 0)
(1, 0, 0, 0)
...
Wait.
The trigger state never changes. It’s stuck at (1, 0, 0, 0).
The pin isn’t toggling. The ChipWhisperer isn’t receiving the trigger signal.
That’s the problem.
What This Means
Without a working trigger:
-
The ChipWhisperer captures at random times
-
There’s no synchronization with AES execution
-
Every trace is meaningless
It doesn’t matter if AES is running. It doesn’t matter if power consumption is leaking information. If you’re not capturing at the right moment, you capture nothing.
It’s like trying to photograph lightning without knowing when it strikes. You just get pictures of empty sky.
Why Did This Happen?
I can think of a few reasons:
1. Wiring issue
-
Maybe the trigger wire isn’t making good contact
-
Maybe there’s a loose connection somewhere
2. Firmware problem
-
Maybe the GPIO pin isn’t configured correctly
-
Maybe the code isn’t actually running
3. Voltage level mismatch
-
The STM32 outputs 3.3V logic
-
The ChipWhisperer expects 3.3V input
-
But maybe there’s an impedance issue or signal degradation
4. Timing issue
-
Maybe the trigger pulse is too short
-
Maybe the ChipWhisperer’s trigger detection threshold is wrong
I need to debug this systematically with an oscilloscope to see what’s actually happening on that wire.
The Glitching Plan (That Never Happened)
I also wanted to try voltage fault injection.
The idea: Send a brief voltage spike or drop to the chip’s power rail at exactly the right moment. This can cause:
-
Instruction skips (the CPU misses an operation)
-
Bit flips in memory
-
Logic errors in comparisons
For example, if the firmware checks the RDP protection level like this:
if (rdp_level == LEVEL_1) {
// Block debug access
}
A well-timed glitch might corrupt that comparison, making the chip think protection is disabled.
But you need a working trigger to know when to glitch. Without timing synchronization, you’re just randomly zapping the chip and hoping something breaks.
So I couldn’t test this either.
What I Learned (The Hard Way)
1. Trigger Signals Are Critical
Side-channel analysis is 90% about timing. If you can’t synchronize your captures with the target operation, nothing else matters.
2. Hardware Modifications Are Necessary
You can’t just plug a dev board into a ChipWhisperer and expect it to work. You need to:
-
Isolate power domains
-
Remove filtering components
-
Insert measurement shunts
-
Verify every connection
3. Debugging Is Non-Negotiable
When something doesn’t work, you need to trace the problem systematically:
-
Verify wiring
-
Check trigger signals
-
Inspect firmware
-
Validate ADC settings
-
Test each component individually
4. Failure Is Part of the Process
I didn’t extract any keys. I didn’t bypass any protection. But I learned exactly where the setup breaks and how to fix it.
That’s progress.
Why This Matters for IoT Security
Even though I failed, this experiment shows something important: Side-channel attacks are real, and they’re not that hard to attempt.
I used:
-
A $200 ChipWhisperer
-
A $15 dev board
-
Open-source software
-
Basic soldering skills
The barrier to entry is low. And once you get the trigger working correctly (which I will eventually), the attack pipeline is well-documented and repeatable.
Production IoT devices often use the same STM32 chips. If they expose debug ports, use weak protection levels, or rely solely on RDP, they’re vulnerable.
What Actually Stops These Attacks?
1. No physical access
-
If an attacker can’t touch the device, they can’t attack it
-
Tamper-evident enclosures help
-
Potting (encasing in epoxy) makes hardware access very difficult
2. Remove debug interfaces
-
Don’t expose SWD/JTAG pins on production boards
-
Use one-time programmable (OTP) fuses to permanently disable debug
3. Use proper RDP levels
-
RDP Level 2 permanently locks the chip
-
No debug, no firmware extraction, ever
-
Downside: If something breaks, the chip is dead
4. Power supply filtering
-
Keep decoupling capacitors in production devices
-
Add extra filtering to smooth power consumption
-
Makes side-channel attacks much harder
5. Randomized execution
-
Add random delays in crypto operations
-
Shuffle AES round order
-
Desynchronizes power traces
6. Use secure elements
-
Offload key storage to dedicated crypto chips
-
Even if the MCU is compromised, keys are safe
7. Detect glitching attempts
-
Monitor supply voltage for anomalies
-
Reset or shut down if glitches detected
None of these are perfect. But layered together, they make attacks exponentially harder.
What’s Next?
I’m not giving up on this. Here’s what I need to do:
Immediate fixes:
-
Use an oscilloscope to verify the trigger signal on PA5
-
Check firmware GPIO configuration
-
Test with a known-good trigger setup
-
Validate ChipWhisperer trigger detection settings
Once the trigger works:
-
Capture clean, synchronized AES traces
-
Perform CPA to extract the key (with RDP disabled first)
-
Re-enable RDP and see if the attack still works
-
Attempt voltage glitching to bypass RDP
Advanced experiments:
-
Test different glitch widths, offsets, and amplitudes
-
Try instruction-skip attacks on bootloader checks
-
Compare attack success rates with different STM32 models
The Bigger Lesson
This experiment didn’t go as planned. I didn’t break encryption. I didn’t bypass security. I spent hours modifying hardware and writing code just to discover that my trigger wasn’t working.
But here’s the thing: This is what real hardware hacking looks like.
It’s not like the movies where you plug in a USB stick and bypass all security in 30 seconds. It’s:
-
Careful hardware modification
-
Systematic debugging
-
Failed attempts
-
Learning from mistakes
-
Iterating until it works
And when it finally does work, you’ll understand the system at a level that no amount of reading documentation can teach you.
That’s the point.
Technical Summary
Target Hardware:
-
STM32 Nucleo F303RE
-
ARM Cortex-M4 processor
-
AES-128 encryption firmware
-
RDP Level 1 enabled
Attack Hardware:
-
ChipWhisperer Lite
-
10-ohm shunt resistor
-
Modified target board (power isolated, capacitors removed)
Attack Method:
-
Correlation Power Analysis (CPA)
-
Voltage fault injection (planned)
Modifications Made:
-
Removed solder bridge SB2 (power isolation)
-
Removed decoupling capacitors (signal clarity)
-
Removed JP6 jumper (current measurement path)
-
Inserted shunt resistor (current sensing)
Configuration:
-
Clock: 8 MHz
-
ADC sample rate: 32 MHz
-
Capture length: 3000 samples
-
Trigger mode: Rising edge
Result:
-
Key extraction: Failed
-
Root cause: Trigger signal not reaching ChipWhisperer
-
Captured traces: Unsynchronized, analytically invalid
Status:
-
Hardware setup: Complete
-
Trigger issue: Identified but not resolved
-
Next step: Debug trigger signal with oscilloscope
Key Takeaways
-
Side-channel attacks exploit physics, not math - Cryptography can be perfect, but hardware leaks information through power, timing, and electromagnetic radiation.
-
Trigger synchronization is everything - Without precise timing, power traces are useless noise.
-
Hardware modification is required - Development boards are designed for convenience, not attack resistance. You need to strip away protections to see the raw signal.
-
Debugging is 90% of the work - When attacks fail, it’s usually not because the attack is impossible, but because something in your setup is broken.
-
Physical access changes everything - Software security doesn’t matter if an attacker can manipulate hardware directly.
-
Defense requires layers - No single protection mechanism is sufficient. You need multiple overlapping defenses.
-
Failure teaches more than success - I learned exactly where this attack breaks and how to fix it. That’s more valuable than blindly following a tutorial that works.
This was a security research experiment to understand hardware attack techniques. The goal is to improve embedded system security by understanding real attack vectors. If you’re building IoT devices, please implement proper security measures - your users depend on it.
Want to see this attack work? I’ll post a follow-up once I get the trigger fixed and successfully extract an AES key. Subscribe to stay updated.
And if you’re working on similar hardware security research, let me know what I missed. I’m always learning.








