openSUSE:UEFI

Usare UEFI

Introduzione allo standard

UEFI (Unified Extensible Firmware Interface) è un nuovo standard industriale che definisce le diverse interfacce che un sistema deve fornire nell'ambiente di pre-avvio di sistema ( o pre-boot). UEFI avrà il controllo del sistema dopo che questo è stato acceso e il sistema operativo è stato completamente caricato. Inoltre, UEFI ha il compito di fornire un'interfaccia tra le risorse messe a disposizione dal sistema e il sistema operativo.

In altre parole, UEFI è stato introdotto per sostituire ed estendere il vecchio firmware del BIOS.

UEFI non è una novità: Intel lavora su EFI / UEFI dalla metà degli anni Novanta e ci sono aziende, come HP o Apple, che producono macchine con firmware EFI da ormai molto tempo. Ma è stato quando Microsoft ha annunciato Windows 8 che UEFI è diventato il sistema necessario per avviare le nuove macchine certificate.

Le specifiche relative a UEFI (http://www.uefi.org/specs/) sono un grosso documento che contiene tutte le interfacce, variabili e strutture che il produttore del firmware deve fornire, e a cui il sistema operativo deve poter avere accesso. La buona notizia è che Linux è in grado di usare EFI in fase di avvio fin dal 2000, grazie a GRUB o elilo. Quindi openSUSE 12.2 era dotata del supporto a UEFI, mentre la recente (al momento di scrivere) openSUSE 12.3 ha aggiunto il supporto, sperimentale, per l'estensione Secure Boot (avvio protetto del sistema).

Il Secure boot si presenta come un'estensione di UEFI proprio perché uno dei punti di forza di quest'ultimo è la possibilità di essere ampliato mediante estensioni. UEFI è infatti dotato al suo interno di una macchina virtuale che è indipendente dall'architettura su cui si trova in esecuzione. Lo standard prevede file binari particolari, appositamente compilati per questa macchina virtuale (binari EFI), che è possibile eseguire all'interno di quell'ambiente. Tali binari possono essere driver di dispositivi, applicazioni o estensioni allo standard UEFI. UEFI, in un certo senso, è come un piccolo sistema operativo che viene eseguito quando il computer viene acceso, e il cui compito principale è trovare un altro sistema operativo da caricare in memoria.

Per sapere se il proprio computer è una macchina dotata di UEFI, normalmente si procede controllando la configurazione del firmware dopo aver tenuto premuto F1 (o ESC, a seconda del modello di computer) durante la fase di accensione della macchina. Navigando tra i menu che verranno visualizzati, si noterà che la macchina può funzionare in modalità compatibile (legacy mode, ovvero la vecchina modalità BIOS), modalità EFI e infine in una modalità ibrida, in cui la modalità effettiva verrà selezionata in base al sistema operativo che si starà caricando nel computer.

Se il proprio computer non fosse dotato di supporto a UEFI ma si volesse comunque provare questa nuova tecnologia con openSUSE, sarà possibile usare QEMU e l'implementazione modello di UEFI fatta da Intel: UEFI e Secure Boot con QEMU.

GPT

Con l'introduzione di UEFI non cambiano soltanto il firmware, le chiamate di sistema e le interfacce; viene anche introdotto un nuovo stile di partizionamento dei dischi fissi. La nuova tabella delle partizioni GUID Partitioning Table (GPT) sostituisce infatti la vecchia soluzione basata sul Master Boot Record (MBR).

Il partizionamento basato su MBR presenta alcuni limiti rilevanti, come il numero di partizioni primarie e logiche che si possono creare, oltre che limitazioni sulla dimensioni massima di tali partizioni. Con il partizionamento GPT questi problemi vengono risolti per cui è ora possibile creare un numero arbitrario di partizioni (fino a 128) e poter indirizzare una spazio su disco di 2^64 byte (ovvero nell'ordine dell'Exabyte). Questo tipo di partizionamento è dunque particolarmente indicato per dischi di grandi dimensioni. Un'altra differenza fondamentale è che usando GPT per riferirsi alle partizioni viene assegnato a ciascuna di essere un codice numerico di identificazione univoco (UUID), evitando così possibili collisioni tra gli identificativi assegnati a più partizioni diverse.

Nel caso in cui, durante una nuova installazione, YaST rilevi che si sta operando in modalità EFI, cercherà di creare automaticamente una partizione GPT. Una volta creato una schema di partizioni GPT, non è più possibile utilizzare il vecchio comando fdisk per creare, eliminare o modificare le partizioni. Il nuovo strumento per questo scopo si chiama gdisk ed è disponibile nel pacchetto gptfdisk; l'interfaccia, ovviamente da riga di comando, è la stessa che si aveva a disposizione con il programma di sistema fdisk.

Occasionalmente, si potrebbe voler rimuovere il formato GPT dal disco fisso del proprio computer, ad esempio nel caso in cui si intenda fare delle prove e sperimentare un po' con le diverse modalità di partizionamento. Questo può essere ottenuto usando YaST2: per farlo accedere alla finestra di configurazione Partizionatore avanzato, selezionare il corretto disco fisso e dal pulsante a discesa "Avanzate..." selezionare l'opzione "Crea nuova tabella delle partizioni".

Questa procedura sostituirà la tabella delle partizioni in funzione del sistema in esecuzione in quel momento.

Partizione di sistema EFI

La partizione di sistema EFI (EFI System Partition o ESP) è la partizione in cui UEFI si aspetta di trovare i programmi EFI che si possono usare per avviare tutti i sistemi operativi installati nel dispositivo. Inoltre, EFI rileverà all'interno di tale partizione alcuni driver di dispositivo da usare nella fase di avvio del sistema, oltre ad altri strumenti che è necessario mettere in esecuzione prima che il sistema operativo venga avviato.

La partizione usa il file system FAT e può essere creata mediante YaST2 durante un'installazione ex novo, oppure usandone una già esistente nel caso di macchina che avvii due, o più, sistema operativi (ovvero con computer in "dual boot"). Questo significa che se è presente nel sistema una versione di Windows precedentemente installata, YaST2 rileverà la partizione EFI (se presente, ad esempio dipende dalla versione di Windows installata, hardware, ecc.), vi inserirà il nuovo bootloader EFI usato per caricare openSUSE e, infine, monterà la suddetta partizione nel punto di montaggio /boot/efi.

Per impostazione predefinita, il firmware andrà alla ricerca di /EFI/BOOT/bootx64.efi per l'estensione da caricare ed eseguire al fine di caricare il sistema operativo. Su macchine Windows, la corretta estensione è data dal percorso /EFI/Microsoft/Boot/BCD.efi, e per openSUSE è /EFI/opensuse/grubx64.efi (oppure shim.efi, qualora sia abilitato l'avvio protetto - ossia il secure boot).

Il Boot Manager (gestore avvii)

Al fine di selezionare l'estensione appropriata che provvederà al caricamento del sistema operativo, EFI mette a disposizione degli utenti un boot manager (gestore avvii) interno; spetta al sistema operativo il compito di creare una nuova voce per il proprio stesso caricamento. Per ottenere un elenco di tutte le voci di avvio presenti, sarà sufficiente accedere al gestore degli avvii (boot manager) durante la fase di accensione del sistema, solitamente premendo il testo F9 o F12. Mediante lo strumento di gestione efibootmgr è invece possibile visualizzare e modificare le singole voci; ad esempio, per visualizzare un elenco delle voci attuali sarà sufficiente eseguire il comando efibootmgr -v.

Nella schermata qui sopra si può notare che openSUSE ha creato due voci di avvio differenti: una da usarsi quando ci si trova in modalità protetta (secureboot), l'altro per quando si è in modalità "normale" (ovvero non protetta).

Se per qualche motivo una delle voci inserite dovesse andare persa e non essere più disponibile, la si può creare nuovamente usando efibootmgr. Per esempio, per creare di nuovo la voce 'opensuse' si può usare la riga di comando:

# efibootmgr -c -L "openSUSE-alt" -l '\EFI\opensuse\grubx64.efi'

Variabili relative a EFI

Lo standard UEFI definisce una serie di variabili che sono memorizzate in un'area non-volatile del firmware. Queste variabili vengono usate per salvare le informazioni e modificare in base alle proprie esigenze il comportamento del sistema UEFI. Ad esempio quando viene creata una nuova voce nel boot manager, oppure quando si attiva o disattiva l'opzione per l'avvio protetto (secure boot), in effetti si sta accedendo, per modificarlo, al valore di una di queste variabili.

È possibile interrogare o accedere a queste variabili direttamente da openSUSE, tramite Sysfs. Sysfs è un file system virtuale fornito dal kernel al fine di esportare nello spazio utente alcune delle informazioni interne di sistema. Le variabili in questione si trovano in '/sys/firmware/efi/vars/'. quindi, ad esempio, l'ultima voce del boot loader può essere interrogata con:

$ hexdump -C /sys/firmware/efi/vars/Boot0007-*/data

Avvio protetto (Secure Boot)

Nozioni di base

L'avvio protetto (secure boot) di UEFI è un metodo per limitare quali file binari si possono eseguire per avviare il sistema. Il firmware consente l'esecuzione soltanto di quei boot loader devono essere firmati con chiave crittografica di una ben nota entità riconosciuta. Nel contesto dell'avvio protetto per identificare una tale entità vengono usati certificati nello standard X.509.

Attualmente (almeno al momento di scrivere) la maggior parte dell'hardware di PC per uso personale/domestico ad avere l'avvio protetto abilitato viene venduto con Microsoft Windows 8 installato. Di conseguenza il firmware accetta soltanto Microsoft come unica entità riconosciuta per firmare crittograficamente i boot loader. Per riuscire ad avviare openSUSE senza dover riconfigurare l'elenco dei fornitori di firme riconosciuti e autorizzati, né dovendo ricorrere a disattivare il Secure Boot (e quindi l'avvio protetto), il bootloader di openSUSE deve quindi essere firmato da Microsoft.

Implementazione in openSUSE 12.3

Il boot loader predefinito usato da openSUSE 12.3 con sistemi UEFI è grub2. Quando si opera in modalità di avvio protetto (secure boot) viene usato anche un boot loader aggiuntivo, il cui nome è 'shim'. Invece di invocare grub2 direttamente, quando si trova in quella modalità il firmware carica innanzitutto 'shim', quest'ultimo è firmato da Microsoft, in modo tale da poter essere riconosciuto dal firmware. A sua volta 'shim' è in grado di riconoscere e accettare il certificato di openSUSE che è stato usato per firmare grub2; a questo punto grub2 sarà in grado di caricare i kernel Linux che siano stati anch'essi firmati con i certificati di openSUSE. Una volta finito di caricare il kernel Linux termina anche il raggio di azione dell'avvio protetto (secure boot). Il kernel Linux usato in openSUSE non impone, infatti, ulteriori restrizioni.

Al fine di consentire l'utilizzo sia di boot loader personalizzati che di versioni personalizzate del kernel, shim mette a disposizione un metodo per importare firme personali. Per questo scopo viene usato il programma 'MokManager': quando a 'shim' vengono passate le istruzioni di caricare un file binario che non è stato formato firmato da una entità riconosciuta, lo stesso shim si occupa di richiamare MokManager il quale consente di importare i certificati nel database dei fornitori di firme riconosciuti.

Come attivare o disattivare il supporto per Secure Boot

Il supporto all'avvio protetto con Secure Boot fornito da openSUSE 12.3 è ancora considerato sperimentale. Il programma di installazione fornito da YaST non è in grado di rilevare automaticamente se l'avvio protetto è attivato, per cui durante l'installazione offre la possibilità di abilitare manualmente il supporto per Secure Boot (avvio protetto). L'attivazione di tale opzione è necessaria per far sì che venga lanciata l'installazione di shim. Per abilitare o disabilitare il supporto per Secure Boot (avvio protetto) in un sistema openSUSE già installato si può ricorrere al modulo Boot Loader di YaST.

Come determinare se sul sistema è attivo Secure Boot

Per determinare se su un computer o dispositivo è attivato l'avvio protetto (secure boot) nel firmware, digitare il seguente comando come root in una shell di Linux:

# od -An -t u1 /sys/firmware/efi/vars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c/data

L'avvio protetto con Secure Boot risulta abilitato se il comando stampa il risultato '1'. Alcune versioni di firmware sono note per non funzionare correttamente e visualizzare come risultato '0' anche nei casi in cui l'avvio protetto sia effettivamente attivato.

Avviare un kernel personalizzato

Secure boot non impedisce all'utente di utilizzare una versione di kernel da esso stesso compilata, è sufficiente, infatti, che tale kernel venga firmato con il proprio certificato personale e fare sì che quel certificato venga riconosciuto dal firmware o dal database MOK (Machine Owner Key, vedi il glossario), con la seguente procedura:

  1. crea una chiave X.509 personale e relativo certificato per firmare eseguibili e binari:
    openssl req -new -x509 -newkey rsa:2048 -sha256 -keyout key.asc -out cert.pem -nodes -days 666 -subj "/CN=$USER/"
  2. impacchetta chiave e certificato in un file con formato PKCS#12:
    openssl pkcs12 -export -inkey key.asc -in cert.pem -name kernel_cert -out cert.p12
  3. genera il database NSS che verrà usato da pesign:
    certutil -d . -N
  4. importa chiave e certificato, contenuti nel pacchetto PKCS#12, all'interno del database NSS:
    pk12util -d . -i cert.p12
  5. firma il kernel con quel nuovo certificato:
    pesign -n . -c kernel_cert -i arch/x86/boot/bzImage -o vmlinuz.signed -s
  6. visualizza l'elenco delle firme applicate all'immagine del kernel:
    pesign -n . -S -i vmlinuz.signed

A questo punto si potrà installare il kernel in /boot, come al solito. Dato che il kernel ha ora una nuova firma, sarà necessario importare nel firmware, o nel MOK, il certificato usato per firmarlo:

  1. converti il certificato nel formato DER per importarlo nel firmware UEFI o nel MOK:
    openssl x509 -in cert.pem -outform der -out cert.der
  2. copia il certificato nella partizione ESP, per un accesso più agevole al file:
    sudo cp cert.der /boot/efi/

Sfortunatamente mokutil al momento di scrivere non era ancora utilizzabile su openSUSE 12.3, per cui non c'è un metodo pratico per lanciare MOK automaticamente. La procedura qui di seguito illustra come lanciare MOK manualmente.

  • riavvia
  • nel menu di grub premi il tasto 'c'
  • digita (supponendo la partizione ESP sia 'gpt1' nel disco 'hd0'):
    chainloader (hd0,gpt1)/EFI/opensuse/MokManager.efi
    boot
  • seleziona "Enroll key from disk"
  • spostati in corrispondenza del file cert.der, poi premi Invio
  • segui le istruzioni per importare la chiave (enroll). Solitamente ciò avviene premendo il tasto '0' e quindi 'y' per confermare

In alternativa è possibile che il firmware fornisca metodi propri per aggiungere una nuova chiave al database 'db'.

Avviare il computer senza chiavi fornite dal produttore

Nel caso in cui il menu del firmware presenti l'opzione per reimpostare le chiavi usate per l'avvio protetto (reset chiavi per secure boot), si avrà allora la possibilità di installare un nuovo set di PK, KEK e db senza le chiavi di Microsoft. In tal caso importare il file /usr/lib64/efi/shim-opensuse.der all'interno di db, per far sì che venga avviato uno dei kernel di openSUSE. La versione di shim predefinita è firmata sia da Microsoft che da openSUSE ma alcune versioni di firmware non supportano più di una firma; se è questo il caso, installare invece /usr/lib64/efi/shim-opensuse.efi, che porta soltanto la firma di openSUSE, così come /boot/efi/EFI/opensuse/shim.efi.

Avviare un computer che supporta una sola firma con chiavi fornite dal produttore

Alcuni firmware potrebbero ancora non essere in grado di processare più di una firma contenuta nelle immagini EFI, e il shim predefinito in questo caso non funzionerebbe correttamente. Se il menu del firmware non dovesse prevedere la possibilità di installare una chiave nuova, sarà necessario aggirare la limitazione, estraendo manualmente la firma di openSUSE.

  1. Installare mozilla-nss-tools e pesign:
    zypper install mozilla-nss-tools pesign
  2. creare un database nss temporaneo:
    mkdir certdb
    certutil -N -d certdb
    (premi "Invio" per ignorare la richiesta di inserire la password)
  3. estrarre la firma di openSUSE
    pesign -n certdb/ -r -i /usr/lib64/efi/shim.efi -o shim.efi -u 1
  4. sostituire il file shim.efi predefinito con il nuovo file shim.efi, generato durante l'estrazione appena effettuata:
    mv shim.efi /boot/efi/EFI/opensuse/shim.efi
  5. eliminare il database nss temporaneo:
    rm -rf certdb

Questi passaggi dovranno essere ripetuti dopo ogni volta che viene aggiornato shim. Questo tipo di firmware dovrebbe essere sempre più raro, dato che il supporto per le firme multiple è già incluso nella versione corrente di edk2 da ben più di un anno, tuttavia il problema potrebbe ancora presentarsi nel caso di macchine datate.

Glossario

PK
La "Platform Key", con tale termine solitamente si fa riferimento al certificato installato nella macchina dal produttore dell'hardware. Per avere il permesso di modificare la KEK è necessaria una firma valida della PK.
KEK
La "Key Exchange Key", per aggiornare il database delle firme è richiesta una firma valida della "Key Exchange Key".
db
Il database delle firme (Signature Database) raccoglie certificati riconosciuti, firme o hash di file binari (eseguibili); solo i file binari verificabili usando quel database possono essere eseguiti dal firmware. Per aggiornare il database delle firme è richiesta una firma valida della KEK.
dbx
Il database delle firme vietate (Forbidden Signatures Database) è l'opposto di quello delle firme ('db'), sostanzialmente una lista nera di certificati, firme ed hash. Se un file binario corrisponde ad una qualsiasi delle voci in quella lista allora non può essere eseguito. Per aggiornare il database delle firme vietate è richiesta una firma valida della KEK.
ESP
La partizione di sistema EFI (EFI System Partition)
MOK
Machine Owner Keys (chiavi private dell'utente del computer). Un database supplementare di certificati o hash usato da MokManager. MokManager può essere utilizzato in modo interattivo dall'utente durante l'avvio del computer, allo scopo di aggiornare le MOK.