Introduction
Le boot sécurisé, ou Secure Boot, est arrivé avec les EFI et permet de restreindre le lancement de certaines applications seulement au démarrage de la machine. Une application UEFI est un binaire au format Portable Executable, au même titre que les .exe de Windows, dont l'extension est .EFI. Le boot sécurisé permet donc de contrôler l'exécution de ces fichiers binaires en les autorisant ou non à s'exécuter. Afin d'être bootables, ces programmes doivent se trouver sur une partition FAT (16 ou 32) lors du démarrage de la machine. Ces dernières peuvent être situées sur une clé USB ou sur une partition du disque dur.
Avec l'arrivée de Windows 8, Microsoft a imposé aux constructeurs de mettre en place le boot sécurisé sur les (U)EFI afin de permettre le démarrage uniquement au bootloader de Windows et cela pour des raisons de sécurité. Ainsi, par défaut aucun autre programme .EFI n'est bootable (leur boot sécurisé étant actif par défaut). Une méthode consiste à désactiver le Secure Boot dans le BIOS/UEFI. À partir de là, n'importe quel programme .EFI est bootable.
But final
À travers ce mini tutoriel, notre but est d'être capable d'exécuter un seul et unique programme .EFI au démarrage avec le Secure Boot actif. Il s'agit du programme Pong.efi que avons réalisé lors du précédent tutoriel. Nous allons faire en sorte que ce programme s'exécute avec le Secure Boot activé.
Note: Afin de suivre ce tutoriel, vous devez au préalable savoir démarrer un programme .EFI et savoir comment accéder au menu (U)EFI (ancien BIOS menu), qui se fait généralement avec la touche F7, F12 ou Échap au démarrage de la machine.
État des lieux
Après avoir activé le Secure Boot, en essayant de démarrer sur le Pong, voici le message obtenu :
Image verification failed ! Image certification not foud in Authorized Database(db)!
Ceci est dû au fait que les clés, installées par défaut dans les PC vendus avec Windows 8, permettent de démarrer uniquement sur le bootloader de Windows. Nous allons donc générer nos propres clés qui permettront de démarrer notre Pong, et seulement lui.
En (U)EFI, il existe 4 variables non volatiles importantes qui s'installent dans une ROM de la carte mère, donc de manière persistante. Les voici :
- La Platform Key (PK) : Cette clé contient au plus une entrée. Lorsqu'elle est effacée, le système désactive le Secure Boot et l'utilisateur peut modifier les clés présentées ci-dessous librement, c'est-à-dire sans vérification de signature.
- La Key Exchange Key (KEK) : Cette variable contient une ou plusieurs clés publiques RSA. Ainsi, la mise à jour des variables db ou dbx (ci-dessous) nécessite d'être signée avec l'une des clés privées associées aux clés publiques contenues dans cette variable KEK.
- Signature Database (db) : Cette variable contient une base de données des signatures, des clés publiques, voire même des hash des programmes qui sont autorisés à s'exécuter.
- Forbidden Signatures Database (dbx) : Cette variable agit comme une blacklist des programmes voulant s'exécuter.
Génération de nouvelles clés
La première étape consiste à générer nos propres clés PK, KEK et db. Pour ce faire, nous aurons besoin d'un PC sous Linux muni d'OpenSSL. Créons un dossier qui contiendra nos clés :
$ mkdir efikeys $ cd efikeys efikeys/ $
Maintenant, utilisons OpenSSL afin de générer des clés RSA de longueur 2048 bits, puis un certificat X.509 utilisant SHA-256 et expirant dans 10 ans :
efikeys/ $ openssl req -new -x509 -newkey rsa:2048 -subj "/CN=platform key PONG/" -keyout PK.key -out PK.crt -days 3650 -nodes -sha256 efikeys/ $ openssl req -new -x509 -newkey rsa:2048 -subj "/CN=key-exchange-key PONG/" -keyout KEK.key -out KEK.crt -days 3650 -nodes -sha256 efikeys/ $ openssl req -new -x509 -newkey rsa:2048 -subj "/CN=kernel-signing key PONG/" -keyout db.key -out db.crt -days 3650 -nodes -sha256
Note : Le contenu du "Common name" (CN) peut être remplacé par ce que vous souhaitez.
Nous avons dès lors trois certificats (PK.crt, KEK.crt et db.crt) ainsi que les clés privées associées (PK.key, KEK.key et db.key)
Préparation et mise en place des clés
Maintenant que nous avons nos clés et certificats, nous devons générer une liste de signatures que nous aurons signé au format .auth. Certains UEFI, y compris celui de notre machine de test, n'acceptent que ce format. Pour cela, nous aurons besoin d'un utilitaire open-source téléchargable ici : app-crypt/efitools.
Générons notre liste de signatures dans un premier temps, puis signons la avec notre Platform Key privée. Voici les commandes à utiliser :
efikeys/ $ cert-to-efi-sig-list -g "$(uuidgen)" PK.crt PK.esl efikeys/ $ sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth
Faisons de même pour la KEK et la db :
efikeys/ $ cert-to-efi-sig-list -g "$(uuidgen)" KEK.crt KEK.esl efikeys/ $ sign-efi-sig-list -a -k PK.key -c PK.crt KEK KEK.esl KEK.auth efikeys/ $ cert-to-efi-sig-list -g "$(uuidgen)" db.crt db.esl efikeys/ $ sign-efi-sig-list -a -k KEK.key -c KEK.crt db db.esl db.auth
Afin de mettre en place ces clés .auth dans notre UEFI, transférons les sur une clé USB, démarrons sur le menu UEFI, rendons-nous dans la section "Key Management", puis dans cet ordre là :
- Effaçons les clés existantes (Clear Secure Boot keys)
- Mettons en place la clé db.auth (Set DB from File)
- Mettons en place la clé KEK.auth (Set KEK from File)
- Mettons en place la clé PK.auth (Set PK from File)
Dans ces trois dernières étapes, une fenêtre graphique apparaîtra dans laquelle il sera possible de sélectionner les fichiers .auth présents sur la clé USB. Une fois mis en place, quittons le menu avec "Save & Exit".
Note : La clé dbx a été délaissée délibérément, nous pourrons alors soit générer une liste vierge, soit récupérer l'ancien fichier dbx présent dans le Secure Boot de l'UEFI (faisable directement depuis le menu), le re-signer avec notre nouvelle clé KEK.key et le remettre en place avec sa nouvelle signature.
Signer le binaire
Maintenant que nos clés sont en place, essayons d'exécuter notre Pong.efi. La même erreur que précédemment s'affiche :
Image verification failed ! Image certification not foud in Authorized Database(db)!
En effet, le binaire n'est toujours pas signé. Signons-le avec notre clé. Pour cela, nous allons utiliser l'utilitaire sibsign issu du paquet sbsigntool. Prenons notre binaire Pong.efi et créons un binaire Pong-signed.efi :
efikeys/ $ sbsign --key db.key --cert db.crt --output Pong-signed.efi Pong.efi
Remarquons que dans notre cas, il a fallu utiliser la clé privée db (et non KEK) ainsi que son certificat. Cela n'est pas une généralité et dépend des machines.
Après avoir généré ce binaire signé, plaçons-le sur notre clé USB sous le nom de BOOTX64.EFI de manière à avoir l'arborescence suivante :
└── EFI └── BOOT └── BOOTX64.EFI
Démarrons sur la clé et hop ! Notre Pong a démarré !
Pour aller plus loin
Dans ce tutoriel, nous avons généré des clés qui permettent l'exécution uniquement de notre programme, le bootloader Windows ne sera ainsi plus autorisé à démarrer. Une solution est de "fusionner" nos fichiers esl afin de pouvoir profiter de l'ancienne certification ainsi que de la nouvelle. De plus, l'installation peut se faire aussi directement depuis la machine cible si cette dernière est munie d'une distribution Linux. Toutes ces informations ainsi que toutes les informations précédentes données dans ce tutoriel sont détaillées et expliquées dans le lien suivant (en anglais), dont notre article s'inspire grandement :