As of August 2020 the site you are on (wiki.newae.com) is deprecated, and content is now at rtfm.newae.com. |
Difference between revisions of "Tutorial A5-Bonus Breaking AES-256 Bootloader"
(→Background: Added source code) |
(Moved source code) |
||
Line 7: | Line 7: | ||
* Repeat of theory from tutorial | * Repeat of theory from tutorial | ||
− | == | + | == The IV == |
− | + | * Suggest some ideas | |
+ | == The Signature == | ||
+ | * Timing attack | ||
+ | * Show firmware | ||
− | + | = Exploring the Bootloader = | |
+ | 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. | ||
+ | |||
+ | == Bootloader Source Code == | ||
+ | Inside the bootloader's main loop, it does three tasks that we're interested in: | ||
+ | * it decrypts the incoming ciphertext; | ||
+ | * it applies the IV to the decryption's result; and | ||
+ | * it checks for the signature in the resulting plaintext. | ||
+ | This snippet from <code>bootloader.c</code> shows all three of these tasks: | ||
<pre> | <pre> | ||
Line 42: | Line 53: | ||
} | } | ||
</pre> | </pre> | ||
− | |||
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 | 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 | ||
<pre> | <pre> | ||
Line 103: | Line 113: | ||
3a2: 87 cf rjmp .-242 ; 0x2b2 | 3a2: 87 cf rjmp .-242 ; 0x2b2 | ||
</pre> | </pre> | ||
− | |||
− | == | + | We'll use both of the source files throughout the tutorial. |
− | + | ||
− | == | + | == Power Traces == |
− | + | ||
− | + | ||
+ | == Matching Power to Code == | ||
+ | |||
= Attacking the IV = | = Attacking the IV = |
Revision as of 06:05, 23 June 2016
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.
This tutorial is under construction! Check back in a few days.
Contents
Background
AES in CBC Mode
- Repeat of theory from tutorial
The IV
- Suggest some ideas
The Signature
- Timing attack
- Show firmware
Exploring the Bootloader
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 supersecret.h
counts as cheating.) Instead, we'll use the source to help us identify important parts of the power traces.
Bootloader Source Code
Inside the bootloader's main loop, it does three tasks that we're interested in:
- it decrypts the incoming ciphertext;
- it applies the IV to the decryption's result; and
- it checks for the signature in the resulting plaintext.
This snippet from bootloader.c
shows all three of these tasks:
// Continue with decryption trigger_high(); aes256_decrypt_ecb(&ctx, tmp32); trigger_low(); // Apply IV (first 16 bytes) for (i = 0; i < 16; i++){ tmp32[i] ^= iv[i]; } //Save IV for next time from original ciphertext for (i = 0; i < 16; i++){ iv[i] = tmp32[i+16]; } // Tell the user that the CRC check was okay putch(COMM_OK); putch(COMM_OK); //Check the signature if ((tmp32[0] == SIGNATURE1) && (tmp32[1] == SIGNATURE2) && (tmp32[2] == SIGNATURE3) && (tmp32[3] == SIGNATURE4)){ // Delay to emulate a write to flash memory _delay_ms(1); }
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
avr-objdump -m avr -D bootloader.hex > disassembly.txt
This will convert the hex file into assembly code, making it more human-readable. The important part of this assembly code is:
344: d3 01 movw r26, r6 346: 93 01 movw r18, r6 348: f6 01 movw r30, r12 34a: 80 81 ld r24, Z 34c: f9 01 movw r30, r18 34e: 91 91 ld r25, Z+ 350: 9f 01 movw r18, r30 352: 89 27 eor r24, r25 354: f6 01 movw r30, r12 356: 81 93 st Z+, r24 358: 6f 01 movw r12, r30 35a: ee 15 cp r30, r14 35c: ff 05 cpc r31, r15 35e: a1 f7 brne .-24 ; 0x348 360: fe 01 movw r30, r28 362: b1 96 adiw r30, 0x21 ; 33 364: 81 91 ld r24, Z+ 366: 8d 93 st X+, r24 368: e4 15 cp r30, r4 36a: f5 05 cpc r31, r5 36c: d9 f7 brne .-10 ; 0x364 36e: 84 ea ldi r24, 0xA4 ; 164 370: 0e 94 16 02 call 0x42c ; 0x42c 374: 84 ea ldi r24, 0xA4 ; 164 376: 0e 94 16 02 call 0x42c ; 0x42c 37a: 89 89 ldd r24, Y+17 ; 0x11 37c: 88 23 and r24, r24 37e: 09 f0 breq .+2 ; 0x382 380: 98 cf rjmp .-208 ; 0x2b2 382: 8a 89 ldd r24, Y+18 ; 0x12 384: 8b 3e cpi r24, 0xEB ; 235 386: 09 f0 breq .+2 ; 0x38a 388: 94 cf rjmp .-216 ; 0x2b2 38a: 8b 89 ldd r24, Y+19 ; 0x13 38c: 82 30 cpi r24, 0x02 ; 2 38e: 09 f0 breq .+2 ; 0x392 390: 90 cf rjmp .-224 ; 0x2b2 392: 8c 89 ldd r24, Y+20 ; 0x14 394: 8d 31 cpi r24, 0x1D ; 29 396: 09 f0 breq .+2 ; 0x39a 398: 8c cf rjmp .-232 ; 0x2b2 39a: 83 e3 ldi r24, 0x33 ; 51 39c: 97 e0 ldi r25, 0x07 ; 7 39e: 01 97 sbiw r24, 0x01 ; 1 3a0: f1 f7 brne .-4 ; 0x39e 3a2: 87 cf rjmp .-242 ; 0x2b2
We'll use both of the source files throughout the tutorial.
Power Traces
Matching Power to Code
Attacking the IV
Steps:
- Investigation
- Look at bootloader code
- Move trigger
- Record 1
- Show different instructions in trace
- Making the attack feasible
- Capture a bunch (500?)
- Apply decryption
- Look at one bit
- Find means + plot
- Find differences + plot
- Automating the attack
- Finding the attack points
- Getting a single bit
- Building the IV bytes
- Full script in appendix
Example:
#Imports for IV Attack from Crypto.Cipher import AES def initPreprocessing(self): self.preProcessingResyncSAD0 = preprocessing.ResyncSAD.ResyncSAD(self.parent) self.preProcessingResyncSAD0.setEnabled(True) self.preProcessingResyncSAD0.setReference(rtraceno=0, refpoints=(6300,6800), inputwindow=(6000,7200)) self.preProcessingResyncSAD1 = preprocessing.ResyncSAD.ResyncSAD(self.parent) self.preProcessingResyncSAD1.setEnabled(True) self.preProcessingResyncSAD1.setReference(rtraceno=0, refpoints=(4800,5100), inputwindow=(4700,5200)) self.preProcessingList = [self.preProcessingResyncSAD0,self.preProcessingResyncSAD1,] return self.preProcessingList class AESIVAttack(object): numSubKeys = 16 @staticmethod def leakage(textin, textout, guess, bnum, setting, state): knownkey = [0x94, 0x28, 0x5D, 0x4D, 0x6D, 0xCF, 0xEC, 0x08, 0xD8, 0xAC, 0xDD, 0xF6, 0xBE, 0x25, 0xA4, 0x99, 0xC4, 0xD9, 0xD0, 0x1E, 0xC3, 0x40, 0x7E, 0xD7, 0xD5, 0x28, 0xD4, 0x09, 0xE9, 0xF0, 0x88, 0xA1] knownkey = str(bytearray(knownkey)) ct = str(bytearray(textin)) aes = AES.new(knownkey, AES.MODE_ECB) pt = aes.decrypt(ct) return getHW(bytearray(pt)[bnum] ^ guess)
Appendix D AES-256 IV Attack Script
NB: This script works for 0.10 release or later, see local copy in doc/html directory of chipwhisperer release if you need earlier versions
Full attack script, copy/paste into a file then add as active attack script:
#IV Attack Script from chipwhisperer.common.autoscript import AutoScriptBase #Imports from Preprocessing import chipwhisperer.analyzer.preprocessing as preprocessing #Imports from Capture from chipwhisperer.analyzer.attacks.CPA import CPA from chipwhisperer.analyzer.attacks.CPAProgressive import CPAProgressive import chipwhisperer.analyzer.attacks.models.AES128_8bit # Imports from utilList # Imports for AES256 Attack from chipwhisperer.analyzer.attacks.models.AES128_8bit import getHW #Imports for IV Attack from Crypto.Cipher import AES class AESIVAttack(object): numSubKeys = 16 @staticmethod def leakage(textin, textout, guess, bnum, setting, state): knownkey = [0x94, 0x28, 0x5D, 0x4D, 0x6D, 0xCF, 0xEC, 0x08, 0xD8, 0xAC, 0xDD, 0xF6, 0xBE, 0x25, 0xA4, 0x99, 0xC4, 0xD9, 0xD0, 0x1E, 0xC3, 0x40, 0x7E, 0xD7, 0xD5, 0x28, 0xD4, 0x09, 0xE9, 0xF0, 0x88, 0xA1] knownkey = str(bytearray(knownkey)) ct = str(bytearray(textin)) aes = AES.new(knownkey, AES.MODE_ECB) pt = aes.decrypt(ct) return getHW(bytearray(pt)[bnum] ^ guess) class userScript(AutoScriptBase): preProcessingList = [] def initProject(self): pass def initPreprocessing(self): self.preProcessingResyncSAD0 = preprocessing.ResyncSAD.ResyncSAD(self.parent) self.preProcessingResyncSAD0.setEnabled(True) self.preProcessingResyncSAD0.setReference(rtraceno=0, refpoints=(6300,6800), inputwindow=(6000,7200)) self.preProcessingResyncSAD1 = preprocessing.ResyncSAD.ResyncSAD(self.parent) self.preProcessingResyncSAD1.setEnabled(True) self.preProcessingResyncSAD1.setReference(rtraceno=0, refpoints=(4800,5100), inputwindow=(4700,5200)) self.preProcessingList = [self.preProcessingResyncSAD0,self.preProcessingResyncSAD1,] return self.preProcessingList def initAnalysis(self): self.attack = CPA(self.parent, console=self.console, showScriptParameter=self.showScriptParameter) self.attack.setAnalysisAlgorithm(CPAProgressive, AESIVAttack, None) self.attack.setTraceStart(0) self.attack.setTracesPerAttack(100) self.attack.setIterations(1) self.attack.setReportingInterval(25) self.attack.setTargetBytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) self.attack.setTraceManager(self.traceManager()) self.attack.setProject(self.project()) self.attack.setPointRange((4800,6500)) return self.attack def initReporting(self, results): results.setAttack(self.attack) results.setTraceManager(self.traceManager()) self.results = results def doAnalysis(self): self.attack.doAttack()