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