Article de : Mohamed BELOUARGA et Fabien Lahoudere
Le monde est de plus en plus connecté, et des millions d'appareils sont conçus pour être connectés soit à des serveurs, soit entre eux. Cette hyperconnectivité s'accompagne de nombreuses menaces, et les systèmes embarqués sous Linux n'y échappent pas.
Dans cet article, nous aborderons une technique permettant de renforcer la sécurité des appareils Linux embarqués ; toutefois, le lecteur doit savoir que cette méthode ne protège pas ces appareils contre toutes les menaces.
Le lecteur doit savoir que l'auteur est un ingénieur spécialisé dans Linux embarqué et non un expert en cybersécurité.
Qu'est-ce que le démarrage sécurisé ?
Le démarrage sécurisé consiste à mettre en place une chaîne de confiance entre les différents composants logiciels d'un appareil Linux embarqué. Cette chaîne de confiance est mise en place pour empêcher les appareils d'exécuter des logiciels corrompus ou provenant d'une source autre que le fabricant de l'appareil.
Cette chaîne de confiance est, en réalité, un processus de vérification à plusieurs niveaux qui permettra d'identifier l'origine de ces composants logiciels

Tout d'abord, le code ROM vérifie que le chargeur d'amorçage provient bien du fabricant ; ensuite, le chargeur d'amorçage vérifie que le noyau Linux provient également du fabricant avant de le lancer ; enfin, le noyau vérifie que le ROOTFS ( l'application) provient bien du fabricant.
Nous verrons ci-dessous comment fonctionne cette chaîne de confiance – ou ce que l'on appelle le « démarrage sécurisé » – et comment la mettre en œuvre.
Comment mettre en place le démarrage sécurisé
Sécurisation du chargeur d'amorçage
Cette partie dépend du matériel et est mise en œuvre par le matériel et le code ROM. Le code ROM vérifie que le chargeur d'amorçage provient bien du fabricant, en contrôlant sa signature. La signature du chargeur d'amorçage correspond généralement à son hachage chiffré à l'aide d'une clé privée.
Si la signature est corrompue, le code ROM ne lance pas le chargeur d'amorçage, ce qui empêche l'appareil de démarrer.
Sécurisation du noyau
Une fois la vérification effectuée, le code ROM lance le chargeur d'amorçage.
Le chargeur d'amorçage initialise juste le matériel nécessaire (au moins la SDRAM et la console série) pour démarrer le noyau et charger ce dernier ainsi que l'arborescence des périphériques en mémoire vive.
Avant de démarrer le noyau, le chargeur d'amorçage vérifie la signature du noyau et de l'arborescence des périphériques (ainsi que celle d'autres binaires si nécessaire).
Si des fichiers binaires doivent être vérifiés, une image FIT contenant tous ces fichiers binaires peut être utilisée pour gagner en efficacité dans ce processus.
Sécurisation du ROOTFS
Pour sécuriser le ROOTFS, il est préférable d'utiliser un ROOTFS en lecture seule et de tirer parti d'une fonctionnalité fournie par le noyau, appelée DM-verity.
Dm-verity utilise un arbre de hachage pour s'assurer que le ROOTFS n'est pas corrompu. La couche 0 de l'arbre de hachage contient les hachages du ROOTFS : un hachage tous les 4 Ko.
Vous trouverez plus de détails dans le schéma ci-dessous.

- La couche 0 contient les hachages du ROOTFS, à raison d'un hachage par tranche de 4 Ko de mémoire
- La COUCHE 1 contient les hachages de la COUCHE 0
- Hachages de la COUCHE 1 au niveau de la COUCHE 2 …
- Jusqu'à ce que nous obtenions un hachage final, appelé « hachage racine ».
Pour utiliser DM-verity sur la partition ROOTFS, il est plus simple d'utiliser un InitRamFS qui lance DM-verity sur la partition ROOTFS avant de basculer vers le ROOTFS.
Le fichier InitRamFS (qui contient le hachage racine) doit être ajouté à l'image FIT et doit également être signé.
Si DM-verity détecte une corruption dans le ROOTFS ou si le hachage racine a changé, cette fonctionnalité provoque une panique du noyau, ce qui bloque le démarrage.
Exemple d'imx8
Pour illustrer certains aspects du démarrage sécurisé liés au matériel, nous prendrons l'exemple de l'imx8 :
Outils CST
Avant de tenter de mettre en place le démarrage sécurisé sur l'IMX8, nous devons générer des clés privées qui serviront à signer les binaires. NXP fournit des outils CST (Code Signing Tool) qui permettent de générer des clés privées et publiques, et de signer le chargeur d'amorçage ainsi que d'autres binaires.
Fusibles et CAAM
L'Imx8 intègre un module appelé CAAM (Cryptographic Acceleration and Assurance Module) qui servira à accélérer la vérification de toutes les signatures. L'Imx8 dispose également de registres appelés « registres programmables une seule fois » (eFuse).
Pour activer la vérification de signature, les eFuses SRK_HASH doivent être programmés avec les hachages des clés publiques générées ; pour verrouiller la carte, un autre eFuse doit être programmé.
Tous ces éléments serviront à mettre en œuvre le HAB (High Assurance Boot) : le démarrage sécurisé imx.
Code ROM
Au démarrage, le code ROM vérifie si les eFuses SRK_HASH sont programmés. Si c'est le cas, il vérifie la signature du bootloader (SPL + ATF + OPTEE + U-boot). Selon que la carte est verrouillée ou non, le code ROM poursuivra le processus de démarrage ou l'interrompra :

Le code Rom vérifie une image, comme le montre l'illustration ci-dessous :

Remarque : d'autres eFuses doivent également être programmés pour que le démarrage sécurisé fonctionne correctement. Par exemple, l'eFuse qui désactive le JTAG.
Imx-boot
Après avoir vérifié sa signature, le code ROM lance le chargeur d'amorçage (SPL, puis ATF et OPTEE, puis U-boot).
U-boot doit être configuré pour vérifier la signature de l'image FIT si le HAB est activé. La vérification de la signature de l'image FIT s'effectue en appelant certaines fonctions du code ROM (via l'ATF).
U-boot se comportera alors comme le code ROM de l'étape précédente : si la carte est verrouillée et que la signature est corrompue, il interrompra le processus de démarrage.
Image de démarrage et ROOTFS
L'image Fit Image contient au moins trois éléments : le noyau, l'arborescence des périphériques et le système de fichiers InitRamFS.
Lorsque U-boot vérifie la signature de l'image, il extrait ces éléments et lance le noyau.
Lorsque le noyau est lancé avec l'InitRamFS, ce dernier applique DM-verity à la partition ROOTFS et fournit au noyau le hachage racine. Enfin, le noyau poursuit le démarrage sur la partition ROOTFS.
Ces différentes étapes constituaient le démarrage sécurisé pour imx8 :

Le lecteur curieux trouvera davantage d'informations sur la mise en œuvre de HAB sur Internet ; cette deuxième partie de l'article n'avait pas pour but d'expliquer tous les détails de HAB, mais seulement de montrer le lien entre le démarrage sécurisé et le matériel.



.jpg)