Brevet FR2879776A1 — publié le 20060623

La présente invention a pour objet un procédé pour l'adaptation automatique de programmes à des exigences opérationnelles. Elle s'applique notamment, mais non exclusivement, aux applications qui nécessitent l'intégration de propriétés de sécurité fortes, comme la gestion sécurisée du cycle de vie d'une application, l'authentification des utilisateurs de la carte, la sécurisation des échanges entre la carte et le terminal, et la protection des données sensibles de l'application en intégrité et en confidentialité. Les cartes à puces répondant à la norme ISO7816 et intégrant la technologie "Java Card" définie par Sun Microsystems, indifféremment en version 2.1 ou 2.2, sont utilisées pour le stockage et l'exécution de données et d'applications dans des domaines tels que l'information médicale, les porte-monnaie électroniques, les certificats et clés de chiffrement, les profils utilisateurs, les points de fidélité, les jeux, etc. De par la généralisation des contraintes die sécurité à divers domaines et supports applicatifs, ce domaine d'application peut être étendu, notamment aux environnements mobiles et embarqués supportant la technologie "Java" (mobiles compatibles MIDP, terminaux STIP/FINREAD, etc. ). D'une façon générale, on sait que dans le secteur des cartes à puce, les spécifications sont généralement très stables (par exemple dans le secteur bancaire), ce qui permet d'obtenir des codes fonctionnellement corrects, puisque l'investissement d'écriture d'une application peut être amorti sur une période relativement longue. -1.- - 2 - A l'inverse, les contraintes de sécurité qui portent sur les applications évoluent à un rythme rapide, en fonction des avancées technologiques dont disposent les attaquants (et surtout les laboratoires qui pratiquent les évaluations sécuritaires des cartes). Cette évolution rapide force à une évolution constante du code des applications, malgré la stabilité des spécifications fonctionnelles. De plus, l'écriture de code relatif à la sécurité et son intégration au sein d'une application constituent une tâche difficile, dont la complexité croît au fil des ans. La plupart des développeurs d'applications "Java Card" n'ont généralement pas de formation nécessaire en sécurité. Le nonrespect de certaines règles de sécurité ou une implémentation incorrecte de certains mécanismes de sécurisation peuvent introduire des failles de sécurité au niveau de l'application mais également au niveau du système entier. Par ailleurs, les développeurs d'applications sont de plus en plus souvent amenés à devoir démontrer que les programmes qu'ils proposent vérifient la politique de sécurité définie par leurs clients et partenaires. Pour cela, les programmes doivent passer à travers des évaluations sécuritaires qui incluent entre autre des analyses automatiques de code. Une difficulté supplémentaire pour les développeurs d'applications est donc de pouvoir structurer leur code de manière à ce que ces analyses automatiques de code (qui ne sont jamais complètes) soient capables de démontrer que leurs applications respectent les politiques de sécurité. L'invention a pour but de faciliter l'écriture de code sécurisé dans le cadre du développement d'applications répondant à des normes de sécurité précises (par exemple "GlobalPlatform"). A cet effet, elle propose une technique de génération automatique de code sécurisé. L'objectif est donc de permettre aux développeurs de décrire une politique de sécurité plutôt que de l'implémenter, et d'ensuite générer du code source sécurisé à partir du modèle décrit. La politique de sécurité permet au développeur d'applications d'établir des règles relatives à trois principes de sécurité, représentant les besoins majeurs aujourd'hui: É La définition et la vérification du cycle de vie de l'application É La sécurisation des échanges entre la carte et le terminal É La sécurisation des structures de données utilisées par l'application -3.- La technique peut facilement être étendue à d'autres besoins de sécurité, si ils s'avèrent importants dans l'avenir. L'invention propose en outre de sécuriser de manière automatique une application, sans intervention du développeur sur son code. En vue de parvenir à ces résultats, l'invention propose d'une façon générale un procédé d'adaptation automatique de programmes à des exigences opérationnelles, ce procédé comprenant les étapes suivantes: a) l'analyse statique du code source ou binaire du programme initial pour en extraire les caractéristiques nécessaires pour établir lesdites exigences opérationnelles; b) la dérivation, à partir des exigences opérationnelles et des caractéristiques du programme extraites à l'étape d'analyse, d'un modèle opérationnel; c) la génération, à partir du modèle opérationnel obtenu à l'étape de dérivation, de 15 code source ou binaire permettant de mettre en oeuvre lesdites exigences opérationnelles; d) l'intégration du code source ou binaire généré dans le programme initial. Avantageusement, dans ce procédé : la susdite analyse statique du programme initial pourra consister en une analyse par interprétation abstraite, la susdite analyse du programme initial pourra comprendre l'extraction du programme initial des informations sur les fonctions, procédures ou méthodes définies ou utilisées par le programme, ou les données, variables ou champs d'objets définis ou accédés dans le programme initial, ou les endroits dans le programme correspondant à certains appels de fonctions, procédures ou invocations de méthodes ou à certains accès à des variables ou champs d'objets, le susdit modèle opérationnel pourra être défini en format XML, la susdite génération de code pourra produire de nouvelles fonctions ou procédures, ou méthodes, des classes au sens des langages à objets, des aspects au sens des langages à aspects, et/ou des services au sens du langage "Java Card 2.2. ", la susdite intégration de codes pourra comprendre les étapes suivantes: -4,- a) analyse statique du programme initial pour identifier des points d'insertion; b) insertion de code aux points d'insertion identifiés dans l'étape d'analyse statique; la susdite analyse statique du programme initial pourra consister en une analyse par interprétation abstraite, la susdite analyse statique du programme initial pourra comprendre une étape d'extraction du programme initial des informations sur les fonctions, procédures ou méthodes définies ou utilisées par le programme, ou les données, variables ou champs d'objets définis ou accédés dans le programme initial, ou les endroits dans le programme correspondant à certains appels de fonctions, procédures ou invocations de méthodes ou à certains accès à des données, variables ou champs d'objets, la susdite insertion de code pourra comprendre des étapes d'ajouts de code avant et/ou après les points d'insertion identifiés et/ou des étapes de remplacements de code aux points d'insertion identifiés, les exigences opérationnelles pourront comporter alternativement ou en combinaison, soit: des restrictions d'exécution d'opérations, fonctions, procédures ou méthodes, lesdites conditions étant dépendantes de l'état d'exécution courant du programme, et des traitements à effectuer en cas de non respect de ces restrictions, soit: - des conditions d'exécution d'opérations, fonctions, procédures ou méthodes, lesdites restrictions étant dépendantes de paramètres d'exécution desdites opérations, fonctions, procédures ou méthodes, et des traitements à effectuer en cas de non respect de ces conditions, soit: - des contraintes sur l'utilisation de certaines données, variables ou champs d'objets, et - des traitements à effectuer en cas de non respect de ces contraintes, les traitements à effectuer en cas de non respect des contraintes ou conditions relatives aux susdites exigences opérationnelles pourront comprendre le blocage du programme ou du dispositif sur lequel il s'exécute et/ou l'émission de signaux d'alerte à destination de son environnement, chaque état de programme dépendant des restrictions imposées par les susdites exigences opérationnelles pourra être associé à un ensemble d'opérations, fonctions, procédures ou méthodes autorisées dans cet état et un ensemble d'états dits successeurs valides résultant de l'exécution d'une des dites opérations, fonctions, procédures ou méthodes autorisées, lesdits états pouvant inclure des états définis dans la spécification "GlobalLPlatform", les conditions d'exécution imposées par les susdites exigences opérationnelles pourront comporter: É des conditions l'intégrité des paramètres et/ou des résultats des opérations, fonctions, procédures ou méthodes, et/ou É des conditions de confidentialité des paramètres et/ou des résultats des opérations, fonctions, procédures ou méthodes, lesdites opérations pouvant consister en des opérations de traitement de commandes par une carte à puce, auquel cas les paramètres des opérations sont des données au format APDU ou RMI envoyées à la carte à puce et les résultats des données au format APDU ou RMI retournées par la carte en réponse aux données reçues, lesdites contraintes sur l'utilisation des données, variables ou champs d'objets imposées par les susdites exigences opérationnelles incluent des contraintes d'intégrité des données, variables ou champs d'objets et/ou des contraintes de confidentialité des données, variables ou champs d'objets, dans le cas où les susdites exigences opérationnelles comportent: - des restrictions d'exécution d'opérations, fonctions, procédures ou méthodes, lesdites conditions étant dépendantes de l'état d'exécution courant du programme, et - des traitements à effectuer en cas de non respect de ces restrictions, le code généré permet de: a) réaliser les changements d'état du programme, b) contrôler le respect des restrictions d'exécutions d'opérations, fonctions, procédures ou méthodes dépendantes de l'état d'exécution courant du programme, et c) effectuer les traitements indiqués en cas de non respect de ces restrictions. Dans le cas où les susdites exigences opérationnelles comportent: des conditions d'exécution d'opérations, fonctions, procédures ou méthodes, lesdites restrictions étant dépendantes de paramètres d'exécution desdites opérations, fonctions, procédures ou méthodes, et des traitements à effectuer en cas de non respect de ces conditions. Le code généré permet de: a) contrôler les conditions d'exécution d'opérations, fonctions, procédures ou méthodes, et b) effectuer les traitements indiqués en cas de non respect de ces conditions. Dans le cas où les susdites exigences opérationnelles comportent: des contraintes sur l'utilisation de certaines données, variables ou champs d'objets, et des traitements à effectuer en cas de non respect de ces contraintes. Le code généré permet de: a) contrôler le respect des contraintes sur l'utilisation des données, variables ou champs d'objets, et b) effectuer les traitements indiqués en cas cle non respect de ces contraintes. Dans le cas où les susdites conditions d'exécution incluent des conditions d'intégrité des paramètres et/ou des résultats des opérations, fonctions, procédures ou méthodes, le code généré permet de vérifier l'intégrité des paramètres et/ou d'assurer l'intégrité des résultats desdites opérations, fonctions, procédures ou méthodes. Dans le cas où les susdites conditions d'exécution incluent des conditions de confidentialité des paramètres et/ou des résultats des opérations, fonctions, procédures ou méthodes, le code généré permet de déchiffrer les paramètres et/ou de chiffrer les résultats desdites opérations, fonctions, procédures ou méthodes afin de gérer leur confidentialité. Dans le cas où lesdites contraintes sur l'utilisation des données, variables ou champs d'objets imposées par les susdites exigences opérationnelles incluent des contraintes d'intégrité des données, variables ou champs d'objets, le code généré permet de vérifier les contraintes d'intégrité des données, variables ou champs d'objets avant leur utilisation et/ou de calculer les données d'intégrité avant toute inscription en mémoire des données, variables ou champs d'objets. Dans le cas où lesdites contraintes sur l'utilisation des données, variables ou champs d'objets incluent des contraintes de confidentialité des données, variables ou champs d'objets, le code généré permet de déchiffrer les données, variables ou champs d'objets avant leur utilisation et/ou de chiffrer les données, variables ou champs d'objets avant leur inscription en mémoire. L'invention s'applique aussi bien à une carte à puce qu'à un téléphone modulaire, à un assistant numérique personnel, à un terminal de paiement bancaire ou à un terminal de paiement portatif. Elle concerne également un système pour l'adaptation automatique de programmes à des exigences opérationnelles conformément au procédé. Un mode de mise en oeuvre du procédé selon l'invention tel que précédemment défini pour la génération automatique de code de sécurisation d'applications sera décrit ci- après, à titre d'exemple non limitatif, avec référence aux dessins annexés dans lesquels: La figure 1 est une représentation schématique d'un code de sécurité généré ; La figure 2 est un diagramme illustrant les étapes d'insertion du code généré dans le code de l'application. Pour ce type d'application, le procédé selon l'invention propose d'appliquer une technique de génération automatique d'un code permettant d'appliquer la politique de sécurité sur une application donnée, et d'insérer ce code dans le code applicatif existant, le processus de développement d'une application sécurisée par la technique de génération automatique de code comprenant les étapes suivantes: 1. l'écriture de l'application sans contraintes de sécurité, 2. la définition de la politique de sécurité de l'application, 3. la transformation de la politique de sécurité en modèle de sécurité utilisable pour la génération de code, 4. la génération du code de sécurité à partir du modèle de sécurité, 5. l'Intégration du code de sécurité dans l'application initiale non sécurisée. Bien entendu, l'invention concerne égalernent les techniques permettant dans les susdites étapes de transformation, de génération et d'intégration, de dériver du code exécutable puis un modèle de sécurité et d'insérer ce code dans du code applicatif existant et, en particulier, la manière dont une application existante peut être dans un premier temps analysée pour mettre en évidence ses besoins de sécurité, et être dans un deuxième temps modifiée pour intégrer du code de sécurité répondant à ces besoins. On rappelle à ce sujet qu'une politique de sécurité définit les principes généraux de sécurité qui doivent être appliqués à l'application. La politique de sécurité n'est pas spécifique à une application, mais globale à un opérateur ou à un ensemble d'opérateurs qui partagent des besoins similaires. Une politique de sécurité consiste en un ensemble de règles concernant la sécurité des applications, qui doivent être appliquées sur toutes les applications. Des exemples de règles sont: É L'application doit supporter un état terrniné dans lequel les données sensibles sont éliminées et certains attributs de sécurité peuvent être consultés par des commandes spéciales. É La visibilité des méthodes doit être aussi restreinte que possible. É L'application ne doit pas définir de classes "Shareable" ou "allouer" des instances de classes "Shareable" définies dans d'autres applications. Ces règles sont utilisées tout au long de la définition du modèle de sécurité, et aussi lors de la génération du code de sécurité. Le modèle de sécurité est défini autour de trois principes fondamentaux répondant aux normes de sécurité définies entre autre par la spécification "GlobalPlatform". Ces trois principes sont la définition et la vérification du cycle de vie d'une application, la sécurisation des échanges entre la carte et le terminal et la sécurisation des structures de données utilisées par l'application. Le modèle de sécurité d'une application dépend de l'application elle-même. Les informations nécessaires pour l'établissement du modèle de sécurité sont extraites du programme non sécurisé (ces informations incluent par exemple la liste des fonctions de l'application et la liste des champs de l'application). Cette extraction est effectuée par une analyse statique du programme, pendant laquelle les règles de la politique de sécurité sont soumises à vérification. Le modèle de sécurité peut ensuite être spécifié par le développeur en définissant diverses propriétés de sécurité pour chaque élément existant de son application (champs et fonctions). La définition du modèle de sécurité prend en compte les trois aspects suivants: Définition et vérification du cycle de vie d'une application, définition du niveau de sécurité des communications entre la carte et le terminal et définition de structures de données sécurisées. - Définition et vérification du cycle de vie d'une application La définition et la vérification d'un cycle de vie est un aspect important dans la définition d'une politique de sécurité. En effet, certains traitements ne peuvent être exécutés que lorsque l'application se trouve dans un état donné. Par exemple, la spécification GlobalPlatform définit à des états APPLICATION_1NSTALLED et APPLICATION_SELECTABLE indiquant respectivement qu'une application a été installée sur la carte et est sélectionnable. Une politique de sécurité plus complète peut définir plus d'états couvrant un cycle de vie plus large ainsi qu'une table de transitions entre états. De plus le développeur d'applications peut également définir de nouveaux états propres à son application et les insérer dans la table des transitions existante. Pour chaque état, le modèle de sécurité inclut au moins les informations suivantes: É La liste des états qui sont des successeurs valides de cet état, ou le fait que l'état est un état réversible (comme l'état "BLOCKED" de "GlobalPlatform". É La liste des fonctions qui peuvent être exécutées dans cet état. É Pour chaque transition possible depuis cet état, une liste de conditions nécessaires et suffisantes pour démarrer la transition. - 10 - Ces trois aspects seront développés ci-après: Il est possible de définir plusieurs variables d'état, et de considérer des états 5 permanents ou temporaires. - Définition du niveau de sécurité des communications entre la carte et le terminal Le modèle de sécurité permet aux développeurs d'applications d'indiquer le niveau de sécurité relatif à chaque fonction du programme (une fonction peut être soit le traitement d'une instruction particulière si l'application traite directement des commandes APDU, soit le traitement d'une méthode particulière si l'application est basée sur le protocole RMI de "Java Card"). Les propriétés de sécurité prises en compte lors du traitement d'une instruction sont: É Authentification du porteur de la carte: indique qu'une commande ne peut être traitée que si le porteur de la carte a été préalablement authentifié selon une méthode particulière. É Intégrité de la commande: indique que la commande contient une preuve de son intégrité et que celle-ci doit être vérifiée avant le traitement de la commande. É Confidentialité de la commande: indique que la confidentialité de la commande est protégée (la commande est chiffrée) et que la commande doit donc être déchiffrée avant son traitement. É Intégrité de la réponse: indique que la réponse renvoyée au terminal doit contenir une preuve garantissant son intégrité. É Confidentialité de la réponse: indique que la réponse renvoyée au terminal doit être confidentielle et doit donc être chiffrée avant son envoi. Chacune de ces propriétés peut être sélectionnée de façon indépendante. La génération de code permet d'automatiser les traitements de données liés à la prise en compte de ces propriétés. De plus, il est possible de générer du code effectuant le traitement complet de commandes spécifiques liées à la sécurité et définies par la spécification "GlobalPlatform". -ll- - Définition de structures de données sécurisées La plupart des interfaces de programmations ne permettent de sécuriser que des communications ou de chiffrer des données simples. La sécurisation de structures de données plus évoluées est donc traditionnellement réalisée manuellement par les développeurs d'applications. Tout comme la sécurisation des commandes et réponses APDU, la sécurisation de structures de données reste une tâche complexe et fastidieuse et peut introduire des failles de sécurité en cas de mauvaise manipulation. Ici encore, la génération de code automatise cette tâche de façon sûre. Pour cela le modèle de sécurité inclut les différentes informations nécessaires à la définition d'une structure sécurisée, soit le nom de la structure et différentes informations sur chacun de ses champs de données. Le modèle de sécurité définit chaque champ de donnée de la manière suivante: É Le nom du champ. É Le type de donnée: il s'agit de différents types de données rencontrés, à savoir un octet (byte), un entier sur deux octets (short), un tableau d'octets ou une référence "Java" (pouvant être une référence sur une structure sécurisée.). É La persistance en mémoire du champ de donnée (persistant, effacé lors de la désélection de l'applet ou lors d'une réinitialisation de la carte.). É Les contraintes de sécurité du champ de données: le champ peut inclure une preuve de son intégrité et sa confidentialité peut être protégée, et plusieurs niveaux sont disponibles pour chacune de ces propriétés en fonction des besoins exprimés dans la politique de sécurité. É Les actions de sécurité associées au champ. En particulier, les actions à prévoir 30 quand l'intégrité du champ est compromise (terminaison immédiate de la carte, utilisation d'un compteur, appel d'une fonction de l'application, etc.). Le modèle de sécurité est défini par des éléments référençant l'application à sécuriser (informations concernant ses champs et méthodes) ainsi que par des éléments propres à la sécurité (définitions des différents états, des transitions entre états, du niveau de sécurité des commandes, etc.). Le modèle de sécurité peut être écrit dans un document indépendant au format XML (souvent généré à partir d'une interface graphique permettant de saisir le modèle) ou directement dans le code source de l'application en utilisant les fonctionnalités d'annotation de code telle que celles offertes par la version 1.5 de Java. L'exemple ci-dessous montre une définition possible d'un modèle de sécurité dans un format semblable à XML. Il définit: É Une méthode, en lui associant les niveaux de sécurité requis pour les commandes 15 et réponses ainsi qu'une liste d'états valides pour l'exécution de la méthode. É Des états, chaque état définit la liste des états suivants valides, pouvant être atteints suivant certaines conditions. É Une structure sécurisée définissant les champs de la structure et les propriétés de sécurité de chaque champ. - 13 - true true true true true int true true false Une fois le modèle de sécurité établi, l'étape suivante consiste à générer 30 automatiquement le code sécurisé nécessaire pour mettre en oeuvre le modèle de sécurité. Les fonctionnalités du code sécurisé sont les suivantes: - 1 4 - É Définition d'une machine à états: à partir des différents états et transitions définis dans le modèle de sécurité, une machine à état peut être générée. Une méthode de changement d'état est également générée. Elle permet à l'application de valider une transition dans la machine à état. Une transition n'est validée que si le nouvel état est un successeur valide de l'état courant et si certaines conditions (optionnelles) définies par le développeurs dans le modèle de sécurité sont remplies. É Vérification de l'état courant: une méthode permettant de retrouver l'état courant de l'application est générée. Des appels à cette méthode seront insérés dans le code source de l'application afin de valider qu'une opération peut être exécutée dans l'état courant. É Service de sécurité : il effectue des traitements liés à la sécurité sur les commandes et réponses. Certaines spécifications comme "GlobalPlatform" précise les formats des commandes et réponses. Ces formats définissent notamment le niveau de sécurité attendu des commandes et réponses. Ce service de sécurité spécifique à une spécification peut alors effectuer automatiquement les tâches liées à la sécurité des commandes et réponses. Il peut notamment vérifier l'intégrité des commandes, déchiffrer les commandes, authentifier l'utilisateur, chiffrer et insérer une preuve d'intégrité des réponses. Le code de ce service peut être soit généré automatiquement, soit défini dans une librairie livrée avec le code sécurisé. Des appels aux méthodes de ce service seront insérés dans le code source de l'application afin de traiter automatiquement les commandes et réponses. É Vérification du niveau de sécurité : une méthode permettant de tester le niveau de sécurité d'une commande (tel que défini par la spécification de sécurité) est générée. Des appels à cette méthode seront insérés dans le code source de l'application afin de déterminer si une opération peut être exécutée en fonction du niveau de sécurité courant. É Structure sécurisée: Les structures sécurisées définies dans le modèle de sécurité sont générées ainsi que les méthodes d'accès et d'altération de chacun des champs. Le code de ses méthodes implémente la sécurisation des champs en fonction du niveau de sécurité défini par le développeur. - 15 - Le code sécurisé lié aux états de l'application ainsi qu'aux structures de données sécurisées est dépendant des informations contenues dans le modèle de sécurité. Ce code est donc généré depuis un outil de génération de code en plusieurs étapes: É Le modèle de sécurité est chargé dans l'outil de génération de code. Cela permet à l'outil d'accéder aux éléments contenus dans le modèle. É Le code sécurisé est généré dans des fichiers sources. Le service de sécurité générique et la méthode de vérification du niveaude sécurité des commandes peuvent être fournis sous forme de librairie indépendante de l'application car ils ne dépendent pas du modèle de sécurité. Ils sont néanmoins spécifiques à une norme de sécurité (par exemple "GlobalPlatform"). Le code généré peut être indifféremment du code source ou du code binaire. La nature du code généré dépendra de la solution d'insertion du code à l'application ainsi que de la nature de l'application. Il pourra s'agir d'aspects ou de classe. Dans un environnement "Java Card 2.2", le service de sécurité pourra être généré sous forme de Service tel que défini par "Java Card 2.2" et pouvant être facilement inséré au sein d'une application. La dernière étape est la plus complexe, puisqu'elle consiste à modifier le code existant pour y intégrer le code de sécurité généré lors de l'étape précédente. Lors de cette étape, le code doit également être modifié afin de vérifier les propriétés de la politique de sécurité qui étaient violées dans le code original. Tel qu'illustré sur la figure 1, le code de sécurité généré conformément au procédé selon l'invention comprend une fonction de validation de transition d'états (bloc 1), une fonction de traitement de la sécurité des commandes et des réponses (bloc 2), une fonction de vérification de l'état et du niveau de sécurité courant (bloc 3) et une fonction d'accès aux structures de données sécurisées (bloc 4). La figure 2 schématise les points d'insertion du code généré à l'étape précédente dans le code d'une application comprenant: - 16 - une étape de réception d'une commande (bloc 5), une étape d'analyse de la commande (bloc 6), une étape d'appel de la fonction correspondante (bloc 7), une étape de traitements divers (bloc 8), une étape de changement d'état (bloc 9), une étape de construction de la réponse (bloc 10), une étape d'envoi de la réponse (bloc 11). Ainsi, les fonctions du bloc 2 (traitement sécurisé des commandes et réponses) ?? seront insérées après l'étape de réception (bloc 5) pour le traitement des commandes et après l'étape de construction de la réponse (bloc 10) pour le traitement des réponses. Les fonctions du bloc 3 (vérification) seront insérées après l'étape d'analyse de la 15 commande (bloc 6). Les fonctions du bloc 4 (accès aux structures de données sécurisées) seront insérées à l'étape de traitements divers (bloc 8). Les fonctions du bloc 1. (validation des transitions d'état) seront insérées à l'étape de changement d'états (bloc 9). L'insertion du code peut être effectuée indifféremment au niveau du code source de l'application ou au niveau du code binaire de l'application. L'insertion du code sécurisé s'effectue selon plusieurs types de manipulations: É Remplacement d'une séquence de code par une séquence modifiée incluant l'utilisation du code de sécurité. É Insertion à certains endroits du programme d'une séquence qui utilise le code de sécurité. É Insertion des données nécessaires et des traitements correspondants (incluant si nécessaire le traitement de fonctions spécifiques). L'insertion est effectuée en plusieurs étapes: - 1'7 - É Chargement du code à modifier dans un outil permettant de le faire. É Utilisation d'analyse statique pour repérer les endroits à modifier. É Remplacement ou insertion du code de sécurité. É Génération du nouveau code. En matière de mise à jour du code, une des spécificités majeures de l'invention est d'utiliser une analyse statique de code sophistiquée afin de repérer les endroits où le code doit être modifié. L'application obtenue après l'insertion du code de sécurité est fonctionnellement strictement équivalente à l'application initiale. Cependant, sa spécification fonctionnelle peut dans certains cas être modifiée, par exemple par l'ajout de fonctions spécifiquement liées à la sécurité (authentification de l'utilisateur, établissement d'un canal sécurisé, ...). Plusieurs solutions d'intégration du code de sécurité au code de l'application seront présentées ci-après: Solution 1 Cette solution comprend les étapes suivantes: 1) Une étape de chargement du code binaire à modifier dans un outil permettant de le faire. 2) Une étape d'analyse du code binaire de l'application. L'analyse statique repère: É Les changements d'états de l'application, soit en repérant les différentes affectations d'une valeur à un champ correspondant à l'état courant de l'application (le développeur devra expliciter le champ correspondant à l'état courant de l'application), soit en repérant les fonctions d'accès et d'altération de l'état courant de l'application (fonctions "getter/setter" spécifié par le développeur) ainsi que les différents appels à ces fonctions. É L'appel aux fonctions de traitement ou de pré-traitement des commandes et réponses. Par exemple, dans un contexte "Java Card", l'analyseur repère les appels à la fonction processAPDU ou les appels aux fonctions processDataln et processDataOut d'un service "Java Card 2.2". É Les affectations des champs à sécuriser (ces champs sont ceux définis dans le modèle de sécurité) ou les appels aux fonctions d'altérations et d'accès de ces champs (getter/setter). É Les différents appels aux méthodes à sécuriser (la liste de ces méthodes est définie dans le modèle de sécurité.) Cette analyse sur le code binaire peut être réalisée au moyen d'algorithmes d'interprétation abstraite. Cette technique d'analyse statique est facilement applicable aux fichiers binaires "Java" dans la mesure où elle est à la base du vérifieur de bytecode standard de "Java". Pour améliorer la précision de l'analyse, ces algorithmes sont également complétés par des algorithmes d'analyse du flot de contrôle de l'application. Grâce à ces algorithmes, il est possible de déterminer les informations nécessaires à la transformation du code: É Dans tous les cas, il est possible de repérer les accès (en lecture ou en écriture) aux champs de l'application, ainsi que l'existence éventuelle de fonction spécialisées pour la consultation et la mise à jour de ces champs ("getter/setter"). É Dans tous les cas, il est également possible de repérer les invocations des méthodes de traitement d'un APDU (réception des données, appel à des fonctions de pré-traitement des commandes et des réponses), ainsi que les invocations des méthodes à sécuriser, qui sont connues. É Si l'application est partiellement sécurisée, il est également possible de repérer les invocations des méthodes de vérification de la sécurité de transport, dans la mesure où des APIs standardisées sont utilisées. É Enfin, il est possible de localiser les changements d'états de l'application, si la variable d'état a préalablement été identifiée par le développeur, soit comme étant une variable de son programme, soit comme étant la variable d'état gérée par la plate-forme. 2879776 - 19 - 3) Une étape de remplacement ou d'insertion de code binaire. L'insertion a lieu directement dans le code binaire de l'application. Les fonctionnalités du code inséré sont les suivantes: É La validation des changements d'états: une nouvelle méthode d'altération de l'état courant est générée, elle inclut un appel à la fonction de machine à états. Si l'application utilise déjà une fonction d'altération pour modifier son état courant, celle-ci est remplacée. Si l'application modifie directement la valeur de l'état courant, les affectations sont remplacées par des appels à la fonction d'altération générée. É La sécurisation des commandes/réponses: des appels de fonctions du service de sécurité sont insérés dans les phases de pré et post traitements des commandes et réponses afin d'effectuer les traitements liés à la sécurité des commandes et réponses (déchiffrage, chiffrage, vérification d'intégrité, authentification de l'utilisateur). É La sécurisation des structures de données: chaque interaction avec des champs de données à sécuriser est remplacée par un appel à la fonction d'altération ou d'accès à la structure de données sécurisée correspondante. La déclaration du champ non sécurisé est supprimée. Une nouvelle fonction est générée dans le code de l'application. Cette fonction est appelée lorsque la sécurité de la structure est compromise et permet d'exécuter une procédure de contre-mesure définie dans le modèle de sécurité (terminaison de l'application, etc.). É Les contrôles des appels aux méthodes de l'application: un code de contrôle est inséré avant chaque appel aux méthodes de l'application définies dans le modèle de sécurité. Ce code vérifie que l'application se trouve dans l'état spécifié par le modèle de sécurité et que la commande correspondante à la méthode de l'application est suffisamment sécurisée (le niveau de sécurité de la commande est également défini dans le modèle de sécurité). Une fois les changements à effectuer repérés par analyse statique, le remplacement du bytecode existant par du bytecode sécurisé est plutôt simple: É Pour les accès aux champs (en lecture ou en écriture), il suffit de remplacer les instructions de lecture ou d'écriture par des invocations de la fonction effectuant - 20 - cette lecture ou cette écriture de manière sécurisée. Les arguments étant les mêmes, cela ne pose aucun problème. É Pour les changements d'état, la procédure est la même. É Pour la sécurisation des méthodes, une méthode incluant les vérifications et l'appel à la méthode à sécuriser est générée, et l'appel de la méthode originale est remplacé par un appel à la nouvelle méthode. Encore une fois, les paramètres sont identiques, et la vérification est donc simple. É Pour la sécurisation des échanges, la technique est similaire, et consiste à définir des méthodes intermédiaires qui ajoutent des traitements sécuritaires en plus des simples échanges de données. De manière à optimiser le code produit, il est parfois préférable de ne pas générer de nouvelles méthodes, mais de plutôt inclure le code directement dans les méthodes existantes. Ceci est en particulier intéressant pour les méthodes qui ne sont appelées qu'une fois. Dans ce cas, des techniques classiques d'expansion du code sont utilisées. Solution 2 Cette solution est identique à la solution 1 mais l'analyse, la génération et l'insertion se font au niveau du code source de l'application. Cela permet au développeur de pouvoir retravailler le code de l'application après sa sécurisation pour y inclure notamment des procédures de contre-mesures spécifiques exécutées lorsque, par exemple, la sécurité d'une structure de donnée sécurisée est compromise. Dans cette solution, les techniques utilisées pour l'analyse, la génération et l'insertion du code sont très similaires à celles utilisées sur le code binaire. La structure du code source "Java" est suffisamment simple pour permettre des modifications de manière assez aisée une fois la syntaxe d'un programme analysée. Solution 3 Cette solution se base sur une technique de programmation par aspects et nécessite un compilateur spécifique. Elle ne requiert pas d'analyse statique du code. Dans cette solution, le code de sécurité généré à partir du modèle de sécurité se présente sous forme d'aspect. Le code source de l'aspect généré définit lui-même les points d'insertion dans le code de l'application en définissant les éléments standard de la construction d'aspects: pointcuts , advices et introductions . Ces éléments permettent de définir exactement où seront insérés les appels au code sécurisé. Au moins quatre types d'aspects différents pourront être générés: É Un aspect de validation des changements d'états: le code de cet aspect est invoqué avant que l'application effectue un changement d'état afin de valider ce changement. É Un aspect de sécurisation des commandes/réponses: le code de cet aspect est invoqué avant tout traitement de commande et envoi de réponse. É Un aspect de sécurisation des données: le code de cet aspect est exécuté avant et après chaque accès à une structure de donnée depuis l'application. L'utilisation de cet aspect requiert que l'application accède aux données à sécuriser uniquement par des méthodes d'accès et d'altération (pas d'accès direct depuis une méthode publique). É Un aspect de validation des appels de méthodes: le code de cet aspect vérifie que l'application se trouve dans l'état spécifié par le modèle de sécurité et que le niveau de sécurité courant est suffisant pour permettre l'invocation de la méthode. Cet aspect est invoqué avant chaque appel aux méthodes définies par le modèle de sécurité. Les aspects sont écrits dans un langage spécifique. Ainsi, l'application et les aspects doivent être compilés par un compilateur spécifique qui se charge d'insérer les appels aux codes des aspects dans le code binaire de l'application. Cette solution seule ne permet pas de modifier le code de l'application afin de vérifier les propriétés de la politique de sécurité qui étaient violées dans le code original. Solution 4 Cette solution est basée sur l'utilisation de la version 1.5 de Java. Le modèle de sécurité est défini en tant qu'annotation au code source de l'application à sécuriser. Plusieurs techniques de modification du code de l'application sont possibles: - 22 - É L'utilisation d'un compilateur spécifique qui génère du code binaire sécurisé en fonction des annotations. É La modification du code binaire à l'exécution, avant le chargement des classes, depuis un "Class Loader" spécifique, peut utiliser l'interface "ClassFileTransformer de Java 1.5". É La modification du code binaire ou du code source depuis un outil spécifique. Cette solution est similaire aux solutions 1 et 2 précédemment évoquées. La différence vient du modèle de sécurité qui est décrit directement dans le code source de l'application. L'exemple ci-après a pour but de présenter le déroulement du processus de sécurisation de code depuis la définition du modèle de sécurité jusqu'à l'insertion du code sécurisé. L'exemple présenté ici est minimal et très simple. Il concerne la sécurisation du cycle de vie de l'application. L'application existante traitée dans cet exemple est supposée posséder au minimum deux états: Etat1 et Etat2 . La génération automatique de code de sécurisation est ici utilisée pour sécuriser la transition entre Etat1 et Etat2 . Soit le modèle de sécurité suivant qui définit simplement la validité d'une transition entre l'état Etat1 et Etat2 de l'application. La transition est valide uniquement si la variable MyVar est égale à la constante MyConst . Dans le cas où la transition serait invalidée, le modèle de sécurité permet de définir une procédure de contre-mesure. Dans cet exemple de modèle de sécurité, la contre mesure est effectuée en invoquant une méthode de l'application. - 23 - Une fois le modèle de sécurité définit, le code de sécurité est généré. Dans l'exemple présent, le code généré crée une machine à états permettant de définir et valider les transitions. Le code généré peut être indifféremment du code source ou du code binaire. Dans cet exemple, par souci de clarté, le code généré est écrit en pseudo-code. La validation ou l'invalidation d'une transition peut se concrétiser par un code de retour de la fonction de validation. Par exemple, lorsqu'une transition est validée, le code de retour de la fonction est 1 , sinon 0 . 10 Fonction validationEtat ( étatCourant, nouvelEtat) { si étatCourant = Etat 1 si nouvelEtat = Etat2 si MyVar = MyConst valider la transition sinon invalider la transition sinon invalider la transition L'étape suivante consiste à insérer le code généré dans le code de l'application afin de mettre en oeuvre le modèle de sécurité. Pour cela, la technique d'analyse statique de code repère les endroits où le code doit être modifié. Dans le cadre de la sécurisation des changements d'états, l'analyse statique repère les changements d'états effectués par le code existant de l'application. Le développeur est supposé avoir préalablement explicité le champ correspondant à l'état courant de l'application. Dans cet exemple, l'application effectue un changement d'état simplement de la façon suivante: étatCourant = Etat2 Après avoir repéré l'altération de la variable d'état, les points d'insertion du code sécurisé sont définis. Dans cet exemple, du code sécurisé est inséré avant et après le changement d'état. Un appel à la fonction de validation des changements d'états est inséré avant que l'application n'altère la variable d'état courant. Si cette fonction valide la transition, l'application est autorisée à altérer sa variable d'état, sinon le code d'invocation de la contre mesure définit par le modèle de sécurité est inséré. Le code résultant devient alors: etc. validationEtat ( étatCourant, Etat2 ) si transition validée étatCourant = Etat2 sinon MyMethod() Dans certains cas, il peut être préférable de ne pas utiliser de nouvelles fonctions afin d'optimiser les performances du code de l'application finale. C'est par exemple le cas si l'application n'effectue qu'un seul changement d'état. Dans ce cas une technique classique d'expansion de code est utilisée afin de produire le code suivant: si étatCourant = Etat 1 si MyVar _ MyConst étatCourant = Etat2 sinon MyMethod() Le code de sécurisation généré peut être directement intégré au code de l'application ou utiliser une librairie spécifique de sécurité. Dans ce dernier cas la librairie doit fournir toutes les fonctionnalités nécessaires à la sécurisation du code au standard définit par la spécification de sécurité (par exemple "GlobalPlatform"). La sécurisation de structures de données et la sécurisation du cycle de vie d'une application constituent des notions de sécurité généralisables à un large type d'applications. Il est donc possible d'utiliser la technique de génération de code pour faciliter la sécurisation d'applications en environnements mobiles et embarqués (J2ME, STIP, FINREAD.) La gestion du cycle de vie semble tout à fait adaptée à des environnements où les applications sont exécutées de façon asynchrones (STIP, FINREAD). De telles applications définissent différents états et machines à états. - 26 - Revendications 1. Procédé d'adaptation automatique de programmes à des exigences opérationnelles, caractérisé en ce qu'il comprend les étapes suivantes: a) l'analyse statique du code source ou binaire du programme initial pour en extraire les caractéristiques nécessaires pour établir lesdites exigences opérationnelles; b) la dérivation, à partir des exigences opérationnelles et des caractéristiques du programme extraites à l'étape d'analyse, d'un modèle opérationnel; c) la génération, à partir du modèle opérationnel obtenu à l'étape de dérivation, de code source ou binaire permettant de mettre en oeuvre lesdites exigences opérationnelles; d) l'intégration du code source ou binaire généré dans le programme initial. 2. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 1, caractérisé en ce que ladite analyse statique du programme initial est une analyse par interprétation abstraite. 3. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 1, caractérisé en ce que ladite analyse du programme initial comprend l'extraction du programme initial des informations sur les fonctions, procédures ou méthodes définies ou utilisées par le programme, ou les données, variables ou champs d'objets définis ou accédés dans le programme initial, ou les endroits dans le programme correspondant à certains appels de fonctions, procédures ou invocations de méthodes ou à certains accès à des variables ou champs d'objets. 4. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 1., caractérisé en ce que ledit modèle 30 opérationnel est défini dans un format XML. 5. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 1, caractérisé en ce que ladite génération de code produit de nouvelles fonctions ou procédures ou méthodes. - 27 - 6. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 1, caractérisé en ce que ladite génération de code produit des classes au sens des langages à objets. 7. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 1, caractérisé en ce que ladite génération de code produit des aspects au sens des langages à aspects. 8. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 1, caractérisé en ce que ladite génération de code produit des services au sens du langage "Java Card 2. 2". 9. Procédé d'adaptation automatique de programmes à des exigences 15 opérationnelles selon la revendication 1, caractérisé en ce que ladite intégration de code comprend les étapes suivantes: a) analyse statique du programme initial pour identifier des points d'insertion; b) insertion de code aux points d'insertion identifiés dans l'étape d'analyse statique. 10. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 9, caractérisé en ce que ladite analyse statique du programme initial est une analyse par interprétation abstraite. 11. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 9, caractérisé en ce que ladite analyse du programme initial comprend une étape d'extraction du programme initial des informations sur les fonctions, procédures ou méthodes définies ou utilisées par le programme, ou les données, variables ou champs d'objets définis ou accédés dans le programme initial, ou les endroits dans le programme correspondant à certains appels de fonctions, procédures ou invocations de méthodes ou à certains accès à des données, variables ou champs d'objets. - 28 - 12. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 9, caractérisé en ce que ladite insertion de code comprend des ajouts de code avant et/ou après les points d'insertion identifiés. 13. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 9, caractérisé en ce que ladite insertion de code comprend des remplacements de code aux points d'insertion identifiés. 14. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon l'une des revendications précédentes, caractérisé en ce que lesdites exigences opérationnelles comportent: -des restrictions d'exécutions d'opérations, fonctions, procédures ou méthodes, lesdites conditions étant dépendantes de l'état d'exécution courant du programme, et - des traitements à effectuer en cas de non respect de ces restrictions. 15. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon l'une des revendications précédentes, caractérisé en ce que lesdites exigences opérationnelles comportent: des conditions d'exécution d'opérations, fonctions, procédures ou méthodes, lesdites restrictions étant dépendantes de paramètres d'exécution desdites opérations, fonctions, procédures ou méthodes, et des traitements à effectuer en cas de non respect de ces conditions. 16. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon l'une des revendications précédentes, caractérisé en ce que lesdites exigences opérationnelles comportent: -des contraintes sur l'utilisation de certaines données, variables ou champs d'objets et - des traitements à effectuer en cas de non respect de ces contraintes. 17. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon l'une des revendications 14, 15 ou 16, caractérisé en ce que les traitements à effectuer en cas de non respect desdites contraintes ou conditions - 29 - comportent le blocage du programme ou du dispositif sur lequel il s'exécute et/ou l'émission de signaux d'alerte à destination de son environnement. 18. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 14, caractérisé en ce que chaque état du programme est associé à un ensemble d'opérations, fonctions, procédures ou méthodes autorisées dans cet état et un ensemble d'états dits successeurs valides résultant de l'exécution d'une des dites opérations, fonctions, procédures ou méthodes autorisées. 19. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 18, caractérisé en ce que lesdits états du programme incluent les états définis dans la spécification "GlobalPlatform". 20. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 15, caractérisé en ce que lesdites conditions d'exécution incluent des conditions d'intégrité des paramètres et/ou des résultats des opérations, fonctions, procédures ou méthodes. 21. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 15, caractérisé en ce que lesdites conditions d'exécution incluent des conditions de confidentialité des paramètres et/ou des résultats des opérations, fonctions, procédures ou méthodes. 22. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon l'une des revendications 19, 20 ou 21, caractérisé en ce que lesdites opérations sont des opérations de traitement de commandes par une carte à puce. 23. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 22, caractérisé en ce que les paramètres des opérations sont des données au format APDU ou RMI envoyées à la carte à puce et les résultats des données au format APDU ou RMI retournées par la carte en réponse aux données reçues. 24. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 16, caractérisé en ce que lesdites contraintes sur l'utilisation des données, variables ou champs imposées par les susdites exigences opérationnelles d'objets incluent des contraintes d'intégrité des données, variables ou champs d'objets. 25. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 16, caractérisé en ce que lesdites contraintes sur l'utilisation des données, variables ou champs d'objets incluent des contraintes de confidentialité des données, variables ou champs d'objets. 26. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 14, caractérisé en ce que le code généré permet de: a) réaliser les changements d'état du programme, b) contrôler le respect des restrictions d'exécution d'opérations, fonctions, procédures ou méthodes dépendantes de l'état d'exécution courant du programme, et c) effectuer les traitements indiqués en cas de non respect de ces restrictions. 27. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 15, caractérisé en ce que le code généré permet de. a) contrôler les conditions d'exécution d'opérations, fonctions, procédures ou méthodes, et b) effectuer les traitements indiqués en cas de non respect de ces conditions. 28. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 16, caractérisé en ce que le code généré permet de: a) contrôler le respect des contraintes sur l'utilisation des données, variables ou champs d'objets, et b) effectuer les traitements indiqués en cas de non respect de ces contraintes. -31 - 29. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 20, caractérisé en ce que le code généré permet de vérifier l'intégrité des paramètres et/ou d'assurer l'intégrité des résultats desdites opérations, fonctions, procédures ou méthodes. 30. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 21, caractérisé en ce que le code généré permet de déchiffrer les paramètres et/ou de chiffrer les résultats desdites opérations, fonctions, procédures ou méthodes afin de gérer leur confidentialité. 31. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 24, caractérisé en ce que le code généré permet de vérifier les contraintes d'intégrité des données, variables ou champs d'objets avant leur utilisation et/ou de calculer les données d'intégrité avant toute inscription en mémoire des données, variables ou champs d'objets. 32. Procédé d'adaptation automatique de programmes à des exigences opérationnelles selon la revendication 25, caractérisé en ce que le code généré permet de déchiffrer les données, variables ou champs d'objets avant leur utilisation et/ou de chiffrer les données, variables ou champs d'objets avant leur inscription en mémoire. 33. Application du procédé selon l'une des revendications 1 à 32 à une carte à puce, à un téléphone modulaire, à un assistant numérique personnel, à un terminal de 25 paiement bancaire ou à un terminal de paiement portatif. 34. Système pour l'adaptation automatique de programmes à des exigences opérationnelles conformément au procédé selon l'une des revendications 1 à 32.