Advanced Encryption Standard résistant dans un contexte

Transcription

Advanced Encryption Standard résistant dans un contexte
Advanced Encryption Standard résistant dans un
contexte Boı̂te Blanche
Rémy REY
May 13, 2015
1
1
Introduction
L’Advanced Encryption Standart (AES) définit une référence pour la cryptographie symétrique moderne depuis 2000. Cependant, si sa conception le rend
résistant aux attaques sur un message chiffré, elle ne s’attaque ni au problème
de partage de clef qui relève de la cryptographie symétrique, ni au problème
de confiance en l’hôte (ou la machine) qui l’exécute. Il va de soi que la cryptographie asymétrique permet déjà d’échanger des clefs, ce ne sera donc pas le
problème soulevé ici.
En revanche, la sûreté de l’environnement d’exécution est une question épineuse.
Laisser une clef secrète en clair sur une machine possiblement infectée, ou entre les mains d’un tiers malveillant, peut être compromettant pour une zone de
sécurité (celle dont on donne l’accès avec la clef). Considérer un tel cas de figure
peut sembler étrange, c’est pourquoi il est nécessaire de se placer d’un point de
vue un peu particulier : celui de l’industrie multimédia.
En effet, l’industrie multimédia (maison de disques, studios, jeux vidéos, cinéma)
subit des pertes considérables à cause du piratage et du partage de fichier. C’est
pourquoi ils ont besoin de se prémunir des attaques sur le contenu distribué en
le chiffrant. Comme chaque utilisateur est un pirate potentiel, il faut donc introduire un contrôle de ces données, ce qu’on appelle la Gestion Numérique des
Droits ou DRM (Digital Right Managment en anglais). C’est ce contexte particulier qui nécessite un nouveau mode de cryptage. On doit pouvoir décrypter
sur la machine du client sans pour autant lui fournir la clef, et en personnalisant
l’algorithme pour restreindre l’utilisation à ce seul client.
Nous allons ici étudier une méthode, proposée à l’origine par Chow et al.[6] et
explicité par Muir[3] qui permet de transformer le standard pour tenter de le
rendre plus résistant, c’est-à-dire essayer de le protéger dans un contexte plus
général qu’a l’accoutumée.
2
A propos des différents contextes d’attaque
Pour comprendre l’enjeu de la construction, nous allons délimiter le contexte des
attaques sur le système de chiffrement. En effet, un cryptosystème n’a de sens
que lorsqu’il est plongé dans un contexte d’attaque bien défini. Il faut distinguer
les limites technologiques et les hypothèses d’attaque. Il est par exemple admis
que quelque soit la nature de l’attaquant, une attaque brute nécessitant 2100
opérations élémentaires est aujourd’hui hors de portée. En revanche, on peut
émettre certaines hypothèses concernant les connaissances de l’attaquant (sur
du hardware par exemple) ou sur son accès à l’exécution du programme cible.
Aussi une implantation, ou un système qui peut être considérer comme sûr dans
un contexte, ne fonctionnera plus forcément dans un contexte plus général. On
va donc définir trois contextes généraux d’attaque hiérarchisés pour expliquer
précisément pourquoi l’AES standard n’est plus adapté dans le cas évoqué en
introduction.
2.1
Boite Noire
La boı̂te noire est le cas le plus favorable pour la défense. On considère que
l’attaquant ne voit l’algorithme que comme un oracle qui répond selon les entrées
2
fournies. Les hypothèses sur les pouvoirs de l’attaquant peuvent influencer la
complexité des attaques : connaissance du clair, clair choisi, chiffré choisi, etc.
Un exemple simple est l’attaquant observant du trafic crypté sur le réseau.
Dans cette situation un AES standard en mode CBC est résistant et aucune
attaque praticable n’est à ce jour connue. Évidemment, cela nécessite d’avoir
des machines parfaitement sécurisées et que le client derrière la machine soit
quelqu’un de confiance, et cette hypothèse peut sembler utopiste. On comprend
bien qu’au delà d’une simple application aux DRM, le contexte de boı̂te noire
est peut être un peu trop restrictif et que le design d’algorithme plus résistant
va devenir une nécessité pour augmenter la sécurité.
2.2
Boite Grise
Ici, l’attaquant dispose bien évidemment de la boite noire, mais également d’un
accès indirect à l’exécution. Il va pouvoir déployer ce que l’on appelle les attaques par canaux auxiliaires (Side-channel Attacks en anglais). On peut collecter des données physiques lors de l’exécution comme le temps d’exécution, la
consommation énergétique, le bruit acoustique, les émanations électromagnétiques.
On va ensuite les mettre à profit pour en déduire des informations sur la clef
ou même l’implantation. On peut également essayer de générer des fautes en
espérant que la machine fuite des informations via ses registres ou sa RAM.
Un exemple simple de boı̂te grise est une carte bancaire. En effet, on connaı̂t
l’algorithme exécuté qui est issu des standards en la matière (donc soit RSA,
soit ECC) et on a accès à la carte (moyennant un peu de matériel, on peut
la questionner avec différentes entrées et récupérer ses réponses). Cependant,
l’architecture reste partiellement inconnue, et l’accès aux registres reste compliqué du fait des protections du hardware. On a donc un système relativement
bien protégé du point de vue purement informatique, et pourtant, il était à la
base très fragile à cause des informations physique émises.
Une des premières attaques développée passait par l’analyse de la consommation
énergétique de la carte. En effet, lors de l’exécution on doit porter un nombre m
à une puissance d qui se trouve être la clef secrète. La fonction d’exponentiation
associée est la suivante :
int p u i s s a n c e ( int m, int d ) =
{
i f ( d == 0 ) return 1 ;
int r e s = p u i s s a n c e (m, d >> 1 ) ;
res = res ∗ res ;
i f ( ! ( d && 1 ) ) {
return r e s ∗ m;
} else {
return r e s ;
}
}
Il s’agit de l’exponentiation rapide récursive. A chaque étape on élève au carré
et on divise l’exposant par deux, si l’exposant est impair, il faut une multiplication supplémentaire. Cette multiplication introduit une sur-consommation
3
d’énergie pour chaque bit de clef valant 1. On peut donc aisément lire sur un
oscilloscope la valeur de la clef.
Cette attaque est relativement simple et une contre-mesure fût apportée rapidement, en uniformisant le calcul :
int p u i s s a n c e ( int m, int d ) =
{
i f ( d == 0 ) return 1 ;
int r e s = p u i s s a n c e (m, d >> 1 ) ;
res = res ∗ res ;
i f ( ! ( d && 1 ) ) {
r e s = r e s ∗ m;
} else {
r e s ∗ m;
}
return r e s ;
}
La deuxième opération ne sert pas, mais génère quand même l’énergie nécessaire
pour uniformiser l’énergie mesurée.
On constate donc que même si un système présente les caractéristiques d’une
boı̂te noire, il est souvent difficile d’assurer ce contexte parfaitement. D’une
part les capteurs physiques deviennent de plus en plus puissants, d’autre part
on ne peut pas envisager tous les moyens d’attaques possibles, ce qui entraı̂ne
une course entre attaques et contre-mesures. Cela justifie déjà la volonté de se
placer dans le pire des cas qui soit et de supposer un attaquant tout puissant
sur la plate-forme d’exécution.
2.3
Boı̂te Blanche
On donne maintenant les pleins pouvoirs à l’attaquant. Il dispose d’un accès
complet à la machine et au code, peut exécuter le programme via un débogueur,
peut choisir autant d’entrées qu’il le souhaite, peut tenter de régénérer le code
source. Il faut donc apporter des contre-mesures à chacun des aspects évoqués
ci-dessus.
Le premier constat que l’on peut faire est que la clef ne doit pas apparaı̂tre en
clair dans la mémoire. Il est donc nécessaire de la diffuser dans l’algorithme
de manière à pouvoir l’utiliser sans la révéler. Un AES standard échoue déjà
à cette tâche puisqu’il faut lui donner la clef en clair en argument pour qu’il
fonctionne.
En ce qui concerne l’algorithmique et le reverse engineering, la tâche est plus
délicate. On peut supposer que l’adversaire connaı̂t l’algorithme utilisé, qu’il
a par exemple connaissance de cet article, et que par conséquent, il sait quel
type de données et de variables il doit chercher. L’offuscation du code source
constitue donc une solution mitigée. Elle ne servira après tout qu’à ralentir ou
à augmenter les ressources nécessaires à l’attaque. La question est de quantifier
cette apport de difficulté. Là encore le standard ne présente aucune protection
4
: le code source est disponible et l’exécution via un déboguer révèle la totalité
des informations.
Enfin le choix des entrées du programme est un problème. En effet, pouvoir
choisir ses entrées permet de monter une analyse statistique sur l’implantation
qui peut lâcher des informations sur une partie de la clef secrète, et donc diminuer la complexité d’une attaque. Il s’agira donc de modifier les entrées pour en
supprimer le contrôle.
La norme définie pour AES constitue un système résistant dans le cadre d’un
usage particulier (exécution dans un environnement de confiance). Nous voulons
prendre plus de cas d’attaque en ligne compte et cela souligne forcément les faiblesses du premier modèle plongé dans ce contexte. En contre partie, l’implantation
présentée ici n’atteindra pas les mêmes niveaux de résistances dans le contexte
boı̂te blanche (la complexité des attaques sera bien inférieure à 2128 si on dispose
du code source par exemple).
Commençons par analyser la composition de ce fameux algorithme.
3
Advanced Encryption Standart
Ce standard a été conçu en 2000 par Joan Daemen et Vincent Rijmen [1]. Il est
depuis décrit comme l’algorithme de référence pour la cryptographie symétrique
dans le FIPS 197[4].
3.1
Le corps fini de Rijndael
Commençons par définir le corps fini F28 . En effet les octets servent de représentation
aux éléments d’un corps spécial, défini lors de la conception du standard et qui
induit une opération particulière. D’un point de vue purement mathématique,
tous les corps de ce cardinal sont identiques, mais pour l’algorithmique, ils
diffèrent. Le choix effectué est donc celui d’une opération.
Le corps est défini comme l’ensemble des polynômes à coefficient binaire (i.e.
appartenant à F[X]) modulo un polynôme primitif. Un polynôme primitif P
est un polynôme irréductible, et de plus, si α était une racine de ce polynôme,
alors :
F2 (α)X = {αi , i = 1, . . . #F2 [α] − 1}
(1)
La racine d’un polynôme primitif génère les éléments inversibles du corps. On
note que #F2 [α] = deg(P ), il faut choisir le polynôme en relation avec la taille
de l’espace que l’on veut représenter.
Dans notre cas, nous choisissons le polynôme P (X) = X 8 +X 4 +X 3 +X 2 +1.
Chaque octet représente alors un polynôme de degré 7, chaque bit étant la valeur
du coefficient devant un monôme X i .
L’opération d’additionLest assez naturellement définie comme le ’ou exclusif’
logique (aka xor noté ).
L’opération de multiplication est définie comme la multiplication des polynômes
modulo le polynôme primitif P. Cela donne en pratique un algorithme particulier
sur les octets.
5
3.2
L’algorithme
L’algorithme de l’AES est composé de différentes opérations sur les 16 octets de
l’état. Ces opérations constituent le cœur de l’algorithme qui est répété dans
un certain nombre de rondes (de l’anglais round ).
Nous étudions ici la version 128 bits du standard, cependant les versions 192 et
256 bits ne diffèrent que par la génération de la clef complète et dans le nombre
d’itérations.
Nous détaillons ci-dessous les différentes opérations dans une optique de comprendre leur nécessité dans la conception et de déterminer une manière naturelle
et sécurisée d’y intégrer la clef.
Subbytes Opération de substitution des octets.
Pour rendre plus difficile la cryptanalyse, on choisit une bijection, fortement non linéaire. SubBytes compose une opération d’inversion dans le
corps fini de Rijndael F28 avec une transformation affine (explicité par
l’équation 2) sur le même corps vu en tant qu’espace vectoriel.






f (X) = 





1
1
1
1
1
0
0
0
0
1
1
1
1
1
0
0
0
0
1
1
1
1
1
0
0
0
0
1
1
1
1
1
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
1
1
1
1
0
0
0
1
1
1
1
1
1
0
0
0
1












•X +










1
1
0
0
0
1
1
0












(2)
Shiftrows Change l’ordre des octets dans l’état.
Cette opération est censé apporter la diffusion dans l’algorithme, c’est à
dire, mélanger au mieux les octets de l’état entre les différentes opérations.
En effet, chaque ronde opère en parallèle sur les quatre colonnes de l’état,
composée chacune de 4 octets. Il s’agit donc de mélanger ces colonnes en
décalant les lignes.
La première ligne reste en place, la deuxième est décalée de une case vers
la droite, la troisième de deux cases et la quatrième de trois cases.
0
1
2
3
4
5
6
7
8
9
10
11
12
0
5
13
⇒
10
14
15
15
4
9
14
3
8
13
2
7
12
1
6
11
(3)
Si on représente l’état en ligne, on obtient une permutation de Z/16Z qui
correspond également à la génération de ce groupe muni de l’addition, par
l’élément 5.
0
5
10
15
4
9
14
3
8
2
7
12
1
6
11
(4)
MixColumns Multiplication de chaque colonne de l’état avec une matrice MC.


02 03 01 01
 01 02 03 01 

MC = 
(5)
 01 01 02 03 
03 01 01 02
6
Figure 1: Schéma de ShiftRows avec deux état de 128 bits
Chaque colonne est considérée comme un vecteur de taille 4 à valeur dans
F28 . L’état devient les colonnes résultants des quatre multiplications avec
M C.
Cette opération linéaire sur les octets permet d’ajouter de la diffusion
entre les 4 valeurs d’une colonne de l’état. Du fait de sa combinaison avec
ShiftRows, à la fin d’une ronde la sortie devient dépendante de tous les
bits de l’entrée.
AddRoundKey opération binaire xor avec un bloc de 128 bits dérivés de la
clef.
Cette opération ajoute à chaque ronde une couche de confusion liée à
la clef. Cela permet de brouiller l’état à chaque exécution du cœur de
l’algorithme.
Déroulement L’algorithme consiste en une alternance de ces différentes opérations
sur 10 itérations (uniquement en AES 128 bit, le nombre est plus important pour les autres versions).
On peut noter la présence d’une ronde 0, où on ajoute seulement la clef
primitive (a partir de laquelle on va dériver 10 clefs secondaires de 128 bits
chacune). De plus, dans la dernière ronde, on n’effectue pas l’opération
MixColumns parce qu’elle n’apporte pas grand chose à la sécurité de
l’ensemble et qu’elle constituerait un surcoût inutile.
AddRoundKey(0)
for i in 1..9
SubBytes
Shiftrows
MixColumn
AddRoundKey(i)
SubBytes
Shitrows
AddRoundKey(10)
3.3
L’implantation de référence
Dans l’implantation, on manipule un état de 16 octets d’information (représenté
par une matrice de 4x4 octets).
L’implantation tabule les opérations au détriment d’un peu de place en mémoire.
Tabuler un ensemble d’opération f revient à pré-calculer la sortie associée à
chaque entrée possible, et à l’enregistrer dans une table. Ainsi, le programme
7
n’a plus qu’a lire la valeur f (x) à l’indice x de la table. L’idée est bien sûr
que l’ensemble des opérations correspondant à une table coûte plus cher qu’un
accès.
Pour le mode 128 bits, on dispose de 4 tables T ei (i ∈ 0..3), qui contiennent
chacune SubBytes et une partie de MixColumns (détails ci-dessous).
ShiftRows est effectué avant SubBytes en mappant les octets de l’état dans les
bonnes tables.
Une dernière opération xor avec un bloc de clef dérivée réalise le AddRoundKey(i).
Opération MixColumns
Pour cette opération, on décompose la multiplication du vecteur d’entrée (vecteurs
de 4 octets [x0 , x1 , x2 , x3 ]) par la matrice MC en quatre multiplication de colonnes
par un scalaire, et 3 xor.


01
01 
x
03  3
02
(6)
Chacune de ces multiplications de colonne par un scalaire x appartenant à
F256 est tabulé. On n’a donc qu’à lire la valeur dans la table correspondante
à l’indice x. Cette table comporte donc 256 entrées de mots de 32 bits, pour
relier chaque octet possible en entrée à un résultat.
Bien évidemment, l’opération de substitution des octets est également tabulée
et cette table est composée avec les quatre tables découlant de MixColumns ce
qui limite les accès lors de l’exécution.
En définitive, une ronde d’AES classique ne nécessite que 16 accès à des tableaux
ainsi que quelques opérations bits à bits (exactement 12 décalages, 12 and et 16
xor 32 bits).
02
 01

 01
03
4
03
02
01
01
01
03
02
01

01
x0
 x1
01 

03   x2
02
x3




02
  01 

=


  01  x0 ⊕
03


03

02 
 x ⊕
01  1 
01


01

03 
 x ⊕
02  2 
01
Implantation boite blanche
Nous allons a présent nous intéresser a la transformation de cet algorithme, en
une version boı̂te blanche. L’idée principale étant d’embarquer la clef au cœur
de l’implantation (et donc, de ne plus l’avoir comme entrée du programme) et
de la protéger par des couches d’offuscation aléatoires. La clef ne doit plus
apparaı̂tre dans les registres lors de l’exécution, et tous les éléments qui en
dépendent doivent être considérés comme autant de secrets à encrypter.
Le code que nous allons donc générer sera instancié avec une clef particulière et
ne pourra donc calculer les cipher de l’AES que pour cette clef. On peut dès
lors gérer la communication avec une personne sans lui confier le secret de la
clef.
4.1
Le principe de la protection
Pour mener a bien cette tâche, nous allons dans un premier temps tabuler toutes
les opérations. Avoir les opérations effectuées par la machine compromettrait
8
Figure 2: Schéma d’une partie de ronde
9
les opérandes, notamment les clefs de rondes dans AddRoundKey, parce qu’ils
seraient alors chargés en clair dans la mémoire.
On va reprendre le principe de l’implantation de référence (opérations du coeur
de ronde tabulées) mais altérer l’algorithme de manière a pouvoir intégrer l’ajout
de clef dans la table.
Modification de l’algorithme
for i in 1..9
Shiftrows
AddShiftedRoundKey(i-1)
SubBytes
MixColumn
Shitrows
AddShiftedRoundKey(9)
SubBytes
AddRoundKey(10)
ShiftRows opère sur l’ensemble des 128 bits d’état et ne peut pas être tabulée
(cela nécessiterait le montant irréalisable de 2128 × 128 bits en mémoire). On
va donc séparer cette opération du reste de la ronde.
SubBytes opère octet par octet, on peut la commuter avec ShiftRows (modifier
les octets avant ou après les avoir mélangés donne le même résultat).
Pour éviter d’avoir la clef primitive ajoutée seule, on décale chaque clef dans la
ronde suivante. Cette modification nécessite d’appliquer a chaque clef ShiftRows
pour conserver l’algorithme initial. La dernière ronde intègre alors l’ajout de la
9ème clef mélangée par ShiftRows en plus de SubBytes et l’ajout de la 10ème
clef non modifiée.
Tabulation des opérations
Le choix des tailles des tables (et donc des représentation utilisée pour les
opérations) est motivé par la nécessité d’un bon compromis sécurité/mémoire.
En effet, tabuler une fonction ayant n bits en entrée et m bits en sortie, nécessite
2n × m bits en mémoire. En poussant le raisonnement a l’extrême, on pourrait
tabuler l’opération complète de l’AES en générant une table de 2128 entrées possibles correspondant aux 2128 sorties qui donnerait immédiatement le résultat de
l’opération d’encryptage. Cependant, cela est inimaginable. En effet 2128 vaut
environ 3.4 × 1038 , on a donc une taille bien au delà de la capacité de stockage disponible sur la planète. On va donc choisir des implantations occupant
une taille raisonnable en mémoire et nous discuterons par la suite du niveau de
sécurité atteint.
Les opérations de l’AES, prennent chacune en entrée une taille spécifique, ce
qui induit plusieurs échelles pour le choix des tables.
L’implantation de référence utilise des tables de 256 valeurs (8 bits en entrée)
ce qui constitue un bon rapport mémoire/rapidité des opérations. C’est également
adapté a la représentation de l’état en octet, et au calcul de l’opération MixColumns. Nous allons reprendre ce modèle comme base de travail.
Les rondes sont calculées de la manière suivante : une première série de 16 tables
10
Taille de l’entrée
128 bits
32 bits
16 bits
8 bits
Taille de la sortie
128 bits
32 bits
32 bits
32 bits
Espace Mémoire nécessaire
2131 Go
17 Go
260 Ko
1 Ko
Table 1: Espace mémoire nécessaire a la tabulation d’une opération
notées (Ti ) donne pour chaque octet de l’état sk (en position i après ShiftRows),
une valeur sur 32 bits ti .
ti = MixColumnsi
mod 4
◦ SubBytes ◦ AddRoundKey(nround)i (sk )
Les ti sont alors ajoutés 4 à 4 via 3 séries de tables xor. Pour les raisons de
mémoire évoqué plus haut, ces tables prennent en entrée 2 × 4 bits et donnent le
résultat du xor bit à bit des deux nibbles. On est obligé de générer une nouvelle
table pour chaque opération xor à cause des encodages des tables que l’on va
introduire ci-dessous. Au final on obtient l’état avec une itération de plus.
s00−3 = t0 ⊕ t1 ⊕ t2 ⊕ t3
s04−7 = t4 ⊕ t5 ⊕ t6 ⊕ t7
s08−11 = t8 ⊕ t9 ⊕ t10 ⊕ t11
s012−15 = t12 ⊕ t13 ⊕ t14 ⊕ t15
Nous avons, pour l’instant, pour chaque ronde, 16 tables 8 à 32 bits (8 bits
en entrées, 32 en sortie) pour les opérations de ronde et un total de 96 tables 8
bits à 4 bits pour effectuer les 12 xor de 32 bits.
4.2
L’encodage
Nous disposons a présent de tables permettant de calculer une ronde, cependant
a partir des entrées et sorties de ces tables il sera aisé pour un attaquant de
retrouver les différentes clefs de ronde. En effet, étant donnée l’état après une
ronde, il suffit de calculer l’inverse de MixColumns ◦ SubBytes pour obtenir la
clef de ronde ajoutée a l’entrée.
n
SubBytes−1 ◦ MixColumns−1 (s00−3 ) = s0−3 ⊕ k0−3
C’est encore plus facile pour l’attaquant si il a accès à tout le contenu de ces
tables.
On comprend de ce fait la nécessité de considérer ces tables comme un véritable
secret qui ne doit pas être visible en clair sur la machine exécutant le programme.
4.2.1
La composition
Pour protéger le contenu d’une table, on va composer notre table représentant
une fonction P , avec deux bijections aléatoires F −1 et G. Ainsi le contenu de
la table devient aléatoire, et les entrées et sorties de la table ne sont plus compromettantes.
P → P 0 = F −1 ◦ P ◦ G
11
Figure 3: Table xor protégée
Si l’entrée de cette table P provient d’une table O, on va lier correctement les
bijections de manière à conserver le calcul originel à deux bijections près.
O → O0 = E −1 ◦ O ◦ F
O0 ◦ P 0 = (E −1 ◦ O ◦ F ) ◦ (F −1 ◦ P ◦ G) = E −1 ◦ (O ◦ P ) ◦ G
Pour complexifier le décodage, on va utiliser ce principe de composition aux
différents niveaux de calcul dans l’algorithme. Par exemple, on peut considérer
une ronde comme étant une seule opération et ajouter des fonctions entre les
rondes.
On va donc générer un grand nombre de bijections de différents types et opérant
sur différents espaces pour fondre les clefs dans les boı̂tes.
4.2.2
Les différents niveaux d’encodage
Boı̂tes
Pour protéger toutes les boı̂tes de l’implémentation, on va disposer des petites
bijections 4 × 4 bits qui seront des permutations de l’ensemble des mots de 4
bits. Ce format est imposé par les sorties des tables xor qui sont fixées à 4 bits.
Pour les autre boı̂tes (de 8 et 32 bits), on juxtapose simplement plusieurs de ces
bijections. Un travail de cartographie précis est nécessaire pour tenir compte
des correspondances entre entrées et sorties des différentes tables. Par exemple,
une seule table du cœur va alimenter 8 tables xor. D’une ronde a l’autre il
est également nécessaire de tenir compte de l’opération ShiftRows qui modifie
l’ordre des tables.
Ronde
On va également intégrer pour chaque ronde un codage linéaire, à l’aide de deux
matrices : L et M B. Elles sont appliquées respectivement en entrée et en sortie
des tables opérant AES. Pour annuler leur effet, on introduit de nouvelles tables
Oi en composant M Br−1 et L−1
r . on détaille leur construction ci-après.
12
Programme
Enfin nous intégrons des protections au niveau du programme. C’est-à-dire que
nous encodons l’entrée et la sortie du programme. Il s’agit d’encodages 8 × 8
bits qui sont composés avant les premières tables et après les dernières tables.
Cet encodage externe est nécessaire pour deux raisons.
D’abord il transforme la boı̂te qui à l’origine décrypte le contenu en une boı̂te
qui décode, puis décrypte, puis encode le contenu. Si cet encodage n’était pas
présent, la recherche de la clef ne serait plus forcément nécessaire puisqu’on
dispose de l’outil permettant de décrypter.
D’autre part, cet encodage offre une protection pour les premières et dernières
tables qui jusque là n’étaient encodées que d’un seul côté (qu’en sortie pour les
premières boı̂tes et qu’en entrée pour les dernières boı̂tes). Laisser ces boites
sans un double encodage laisserait le champ libre à l’exploitation d’une attaque
relativement accessible sur un ordinateur commun.
Comme pour les encodages de boı̂tes, on choisit des bijections aléatoires uniformément choisies parmi les permutations de l’ensemble des mots de 8 bits.
4.3
La diffusion
Les encodages aléatoires sont mis en place pour assurer la confusion. Maintenant
pour protéger le secret de la clef dans les tables, il est nécessaire d’ajouter de la
diffusion. Pour ce faire, nous intégrons les transformations linéaires (encodages
de rondes) aux tables de base.
La première (notée L) appliquée en entrée est diagonale par bloc. Chaque bloc
de 8 bits s’applique à une partie de la ronde (un octet de l’état) et son inverse
est appliquée à la ronde suivante sur le bloc correspondant (la rotation par
ShiftRows mélangeant les blocs).
La deuxième matrice MB doit assurer un maximum de diffusion pour chaque
colonne de l’état, c’est-à-dire pour 32 bits sur les 128. Pour maximiser son
efficacité, on recommande qu’elle soit composé de sous blocs 4 × 4 inversibles.
Ce choix est lié à la taille des bijections encodant toutes les boı̂tes. L’idée est de
faire dépendre au maximum chaque nibble de sortie de tous les autres nibbles.
Elle est donc appliquée à la sortie des opérations de l’AES et inversée lors de la
ronde suivante.
Pour chaque ronde, on construit 4 matrices MB composées de sous-blocs 4 × 4
inversibles et 4 matrices Li de 32 bits qui sont composées de 4 sous-blocs de 8 bits
(sur la diagonale). Sur chaque colonne i..i + 3, on applique d’abord la matrice
−1
M Bi..i+3 , puis on construit une autre table contenant l’opération M Bi..i+3
◦ Li .
L0−3
L0 (0) (0) (0)
(0) L1 (0) (0)
=
(0) (0) L2 (0)
(0) (0) (0) L3
M B 0−3
B1,1
= ...
B8,1
13
...
¨
...
B1,8
..
.
B8,8
Figure 4: Table du coeur protégée
Figure 5: Table introduite pour supprimer les effets de MB
14
Construction
Pour construire une telle matrice M B, nous employons la méthode inductive
développée par Xiao et Zhou[7] . Cette méthode commence avec des sous-blocs
de taille k et produit une matrice de taille n multiple de k dont tous les sousblocs de taille k sont de rang maximal. On va donc expliciter la méthode pour
n = 32 et k = 4.
Résultats Préliminaires
On va utiliser plusieurs résultats sur les matrices pour parvenir à construire
l’induction.
Tout d’abord, on utilise une décomposition matricielle relativement simple :
M = P × Ir × Q−1
où la matrice Ir est définie avec le rang r de la matrice M tel que :
Idr (0)
Ir =
(0) (0)
Une telle décomposition est accessible avec un pivot de Gauss. On stocke les
opérations sur les lignes dans une matrice, et les opérations sur les colonnes dans
l’autre matrice. Le pivot est exécuté sur les lignes jusqu’à atteindre le rang de la
matrice, on remonte ensuite en simplifiant les colonnes. A la fin, on se retrouve
avec la matrice Ir et dans les autres, les deux matrices de la décomposition. On
note que les opérations sur les lignes de la matrice M doivent être exécutées sur
les colonnes de la matrice P et celles sur les colonnes de M sur les lignes de
Q−1 . Du fait des opérations utilisées, les matrices P et Q−1 sont inversibles.
Une fois que nous disposons de cette décomposition, on construit des matrices
Ar , telles que Ar + Ir soit inversible. Comme la taille des matrices que nous
cherchons est 4, on peut les énumérer pour les 4 valeurs de r.




1 1 0 0
0 1 0 0
 1 0 0 0 
 1 0 0 0 



r = 1 A1 = 
 0 0 1 0  A1 + I1 =  0 0 1 0 
 0 0 0 1 
 0 0 0 1 
0 1 0 0
1 1 0 0
 1 1 0 0 
 1 0 0 0 



r = 2 A2 = 
 0 0 1 0  A2 + I2 =  0 0 1 0 
 0 0 0 1 
 0 0 0 1 
1 1 1 0
0 1 1 0
 1 1 0 0 
 1 0 0 0 



r = 3 A3 = 
 1 0 0 0  A3 + I3 =  1 0 1 0 
 0 0 0 1 
 0 0 0 1 
0 1 0 0
1 1 0 0
 1 1 0 0 
 1 0 0 0 



r = 4 A4 = 
 0 0 0 1  A4 + I4 =  0 0 1 1 
0 0 1 1
0 0 1 0
15
L’induction
Par la suite on s’intéresse à l’équation qui va permettre l’induction :
M 0
I M −1 Y
M
Y
•
=
X W
0
I
X XM −1 Y + W
M est une matrice carrée inversible de taille n = 4k. X et Y sont respectivement
des matrices de taille 4 × n et de taille n × 4. Si W est un bloc 4 × 4 inversible,
le membre de gauche est produit de deux matrices inversibles donc la matrice
de droite est une matrice carrée de taille n + 4 inversible.
On cherche donc à trouver une matrice W tel que la matrice XM −1 Y + W soit
un bloc inversible. Alors si M est constituée de blocs inversibles, en construisant
X et Y au hasard à partir de blocs inversibles, on réussit à générer une matrice
un peu plus grande, dont tous les sous-blocs de taille 4 sont inversibles.
En choisissant W = P Ar Q−1 avec r le rang de XM −1 Y et en utilisant les
résultats préliminaires, on obtient le résultat voulu.
Cette induction nous permet donc de générer une matrice M B de taille 32 × 32
dont tous les sous-blocs de taille 4 × 4 sont inversibles, tel que Chow et al.[6] le
recommandent.
L’induction présentée à la base par Xiao et Zhou généralise le concept à toutes
les tailles de matrices et hors du corps Z/2Z.
5
5.1
Les choix de conception
Taille et performance de l’implantation
Espace mémoire
Cette implantation totalise un nombre important de tables de tailles diverses.
Toutes les tables ont 256 entrées (8 bits), mais la valeur qu’elles rendent varie
en taille. On va distinguer les tables opérant les xor qui contiennent des nibbles,
les tables d’opérations qui du fait des matrices contiennent des mots de 32 bits,
et les tables de la dernière ronde qui contiennent des octets. Les tailles en octets
sont explicitées ci-dessous.
Type
xor
Opérations
Ronde 10
Taille sortie
4 bits
32 bits
8 bits
Nombre
1920
320
16
Espace total
245 Ko
327 Ko
4 Ko
On compte de plus les instructions intermédiaires pour effectuer les accès et
repositionner les variables (pour effectuer les xor 32 bits avec les 8 tables par
exemple).
En tout, le fichier binaire arrive à une taille de 2,3 Mo sur le disque. C’est donc
une taille qui reste raisonnable pour un transfert régulier via le réseau internet
par exemple. On reste donc dans le domaine du possible pour les applications
envisagées (principalement les DRM) et on peut même changer les clefs assez
souvent.
Cela reste cependant démesuré comparé au standard dont l’implémentation tient
en un peu moins de 5 ko.
16
17
Figure 6: Partie de ronde avec encodage complet
Temps d’exécution
L’ajout des protections a considérablement ralenti l’AES par rapport au standard (qui est optimisé rappelons-le).
Lors d’une exécution, on va accéder à chaque table exactement une fois soit
2256 fois. De plus, pour gérer les xor, on doit effectuer pour chaque table, deux
et logiques, deux ou logiques et deux décalages. soit un total de presque 12000
opérations binaires.
Par comparaison, l’implantation de base compte environ 500 opérations binaires
et 160 accès aux tables. Le rapport semble être de base de plus de 20 fois plus
lent. Dans la pratique on obtient un coefficient de l’ordre de 50 fois plus lent.
Ci-dessous, une expérience réalisée sur un ordinateur personnel (Macbook Pro
2011, MacOS X Yosemite, Intel Core i7 2.7 GHz).
Classique
Boite Blanche
Temps
162 ms
7.64 s
Débit
790 Mb/s
17 Mb/s
Nous avons seulement testé une boı̂te blanche nue. L’offuscation de cette
implantation nécessaire pour augmenter la protection va la ralentir.
6
Réflexions a posteriori
Nous avons produit une implantation primitive de boı̂te blanche pour AES. Elle
offre une couche de protection qui introduit déjà une certaine complexité pour
l’attaquant, cependant elle ne se suffit pas à elle-même.
Par exemple, on peut constater que la matrice M B peut simplement être ignorée. On ne prend donc plus en compte seulement les entrées et les sorties
au niveau de la ronde (entrées des boı̂tes Lri ◦ Ti ◦ M B et la deuxième série de
boites M B −1 ◦ Lr+1
). Le résultat possède l’apparence d’une boı̂te Lri ◦ Ti ◦ Lr+1
i
i
qui est plus facilement analysable. C’est d’ailleurs le point d’entrée de l’attaque
développée par Billet, Gilbert et Eisen[5]. Cette attaque peut s’effectuer en
moins de 230 opérations, ce qui en fait une attaque praticable causée par cette
faiblesse.
On ne comprend donc l’intérêt de tous les éléments présentés ici que dans un
contexte plus général. Il est nécessaire d’appliquer d’autres couches de protection, comme les encodages duaux proposés par Karroumi[2] et des techniques
plus génériques d’offuscation.
Dans l’état actuel, la cryptographie boı̂te blanche reste très empirique, et la
recherche se fait par tâtonnement (essais et contre-mesures associées se succèdent).
Il est nécessaire d’étendre le domaine en apportant différents exemples d’implantation
(variation des paramètres de taille des entrées, des clefs ou changement de
représentation, d’encodages). Nous pourrons alors espérer dégager des principes
qui permettront de construire des modèles génériques ou de valider les modèles
existants.
7
Remerciements
Mes remerciements vont d’abord à Mme Cani, notre professeur responsable du
module Introduction à la Recherche en Laboratoire, grâce à qui j’ai pu effectuer
18
ce travail de recherche. Je remercie également mon professeur référent M. ElbazVincent qui m’a proposé ce sujet d’étude, a suivi mes efforts tout au long du
semestre et m’a apporté de nombreuses références et connaissances. Je voudrais
encore remercier l’Ensimag et l’UJF pour permettre ce genre d’initiatives qui
sont intéressantes dans notre parcours. Ma dernière pensée va pour tous les
étudiants de l’Ensimag avec qui j’ai pu échanger sur ce sujet et sur les problèmes
que j’ai rencontré.
References
[1] Joan Daemen and Vincent Rijmen. The design of rijndael: Aes - the advanced encryption standard. Springer, 2002.
[2] Mohamed Karroumi. Protecting white-box aes with dual ciphers.
[3] James A. Muir. A tutorial on white-box. Advances in Network Analysis and
its Applications, (18):209–229, 2013.
[4] N.I.S.T. Announcing the advanced encryption standard. Federal Information
Processing Standards Publication, (197), 2001.
[5] C. Ech-Chatbi O. Billet, H. Gilbert. cryptanalysis of a white box aes implementation. SAC, (3357):227–240, 2005.
[6] S. Chow P. Heisen H. Johnson P.C. van Oorschot. White box cryptography
and an aes implementation. 2002.
[7] James Xiao and Yongxin Zhou. Generating large non-singular matrices over
an arbitrary field with blocks of full rank. 2002.
19

Documents pareils