• Aucun résultat trouvé

4.2 Architecture logicielle

5.2.2 Ce que l’on prouve

Ce que l’on prouve concerne l’intégrité des données. En résumé (les détails sont exposés dans la suite), pour garantir l’intégrité d’une zone, SecBus maintient un hash de cette zone sous forme d’arbre de Merkle qui est mis à jour quand on écrit dans cette zone et lu pour vérification chaque fois que l’on lit dans cette zone. C’est ce qu’illustre la figure 5.3.

tree associated protected page address space

update tree & write cpu−memory bus verify tree & read CPU

update tree write

read verify tree

tree root Chip

cache hardware

HSM

FIGURE 5.3 – Protection d’intégrité par des arbres de Merkle

Seule la racine de l’arbre est sauvegardée à l’intérieur de la puce. Les autres nœuds sont en mémoire. Ceci est coûteux : vérifier et mettre à jour les arbres engendre beaucoup de commu- nications sur le bus. Aussi SecBus est doté d’un cache sur la puce pour les nœuds, avec une gestion assez subtile. Une autre optimisation consiste à ne parcourir que les nœuds utiles des arbres lors des diverses opérations (les ascendants et “oncles” des cellules mémoire accédées). Enfin on évite l’initialisation des arbres en utilisant des arbres creux. De tout ceci il découle qu’une preuve complète devrait traiter les divers points suivants :

1. Preuve du principe de protection par les arbres de Merkle. C’est une approche classique et il est généralement admis que cela fonctionne (à l’incertitude des collisions près). Pour une preuve complète, il faudrait le prouver.

2. Preuve de l’optimisation par un parcours partiel pour garantir qu’il suffit de considérer les ascendants et oncles des cellules accédées pour garantir le respect de la structure d’arbre de Merkle.

3. Preuve des algorithmes réels de SecBus garantissant qu’ils se comportent comme les algorithmes théoriques sur lesquels on prouve les points précédents.

4. Preuve de la correction comportementale des arbres creux pour assurer que l’utilisation des arbres creux est similaire à celle des arbres classiques. Il s’agit de montrer que l’on obtient les mêmes résultats sur une mémoire non corrompue (donc pas de fausse alerte) et que la seule différence porte sur l’accès à des cellules non corrompues dans une mémoire corrompue : dans ce cas, l’accès est sûr pour la donnée concernée. La corruption sur d’autres cellules que celle accédée est détectée différemment par les deux algorithmes.

5. Preuve de la sécurité des algorithmes réels garantissant que leur exécution peut effec- tivement être considérée comme atomique, c’est-à-dire qu’elle n’introduit pas d’accès multiples dangereux à la mémoire.

6. Preuve de la transparence des caches pour garantir que l’utilisation des caches ne com- promet pas les résultats des points précédents.

Mener les preuves des points 1 et 2 sur les algorithmes finaux avec le détail des choix d’im- plémentation serait extrêmement complexe. Les preuves formelles nécessitent l’explicitation de tous les détails et l’abstraction est indispensable pour les rendre abordables. Il est donc oppor- tun de mener ces preuves sur des algorithmes mathématiques abstraits, épurés. Il faut ensuite montrer que les algorithmes concrets implémentent bien les algorithmes abstraits, ce qui est l’approche usuelle par raffinement. La preuve de raffinement est l’objet du point 3.

Le point 4 peut être abordé au niveau abstrait comme concret. Une preuve manuelle serait plus simple au niveau abstrait mais en utilisant un outil permettant de vérifier automatique- ment l’équivalence de programme, le niveau concret semble faisable (comme nous le verrons plus loin avec une preuve partielle). Les points 5 et 6 concernent intrinsèquement le niveau concret et doivent donc être prouvés à ce niveau. Enfin, le dernier point à ne pas oublier est que toute preuves porte sur des objets mathématiques et la correspondance entre le physique et ses modèles mathématiques doit être assurée par d’autres moyens.

Parmi toutes ces étapes d’une preuve “idéale”, deux ont été abordées :

— En utilisant la méthode B et l’outil de preuve Atelier B associé, le point 3 a été traité : les arbres de Merkle ont été modélisés selon une représentation mathématique abstraite standard. Sur cette représentation ont été spécifiés des algorithmes fonctionnels pour la lecture et l’écriture dans la mémoire effectuant les mises à jour et vérifications associées sur les arbres. Il a ensuite été prouvé que la représentation concrète des arbres et les algorithmes finaux sur cette dernière constituaient bien un raffinement (c’est-à-dire une implémentation conforme) de la version abstraite.

— En utilisant l’outil EasyCrypt, le point 4 a été partiellement traité au niveau concret : il a été prouvé que l’algorithme sur les arbres creux avait le même comportement que celui des arbres standard sur une mémoire non corrompue.

La figure 5.4 suivante résume ces différents points. La fiabilité des caches et l’atomicité de l’exécution des algorithmes réels n’ont pas été traités.

mathematical representation makes proof of merkel tree principle easier Abstract Algo mathematical tree Concrete Algo concrete tree implementation equivalence behavioural

on non corrupted memory

proof at low level using easycrypt refinement using AtelierB implementation Concrete Algo hollow tree

FIGURE 5.4 – Les deux étapes d’une preuve

Garantir la correspondance entre les deux niveaux d’abstraction ne suffit pas à prouver leur correction car ils pourraient être tous les deux erronés. Mais cette preuve de la relation d’im- plémentation entre deux représentations différentes renforce la confiance que l’on peut avoir en chacune d’entre elles. De plus l’abstraction facilite la compréhension et la vérification hu- maine. Elle rend abordable la preuve du point 1 (Principe de sécurité de Merkle) qui renforcerait considérablement cette confiance. Enfin, ce raffinement montre que l’implémentation est sûre (par exemple qu’il n’y a pas d’erreur de calculs d’indices) et que les preuves au niveau abstrait offrent les bonnes garanties sur le niveau concret.

Le travail avec EasyCrypt constituait une étude de faisabilité. La garantie apportée sur le cas “sain” est satisfaisante. Le cas où la mémoire est corrompue, quoique plus complexe, semble abordable.

5.2.3

Quelques précisions sur la preuve de raffinement avec la méthode