Brevet FR2980600A1 — publié le 20130329

La présente invention concerne un procédé et un système de sécurisation d'une application logicielle comprenant au moins une instruction conditionnelle. Elle s'applique à titre illustratif et non exclusif à une application logicielle utilisée sous forme compilée. La compilation est l'opération par laquelle une application logicielle écrite en langage de programmation haut niveau ("code source") est traduite en un fichier d'instructions élémentaires (bytecode ou code assembleur) reposant généralement sur un langage de plus bas niveau. La compilation est un processus bien connu de l'homme de l'art et, à ce titre, ne sera pas plus détaillée dans le présent document. Comme décrit par la suite, le fichier compilé d'instructions élémentaires peut présenter certains inconvénients sécuritaires, eu égard à une instruction conditionnelle. L'exemple illustratif présenté ci-après concerne le cas de telles applications pour une machine virtuelle de la famille Java. Bien entendu, comme il ressort notamment de la présentation générale de l'invention, cette dernière n'est ni limitée aux machines virtuelles, ni à la présence d'une compilation, lesquelles constituent des modes de réalisation particuliers dotés d'avantages respectifs. Ainsi, une application logicielle peut être écrite dans un langage de programmation haut niveau et indépendamment de l'architecture matérielle d'exécution. Dans ce cas, l'exécution de cette application sur une architecture matérielle particulière est rendue possible par une couche logicielle intermédiaire, spécifique au matériel et appelée "machine virtuelle". Dans ce cas, l'application logicielle écrite en langage haut niveau peut être compilée en un fichier intermédiaire d'instructions reconnues par la machine virtuelle. Ce fichier intermédiaire est ultérieurement utilisé par la machine virtuelle pour exécuter l'application. C'est le cas d'applications dans le domaine des cartes à puce avec la machine virtuelle Java Card (nom commercial), sorte de machine virtuelle Java spécifiquement conçue pour les cartes à puce. Classiquement, les développeurs utilisent le langage Java de haut niveau pour écrire une application logicielle A (fichier de type .JAVA). La compilation vers un fichier intermédiaire F utilisé par la machine virtuelle Java Card s'opère en deux étapes comme montré schématiquement sur la figure 1: une première compilation de l'application écrite en Java en un fichier intermédiaire FC de type ".CLASS" exécutable par n'importe quelle machine virtuelle Java, puis une conversion du fichier ".CLASS" en un autre fichier intermédiaire F de type ".CAP" exécutable par n'importe quelle machine virtuelle Java Card. Les fichiers intermédiaires FC, F comportent un ensemble d'instructions élémentaires IE reconnues par une machine virtuelle respective, lesquelles précisent le déroulement de l'exécution de l'application logicielle. Pour garantir une bonne exécution de cette dernière, ils doivent donc respecter une certaine structure spécifiée par la machine virtuelle. En programmation informatique, il existe des instructions particulières connues de l'homme de l'art sous l'appellation d'"instructions conditionnelles". Ces instructions permettent de faire varier le comportement de l'application selon une ou plusieurs conditions. Ces conditions peuvent être représentées, au niveau des instructions de l'application ou des instructions élémentaires des fichiers intermédiaires, par des variables d'un type particulier appelé booléen (c'est-à-dire présentant deux états E0 et El uniquement) permettant de définir si une condition est vraie ou fausse. La figure 2 illustre schématiquement une instruction conditionnelle IC dans un fichier en langage haut niveau: une variable "condition" de type booléen VB est utilisée et mémorise généralement le résultat (ici El ="vraie" ou E0="fausse") de l'évaluation d'une expression définissant la ou les conditions. L'instruction conditionnelle "if (condition)" permet de définir une branche de condition vérifiée par laquelle des instructions spécifiques sont exécutées en cas de condition vérifiée et une branche de condition non vérifiée par laquelle d'autres instructions spécifiques sont exécutées en cas de condition non vérifiée. Par exemple, un tel schéma est utilisé lors de la vérification d'un code PIN (pour Personal Identification Number) saisi par un utilisateur pour valider une transaction bancaire comme illustré par la figure 3a. La variable booléenne VB "pinValid" mémorise le résultat de l'expression "pinSaisi ==? pinRef', où pinSaisi est le code PIN saisi par l'utilisateur et pinRef est la valeur de référence en mémoire. Généralement cette variable prend la forme d'un entier: "0" pour l'état E0="fausse", et "1" pour l'état El ="vraie". Si la condition pinValid est vérifiée, l'instruction conditionnelle IC "if (pinValid)" permet d'entrer dans la branche relative à l'acceptation de la transaction bancaire, alors qu'une absence de vérification de la condition fait basculer l'exécution de l'application vers la branche relative au refus de la transaction bancaire. La figure 3b représente les bytecodes Java (ou code intermédiaire) correspondant au code de la figure 3a, c'est-à-dire les instructions élémentaires IE du fichier .CLASS obtenu par compilation du code de la figure 3a: l'instruction élémentaire "iload 1" charge la valeur de la variable locale n°1 (ici pinValid) sur la pile d'opérandes de l'exécution; l'instruction élémentaire conditionnelle IEC "ifeq Ll" indique que si la valeur sur la pile d'opérandes (donc pinValid) vaut 0, l'exécution procède à un saut à la ligne L1; enfin "goto L2" indique de sauter à la ligne L2. Sur cette même figure, les instructions élémentaires entre "ifeq L1" et la ligne L1 définissent une portion de code conditionnée à cette instruction conditionnelle, en particulier en sa branche de condition validée. De façon symétrique, les instructions élémentaires entre la ligne L1 et la ligne L2 définissent une autre portion de code conditionnée à cette instruction conditionnelle, en particulier en sa branche de condition non-validée. Les portions conditionnées par l'instruction conditionnelle sont donc les ensembles d'instructions élémentaires dont l'exécution est réalisée dans un cas ("vraie" ou "fausse") de la condition, mais ne l'est pas dans l'autre cas de la condition. L'exécution d'une application logicielle, par une machine virtuelle dans le présent exemple, présente intrinsèquement un certain niveau de sécurité. Toutefois certaines attaquent peuvent mettre à mal cette sécurité. Par exemple, les applications Java exécutées sur des machines virtuelles, notamment de type Java Card, restent susceptibles d'attaques, en particulier d'attaques par injection de fautes. Ce type d'attaques consiste à perturber l'exécution de l'application par la machine virtuelle, dans le but de modifier son comportement. Elles sont généralement réalisées en perturbant physiquement le matériel sur lequel l'application est exécutée, par exemple par perturbation lumineuse (laser) ou électrique (pic de tension). Ces perturbations engendrent la modification des valeurs de certaines variables ou de la pile d'exécution, ou provoquent encore le saut ou la modification de certaines instructions. De telles attaques sont particulièrement utilisées contre des applications s'exécutant sur des cartes à puce, largement utilisées dans des transactions financières. Bien entendu de telles attaques sont également possibles sur des applications écrites directement en code assembleur et exécutées directement dans une architecture matérielle (par exemple de carte à puce). Les instructions conditionnelles sont critiques d'un point de vue sécuritaire eu égard à ce type d'attaque. En effet, étant à la base de vérifications (par exemple pour une authentification) pour ces transactions, des personnes mal intentionnées ciblent de façon privilégiée ces instructions conditionnelles en tentant de corrompre leur exécution. Ces attaques conduisent alors à exécuter une partie de l'application logicielle qui n'aurait pas dû l'être, compte tenu de la valeur de la condition. En reprenant l'exemple de la figure 3 (code PIN), une personne mal intentionnée cherche typiquement à faire accepter une transaction sans connaître le bon code PIN. Les deux types d'attaques par injection de fautes évoqués précédemment sont utilisés. Le premier type d'attaque, relatif à la modification de la valeur de la variable pinValid, est facilité par le fait combiné que la majorité des langages de programmation, incluant le langage Java, associent, comme indiqué précédemment, la valeur 0 d'une variable sur plusieurs bits (généralement 16 bits) à la condition fausse et toute autre valeur (entre 1 et 65535) à la condition vraie, et que les instructions élémentaires conditionnelles vérifient uniquement si la valeur de la variable est 0 ou non (l'instruction élémentaire "ifeq"). Dans ce cas, l'instruction élémentaire conditionnelle est basée sur l'état 0 de la variable booléenne, signifiant qu'elle ne tient pas compte de l'autre état de cette variable pour déterminer si la condition est remplie. Ainsi pour que l'attaque réussisse, il suffit que l'injection de faute assigne une valeur différente de 0 à la variable utilisée (et non la valeur particulière 1). Or, il est généralement admis qu'une injection de faute peut fixer une variable à une valeur aléatoire. Concernant le deuxième type d'attaque, relatif au saut de l'exécution de l'instruction conditionnelle "ifeq", pour que l'attaque réussisse, il faut alors que l'injection de faute ne saute que l'instruction conditionnelle de sorte que l'exécution de l'application continue, et accepte la transaction. Il est également admis qu'une injection de faute permet de sauter une instruction. Pour pallier ces lacunes sécuritaires, des mécanismes peuvent être mis en place, permettant à une portion de code soumis à une certaine condition d'être exécuté uniquement si la condition est vérifiée, et ce malgré l'éventualité d'attaques par injection de faute. Un mécanisme possible de sécurisation est celui visant à doubler les instructions conditionnelles dans le code de langage haut niveau de l'application logicielle (donc le fichier .JAVA dans le cadre de la programmation Java). La figure 4a illustre le code source haut niveau obtenu pour une sécurisation de l'exemple de la figure 3a (transaction bancaire sur acceptation d'un code PIN) par doublement à l'identique des instructions conditionnelles. La figure 4b représente le fichier intermédiaire correspondant (de type .CLASS), où les instructions ajoutées (ici après la phase de compilation) sont en gras souligné. Dans le doublement à l'identique, des instructions conditionnelles de redondance vérifient si la valeur (pinValid) testée par l'instruction conditionnelle d'origine est bien celle attendue dans chaque branche de cette instruction d'origine. De façon similaire, la figure 5a illustre le code source haut niveau obtenu pour une sécurisation du même exemple (code PIN) par doublement à l'opposé des 20 instructions conditionnelles. La figure 5b représente le fichier intermédiaire correspondant, où les instructions ajoutées sont en gras souligné. Dans le doublement à l'opposé, des instructions conditionnelles de redondance vérifient si la valeur (pinValid) testée par l'instruction conditionnelle d'origine est l'opposée de celle attendue dans chaque branche de cette instruction 25 d'origine. Dans ces deux configurations, des instructions de réaction sont prévues dans les branches conditionnelles relevant d'une incohérence ou divergence entre l'évaluation de la condition par l'instruction conditionnelle d'origine et l'évaluation de la même condition par une des instructions conditionnelles de redondance. 30 A titre illustratif, une instruction de réaction peut consister en l'effacement d'une zone mémoire de stockage d'informations confidentielles ou secrètes, telles qu'une clé cryptographique. Selon cette approche, une attaque par injection de fautes est détectée par les instructions conditionnelles de redondance. Pourtant, ce mécanisme de sécurisation d'applications logicielles présente certains inconvénients. Un premier inconvénient majeur réside dans le fait que ces mécanismes de sécurisation protègent uniquement contre des attaques basées sur l'injection d'une seule faute. Or, il est classique qu'une personne mal intentionnée tente de perturber deux fois (attaque double) la variable utilisée par les instructions conditionnelles, ce qui mettrait en échec les deux mécanismes évoqués précédemment. De même, une attaque double pour sauter l'exécution d'instructions conditionnelles met à mal la sécurisation par doublement à l'identique. Un second inconvénient, spécifique au cas mettant en oeuvre une compilation, concerne l'augmentation du coût de développement des applications intégrant cette sécurisation. En effet, le code redondant, c'est-à-dire définissant le doublement de l'instruction conditionnelle et les instructions de réaction, doit dans ce cas être ajouté au code source de haut niveau par le développeur de l'application logicielle. Ces ajouts sont toutefois fastidieux, d'autant que le nombre d'instructions conditionnelles est généralement assez élevé. Par ailleurs, ces ajouts vont à l'encontre de la philosophie de certaines machine virtuelles, telles que Java Card, selon lesquelles des développeurs non spécialisés devraient être capables d'écrire des applications logicielles pour cartes à puce. Enfin, eu égard au nombre élevé d'instructions conditionnelles dans un code source, il est difficile d'être certain que toutes les situations conditionnelles ont été correctement traitées. Cette situation provient du fait que, puisque le code source ajouté pour le doublement n'intervient pas dans les cas fonctionnels usuels (mais uniquement en cas d'attaque), il ne peut être testé efficacement. La figure 6 résume cet état des lieux, où "ok" signifie qu'une protection est obtenue, et "nok" indique l'existence d'un risque de défaut de protection. La présente invention vise à pallier au moins un des inconvénients des techniques de sécurisation d'applications logicielles décrites ci-dessus. Dans ce dessein, l'invention concerne tout d'abord un procédé de sécurisation d'une application logicielle comprenant au moins une instruction conditionnelle basée sur une variable booléenne à deux états, le procédé comprenant les étapes suivantes, mises en oeuvre par un programme informatique : - obtenir un fichier de l'application logicielle et comprenant des instructions; - déterminer, dans le fichier obtenu, au moins une instruction conditionnelle basée sur un premier état d'une variable booléenne; - modifier le fichier obtenu pour y ajouter au moins une instruction conditionnelle de redondance de l'instruction déterminée basée sur le second état de la variable booléenne et au moins une instruction définissant une réaction en cas de divergence entre l'évaluation de l'instruction conditionnelle déterminée et l'évaluation de l'instruction conditionnelle de redondance. On entend ici par "variable booléenne" une variable représentative d'une information booléenne (c'est-à-dire de deux états), indépendamment du nombre de bits utilisés pour coder cette variable. On entend également par "instruction de redondance" une instruction additionnelle qui procure un dédoublement de l'instruction à redonder. La présente invention augmente le niveau de sécurité de l'application logicielle à l'égard des attaques par faute. En effet, alors que deux fautes ayant un résultat aléatoire sur la variable booléenne mettent en échec les solutions décrites précédemment, le procédé selon l'invention ne peut être mis en défaut que lorsque les deux fautes arrivent à modifier la variable booléenne à son second état (disons la valeur "1", par opposition à la valeur "0" définissant le premier état). Cela est rendu possible par l'ajout de l'instruction de redondance, laquelle se base et vérifie le second état (soit "1") de la variable booléenne par rapport à l'instruction conditionnelle initialement prévue dans le fichier applicatif. Or les attaques par injection de faute connues à ce jour n'offrent pas une précision permettant d'affecter la valeur souhaitée à la variable booléenne: chaque injection de faute est aléatoire. Il en résulte une probabilité très faible que la faute injectée conduise exactement au second état ("1"). Cette probabilité est d'autant plus faible que la variable booléenne est codée sur un grand nombre de bits. En outre, le procédé selon l'invention est facilement automatisable et transparent pour le développeur de l'application logicielle en langage haut niveau. En effet, ces modifications peuvent être opérées automatiquement sur un code intermédiaire (bytecode) ou assembleur, issu par exemple de la compilation d'un code source haut niveau. Les coûts de développement s'en trouvent réduits, et le systématisme de l'automatisation permet de s'assurer qu'aucune instruction conditionnelle n'a été oubliée. Enfin, en opérant au niveau d'un fichier intermédiaire, une optimisation du volume de code ajouté peut être obtenue, offrant un gain d'espace mémoire. Au demeurant, il sera observé qu'aucune modification d'une éventuelle machine virtuelle sur laquelle serait exécutée l'application logicielle compilée n'est nécessaire pour la mise en oeuvre de la sécurisation selon l'invention. Selon un mode de réalisation, le fichier obtenu est un fichier intermédiaire comprenant des instructions élémentaires et résultant d'une compilation de l'application logicielle programmée en langage haut niveau, les instructions déterminée et ajoutées étant des instructions élémentaires dans ledit fichier intermédiaire. Le cas d'une application logicielle compilée reflète un contexte courant, notamment pour la famille de machine virtuelle Java. Selon une caractéristique particulière, le langage de haut niveau est le langage Java, et le fichier intermédiaire est un fichier d'extension CLASS exécutable sur une machine virtuelle Java. En particulier, le fichier intermédiaire une fois modifié par l'ajout des instructions élémentaires est converti en fichier d'extension CAP exécutable sur une machine virtuelle Java Card. Selon un autre mode de réalisation de l'invention, déterminer au moins une instruction conditionnelle comprend identifier les variables booléennes utilisées dans le fichier obtenu et parcourir le fichier obtenu pour détecter les instructions conditionnelles opérant sur une des variables identifiées. L'identification des variables booléennes est aisée et rapide car un fichier applicatif contient le plus souvent des informations sur le type de chaque variable utilisée. De plus, le parcours du fichier s'avère peu complexe dès lors que les variables booléennes sont déjà identifiées, car par exemple seules les instructions s'appliquant sur une des variables identifiées doivent être analysées eu égard à leur nature conditionnelle. Selon une caractéristique de l'invention, ladite variable booléenne est codée par une variable binaire de plusieurs bits (par exemple un octet ou deux octets 16 bits) dans le fichier obtenu. Plus le nombre de bits utilisés est grand, meilleure est la sécurisation de l'application selon l'invention. En particulier, l'instruction conditionnelle déterminée comprend une comparaison de la variable booléenne avec la valeur 0 (le premier état de la variable booléenne), et l'instruction conditionnelle de redondance comprend une comparaison de la variable de type booléen avec une valeur prédéfinie différente de 0 (le second état de la variable booléenne), notamment la valeur 1. Cette configuration correspond à la situation la plus courante. Selon une caractéristique particulière, ladite comparaison avec la valeur 1 comprend le chargement, sur une pile d'opérandes d'exécution, de la valeur 1 (ou de façon générale de la valeur représentant le second état de la variable booléenne) et l'exécution d'une instruction de comparaison des deux opérandes au sommet de la pile. Cette disposition permet de s'affranchir des limites de certains langages, notamment intermédiaires ou assembleurs, ne présentant que des instructions de comparaison d'un opérande de la pile avec la valeur 0 et non avec une valeur autre. Dans un mode de réalisation, la modification du fichier obtenu comprend l'ajout d'une instruction de chargement, sur une pile d'opérandes d'exécution, de la variable booléenne, de sorte à stocker simultanément deux occurrences de la variable dans la pile, les deux occurrences étant affectées respectivement à l'exécution de l'instruction conditionnelle déterminée et à l'exécution de l'au moins une instruction conditionnelle de redondance. Dans un mode de réalisation, l'instruction conditionnelle de redondance basée sur le second état de la variable booléenne est ajoutée dans une branche conditionnelle de l'instruction conditionnelle déterminée. Ainsi, l'instruction de redondance ajoutée est imbriquée dans l'exécution de l'instruction conditionnelle initiale, assurant de la sorte un double contrôle précis. En particulier, l'instruction conditionnelle de redondance basée sur le second état de la variable booléenne est ajoutée parmi les instructions conditionnées par l'instruction conditionnelle déterminée et correspondant au cas où la variable booléenne n'est pas dans le premier état, et une deuxième instruction conditionnelle de redondance vérifiant l'absence du premier état dans la variable booléenne est ajoutée parmi les instructions conditionnées par l'instruction conditionnelle déterminée et correspondant au cas où la variable booléenne est dans le premier état. Cette configuration permet de combiner l'approche du doublement à l'identique (la première instruction de redondance ajoutée peut vérifier le second état dans la branche correspondant à ce second état), et l'approche du doublement à l'opposé (pour la deuxième instruction de redondance ajoutée). Selon une caractéristique particulière, l'au moins une instruction de réaction est ajoutée entre ladite instruction conditionnelle de redondance basée sur le second état de la variable booléenne et les instructions conditionnées par l'instruction conditionnelle déterminée et correspondant au cas où la variable booléenne n'est pas dans le premier état. Cette disposition garantit qu'en cas d'attaques par injection de fautes visant à sauter des instructions conditionnelles, l'exécution se poursuit dans la portion de code correspondant à la détection d'une attaque et à la réaction prévue. En particulier, la deuxième instruction conditionnelle de redondance est configurée pour renvoyer l'exécution du fichier obtenu vers l'au moins une instruction de réaction, lorsque la variable booléenne n'est pas dans le premier état. Cette configuration permet de ne pas dédoubler les instructions de réaction, optimisant la taille du fichier modifié. Corrélativement, l'invention concerne également un système de sécurisation d'une application logicielle comprenant au moins une instruction conditionnelle basée sur une variable booléenne à deux états, le système comprenant un programme informatique incluant des instructions de code pour exécuter les étapes suivantes lorsque le programme est chargé et exécuté par un microprocesseur : - obtenir un fichier de l'application logicielle et comprenant des instructions; - déterminer, dans le fichier obtenu, au moins une instruction conditionnelle basée sur un premier état d'une variable booléenne; - modifier le fichier obtenu pour y ajouter au moins une instruction conditionnelle de redondance de l'instruction déterminée basée sur le second état de la variable booléenne et au moins une instruction définissant une réaction en cas de divergence entre l'évaluation de l'instruction conditionnelle déterminée et l'évaluation de l'instruction conditionnelle de redondance. Le système selon l'invention présente des avantages similaires à ceux du procédé de sécurisation exposé ci-dessus. De façon optionnelle, le système peut comprendre des moyens se rapportant aux caractéristiques du procédé de sécurisation exposé précédemment. D'autres particularités et avantages de l'invention apparaîtront encore dans la description ci-après, illustrée par les dessins ci-joints, dans lesquels : - la figure 1 illustre schématiquement les étapes de compilation d'un fichier Java en un fichier intermédiaire exécutable sur une machine virtuelle de type Java Card; - la figure 2 illustre schématiquement une instruction conditionnelle dans un fichier en langage haut niveau; - les figures 3a et 3b illustre un exemple d'instruction conditionnelle basé sur la vérification d'un code PIN, respectivement dans un langage haut niveau et dans un langage intermédiaire de compilation, type bytecode; - les figures 4a et 4b illustre le même exemple incorporant un mécanisme de sécurisation de l'état de l'art par doublement à l'identique de l'instruction conditionnelle, respectivement dans le langage haut niveau et dans le langage intermédiaire de compilation, type bytecode; - les figures 5a et 5b illustre le même exemple incorporant un mécanisme de sécurisation de l'état de l'art par doublement à l'opposé de l'instruction conditionnelle, respectivement dans le langage haut niveau et dans le langage intermédiaire de compilation, type bytecode; - la figure 6 illustre le niveau de sécurité obtenu par les mécanismes des figures 4 et 5; - la figure 7 illustre, sous forme de logigramme, des étapes d'un mode de réalisation de l'invention; - la figure 8 illustre la modification d'un fichier intermédiaire selon l'invention, dans l'exemple de la figure 3; et - la figure 9 illustre le niveau de sécurité obtenu par les mécanismes selon l'invention. Comme illustré sur la figure 7, un procédé de sécurisation selon un mode de réalisation de l'invention relatif à une application logicielle compilée peut notamment comprendre les étapes consistant à : - obtenir 100 un fichier intermédiaire FC ou F possiblement résultant d'une compilation de l'application logicielle A et comprenant des instructions élémentaires 1E; - déterminer 110, dans le fichier intermédiaire obtenu, au moins une instruction élémentaire conditionnelle IC basée sur un premier état El d'une variable booléenne VB; - modifier 120 le fichier intermédiaire obtenu pour y ajouter au moins une instruction élémentaire conditionnelle de redondance ICR de l'instruction déterminée basée sur le second état E0 de la variable booléenne VB et au moins une instruction élémentaire IR définissant une réaction en cas de divergence entre l'évaluation de l'instruction élémentaire conditionnelle déterminée et l'évaluation de l'instruction élémentaire conditionnelle de redondance. La figure 8 illustre le fichier intermédiaire FC obtenu (sur la gauche) et le fichier intermédiaire modifié FM (sur la droite) conformément à un mode de réalisation de l'invention mettant en oeuvre le langage Java et une machine virtuelle Java. Dans le cas d'une machine virtuelle Java, ainsi que dans le cas particulier de Java Card où les variables booléennes sont transformées en des variables de type entier (sur 2 octets généralement) lors de l'étape de conversion, on considèrera de préférence le fichier .CLASS comme fichier intermédiaire utilisé. Bien entendu, l'homme de l'art sera à même d'adapter les enseignements de l'invention à d'autres langages de programmation, notamment de type assembleur, sans qu'une compilation ait nécessairement eut lieu. Comme représenté sur la figure 7, la détermination 110 peut comprendre les étapes suivantes: identifier 112 les variables booléennes VB utilisées dans le fichier intermédiaire FC, F et parcourir le fichier intermédiaire pour détecter les instructions conditionnelles IC opérant sur une des variables identifiées. Ainsi l'étape de détermination 110 consiste à détecter les instructions conditionnelles sur des variables de type booléen VB, et ce dans le code intermédiaire FC de l'application A. Le fichier intermédiaire FC contient les informations (non représentées) sur le type de chaque variable utilisée dans le programme. Une approche consiste donc à parcourir une première fois ce fichier pour déterminer 112 quelles sont les variables VB de type booléen utilisées. Par exemple, la variable locale n°1 (pinValid) peut être identifiée comme une variable booléenne grâce à la définition qui en est faite en début de fichier. Puis, le fichier FC d'instructions est à nouveau parcouru pour détecter 114 les instructions élémentaires conditionnelles IEC opérant sur l'une des variables booléennes obtenues à l'étape 112. Dans l'exemple du code Java compilé (fichier .CLASS), les instructions IEC peuvent être détectées par la présence du préfixe "if" dans la représentation proposée du fichier FC (en code assembleur) ou par la connaissance des codes hexadécimaux ("Bytecodes" par exemple les bytecodes Java) codant ces instructions élémentaires conditionnelles. Si la ou les variables sur lesquelles l'instruction conditionnelle se base sont indiquées au niveau de l'instruction élémentaire identifiée, la vérification que cette ou ces variables soient des variables booléennes est directe grâce à l'étape 112 30 précédente. En revanche, dans le cas par exemple du fichier FC .CLASS de la figure 8, l'instruction élémentaire conditionnelle IEC "ifeq" se base sur l'opérande au sommet de la pile d'exécution. La vérification de la nature de la variable au sommet de la pile d'exécution peut alors consister à remonter les instructions pour déterminer celle ou 35 celles qui ont contribué à la production de ce dernier opérande. Dans l'exemple de la figure 8, l'instruction élémentaire "iload_1" permet de déterminer que le dernier opérande chargé est la variable locale n°1, laquelle a été déterminée comme étant booléenne lors de l'étape 112. Ainsi, l'instruction élémentaire conditionnelle "ifeq L1" est retournée comme résultat à l'étape 114. Lors de l'étape 114, les portions de code intermédiaire conditionnées par cette instruction élémentaire conditionnelle IEC identifiée sont également déterminées. Dans le présent exemple, une première portion du code conditionné comprend la branche conditionnelle relative à la condition vérifiée (c'est-à-dire lorsque la variable locale n°1 ou "pinValid" vaut "1") et regroupe les instructions élémentaires depuis l'instruction IEC identifiée (non comprise) jusqu'à l'instruction "goto L2". La deuxième portion du code conditionné comprend la branche conditionnelle relative à la condition non vérifiée (c'est-à-dire lorsque la variable locale n°1 ou "pinValid" vaut "0") et regroupe les instructions élémentaires depuis la ligne L1 (directement identifiable car indiquée dans l'instruction IEC elle-même: "ifeq L1") jusqu'à la ligne L2 (non comprise). La détermination de cette limite au niveau de la ligne L2 découle ici directement de l'instruction finale "goto L2" de la première branche conditionnelle. En effet, la ligne L2 étant réalisée pour les deux branches conditionnelles, elle ne fait plus partie des instructions élémentaires conditionnées par IEC. Comme représenté sur la figure 7, la modification 120 du fichier FC peut comprendre les étapes suivantes: ajouter 122 des instructions élémentaires de contrôle à l'application A au niveau du fichier FC, puis ajouter 124 des instructions élémentaires de réaction IR au fichier FC. Ces étapes peuvent être réalisées conjointement. Les instructions élémentaires de contrôle font partie des instructions élémentaires reconnues par la machine virtuelle à laquelle le fichier FC est destiné. Elles ont pour but d'effectuer un contrôle redondant de chaque instruction conditionnelle IC opérant sur une variable booléenne VB, en se basant sur l'autre état que celui pris en compte dans ladite instruction conditionnelle IC Dans l'exemple de la figure 8, l'instruction IEC détectée est "ifeq L1" se base sur l'état E0="0" de la variable booléenne "pinValid". Par conséquent, une instruction élémentaire conditionnelle de redondance ICR basée sur l'état E1="1" est ajoutée lors de l'étape 122. Le code modifié de FM contient ainsi des instructions conditionnelles comparant la variable booléenne à chacun de ses deux états possibles (0 et 1). En détail, deux instructions élémentaires conditionnelles de redondance IEC sont ajoutées dans le fichier FC. Pour permettre l'exécution de ces instructions conditionnelles en plus de l'instruction IEC déjà présente dans FC, on duplique la ou les instructions élémentaires permettant d'obtenir la variable booléenne VB au sommet de la pile d'opérandes. Dans l'exemple, cela consiste à ajouter une instruction élémentaire de chargement, sur la pile d'opérandes d'exécution, de la variable booléenne locale n°1 (instruction "iload_1"), de sorte à stocker simultanément deux occurrences de la variable dans la pile. Ainsi, ces deux occurrences sont affectées respectivement à l'exécution de l'instruction élémentaire conditionnelle déterminée IEC et à l'exécution de l'instruction élémentaire conditionnelle de redondance ICR1 ou ICR2. Bien entendu, d'autres configurations peuvent être prévues: par exemple l'instruction de chargement "iload_1" peut être juste après l'instruction "ifeq L1". La première instruction ICR1 est basée sur l'état E1="1" de la variable pinValid et insérée dans la branche conditionnelle correspondant à cet état pour l'instruction IEC détectée lors de l'étape 114. Cette insertion est réalisée avant la portion de code conditionnée de cette branche (sur la figure avant "II Accepter ... goto L2" représentant les instructions élémentaires de cette branche). Cette instruction ICR1 compare ainsi la variable locale n°1 (au sommet de la pile d'opérandes) avec l'état E1=1. Or, dans le cas Java, il n'existe pas d'instruction élémentaire de comparaison avec un entier différent de 0 (ici avec l'état E1=1). Cette comparaison est alors prévue comme suit: charger, sur la pile d'opérandes d'exécution, la valeur 1 par l'ajout de l'instruction "iconst_1" et exécuter une instruction élémentaire de comparaison ICR1 des deux opérandes au sommet de la pile par l'ajout de l'instruction "ificmpeq". "if_icmpeq L3" est l'instruction qui compare les deux valeurs sur la pile d'opérandes et saute en L3 en cas d'égalité ou continue l'exécution en cas d'inégalité. La seconde instruction ICR2 ("ifne L4": si la valeur sur la pile d'opérandes ne vaut pas 0, sauter en L4, sinon continuer) est basée sur l'état E0="0" de la variable VB et insérée dans l'autre branche conditionnelle, avant la portion de code conditionnée de cette branche (sur la figure avant "II Refuser ..." représentant les instructions élémentaires de cette branche). Les instructions élémentaires de réaction IR ajoutées lors de l'étape 124 sont conçues pour être exécutées lorsqu'une erreur (ou attaque) est détectée, par 35 exemple en cas de divergence entre l'évaluation de l'instruction élémentaire conditionnelle déterminée IEC et l'évaluation de l'instruction élémentaire conditionnelle de redondance ICR1 ou ICR2. Une réaction peut être par exemple l'effacement d'une donnée sensible en mémoire ou un reset de matériel. Pour minimiser l'augmentation de la taille du fichier intermédiaire du fait de sa modification, on prévoit que l'une des deux instructions élémentaires conditionnelles de redondance ICR1 ou ICR2 soit configurée pour renvoyer l'exécution du fichier intermédiaire vers les instructions élémentaires de réaction IR prévues au niveau de l'autre instruction de redondance ICR2 ou ICR1. Dans l'exemple de la figure 8, l'instruction ICR2 "ifne L4" renvoie en effet à la ligne L4 où sont définies les instructions de réaction IR pour ICR1. Toujours en référence à cette figure, les instructions élémentaires de réaction IR sont ajoutée entre l'instruction élémentaire conditionnelle de redondance ICR1 basée sur l'état E1=1 de la variable booléenne VB et la portion d'instructions élémentaires conditionnées par l'instruction conditionnelle déterminée IEC et correspondant au cas où la variable booléenne VB est différente de 0, c'est-à-dire avant "II Accepter ... goto L2". Comme cette branche VBA fait immédiatement suite, dans le code de FC, à l'instruction conditionnelle IEC (puisque l'instruction IEC généralement utilisée compare la variable à 0), la mise en place des instructions IR dans la suite immédiate permet de sécuriser l'application contre les fautes sautant les instructions conditionnelles. Le fichier modifié FM selon l'invention (et donc l'application A modifiée) vérifiera ainsi en deux temps si l'opérande de l'instruction conditionnelle vaut bien 0 ou 1 respectivement dans le cas où la condition est fausse ou vraie. Si le résultat de ces deux vérifications n'est pas cohérent les instructions de réaction IR sont alors exécutées. Dans le cas de Java Card, les modifications apportées au fichier .CLASS durant cette étape 120 sont répercutées sur le fichier .CAP lors de l'étape de conversion évoquée en lien avec la figure 1. La figure 9 illustre le niveau de sécurisation obtenu par la mise en oeuvre de l'invention, contre les attaques par simple ou double fautes impliquant une modification de valeur ou un saut d'instruction. On constate une augmentation notable du niveau de sécurité par rapport aux solutions de l'état de l'art évoquées précédemment. Deux sauts d'instructions sont désormais détectés à chaque attaque, puisque la configuration proposée par l'invention conduit à insérer les instructions de réaction IR juste après les deux premières instructions conditionnelles IEC et ICR1 qui seraient sautées. La quasi-totalité des doubles fautes impliquant une modification de valeur est détectée. Seule une double faute forçant les deux fois la variable booléenne VB à l'état E1=1 pourrait ne pas être détectée. Or les techniques d'attaques par injection de faute ne permettent que de modifier aléatoirement de telles variables. Ainsi, l'invention permet de sécuriser à 99,99% une application A comprenant une instruction conditionnelle opérant sur une variable booléenne codée sur 16 bits. Bien entendu cette sécurisation est encore augmentée si la variable VB est codée sur un plus grand nombre de bits. La présente invention peut être mise en oeuvre dans un système informatique classique comprenant un microprocesseur. Dans ce cas, elle est mise en oeuvre par l'exécution d'un programme informatique contenant des instructions de code pour exécuter ou mettre en oeuvre les étapes évoquées ci-dessus, lorsque le programme est chargé et exécuté par le microprocesseur. Les exemples qui précèdent ne sont que des modes de réalisation de l'invention qui ne s'y limite pas. En particulier, bien que l'invention ait été largement décrite en lien avec un fichier intermédiaire FC résultant de la compilation du fichier application A, elle s'applique également à un fichier applicatif directement édité par un utilisateur programmeur. C'est par exemple le cas des fichiers programmés en langage assembleur sur lesquels la sécurisation selon l'invention s'avère particulièrement efficace, en particulier grâce à l'automatisation du procédé par le programme informatique comprenant celui-ci. REVENDICATIONS1. Procédé de sécurisation d'une application logicielle (A) comprenant au moins une instruction conditionnelle (IC) basée sur une variable booléenne (VB) à deux états (E0, El ), le procédé comprenant les étapes suivantes, mises en oeuvre par un programme informatique : - obtenir (100) un fichier (FC) de l'application logicielle (A) et comprenant des instructions (1E); - déterminer (110), dans le fichier obtenu (FC), au moins une instruction conditionnelle (IEC) basée sur un premier état (E0) d'une variable booléenne (VB); - modifier (120) le fichier obtenu (FC) pour y ajouter (122, 124) au moins une instruction conditionnelle (ICR1) de redondance de l'instruction déterminée (IEC) basée sur le second état (El ) de la variable booléenne (VB) et au moins une instruction (IR) définissant une réaction en cas de divergence entre l'évaluation de l'instruction conditionnelle déterminée (IEC) et l'évaluation de l'instruction conditionnelle de redondance (ICR1). 2. Procédé selon la revendication 1, dans lequel déterminer (110) au moins une instruction conditionnelle (IEC) comprend identifier (112) les variables booléennes (VB) utilisées dans le fichier obtenu (FC) et parcourir (114) le fichier obtenu (FC) pour détecter les instructions conditionnelles opérant sur une des variables identifiées. 3. Procédé selon la revendication 1 ou 2, dans lequel ladite variable booléenne (VB) est codée par une variable binaire de plusieurs bits dans le fichier obtenu. 4. Procédé selon la revendication 3, dans lequel l'instruction conditionnelle déterminée (IEC) comprend une comparaison de la variable booléenne (VB) avec la valeur 0, et l'instruction conditionnelle de redondance (ICR1) comprend une comparaison de la variable de type booléen avec la valeur 1. 5. Procédé selon la revendication 4, dans lequel ladite comparaison avec la valeur 1 comprend le chargement, sur une pile d'opérandes d'exécution, de la valeur 1 et l'exécution d'une instruction de comparaison (if_icmpeq) des deux opérandes au sommet de la pile. 6. Procédé selon l'une des revendications 1 à 5, dans lequel la modification (120) du fichier obtenu (FC) comprend l'ajout d'une instruction de chargement (i_load), sur une pile d'opérandes d'exécution, de la variable booléenne(VB), de sorte à stocker simultanément deux occurrences de la variable dans la pile, les deux occurrences étant affectées respectivement à l'exécution de l'instruction conditionnelle déterminée (IEC) et à l'exécution de l'au moins une instruction conditionnelle de redondance (ICR1). 7. Procédé selon l'une des revendications 1 à 6, dans lequel l'instruction conditionnelle de redondance (ICR1) basée sur le second état (El) de la variable booléenne (VB) est ajoutée dans une branche conditionnelle de l'instruction conditionnelle déterminée (IEC). 8. Procédé selon l'une des revendications 1 à 7, dans lequel l'instruction conditionnelle de redondance (ICR1) basée sur le second état (El) de la variable booléenne (VB) est ajoutée parmi les instructions conditionnées par l'instruction conditionnelle déterminée (IEC) et correspondant au cas où la variable booléenne n'est pas dans le premier état (E0), et une deuxième instruction conditionnelle de redondance (ICR2) vérifiant l'absence du premier état (E0) dans la variable booléenne (VB) est ajoutée parmi les instructions conditionnées par l'instruction conditionnelle déterminée (IEC) et correspondant au cas où la variable booléenne est dans le premier état. 9. Procédé selon la revendication 8, dans lequel l'au moins une instruction de réaction (IR) est ajoutée entre ladite instruction conditionnelle de redondance (ICR1) basée sur le second état (El) de la variable booléenne (VB) et les instructions conditionnées par l'instruction conditionnelle déterminée (IEC) et correspondant au cas où la variable booléenne n'est pas dans le premier état. 10. Procédé selon la revendication 9, dans lequel la deuxième instruction conditionnelle de redondance (ICR2) est configurée pour renvoyer l'exécution du fichier obtenu (FC) vers l'au moins une instruction de réaction (IR), lorsque la variable booléenne n'est pas dans le premier état. 11. Procédé selon l'une des revendications 1 à 10, dans lequel le fichier obtenu (FC, F) est un fichier intermédiaire comprenant des instructions élémentaires (1E) et résultant d'une compilation de l'application logicielle (A) programmée en langage haut niveau, les instructions déterminée (IEC) et ajoutées (ICR1, IR) étant des instructions élémentaires dans ledit fichier intermédiaire. 12. Procédé selon la revendication 11, dans lequel le langage de haut niveau est le langage Java, et le fichier intermédiaire est un fichier d'extension CLASS exécutable sur une machine virtuelle Java. 13. Procédé selon la revendication 12, dans lequel le fichier intermédiaire une fois modifié par l'ajout des instructions élémentaires est converti en fichier d'extension CAP exécutable sur une machine virtuelle Java Card. 14. Système de sécurisation d'une application logicielle (A) comprenant au moins une instruction conditionnelle (IC) basée sur une variable booléenne (VB) à deux états (E0, El ), le système comprenant un programme informatique incluant des instructions de code pour exécuter les étapes suivantes lorsque le programme est chargé et exécuté par un microprocesseur : - obtenir (100) un fichier (FC) de l'application logicielle (A) et comprenant des instructions (1E); - déterminer (110), dans le fichier obtenu (FC), au moins une instruction conditionnelle (IEC) basée sur un premier état (E0) d'une variable booléenne (VB); - modifier (120) le fichier obtenu (FC) pour y ajouter (122, 124) au moins une instruction conditionnelle (ICR1) de redondance de l'instruction déterminée (IEC) basée sur le second état (El) de la variable booléenne (VB) et au moins une instruction (IR) définissant une réaction en cas de divergence entre l'évaluation de l'instruction conditionnelle déterminée (IEC) et l'évaluation de l'instruction conditionnelle de redondance (ICR1).