Saviez-vous que votre Android n’est pas le seul OS dans votre smartphone ? À côté et bien caché s’exécute un environnement dédié à la sécurité plus communément appelé TEE. Partons à l’aventure et découvrons ce petit monde qui discrètement vous protège.
Un TEE (Trusted Execution Environment) est défini comme un environnement de sécurité restreint s’exécutant en parallèle d’un système principal tel qu’Android ou Windows, nommé REE (Rich Execution Environment). Son objectif est de fournir des services de sécurité tels que la gestion de clefs cryptographiques ou la gestion de procédures d’authentification. Dans un premier temps, il a principalement été utilisé pour sécuriser la diffusion de contenu vidéo premium et la gestion des droits associés (DRM). Il permettait de garantir aux ayants droit que le REE ne pouvait pas garder une copie en clair du film téléchargé, car seul un flux chiffré y transitait, la clef de déchiffrement n'étant détenue que par le TEE. Son utilisation s'est ensuite étendue aux mécanismes d’authentification ou encore aux plateformes de paiement bancaire. En tant que zone de confiance, le TEE est construit autour d’une faible TCB (Trusted Code Base) pouvant être auditée et même certifiée sous Critères Communs ; même si la pratique nous montre que les OS pour TEE peuvent se révéler être de réels systèmes complexes. Il existe différentes technologies pour mettre en place un TEE : Apple Secure Enclave, Intel SGX ou encore ARM TrustZone. C’est à ce dernier que cet article est consacré.
1. Introduction à la technologie ARM TrustZone
1.1 Une séparation logicielle et matérielle
TrustZone est une extension matérielle pour la technologie ARM ayant pour objectif la mise en place de ces deux environnements d’exécution, TEE et REE, sur un même système sur puce (SoC). Pour rappel, un SoC est un système complet embarqué sur une seule puce, pouvant comprendre de la mémoire, un ou plusieurs microprocesseurs, des périphériques d'interface, ainsi que d’autres potentiels composants. Dans cette section, vous allez découvrir comment l’architecture matérielle permet de restreindre les droits d’accès du REE sur ce SoC tandis que le TEE jouit de tous les droits d’accès au système. L’intérêt principal est d’apporter un environnement de confiance dont les garanties de sécurité peuvent être assurées (démarrage sécurisé, confidentialité des données traitées...), même lors d’une compromission totale du REE.
Comme vous allez le découvrir, la technologie TrustZone ne se limite pas seulement au CPU : elle s’étend aussi au périmètre du SoC. Ainsi des composants (régions de la mémoire RAM, périphériques, accélérateurs cryptographiques…) peuvent être dédiés au TEE ou partagés avec le REE, et cela statiquement à la création du SoC ou dynamiquement pendant l’exécution.
Cette technologie de cloisonnement a été adaptée aux processeurs applicatifs Arm Cortex-A (mobiles, set-top-box, et depuis peu dans les voitures...) et récemment pour les processeurs embarqués Arm Cortex-M (utilisé pour des équipements type IOT). Dans le cadre de cet article, nous nous focaliserons sur les plateformes mobiles et plus précisément sur les smartphones Android. En effet, l’ensemble des SoC utilisés pour la construction des smartphones récents intègre TrustZone et embarque un TEE, rendu obligatoire par Google pour la protection des clefs de chiffrement.
Rentrons un peu plus dans les détails et intéressons-nous à la traduction technique de cette isolation.
Tout d’abord, regardons le CPU d’un peu plus près. Par défaut, un processeur ARM possède 3 niveaux d’exécution (appelés Exception Levels – EL) : EL0 étant le niveau le moins privilégié pour les processus utilisateur, EL1 pour le noyau et EL2 pour l’hyperviseur. Avec l’extension TrustZone, le CPU se voit ajouter un nouveau niveau EL3 appelé Secure Monitor ainsi que deux états d’exécution : Secure (S) et Non-Secure (NS). En mode Non-Secure, les trois niveaux EL0-2 sont conservés, en revanche dans le mode Secure seuls EL0 et EL1 subsistent. Ces deux modes se traduisent ainsi par des registres supplémentaires dans le CPU et des gestions d’accès liés à ces niveaux. Ainsi, il est tout à fait possible de lancer un système d’exploitation avec des applications non privilégiées au sein du mode Secure.
Figure 1 : Niveaux d’exception Armv8 avec extension TrustZone.
Le passage du mode NS au mode S, ou inversement s’effectue lors de l’exécution d’une instruction SMC (Secure Monitor Call) ou lors d’une exception matérielle (IRQ, FIQ). Tout passage traverse obligatoirement un composant logiciel, appelé Secure Monitor, s’exécutant en EL3 (niveau d’exécution le plus privilégié), et ainsi responsable de la sauvegarde et restauration des registres et du filtrage de certains accès. ARM fournit d’ailleurs une implémentation de référence pour ce composant : Arm Trusted Firmware [ATF]. La gestion des SMC et des exceptions est configurée par le Secure Monitor pendant la phase de démarrage par la création et l’enregistrement d’une table de pointeurs vers les gestionnaires respectifs (registre MVBAR - Monitor Vector Base Address Pointer).
À noter que la répartition des niveaux d’exception sur Armv7 est différente de Armv8 telle que représentée dans la figure 1, mais les concepts restent les mêmes.
Avec Armv8.4-A, un nouveau niveau voit son apparition : un Secure EL2 pour répondre au besoin d'avoir plusieurs OS en TrustZone (ce qui est déjà le cas aujourd’hui, mais compliqué à intégrer).
1.2 Propagation du bit NS
La technologie TrustZone ne se limite pas seulement au CPU : elle s’étend aussi au périmètre du SoC, et là réside la principale différence entre TrustZone et virtualisation. En effet, l’état courant du CPU au moment de l’exécution (Secure ou Non-Secure) est propagé sur le bus interne (AXI) jusqu’aux différents contrôleurs (RAM, APB, I2C…). Chaque transaction sur ce bus embarque un bit supplémentaire décrivant le type de transaction, Secure ou Non-Secure (AxProt [1]). Ces derniers peuvent ainsi adapter leur comportement en fonction de l’origine de la commande. Toute transaction émanant du CPU, ou d’autres composants, qui s’exécute en mode NS génèrera des requêtes NS sur le bus, tandis que le mode Secure pourra choisir le type de requêtes à envoyer, S ou NS.
Pour dédier des sections de mémoire RAM au mode Secure, un composant particulier est ajouté en amont du contrôleur RAM, typiquement un ARM TZASC (TrustZone Address Space Controlleur) ou toute autre déclinaison propriétaire de ce pare-feu. Ce composant filtre les accès NS à certaines plages mémoire configurées comme Secure. Ces plages pouvant être statiques, intégrées dans le composant lui-même, ou mises en place lors de la phase de boot, voire même à la demande dans certains cas d’usage.
Généralement, lors de la phase d’intégration, une zone de mémoire physique est dédiée au TEE et reste ainsi statiquement dédiée. Il est important que cette zone reste la même. Prenons le cas d’une warm boot attack : si elle changeait à chaque démarrage de l’appareil, un attaquant serait en mesure de scanner l’intégralité de la mémoire qui lui est accessible et ainsi retrouver des secrets laissés par la dernière exécution du TEE.
Afin de compléter ce cloisonnement mémoire, les différents caches du CPU ont dû être adaptés. Chaque ligne de cache possède désormais un bit décrivant à quel état elle appartient. En cas d’accès depuis l’autre état, la ligne est ignorée « cache miss », et remplacée par le résultat du nouvel accès en RAM. Cet effet observable est d’ailleurs à l’origine de certaines attaques par canaux auxiliaires, comme décrit dans la section 4 de cet article.
Les périphériques branchés sur l’APB (Advanced Peripheral Bus) peuvent également être filtrés (e.g. horloges et minuteurs, boutons physiques). Certains peuvent être dédiés Secure à la construction du SoC ou gérés dynamiquement.
Figure 2 : Exemple d’un partage TEE/REE dans un SoC.
La communication entre les deux modes par SMC reste lente et limitée à quelques dizaines d’octets. Le monde Secure étant privilégié, il est libre d’accéder à tout l’espace mémoire ; ainsi des canaux d’échanges de données performants peuvent être créés via des espaces de mémoire partagée. Pour s’assurer que le TEE ne modifie pas ses propres données quand le REE fournit des plages d’adresses physiques à partager, le monde Secure réalise des accès NS par une configuration spéciale. Comme ça, pas d’erreurs !
Pour plus d’informations techniques sur la technologie, [Arm-TZ] reste une bonne référence.
1.3 TrustZone Vs Virtualisation
Au début de l’article, nous avons présenté les niveaux d’exception d’un processeur ARM et la présence d’un niveau hyperviseur. Mais pourquoi l’ajout de TrustZone si un mécanisme d’isolation était déjà présent ?
TrustZone et Virtualisation sont deux technologies qui in fine pourraient atteindre les mêmes objectifs de sécurité à savoir la mise en place d’un TEE résistant aux attaques logicielles via exploitation du REE ou de composants du SoC (l’hyperviseur pouvant se protéger dans ce cas grâce à la présence d’une SMMU, déclinaison ARM de l’IOMMU).
Toutefois elles ne rentrent pas en concurrence, mais servent des propos différents et ne s’intègrent pas aux mêmes moments du cycle de construction de l’appareil. Le TEE peut être fourni avec le SoC de façon à proposer ses services au futur OS principal qui sera ajouté par le constructeur d’appareil. Ce dernier peut alors ajouter de nouveaux services au TEE ou à un hyperviseur afin de renforcer la sécurité de son système principal. Par exemple, sur les smartphones Samsung Galaxy récents, certains modules Knox peuvent être assurés par l’hyperviseur ou en TEE suivant le type de modèle.
2. Objectifs d’un TEE
2.1 Intégration d’un TEE sur smartphone
Il existe une variété de systèmes d’exploitation destinés à un TEE, appelés TEE-OS, tels que Trustonic Kinibi, Qualcomm QSEE, Huawei iTrustee ou encore Linaro OPTEE ou Nvidia TLK (deux TEE open source). Tous n’ont pas été déployés sur le terrain et aujourd’hui les trois TEE-OS majoritaires restent ceux de Trustonic, Qualcomm et Huawei. Propriétaires à l’origine, Kinibi et iTrustee ont su évoluer pour répondre à un standard commun : GlobalPlatform TEE, présenté dans la section suivante.
Afin d’opérer correctement, ces TEE-OS nécessitent toutefois certains prérequis essentiels sur l’intégration matérielle. En particulier, la présence des éléments suivants :
- la présence d’un mode sécurisé sur le SoC ;
- une procédure de démarrage sécurisée bloquant toute tentative d’installation d’une ancienne version du code ;
- une zone de mémoire dédiée au TEE et constante durant le cycle de vie de l’appareil ;
- une clef matérielle unique par SoC (HUK) injectée lors de la phase de production dans une zone à écriture unique telle que des fusibles eFuse. Le TEE n’ayant généralement pas de zone Flash dédiée‚ elle doit s’appuyer sur le REE pour le stockage de données persistantes. Pour assurer la confidentialité et l’authenticité de ce stockage, un système de fichiers sécurisé basé sur cette clef doit être mis en place ;
- l’absence de mode débogage pour le mode sécurisé sur les appareils de production ;
- un générateur de nombres aléatoires matériel fournissant une source d’entropie suffisante pour assurer la génération de clefs, de vecteurs d’initialisation ou de jetons anti-rejeux ;
- certains systèmes d’exploitation TEE se reposent également sur la technologie RPMB (Replay Protected Memory Block) pour protéger certaines données ou certaines parties de son code contre le chargement de versions antérieures (Rollback Downgrade Protection). Grâce à la mise en place en usine d’un secret partagé entre TEE et contrôleur Flash, il devient possible d’établir un canal sécurisé entre ces deux composants et de rendre impossible la modification de ces secteurs par le REE
- Cette liste permet la mise en place d’un socle de base sécurisé pour un TEE. Elle s’est toutefois étoffée pour supporter de nouveaux besoins :
- si la plateforme comporte des capteurs biométriques, ces derniers sont alors accédés via un bus I2C/SPI dédié au TEE ;
- pour supporter la fonctionnalité d’interface de confiance avec l’utilisateur (Trusted User Interface – TUI), l’écran du smartphone doit également pouvoir basculer en mode sécurisé temporairement et assurer l’intégrité et la confidentialité des données affichées par le TEE, bien que certains capteurs de l’appareil puissent introduire certains biais. Pour compléter cette fonctionnalité, le capteur d’appui sur l’écran ou des boutons physiques de l’appareil sont également dédiés temporairement, offrant une entrée utilisateur de confiance ;
- la dernière pierre angulaire nécessaire pour utiliser les services d’un environnement de confiance est l’injection d’une clef en usine lors de la fabrication du SoC. Cette clef secrète sera utilisée par la suite par le TEE pour la génération d’attestations afin de prouver qu’une opération s’est bien réalisée dans cet environnement de confiance et non dans un émulateur.
2.2 Utilisation du TEE sur smartphone
- Android KeyMaster : Bien que la motivation principale des constructeurs de smartphones pour l’intégration d’un TEE à leurs produits ait été la protection DRM, Android a su tirer profit de sa présence en permettant l’exécution du composant KeyMaster en zone sécurisée. Ainsi, les clés cryptographiques du système et de ses applications y sont stockées et traitées. Depuis Android N, l’intégration du KeyMaster en TEE est devenue obligatoire, impliquant sa présence sur tout smartphone aujourd’hui. Ainsi, lors de la phase de déverrouillage du smartphone par code PIN, mot de passe ou vérification biométrique, le déblocage des clefs de chiffrement de l’appareil est assuré en TEE, renforçant considérablement la sécurité de l’appareil.
- Samsung Knox : Bien que l’objectif soit de protéger des données et des services lors de la compromission partielle ou totale de la REE, Samsung a aussi profité de la présence d’un TEE pour augmenter la résistance du système Android contre les tentatives de corruption à travers différents modules tels que PKM (Periodic Kernel Measurement), en charge de surveiller l’activité du système Android et détecter tout comportement anormal, ou encore le module KRP (Runtime Kernel Protection), en charge de l’exécution de certains mécanismes bas niveau du noyau Android [KNOX].
- Samsung-Pay : L’intégration de l’application bancaire de Samsung passe aussi par le TEE, où sont protégés les secrets liés aux protocoles de paiement. Les interfaces graphiques, telles que la saisie du code PIN ou la confirmation de transaction, sont également protégées par interface de confiance (Trusted-UI).
- FIDO (Fast IDentity Online) est un très bon exemple d’utilisation de toutes les briques d’un TEE. FIDO UAF (Universal Authentification Framework) est un protocole destiné à remplacer l’utilisation du mot de passe par une procédure d’authentification réalisée sur une plateforme de confiance appelée « authenticator ». Pour plus d’informations sur ce sujet, le lecteur curieux pourra se référer à l’article sur « WebAuthn » dans MISC N°98 [MISC-98]. Dans le cas d’un mobile, un « authenticator » peut se traduire en une application 100 % Android, avec ou sans support du KeyMaster en TEE, voire une application dédiée en TEE. Cela se traduit par différents niveaux de sécurité : L1 sans support TEE, L2 et L2+ avec implémentation partielle, type KeyMaster, ou complète en TEE. L’utilisation d’un TEE avec TUI et protocole d’attestation permet d’atteindre L2+.
- WYSIWYS : La combinaison de ces trois briques (TEE/TUI/attestation) permet la mise en place d’une fonctionnalité de sécurité très appréciée des services nécessitant une acceptation explicite de l’utilisateur pour la réalisation d’opérations sensibles telles que des transactions bancaires ou l’authentification sur un service : WYSIWYS (What You Sign Is What You See). Le principe est le suivant : le texte affiché dans l’interface de confiance ainsi que la décision de l’utilisateur (confirmation ou refus) est alors signé avec une clef TEE. Le mécanisme d’attestation permettra ainsi de s’assurer que la clef utilisée pour signer ce message provient effectivement d’un environnement TEE avec support de TUI et non d’un émulateur.
2.3 GlobalPlatform TEE
Le concept de TEE/REE a été standardisé par le consortium GlobalPlatform tel que décrit dans leur document « TEE System Architecture » [GP-TEE-ARC]. Toute une suite de standards ont été émis afin de :
- permettre des TEE interopérables ;
- définir le concept de Trusted Applications (TA) : applications non-privilégiées s’exécutant dans TEE, et de Client Application (CA) : composant REE utilisant les services d’une TA ;
- définir un ensemble d’APIs à destination des Trusted Applications (TEE Internal API Specification) ;
- définir les APIs à destination de la REE pour appeler les services des TAs (TEE Client API Specification) ;
- définir un modèle de sécurité à travers un Protection Profile reconnu par les Critères Communs.
Le Protection Profile TEE édité par GlobalPlatform donne une définition claire des objectifs de sécurité d’un TEE qui peuvent être listés ainsi :
- authenticité du code TEE via une procédure de démarrage sécurisée ;
- protection contre le retour à une version précédente du code TEE ;
- capacité de lancer des Trusted Applications non privilégiées ;
- vérification de l’authenticité des TAs à l’installation permettant de définir la notion d’identité et de propriétaire d’une TA ;
- isolation et communication sécurisée entre TAs et REE, ainsi qu’entre TAs ;
- stockage et traitement sécurisé des données et clefs cryptographiques des TAs ainsi que la protection contre la copie du stockage en REE d’un appareil vers un autre ;
- APIs internes pour les TAs tels qu’un générateur de nombres aléatoires (RNG), des APIs cryptographiques résistantes aux attaques par canaux auxiliaires, et l’accès à une source de temps monotonique ;
- et surtout, la résistance de ces propriétés aux attaques logicielles et matérielles non-invasives.
Pour les habitués des Critères Communs, ce Protection Profile permet de certifier au niveau EAL2+ augmenté par AVA_TEE.2 nécessitant une phase de tests d’intrusion sur le produit. À ce jour, deux systèmes d’exploitation pour TEE possèdent un certificat de sécurité : Trustonic Kinibi-311A, certifié par l’ANSSI [KINIBI-CC] et Samsung TEEgris 2.5, certifié par GlobalPlatform.
3. Profitez du TEE depuis votre application Android
3.1 KeyMaster : protéger vos clefs en TEE
KeyMaster protège les clefs du système Android, mais peut aussi protéger celle des applications. Il suffit de générer ou d’importer ses clefs comme vous le montre l’exemple suivant. Celui-ci vous montrera aussi comment protéger l’utilisation de la clef de sorte qu’elle ne soit accessible uniquement pendant 5 minutes suivant un déverrouillage du téléphone. Enfin, les APIs permettant de récupérer une chaîne de certificat prouvant que la clef est bien stockée en TEE.
# Génération d’une clé EC via le KeyStore Android
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
kpg.initialize(new KeyGenParameterSpec.Builder("keyAlias", KeyProperties.PURPOSE_SIGN)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setUserAuthenticationRequired(true)
.setUserAuthenticationValidityDurationSeconds(5 * 60)
.build());
KeyPair kp = kpg.generateKeyPair();
# Test local de clé en TEE
KeyFactory factory = KeyFactory.getInstance(kp.getPrivate().getAlgorithm(), "AndroidKeyStore");
KeyInfo keyInfo = factory.getKeySpec(key, KeyInfo.class);
boolean isHardwareBacked = keyInfo.isInsideSecureHardware();
# Génération d’une attestation pour vérification côté serveur
Certificate[] certs = KeyStore.getInstance("AndroidKeyStore").getCertificateChain("keyAlias") ;
# Utilisation de la clé pour signature
Signature signature = Signature.getInstance("SHA256withECDSA");
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
PrivateKey privateKey = (PrivateKey) keyStore.getKey("keyAlias", null);
PublicKey publicKey = keyStore.getCertificate("keyAlias").getPublicKey();
signature.initSign(privateKey);
À noter que KeyMaster souffre de certaines limitations :
- la liste des algorithmes utilisables reste limitée et ne répondra pas à tous les besoins ;
- il n’existe que deux moyens de protéger sa clef par une authentification utilisateur : 1. Pendant un laps de temps après un déverrouillage, laissant toutes les clefs accessibles pendant cette période ; 2. À chaque utilisation de cette clé, mais uniquement par vérification biométrique (ne fonctionne pas avec un code PIN) ;
- la logique applicative de l’application Android n’est pas protégée (voir 3.2) ;
- enfin, les certificats d’attestation de KeyMaster ne permettent pas d’identifier précisément l’appareil qui l’a généré. Les clefs d’attestation Google sont injectées par série minimum de 10 000 appareils. Ainsi, une attestation peut tout aussi provenir d’un autre téléphone pirate partageant cette même clef.
3.2 Protégez votre code, vos données et vos clefs en TEE
Bien que l’utilisation d’Android KeyMaster permette de profiter de la présence du TEE, elle souffre des limitations décrites précédemment et la protection reste limitée aux appels successifs à ce service sans apporter de protection globale de la logique applicative. L’application Android peut toujours être modifiée (injection de code malveillant ou suppression de certaines validations) et distribuée sur Internet.
Pour protéger efficacement le code sensible d’une application, il convient de développer celui-ci sous la forme d’une Trusted Application. Le code et les données traitées restent ainsi en TEE profitant des garanties d’intégrité et de confidentialité. Tous les services que le KeyMaster pourrait offrir sont disponibles au TAs et sont même étendus. Voici quelques exemples :
- support étendu de suites cryptographiques ;
- renforcement de la protection par authentification ;
- création d’interfaces de confiance TUI personnalisées répondant aux besoins spécifiques du développeur.
Une Trusted Application revient à un code natif exposant 5 APIs :
- TA_Create/DestroyEntryPoint : appelées respectivement lors du démarrage et de fin de la TA dans le TEE ;
- TA_Open/CloseSessionEntryPoint : appelées respectivement lors l’ouverture d’une session depuis la REE ou depuis une autre TA. Si la TA est configurée pour être en instance unique, plusieurs sessions pourront y être créées ; dans le cas contraire, toute ouverture de session génèrera la création d’une nouvelle instance ;
- TA_InvokeCommandEntryPoint : une fois la session ouverte, l’appelant peut appeler la TA à plusieurs reprises par cette API.
L’application Android, ou toute partie cliente, contacte le TEE puis la TA via les APIs suivantes :
- TEEC_InitializeContext : préparation de la communication avec le TEE ;
- TEEC_OpenSession : ouverture d’une session vers la TA ;
- TEEC_InvokeCommand : appel d’une API de la TA. Le passage de paramètres peut se faire par simples valeurs (entier 32/64 bits) ou par mémoire partagée.
Figure 3 : Communication entre un APK android et une Trusted Application en TEE.
Voici un exemple simpliste d’une CA accédant aux services d’une TA type FIDO pour s’authentifier auprès d’un service.
[--- CA ---]
/* Initialisation de la connexion avec le TEE */
result = TEEC_InitializeContext(NULL, &context);
operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
/* Ouverture d’une session avec la Trusted Application "MYFIDO" */
result = TEEC_OpenSession(&context, &session, &MYFIDO_TEE_UUID, NULL, NULL, &operation, NULL);
/* Préparation des paramètres : Entrée et sortie par mémoire partagée */
memset(&sOperation, 0, sizeof(TEEC_Operation));
sOperation.params[0].tmpref.buffer = (void*)(serviceToAuthenticate);
sOperation.params[0].tmpref.size = serviceToAuthenticateLen;
sOperation.params[1].tmpref.buffer = commandOutput;
sOperation.params[1].tmpref.size = commandOutputSize;
sOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_OUTPUT,
TEEC_NONE, TEEC_NONE);
/* Invocation des services de la TA en TEE */
TEEC_InvokeCommand(&session, CMD_GET_AUTHENTICATION_TOKEN,
&sOperation, NULL);
[--- TA ---]
TEE_Result TA_EXPORT TA_InvokeCommandEntryPoint(IN OUT void* pSessionContext,
uint32_t nCommandID, uint32_t nParamTypes, TEE_Param pParams[4])
TEE_Result nResult;
switch (nCommandID)
{
case CMD_REGISTER_SERVICE:
[...]
break;
case CMD_AUTHENTICATE_SERVICE: {
if (nParamTypes != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE))
{
TEE_DbgPrintLnf("MYFIDO: Wrong parameter types");
return TEE_ERROR_BAD_PARAMETERS;
}
/*
* Copie et validation du buffer d'entrée en mémoire sécurisée
* [optionnel] Validation du consentement utilisateur par affichage en TUI
* "Confirmez vous l’authentification sur le service" + serviceName
* Authentification de l'utilisateur par vérification biométrique
* Récupération de la clé privée associée au service
* Signature du jeton et copie de la réponse dans le buffer de sortie
*/
nResult = TEE_SUCCESS;
break;
default:
TEE_DbgPrintLnf("MYFIDO invalid command ID: 0x%X", nCommandID);
nResult = TEE_ERROR_BAD_PARAMETERS;
break;
}
return nResult;
}
Toutefois, l’installation d’une Trusted Application tierce depuis une application Android ne peut se faire uniquement que sur les appareils qui embarquent un TEE ouvert. Tandis que QSEE ou TrustedCore ne supportent que l’installation de code signé par l’OEM, aujourd’hui seul Kinibi supporte ce scénario à travers l’implémentation du protocole [GP-TMF]. Ce protocole définit en particulier la notion d’identité d’application TEE et de propriétaire de cette identité grâce à un mécanisme cryptographique. L’identité (utilisée pour assurer l’isolation) est un dérivé d’une clef publique. Ainsi chaque code est signé avec la partie privée de cette clef, assurant que seul le possesseur de cette clef puisse exécuter du code sous cette identité.
4. Attaques sur les environnements TrustZone
Partager le même SoC et le même CPU pour le REE et le TEE est le fer de lance de la technologie TrustZone. Avoir la performance et la sécurité sans compromis ! Toutefois ce partage s’accompagne de risques qu’il convient de connaître lors de l’intégration du TEE dans le SoC ou lors du développement de Trusted Applications.
4.1 Les dangers d’un cache partagé
Le partage du cache entre TEE et REE apporte un gain de performance non négligeable, mais côté sécurité, cela introduit un moyen potentiel d’observer les effets de l’exécution du TEE sur celui-ci. Comme décrit en première section de l’article, tout accès REE à une ligne accédée par le TEE et donc marquée comme Secure revient à un cache miss, et résulte en accès RAM. Cette différence de temps d’accès peut être observée via des outils tels que CacheGrab pour construire des attaques telles que les reconstructions de clefs secrètes sur des implémentations d’algorithmes cryptographiques non résistants. Un exemple récent est l’attaque sur l’implémentation AES-256 et AES-256-GCM de KeyMaster sur le Samsung Galaxy S6 [GS6-CacheAttack]. Un autre exemple d’attaque via le cache CPU, également applicable ici, a été présenté dans [MISC-88].
On ne peut parler d’attaques par canaux auxiliaires sur le cache CPU sans mentionner les récentes attaques Spectre et Meltdown. Les processeurs ARM et autres dérivés de Samsung et Qualcomm ne font pas exception, il en est de même pour l’environnement TrustZone. Ainsi le TEE-OS, comme un OS classique, peut être la cible d’attaques internes depuis une TA compromise s’il n’est pas protégé. Même si théoriquement les effets de Spectre en TEE pourraient être observés en REE, les effets induits par les échanges entre ces derniers rendent ce scénario irréalisable en pratique.
4.2 Les dangers d’une mémoire partagée
Avec la publication de l’outil Drammer, la faisabilité d’une attaque Rowhammer en environnement mobile n’est plus à démontrer. Bien que l’attaque ait été réalisée depuis une application Android pour corrompre des zones du noyau Android, le même principe pourrait être appliqué depuis une TA sur le noyau du TEE-OS. Toutefois, comparées aux applications Android, les applications TEE ne répondent pas forcément aux prérequis nécessaires pour monter une attaque pratique et déterministe.
Au-delà d’une attaque interne, le TEE pourrait également être attaqué depuis le REE. En effet, ces deux environnements se côtoient dans les barrettes de RAM. Ainsi le REE serait en capacité de monter cette attaque sur les bords des blocs de mémoire dédiés TEE. Ce scénario a d’ailleurs été démontré par Pierre Carru à la GreHack 2017 [Rowhammer-TZ]. Toutefois ce scénario a été construit sur mesure pour la démonstration et ne répond pas forcément aux intégrations réelles.
4.3 Les dangers d’un CPU partagé !
Bien que la documentation ARM déconseille vivement de laisser la gestion de la puissance des CPU au REE, cette directive n’a toutefois pas été suivie et un exemple d’attaque a été réalisé : [CLKScrew]. Le principe est relativement simple, le REE s’arrange pour faire exécuter temporairement le TEE sur un cœur précis, puis augmenter ou diminuer suffisamment la puissance de ce cœur afin de générer des « glitch » : erreurs lors d’accès mémoire ou d’exécution d’instruction CPU. Ces « glitch » difficilement maîtrisables peuvent parfois conduire à des fuites de clefs AES ou des contournements d’une vérification de signature RSA, comme nous le montre cette publication. Cette attaque reste toutefois très théorique et difficilement réalisable en pratique.
4.4 Dangers lors de l’intégration sur Android
L’objectif d’un TEE reste avant tout d’améliorer la sécurité globale sans pour autant dégrader celle du système principal. Pour la communication avec le TEE, des composants privilégiés sont ajoutés à Android, en particulier pour la gestion des mémoires partagées. Le TEE et les TAs n’ont aucune connaissance du fonctionnement du système principal et des mécanismes d’isolation imposés. C’est aux composants Android qu’il revient d’assurer le respect des mécanismes d’isolation Android, bien que cela n’ait pas toujours été fait correctement comme il a pu être observé dans la publication académique [Boomerang]. Sans mentionner les failles logicielles classiques telles que les CVE-2014-4322 ou CVE-2016-3931 trouvées dans les intégrations Qualcomm.
Conclusion
Suite au gain de popularité, des études académiques ont été menées sur l’utilisation de TrustZone dans les téléphones mobiles, présentant des attaques possibles en environnement contrôlé bien souvent éloignées des contraintes réelles. Aujourd’hui présent sur tous les mobiles Android, le TEE TrustZone s’impose comme technologie de renforcement de la sécurité, assurant la protection des clefs de chiffrement jusqu’à la protection d’applications complètes. Et avec l’intégration de la biométrie et d’une interface de confiance, cette technologie ouvre désormais de nouvelles possibilités de services sécurisés.
Remerciements
Je tiens à remercier mes collègues de Trustonic et ainsi que mes amis qui ont participé à l’effort d’élaboration et de relecture de l’article.
Références
[Arm-TZ] « Building a Secure System using TrustZone® Technology », whitepaper
[ATF] https://github.com/Arm-software/arm-trusted-firmware
[KNOX] https://developer.samsung.com/tech-insights/pay/device-side-security
[GP-TEE-ARC] GlobalPlatform : TEE System Architecture, GPD_SPE_009
[GP-TMF] GlobalPlatform : TEE Management Framework, GPD_SPE_120
[GS6-CacheAttack] « Cache-Attacks on the Arm TrustZone implementations of AES-256 and AES-256-GCM via GPU-based analysis », B. Lapid et A. Wool, 2018
[MISC-88] « Attaques par canaux auxiliaires utilisant les propriétés du cache CPU », David Berard - Vincent Fargues, MISC n°88, novembre 2016
[MISC-98] « WebAuthn : enfin la fin des mots de passe », Clément Notin, MISC n°98, juillet-août 2018
[Rowhammer-TZ] « Attack TrustZone with Rowhammer », Pierre Carru , GreHack 2017
[Boomerang] « BOOMERANG: Exploiting the Semantic Gap in Trusted Execution Environments », A. Machiry et al. , NDSS 2017
[CLKScrew] « CLKSCREW: Exposing the Perils of Security-Oblivious Energy Management », A. Tang et al. , USENIX 2017