La cohérence de la mémoire cache depuis la partie reconfigurable dans un SoC complexe hétérogène
Dans un SoC complexe hétérogène, l’unité SCU maintient la cohérence de la mémoire cache entre les différents cœurs du processeur (comme cela est détaillé dans la section chap1-1.2.5). L’unité SCU arbitre les requêtes vers la mémoire cache L2 des cœurs du processeur qui sont issues des interfaces maîtres des accélérateurs matériels connectés à l’interface ACP (Accelerator Coherency Port). Une interface maître connectée à l’interface ACP peut lire la mémoire cohérente directement à partir des mémoires caches L1 et L2, mais ne peut pas écrire directement dans le cache L1. Les scénarios possibles de lecture et d’écriture d’une interface maître ACP sont les suivants : Requête de lecture avec des données cohérentes dans la mémoire cache L1 : l’interface maître ACP obtient les données directement de la mémoire cache L1. Requête de lecture avec des données cohérentes dans la mémoire cache L2 : la demande est mise en file d’attente dans le SCU et la requête est transmise à la mémoire cache L2. Requête de lecture avec des données cohérentes qui n’existent pas dans les mémoires cache L1 et L2 : selon l’état précédant des données, les mémoires cache L1 ou L2 peuvent lancer une requête pour obtenir les données demandées à la mémoire RAM ou bien à la mémoire principale avec la mise en attente de la requête initiale jusqu’à la disponibilité des données. Requête d’écriture avec des données cohérentes dans le cache L1: dans un premier temps les données au niveau de la mémoire cache L1 sont marquées comme non valides et les lignes de cache sont expulsées vers la mémoire cache L2. Puis, dans un second temps, la requête d’écriture est planifiée dans le SCU et les données sont écrites dans la mémoire cache L2. Enfin, lorsque le processeur accède à la même adresse mémoire que celle visée par la requête, un échec se produit dans la mémoire cache L1. Requête d’écriture avec des données cohérentes dans la mémoire cache L2 : la requête est planifiée dans le SCU puis les données sont écrites dans la mémoire cache L2. Chapitre 4 : Exploitation malicieuse du mécanisme de cohérence de la mémoire cache dans un SoC complexe hétérogène 66 Requête d’écriture avec des données cohérentes qui ne sont pas dans les mémoires cache L1 et L2: la requête est destinée directement au contrôleur de la mémoire externe. Ces scénarios sont contrôlés par les signaux AxCache[3:0] et AxUser[4:0] de l’interface ACP qui sont détaillés dans la section suivante. 1.1. Les signaux AxCache[3:0] et AxUser[4:0] Les signaux AxCache[3:0] et AxUser[4:0] (pour chacun des signaux x = R pour lecture ou x = W pour écriture) de l’interface ACP permettent de contrôler la cohérence d’une requête vers les mémoires cache depuis la partie reconfigurable. Le signal AxUser[4:0] est composé du bit AxUser[0] qui est un bit de partage et des bits AxUser[4:1] qui contrôlent la stratégie d’écriture (Write-back [37], Write-through, … etc) adoptée par la requête. Les bits AxUser[4:0] ne sont pas interprétés par l’unité SCU et ils sont transmis directement au contrôleur de la mémoire cache L2 qui les utilise en cas d’une mémoire cache configurée en mode exclusif. Le signal AxCache[3:0] contrôle aussi la stratégie d’écriture adoptée par la requête. Il est composé des bits suivants : Le bit AxCache[0] qui contrôle la mise en mémoire tampon (Bufferable, B), Le bit AxCache[1] qui contrôle la mise en mémoire cache (Cacheable, C), Le bit AxCache[2] qui contrôle l’allocation sur lecture (Read-Allocate, RA), Le bit AxCache[3] qui contrôle l’allocation sur écriture (Write-Allocate, WA). Selon les recommandations de ARM [68], le bit AxUser[0] et le bit AxCache[1] doivent être valides pour une requête ACP cohérente. 1.2. Le signal AxPort[2:0] Le signal AxPROT[2:0] (pour lequel x = R pour lecture et x = W pour écriture) est un signal d’autorisation d’accès qui permet de protéger les interfaces esclaves des IP sécurisées contre les requêtes malveillantes. Il est composé des bits suivants : Le bit AxPROT[0] qui contrôle le niveau du privilège d’une requête, Le bit AxPROT[1] qui contrôle l’état de sécurité de la requête ACP, Le bit AxPROT[2] qui contrôle l’accès aux données ou aux instructions. Chapitre 4 : Exploitation malicieuse du mécanisme de cohérence de la mémoire cache dans un SoC complexe hétérogène 67 Les interfaces maîtres connectées à l’interface ACP contrôlent le signal AxPROT[2:0], en particulier le bit AxPROT[1] qui transmet l’état de sécurité de la requête à l’interface esclave. Dans un système intégrant la technologie ARM TrustZone, chaque interface maître impose la valeur du bit AxPROT[1], cela peut mettre en danger le système si l’interface maître est exploitée malicieusement par un cheval de Troie. De plus, ce scénario est particulièrement crédible lorsque les interfaces esclave de la partie processeur ne sont pas configurée pour interdire l’accès aux régions sécurisées de la mémoire principale depuis la partie reconfigurable ce qui est souvent le cas. La suite de ce chapitre présente différents types d’attaque exploitant la cohérence de la mémoire cache. 2. Les éléments de l’attaque La section suivante présente les éléments utilisés pour la mise en place des trois attaques présentées à la fin de ce chapitre. Cette section présente tout d’abord les méthodes utilisées pour distinguer l’échec d’un succès d’une requête à la mémoire cache depuis la partie reconfigurable ou depuis la partie processeur. La section présente également les méthodes utilisées pour expulser une ligne de la mémoire cache ciblée par l’attaque. La maîtrise de ces méthodes est indispensable à la réalisation des attaques.
Distinguer un échec d’un succès de la mémoire cache
La première condition pour réussir une attaque visant la mémoire cache consiste à distinguer l’échec d’un succès d’une requête adressée à cette mémoire cache. Cette section présente des méthodes à utiliser pour distinguer l’échec d’un succès depuis la partie reconfigurable ou bien depuis la partie processeur.
Depuis la partie reconfigurable
La méthode présentée dans cette partie se base sur la mesure du temps d’accès à une donnée depuis la partie reconfigurable pour distinguer l’échec d’un succès d’une requête à la mémoire cache. Cette méthode utilise les signaux du bus AXI (détaillés dans la section chap1-1.1) connectant l’interface maître à l’interface ACP pour mesurer le temps d’accès. Mais avant d’utiliser cette méthode, il faut s’assurer que l’interface maître est connectée à l’interface ACP comme cela est indiqué dans la section chap3-1, que les bit AxUser[0] et AxCache[1] soient valides, et que l’unité SCU et le symmetric multiprocessor system (SMP) soient activés. La suite de cette section présente les canaux du bus AXI qui fuitent des informations sur la présence ou pas d’une donnée dans la mémoire cache et la méthode utilisée pour mesurer le temps d’accès. Chapitre 4 : Exploitation malicieuse du mécanisme de cohérence de la mémoire cache dans un SoC complexe hétérogène 68 Durant une requête d’écriture cohérente depuis la partie reconfigurable, l’interface maître envoie l’adresse dans le canal d’adresse d’écriture du bus AXI suivie de la donnée à écrire dans le canal d’écriture de données. Une fois la donnée reçue par l’interface ACP, cette dernière envoie une réponse à la requête à l’interface maître en utilisant le canal d’écriture de réponse. En mesurant le nombre de cycles d’horloge écoulés entre le handshake du canal d’adresse d’écriture et le canal d’écriture de réponse durant une requête d’écriture, on constate que le nombre de cycles d’horloge ne varie pas par rapport à la présence de la donnée dans la mémoire cache L1 ou L2. Donc, il n’est pas possible de distinguer un échec d’un succès lors d’une requête d’écriture. Pour une requête de lecture cohérente depuis la partie reconfigurable, l’interface maître envoie tout d’abord l’adresse à lire dans le canal d’adresse de lecture du bus AXI. Ensuite, si la communication est établie avec l’interface ACP, cette dernière envoie la donnée à l’interface maître en utilisant le canal de lecture de donnée. En mesurant le nombre de cycles d’horloge écoulés entre le handshake du canal d’adresse de lecture et celui du canal de lecture de donnée, le nombre de cycles d’horloge varie selon l’existence ou pas de la donnée dans la mémoire cache L1 ou L2. Il est court, si la donnée réside dans la mémoire cache et il est long dans le cas contraire. Pour distinguer les succès d’un échec d’une requête à la mémoire cache depuis la partie reconfigurable, il suffit donc de compter le nombre de cycles d’horloge entre les deux handshake des deux canaux du bus AXI utilisés dans une requête de lecture. Dans la suite de ce chapitre, l’algorithme 4 est utilisé pour valider les méthodes de mesure de temps et d’expulsion de la ligne de cache introduites dans ce chapitre. L’algorithme effectue en boucle, un accès à l’adresse donnée en entrée, une expulsion de la ligne de cache contenant cette adresse une itération sur deux, et une mesure de temps d’accès à cette adresse. L’algorithme 4 provoque un échec de la mémoire cache toutes les deux itérations en expulsant la ligne de cache. Algorithme 4: Vérification de la méthode utilisée pour distinguer un échec d’un succès Input: adresse for i = nombre_dacces to 0 do Accès(adresse) if !(i%2) then Expulser_ligne_cache (adresse) end if Measure_clock_cycles (Access(adresse)) end for Chapitre 4 : Exploitation malicieuse du mécanisme de cohérence de la mémoire cache dans un SoC complexe hétérogène 69 La méthode utilisée dans la fonction Expulser_ligne_cache est détaillée dans la section chap4-2.2.1 et la méthode utilisée dans la fonction Measure_clock_cycles est celle basée sur la mesure de nombre de cycles d’horloge entre le handshake du canal d’adresse de lecture et le canal de lecture de donnée.