Sécurité et Canaux Auxiliaires CPA on AES

Transcription

Sécurité et Canaux Auxiliaires CPA on AES
Sécurité et Canaux Auxiliaires
CPA on AES
24 octobre 2014
Pré-requis : avoir installé Chipwhisperer 0.7, avr-gcc, avrdude, Python 2.7 (avec les librairies
PyUSB, NumPy, SciPy, PyCrypto).
Exercice - 1 Mise en place du TP
Objectifs de l’exercice : utiliser les outils avr-gcc et avrdude, comprendre le fonctionnement de
”simpleserial.hex”, savoir charger et exécuter un code sur un composant de type carte à puce.
1. Éditer le code simpleserial.c (et donc le fichier généré simpleserial.hex) et modifier le pour qu’il
permette d’effectuer les opérations suivantes sur la carte :
– Charger une clef AES avec la commande ”sk0 k1 · · · k15 ” où s est un caractère special et les ki ,
i ∈ [0..15], sont les octets de clefs codés en hexadécimal.
– Charger un message avec la commande ”mp0 p1 · · · p15 ” où m est un caractère spécial et les pi ,
i ∈ [0..15], sont les octets du message codés en hexadécimal.
– Lorsque la clef et le message ont été chargé, effectuer le calcul AES(k, p) et renvoyer le résultat
sous la forme ”rc0 c1 · · · c15 ” où r est un caractère spécial et les ci , i ∈ [0..15], sont les octets du
texte chiffré codés en hexadécimal.
2. A l’aide de la commande make MCU=atmega328p générer le fichier ”simpleserial.hex” correspondant
au nouveau code.
3. Charger le fichier ”simpleserial.hex” dans le composant ATMega328p à l’aide de la commande
make MCU=atmega328p program (éventuellement après avoir modifié le fichier Makefile à la ligne
317 en remplaçant jtag2isp par avrispmkII).
Exercice - 2 Acquisition des traces
Objectifs de l’exercice : apprendre à utiliser l’outil ChipWhisspererCapture, comprendre le
fonctionnement de l’oscilloscope ChipWhisperer et appréhender les problématiques liées à la recherche d’un signal sensible pour mener une attaque de type DPA.
1. Lancer l’outil ChipWhispererCapture (se trouvant dans le répertoire ”.../chipwhisperer-0.07/software/chipwhisperer/ca
Dans le menu ”General Settings”, choisir ”ChipWhisperer/OpenADC” pour ”Scope Module” et
”Simple Serial” pour ”Target Module”. Dans le menu ”Target Settings”, choisir ”ChipWhisperer”
pour le champs ”connexion”, puis adapter les commandes au nouveau code développé dans l’exercice 1. Charger la configuration du Firmware (Tools→Download CW Firmware). Enfin, cliquer sur
le bouton Com correspondant à Master.
2. Exécuter un chiffrement AES et étudier l’acquisition correspondante. Jouer avec les différentes
options de l’oscilloscope pour améliorer l’acquisition (on pourra par exemple s’appuyer sur l’aide en
ligne disponible à l’adresse http://www.newae.com/sidechannel/cwdocs/hwmultitarget.html).
Prendre note de la meilleure configuration obtenue.
Exercice - 3 Scripter l’acquisition des traces
1
CPA on AES
TP ChipWhisperer n2 – 2014 – 2015
Objectifs de l’exercice : apprendre à utiliser Python pour communiquer avec la carte, programmer sous Python une campagne d’acquisition.
1. Modifier le fichier ”script Exo3 1.py” pour lancer ”ChipWhispererCatpure” avec la spécification de
l’oscilloscope telle que cela a été fait lors du précédent exercice. On pourra s’aider du tutoriel disponible à l’adresse http://www.newae.com/sidechannel/cwdocs/tutorialtimingsimple.html
(attention d’adapter les chemins d’accès aux fichiers à votre environnement de travail).
2. Modifier le fichier ”script Exo3 1.py” pour exécuter un nombre n de chiffrement AES avec un clef
fixe choisie et n messages de 16 octets générés aléatoirement. Le script doit également lire le résultat retourné par la carte et le comparer au résultat attendu (pour cela on utilisera le librairie PyCrypto). Pour se faire on pourra utiliser les commandes suivantes de la classe ChipWhispererCapture.target.driver.s
– con() [permet de se connecter au port série],
– flush() [permet d’effacer le buffer d’entrée],
– write() [écrire sur le buffer d’entrée],
– read() [lire sur le buffer d’entrée].
Aide : partir du fichier ”script Exo3 2.py” si vous n’avez pas bien réussi l’exercice 1.
Exemple de communications avec la carte :
1
2
# create an object ChipWhispererCapture
cap = cwc.ChipWhispererCapture()
3
4
5
6
#Connect to serial port
ser = cap.target.driver.ser
ser.con()
7
8
9
10
11
12
13
#Some useful commands to play with from GUI
ser.flush()
ser.write("k00112233445566778899AABBCCDDEEFF\n")
ser.write("pAABBCCDDEEFF00112233445566778899\n")
respdata = ser.read(33)
print "AES(k,p) = " + respdata
Exemple d’utilisation de PyCrypto :
1
2
3
4
5
6
from Crypto.Cipher import AES
key = ’0123456789abcdef’
mode = AES.MODE_ECB
cipher= AES.new(key, mode)
text = ’0123456789abcdef’
ciphertext = cipher.encrypt(text)
3. Pour chacun des n chiffrements effectués par le fichier ”script TP CPAOnAES template.py”, modifier le script pour mesurer la consommation de courant et sauvegarder chacune des traces mesurées dans un même fichier ”traces CPAOnAES.csv”. Chaque trace est enregistrée avec le format
suivant : [texte, clef, mesures] où texte est un tableau de 16 octets correspondants à l’entrée du
chiffrement, clef est un tableau de 16 octets correspondant à la clef secrète cherchée et mesures
est un tableau de t valeurs (où t a été défini par l’option OpenADC→Trigger Setup → Total
Samples).
Exemple d’utilisation de l’oscilloscope :
UPMC
2
CPA on AES
1
2
3
TP ChipWhisperer n2 – 2014 – 2015
from subprocess import call
import chipwhisperer.capture.ChipWhispererCapture as cwc
from chipwhisperer.capture.scopes.ChipWhispererExtra import CWPLLDriver
4
5
6
#Get main module
cap = cwc.ChipWhispererCapture()
7
8
9
#Show window − even if not used
cap.show()
10
11
12
#NB: Must call processEvents since we aren’t using proper event loop
pe()
13
14
15
16
17
cap.setParameter([’Generic Settings’, ’Scope Module’, ’ChipWhisperer/OpenADC’])
cap.setParameter([’Generic Settings’, ’Target Module’, ’Simple Serial’])
cap.setParameter([’Generic Settings’, ’Trace Format’, ’ChipWhisperer/Native’])
cap.setParameter([’Target Connection’, ’connection’, ’ChipWhisperer’])
18
19
20
21
#Load FW (must be configured in GUI first)
cap.FWLoaderGo()
22
23
24
25
26
#NOTE: You MUST add this call to pe() to process events. This is done automatically
#for setParameter() calls , but everything else REQUIRES this, since if you don’t
#signals will NOT be processed correctly
pe()
27
28
29
30
#Connect to scope
cap.doConDisScope(True)
pe()
31
32
# To fill ...
33
34
35
cap.scope.arm()
pe()
36
37
# To fill ...
38
39
40
41
42
if cap.scope.capture(update=True, NumberPoints=None, waitingCallback=pe):
print "Timeout"
else:
print "Capture OK"
43
44
# To fill ...
45
46
47
#Scope data is contained in scope . datapoints , print first 5 points only
print cap.scope.datapoints[0:4]
Exercice - 4 Attaque Correlation Power Analysis (CPA) sur les traces mesurées
Objectifs de l’exercice : apprendre à exécuter une attaque CPA sur des traces de consommation.
1. En C, écrire un code permettant d’extraire les textes et les mesures de consommation et de les
stocker dans deux tableaux unsigned char **t\_plaintexts et float **t\_traces. Tester le
code en affichant le contenu de certaines traces.
2. Ajouter une fonction permettant de calculer le coefficient de corrélation linéaire entre deux ensembles de valeurs flottantes. Cette fonction pourra avoir le format suivant :
UPMC
3
CPA on AES
1
2
3
4
5
6
7
8
9
TP ChipWhisperer n2 – 2014 – 2015
/∗! \fn float f correlationCoefficient ( float ∗X, float ∗∗Y,UINT v sampleSize)
\param X is a vector of size v samplesize , Y is a matrix with v sampleSize rows
\ brief process the correlation coefficient
\ brief corr(X,Y’[j ]) = (EXY − EX∗ EY)/(sqrt(EXX−EX∗EX)∗sqrt(EYY−EY∗EY))
\ brief where Y’[j ] corresponds to the jth row of the transpose of Y and
\ brief where EX (resp EY) denotes the mean and EXX (resp EYY) denotes the 2nd−order moment
\return an array of correlation values ( float ) (one correlation value for each j in [ v indexStart ..
v indexEnd]
∗/
float* f_correlationCoefficient (float *X, float **Y,UINT v_sampleSize,UINT v_indexStart,
UINT v_indexEnd)
Pour rappel le coefficient de corrélation linéaire ρ(X, Y ) entre deux ensembles de valeurs X = (xi )i
et Y = (yi )i de même taille n est défini par :
Pn
i=1 xi yi − nxy
ρ(X, Y ) = p Pn
Pn
( i=1 (xi − x)2 )(( i=1 (yi − y)2 ))
. Pn
. Pn
où x = n1 i=1 xi (resp. y = n1 i=1 yi ).
3. Modifier le code pour utiliser la fonction f_correlationCoefficient afin de calculer un vecteur de scores pour chaque hypothèse sur le premier octet de clef correspondant à l’exécution
d’AES associée aux traces dans le fichier ”traces CPAOnAES.csv”. Dans cette attaque, on ciblera
la manipulation de la sortie du premier calcul de la boite S de l’AES (notée S) lors du premier tour
du chiffrement. Pour calculer les prédictions associées à une hypothèse sur un octet de clef, on supposera que l’information fuit selon le modèle poids de Hamming (HW). Le code pourra s’appuyer
sur le canevas suivant :
1
2
3
4
5
6
// v sampleSize est le nombre de traces
// traceSize est le nombre de points par trace
// Dans le modele Poids de Hamming on a:
//
t predictions [ i ] = HW [S[v keyHyp ˆ t plaintext[i] ]]
for (unsigned int v_keyHyp = 0 ; v_keyHyp < 256 ; v_keyHyp++)
score [v_keyHyp] = f_correlationCoefficient (t_predictions,t_trace,v_sampleSize,0,
traceSize - 1)
Sauvegarder les vecteurs de scores correspondant à chacune des hypothèses dans un fichier ”scores.csv”.
4. Afficher les vecteurs de scores et en déduire la valeur de l’octet de clef recherché ainsi que les
instants durant lesquels cette donnée est manipulée.
UPMC
4