• Aucun résultat trouvé

6.2 Application partielle de contre-mesures

7.1.1 POA pour RSA

Il existe différentes façons de protéger RSA contre les attaques temporelles : le

blinding [35] (qui n’est pas forcément efficace pour empêcher un attaquant de

retrouver le poids de Hamming de la clé secrète [35]), exécuter l’algorithme en un temps constant (à l’aide d’instructions wait), en un temps variable mais aléatoire (en insérant, à différents moments, des instructions inutiles au chif-frement).

La première contre-mesure développée vise à protéger RSA, implantant l’ex-ponentiation modulaire utilisée par Kocher dans [35]. Dans cet algorithme, le nombre de multiplications modulaires est directement corrélé au nombre de bits égaux à 1 dans la clé. La réalisation de ces multiplications prend plus de temps que l’alternative, réalisée lorsque les bits de la clé valent 0, qui est une assignation.

Plusieurs contre-mesures sont envisageables :

– pour le blinding, nous pourrions définir un point de coupure (cf. définition page 29) sur l’exécution de l’algorithme de déchiffrement et faire en sorte que l’advice (cf. définition page 29) associé remplace le message par sa version protégée.

– pour atteindre un certain temps d’exécution, le point de coupure serait placé sur l’exécution du déchiffrement (around, pour pouvoir mesurer le temps d’exécution du déchiffrement) et l’advice associé correspondrait à un appel à la fonction sleep() avec un paramètre changeant selon le type de temps d’exécution visé (constant, aléatoire, ...).

– l’insertion d’instructions inutiles qui peut se faire avec les mêmes points de coupure (around sur l’exécution), mais avec des advices appropriés.

Nous avons implanté notre propre version de RSA, où l’exponentiation modu-laire1a lieu de la façon suivante (code 4) :

1. Notons que la multiplication n’est pas la multiplication de Montgomery, afin d’exploiter le temps nécessaire à la multiplication.

Code 4 Implantation de l’exponentiation modulaire de RSA

1 public static BigInteger powerModHamming(BigInteger modulus, BigInteger exp, BigInteger base){ // Fast Exp implementation

2 // The code below produces the same result as

3 // return c.modPow(e,n);

4 // However, we did implement it ourselves to simulate a situation where an attacker is able to obtain leaked information from the exponentiation function about the used exponent.

5 ArrayList<Boolean> d = new ArrayList<Boolean>();

6 d = convert(exp);

7 BigInteger result = BigInteger.ONE; //long result = 1;

8 BigInteger r = BigInteger.ZERO; //long r = 0;

9

10 for(int i = 0; i < d.size(); i++){

11 if(d.get(i) == true){

12 slowDown();

13 r = result.multiply(base).mod(modulus); //r = (result * base) % modulus

;

14 }

15 else

16 r = result;

17 result = r.multiply(r).mod(modulus); //result = (r * r) % modulus;

18 }

19 return r;

20

21 }

Cette implantation a été conçue pour illustrer notre approche. Le temps d’exé-cution sera donc lié au poids de Hamming de la clé puisqu’une multiplication, classique, est exécutée pour chaque bit valant 1 dans la clé. Nous avons ajouté un certain délai avant la réalisation de chaque multiplication, afin d’augmen-ter la précision des mesures de temps et d’avoir une différence plus marquée dans les temps d’exécution (ceci simule l’utilisation d’outils de mesure plus précis).

En mesurant le temps d’exécution de notre implantation, un attaquant peut obtenir le poids de Hamming de la clé secrète, car le temps du déchiffrement est directement proportionnel à celui-ci. Une telle information diminue dras-tiquement le temps nécessaire pour retrouver la clé utilisée, car seules les clés d’un certain poids de Hamming doivent être testées. L’attaque pour retrouver l’exacte valeur de la clé fonctionnera d’autant mieux que la clé est petite et si l’attaquant dispose d’une grande précision de mesure (symbolisée, dans notre cas, par la durée du délai avant chaque multiplication).

Contre-mesure

Notre contre-mesure va faire en sorte que le déchiffrement prenne exactement le même temps, indépendamment de la valeur de la clé.

L’aspect

Il serait assez facile de modifier directement le code pour faire en sorte qu’une multiplication ait lieu indépendamment de la valeur du bit considéré. Mais, cette approche ferait en sorte que différentes facettes (déchiffrement et contre-mesure) soient mélangées. Le code deviendrait plus compliqué à lire (de ma-nière générale) et, pour un code déjà validé comme étant correct et ne pou-vant donc plus être modifié (à moins de vouloir à nouveau le certifier), une telle approche n’est pas souhaitée. Nous allons donc utiliser la POA pour créer un aspect, pouvant être évalué et validé indépendamment du code source. Le tisseur devra, lui aussi, avoir été validé, ainsi que les autres outils (compila-teur...) pour que la confiance en l’implantation soit totale.

Notre proposition se révèle être assez simple : pour chaque exécution du dé-chiffrement avec une clé e pour un message m, nous allons procéder à un déchiffrement supplémentaire utilisant la clé ¯d(complément bit-à-bit de la clé d) et le même message m qui sera exécuté avant l’exécution initialement de-mandée. Ainsi, si le poids de Hamming de d vaut x (HW (d) = x), le poids de Hamming de ¯dvaut w − m (HW ( ¯d) = w − x), où w est la longueur en bits de la clé. Cette deuxième exécution peut utiliser des paramètres erronés pour un fonctionnement normal, mais ceci n’est pas important car le résultat n’est pas récupéré.

Cette contre-mesure, jamais rencontrée dans la littérature précédemment, se rapproche fortement des contre-mesures visant à avoir un temps d’exécution fixe, mais elle ne laisse pas le processeur dans un état idle pour atteindre un temps constant. Le temps d’exécution obtenu sera égal au temps obtenu, pour une version non protégée, si tous les bits de la clé secrète valaient 1.

Code 5 Aspect PowerComplement pour RSA

1 public aspect PowerComplement {

2 long around(long n, long d, long m) : (execution(* RSA.decrypt(..))) args(n,d,m) { 3 RSA.powerModHamming(n,RSA.getMaxValue().subtract(d),m);

4 return proceed(n, d, m);

5 }

6 }

L’aspect PowerComplement est constitué du point de coupure : long around(long n, long d, long m)

qui substitue chaque exécution de la méthode decrypt de la classe RSA re-cevant les trois paramètres (n, d, m) par l’advice qui consiste en l’appel à la méthode :

dont le résultat n’est ni utile ni sensé, et qui procède ensuite à la requête ini-tiale.

L’implantation d’un temps d’exécution constant à l’aide d’aspect se ferait en remplaçant le code de l’aspect précédent par le code suivant :

Code 6 Temps Constant pour RSA

1 long start = System.currentTimeMillis(); 2 long res = RSA.powerModHamming(n,d,m); 3 long stop = System.currentTimeMillis(); 4 Thread.sleep(t-(start-stop));

5 return res;

où t est une constante définie à l’avance.

Résultats

Les expériences ont été conduites avec des ensembles de clés, de 256 bits, constitués de, respectivement, 20, 100, 1 000, 10 000 et 100 000 clés diffé-rentes que nous avons générées. Pour chaque exécution, un message aléatoire m ∈ Zn est choisi. Chaque exécution procède au chiffrement et au ment du message. Les mesures de temps ont lieu avant et après le déchiffre-ment et sont enregistrées. Sur base de ce temps de déchiffredéchiffre-ment, la clé est estimée (en connaissance du temps nécessaire à la multiplication). La même procédure est exécutée lorsque la contre-mesure est utilisée. Pour chaque ex-périence, nous regardons le taux de succès (poids de Hamming correctement identifiés). Pour les attaques sans contre-mesure, le taux de succès varie entre 80% et 84%. Ce taux de succès chute à 0% lorsque la contre-mesure est utili-sée.