Brevet FR2832821A1 — publié le 20030530

Procédé de vérification de codes pour microcircuits à ressources limitées La présente invention concerne un procédé de vérification de codes utilisés avec des microcircuits à ressources limitées, tels que utilisés dans des cartes à puce, notamment pour vérifier l'intégrité et assurer l'innocuité du code. Les cartes à microcircuit électronique, dites cartes à puce, sont utilisées comme support informatique mobile pour des applications très diverses et exigeant pour la plupart d'entre elles un haut niveau de sécurité, notamment les opérations bancaires, les paiements sécurisés, l'accès aux bâtiments ou à des zones sécurisées et les télécommunications. L'utilisation répandue des cartes à puce et la diversité de leurs applications tendent actuellement à l'utilisation de plateformes ouvertes, telle la plateforme connue sous le nom de"Java", qui permet le chargement, dans la mémoire d'une machine de traitement de données électroniques, d'applications compatibles avec la plateforme. Une plateforme tel que Java présente deux avantages, la standardisation du code intermédiaire, dit"bytecode", et son indépendance par rapport à la machine. Tout programme Java peut donc être compilé en une série d'instructions bytecode universellement comprises par toute machine basée sur une telle plateforme. Etant donné que les cartes à puce sont mobiles et qu'elles sont utilisées en relation avec des systèmes informatiques étrangers, ou qu'elles exécutent un bytecode d'origine soit inconnue, soit non-sécurisée, il est nécessaire de vérifier l'intégrité et l'innocuité du programme utilisé avec la carte. Un programme de vérification de code intermédiaire de type Java est décrit dans le brevet US 5,740, 441. Le procédé de vérification décrit dans ce brevet est adapté aux systèmes informatiques tels que des ordinateurs PC dont la puissance de calcul de leur processeur et la capacité de leur mémoire vive RAM (Random Access Memory) sont nettement supérieures à celles d'une carte à puce. La puissance d'un processeur et la capacité de la mémoire vive ou de la mémoire persistante ROM (Read Only Memory) sont fonction de la surface de silicium encarté. Les cartes à puce devant d'une part respecter des contraintes mécaniques, en particulier la torsion et la flexion, et d'autre part garantir une durée de vie raisonnable, leur surface de silicium ne dépasse généralement pas 27 mm2. La mémoire d'une carte à puce a typiquement une capacité entre 128 et 496 octets, par conséquent bien inférieure aux 64 à 128 mega-octets de RAM dont dispose l'ordinateur PC le moins performant proposé actuellement sur le marché. Il existe plusieurs solutions permettant de vérifier le bytecode dans des dispositifs dont la capacité de mémoire est très limitée. L'une de ces approches consiste à modifier le code intermédiaire du programme à vérifier à l'extérieur du dispositif de telle sorte que le procédé de vérification soit plus aisé sans entraîner pour autant une diminution de fiabilité. Cette approche implique une compatibilité des différents systèmes informatiques, réduisant ainsi la sphère d'utilisation des microcircuits utilisant ces méthodes de vérification. Une autre approche consiste à ajouter au code le résultat d'un algorithme de pré-calcul qui sera ensuite repris par le vérifieur du bytecode. Il peut s'agir par exemple de la méthode PCC (Proof Carrying Code) ou d'une variante de cette dernière qui permet au vérifieur encarté d'utiliser des algorithmes plus simples. Un programme, tel qu'un applet Java quelconque, ne comprennent pas le code supplémentaire PCC, ne pourra donc pas être vérifié par le microcircuit. La sphère d'utilisation des microcircuits utilisant ces méthodes est donc limitée. Les procédés conventionnels de vérification du code intermédiaire (bytecode) Java destinés à être utilisés dans des microcircuits à ressources limitées peuvent également avoir les inconvénients d'augmenter la quantité d'informations à transmettre au microcircuit, de nécessiter l'implémentation et l'exécution d'un logiciel relativement complexe dans le système informatique externe en communication avec la carte à puce, ou de limiter l'utilisation de certaines techniques d'optimisation de calcul du programme. Tenant compte de ce qui précède, l'un des objectifs de l'invention est de fournir un procédé de vérification de code intermédiaire destiné à être exécuté dans un objet à microcircuit à ressources limitées, économe en termes d'occupation des ressources de mémoire du microcircuit, notamment la mémoire volatile et/ou la mémoire persistante accessible en écriture et lecture du microcircuit. Il est avantageux de fournir un procédé de vérification destiné à être exécuté dans un objet à microcircuit à ressources limitées, ayant un large spectre d'utilisation pour une plateforme donné, tel que le Java ou des variantes telles que le Javacard. Il est en outre avantageux de réduire l'utilisation des ressources de calculs du microcircuit de l'objet. Il est également avantageux de réduire le temps nécessaire pour effectuer la vérification d'un programme à vérifier. Des buts de l'invention sont réalisés par un procédé selon la revendication 1. Dans la présente invention, un procédé de vérification de codes intermédiaires exécutable par un microcircuit à ressources limitées connecté à un système de traitement de données externe, comprend une phase de chargement d'instructions du code intermédiaire ou d'informations à vérifier associées aux instructions du code intermédiaire dans une mémoire du microcircuit, une phase d'initialisation desdites informations à vérifier et une phase de vérification de l'intégrité du code intermédiaire, caractérisé en ce que, dans la phase d'initialisation, une fonction cryptographique est appliquée dans le microcircuit auxdites informations à vérifier ou auxdites instructions du code intermédiaire pour générer un code d'authentification, et au moins une partie desdites informations à vérifier ou desdites instructions du code intermédiaire sont envoyés et stockés dans le système de traitement de données externe. La fonction cryptographique peut être une fonction de chiffrement utilisant au moins une clé secrète k. Avantageusement, le stockage dans le système de traitement de données externe des instructions ou des informations à vérifier associé aux instructions de code intermédiaire permet de réduire l'utilisation des mémoires du microcircuit accessibles en écriture et lecture, telles que les mémoires volatiles RAM (Random Access Memory) ou les mémoires persistantes de type FLASHRAM ou EEPROM (Electrical Erasable Programmable Read Only Memory), sans pour autant compromettre la sécurité du procédé de vérification. En effet, le calcul d'un code d'authentification (MAC) sur la base d'une clé secrète générée dans le microcircuit et fonction des données envoyées au système de traitement de données externe permet de vérifier l'intégrité de ces données rappelées selon besoin dans le microcircuit en comparant le code d'authentification reçu du système externe avec le code d'authentification calculé dans le microcircuit. D'autre part, le procédé de vérification selon l'invention a un large spectre d'utilisation du fait qu'il ne nécessite pas de modification ou d'adjonction au code intermédiaire par un système externe. La présente invention est avantageusement applicable à la vérification de programmes basées sur une plate-forme Java ou de variantes Java telle que Javacard, les plate-formes Java étant très répandues. La clé secrète peut avantageusement être éphémère et générée par le microcircuit. Elle pourrait toutefois être stockée dans une mémoire du microcircuit. Dans une première forme d'exécution, les instructions du code intermédiaire sont stockées dans le microcircuit et au moins une partie des informations à vérifier associées aux instructions du code intermédiaire, comprenant un tableau de données de type, sont stockées dans le système externe. Le code d'authentification est calculé en utilisant la clé secrète générée dans le microcircuit et au moins les données de type. Les données de type sont par la suite envoyées au système externe avec le code d'authentification pour stockage. Dans une autre variante, le code d'authentification est calculé avec une fonction de hachage sans utiliser une clé secrète, le code d'authentification étant toutefois stocké dans le microcircuit. Les informations à vérifier peuvent également comprendre une valeur d'état (ou Flag ) pouvant prendre les valeurs changed ou unchanged pour indiquer si une ligne du tableau de données de type a été changée ou non. La valeur d'état peut être incorporée dans le calcul du code d'authentification et envoyée au système externe pour stockage avec les données de type. Les informations à vérifier associées aux instructions du code intermédiaire peuvent également comprendre un compteur associé à une instruction ou à une séquence d'instructions à l'intérieur de laquelle il ne peut pas y avoir de sauts, le compteur indiquant le nombre de fois que l'instruction ou la séquence d'instructions est parcourue pendant le procédé de vérification. La valeur du compteur peut être incorporée dans le calcul du code d'authentification, ce qui permet de manière avantageuse de s'assurer que les informations à vérifier qui sont reçues du système externe selon besoin dans le microcircuit sont les plus récentes. Dans une variante de la première forme d'exécution, le compteur est stocké dans le système externe. A cette fin, le microcircuit génère une deuxième clé secrète pour le calcul d'un deuxième code d'authentification basé sur cette clé et fonction du compteur de manière à pouvoir envoyer le compteur accompagné du deuxième code d'authentification au système externe pour stockage. Le compteur reçu du système externe selon besoin peut donc être vérifié en comparant le code d'authentification retourné par le système avec un code d'authentification calculé dans le microcircuit. Dans une deuxième forme d'exécution d'un procédé de vérification selon l'invention, au moins une partie des informations à vérifier associées aux instructions du code intermédiaire sont stockées dans le microcircuit alors que les instructions sont stockées dans le système externe. Pendant la vérification, le microcircuit reçoit du système externe selon besoin une instruction du code intermédiaire ainsi que le code d'authentification, et vérifie que le code d'authentification reçu du système externe correspond bien au code d'authentification calculé par le microcircuit. Dans une autre variante de cette forme d'exécution, au lieu de recevoir avec chaque instruction le code d'authentification, le microcircuit génère et actualise une variable interne qui est fonction de la variable interne précédente et un code d'authentification résultant d'un chiffrement appliqué sur l'instruction correspondante, et le système externe génère et stocke une variable externe qui est fonction de la variable externe précédente et le code d'authentification envoyé dans la phase d'initialisation par le microcircuit au système externe. Les variables interne et externe sont vérifiées dans le microcircuit dans une phase de vérification finale, et si la variable externe n'est pas conforme à la variable interne, le programme à vérifier est rejeté. Cette variante permet de manière avantageuse, d'une part à réduire les communications entre le microcircuit et le système externe, d'autre part à réduire l'initialisation de la mémoire volatile du microcircuit. Les communications entre le système externe et le microcircuit peuvent être également réduites en faisant de sorte que le système externe suit le procédé de vérification en parallèle et envoie automatiquement, c'est-à-dire sans demande du microcircuit, les informations à vérifier sont stockées dans le système externe. D'autres caractéristiques avantageuses de l'invention ressortiront des revendications, de la description détaillée de formes d'exécution de l'invention donnée ci-après et des dessins annexés, dans lesquels : la Fig. 1 est une représentation simplifiée d'instructions de code intermédiaire (bytecode) et d'informations associées aux instructions ; la Fig. 2 montre un organigramme illustrant l'enchaînement des étapes dans une phase de connexion et de chargement d'un procédé de vérification de code intermédiaire selon l'invention ; la Fig. 3 montre un organigramme illustrant l'enchaînement des étapes dans une phase d'initialisation d'un procédé de vérification de code intermédiaire selon une première forme d'exécution de l'invention ; la Fig. 4 montre un organigramme illustrant l'enchaînement des étapes dans une phase de vérification d'un procédé de vérification de code intermédiaire selon une première forme d'exécution de l'invention ; la Fig. 5 montre un organigramme illustrant l'enchaînement des étapes dans une phase de vérification finale d'un procédé de vérification de code intermédiaire selon une première forme d'exécution de l'invention ; la Fig. 6 montre un organigramme illustrant l'enchaînement des étapes dans une phase d'initialisation d'un procédé de vérification de code intermédiaire selon une deuxième forme d'exécution de l'invention ; la Fig. 7 montre un organigramme illustrant l'enchaînement des étapes dans une phase de vérification d'un procédé de vérification de code intermédiaire selon une deuxième forme d'exécution de l'invention ; la Fig. 8 montre un organigramme illustrant l'enchaînement des étapes dans une phase de vérification finale d'un procédé de vérification de code intermédiaire selon une deuxième forme d'exécution de l'invention ; la Fig. 9 montre un organigramme illustrant l'enchaînement des étapes dans une phase de vérification d'un procédé de vérification de code intermédiaire selon une variante de la deuxième forme d'exécution de l'invention ; la Fig. 10 montre un organigramme illustrant l'enchaînement des étapes dans une phase de vérification finale d'un procédé de vérification de code intermédiaire selon une variante de la deuxième forme d'exécution de l'invention. La Fig. 1 montre, de manière simplifiée, une série d'instructions 1 à S d'un code intermédiaire, tel qu'un bytecode Java, ainsi que des données associées à chacune de ces instructions, ces données comprenant un flag F [i] pouvant prendre les valeurs d'état"changed"ou "unchanged", un tableau de données de type ou"frame" T [i] et un compteur C [i] de changement de données dans le tableau. Chaque ligne du tableau comprend une série de données indiquant le type de chacune des valeurs du registre utilisées par l'instruction correspondante du bytecode, ainsi que les données indiquant le type de chacune des valeurs stockées dans la pile utilisée par le bytecode. La taille du registre ainsi que celle de la pile sont déterminées dans les phases de connexion et de chargement au moyen de compteurs ayant pour fonction de compter le nombre de données du registre et de déterminer la taille maximale de la pile. Faisant référence à la Fig. 2, les étapes de connexion de chargement d'une carte à puce sont montrées à titre d'exemple, étant entendu que l'invention peut s'appliquer à toute sorte d'autres objets à microcircuit destinés à être connectés à un système informatique externe par contact direct ou par ondes électromagnétiques, dont les ressources de mémoire et/ou de calculs sont limitées. L'étape 10 de connexion du microcircuit, représentant par exemple l'insertion d'une carte à puce dans un terminal, est suivie par une étape 12 de négociation du protocole de communication entre le microcircuit de la carte et le système informatique du terminal. Une fois la communication établie, il y a une étape 14 de chargement de données du programme à vérifier dans la mémoire du microcircuit. Le programme, qui peut par exemple être un applet Java, est présenté à la carte sous forme de code intermédiaire ou"bytecode"défini de manière simplifiée par une série d'instructions B [i], tel que montré dans la Fig. 1, et ses arguments. La mémoire à laquelle on se réfère dans l'étape 14 peut être une mémoire volatile telle que la mémoire RAM (Random Access Memory) ou une mémoire persistante telle que la mémoire EEPROM (Electric Erasable Programmable Read Only Memory) ou FLASHRAM, ou une combinaison de plusieurs de ces mémoires. Les données qui sont chargées dans le microcircuit de l'objet à ressources limitées dépendent de la forme d'exécution de l'invention. De manière générale, dans des formes d'exécution de l'invention, on charge soit les instructions du code intermédiaire dans une mémoire du microcircuit et on stocke le tableau de types associé aux instructions dans le système de traitement de données externe (ci-après "système externe") avec lequel le microcircuit est connecté, soit on charge le tableau de types dans une mémoire du microcircuit et on stocke les instructions du code intermédiaire dans le système externe. Une première forme d'exécution de l'invention sera décrite en relation avec les figures 3 à 5 qui montrent des organigrammes de différentes phases d'un procédé de vérification d'un programme destiné à être utilisé en relation avec un objet à microcircuit à ressources limitées, tel qu'une carte à puce. La première phase du procédé de vérification est une phase d'initialisation suivant de manière générale les étapes de l'organigramme montré dans la Fig. 3. Dans cette phase d'initialisation, le microcircuit génère dans l'étape 16 une clé secrète k de préférence éphémère et utilisée seulement pour un procédé de vérification. La clé secrète pourrait également être stockée dans une mémoire non volatile du microcircuit si l'on est un peu moins exigeant sur le niveau de sécurité. Pour augmenter le niveau de sécurité, on peut également générer dans le microcircuit une valeur h représentant le résultat d'une fonction de hâchage sur l'état du microcircuit avant que la vérification ne commence, et sur le fichier CAP, c'est-à-dire le fichier d'instructions du code intermédiaire avec ses arguments. La clé secrète k ainsi que la valeur de hâchage h seront utilisées pour le calcul d'un code d'authentification MAC (Message Authentification Code). Dans l'étape suivante 18, on forme une ligne T [i] d'un tableau T de données de type initialisé et l'on ajoute à cette ligne un compteur C [i] et une valeur d'état dite"flag"F [i], qui sont également initialisés. Le compteur C [i] représente le nombre de fois que l'instruction correspondante a été parcourue, la valeur initiale de C [i] étant mise à 0, sauf pour la première instruction où C [i] = 1. La valeur d'état ou flag F [i] peut prendre la valeur"changed"ou"unchanged", le flag F [i] étant initialisé à la valeur"unchanged"sauf pour la première instruction où F [i] ="changed". Le microcircuit calcule ensuite (étape 20) un MAC r [i] qui est une fonction utilisant la clé secrète k des 1 valeurs de la ligne décrite précédemment, c'est-à-dire une fonction du flag F [i], du compteur C [i], du tableau de données de type T [i] et du numéro d'instruction i. Suite au calcul du MAC, le microcircuit envoie (étape 22) au système externe les valeurs du flag F [i], du tableau T [i], de la position de l'instruction i ainsi que le MAC r [i], ces données étant stockées dans une mémoire du système externe. Le microcircuit garde en mémoire la valeur du compteur C [i]. Les étapes d'initialisation 18, de calcul d'un code 20 et de l'envoi au terminal 22 sont effectuées pour toutes les instructions S du code à vérifier, c'est-à-dire pour i allant de 1 à S. Il est à noter que le stockage dans une mémoire volatile telle que RAM du microcircuit, de la valeur du compteur C [i] permet d'éviter le renvoi de données non actualisées par le système au microcircuit. Un tel renvoi pourrait attaquer l'intégrité de la procédure de vérification par la substitution d'un type par un autre type lors de la procédure de vérification. Après la phase d'initialisation commence la phase de vérification telle que décrite en rapport avec l'organigramme montré dans la Fig. 4. Dans la première étape 24, le microcircuit demande au système externe de lui renvoyer une ligne de données de type T [i] dont le flag correspondant F [i] a la valeur d'état"changed". Dans la prochaine étape 26, le microcircuit vérifie que le MAC r [i] envoyé par le système externe est correct. Dans cette procédure de vérification, on recalcule le MAC r [i] dans le microcircuit sur la base des valeurs du compteur C [i] et de la clé secrète k qui sont stockées dans une mémoire du microcircuit ainsi que la ligne de données de type du tableau T [i] et la valeur du flag F [i] renvoyées par le système externe. La valeur de MAC calculée par le microcircuit est comparée avec la valeur envoyée par le terminal et en cas de différence, le programme à vérifier est rejeté et la phase de vérification se termine par un échec. Cette vérification du MAC permet d'assurer que les données renvoyées par le terminal n'ont pas été manipulées ou substituées et concordent bien avec les données les plus courantes envoyées par le microcircuit au système externe pour stockage. En cas de concordance du MAC, on utilise dans l'étape suivante 28 les données de type dans la ligne du tableau T [i] pour vérifier si les règles de transition de type permettent l'exécution de l'instruction correspondante B [i]. Si l'instruction B [i] à la position i implique une transition de type d'au moins une des données de la ligne du tableau T [i] correspondant qui n'est pas permise selon les règles de transition de type, le programme est rejeté et la phase de vérification se termine par un échec. Si les règles de transition sont respectées, la prochaine étape 29 consiste à appliquer les règles de transition de type aux données dans la ligne du tableau T [i], les résultats étant stockés dans un tableau de travail T', et l'on incrémente le compteur C [i] de 1. Pour toutes les instructions aux positions j qui sont les successeurs potentiels de l'instruction à la position i, le microcircuit rappelle (étape 30) la ligne de données de type T [j] ainsi que le MAC r [j] du système externe et vérifie, de la même manière que décrite cidessus en relation avec l'étape 26, que le MAC retourné par le système externe est correct. En cas d'échec, le programme à vérifier est rejeté et le procédé de vérification se termine par un échec. Dans la prochaine étape 34, les données de type de la ligne T [j] sont unifiées avec les données de type de la ligne T [i] se trouvant dans le tableau de travail T', mais si l'unification n'est pas possible, le programme à vérifier est rejeté. Dans le cas contraire, si les données de type de la ligne T [i] ont changées, on incrémente le compteur C [j] de 1 (étape 36) et on calcule un MAC r [j] pour la ligne j en fonction des valeurs du flag F [j] ="changed", le compteur C [j], la position de l'instruction j, et la ligne de tableau T [j] (étape 38). Dans la prochaine étape 40, on envoie le flag F [j] ="changed", la ligne de tableau T [j] actualisée dans l'étape 34, la position de l'instruction j et le MAC r [j] qui vient d'être calculé, ces valeurs actualisées remplaçant les valeurs stockées dans le système externe. Dès que toutes les instructions B [j] successeurs potentiels de l'instruction B [i] ont été traitées, on passe à la prochaine étape 42 où l'on calcule le MAC r [i] de la même manière qu'auparavant, mais avec les valeurs des données de type T [i] et du compteur de changement C [i] actualisé. Ensuite (étape 44) on envoie au système externe la valeur du flag F [i] ="unchanged", la ligne du tableau T [i] actualisée, la position i et le MAC r [i] qui vient d'être calculé, ces valeurs actualisées remplaçant les valeurs précédentes à l'entrée i de la mémoire du système externe. S'il y a encore des lignes dont le flag F [i] ="changed", on répète les étapes 24 à 44 décrites ci-dessus, sinon on procède à la phase de vérification finale, dont l'organigramme est montré à la Fig. 5. Dans la phase de vérification finale, le microcircuit rappelle la ligne de données de type T [i] du tableau T, la position de la ligne i, ainsi que le MAC r [i] stocké dans la mémoire du système externe (étape 46) et vérifie que le MAC retourné par le système externe correspond bien à un MAC calculé par le microcircuit en utilisant les valeurs du flag F [i] ="unchanged", le compteur C [i], la position i et la ligne de données du type T [i] (étape 48). Le succès de cette vérification permet d'assurer que le flag de toutes les instructions a bien la valeur d'état"unchanged"et le procédé de vérification du programme à vérifier peut se terminer avec succès. On peut constater de la description du procédé ci-dessus que l'on peut effectuer une vérification entière d'un programme destinée à être exécutée par un microcircuit à ressources de mémoire très limitées sans pour autant compromettre la sécurité du procédé. En effet, pour effectuer le procédé ci-dessus, le microcircuit doit disposer d'une mémoire permettant de stocker S instructions du code intermédiaire et S compteurs C [i] ainsi que des mémoires tampons permettant la réception d'une ligne de données associées à une instruction du système externe et le calcul du MAC. De manière avantageuse, on peut encore réduire l'utilisation de la mémoire du microcircuit en ne stockant qu'un compteur C [i] par séquence d'instructions à l'intérieur de laquelle il ne peut pas y avoir de sauts. Par exemple, les séquences d'instructions de i = 1 à i = 3, et de i = 4 à 1 = 8, montrées dans la Fig. 1 peuvent être associées à un seul compteur. Dans une variante de la première forme d'exécution que l'on vient de décrire, on peut encore réduire l'utilisation des mémoires accessibles en écriture et lecture du microcircuit par le programme de vérification en stockant les valeurs du compteur C [i] dans le système externe, sans pour autant compromettre le niveau de sécurité du procédé de vérification. A cette fin, le microcircuit génère une deuxième clé secrète k', de préférence éphémère, différente à la première clé secrète k. Dans la mémoire du microcircuit on stocke un seul compteur t que l'on initialise à la valeur 0. Par rapport au procédé décrit auparavant, au lieu de stocker la valeur du compteur dans le microcircuit dans la phase d'initialisation et de l'incrémenter et le stocker dans le microcircuit dans la phase de vérification, on stocke le compteur C [i] dans une mémoire du système externe. Dans la phase d'initialisation, on calcule un MAC m [i], en fonction de la position i, du compteur C [i] et du compteur unique t. La valeur du compteur C [i] est initialisée à 0, et la valeur du compteur unique t stockée dans la mémoire du microcircuit est également initialisée à la valeur 0. On effectue cette initialisation pour tous les séquences d'instructions du code intermédiaire à vérifier. Pour lire le compteur C [i] pendant la phase de vérification, le microcircuit rappelle ou reçoit du système externe : la position i, la valeur du compteur C [i] et la valeur du MAC m [i]. Le MAC m [i] renvoyé par le système externe est vérifié par le microcircuit qui recalcule le MAC et, en cas de différence, rejette le programme à vérifier et termine le procédé de vérification par un échec. Quand le bloc de séquences d'instructions en question est parcouru par le programme de vérification, le compteur C [i] est incrémenté par 1 et le compteur unique t dans le microcircuit est également incrémenté par la valeur 1. Le microcircuit recalcule un MAC actualisé m [i] en fonction de la position i, du compteur C [i] actualisé et du compteur t actualisé. Le microcircuit envoie ensuite le MAC m [i] actualisé au système externe. Le compteur t stocké dans le microcircuit (par exemple un compteur à 32 bits) permet d'assurer que les compteurs C [i] des séquences d'instructions renvoyés par le système externe sont les derniers actualisés, le compteur unique t prenant toutefois moins de place en mémoire que l'ensemble des compteurs C [i]. Les calculs a effectuer par le microprocesseur du microcircuit pendant la vérification d'un programme à vérifier peuvent être réduits par des modifications de certaines étapes du procédé décrit ci-dessus. Selon une variante, l'étape d'unification du type décrit auparavant en rapport avec l'étape 36 de la Fig. 4, est effectuée à l'aide du système externe. Le code intermédiaire étant fixe, c'est-à-dire déterminé, le système externe peut suivre en parallèle la séquence d'étapes de vérification effectuées par le microcircuit. On peut avantageusement transférer au système externe la tâche de trouver le prochain ancêtre commun de deux types lors de l'unification. Le microcircuit de l'objet à ressources limitées vérifie seulement si le résultat retourné par le système externe est effectivement le prochain ancêtre commun des deux types à unifier. Cette dernière détermination requiert moins de calculs que la recherche de l'ancêtre commun et diminue donc le calcul à effectuer par le microcircuit. D'autre part, du fait que le code intermédiaire est déterminé, le rappel de données stockées dans le système externe par le microcircuit, par exemple aux étapes 24 et 30 de la phase de vérification montrée dans la Fig. 4 ou dans l'étape 46 montrée dans la Fig. 5, peut être effectué automatiquement par le système externe, c'est-à-dire sans qu'une demande soit envoyée par le microcircuit, réduisant ainsi le flux de communications entre le microcircuit et le système externe. On peut encore réduire les calculs à effectuer par le microcircuit en optimisant l'envoi des lignes de données de type T [i] au microcircuit, le système externe se chargeant de trouver l'ordre optimal de traitement des lignes d'instructions B [i]. Il est à noter à cet égard que le changement de l'ordre des lignes à vérifier, c'est-à-dire dans le cas où le flag F [i] a la valeur "changed", ne réduit pas la fiabilité du procédé de vérification, puisque le procédé se termine seulement quand il n'y a plus de flag F [i] avec la valeur"changed" (sauf si le programme à vérifier a été rejeté). En ce qui concerne le calcul des MAC, le temps du calcul peut être fortement réduit si le microcircuit est muni de co-processeurs pour le calcul des clés secrètes. Si plusieurs clés secrètes sont générées, on peut même générer un MAC en quelques cycles, voire seulement un cycle d'horloge, suivant par exemple un MAC dit"DES3" (triple Data Encryption Standard), où on effectue un chiffrement avec une première clé secrète k, suivi par un déchiffrement par une deuxième clé secrète k', suivi par un chiffrement avec la première clé k. Dans une autre variante de la première forme d'exécution, pour réduire le temps de communication, on garde en mémoire à l'intérieur du microcircuit les valeurs successives de tous les MAC r [i] au lieu de les envoyer au système externe pour stockage. Lorsque le système externe renvoie au microcircuit les valeurs de type T [i], le microcircuit recalcule le MAC r [i] associé à ces informations reçues et vérifie qu'il est identique au MAC r [i] stocké à l'intérieur du microcircuit. Pour éviter de générer une clé secrète, il est possible, dans cette variante, que la fonction cryptographique soit une fonction de hachage H. Au lieu de calculer un MAC utilisant une clé secrète, le microcircuit calcule le résultat r [i] de la fonction de hachage H appliquée à la valeur de type T [i], au flag F [i] et au compteur C [i]. Le microcircuit garde le code d'identification r [i] en mémoire. Lorsque le système externe renvoie au microcircuit les valeurs de type T [i], le microcircuit recalcule le code d'authentification r [i] associé à ces informations reçues et vérifie qu'il est identique au code d'authentification r [i] stocké à l'intérieur du microcircuit. Dans la première forme d'exécution décrite cidessus, il est à noter que la phase de vérification ne doit pas nécessairement directement suivre la phase de chargement. En effet, le code intermédiaire d'un programme à vérifier peut être chargé dans le microcircuit, par exemple d'une carte à puce, à partir d'un premier système externe, le procédé de vérification étant exécuté en temps voulu en connectant le microcircuit à un deuxième système de traitement de données externe qui peut être différent du premier système externe utilisé pour le chargement du code intermédiaire. Ceci pourrait être utile par exemple pour le chargement d'un applet Java par un appareil portable sans fil, la vérification et l'exécution du code intermédiaire étant toutefois exécutées plus tard en connectant le microcircuit à un ordinateur ou autre système de traitement de données externe. Les figures 6 à 8 montrent des organigrammes de différentes phases d'un procédé de vérification selon une deuxième forme d'exécution qui diffère de la première forme d'exécution principalement en ce que l'on stocke dans une ou plusieurs mémoires du microcircuit, qui sont accessibles en écriture et en lecture, le tableau T [i] de données de type associé aux instructions B [i] du code intermédiaire, ces dernières étant stockées dans le système externe et rappelées dans le microcircuit au besoin en fonction de la ligne i à vérifier lors de la procédure de vérification. La phase de connexion et de chargement montrée par l'organigramme dans la Fig. 2 est donc essentiellement la même pour cette forme d'exécution, sauf que l'on ne stocke pas les instructions B [i] du code intermédiaire dans la mémoire de la carte, mais un tableau T [i] de données de type associé aux instructions B [i], notamment les types des valeurs dans le registre et des variables dans la pile. Le chargement de ces données dans le microcircuit peut également être effectué lors de la phase d'initialisation montrée dans l'organigramme de la Fig. 6. La première étape 116 de la phase d'initialisation comprend la génération d'une clé secrète k comme pour la première forme d'exécution. Ensuite, dans une prochaine étape 117, le microcircuit génère et initialise une variable u, par exemple à 0, et passe aux étapes d'initialisation 118 dans lesquelles le microcircuit reçoit du système externe une instruction B [i] avec ses arguments (étape 118a) dans une mémoire tampon du microcircuit, ce qui permet de générer une ligne de données de type T [i] (étape 118b) qui est stockée dans une mémoire du microcircuit accessible en lecture et écriture, par exemple dans un EEPROM du microcircuit. Un flag F [i] est également rattaché à cette ligne et peut avoir les valeurs"changed"ou"unchanged" comme décrit auparavant. Le flag F [i] est stocké dans une mémoire de la carte (par exemple RAM ou EEPROM) et initialisé à"unchanged"pour i allant de 2 à S, le premier flag F [l] étant initialisé à la valeur d'état "changed" (étape 118c). Dans la prochaine étape 120, le microcircuit calcule un MAC r [i] qui est une fonction de la position i et de l'instruction B [i] et ses arguments utilisant la clé secrète k. Dans l'étape suivante 117b, on actualise la variable u qui devient le résultat d'une fonction de hachage H appliquée sur les valeurs : de la position i, de l'instruction B [i] et ses arguments et de la valeur précédente de u. La valeur actualisée de u remplace la valeur précédente. Dans l'étape suivante 120, on envoie le MAC r [i] au système externe et on le stocke dans une mémoire de ce système. Les étapes 117a, 118a, 118b, 118c, et 120 et 117b sont effectuées pour i allant de 1 au nombre d'instructions S du code intermédiaire à vérifier. Il est à noter que dans l'étape 118a de réception d'une instruction B [i] du système externe, la nouvelle instruction reçue est placée dans une mémoire tampon du microcircuit en remplaçant l'instruction précédente, de façon à ce que la mémoire tampon ne contient qu'une instruction à la fois. Après traitement de toutes les instructions, le programme de vérification passe à la phase de vérification dont les étapes sont montrées dans l'organigramme de la Fig. 7. Dans la première étape 124 de la phase de vérification, le microcircuit rappelle ou reçoit automatiquement du système externe l'instruction B [i], dont la valeur d'état du flag F [i] ="changed", ainsi que le MAC correspondant r [i]. Dans l'étape suivante 126, le MAC r [i] est vérifié de la même manière que décrite en rapport avec la première forme d'exécution, et s'il est juste, le microcircuit vérifie si les règles de transition de type permettent l'exécution de l'instruction (étape 128). Si la vérification effectuée lors des étapes 126,128 retourne des résultats incorrects, le programme à vérifier est rejeté et le procédé de vérification se termine par un échec. Dans l'étape suivante 129, la ligne de données de type du tableau T [i] est actualisée, tenant compte des opérations que l'instruction B [i] effectue sur ces données, et stockée dans un tableau de travail T'. Dans l'étape suivante 130, le microcircuit rappelle ou reçoit automatiquement du système externe une instruction B [j] successeur potentiel de l'instruction B [i] et vérifie dans l'étape 132 que le MAC r [j] retourné par le système externe est correct. Dans le cas négatif, le programme à vérifier est rejeté, et dans le cas positif, le procédé passe à l'étape 134 d'unification des données de type T [j] associées à l'instruction B [j] successeur potentiel de B [i], avec la ligne T [i] stockée dans le tableau de travail T'. Les données actualisées T [j] sont stockées dans la mémoire du microcircuit. Toutefois, si l'unification des données de type n'est pas possible, le programme à vérifier est rejeté. Si des données de type dans la ligne T [j] ont étés modifiées, la valeur d'état du flag F [j] est mise à"changed"et est stockée dans le microcircuit (étape 140). Après traitement de toutes les instructions successeurs potentiels, le microcircuit actualise le flag F [i] de la ligne i à la valeur"unchanged"et le stocke dans le microcircuit (étape 144). S'il y a encore des instructions dont le flag F [i] a la valeur"changed", on répète la phase de vérification commençant par l'étape 124, sinon le programme de vérification passe à la phase de vérification finale décrite à l'aide de l'organigramme de la Fig. 8. Il est à noter que la mémoire tampon dans laquelle l'instruction B [i] et l'instruction successeur potentiel B [j] sont stockées, est libérée à la fin de chaque boucle pour le stockage de la-prochaine instruction de façon à ce que la capacité de la mémoire de travail nécessaire pour stocker les instructions dans le microcircuit lors de la procédure de vérification, reste très faible. De préférence, les données de type T [i] sont stockées dans une mémoire non volatile accessible en écriture et lecture, par exemple de type EEPROM ou FLASHRAM, ces mémoires ayant une densité de stockage plus élevée que les mémoires volatiles telles que la mémoire RAM. A titre d'exemple, un grain de microcircuit correspond à environ 64 octets de mémoire FLASHRAM, 2 à 64 octets de mémoire EEPROM et 1 octet de mémoire RAM. La mémoire EEPROM a toutefois une durée de vie plus limitée, puisque l'on garantit normalement dix mille à un million écritures seulement. Ceci est toutefois bien suffisant pour la plupart des applications de cartes à puce, par exemple les cartes utilisées pour les opérations bancaires ou les badges électroniques d'identification, puisque leur durée de vie est souvent limitée par d'autres considérations, telles que l'usure mécanique. Certaines données qui sont souvent écrites en mémoire mais n'occupent que peu de la capacité de la mémoire, telles que la valeur d'état du flag F [i], peuvent être stockées dans la mémoire volatile RAM. Dans la phase de vérification finale montrée par l'organigramme dans la Fig. 8, on supprime le tableau des données de type T [i] de la mémoire du microcircuit (étape 149). Dans l'étape suivante 151, le microcircuit initialise une variable u'. Ensuite, le microcircuit rappelle ou reçoit une instruction B [i] et le stocke dans une mémoire du microcircuit (étape 153). Dans l'étape suivante 155, le microcircuit calcule une valeur u' actualisée par une fonction de hachage appliquée à : la valeur précédente de u', l'instruction B [i] et la position i. La valeur u'actualisée est stockée dans une mémoire du microcircuit en remplaçant la valeur initialisée. A la fin (étape 157) le programme vérifie si la variable u'est égale à la valeur de la variable u établie lors de la phase de vérification et stockée dans le microcircuit. S'il y a une différence, le programme à vérifier est rejeté, sinon la vérification se termine avec succès. Afin de réduire les calculs à effectuer par le microprocesseur du microcircuit, on peut avantageusement calculer un seul MAC pour toutes les instructions d'un bloc de séquences d'instructions où il n'y a pas de sauts possibles. On réduit donc le nombre de MAC qui doivent être calculés. On diminue également les communications entre le microcircuit et le système externe en réduisant le nombre de MAC qui doivent être envoyés au système externe et rappelés du système externe. On peut également éviter l'utilisation de la fonction de hachage H sur la variable u, si l'on vérifie le MAC r [i] pour i allant de 1 au nombre d'instructions S avant l'installation du programme pour exécution dans le microcircuit. La Fig. 9 montre un organigramme illustrant la phase de vérification d'une variante de la deuxième forme d'exécution. La phase d'initialisation de la présente variante est essentiellement la même que celle décrite pour la deuxième forme d'exécution par rapport à la Fig. 6. Les mêmes numéros de référence sont donnés aux étapes qui sont essentiellement les mêmes que celles déjà décrites. Dans cette variante, on réduit l'utilisation de la mémoire volatile du microcircuit en évitant la réception et le rappel d'un MAC r [i] et r [j] à la réception de l'instruction B [i] respectivement B [j] dans la phase de vérification. Au lieu de rappeler un MAC r [i] à chaque itération de i, comme décrit auparavant en rapport avec la Fig. 7, on initialise une variable interne Ac = 0 dans le microcircuit et une variable externe At = 0 dans le système externe (étape 223), ces deux variables étant actualisées dans le microcircuit respectivement dans le système externe (étapes 225 et 227) après chaque réception d'une instruction B [i] (étape 124) les variables étant également actualisées (étape 231) après chaque rappel ou réception d'une instruction de j successeur potentiel de B [i] (étape 130). La variable interne Ac stockée dans le microcircuit est actualisée en appliquant une fonction d'actualisation (non constante) à la variable interne Ac précédente et un MAC r [i] fonction de la position i et de l'instruction B [i]. La fonction d'actualisation est avantageusement une fonction booléenne de type'XOR'sur les bits du variable Ac et les bits du MAC r [i], cette fonction n'exigeant que peu de ressources de calcul. D'autres fonctions peuvent toutefois être implémentées pour l'actualisation de la variable interne sans sortir du cadre de l'invention, par exemple la somme de la variable Ac précédente et le MAC r [i]. La variable externe At stockée dans le système externe est actualisée en appliquant une fonction d'actualisation (non constante) à la variable externe At précédente et le MAC r [i] qui à été envoyé au système externe lors de la phase d'initialisation. La fonction d'actualisation peut également être une fonction booléenne de type'XOR'sur les bits du variable externe At et les bits du du MAC r [i], ou une autre fonction non constante. La phase de modification finale de la présente variante comprend les mêmes étapes 149 à 157 que la variante décrite en rapport avec la figure 8, et une étape 259 supplémentaire où le microcircuit reçoit du système externe la valeur de la variable externe At et la compare avec la variable interne Ac stockée dans le microcircuit. En cas d'équivalence, le procédé de vérification se termine avec succès, sinon le programme à vérifier est rejeté. Il est à noter que le microcircuit à ressources limitées peut également être utilisé pour la seule exécution du procédé de vérification du code intermédiaire qui sera par la suite introduit dans un autre système de traitement de données pour exécution. REVENDICATIONS 1. Procédé de vérification d'un code intermédiaire exécutable par un microcircuit à ressources limitées connecté à un système de traitement de données externe, comprenant une phase de chargement d'instructions du code intermédiaire ou d'informations à vérifier associées aux instructions du code intermédiaire dans une mémoire accessible en écriture et en lecture du microcircuit, une phase d'initialisation desdites informations à vérifier et une phase de vérification de l'intégrité du code intermédiaire, caractérisé en ce que, dans la phase d'initialisation, une fonction cryptographique est appliquée dans le microcircuit auxdites informations à vérifier ou auxdites instructions du code intermédiaire pour générer un code d'authentification r [i] et au moins une partie desdites informations à vérifier ou desdites instructions du code intermédiaire sont envoyés et stockés dans le système de traitement de données externe. 2. Procédé de vérification selon la revendication 1, caractérisé en ce que le code intermédiaire est basé sur une plateforme Java ou d'une variante de celle-ci. 3. Procédé de vérification selon la revendication 1 ou 2, caractérisé en ce que les instructions B [i] du code intermédiaire sont stockées dans une mémoire accessible en lecture et en écriture du microcircuit et les informations à vérifier associées aux instructions du code intermédiaire, comprenant un tableau T [i] de données de type, sont stockées dans le système externe. 4. Procédé de vérification selon la revendication 3, caractérisé en ce que la fonction cryptographique est une fonction de chiffrement utilisant au moins une clé secrète k. 5. Procédé de vérification selon la revendication précédente, caractérisé en ce que la clé secrète est éphémère et générée par le microcircuit. 6. Procédé de vérification selon la revendication 4 ou 5, caractérisé en ce que le code d'authentification est envoyé et stocké dans le système externe. 7. Procédé selon la revendication précédente, caractérisé en ce que, dans la phase de vérification, le microcircuit reçoit du système externe lesdites informations à vérifier ainsi que le code d'authentification r [i], et le microcircuit vérifie que le code d'authentification r [i] reçu du système externe correspond au code d'authentification calculé par le microcircuit. 8. Procédé selon l'une des revendications 3 à 7, caractérisé en ce que les informations à vérifier associées aux instructions de code intermédiaire comprennent une valeur d'état F [i] pouvant prendre une première valeur ( changed ) pour indiquer qu'une ligne de données de type du tableau T [i] a été changée, ou une deuxième valeur d'état ( unchanged ) pour indiquer que les données de type du tableau T [i] n'ont pas changé, la valeur d'état F [i] étant incorporée dans le calcul du code d'authentification r [i] et envoyé au système externe pour stockage avec les données de type du tableau T [i]. 9. Procédé de vérification selon la revendication précédente, caractérisé en ce que, dans la phase de vérification finale, le code d'authentification r [i] est reçu du système externe dans le microcircuit, et le microcircuit vérifie que le code d'authentification r [i] reçu du système externe correspond au code d'identification calculé par le microcircuit en prenant la première valeur d'état ( unchanged ) pour la valeur d'état F [i]. 10. Procédé de vérification selon l'une des revendications 4 à 9, caractérisé en ce que les informations à vérifier associées aux instructions du code intermédiaire comprennent un compteur C [i] associé à une desdites instructions B [i] ou à une séquence sans sauts desdites instructions, le compteur C [i] indiquant le nombre de fois que l'instruction B [i] ou la séquence d'instructions est parcourue par le procédé de vérification. 11. Procédé de vérification selon la revendication précédente, caractérisé en ce que le compteur C [i] est incorporé dans le calcul du code d'authentification r [i]. 12. Procédé de vérification selon la revendication 10, caractérisé en ce que le microcircuit génère au moins une deuxième clé secrète k'et calcul au moins une deuxième code d'authentification (MAC) m [i] sur la base de la deuxième clé secrète k'et fonction du compteur C [i], le compteur C [i] étant envoyé avec le deuxième code d'authentification m [i] au système externe pour stockage. 13. Procédé de vérification selon la revendication précédente, caractérisé en ce que le microcircuit stocke un compteur unique t, le compteur unique t étant incorporé dans le calcul du deuxième code d'authentification m [i]. 14. Procédé de vérification selon l'une des revendications 1 à 5, caractérisé en ce que le code d'authentification r [i] est stocké dans le microcircuit. 15. Procédé de vérification selon la revendication précédente, caractérisé en ce que, dans la phase de vérification, le microcircuit reçoit du système externe lesdites informations à vérifier et recalcule le code d'authentification r [i] associé à ces informations reçues, et vérifie qu'il est identique au code d'authentification stocké dans le microcircuit. 16. Procédé de vérification selon la revendication 1 ou 2, caractérisé en ce que lesdites informations à vérifier associées aux instructions du code intermédiaire comprennent un tableau T [i] de données de type qui est chargé dans une mémoire accessible en écriture et en lecture du microcircuit. 17. Procédé de vérification selon la revendication 16, caractérisé en ce que, dans la phase d'initialisation, on génère une variable u, la variable résultant d'une fonction de hachage sur une valeur précédente de cette variable u et une instruction B [i], et on stocke la variable u dans le microcircuit. 18. Procédé de vérification selon la revendication 16, caractérisé en ce que, dans une phase de vérification finale, le microcircuit reçoit du système externe une instruction B [i] du code intermédiaire et calcule une variable u', qui est une fonction de hachage sur l'instruction B [i] et d'une valeur précédente de la variable u', et le microcircuit compare la variable calculée u'avec la variable u stockée dans le microcircuit. 19. Procédé de vérification selon la revendication 16,17 ou 18, caractérisé en ce que, dans la phase de vérification, le microcircuit reçoit du système externe une instruction B [i] ainsi que le code d'authentification r [i], et le microcircuit vérifie que le code d'authentification reçu du système externe correspond au code d'authentification calculé par le microcircuit. 20. Procédé de vérification selon l'une des revendications 16 à 19, caractérisé en ce que, dans la phase de vérification, on génère et stocke une variable interne Ac dans le microcircuit, la variable interne Ac étant actualisée en appliquant une fonction non constante sur une valeur précédente de cette variable interne et le code d'authentification r [i] calculé par le microcircuit, et on génère et stocke dans le système externe une variable externe At, la variable externe étant une fonction non constante sur une valeur précédente de cette variable externe et le code d'authentification r [i], les variables interne et externe étant actualisées chaque fois qu'une instruction ou séquence d'instructions est parcourue. 21. Procédé de vérification selon la revendication précédente, caractérisé en ce que, dans une phase de vérification finale, le microcircuit reçoit du système externe la variable externe At et vérifie la conformité de celle-ci avec la variable interne Ac. 22. Procédé de vérification selon la revendication 20 ou 21, caractérisé en ce que la fonction d'actualisation appliquée aux variables interne, respectivement externe est une fonction booléene de type XOR .