FR 3098319 A1 20210108 FR 1907498 A 20190705 Description Titre de l'invention : PROCÉDÉ D'EXÉCUTION D'UN CODE BINAIRE D'UNE FONCTION SÉCURISÉE PAR UN MICRO- PROCESSEUR [pool j L'invention concerne un procédé d'exécution d'un code binaire d'une fonction sécurisée par un microprocesseur. L'invention concerne également : - un code binaire d'une fonction sécurisée, un support d'enregistrement d'informations et un microprocesseur pour la mise en oeuvre de ce procédé d'exécution, et - un compilateur pour générer ce code binaire. [0002] Pour obtenir des informations sur un code binaire ou provoquer un fonctionnement inattendu du code binaire, de nombreuses attaques sont possibles. [0003] Certaines de ces attaques sont basées sur un usage erroné d'un pointeur de donnée. On rappelle ici qu'un pointeur de donnée est une donnée qui contient l'adresse de la donnée à traiter et non pas directement la valeur de la donnée traitée. [0004] L'usage de tels pointeurs de données est fréquent dans un code exécutable. Par exemple, un tel pointeur est utilisé pour pointer vers la première cellule d'un tableau de plusieurs cellules. Ensuite, pour traiter la cellule suivante de ce tableau, il suffit simplement d'incrémenter l'adresse contenue dans le pointeur d'un pas prédéterminé. [0005] Lors de la conception du code source, le pointeur est prévu pour manipuler et traiter un groupe de données d'une taille prédéterminée. Toutefois, lors de l'exécution du code binaire correspondant, il est parfois possible de s'arranger pour que ce pointeur pointe sur une donnée située en dehors de ce groupe de données. Par exemple, un tel usage erroné de ce pointeur est provoqué en saisissant, dans un champ de saisie, une donnée dont la taille est bien plus grande que celle prévue initialement par les développeurs de la fonction sécurisée. Grâce à cela, il est possible d'écrire des données dans des plages d'adresses où cela ne devrait pas être fait. Autrement dit, le pointeur est utilisé pour pointer vers des adresses invalides. Un exemple de ce premier type d'attaque est connu sous le terme de « attaque par dépassement de tampon» ou « stack overflow attack », lorsque cette attaque vise la pile utilisée par la fonction sécurisée. Lorsque le pointeur est utilisé pour écrire des données avant la plage d'adresses prévue à cet effet dans la pile, l'attaque est également connue sous le ternie de « stack undefflow attack ». [0006] Ce premier type d'attaque peut être mis en oeuvre de façon assez similaire pour écrire des données à des adresses invalides dans d'autres parties de la mémoire que la pile, comme par exemple, dans une partie connue sous le terme de « tas » (« heap » en anglais). 2 [0007] Ces premiers types d'attaques ont en commun d'utiliser un pointeur valide pour pointer sur des adresses invalides. On dit alors qu'elles concernent ce qui touche au domaine de la « sécurité spatiale » (« spatial safcty » en anglais). [0008] Il existe aussi des usages erronés des pointeurs qui touchent au domaine de la sécurité temporelle (« temporal safcty » en anglais). Dans cocas, un pointeur invalide est utilisé pour pointer sur une adresse valide. Un pointeur invalide est un pointeur qui a été utilisé de façon valide pour traiter des données dans un contexte limité, et qui est ensuite utilisé à nouveau en dehors dc cc contexte limité. Cela peut se produire si, par exemple, ce pointeur n'a pas correctement été réinitialisé ou initialisé. Cc type de pointeur invalide est connu sous le terme anglais de « dangling pointer ». [0009] Certaines attaques repèrent donc ces pointeurs invalides, puis les utilisent pour lire ou écrire des données à des instants où ils ne devraient pas être utilisés pour cela. À titre d'illustration de cc second type d'attaque, on peut citer l'attaque connue sous l'expression anglaise de « use-a-Ber-free ». [0010] On notera aussi que les attaques basées sur des usages erronés de pointeurs ne concernent pas que les pointeurs de données, c'est-à-dire, les pointeurs qui pointent vers une donnée à traiter par le microprocesseur. Ce type d'attaque concerne également les pointeurs appelés ici « pointeurs de fonctions », c'est-à-dire, un pointeur qui contient l'adresse non pas d'une donnée, niais d'une instruction à exécuter par le microprocesseur. [0011] Plusieurs solutions ont déjà été proposées pour rendre plus difficile un usage erroné d'un pointeur. [0012] Par exemple, une solution consiste à utiliser des pointeurs enrichis comme par exemple, les pointeurs connus sous l'expression anglaise de « low-fat pointer ». Dans ce cas, chaque pointeur comporte en plus de l'adresse de la donnée vers laquelle il pointe, une plage de bits contenant au moins une limite supérieure ou inférieure. Ensuite, à chaque fois que ce pointeur est utilisé, un mécanisme de détection est mis en oeuvre pour détecter si l'adresse actuelle vers laquelle pointe ce pointeur dépasse, par exemple, la limite supérieure. En réponse à un tel dépassement, une erreur est signalée. Ainsi, un usage erroné de ce pointeur est détecté. Un exemple d'implémentation d'un tel pointeur enrichi est décrit dans l'article suivant : T. Kroes et AL :« Delta Pointers: Buffer Overtlow Checks Without the Checks », in Proceedings of the Thirteenth EuroSys Conference, New York, NY, USA, 2018, p. 22:1-22:14. [0013] Ces solutions fonctionnent correctement pour un type d'attaque bien précis ou pour un nombre limité d'attaques. Par exemple, la solution décrite dans l'article de T. Kroes et AL fonctionne uniquement pour contrer les attaques du type « stack overtlow attack », mais ne fonctionne pas contre les attaques du type « stack undefflow attack ». Elle ne fonctionne pas non plus contre les attaques qui concernent le domaine de la 3 sécurité temporelle, comme l'attaque « use-after-free ». [0014] L'invention vise à proposer un procédé d'exécution d'une fonction sécurisée par un microprocesseur, robuste vis-à-vis d'un spectre plus large d'attaques basées sur un usage erroné d'un pointeur. [0015] L'invention a donc pour objet un tel procédé d'exécution d'un code binaire d'une fonction sécurisée par un microprocesseur, ce procédé comportant les étapes suivantes : a) l'enregistrement dans une mémoire d'une ligne de code, cette ligne de code comportant un cryptogramme du code et une première étiquette d'intégrité permettant de vérifier l'intégrité de la ligne de code, b) l'obtention, par le microprocesseur, d'un premier pointeur contenant l'adresse à laquelle est enregistrée cette ligne de code, puis c) l'exécution, par le microprocesseur, d'une instruction de lecture de cette ligne de code à l'aide du premier pointeur et, pour cela, l'exécution des opérations suivantes par le microprocesseur : cl) le chargement du premier pointeur dans un registre du microprocesseur, c2) le chargement de la ligne de code enregistrée à l'adresse contenue dans le premier pointeur, puis c3) la vérification de l'intégrité de la ligne de code chargée, cette vérification comportant la construction d'une seconde étiquette d'intégrité à partir du cryptogramme contenu dans la ligne de code chargée, puis la comparaison de cette seconde étiquette d'intégrité à la première étiquette d'intégrité contenue dans la ligne de code chargée, puis c4) lorsque la seconde étiquette d'intégrité ne correspond pas à la première étiquette d'intégrité, c'est-à-dire que la vérification de l'intégrité de la ligne de code chargée échoue, le microprocesseur déclenche systématiquement le signalement d'une faute d'exécution, et c5) lorsque la seconde étiquette d'intégrité correspond à la première étiquette d'intégrité, c'est-à-dire que la ligne de code chargée est intègre, le cryptogramme du code est déchiffré pour obtenir un code en clair et le déclenchement d'une faute d'exécution est inhibé ; dans lequel : - l'obtention du premier pointeur comporte l'obtention d'un premier pointeur comprenant : - une première plage de bits contenant l'adresse de la ligne de code, et - une seconde plage différente de bits contenant un identifiant du premier pointeur, l'identifiant de ce premier pointeur permettant d'identifier de façon unique ce premier pointeur parmi un ensemble contenant plusieurs pointeurs différents mis en oeuvre lors de la même exécution du code binaire parce microprocesseur, - l'enregistrement de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle la première étiquette d'intégrité est construite ou chiffrée à l'aide de l'identifiant du premier pointeur, - lors du chargement de la ligne de code, c'est l'adresse contenue dans la première plage de bits du premier pointeur chargé qui est utilisée et l'identifiant du premier pointeur contenu dans la seconde plage de bits n'est pas utilisé, - lors de la vérification de l'intégrité de la ligne de code chargée, la seconde étiquette d'intégrité est construite, en plus, en utilisant l'identifiant du premier pointeur contenu dans la seconde plage de bits du premier pointeur chargé, de sorte que si un second pointeur, différent du premier pointeur, est utilisé à la place du premier pointeur pour lire ou écrire cette ligne de code, la vérification de l'intégrité de la ligne de code échoue. [0016] Les modes de réalisation de cc procédé d'exécution peuvent comporter une ou plusieurs des caractéristiques suivantes : 1) L'enregistrement de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle le cryptogramme est construit à l'aide de l'identifiant du premier pointeur contenu dans la seconde plage de bits, et lors du déchiffrement du cryptogramme du code, le cryptogramme est déchiffré en utilisant l'identifiant de pointeur contenu dans la seconde plage de bits du premier pointeur chargé. 2) L'enregistrement de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle la première étiquette d'intégrité est aussi construite ou chiffrée à l'aide de l'adresse contenue dans la première plage de bits du premier pointeur, et lors de la vérification de l'intégrité de la ligne de code chargée, la seconde étiquette d'intégrité est construite, en plus, en utilisant l'adresse contenue dans la première plage de bits du premier pointeur chargé. 3) L'enregistrement de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle le cryptogramme est aussi construit à l'aide d'une clé secrète indépendante de l'identifiant du premier pointeur et de l'adresse contenue dans ce premier pointeur, et lors du déchiffrement du cryptogramme, le cryptogramme est aussi déchiffré en utilisant cette clé secrète stockée dans une mémoire sécurisée du microprocesseur avant le début de l'exécution du code binaire par ce microprocesseur. 4) L'obtention du premier pointeur comporte l'obtention d'un premier pointeur dont la taille, en nombre de bits, est égale à la taille d'une adresse, c'est-à-dire au nombre de bits maximal que peut contenir une adresse transférée du microprocesseur jusqu'à la mémoire par l'intermédiaire d'un bus d'adresse. 5) L'enregistrement de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle le code est une donnée et l'étape a) comporte, en réponse à l'exécution, par le microprocesseur, d'une instruction d'écriture de cette donnée dans la mémoire à l'adresse contenue dans le premier pointeur : - la construction de la ligne de code comportant le cryptogramme de la donnée et la première étiquette d'intégrité construite ou chiffrée à l'aide de l'identifiant du premier pointeur contenu dans sa seconde plage de bits, puis - l'enregistrement de la ligne de code ainsi construite à l'adresse contenue dans la première plage de bits du premier pointeur. 6) L'étape h) précède l'étape a) et l'étape b) comporte : hl ) l'exécution par le microprocesseur d'une instruction d'allocation dynamique d'une zone mémoire dans la mémoire, cette instruction d'allocation étant contenue dans le code binaire de la fonction sécurisée, puis b2) en réponse : - la réservation dans la mémoire, d'une zone libre d'une taille prédéterminée, dans laquelle le microprocesseur peut écrire et lire des lignes de codes, et - la génération du premier pointeur qui contient, dans sa première plage de bits, une adresse de la zone mémoire réservée et dans sa seconde plage de bits l'identifiant du premier pointeur. 7) En réponse à l'exécution, par le microprocesseur, d'une instruction de libération de la zone de mémoire allouée vers laquelle le premier pointeur pointe, l'identifiant du premier pointeur est modifié et/ou le contenu de cette zone de mémoire est réécrit avec des valeurs différentes. 8) L'opération cl) comporte : - l'exécution, par le microprocesseur, d'une instruction de chargement, à partir de la mémoire, d'une ligne de donnée contenant un cryptogramme du premier pointeur, puis - le déchiffrement du cryptogramme du premier pointeur pour obtenir le premier pointeur en clair. 9) La ligne de donnée contenant le cryptogramme du premier pointeur est construite de la même manière que la ligne de code enregistrée à l'adresse contenue dans ce premier pointeur mais en remplaçant l'identifiant du premier pointeur par une valeur nulle. 10) L'enregistrement de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle le code est la première instruction exécutable (l'une routine appelée par le microprocesseur et le procédé comporte : - l'exécution, par le microprocesseur, d'une instruction d'appel de cette routine, puis - en réponse, l'étape b) comporte le chargement du premier pointeur à partir d'une table pré-enregistrée associant un identifiant de cette routine au premier pointeur, puis - pour chaque ligne d'instruction de la routine, l'exécution de l'opération c3) en utilisant à chaque fois l'identifiant du premier pointeur chargé pour construire la seconde étiquette d'intégrité. 6 [0017] L'invention a également pour objet un code binaire d'une fonction sécurisée apte à être exécuté par un microprocesseur, en mettant en oeuvre le procédé d'exécution ci-dessus, dans lequel le code binaire comporte : - une ligne de code comportant le cryptogramme du code et une première étiquette d'intégrité permettant de vérifier l'intégrité de la ligne de code ; - un premier pointeur contenant l'adresse à laquelle est enregistrée la ligne de code, - une instruction de lecture de la ligne de code à l'aide du premier pointeur qui, lorsqu'elle est exécutée par le microprocesseur, déclenche l'exécution des opérations suivantes par le microprocesseur : cl) le chargement du premier pointeur dans un registre du microprocesseur, c2) le chargement de la ligne de code enregistrée à l'adresse contenue dans le premier pointeur, puis c3) la vérification de l'intégrité de la ligne de code chargée, cette vérification comportant la construction d'une seconde étiquette d'intégrité à partir du cryptogramme contenu dans la ligne de code chargée, puis la comparaison de cette seconde étiquette d'intégrité à la première étiquette d'intégrité contenue dans la ligne de code chargée, puis c4) lorsque la seconde étiquette d'intégrité ne correspond pas à la première étiquette d'intégrité, c'est-à-dire que la vérification de r intégrité de la ligne de code chargée échoue, le microprocesseur déclenche systématiquement le signalement d'une faute d'exécution, et c5) lorsque la seconde étiquette d'intégrité correspond à la première étiquette d'intégrité, c'est-à-dire que la ligne de code chargée est intègre, le cryptogramme du code est déchiffré pour obtenir un code en clair et le déclenchement d'une faute d'exécution est inhibé; dans lequel : - le premier pointeur comprend : - une première plage de bits contenant l'adresse de la ligne de code, et - une seconde plage différente de bits contenant un identifiant du premier pointeur, l'identifiant de ce premier pointeur permettant d'identifier de façon unique ce premier pointeur parmi un ensemble contenant plusieurs pointeurs différents mis en oeuvre lors de la même exécution du code binaire par ce microprocesseur, et - la première étiquette d'intégrité est construite ou chiffrée à l'aide de l'identifiant du premier pointeur.. [0018] L'invention a également pour objet un support d'enregistrement d'informations, lisible par un microprocesseur, ce support d'enregistrement d'informations comportant le code binaire ci-dessus. [0019] L'invention a également pour objet un microprocesseur pour la mise en oeuvre du 7 procédé revendiqué, ce microprocesseur étant configure pour exécuter les étapes suivantes : a) l'enregistrement dans une mémoire d'une ligne de code, cette ligne de code comportant un cryptogramme du code et une première étiquette d'intégrité permettant de vérifier l'intégrité de la ligne de code, b) l'obtention, par le microprocesseur, d'un premier pointeur contenant l'adresse à laquelle est enregistrée cette ligne de code, puis c) l'exécution, par le microprocesseur, d'une instruction de lecture de cette ligne de code à l'aide du premier pointeur et, pour cela, l'exécution des opérations suivantes par le microprocesseur : cl) le chargement du premier pointeur dans un registre du microprocesseur, c2) le chargement de la ligne de code enregistrée à l'adresse contenue dans le premier pointeur, puis c3) la vérification de l'intégrité de la ligne de code chargée, cette vérification comportant la construction d'une seconde étiquette d'intégrité à partir du cryptogramme contenu dans la ligne de code chargée, puis la comparaison de cette seconde étiquette d'intégrité à la première étiquette d'intégrité contenue dans la ligne de code chargée, puis c4) lorsque la seconde étiquette d'intégrité ne correspond pas à la première étiquette d'intégrité, c'est-à-dire que la vérification de l'intégrité de la ligne de code chargée échoue, le microprocesseur déclenche systématiquement le signalement (l'une faute d'exécution, et c5) lorsque la seconde étiquette d'intégrité correspond à la première étiquette d'intégrité, c'est-à-dire que la ligne de code chargée est intègre, le cryptogramme du code est déchiffré pour obtenir un code en clair et le déclenchement d'une faute d'exécution est inhibé ; dans lequel le microprocesseur est également configuré pour : - lors de l'obtention du premier pointeur, obtenir un premier pointeur comprenant : - une première plage de bits contenant l'adresse de la ligne de code, et - une seconde plage différente de bits contenant un identifiant du premier pointeur, l'identifiant de ce premier pointeur permettant d'identifier de façon unique ce premier pointeur parmi un ensemble contenant plusieurs pointeurs différents mis en oeuvre lors de la même exécution du code binaire par ce microprocesseur, - lors de l'enregistrement de la ligne de code, l'enregistrement d'une ligne de code dans laquelle la première étiquette d'intégrité est construite ou chiffrée à l'aide de l'identifiant du premier pointeur, - lors du chargement de la ligne de code, c'est l'adresse contenue dans la première plage de bits du premier pointeur chargé qui est utilisée et l'identifiant du premier 8 pointeur contenu dans la seconde plage de bits n'est pas utilisé, - lors de la vérification de l'intégrité de la ligne de code chargée, la seconde étiquette d'intégrité est construite, en plus, en utilisant l'identifiant du premier pointeur contenu dans la seconde plage de bits du premier pointeur chargé, de sorte que si un second pointeur, différent du premier pointeur, est utilisé à la place du premier pointeur pour lire ou écrire cette ligne de code, la vérification de l'intégrité de la ligne de code échoue. [0020] Enfin, l'invention a également pour objet un compilateur apte à transformer automa- tiquement un code source d'une fonction sécurisée en un code binaire tel que revendiqué, cc compilateur étant configure à cet effet pour générer pour au moins un code contenu dans le code source : - une ligne de code comportant le cryptogramme de cc code et une première étiquette d'intégrité permettant de vérifier l'intégrité de la ligne de code ; - un premier pointeur contenant l'adresse à laquelle est enregistrée la ligne de code, - une instruction de lecture de la ligne de code à l'aide du premier pointeur qui, lorsqu'elle est exécutée par le microprocesseur, déclenche l'exécution des opérations suivantes par le microprocesseur : cl) le chargement du premier pointeur dans un registre du microprocesseur, c2) le chargement de la ligne de code enregistrée à l'adresse contenue dans le premier pointeur, puis c3) la vérification de l'intégrité de la ligne de code chargée, cette vérification comportant la construction d'une seconde étiquette d'intégrité à partir du cryptogramme contenu dans la ligne de code chargée, puis la comparaison de cette seconde étiquette d'intégrité à la première étiquette d'intégrité contenue dans la ligne de code chargée, puis c4) lorsque la seconde étiquette d'intégrité ne correspond pas à la première étiquette d'intégrité, c'est-à-dire que la vérification de l'intégrité de la ligne de code chargée échoue, le microprocesseur déclenche systématiquement le signalement d'une faute d'exécution, et c5) lorsque la seconde étiquette d'intégrité correspond à la première étiquette d'intégrité, c'est-à-dire que la ligne de code chargée est intègre, le cryptogramme du code est déchiffré pour obtenir un code en clair et le déclenchement d'une faute d'exécution est inhibé ; dans lequel : - le premier pointeur comprend : - une première plage de bits contenant l'adresse de la ligne de code, et - une seconde plage différente de bits contenant un identifiant du premier pointeur, l'identifiant de ce premier pointeur permettant d'identifier de façon unique ce premier 9 pointeur parmi un ensemble contenant plusieurs pointeurs différents mis en oeuvre lors de la même exécution du code binaire par ce microprocesseur, et - la première étiquette d'intégrité est construite ou chiffrée à l'aide de l'identifiant du premier pointeur. [0021] L'invention sera mieux comprise à la lecture de la description qui va suivre, donnée uniquement à titre d'exemple non limitatif et faite en se référant aux dessins sur lesquels : - la figure 1 est une illustration schématique de l'architecture d'un appareil électronique apte à exécuter un code binaire d'une fonction sécurisée, - la figure 2 est une illustration schématique de la structure d'un pointeur enrichi utilisé lors de l'exécution du code binaire par l'appareil de la figure 1, - la figure 3 est une illustration schématique de la structure d'une ligne de donnée utilisée lors de l'exécution du code binaire par l'appareil de la figure 1, - la figure 4 est un organigramme d'un procédé d'exécution du code binaire par l'appareil de la figure 1 dans lequel l'utilisation des pointeurs de données est sécurisée, - la figure 5 est une illustration schématique de la structure d'une ligne d'instruction du code binaire exécuté par l'appareil de la figure 1, - la figure 6 est un organigramme d'un procédé d'exécution du code binaire par l'appareil de la figure 1 dans lequel l'utilisation des pointeurs d'instructions est sécurisée, - la figure 7 est une illustration schématique d'un compilateur apte à générer le code binaire exécuté par l'appareil de la figure 1. [0022] Chapitre I: Conventions, notations et définitions : [0023] Dans les figures, les mêmes références sont utilisées pour désigner les mêmes éléments. Dans la suite de cette description, les caractéristiques et fonctions bien connues de l'homme du métier ne sont pas décrites en détails. [0024] Dans cette description, les définitions suivantes sont adoptées. [0025] Un « programme » désigne un ensemble d'une ou de plusieurs fonctions prédé- terminées que l'on souhaite faire exécuter par un microprocesseur. [0026] Un « code source » est une représentation du programme dans un langage in- formatique, n'étant pas directement exécutable par un microprocesseur et étant destiné à être transformé par un compilateur en un code machine directement exécutable par le microprocesseur. [0027] Un programme ou un code est dit être « directement exécutable » lorsqu'il est apte à être exécuté par un microprocesseur sans que ce microprocesseur n'ait besoin au préalable de le compiler au moyen d'un compilateur ou de l'interpréter au moyen d'un interpréteur. [0028] Une « instruction » désigne une instruction machine exécutable par un micro- processeur. Une telle instruction est constituée : - d'un opcodc, ou code d'opération, codant la nature de l'opération à exécuter, et -d'un ou plusieurs opérandes définissant la ou les valeurs des paramètres de cette opération. [0029] Un « code machine » est un ensemble d'instructions machines. Il s'agit typiquement d'un fichier contenant une succession de bits portant la valeur «0 » ou « 1 », ces bits codant les instructions à exécuter par le microprocesseur. Le code machine est directement exécutable par le microprocesseur, c'est-à-dire sans nécessiter une compilation ou une interprétation préalable. [0030] Un « code binaire » est un fichier contenant une succession de bits portant la valeur « 0 » ou « 1 ». Ces bits codent des données et des instructions à exécuter par le microprocesseur. Ainsi, le code binaire comprend au moins un code machine et en plus, généralement, des données numériques traitées parce code machine. [0031] Pour être exécuté par un microprocesseur, le code binaire est enregistré dans des lignes d'une mémoire principale. Typiquement, le code binaire comporte plusieurs centaines ou milliers de lignes. Chacune de ces lignes est appelée "ligne de code". Chaque ligne dc code est enregistrées à une adresse qui lui est propre dans la mémoire principale. Chaque ligne de code contient une seule instruction ou à une seule donnée. Par la suite, lorsque le code contenu dans la ligne de code correspond à une instruction, la ligne de code est appelée "ligne d'instruction". Lorsque le code contenu dans la ligne de code correspond une donnée, la ligne de code est appelée "ligne de donnée". Le terme "code" est quant à lui utilisé pour désigner aussi bien une instruction qu'une donnée et le terme "ligne de code" est utilisé pour désigner aussi bien une ligne de donnée qu'une ligne d'instruction. [0032] Au niveau du code binaire, une instruction et une donnée correspondent tous les deux à des bits. Toutefois, les instructions et les données ne sont pas traitées de la même façon par un microprocesseur. Par exemple, une instruction est seulement chargée puis exécutée par le microprocesseur lorsque le compteur ordinal pointe sur cette instruction. Une donnée est chargée par le microprocesseur seulement en réponse à l'exécution par ce microprocesseur d'une instruction de chargement de cette donnée. [0033] On parle d'exécution d'une fonction pour désigner l'exécution des instructions réalisant cette fonction. [0034] Dans un souci de simplification, dans cette description et dans les figures, les ins- tructions ne sont pas représentées sous forme binaire, mais plutôt sous une forme symbolique exprimée dans un langage évolué de plus haut niveau. [0035] Chapitre II: Architecture de l'appareil : [0036] La figure 1 représente un appareil électronique 1 comportant un microprocesseur 2, une mémoire principale 4 et un support 6 de stockage de masse. Par exemple, l'appareil 11 1 est un ordinateur, un smartphonc, une tablette électronique ou similaire. [0037] Le microprocesseur 2 comporte ici : - une unité arithmétique et logique 10; - un ensemble 12 de registres ; - un module de commande 14; - une interface 16 d'entrée/sortie de données, - un chargeur 18 d'instructions comportant un compteur ordinal 26, - une file 22 d'instructions à exécuter, et - un module matériel 28 de sécurisation. [0038] La mémoire 4 est configure° pour stocker des instructions et des données d'un code binaire 30 d'un programme devant être exécuté par le microprocesseur 2. La mémoire 4 est une mémoire à accès aléatoire. Typiquement, la mémoire 4 est une mémoire volatile. La mémoire 4 peut être une mémoire externe au microprocesseur 2 comme représenté sur la figure 1. Dans ce cas, la mémoire 4 est réalisée sur un substrat mécaniquement séparé du substrat sur lequel sont réalisés les différents éléments du microprocesseur 2 comme l'unité 10. [0039] Ici, la mémoire 4 est divisée en mots-machines successifs de longueur fixe. Chaque mot-machine est adressable individuellement et peut être transféré en un seul cycle d'horloge depuis la mémoire 4 jusque dans un registre du microprocesseur par l'intermédiaire d'un bus de données. A cet effet, la taille NMM d'un mot-machine est égale au nombre maximum de bits qui peuvent être transférés simultanément sur ce bus de données. Ici, la taille NMM est strictement supérieure Nin' bits, où brins, bits est le nombre de bits des instructions du jeu d'instructions du microprocesseur 2. Typiquement, Nin' est un entier supérieure ou égale à 8, 16, 32 ou 64. Dans cet exemple, Nins, est égal à 32 et la taille N. est égale à 128 bits. [0040] La position de chaque mot machine dans la mémoire 4 est repéré par une adresse. Pour recevoir cette adresse, la mémoire 4 est reliée au microprocesseur 2 par un bus d'adresses. La taille Ne de l'adresse, en nombre de bits, détermine le nombre maximum de mot-machines qui peuvent être adressés individuellement dans la mémoire 4. Typiquement, la taille Ne est supérieure ou égale à 8, 16, 32 ou 64 bits. Par exemple, dans ce mode de réalisation, la taille Ne est égale à 64 bits. [0041] Classiquement, la mémoire 4 est divisée en plusieurs parties. Par exemple, ici, la mémoire 4 comporte notamment les parties suivantes : - une première partie 42 contenant les instructions à exécuter, - une deuxième partie 44 contenant des données à traiter, - une troisième partie 46 utilisée pour sauvegarder le contexte d'exécution d'une fonction lorsqu'elle appelle une autre fonction appelée "routine", et - une quatrième partie 48 utilisée pour allouer dynamiquement de la mémoire au 12 programme en cours d'exécution afin d'y enregistrer des données. La partie 42 est connue sous le terme de "segment de code" ("code segment" en anglais). La partie 44 contient typiquement les variables statiques et globales du programme exécuté. La partie 46 est connue sous le terme de "pile d'exécution" ("can stack" en anglais). Par conséquent, par la suite, la partie 46 est également appelée "pile 46". Enfin la partie 48 est connue sous le terme de "tas" ("heap" en anglais). Ainsi, par la suite, la partie 48 est également appelée "tas 48". [0042] Le code binaire 30 comporte notamment un code machine 32 d'une fonction sécurisée et un bloc 34 de données nécessaires à l'exécution du code binaire 30. Le code machine 32 et le bloc 34 sont enregistrés dans, respectivement, les parties 42 et 44. [0043] Ici, chaque ligne de code du code binaire correspond à un mot-machine. Ainsi, une ligne de code est chargée dans un registre du microprocesseur 2 en une seule opération de lecture. De même, une ligne de code est écrite dans la mémoire 4 par le microprocesseur 2 en une seule opération d'écriture. Les structures d'une ligne d'instruction et d'une ligne de donnée sont décrites en détail en référence aux figures 3 et 5. [0044] L'exécution du code binaire 30 débute par le chargement et le traitement de données du bloc 34. Ici, en particulier, le bloc 34 comporte notamment un cryptogramme ka* obtenu en chiffrant une clé secrète ka à l'aide d'une clé publique plcc,,, du microprocesseur 2. [0045] A titre d'illustration, le microprocesseur 2 est conforme à l'architecture RISC (« Reduced Instructions Set Computer ») et il met en oeuvre le jeu d'instructions "RISCV". [0046] Ici, l'unité 10 est une unité arithmétique et logique de N1,1, bits. [0047] Le chargeur 18 charge dans la file 22 la prochaine instruction à exécuter par l'unité 10 à partir de la partie 42 de la mémoire 4. Plus précisément, le chargeur 18 charge l'instruction sur laquelle pointe le compteur ordinal 26. [0048] L'unité 10 est notamment configurée pour exécuter les unes après les autres les ins- tructions chargées dans la file 22. Les instructions chargées dans la file 22 sont généralement systématiquement exécutées dans l'ordre où ces instructions ont été enregistrées dans cette file 22. L'unité 10 est aussi capable d'enregistrer le résultat de ces instructions exécutées dans un ou plusieurs des registres de l'ensemble 12. [0049] Dans cette description, on utilisera comme synonymes « exécution par le micro- processeur 2 » et « exécution par l'unité 10 ». [0050] Le module 14 est configuré pour déplacer des données entre l'ensemble 12 de registres et l'interface 16. L'interface 16 est notamment apte à acquérir des données et des instructions, par exemple, depuis la mémoire 4 et/ou le support 6 extérieurs au microprocesseur 2. 13 [0051] Le module 28 est capable d'exécuter automatiquement les différentes opérations décrites en détails dans les chapitres suivants pour sécuriser l'exécution des fonctions sécurisées. Le module 28 fonctionne indépendamment et sans utiliser l'unité 10. Ainsi, il est capable de traiter les lignes de code avant et/ou après que celles-ci soient traitées par l'unité 10. A cet effet, il comporte notamment une mémoire non-volatile sécurisée 29. Aucun accès à cette mémoire 29 sans passer par l'intermédiaire du module 28 n'est prévu. Dans cc mode de réalisation, le module 28 est pré-programmé, par exemple lors de sa conception, pour exécuter des opérations telles que les opérations suivantes : - vérifier l'intégrité et l'authenticité d'une ligne de code à partir d'un code d'authentification de message plus connu sous l'acronyme MAC (« Message Authentification Code »), - construire un code d'authentification de message, - chiffrer un code pour obtenir un cryptogramme de cc code, - déchiffrer un cryptogramme d'un code pour obtenir le code en clair, et - exécuter une fonction préprogrammée [0052] La mémoire 29 est utilisée pour stocker les informations secrètes nécessaires à la mise en oeuvre du procédé des figures 4 et 6. Ici, elle comporte donc notamment des informations secrètes pré-enregistrées avant le début de l'exécution du code binaire 30. En particulier, elle comporte les informations pré-enregistrées suivantes : - une clé secrète k' utilisée pour la vérification des codes d'authentification de message, - un clé privée secrète skr,,, qui permet de déchiffrer les données qui ont été chiffrées à l'aide de la clé publique pkcpu. [0053] Dans cet exemple de réalisation, l'ensemble 12 comporte des registres généraux uti- lisables pour stocker tout type de données. La taille de chacun de ces registres est, par exemple, égale à [0054] Un bus d'échange de données 24 qui relie les différents composants du micro- processeur 2 entre eux est représenté sur la figure 1 pour indiquer que les différents composants du microprocesseur peuvent échanger des données entre eux. Le bus de données et le bus d'adresses qui relient le microprocesseur 2 à la mémoire 4 ont été représentés par une double flèche 50 pour simplifier la figure I. [0055] Le support 6 est typiquement une mémoire non volatile. Par exemple, il s'agit d'une mémoire du type EEPROM ou Flash. Il contient ici une copie 40 de sauvegarde du code binaire 30. Typiquement, c'est cette copie 40 qui est automatiquement recopiée dans la mémoire 4 pour restaurer le code 30, par exemple, après une coupure de courant ou similaire ou juste avant que débute l'exécution du code 30. [0056] CHAPITRE III: SÉCURISATION DES POINTEURS DE DONNEES [0057] Des données D; traitées lors de l'exécution du code machine 32 sont enregistrées dans 14 la mémoire 4. Par exemple, le code binaire 30, en plus du code machine 32, comporte des données à traiter lors de l'exécution du code machine 32. De plus, lors de l'exécution du code machine 32, celui-ci génère des données à enregistrer dans une variable globale ou statique. Ces données sont typiquement contenues dans la partie 44 de la mémoire 4. [0058] De même, à chaque fois qu'une fonction appelante déclenche l'exécution d'une fonction appelée, le contexte d'exécution de la fonction appelante est sauvegardé dans la pile 46. La fonction appelée sauvegarde également dans la pile 46 des données telles que des variables locales. [0059] Lors de l'exécution du code machine 32, des données peuvent aussi être enregistrées dans le tas 48. [0060] Pour traiter et manipuler certaines de ces données, le code machine 32 utilise des pointeurs de données. Un pointeur de donnée est une variable qui contient l'adresse de la ligne de donnée à traiter. L'usage d'un pointeur de donnée est, par exemple, systématique lors que la donnée est enregistrée dans la pile 46 ou le tas 48. Comme décrit dans l'introduction de cette demande, un usage erroné d'un pointeur de donnée peut être exploité pour mener à bien un attaque contre la fonction sécurisée. Pour détecter et mettre en échec de telles attaques, ici, chaque donnée D; enregistrée dans la mémoire 4 et qui est traitée à l'aide d'un pointeur de donnée, est codée dans une ligne respective LD;. La ligne LD; est une ligne de donnée. Par la suite, dans ce chapitre, l'indice j est utilisé pour identifier la ligne de données LD; parmi les autres lignes de données enregistrées dans la mémoire 4. Ici, la taille de la ligne LD; est égale à la taille d'un mot-machine et donc égale à la taille [0061] Par la suite, on note également PD; le pointeur de donnée qui contient l'adresse de la ligne LD; et qui permet de traiter et de manipuler cette ligne de donnée. La structure du pointeur PD; est représentée sur la figure 2. Ici, la taille du pointeur PD; est égale à la taille Ne des athesses mémoires. Le pointeur PD; comporte : - une première plage de bits contenant l'adresse @; poi,'' et - une seconde plage distincte de bits contenant un identifiant IP; du pointeur PD;. Sur la figure 2, les première et seconde plages de bits sont désignées par les symboles, respectivement, @;. et IP;. Par la suite, on note e- l'adresse dans la mémoire 4 à laquelle est enregistrée une ligne LD;. Les lignes LD; sont enregistrées dans une plage d'adresses de la mémoire 4 dont la taille est strictement inférieure à 2Ne afin de laisser suffisamment de place pour coder l'identifiant IP; à l'intérieur du pointeur PDJ. Pour cela, la taille de la première plage de bits est inférieure à Ne-Np bits, où Np est la taille, en nombre de bits, de la seconde plage. De préférence, la taille Np est supérieure à 8 bits ou 16 bits et, généralement, inférieure à 32 bits ou 54 bits. Ici, la taille Np est égale à 16 bits et les adresses @; sont donc codées sur moins de 48 bits. Dans ce mode de réalisation, la première plage correspond aux P^IrNi, bits de poids faibles du pointeur PD; etlaeeo,acIeplanepund du NP bau de poids d u poi', Hm. Pour obtenir l'adresse @; de la ligne LD; à partir du pointeur PDJ, il suffit donc de masquer les bits de poids forts du pointeur PD; utilisés pour enregistrer l'identifiant IPJ. [0062] L'adresse @; est par exemple une adresse virtuelle dans l'espace mémoire du programme. Une telle adresse virtuelle est ensuite convertie automatiquement en une adresse physique par une unité connue sous l'abréviation MMU ("Management Memory Unit"). [0063] L'identifiant IP; est un identifiant qui permet d'identifier de façon unique le pointeur PD, parmi un ensemble d'autres pointeurs utilisés lors de la même exécution du code binaire 30. Ici, il est construit de manière à limiter la probabilité que deux pointeurs de données différents aient le même identifiant de pointeur. Par exemple, les identifiants de pointeurs sont construits pour que cette probabilité soit inférieure à une chance sur dix et, de préférence, une chance sur cinquante ou une chance sur cent ou une chance sur mille. [0064] L'identifiant IP; peut être généré lors de la compilation du code source pour obtenir le code binaire 30. C'est par exemple le cas lorsque le pointeur PD; est déclaré dans le code source. Classiquement, un tel pointeur pointe sur un variable globale ou une variable statique ou une variable locale. Lors de la compilation du code source, pour minimiser la probabilité que deux pointeurs différents aient le même identifiant de pointeur, par exemple, le compilateur génère l'identifiant IP; du pointeur par tirage aléatoire ou pseudo-aléatoire de cet identifiant dans un ensemble EIP. L'ensemble EIP contient toutes les valeurs possibles pour un identifiant de pointeur sauf les valeurs déjà attribuée à un identifiant de pointeur. Dans un autre mode de réalisation, l'identifiant IP; est à chaque fois tirée de façon aléatoire ou pseudo-aléatoire dans l'ensemble EIP. A titre d'illustration, pour faire cela, dans le cas d'un compilateur utilisant LLVM ("Low Level Virtual Machine"), l'instruction "Alloca" est modifiée pour que le pointeur généré au moment de la compilation du code source comporte un identifiant IP; et une adresse @;. L'instruction "Alloca" génère un pointeur qui pointe typiquement sur une variable locale enregistrée dans la pile 46. [0065] Un pointeur peut aussi être généré lors de l'exécution du code binaire 30. C'est notamment le cas lorsque le code binaire comporte des instructions qui, lorsqu'elles sont exécutées par le microprocesseur 2, alloue dynamiquement une zone de mémoire libre pour y enregistrer des données. Lorsque de telles instructions sont exécutées, elles génèrent un pointeur qui pointe vers la zone de mémoire allouée. Ici, de telles instructions sont exécutées par le microprocesseur 2 lors de l'étape 290 décrite plus loin en référence à la figure 6. De telles instructions sont fréquemment utilisées pour 16 allouer dynamiquement une zone de mémoire dans le tas 48. Par exemple, dans un code source utilisant les librairies standards du langage C. de telles instructions correspondent aux fonctions "malloc()", "calloc()", "realloc()", ...etc. Dans ce cas, ces fonctions "malloc()", "calloc()", "realloc()", ...etc sont modifiées pour que le pointeur PD, qu'elles génères comporte, en plus de l'adresse @,, l'identifiant IP,. De préférence, chaque exécution d'une telle fonction doit générer un identifiant IPi aussi différent que possible de l'identifiant IP, généré lors de la précédente exécution de cette même fonction. Pour cela, par exemple, à chaque exécution dune telle fonction : - l'identifiant IP, est tirée, de façon aléatoire ou pseudo-aléatoire, dans l'ensemble EIP, ou - l'identifiant IP, est pris égale à l'empreinte numérique obtenue en appliquant une fonction de hachage à l'adresse @,. [0066] Un tel pointeur PD, qui contient, en plus de l'adresse @),, d'autres informations, c'est-à-dire ici l'identifiant IPi, est appelé "pointeur enrichi". [0067] Les structures de toutes les lignes LD; destinées à être traitées à l'aide d'un pointeur PD; sont identiques. Cette structure est représentée en détail sur la figure 3 dans le cas particulier de la ligne LD;. [0068] La ligne LD; comporte un cryptogramme CD;*, un code MAC, et un code ECC, ;. [0069] Le cryptogramme CD;* est obtenu en chiffrant une concaténation CD; à l'aide de la clé secrète ka et d'un vecteur d'initial isation iv. Plus précisément, le cryptogramme CD;* est obtenu à l'aide de la relation suivante : CD;* = fka(CD; ; iv;), où fka est une fonction de chiffrement, correspondant à une fonction de déchiffrement L 1. pré-programmée dans le module 28. Typiquement, la fonction fia, est une fonction de chiffrement symétrique. Dès lors, la clé ka permettant de déchiffrer le cryptogramme CD;* est préenregistrée dans la mémoire 29 afin de permettre au module 28 de déchiffrer ce cryptogramme CD. [0070] Le vecteur iv; est un vecteur dont la valeur dépend de l'adresse @, et de l'identifiant IPj du pointeta maj. Dans ce mode de réalisation, le vecteur iv; est codé sur le même nombre de bits que le pointeur PD;. [0071] À cet effet, le module 28 comporte une fonction préprogrammée Fi, qui, à chaque adresse @; et à chaque identifiant IPi, associe une valeur différente du vecteur iv. Par exemple, la fonction Fi, est une fonction de hachage ou de chiffrement. On a donc la relation suivante : iv i = F1,(@ [0072] La concaténation CD, est ici la concaténation de la donnée D, et d'un code ECCD,. [0073] Le code ECCD, est une première étiquette d'intégrité qui permet de vérifier l'intégrité de la ligne LDJ. Plus précisément, le code ECCE), permet de détecter une erreur dans la donnée D, et, éventuellement, de corriger cette erreur. Par exemple, le code ECCE), est le code connu sous l'acronyme BCH (Bose, Ray-Chaudhuri, Hocquenghem) qui 17 présente l'avantage d'être particulièrement facile à mettre en oeuvre. Toutefois, tout autre code détecteur ou correcteur d'erreur connu peut être mis en oeuvre. La taille du code ECC'; est supérieure ou égale à 1 ou 2 ou 3 bits et, généralement, inférieure à Nms, . La taille du code ECC', est déterminée en fonction de la robustesse souhaitée. Plus on veut être capable de corriger un nombre de bits erronés important dans la donnée D,, plus la taille du code ECC'; sera grande. [0074] Le code MAC; est une seconde étiquette d'intégrité qui permet aussi de vérifier l'intégrité de la ligne LD,. Plus précisément, ici, le code MAC, est un code permettant de vérifier l'intégrité et l'authenticité du cryptogramme CD,*. Ce code est communément appelé « code d'authentification de message » et connu sous l'acronyme MAC (« Message Authentification Code »). Un tel code MAC, est obtenu en construisant une empreinte numérique à partir du cryptogramme CD,*. Cette empreinte numérique comporte normalement moins de bits que le cryptogramme CD;*. Une telle empreinte numérique est plus connue sous le terme anglais de "digest" ou "hash". Cette empreinte numérique est construite à l'aide d'une fonction prédéterminée et de la clé secrète k' connue seulement de l'auteur du code binaire 30 et du microprocesseur 2. Ici, la clé k' est préenregistrée dans la mémoire 29. De plus, dans ce mode de réalisation, le code MAC; est aussi construit à l'aide de l'adresse @; et de l'identifiant IP;. Par exemple, la fonction prédéterminée est une fonction à sens unique telle qu'une fonction de hachage. Dans ce cas, généralement, l'empreinte numérique est le résultat de l'application de cette fonction de hachage à une combinaison, par exemple une concaténation, du cryptogramme CD;'', de la clé k', de l'adresse @; et de l'identifiant TP;. [0075] À titre d'exemple, pour générer le cryptogramme CD;* et le code MAC;, un al- gorithme de chiffrement authentifié est utilisé. Cet algorithme de chiffrement authentifié peut être choisi parmi les différents candidats à la compétition CAESAR (« Competition for Authentificated Encryption : Security, Applicability, and Robustness ») comme par exemple l'un des algorithmes désignés par les noms suivants : « ACORN », « ASCON », « SILC », « CLOC », « JAMBU », « KETJE ». [0076] Le code ECC, ; est un code correcteur d'erreur qui permet de détecter et de corriger une erreur dans le cryptogramme CD;':' et le code MAC;. Il est par exemple construit comme décrit dans le cas du code ECC';. [0077] La ligne LD; est construite au moment de la génération du code binaire 30 lorsque l'adresse @; est fixée au moment de la compilation. Dans ce cas, le compilateur génère d'abord l'identifiant IP, du pointeur PD, puis cet identifiant IP, et l'adresse @, sont utilisés pour construire la ligne LDJ. [0078] La ligne LD, peut aussi être construite au cours de l'exécution du code binaire 30 C'est le cas lorsque l'adresse @, à laquelle doit être enregistrée la ligne Li:), est uniquement connue au moment où le code binaire 30 s'exécute. Par exemple, cette 18 situation se rencontre lorsque la ligne LD, est enregistrée dans une zone de mémoire allouée dynamiquement dans le tas 48. [0079] La figure 4 représente un procédé d'exécution du code binaire 30 par le micro- processeur 2. [0080] Le procédé débute par une étape 150 de génération puis de fourniture du code binaire 30 dans la mémoire 4. La génération du code binaire 30 est typiquement réalisée par un compilateur tel que celui décrit en référence à la figure 7. La fourniture du code binaire 30 consiste ici ensuite à fournir la copie 40 puis, par exemple, le microprocesseur 2 recopie la copie 40 à l'intérieur de la mémoire 4 pour obtenir le code binaire 30 enregistré dans la mémoire 4. Ainsi, lors de l'étape 150, les lignes LD; construites lors de la compilation du code source et contenues dans le code binaire 30, sont enregistrées dans la mémoire 4 et, généralement, dans la partie 44. [0081] Ensuite, lors d'une phase 152, le microprocesseur 2 exécute le code binaire 30 et, en particulier, le code machine 32. [0082] Éventuellement, l'exécution du code binaire 30 commence par une étape 154 d'authentification de l'auteur de ce code binaire. Si l'authentification a été réussie avec succès, alors le procédé se poursuit par une étape 162. À l'inverse, si l'authentification n'a pas été réussie avec succès, le module 28 considère alors que l'authentification dc l'auteur du code binaire 30 a échoué et le procédé se poursuit par une étape 163. Lors de l'étape 163, l'exécution du code binaire 30 est arrêtée. [0083] Lors de l'étape 162, le module 28 charge notamment le cryptogramme ka* contenu dans le bloc 34 et le déchiffre à l'aide de la clé skcpi, contenue dans la mémoire 29. À l'issue de l'étape 162, la clé ka est contenue dans la mémoire 29. [0084] Après l'étape 162, le microprocesseur 2 exécute, les unes après les autres, les ins- tructions du code machine 32. [0085] Dans ce mode de réalisation, la sécurisation des pointeurs de données intervient à chaque fois que l'instruction exécutée par le microprocesseur 2 est une instruction de lecture d'une ligne de donnée LD; dans la ménini le 4 à une adresse 44 j spécifie par le pointeur PI4j. Cette instruction de lecture comporte typiquement un opérande qui contient l'adresse à laquelle le pointeur PD; est enregistré dans la mémoire 4. [0086] L'exécution de cette instruction de lecture par le microprocesseur 2 déclenche donc d'abord le chargement dans un registre, lors d'une étape 164, du pointeur PD;. [0087] Ensuite, lors d'une étape 166, le microprocesseur 2 charge, par exemple dans un registre Ri du microprocesseur, la ligne LDJ. L'étape 166 comporte l'extraction de l'adresse @; à partir du pointeur PD; chargé. Par exemple, pour cela, l'adresse @; est obtenue en masquant les bits de la seconde plage de bits du pointeur PDJ. Cette opération de masquage permet d'obtenir la même adresse @; que si les Np bits de poids forts étaient égaux à zéro. Ensuite, seule l'adresse @; extraite est transmise à la 19 mémoire 4 par l'intermédiaire du bus d'adresse. En réponse, la mémoire 4 transmet sur le bus de donnée, la ligne LD,. [0088] Ensuite, le module 28 procède à une étape 168 de sécurisation de de la donnée D, et du pointeur PD,. Pour cela, le module 28 réalise successivement les opérations suivantes. [0089] Lors d'une opération 170, le module 28 vérifie s'il existe une erreur dans le cryp- togramme CD," ou le code MAC, à l'aide du code ECCL, contenu dans la ligne LD, chargée. Par exemple, pour cela, le module 28 construit, à l'aide d'une fonction pré-programmée, du cryptogramme CD* et du code MAC], un code ECCL,'. Si le code ECCL,' est différent du code ECCL,. alors une erreur est détectée. Si une erreur est détectée, le module 28 procède immédiatement à une étape 172. [0090] Lors de l'étape 172, le module 28 déclenche le signalement d'une faute d'exécution. [0091] Ici, en parallèle de l'étape 172, si une erreur est détectée, le module 28 procède à une opération 174. Lors de l'opération 174, il corrige le cryptogramme CD;" et le code MAC; à partir des informations contenues dans le code ECCH. À l'issue de l'opération 174, le cryptogramme CD;* corrigé et le code MAC; corrigé sont utilisés à la place, respectivement, du cryptogramme CD;* et du code MAC; contenus dans la ligne LD;. [0092] L'opération 170 permet notamment de détecter et de corriger des fautes introduites dans les lignes de données stockées dans la mémoire 4. [0093] À l'issue de l'opération 174 ou si aucune erreur n'a été détectée lors de l'opération 170, le procédé se poursuit par une opération 176. [0094] Lors de l'opération 176, le module 28 vérifie l'intégiité de la ligne LDi. Ici, il vérifie l'intégrité et l'authenticité du cryptogramme CD;" à l'aide du code MAC;. Pour cela, le module 28 construit un code MAC;' en utilisant le même algorithme que celui mis en oeuvre pour construire le code MAC; sauf qu'il utilise le cryptogramme CD;* chargé lors de l'étape 166. De plus, lors de l'opération 176, le module 28 utilise l'identifiant IP; et l'adresse @; contenus dans le pointeur PD; chargé lors de l'étape 164. Par exemple, le cryptogramme CD;* est concaténé avec la clé k', l'adresse @; et l'identifiant TP;. Le code MAC;' est alors égal à l'empreinte numérique de cette concaténation. Si le code MAC;' ainsi construit est identique au code MAC; chargé, alors l'intégrité et l'authenticité du cryptogramme CD;* est confirmée. Dans ce cas, le cryptogramme CD; * est enregistré dans un registre du microprocesseur et le module 28 procède, lors d'une opération 178, à son déchiffrement. Dans le cas contraire, la vérification de l'intégrité de la ligne LD; échoue et le module 28 procède à l'étape 172. [0095] L'opération 176 permet de valider l'intégrité et l'authenticité de la ligne LD, chargée et aussi de valider que, lors de l'opération 174, le cryptogramme CD,* et/ou le code MAC, ont correctement été corrigés. L'opération 176 permet donc de détecter un remplacement de la ligne LD, par une nouvelle ligne de donnée construite par un auteur qui ne connaît pas la clé k'. L'opération 176 permet aussi de détecter la permutation de la ligne LD; avec une autre ligne LDk enregistrée à une adresse @k différente de l'adresse @,. [0096] L'opération 176 permet aussi de détecter pratiquement tous les usages erronés d'un pointeur. Par exemple, l'opération 176 détecte une utilisation incorrecte d'un pointeur PDk pour lire la ligne LD, ou pour remplacer la ligne LD, par une nouvelle ligne LDk. Plus précisément, si un autre pointeur PDk, différent du pointeur PD,, est utilisé pour lire la ligne LD,, c'est l'identifiant IPk, différent de l'identifiant IPJ, contenu dans le pointeur PDk qui est utilisé pour construire le code MAC:. Par conséquent, le code MAC,' construit est différent du code MAC. Cet usage erroné du pointeur PD,, déclenche donc le signalement d'une faute d'exécution. Si le pointeur PDk est utilisé pour écrire une ligne LD,, à la place de la ligne LD,, alors le code MACk de la ligne LD k est construit à l'aide de identifiant Ensuite, lors de l'utilisation suivante du pointeur PD;, le code MAC;' construit est différent du code MAL car c'est l'identifiant IPi, et non pas l'identifiant IPk, qui est utilisé. Dès lors, cette utilisation erronée du pointeur PDk est aussi détectée. Gracc à cela, les attaques par dépassement de tampon sont détectées. [0097] De même, l'opération 176 permet de détecter l'utilisation du pointeur PD; après que la zone de mémoire contenant la ligne LD; ait été libérée. En effet, typiquement, après la libération de cette zone de mémoire, celle-ci est réutilisée pour y enregistrer d'autres lignes de données. Pour réutiliser cette zone de mémoire, un nouveau pointeur PDk est généré puis utilisé pour enregistrer ces autres lignes LDk. Ce nouveau pointeur PDk comporte un identifiant IPk différent de l'identifiant IP; Ensuite, si le pointeur PD; est utilisé pour lire la ligne LDk, ceci est détecter. En effet, dans ce cas là aussi, le code MAC;' construit sera différent du code MAL de la ligne LDk. Ainsi, l'opération 176 permet de détecter des attaques utilisant des "dangling pointer" ou des attaques du type "use-after-free". [0098] Lors de l'opération 178, le module 28 déchiffre le cryptogramme CD;* en utilisant la clé ka, le vecteur d'initialisation iv; et la fonction fi,, ' pour obtenir la concaténation CD; déchiffrée et donc la donnée D; et le code ECC); déchiffrés. La clé ka est celle qui a été enregistrée dans la mémoire 29 lors de l'étape 162. Lors de l'opération 178, le vecteur iv; est calculé par le module 28 à l'aide de la relation : iv; = Fi,(@,,,,,), où @, et IP; sont l'adresse et l'identifiant contenus dans le pointeur PD; chargé lors de l'étape 164. [0099] Une fois que le cryptogramme CD;* a été déchiffré, lors d'une opération 180, le module 28 enregistre la donnée D; déchiffrée et le code ECCD; déchiffré dans le registre Ri en attendant que cette donnée soit traitée par l'unité 10. [0100] Lorsque la prochaine instruction qui va être exécutée par l'unité 10 est une ins- truction qui traite la donnée Di, le module 28 procède à des opérations 184 et 186. Le 21 module 28 identifie que la prochaine instruction à exécuter va traiter la donnée D, car cette instruction comporte généralement un opérande qui identifie le registre R, dans lequel est enregistré la donnée D. [0101] Lors d'une opéra Lion 184, le moduE 28 vérifie une nouvelle fois l'innhaiié de la ligne LDj. Plus précisément, il vérifie s' il exis Le une erreur dans la donnée Dj contenue dans le registre 121 à l'aide du code ECCD1 égalemeru wntenue dans ce regisire 121 Cote 01S:radon es i réalisée de façon similaire à ce qui a éié dévaii pour l'opération 170 Craie opéradors 184 permet de détecter une masque par injeciion de faute dans le mgisire [0102] Si le module 28 détecte une erreur, alors il procède immédiatemeni à l'éiape 172 De plus, en parallèle, lors d'une opénuion 186, le module 28 corrige la donnée Dj à l'aide du code ECEDj. opéraiion 186 esi similaire à l'opération 174 [0103] on noient aussi q LI, dans un !none de réalisation où l'opéradon 176 est omise, l'opéraiion 184 permet aLI,I de détecier los mêmes usages erronés dm pointeurs de données que ceux détectables lors de l'opénuion 176 En effet, la donnée Dj et le code FEEL/ ont été libitum en d échiffraril le 9')'Piogmnnne C'Dji noiammeni lu l'aide de fiderilifiani 119 du poinieur chargé lors de léiape 164 Dès lors, si le pointeur chargé lors de craie éiape dem pas le poinieurED1 mais un auire pointeur PD", différeni, la dmmée LE déchiffrée ci le code ECCD1 déchiffré lors de l'opénuion 178 Som inconnus, La vérificruion de l'intégrité de la ligne 4171 lors de l'opéra Lion 184 échoue donc. [0104] Ensuite, à l'issue de l'opération 186 ou si aucune erreur n'a été détectée lors de l'opération 184, l'unité 10 exécute l'instruction qui traite la donnée Di. [0105] En parallèle, à chaque fois que l'unité 10 exécute une instruction qui conduit à en- registrer une nouvelle donnée Di dans un registre, noté ici R. de l'ensemble 12, le module 28 construit la concaténation CD, et l'enregistre dans le registre Ri. [0106] Ultérieurement, l'unité 10 exécute une instruction d'écriture dc la donnée Di contenue dans le registre Ri à l'adresse @, contenue dans le pointeur PD,. [0107] En réponse, lors d'une opération 192, le module 28 construit la ligne de donnée LDi qui doit être enregistrée à l'adresse @, j Prou cela. le module 78 CRICU1C le vecteur à l'aide de la relation: irj Fiv(2141, 117E, puis construit le cryptogramme ci)]* à l'aide de la ',bidon ci)]* fka(CD1 ; ivj), puis calcule le code MAC] à l'aide du cry ptog momie nie', de la clé h', de l'adresse ei et de l'identifiant 1181, puis calcule le code FCCI 41 l'aide du cryptogramine EDE" et du code MAEj, puis crinciiene le cryptogramme CDP", le cnde MACj et le code ECClj pour former la ligne 1,Dj. [0108] Ensuite, lors d'une opération 194, le micmorncesscur 7 enregistre la ligne 1.1)1.)nm-trac dans la mémoire 4 à l'adresse ES. Lors de cette opération, l'adresse anj est extraite du pointeur ppi entame décrit dans le cas de l'étape 166. [0109] Lors de l'exécution du code binaire, si un usage erronée d'un pointeur de donnée se produit, le microprocesseur 2 signale, lors de l'étape 172, une faute dans l'exécution du code binaire 30. En réponse à un tel signalement, lors d'une étape 200, le microprocesseur 2 met en oeuvre une ou plusieurs contre-mesures. De très nombreuses contre-mesures sont possibles. Les contre-mesures mises en oeuvre peuvent avoir des degrés de sévérité très différents. Par exemple, les contre-mesures mises en oeuvre peuvent aller d'un simple affichage ou une simple mémorisation d'un message d'erreur sans interrompre l'exécution normale du code binaire, jusqu'à une mise hors service définitive du microprocesseur 2. Le microprocesseur 2 est considéré comme étant hors service lorsqu'il est définitivement placé dans un état où il est incapable d'exécuter un quelconque code binaire. Entre ces degrés de sévérité extrêmes, il existe de nombreuses autres contre-mesures possibles telles que : - l'indication par l'intermédiaire d'une interface homme-machine de la détection des fautes, - l'interruption immédiate de l'exécution du code binaire et/ou sa réinitialisation, et - la suppression du code binaire de la mémoire 4 et/ou la suppression de la copie 40 de sauvegarde et/ou la suppression des données secrètes. [0110] De plus, ici, la contre-mesure mise en OELIIre lors d PéLape 200 peut ému sel, donnée en fonction de reneur détectée et donc en fonction de l'opération qui a conduit à la clebeCtiOn de cette faum. Par exemple, la contreffnesure sélectionnée ne ,era pas la n'élue selon que l'erreur a été détectée lors de l'opération 176 OLÉ 184. [01 1 11 Dan, ce mode de réalisation, le, donnée, qui ,ont enregi,ares dard la mémoire 4 mais qui ne sont pa, manipulées à raide d'un pointeur sont chiffrées par LMprocédé conventionnel de chiffrement. Dans oette demande, ces données SOM désignée, par le symbole Daj. Pour asffirta la cohérence des notations, l'adresse. à laquelle est enrepistrec la don nec Daj dans la inemoirc 4 est aussi noter (Ath Par exemple, ici, le procédé mis en mune pour chiffrer les données Daj est celui decrit dans lc dia pitre V de la demande EP245.77620.6. Dans ccs conditions, chaque donnée Daj est cnrcgistréc dans 'inc ligne 1.Daj de donnée dont la structure cst identique à celle de la ligne I.Dj precédernment décrite. Dc plus, de préfémner, l'adresse jj dc chaque dminec Daj: a la mêmc mille que l'admisse ajtj contenue dans chaque pointeur PDj, ct est contenue dans un mot machine de men, mille que e pointeur PDj et dans la memc ',minière plage dc bits. [0112] Ainsi, l'adresse eh d'une don nec Daj est contenue dans un opérande qui a la memc structure que le pointeur Ppj sauf cille les bits dc la seconde plapc dc bits sont systématiquement nulles. Dans cas conditions pour lire ct écrire dans la mei-1min, 4l111c (10111,5e Daj, lcs mêmes étapes que celles décrites ci dessons dans le cas pani culi cr d'une donné, Djj sont mises Cfl oeuxrc. En effet, la seule différence est que dans le cas d'une donnée Daj, pour obtenir son ',dresse eh à partir dc l'opérande dc l'instruction de lecture, il n'est pÉIS lléCCSSÉ111, CILI 111,1Squcr la seconde plage dc bits dc l'opemnde puisque celle ci cst systeinatiqucinmt égale 11 zéro. Toutefois, lc fait d'exécuter l'nperation de masquage de la seconde plage de bits ne change. ri cil au résultat et l'adresse dé] dc la donnec Daj car correctement obtenue à partir dc l'opérande de l'instruction de lecture. [0113] Dans ce mode de réalisation, lorsqu'un pointeur PD; est enregistré dans la mémoire 4 et qu'il n'est pas lui-même manipulé à l'aide d'un autre pointeur, ce pointeur PD; est une donnée Da; et donc traité comme tel. Le pointeur PD; est donc enregistré sous forme chiffré dans la mémoire 4. Par conséquent, lors de l'étape 164, la ligne de donnée codant ce pointeur PD; est chargée et déchiffrée de la même manière que pour une donnée Dai. [0114] Lorsqu'un pointeur PD; est enregistré dans la mémoire 4 et qu'il est lui-même manipulé à l'aide d'un autre pointeur, ce pointeur PD; est une donnée D; et donc traité comme tel. Ce pointeur PD; est donc lui-aussi enregistré sous forme chitTré dans la mémoire 4. Par contre, lors de l'étape 164, la ligne de donnée codant ce pointeur PD; est chargée et déchiffrée de la même manière que pour une donnée D; et non p' con da, l'' d'une donnée Daj. Ainsi, le procédé fonctionne aussi lorsque qu'un pointeur de donnée pointe lui-même sur un autre pointeur de donnée. Cette situation est connue sous le terme de 23 "pointeur de pointeur". [0115] CHAPITRE IV : SECURISATION DES POINTEURS DE FONCTIONS [0116] Le code machine 32 comporte une succession de lignes d'instruction LI, enregistrées les unes après les autres dans la mémoire 4. Contrairement aux lignes de données LE), décrites précédemment, la ligne LI, code une instruction I, à exécuter par l'unité 10 et non pas une donnée D, à traiter. Par la suite, dans ce chapitre, l'indice j est utilisé pour identifier la ligne d'instruction LI, parmi les autres lignes d'instructions du code machine 32. De plus, l'indice j est aussi utilisé comme un numéro d'ordre indiquant dans quel ordre les lignes LI, sont classées. Ainsi, on note LI," la ligne d'instruction située immédiatement après la ligne LI,. Chaque ligne d'instruction LI, code une instruction du jeu d'instructions du microprocesseur 2 apte à être exécutée, après avoir été déchiffrée et décodée, par l'unité 10 de cc microprocesseur. [0117] Un code binaire peut comporter des pointeurs de fonction. Contrairement à un pointeur de donnée, un pointeur de fonction contient l'adresse d'une ligne d'instruction contenant une instruction à exécuter par le microprocesseur. Ainsi, lorsqu'un pointeur de fonction est lu cela provoque le chargement de l'adresse qu'il contient dans le compteur ordinal 26. L'exécution du code binaire se poursuit donc par l'exécution de l'instruction pointée par ce pointeur de fonction. Ces pointeurs de fonctions sont donc utilisés pour appeler des routines à partir du code d'une fonction principale. Ces routines sont également appelées "fonctions appelées". [0118] A titre (l'illustration, l'usage de telles pointeurs de fonction se rencontre dans les cas suivants : [0119] Cas 1) : Un pointeur de fonction est introduit par le compilateur lorsqu'il rencontre dans le code source certaines instructions particulières. Par exemple, l'instruction "SWITCH" peut entraîner la création par le compilateur d'une table d'association qui, à chaque cas prévu par l'instruction "SWITCH", associe un pointeur de fonction particulier. Lors de l'exécution du code binaire correspondant, le microprocesseur identifie le cas rencontré, puis lit dans la table d'association le pointeur associé à ce cas identifié. [0120] Cas 2) : L'usage de pointeurs de fonctions se rencontre aussi fréquemment dans le contexte de la programmation objet. Dans ce contexte, le code source peut définir une classe d'objets et pour cette classe d'objets plusieurs méthodes. L'appel à ces différentes méthodes d'une classe est alors souvent implémenté dans le code machine en utilisant une mécanisme connu sous le terme de ''vtable" ou "virtual method table". Ce mécanisme utilise un table qui à chaque identifiant de méthode associe un pointeur vers la première instruction de cette méthode. [0121] Cas 3) : Lorsqu'une fonction A appelle une fonction B prédéfinie dans une librairie de fonctions pré-enregistrées, une table est utilisée pour associer à l'identifiant de la 24 fonction B, contenu dans le code binaire de la fonction A, un pointeur vers l'adresse de la première instruction de la fonction B. Dans ce cas, généralement, le pointeur vers la fonction B est généré par un chargeur de librairies dynamiques, connu sous l'anglicisme "loader", au moment où débute l'exécution de la fonction A. [0122] Cas 4) : Il est aussi possible de déclarer dans un code source des pointeurs de fonction. [0123] Pour sécuriser ces pointeurs de fonction contre un usage erroné, la structure de ces pointeurs de fonction est identique à celle décrite en référence à la figure 2. Par la suite, on utilise les symboles PFf, IPr et @f pour désigner, respectivement, un pointeur de fonction, l'identifiant de ce pointeur de fonction et l'adresse vers laquelle pointe ce pointeur de fonction. L'indice f est un identifiant de la fonction pointée par le pointeur PFf. [0124] Les pointeurs de fonctions sont générés lors de la compilation du code source et/ou lors de l'exécution du code binaire. Pour cela, les instructions du compilateur et/ou les instructions exécutées par le microprocesseur 2 qui génèrent de telles pointeurs de fonction sont adaptées pour : - générer l'identifiant Ipf qui permet d'identifier de façon unique le pointeur PFf parmi un ensemble d'autres pointeurs de fonctions utilisés lors de la même exécution du code binaire 30, et - construire et retourner un pointeur PFf contenant l'identifiant IPf et l'adresse @f. [0125] La structure de chaque ligne d'instruction LI; de chaque fonction pointée par un pointeur PFf est représentée dans la figure 5. Cette structure est identique à celle d'une ligne LD;. Toutefois, dans le contexte d'une ligne d'instruction LT, on utilise les symboles T, ECCH, CT et CI;* pour désigner, respectivement, l'instruction codée dans cette ligne, le code correcteur d'erreur associé à cette instruction T, la concaténation de l'instruction I; et du code ECCH et le cryptogramme de cette concaténation. [0126] Par la suite le même symbole @; est utilisé pour désigner l'adresse à laquelle est en- registrée la ligne LT. [0127] Le code ECC,; de la ligne LI; est construit comme décrit pour le code ECCD; sauf que la donnée D; est remplacée pal- l'instruction T. [0128] Le cryptogramme CI;* est construit comme le cryptogramme CD;* sauf que l'identifiant Il); est remplacé par l'identifiant IPf du pointeur qui pointe vers la fonction qui contient cette ligne LT. Ainsi, toutes les lignes LI; d'une même fonction adressée à l'aide du pointeur PFf sont chiffrées en utilisant le même identifiant IPf. Le cryptogramme CT* est donc construit en utilisant la fonction fka, la clé ka, l'adresse @; et l'identifiant IPf. [0129] Le code MAC; est construit comme le code MAC; d'une ligne de donnée sauf que le cryptogramme CD;* et l'identifiant IP; sont remplacés par, respectivement, le cryp- togrammc CT* et l'identifiant IPf. Le code MAC; de la ligne LI; est donc construit en utilisant le cryptogramme ni", la clé k', l'adresse @; et l'identifiant IPf. [0130] Le code ECCL; est construit comme le code ECCL; d'une ligne de donnée sauf que le cryptogramme CD;* est remplacé par le cryptogramme ni". [0131] Le vecteur iv; utilisé pour construire la ligne LT est un vecteur dont la valeur dépend de l'adresse a j de la ligne Llj et de l'identifiant ll'f du pointeur PK A cet effet, par exemple, la relation suivante est utilisée ivj - FivI el [0132] La sécurisation des pOtElletlr, de fonction va maintenant être décrite plus tu déLilit en miasme, au procédé de la figure 6 et dans le cils paniculi où ellcep arise en mumq en combinaison mec les enseignements des chapitre, préi6dent. Ici, la sécurisation des pointeurs d 111,LITICLIIMIS intervient à chaque fois que l'arimuction à exécuter est chargée a laide d'un pointeur de fonction [0133] Plus précisément, dans ce cas, lors d'une étape 264, le microprocesseur 2 charge le pointeur PEr dans le compteur ordinal 26. [0134] Ensuite, lors d'une étape 266, le microprocesseur 2 charge successivement chacune des lignes LI; de la fonction appelée en commençant par la ligne UT enregistrée à l'adresse @f contenue dans le pointeur PEf. Pour cela, l'adresse @f est extraite du pointeur PFf chargé, par exemple, comme décrit dans le cas de l'étape 166. Après cela, l'adresse @f est transmise à la mémoire 4 par l'intermédiaire du bus d'adresse. L'adresse @i de la ligne LI; suivante est par exemple obtenue en incrémentant le compteur ordinal. Le fait d'incrémenter le compteur ordinal modifie l'adresse qu'il contient mais ne modifie pas l'identifiant IPf contenu dans ce compteur ordinal. [0135] Ensuite, le module 28 procède à une étape 268 de sécurisation de l'instruction et du pointeur PFf. Pour cela, le module 28 réalise successivement des opérations 270, 274, 276, 278, 284 et 286 pour chacune des lignes d'instructions LI; de la fonction appelée à l'aide du pointeur PEf. Ces opérations 270, 274, 276, 278, 284 et 286 sont identiques, respectivement, aux opérations 170, 174, 176, 178, 184 et 186 précédemment décrites sauf que les symboles Di, ECC,-,;, CD; et CD;* sont remplacés par les symboles, respectivement, I, ECC,;, CI; et CI;*. [0136] Après l'opération 278, le module 28 enregistre l'instruction If et le code ECC,i dé- chiffrés dans la file 22. Une fois que l'unité 10 a exécuté toutes les instructions qui précédent l'instruction I; dans la file 22, c'est-à-dire lorsque l'instruction I; est la prochaine instruction à exécuter par l'unité 10, le module 28 déclenche l'exécution des opérations 284 et, éventuellement, 286. Puis, lors d'une étape 290, l'unité 10 exécute l'instruction T. [0137] CHAPITRE V : SECURISATION DES POINTEURS INVALIDES [0138] En plus de ce qui a déjà été décrit précédemment, dans un mode de réalisation préférée, les instructions qui libèrent une zone de mémoire sont modifiées pour rendre un pointeur invalide inutilisable. Ici, ces instructions sont exécutées par le microprocesseur 2 lors de l'étape 290. 26 [0139] Par exemple, l'instruction qui libère une zone de mémoire est l'instruction "Free" du langage C. Dans le code source, l'instruction "Free" se présente typiquement sous la forme "Free(PD,)", où "PD," est le pointeur qui pointe vers la zone de mémoire libérée. Une fois que l'instruction "Free(PD,)" a été exécutée, la zone de mémoire libérée dans la mémoire 4 peut être à nouveau allouée et utilisée pour y stocker d'autres lignes de données LDk. [0140] Après, l'exécution de l'instruction "Free(PD,)", le pointeur PD, est invalide et ne doit donc plus être utilisé pour accéder à cette zone de mémoire libérée. [0141] Ici, pour éviter tout usage du pointeur PD, invalide, l'instruction "Free" est modifiée pour que lorsqu'elle est exécutée, lors de l'étape 290, par le microprocesseur 2, alors l'identifiant IP, du pointeur PD, est aussi modifié. Ainsi, si le pointeur PD, est utilisé en dehors de la période de temps pendant laquelle il est valide, cela déclenche systématique une faute d'exécution. En effet, dans ce cas, même si le pointeur PD, est utilisé pour lire, dans la zone de mémoire libérée, la ligne de code LD; qui avait précédemment été écrite en utilisant ce pointeur PD;, alors la nouvelle valeur de l'identifiant IP; est différente de sa précédente valeur. La vérification, lors de l'opération 176, de l'intégrité de ligne LD; échoue donc. [0142] De plus, l'instruction "Free" peut aussi être modifiée pour effacer les lignes de code écrite dans la zone de mémoire libérée. Par exemple, pour cela, c'est ligne de code sont écrasées avec des valeurs aléatoire ou une valeur nulle. Par exemple, pour cela, les lignes écrites dans la zone de mémoire libérée sont écrites en utilisant la nouvelle valeur de l'identifiant IP; du ',hircin mi. [0143] CHAPITRE VI: GENERATION DU CODE BINAIRE [0144] La figure 7 représente un compilateur 300 apte à générer automatiquement le code binaire 30 à partir d'un code source 302. À cet effet, le compilateur 300 comporte typiquement un microprocesseur 304 programmable et une mémoire 306. La mémoire 306 contient les instructions et les données nécessaires pour, lorsqu'elles sont exécutées par le microprocesseur 304, générer automatiquement le code binaire 30 à partir du code source 302. En particulier, lors de la compilation du code source 302, le microprocesseur 304 génère automatiquement les pointeurs PD; pour les lignes LD; et les pointeurs PEf pour les lignes Llf. Plus précisément, lors de la compilation, le compilateur génère pour chacun de ces pointeurs l'identifiant de pointeur correspondant puis construit la ligne pointée par ce pointeur à l'aide de cet identifiant. La conception et la réalisation d'un tel compilateur sont à la portée de l'homme du métier à partir des explications données dans cette description. Par exemple, pour cela, le compilateur 30 repère et identifie automatiquement les pointeurs et les lignes de code qui sont traitées à l'aide de ces pointeurs. Par exemple, le compilateur 300 est un compilateur utilisant la couche d'abstraction LLVM. 27 [0145] CHAPITRE VII: VARIANTES: [0146] Variantes de l'appareil 1 : [0147] D'autres modes de réalisation de l'appareil 1 sont possibles. En particulier, toutes les variantes décrites dans les paragraphes 191 à 194 de la demande EP3457620A1 sont applicables ici. [0148] Dans le cas où seule la sécurisation des pointeurs de données est mise en oeuvre, le module 28 peut être remplacé par un module logiciel qui, lorsqu'il est exécuté par l'unité 10, réalise les mêmes fonctions et opérations que celles décrites pour le module 28. [0149] Variantes de la sécurisation des pointeurs de données : [0150] Les différentes variantes décrites dans le chapitre "Variantes de la sécurisation des données" de la demande EP3457620A1 peuvent être transposées sans difficulté dans le contexte de la présente demande. En particulier, le code ECC,,i peut être remplacé par un simple code détecteur d'erreur permettant seulement de détecter une erreur dans la donnée Di. Un code détecteur d'erreur ne permet pas de corriger l'erreur détectée. Dans ce cas, l'opération 186 de correction de l'erreur est omise. [0151] Dans une variante simplifiée, le code ECCT); est omis. Dans ce mode de réalisation, le microprocesseur 2 n'est plus capable de détecter une erreur dans le déchiffrement du cryptogramme CD* ou une modification de la donnée D qui interviendrait après son déchiffrement et avant son utilisation par l'unité 10. Dans ce cas, les opérations 184 et 186 sont omises [0152] Dans les modes de réalisation décrits jusqu'à présent, à la fois la donnée Di et le code ECCD; sont chiffrés en fonction du vecteur ivi. En variante, soit seulement la donnée Di soit seulement le code ECCD; est chiffré en fonction du vecteur iv. Par exemple, dans la ligne de donnée, le cryptogramme de la donnée Di est obtenu à partir d'une fonction de chiffrement qui n'utilise pas le vecteur iv, tandis que le cryptogramme ECCDC du code ECCD; est obtenu à l'aide de la fonction de chiffrement fl,'(ECCD; ; iv). Dans ce cas, lors de l'opération 178, le module 28 déchiffre le cryptogramme de la donnée Di sans utiliser le vecteur iv i et déchiffre le cryptogramme ECCe en utilisant ce vecteur iv. Ensuite, le reste du procédé est identique à ce qui a déjà été décrit. Dans un mode de réalisation simplifié, puisque la donnée Di n'a pas besoin d'être chiffrée en fonction du vecteur iv, il est aussi possible de ne pas la chiffrer. Par exemple, la ligne de donnée contient alors la donnée Di en clair et le cryptogramme ECCe. Dès lors, lors de l'opération 178, le déchiffrement de la donnée Di est omis puisqu'il suffit de l'extraire de la plage de bits dans laquelle elle est contenue dans la ligne LDi. [0153] A l'inverse, il est aussi possible de modifier la structure des lignes LI); de manière à ce que seule la donnée Di soit chiffrée en fonction du vecteur iv. Par exemple, la ligne LD; comporte un cryptogramme Di* de la donnée Di obtenue en la chiffrant à l'aide de 28 la fonction fu(D, ; iv,) et un cryptogramme ECC',* obtenu en chiffrant le code ECC', à l'aide d'une fonction de chiffrement indépendante du vecteur iv,. Lors de l'opération 178, le module 28 déchiffre le cryptogramme D,* à l'aide du vecteur iv, et déchiffre le cryptogramme ECC',* sans utiliser cc vecteur iv,. Dans ce cas, le code ECC',,,,',,,,', ë,' chiffré et êt, contenu en clair dans la ligne LD,. [0154] Dans une variante simplifiée, le cryptogramme CD,* est construit sans utiliser l'identifiant IP, et/ou sans utiliser l'adresse @, contenus dans le pointeur PD,. Lorsque l'identifiant IP, n'est pas utilisé pour construire le cryptogramme CD,*, alors seul le code MAC, permet de détecter un usage erroné du pointeur PD,. [0155] De nombreux modes de réalisation de la fonction fka sont possibles. Par exemple, la fonction fk, peut être aussi simple qu'une simple opération « OU Exclusif » logique entre la concaténation CD, et le vecteur iv,. [0156] Le chiffrement et le déchiffrement ont été décrits dans le cas particulier où les fonctions fk' et fk» sont des algorithmes de chiffrement qui utilisent un "vecteur d'initial isation" et, de préférence, aussi une clé secrète ka. Toutefois, les fonctions fka et fk' ' peuvent aussi être des algorithmes de chiffrement/déchiffrement dans lesquels un vecteur d'initial isation n'est pas utilisé. Tout cc qui a été décrit ici s'applique alors à l'identique à un tel algorithme de chiffrement/déchiffrement en remplaçant simplement le terme "vecteur d'initialisation" par le ternie "clé". [0157] Dans une autre variante, les clés ka et k' sont les mêmes. [0158] En variante, la fonction Fi, est identique à la fonction fk' sauf qu'elle est appliquée à l'adresse e _ c, à l'identifiant IPj- La fonction Fi, peut aussi utiliser le même algorithme de chiffrement que la fonction fka mais avec une clé de chiffrement différente de la clé ka. [0159] Dans une variante simplifiée, la fonction Fi, est la fonction identité. Dans ce cas, le vecteur iv; est systématiquement égal au pointeur PD;. [0160] Le code ECC, ; peut être remplacé par un simple code détecteur d'erreur Dans ce cas, l'opération 174 de con-ection est omise Dans une autre variante, le code ECC,, est construit de manière à permettre la détection d'une erreur, soit seulement dans le cryptogramme CD;'' soit seulement dans le code MAC;. [0161] Le code ECC, ; peut être omis. Dans ce cas, une erreur dans le cryptogramme CD;* ou dans le code MAC; est détectée uniquement lors de l'exécution de l'opération 176 de vérification de l'intégrité et de l'authenticité du cryptogramme. La détection d'une erreur à l'aide d'un code MAC est généralement plus complexe qu'à l'aide d'un simple code détecteur d'erreur ou d'un simple code correcteur d'erreur. De plus, lorsque le code ECQ, est omis, dans le cas où il existe une erreur dans le cryptogramme CD,* ou le code MACJ, il n'est pas possible de corriger cette erreur. Dans ce dernier cas, par exemple, l'exécution de la fonction sécurisée est donc systématiquement interrompue en cas d'erreur. 29 [0162] En variante, l'opération 176 se poursuit systématiquement par l'opération 178 même si l'intégrité ou l'authenticité du cryptogramme n'a pas pu être confirmée. Dans cc cas, l'opération 176 sert à déclencher le signalement d'une faute d'exécution sans interrompre l'exécution du code binaire. [0163] Pour détecter un usage erroné du pointeur PIDJ, un seul du code MAC; et du code ECCD; est nécessaire. Ainsi, dans un mode de réalisation simplifié, le code MAC; est omis et l'étape 176 est omise. Dans un autre mode de réalisation simplifié, c'est le code ECCD; qui est omis et les étapes 184 et 186 sont omises. [0164] Le nombre de bits et l'emplacement des bits de la seconde plage de bits du pointeur PD; peuvent être modifiés. Par exemple, la seconde plage de bits correspond aux bits de poids faibles du pointeur PDJ. Dans ce cas, il faut adapter le masque utilisé pour extraire, respectivement, l'identifiant IP; et l'adresse @; dans le pointeur PDJ. [0165] En variante, le pointeur PD; peut comporter une troisième plage de bits codant, par exemple, des titres d'accès à la ligne L-13;. Typiquement, ces titres d'accès sont ensuite comparés à des droits d'accès pré-enregistrés dans le microprocesseur 2 lors de l'exécution du code binaire 30. L'accès en lecture ou en écriture à la ligne LD; est autorisé uniquement si les droits d'accès du microprocesseur 2 correspondent aux titres d'accès contenus dans le pointeur PD;. [0166] Ce qui a été décrit ici n'est pas nécessairement mis en oeuvre pour tous les pointeurs de données. Par exemple, pour certains pointeurs de données, la sécurisation est désactivée. Pour cela, l'identifiant IP; est remplacé dans le pointeur PD; par une valeur nulle. L'activation et/ou la désactivation de la sécurisation de certains pointeurs de données sont par exemple programmées en ajoutant une instruction spécifique d'activation, et en alternance de désactivation, associée à ce pointeur de données dans le code source. [0167] Dans d'autres modes de réalisation, la sécurisation des pointeurs de données est uniquement mise en oeuvre pour des lignes de données enregistrées dans une partie spécifique de la mémoire 4. Par exemple, la sécurisation des pointeurs est uniquement mise en oeuvre pour les pointeurs pointant vers des données enregistrées dans la pile 46. Pour cela, seule l'instruction « Alloca » du compilateur LLVM est modifiée pour renvoyer un pointeur PD; contenant l'identifiant IP;. De façon similaire, ce qui a été décrit peut être mis en oeuvre seulement pour les pointeurs pointant vers une ligne de donnée enregistrée dans le tas 48. Dans ce cas, seule l'instruction d'allocation dynamique de mémoire dans le tas 48 est modifiée pour retourner un pointeur enrichi. Il est aussi possible de sécuriser uniquement les pointeurs pointant vers une donnée enregistrée dans la partie 44 de la mémoire 4. [0168] La sécurisation des pointeurs de données peut être omise ou désactivée. Dans ce cas, seule la sécurisation des pointeurs de fonctions est mise en oeuvre. Pour cela, par exemple, tous les identifiants de pointeurs de données ont une valeur nulle. [0169] Variantes de la sécurisation des pointeurs de fonctions : [0170] Toutes les variantes décrites ci-dessus dans le cas particulier d'un pointeur de données peuvent être transposées sans difficulté au cas d'un pointeur de fonction. Par exemple, pour cela, dans chacune des variantes décrites ci-dessus, il suffit de remplacer les symboles D. par, respectivement, les symboles -13, LI, et CL [0171] La sécurisation des pointeurs de fonctions peut être omise ou désactivée. Dans ce cas, seule la sécurisation des pointeurs de données est mise en oeuvre. Pour cela, par exemple, tous les identifiants de pointeurs de fonctions ont une valeur nulle. [0172] En réponse à l'exécution de l'instruction "Free(PD;), il est possible, soit de modifier uniquement la valeur de l'identifiant IPJ, soit uniquement d'effacer les données dans la zone de mémoire libérée. [0173] La sécurisation des pointeurs invalides peut être omises dans un mode de réalisation simplifié. [0174] Variantes communes aux différents chapitres précédents [0175] Les données Da; peuvent être chiffrées et déchiffrées par n'importe quel procédé et pas nécessairement par le procédé de la demande EP3457620A. Dans un mode de réalisation très simplifié, les données Dai ne sont pas chiffrées. [0176] Les instructions I; qui n'appartiennent pas à des fonctions appelées à l'aide d'un pointeur de fonction sont, de préférence, chiffrées. Par exemple, le procédé décrit dans la demande EP3457620A peut être mis en oeuvre pour cela. [0177] Ce qui a été décrit ici s'applique aussi dans un contexte où aucun mécanisme de mémoire virtuelle n'est implémenté. Dans ce cas, aucune adresse virtuelle n'est utilisée et seule les adresses physiques sont utilisées. [0178] La clé ka peut être pré-enregistrée dans la mémoire 29. Dans ce cas, le cryptogramme ka* peut être omis du bloc 34. [0179] Le cryptogramme ki* de la clé k' chiffrée avec la clé publique pic°, peut être en- registré dans le bloc 34. Dans ce cas, la clé k' n'a pas besoin d'être pré-enregistrée dans la mémoire 29. [0180] Une ligne de code peut être plus longue qu'un mot-machine. Dans ce cas, chaque ligne de code se compose de plusieurs mots-machine généralement situés à des adresses mémoires immédiatement consécutives dans la mémoire 4. Dans ce cas, une ligne de code est chargée dans le microprocesseur 2 non pas en une seule opération de lecture, mais en exécutant plusieurs opérations de lecture. Chaque opération de lecture charge dans le microprocesseur un mot-machine respectif de la ligne de code. [0181] Tous les modes de réalisation décrits dans ce texte et, en particulier, les différentes variantes, peuvent être combinés entre eux. 31 [0182] CHAPITRE VIII: AVANTAGES DES MODES DE RÉALISATION DÉCRITS: [0183] Les modes de réalisation décrits ici permettent de déclencher le signalement d'une faute d'exécution dès qu'un second pointeur PDk est utilisé pour lire ou écrire une ligne de code seulement destinée à être lue à l'aide d'un premier pointeur PD, dont l'identifiant IP, est différent de l'identifiant IPk. Ceci est expliqué dans le cas d'un pointeur de donnée mais les explications données ci-dessous se transposent sans difficulté au cas d'un pointeur de fonction. Lors de la lecture de la ligne LD, à l'aide du pointeur PDk, c'est l'identifiant IPk de cc pointeur PDk qui est utilisé lors de la construction de la seconde étiquette d'intégrité MAC;' ou ECC'. Dès lors, la seconde étiquette d'intégrité construite ne correspond pas à la première étiquette d'intégrité MAC, ou ECC', contenue dans cette ligne LD, et construite à l'aide de l'identifiant IPJ. La vérification de l'intégrité de la ligne de donnée échoue donc systématiquement et une faute d'exécution est signalée. Les procédés décrits permettent donc de signaler toute tentative de lecture de la ligne LD; à l'aide du pointeur PDk au lieu du pointeur PD;. Grâce à cela, il est possible de détecter des attaques qui utilisent des pointeurs invalides, comme les « dangling pointers ». [0184] De plus, les modes de réalisation décrits permettent aussi de détecter et de signaler les attaques par dépassement de tampons comme les attaques du type « stack overflow attack » ou « stack underflow attack ». Dans ces attaques, le pointeur PLC1/4 est utilisé pour écrire une nouvelle ligne LE1/4 à la place de la ligne LD;. Ce remplacement de la ligne LD; par la ligne LDk est alors détecté et signalé au moment où le microprocesseur 2 lit la ligne Ln, en utilisant pour cela le pointeur PD;. [0185] Le fait de construire le cryptogramme CD;* à l'aide de l'identifiant IP; du premier pointeur PD; permet de conserver la donnée D; secrète lors d'une tentative de lecture de la ligne LD; en utilisant le second pointeur PDk. En effet, lorsque le pointeur PIDE est utilisé pour lire la ligne LD;, c'est l'identifiant IPk et non pas l'identifiant IP; qui est utilisé pour déchiffrer le cryptogramme CD;''. Cela ne permet pas d'obtenir la donnée D; en clair. [0186] Le fait de construire la première étiquette d'intégrité MAC; ou de chiffrer la première étiquette d'intégrité Enmi. en plus, en utilisant l'adresse contenue dans la première plage de bits du pointeur PD; permet de détecter et de signaler un déplacement non intentionnel de la ligne LD; dans la mémoire. Cela permet notamment de détecter la permutation de la ligne LD; avec une autre ligne LDk. [0187] L'utilisation de la clé secrète ka pour construire les cryptogrammes CD;* permet d'accroître la sécurité du procédé. [0188] Le fait que la taille du pointeur PD; soit égale à la taille d'une adresse permet de charger et de manipuler ce pointeur enrichi comme une adresse classique et donc en un minimum d'instructions. En particulier, il n'est pas nécessaire d'ajouter des ins- 31 tructions supplémentaires pour lire ou écrire l'identifiant du pointeur dans la mémoire 4. [0189] La génération du premier pointeur en réponse à l'exécution d'une instruction d'allocation dynamique d'une zone mémoire permet de mettre en oeuvre le procédé décrit dans le cas où la mémoire est allouée dynamiquement au cours de l'exécution du code binaire. [0190] La modification de l'identifiant du premier pointeur lorsque la zone de mémoire sur laquelle il pointe est libérée, rend très difficile tout usage ultérieur de ce premier pointeur pour lire des données dans cette zone mémoire. [0191] L'enregistrement, dans la mémoire 4, du premier pointeur sous forme chiffrée accroît la sécurité du procédé d'exécution. [0192] Le fait que le pointeur PD; soit enregistré dans une ligne LDai construite de la même manière que la ligne Lpi, mais en utilisant un identifiant de pointeur systématiquement égal à zéro, permet de mettre en oeuvre les mêmes étapes pour lire et écrire ce pointeur PD; dans la mémoire 4, que celle mise en oeuvre pour lire et écrire la ligne LD;. Cela simplifie donc l'implémentation et l'exécution du code binaire 30. [0193] Par ailleurs, le chiffrement des instructions 1; permet de garantir la confidentialité du code binaire 30, ce qui rend le « Reverse Engineering » du code binaire très difficile. La vérification de l'intégrité du cryptogramme Cl* ou CD;* permet de détecter les modifications du code binaire provoquées, par exemple, par des attaques telles que l'injection de fautes dans la mémoire 4. Le fait de vérifier l'authenticité des instructions et des données permet de détecter et de rendre très difficile l'ajout d'instructions supplémentaires dans le code binaire 30 par un attaquant, par exemple, pour y introduire des logiciels malveillants tels que des virus. En effet, même si l'attaquant connaît l'algorithme utilisé pour chiffrer les instructions I; et les données Di, il ne connaît pas la clé secrète k' utilisée pour construire le code MAC;. [0194] Le fait que le code ECC,; ou ECCD; soit un code correcteur d'erreur et pas seulement un code détecteur d'erreur, permet de rendre le procédé d'exécution plus robuste vis-à-vis des attaques par injection de fautes. En effet, dans ce cas, le code correcteur d'erreur permet souvent de corriger l'erreur introduite dans l'instruction I; ou dans la donnée D; de sorte que malgré la présence de telles cireurs, la fonction sécurisée continue de s'exécuter correctement. [0195] L'utilisation du code ECC, ; permet de détecter plus rapidement une erreur dans le cryptogramme CI? ou CD:t ou dans le code MAC; que si seul le code MAC; était utilisé pour cela. L'utilisation du code ECQ; permet donc d'accélérer l'exécution du code binaire. [0196] L'utilisation d'un code correcteur d'erreur pour le code ECCL; permet de rendre le procédé revendiqué plus robuste vis-à-vis des attaques par injection de fautes dans la 33 mémoire 4 ou dans le support 6. En effet, dans ce cas, le code correcteur d'erreur permet souvent de corriger le cryptogramme CI,* ou CD,* ou le code MAC, de sorte que malgré la présence de telles erreurs, la fonction sécurisée s'exécute correctement. 34 [Revendication 1] REVENDICATIONSProcédé d'exécution d'un code binaire d'une fonction sécurisée par un microprocesseur, ce procédé comportant les étapes suivantes : a) l'enregistrement (150, 194) dans une mémoire d'une ligne de code, cette ligne de code comportant un cryptogramme du code et une première étiquette d'intégrité permettant de vérifier l' intégrité de la ligne de code, h) l'obtention (150, 290), par le microprocesseur, d'un premier pointeur contenant l'adresse à laquelle est enregistrée cette ligne de code, puis c) l'exécution, par le microprocesseur, d'une instruction de lecture de cette ligne de code à l'aide du premier pointeur et, pour cela, l'exécution des opérations suivantes par le microprocesseur : cl) le chargement (164, 264) du premier pointeur dans un registre du microprocesseur, c2) le chargement (166, 266) de la ligne de code enregistrée à l'adresse contenue dans le premier pointeur, puis c3) la vérification (176, 184, 276, 284) de l'intégrité de la ligne de code chargée, cette vérification comportant la construction d'une seconde étiquette d'intégiité à partir du cryptogramme contenu dans la ligne de code chargée, puis la comparaison de cette seconde étiquette d'intégrité à la première étiquette d'intégrité contenue dans la ligne de code chargée, puis c4) lorsque la seconde étiquette d'intégrité ne correspond pas à la première étiquette d'intégrité, c'est-à-dire que la vérification de l'intégrité de la ligne de code chargée échoue, le microprocesseur déclenche (172) systématiquement le signalement d'une faute d'exécution, et c5) lorsque la seconde étiquette d'intégrité correspond à la première étiquette d'intégiité, c'est-à-dire que la ligne de code chargée est intègre, le cryptogramme du code est déchiffré (178, 278) pour obtenir un code en clair et le déclenchement d'une faute d'exécution est inhibé ; caractérisé en ce que : - l'obtention (150, 290) du premier pointeur comporte l'obtention d'un premier pointeur comprenant : - une première plage de bits contenant l'adresse de la ligne de code, et - une seconde plage différente de bits contenant un identifiant du premier pointeur, l'identifiant de ce premier pointeur permettant 35 [Revendication 2] [Revendication 3] [Revendication 4] d'identifier de façon unique cc premier pointeur parmi un ensemble contenant plusieurs pointeurs différents mis en oeuvre lors de la même exécution du code binaire par ce microprocesseur, - l'enregistrement (150, 194) de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle la première étiquette d'intégrité est construite ou chiffrée à l'aide de l'identifiant du premier pointeur, - lors du chargement (166, 266) de la ligne de code, c'est l'adresse contenue dans la première plage de bits du premier pointeur chargé qui est utilisée et l'identifiant du premier pointeur contenu dans la seconde plage de bits n'est pas utilisé, - lors de la vérification (176, 184, 276, 284) de l'intégrité de la ligne de code chargée, la seconde étiquette d'intégrité est construite, en plus, en utilisant l'identifiant du premier pointeur contenu dans la seconde plage de bits du premier pointeur chargé, de sorte que si un second pointeur, différent du premier pointeur, est utilisé à la place du premier pointeur pour lire ou écrire cette ligne dc code, la vérification de l'intégrité de la ligne de code échoue. Procédé selon la revendication 1, dans lequel : - l'enregistrement (150, 194) de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle le cryptogramme est construit à l'aide de l'identifiant du premier pointeur contenu dans la seconde plage de bits, et - lors du déchiffrement (178, 278) du cryptogramme du code, le cryptogramme est déchiffré en utilisant l'identifiant de pointeur contenu dans la seconde plage de bits du premier pointeur chargé. Procédé selon l'une quelconque des revendications précédentes, dans lequel : - l'enregistrement (150, 194) de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle la première étiquette d'intégrité est aussi construite ou chiffrée à l'aide de l'adresse contenue dans la première plage de bits du premier pointeur, et - lors de la vérification (176, 184, 276, 284) de l'intégrité de la ligne de code chargée, la seconde étiquette d'intégrité est construite, en plus, en utilisant l'adresse contenue dans la première plage de bits du premier pointeur chargé. Procédé selon l'une quelconque des revendications précédentes, dans lequel : 36 [Revendication 5] [Revendication 6] [Revendication 7] - l'enregistrement (150, 194) de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle le cryptogramme est aussi construit à l'aide d'une clé secrète indépendante de l'identifiant du premier pointeur et de l'adresse contenue dans cc premier pointeur, et - lors du déchiffrement (178, 278) du cryptogramme, le cryptogramme est aussi déchiffré en utilisant cette clé secrète stockée dans une mémoire sécurisée du microprocesseur avant le début de l'exécution du code binaire parce microprocesseur. Procédé selon l'une quelconque des revendications précédentes, dans lequel l'obtention (150, 290) du premier pointeur comporte l'obtention d'un premier pointeur dont la taille, en nombre de bits, est égale à la taille d'une adresse, c'est-à-dire au nombre de bits maximal que peut contenir une adresse transférée du microprocesseur jusqu'à la mémoire par l'intermédiaire d'un bus d'adresse. Procédé selon l'une quelconque des revendications précédentes, dans lequel l'enregistrement (194) de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle le code est une donnée et l'étape a) comporte, en réponse à l'exécution, par le microprocesseur, d'une instruction d'écriture de cette donnée dans la mémoire à l'adresse contenue dans le premier pointeur : - la construction (192) de la ligne de code comportant le cryptogramme de la donnée et la première étiquette d'intégrité construite ou chiffrée à l'aide de l'identifiant du premier pointeur contenu dans sa seconde plage de bits, puis - l'enregistrement (194) de la ligne de code ainsi construite à l'adresse contenue dans la première plage de bits du premier pointeur. Procédé selon la revendication 6, dans lequel l'étape b) précède l'étape a) et l'étape b) comporte : bl) l'exécution (290) par le microprocesseur d'une instruction d'allocation dynamique d'une zone mémoire dans la mémoire, cette instruction d'allocation étant contenue dans le code binaire de la fonction sécurisée, puis b2) en réponse : - la réservation dans la mémoire, d'une zone libre d'une taille prédéterminée, dans laquelle le microprocesseur peut écrire et lire des lignes de codes, et - la génération du premier pointeur qui contient, dans sa première plage de bits, une adresse de la zone mémoire réservée et dans sa seconde 37 [Revendication 8] [Revendication 9] [Revendication 10] [Revendication 11] [Revendication 12] plage de bits l'identifiant du premier pointeur. Procédé selon la revendication 7, dans lequel en réponse à l'exécution (290), par le microprocesseur, d'une instruction de libération de la zone de mémoire allouée vers laquelle le premier pointeur pointe, l'identifiant du premier pointeur est modifié et/ou le contenu de cette zone de mémoire est réécrit avec des valeurs différentes. Procédé selon l'une quelconque des revendications précédentes, dans lequel l'opération cl ) (164) comporte : - l'exécution, par le microprocesseur, d'une instruction de chargement, à partir de la mémoire, d'une ligne de donnée contenant un cryptogramme du premier pointeur, puis - le déchiffrement du cryptogramme du premier pointeur pour obtenir le premier pointeur en clair. Procédé selon la revendication 9, dans lequel la ligne de donnée contenant le cryptogramme du premier pointeur est construite de la même manière que la ligne de code enregistrée à l'adresse contenue dans cc premier pointeur mais en remplaçant l'identifiant du premier pointeur par une valeur nulle. Procédé selon l'une quelconque des revendications précédentes, dans lequel l'enregistrement (150, 152) de la ligne de code comporte l'enregistrement d'une ligne de code dans laquelle le code est la première instruction exécutable d'une routine appelée par le microprocesseur et le procédé comporte : - l'exécution (290), par le microprocesseur, d'une instruction (l'appel de cette routine, puis - en réponse, l'étape b) comporte le chargement (264) du premier pointeur à partir d'une table pré-enregistrée associant un identifiant de cette routine au premier pointeur, puis - pour chaque ligne (l'instruction de la routine, l'exécution de l'opération c3) (276) en utilisant à chaque fois l'identifiant du premier pointeur chargé pour construire la seconde étiquette d'intégrité. Code binaire d'une fonction sécurisée apte à être exécuté par un microprocesseur, en mettant en oeuvre un procédé d'exécution conforme à l'une quelconque des revendications précédentes, dans lequel le code binaire comporte : - une ligne de code comportant le cryptogramme du code et une première étiquette d'intégrité permettant de vérifier l'intégrité de la ligne de code ; 38 [Revendication 13] [Revendication 14] - un premier pointeur contenant l'adresse à laquelle est enregistrée la ligne de code, - une instruction de lecture de la ligne de code à l'aide du premier pointeur qui, lorsqu'elle est exécutée par le microprocesseur, déclenche l'exécution des opérations suivantes par le microprocesseur : cl ) le chargement du premier pointeur dans un registre du microprocesseur, c2) le chargement de la ligne de code enregistrée à l'adresse contenue dans le premier pointeur, puis c3) la vérification de l'intégrité de la ligne de code chargée, cette vérification comportant la construction d'une seconde étiquette d'intégrité à partir du cryptogramme contenu dans la ligne de code chargée, puis la comparaison de cette seconde étiquette d'intégrité à la première étiquette d'intégrité contenue dans la ligne de code chargée, puis c4) lorsque la seconde étiquette d'intégrité ne correspond pas à la première étiquette d'intégrité, c'est-à-dire que la vérification de l'intégrité de la ligne de code chargée échoue, le microprocesseur déclenche systématiquement le signalement d'une faute d'exécution, et c5) lorsque la seconde étiquette d'intégrité correspond à la première étiquette d'intégrité, c'est-à-dire que la ligne de code chargée est intègre, le cryptogramme du code est déchiffré pour obtenir un code en clair et le déclenchement d'une faute d'exécution est inhibé ; caractérisé en ce que : - le premier pointeur comprend : - une première plage de bits contenant l'adresse de la ligne de code, et - une seconde plage différente de bits contenant un identifiant du premier pointeur, l'identifiant de ce premier pointeur permettant d'identifier de façon unique ce premier pointeur parmi un ensemble contenant plusieurs pointeurs différents mis en oeuvre lors de la même exécution du code binaire par ce microprocesseur, et - la première étiquette d'intégrité est construite ou chiffrée à l'aide de l'identifiant du premier pointeur. Support d'enregistrement d'informations, lisible par un microprocesseur, caractérisé en ce que ce support d'enregistrement d'information comporte un code binaire conforme à la revendication 12. Microprocesseur (2) pour la mise en oeuvre d'un procédé conforme à l'une quelconque des revendications 1 à 11, ce microprocesseur étant configuré pour exécuter les étapes suivantes : 39 a) l'enregistrement dans une mémoire d'une ligne de code, cette ligne de code comportant un cryptogramme du code et une première étiquette d'intégrité permettant de vérifier l'intégrité de la ligne de code, h) l'obtention, par le microprocesseur, d'un premier pointeur contenant l'adresse à laquelle est enregistrée cette ligne de code, puis c) l'exécution, par le microprocesseur, d'une instruction de lecture de cette ligne de code à l'aide du premier pointeur et, pour cela, l'exécution des opérations suivantes par le microprocesseur : cl ) le chargement du premier pointeur dans un registre du microprocesseur, c2) le chargement de la ligne dc code enregistrée à l'adresse contenue dans le premier pointeur, puis c3) la vérification de l'intégrité de la ligne dc code chargée, cette vérification comportant la construction d'une seconde étiquette d'intégrité à partir du cryptogramme contenu dans la ligne de code chargée, puis la comparaison de cette seconde étiquette d'intégrité à la première étiquette d'intégrité contenue dans la ligne de code chargée, puis c4) lorsque la seconde étiquette d'intégrité ne correspond pas à la première étiquette d'intégrité, c'est-à-dire que la vérification de l'intégrité de la ligne de code chargée échoue, le microprocesseur déclenche systématiquement le signalement d'une faute d'exécution, et c5) lorsque la seconde étiquette d'intégrité con-espond à la première étiquette d'intégrité, c'est-à-dire que la ligne de code chargée est intègre, le cryptogramme du code est déchiffré pour obtenir un code en clair et le déclenchement d'une faute d'exécution est inhibé ; caractérisé en ce que le microprocesseur est également configuré pour : - lors de l'obtention du premier pointeur, obtenir un premier pointeur comprenant : - une première plage de bits contenant l'adresse de la ligne de code, et - une seconde plage différente de bits contenant un identifiant du premier pointeur, l'identifiant de ce premier pointeur permettant d'identifier de façon unique ce premier pointeur parmi un ensemble contenant plusieurs pointeurs différents mis en oeuvre lors de la même exécution du code binaire par ce microprocesseur, - lors de l'enregistrement de la ligne de code, l'enregistrement d'une ligne de code dans laquelle la première étiquette d'intégrité est construite ou chiffrée à l'aide de l'identifiant du premier pointeur, - lors du chargement de la ligne de code, c'est l'adresse contenue dans la 40 [Revendication 15] première plage de bits du premier pointeur chargé qui est utilisée et l'identifiant du premier pointeur contenu dans la seconde plage de bits n'est pas utilisé, - lors de la vérification de l'intégrité de la ligne dc code chargée, la seconde étiquette d'intégrité est construite, en plus, en utilisant l'identifiant du premier pointeur contenu dans la seconde plage de bits du premier pointeur chargé, de sorte que si un second pointeur, différent du premier pointeur, est utilisé à la place du premier pointeur pour lire ou écrire cette ligne de code, la vérification de l'intégrité de la ligne dc code échoue. Compilateur apte à transformer automatiquement un code source d'une fonction sécurisée en un code binaire de cette fonction sécurisée, caractérisé en cc que le compilateur est apte à transformer automatiquement le code source en un code binaire conforme à la revendication 12, cc compilateur étant configure à cet effet pour générer pour au moins un code contenu dans le code source : - une ligne de code comportant le cryptogramme de cc code et une première étiquette d'intégrité permettant de vérifier l'intégrité de la ligne de code ; - un premier pointeur contenant l'adresse à laquelle est enregistrée la ligne de code, - une instruction de lecture de la ligne de code à l'aide du premier pointeur qui, lorsqu'elle est exécutée par le microprocesseur, déclenche l'exécution des opérations suivantes par le microprocesseur : cl) le chargement du premier pointeur dans un registre du microprocesseur, c2) le chargement de la ligne de code enregistrée à l'adresse contenue dans le premier pointeur, puis c3) la vérification de l'intégrité de la ligne de code chargée, cette vérification comportant la construction d'une seconde étiquette d'intégrité à partir du cryptogramme contenu dans la ligne de code chargée, puis la comparaison de cette seconde étiquette d'intégrité à la première étiquette d'intégrité contenue dans la ligne de code chargée, puis c4) lorsque la seconde étiquette d'intégrité ne correspond pas à la première étiquette d'intégrité, c'est-à-dire que la vérification de l'intégrité de la ligne de code chargée échoue, le microprocesseur déclenche systématiquement le signalement d'une faute d'exécution, et c5) lorsque la seconde étiquette d'intégrité correspond à la première 41 étiquette d' intégrité, c'est-à-dire que la ligne de code chargée est intègre, le cryptogramme du code est déchiffré pour obtenir un code en clair et le déclenchement d'une faute d'exécution est inhibé ; caractérisé en ce que : - le premier pointeur comprend : - une première plage de bits contenant l'adresse de la ligne de code, et - une seconde plage différente de bits contenant un identifiant du premier pointeur, l'identifiant de ce premier pointeur permettant d'identifier de façon unique cc premier pointeur parmi un ensemble contenant plusieurs pointeurs différents mis en oeuvre lors de la même exécution du code binaire par ce microprocesseur, et - la première étiquette d'intégrité est construite ou chiffrée à l'aide de l'identifiant du premier pointeur.