Trusted Execution Environment sur l'exemple d'Intel SGX. Principes de base en termes simples. "Bonjour le monde!"

Cet article s'adresse principalement à un spécialiste novice qui n'est

a commencé à rechercher des méthodes et des moyens d'assurer la sécurité de l'information du code de programme exécutable. Tôt ou tard, tous les développeurs de logiciels et ingénieurs système sont confrontés à une telle tâche, qui s'est produite dans l'un des projets d'Altiriks Systems, dans le cadre duquel il était nécessaire de mettre en œuvre une exécution protégée du code du programme dans un environnement conditionnellement non protégé. À cette fin, en plus des méthodes et moyens de protection des informations déjà bien connus et bien décrits, la technologie Trusted Execution Environment (TEE), rarement utilisée dans les projets russes, ou, parlant en russe, la technologie d'environnements d'exécution fiables, a été choisie. Plus précisément dans cet article, nous avons décidé de décrire un exemple pratique d'utilisation d'enclaves de processeurs Intel pour un environnement d'exécution de code de confiance (Intel Software Guard Extensions ou SGX).



Les environnements d'exécution approuvés ne sont pas uniquement pris en charge par les processeurs d'un fabricant donné. En outre, TEE est pris en charge par un certain nombre de processeurs AMD (Secure Execution Environment, Secure Technology), de processeurs ARM (TrustZone) et de processeurs RISC-V. De plus, TEE est pris en charge par les mainframes modernes IBM Z. Nous avons choisi Intel SGX pour notre exemple car nous pensons qu'au moment d'écrire ces lignes (été 2020) les processeurs Intel sont les plus populaires et disponibles pour les débutants dans l'espace post-soviétique. Pour une liste complète des modèles de processeurs Intel prenant en charge Intel SGX, visitez le site Web d'Intel sous les spécifications des produits Intel (ARK) en sélectionnant la technologie appropriée à rechercher. Et oui, profitez peut-être des émulations Intel SGX à des fins éducatives ou de recherche.Travailler avec plusieurs de ces émulations a révélé un certain nombre de difficultés dans leur mise en place. Vous devez également comprendre que pour de vrais projets de «combat», aucune émulation de technologie basée sur la fonctionnalité de l'appareil n'est, bien entendu, acceptable.



Tous vos commentaires, en particulier avec les commentaires et les ajouts de spécialistes qui ont déjà de l'expérience dans l'utilisation de TEE dans leurs projets, ou avec les questions de ceux qui commencent tout juste à se plonger dans cette technologie, contribuera à une divulgation plus détaillée de ce sujet dans les articles suivants. Merci d'avance!



introduction



La principale question que nous nous posons au début du voyage d'exploration d'environnements d'exécution fiables est la suivante: pouvons-nous faire confiance aux composants d'un système informatique? Et si nous pouvons, comment? Les développeurs, et en particulier les ingénieurs Intel, donnent une réponse sans équivoque à cette question: personne à part Intel lui-même. Qu'est-ce que ça veut dire? Je propose de comprendre cela plus en détail.



Anneaux privilège



Pour des raisons de sécurité, les composants système de tout ordinateur sont divisés en niveaux de privilège. Tous les systèmes modernes basés sur des processeurs Intel et non seulement ont un système d'anneau de privilèges. De l'externe à l'interne, il y a une extension de l'autorité pour le code qui est actuellement traité par le processeur.





Numéro de sonnerie 3. L'anneau externe contient toutes les applications utilisateur que nous utilisons sur l'ordinateur dans la vie quotidienne, elles ont le niveau d'accès le plus bas.

Anneau n ° 2 et n ° 1. Les systèmes d'exploitation et les pilotes de périphérique se trouvent à ces niveaux.

Numéro de sonnerie 0. Mode superviseur. C'est là que se trouve le noyau du système d'exploitation (gestion des périphériques, allocation des ressources entre processus), ainsi que les pilotes système.

Numéro de sonnerie-1. Hyperviseur. Responsable de l'allocation des ressources si plusieurs systèmes d'exploitation fonctionnent sur l'ordinateur en même temps, et est également responsable de leur isolement.

Numéro de sonnerie-2.Mode de gestion du système (SMM - Mode de gestion du système). Gère l'alimentation du système, gère les cartes d'extension.



On peut former de plus en plus d'anneaux pour limiter les pouvoirs des composants de la hiérarchie, créant un système de plus en plus complexe et chargé. Cependant, cela ne fera que faciliter le travail d'un attaquant: plus le système est complexe, plus il est facile d'y trouver des vulnérabilités. Mais comment pouvez-vous fournir une couche de sécurité supplémentaire là où vous en avez besoin? La réponse est un mot.



Enclaves



La tâche principale d'un attaquant est d'obtenir un niveau de privilège qui lui permettrait d'accéder aux ressources système nécessaires. S'il s'agit du secret de l'application victime, alors l'application malveillante a besoin exactement du niveau d'accès responsable du stockage des secrets dans le système. D'où la conclusion que la gestion des secrets applicatifs doit être confiée à l'anneau le plus interne, car l'accès y est le plus difficile de tous. Cependant, cette approche a été quelque peu repensée. Désormais, tous les secrets sont stockés au même niveau avec les applications utilisateur, ainsi que le code qui gère ces secrets sous une condition: personne, absolument personne, à l'exception du processeur, ne peut y accéder. Le programme et les données sont, pour ainsi dire, emballés dans un stockage, dans ce cas, ce stockage est appelé une enclave (Enclave - fermé, verrouillé),la clé dont seul le processeur dispose.





Applications qui fonctionnent avec un environnement de confiance



Plus le système est simple, moins il contient de code, plus il est difficile de l'ouvrir en fonction de failles de sécurité (nous ne parlons pas de systèmes fondamentalement non protégés), nous obtenons un certain axiome: le code qui fonctionne avec un secret doit être aussi simple et court que possible. Il n'est pas pratique de regrouper tout le code du programme dans une enclave, par conséquent, une application utilisant des enclaves doit être divisée en deux parties: «fiable» et «non fiable». Celui de confiance stocke les enclaves (il peut y en avoir plusieurs) et celui qui n'est pas de confiance stocke le code principal du programme.



La partie de confiance est un ensemble de fonctions et de procédures appelées ECALL (Enclave Call). La signature de ces fonctions doit être écrite dans un fichier d'en-tête spécial, et leur implémentation dans le fichier de code source. En général, l'approche est similaire à celle que nous utilisons dans l'écriture habituelle des en-têtes, cependant, dans ce contexte, un langage spécial de type C EDL (Enclave Definition Language) est utilisé. Il est également nécessaire d'écrire des prototypes de ces fonctions qui peuvent être appelées de l'intérieur de l'enclave, ces fonctions sont appelées OCALL (Outside Call). Les prototypes sont écrits dans le même en-tête que les fonctions ECALL, et l'implémentation, contrairement à ECALL, est écrite en conséquence dans la partie non approuvée de l'application.

Les codes approuvés et non approuvés sont étroitement couplés par certification utilisant le protocole Diffie-Hellman. Le processeur est responsable de la procédure de signature, où la clé d'échange d'informations est stockée, qui est mise à jour chaque fois que le système est redémarré. Le contenu des enclaves est stocké dans la mémoire partagée utilisée par les applications utilisateur, mais le stockage est crypté. Seul le processeur peut décrypter le contenu. Dans un monde idéalisé, où le code de l'enclave est écrit sans un seul bogue et où tout le matériel fonctionne exactement comme le fabricant l'a prévu et rien d'autre, nous obtiendrions un système universel et complètement sécurisé. Le principal avantage de ce système est l'exécution de la partie secrète sur le même processeur où tous les autres programmes, y compris les programmes utilisateurs, sont exécutés.



Cependant, ces dernières années, un grand nombre de vulnérabilités microarchitecturales de processeurs modernes sont apparues devant un large public, permettant d'accéder à l'intérieur de l'enclave: Foreshadow (vulnérabilité de classe Spectre), SGAxe, Zombieload, CacheOut et bien d'autres. Il n'y a aucune garantie que cette liste ne sera pas reconstituée avec une autre vulnérabilité matérielle sérieuse, dont le correctif logiciel ne peut pas être appelé un «correctif» logiciel. Peut-être vivrons-nous pour voir le moment où une architecture de processeur complètement nouvelle sera présentée au monde, dans laquelle toutes les lacunes seront corrigées, mais pour l'instant, cela vaut la peine de parler de ce que nous avons sous la main. Et à portée de main, nous avons un outil polyvalent et puissant qui augmente considérablement la sécurité des systèmes actuels. Élever tellementqu'il soit implémenté d'une manière ou d'une autre dans des milliards d'appareils à travers le monde: des montres intelligentes, des smartphones aux énormes grappes informatiques.



Bonjour le monde!



Passons de la théorie à la pratique. Écrivons un petit programme qui implémente la tâche déjà canonique: imprimez la chaîne "Hello world!" Dans cette interprétation, nous indiquerons également l'endroit d'où le message sera envoyé.



Vous devez d'abord télécharger et installer le SDK pour travailler avec SGX à partir du site officiel. Pour télécharger, vous devez suivre une procédure d'inscription simple. Lors de l'installation, il vous sera demandé d'intégrer le package de développement dans la version de VS disponible sur votre ordinateur, faites-le. Tout est prêt pour la mise en œuvre réussie du premier projet utilisant SGX.





Lancez VS et créez un projet Intel SGX.





Nous choisissons un nom pour le projet et pour la solution et attendons "suivant".



Ensuite, vous serez invité à sélectionner une configuration de projet, ne changez rien, laissez les valeurs initialement proposées.







Ajoutez ensuite un autre projet à la solution créée: une application console C ++ classique.

En conséquence, l'image suivante doit apparaître dans la boîte de dialogue des projets:







Ensuite, vous devez lier l'enclave à la partie non approuvée. Faites un clic droit sur le projet "Pièce non approuvée".







Ensuite, vous devez modifier certaines propriétés des projets.



image






Cela doit être fait pour que le programme fonctionne correctement. Nous répétons les étapes pour les deux projets.



Il est également nécessaire d'indiquer le projet principal dans les propriétés de la solution.





Voilà, notre programme est prêt à être mis en œuvre.



Ce programme aura 3 fichiers avec lesquels nous travaillerons: Enclave.edl (le même en-tête), Enclave.cpp (l'implémentation ECALL est précisée), Untrusted Part.cpp (le fichier principal du projet est la partie non approuvée). Mettons le



code suivant dans des fichiers:



Untusted Part.cpp:



#define ENCLAVE_FILE "Enclave.signed.dll" //,     

#include "sgx_urts.h" // ,           
#include "Enclave_u.h" //   
#include "stdio.h"

void print_string(char* buf) //OCALL     -   
{
	printf("ocall output: %s\n", buf);
}

int main()
{
	sgx_enclave_id_t eid; // id ,      ,    id
	sgx_status_t ret = SGX_SUCCESS; //        
	sgx_launch_token_t token = { 0 }; //    
	int updated = 0; //      
	const int BUF_LEN = 30; //  ,     

	ret = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, &token, &updated, &eid, NULL); //  

	if (ret != SGX_SUCCESS)
	{
		printf("Failed to create enclave with error number: %#x\n", ret); //  
		return 0;
	}
	char buf[BUF_LEN]; //  ,      

	enclaveChat(eid, buf, BUF_LEN); // ECALL  

	printf("\noutput form main(): %s\n", buf); //  
}


Enclave.edl:



enclave {
    from "sgx_tstdc.edl" import *;

    trusted {
        /* define ECALLs here. */
        public void enclaveChat([out, size=len] char* str, size_t len);
        /*   ,    . OUT -   ,   
                , out     .
           ,          ,
                 .
        */
    };

    untrusted {
        /* define OCALLs here. */
        void print_string([in, string] char* buf); //  ,     
    };
};


Enclave.cpp:



#include "Enclave_t.h"

#include "sgx_trts.h"
#include <cstring>

void enclaveChat(char* str, size_t len)
{
	char* secret = "Hello from better place"; //   

	memcpy(str, secret, len); //   ,  

	print_string(secret); // OCALL-  
}


Appuyez sur f7 - générez la solution, puis ctrl + f5 pour l'exécuter.



Si vous obtenez une erreur comme celle-ci:





assurez-vous qu'Intel SGX est activé dans le BIOS: Bios: Security / IntelSGX / Enabled.



Au cas où il n'y aurait pas d'erreur, et devant l'écran de la console, vous avez vu les lignes suivantes:





... félicitations, votre premier programme avec la technologie Intel SGX est prêt. J'espère que les commentaires dans le code étaient complets pour la compréhension, sinon, vous pouvez toujours poser des questions ici dans les commentaires ou dans les messages privés.



All Articles