Cos’è UEFI Secure Boot?
UEFI Secure boot è un meccanismo di verifica per assicurare che il codice lanciato dal firmware sia affidabile.
Un uso corretto e sicuro di UEFI Secure Boot richiede che ogni binario caricato all’avvio sia convalidato rispetto a chiavi note, situate nel firmware, che denotano fornitori e fonti affidabili per i binari, o binari specifici affidabili che possono essere identificati tramite hashing crittografico.
La maggior parte dell’hardware x86 viene dalla fabbrica precaricato con le chiavi Microsoft. Questo significa che possiamo generalmente fare affidamento sul firmware di questi sistemi per fidarci dei binari che sono firmati da Microsoft, e la comunità Linux fa molto affidamento su questo presupposto per far funzionare il Secure Boot. Questo è lo stesso processo usato da Red Hat e SUSE, per esempio.
Molte architetture ARM e altre supportano anche UEFI Secure Boot, ma potrebbero non precaricare le chiavi nel firmware. Su queste architetture, potrebbe essere necessario ri-firmare le immagini di avvio con un certificato che viene caricato nel firmware dal proprietario dell’hardware.
Piano di implementazione iniziale: Piano di implementazione.
Architetture supportate
-
amd64: Un binario shim firmato da Microsoft e un binario grub firmato da Canonical sono forniti nell’archivio principale di Ubuntu come shim-signed o grub-efi-amd64-signed.
-
arm64: A partire dalla 20.04 (‘focale’), un binario shim firmato da Microsoft e un binario grub firmato da Canonical sono forniti nell’archivio principale di Ubuntu come shim-signed o grub-efi-arm64-signed. C’è un bug di GRUB sotto indagine che deve essere risolto prima che questo funzioni da un capo all’altro.
Testare UEFI Secure Boot
Se sei interessato a testare Secure Boot sul tuo sistema, consulta qui la guida: UEFI/SecureBoot/Testing.
Come funziona UEFI Secure Boot su Ubuntu
Su Ubuntu, tutti i binari pre-costruiti destinati ad essere caricati come parte del processo di avvio, con l’eccezione dell’immagine initrd, sono firmati dal certificato UEFI di Canonical, che è implicitamente affidabile essendo incorporato nel caricatore shim, a sua volta firmato da Microsoft.
Su architetture o sistemi in cui i certificati di firma precaricati da Microsoft non sono disponibili o caricati nel firmware, gli utenti possono sostituire le firme esistenti su shim o grub e caricarle come desiderano, verificando rispetto ai propri certificati importati nel firmware del sistema.
Quando il sistema si avvia, il firmware carica il binario di shim come specificato nelle variabili BootEntry del firmware. Ubuntu installa la propria BootEntry al momento dell’installazione e può aggiornarla ogni volta che il bootloader GRUB viene aggiornato. Poiché il binario di shim è firmato da Microsoft; è convalidato e accettato dal firmware quando si verifica rispetto ai certificati già presenti nel firmware. Poiché il binario shim incorpora un certificato Canonical così come il proprio database di fiducia, ulteriori elementi dell’ambiente di boot possono, oltre ad essere firmati da uno dei certificati accettabili precaricati nel firmware, essere firmati dalla chiave UEFI di Canonical.
La prossima cosa caricata da shim è l’immagine del secondo stadio. Questa può essere una delle due cose: o GRUB, se il sistema si sta avviando normalmente; o MokManager, se è richiesta la gestione delle chiavi, come configurato dalle variabili del firmware (di solito cambiate quando il sistema era precedentemente in esecuzione).
Se l’avvio è normale; viene caricato il binario di GRUB (grub*.efi) e viene tentata la sua convalida rispetto a tutte le fonti attendibili precedentemente conosciute. Il binario GRUB per Ubuntu è firmato dalla chiave UEFI di Canonical, quindi viene convalidato con successo e il processo di avvio continua.
Se si avvia per procedere con i compiti di gestione delle chiavi, viene caricato il binario MokManager (mm*.efi). Questo binario è esplicitamente fidato da shim essendo firmato da una chiave effimera che esiste solo mentre il binario di shim viene costruito. Questo significa che solo il binario di MokManager costruito con un particolare binario di shim potrà essere eseguito e limita la possibilità di compromettere l’uso di strumenti compromessi. MokManager permette a qualsiasi utente presente alla console del sistema di iscrivere chiavi, rimuovere chiavi fidate, iscrivere hash binari e attivare la convalida di Secure Boot a livello di shim, ma la maggior parte dei compiti richiede l’inserimento di una password impostata in precedenza per confermare che l’utente alla console è effettivamente la persona che ha richiesto le modifiche. Queste password sopravvivono solo attraverso una singola esecuzione di shim / MokManager; e vengono cancellate non appena il processo viene completato o annullato. Una volta che la gestione delle chiavi è completata, il sistema viene riavviato e non continua semplicemente con l’avvio, poiché le modifiche alla gestione delle chiavi possono essere richieste per completare con successo l’avvio.
Una volta che il sistema continua l’avvio con GRUB; il processo GRUB carica qualsiasi configurazione richiesta (di solito carica la configurazione dall’ESP (EFI System Partition), puntando a un altro file di configurazione sulla partizione root o di avvio), che lo indirizzerà all’immagine del kernel da caricare.
Le applicazioni EFI fino a questo punto hanno pieno accesso al firmware del sistema, compreso l’accesso alla modifica delle variabili di fiducia del firmware, il kernel da caricare deve anche essere convalidato rispetto al database di fiducia. I kernel ufficiali di Ubuntu essendo firmati dalla chiave UEFI di Canonical, vengono convalidati con successo, e il controllo viene consegnato al kernel. Le immagini Initrd non sono convalidate.
Nel caso di kernel non ufficiali, o kernel costruiti dagli utenti, devono essere prese ulteriori misure se gli utenti desiderano caricare tali kernel mantenendo le piene capacità di UEFI Secure Boot. Tutti i kernel devono essere firmati per poter essere caricati da GRUB quando UEFI Secure Boot è abilitato, quindi l’utente dovrà procedere con la propria firma. In alternativa, gli utenti possono desiderare di disabilitare la convalida in shim mentre si avvia con Secure Boot abilitato su un kernel ufficiale usando “sudo mokutil –disable-validation”, fornendo una password quando richiesto, e riavviando; oppure disabilitare completamente Secure Boot nel firmware.
Fino a questo punto, qualsiasi fallimento nel convalidare un’immagine da caricare viene incontrato con un errore critico che ferma il processo di avvio. Il sistema non continuerà l’avvio e potrebbe riavviarsi automaticamente dopo un periodo di tempo, dato che altre variabili BootEntry possono contenere percorsi di avvio validi e affidabili.
Una volta caricato, i kernel convalidati disabiliteranno i servizi di avvio del firmware, eliminando così i privilegi e passando effettivamente alla modalità utente; dove l’accesso alle variabili fidate è limitato alla sola lettura. Date le ampie autorizzazioni concesse ai moduli del kernel, qualsiasi modulo non incorporato nel kernel dovrà essere convalidato al momento del caricamento. I moduli costruiti e spediti da Canonical con i kernel ufficiali sono firmati dalla chiave UEFI di Canonical e, come tali, sono affidabili. I moduli personalizzati richiederanno all’utente di fare i passi necessari per firmare i moduli prima che il loro caricamento sia permesso dal kernel. Questo può essere ottenuto utilizzando il comando “kmodsign”.
I moduli non firmati sono semplicemente rifiutati dal kernel. Qualsiasi tentativo di inserirli con insmod o modprobe fallirà con un messaggio di errore.
Dato che molti utenti richiedono moduli di terze parti per far funzionare correttamente i loro sistemi o per far funzionare alcuni dispositivi; e che questi moduli di terze parti richiedono di essere costruiti localmente sul sistema per essere adattati al kernel in esecuzione, Ubuntu fornisce strumenti per automatizzare e semplificare il processo di firma.
Come posso fare la firma non automatica dei driver?
Alcuni progetti possono richiedere l’uso di driver del kernel personalizzati che non sono impostati in modo da funzionare con DKMS. In questi casi, le persone dovrebbero fare uso degli strumenti inclusi nel pacchetto shim-signed: lo script update-secureboot-policy è disponibile per generare un nuovo MOK (se nessun modulo costruito con DKMS ne ha già attivato la generazione).
Utilizzare il seguente comando per iscrivere una chiave esistente in shim:
sudo update-secureboot-policy --enroll-key
Se non esiste un MOK, lo script uscirà con un messaggio in tal senso. Se la chiave è già iscritta, lo script uscirà senza fare nulla. Se la chiave esiste ma non risulta essere iscritta, all’utente verrà richiesta una password da usare dopo il riavvio, in modo che la chiave possa essere iscritta.
Si può generare un nuovo MOK usando il seguente comando:
sudo update-secureboot-policy --new-key
E poi iscrivere la chiave appena generata in shim con il comando precedentemente menzionato per questo compito.
I moduli del kernel possono poi essere firmati con il comando kmodsign (vedi UEFI/SecureBoot/Signing) come parte del loro processo di costruzione.
Implicazioni di sicurezza nella gestione delle chiavi del proprietario della macchina
Il MOK generato al momento dell’installazione o all’aggiornamento è specifico della macchina, e permesso solo dal kernel o dallo shim per firmare i moduli del kernel, tramite l’uso di uno specifico OID KeyUsage (1.3.6.1.4.1.2312.16.1.2) che denota i limiti del MOK.
Le versioni recenti dello shim includono la logica per seguire le limitazioni delle chiavi di sola firma del modulo. Queste chiavi potranno essere iscritte nel firmware nel database di fiducia di shim, ma saranno ignorate quando shim o GRUB convalideranno le immagini da caricare nel firmware. La funzione verify() di shim convaliderà con successo solo le immagini firmate da chiavi che non includono l’OID “Module-signing only” (1.3.6.1.4.1.2312.16.1.2) KeyUsage. I kernel di Ubuntu usano il database di fiducia globale (che include sia quello di shim che quello del firmware) e accetteranno qualsiasi chiave inclusa come chiave di firma quando si caricano i moduli del kernel.
Viste le limitazioni imposte al MOK generato automaticamente e il fatto che gli utenti con accesso da superutente al sistema e accesso alla console di sistema per inserire la password richiesta quando si iscrivono le chiavi hanno già un accesso di alto livello al sistema; la chiave MOK generata è tenuta sul filesystem come file regolare di proprietà di root con permessi di sola lettura. Questo è ritenuto sufficiente per limitare l’accesso al MOK per la firma da parte di utenti o script malevoli, specialmente se si considera che nessun MOK esiste sul sistema a meno che non richieda driver di terze parti. Questo limita la possibilità di compromissione dall’uso improprio di una chiave MOK generata per firmare un modulo maligno del kernel. Questo equivale alla compromissione delle applicazioni userland che sarebbe già possibile con l’accesso del superutente al sistema, e la messa in sicurezza di questo è fuori dallo scopo di UEFI Secure Boot.
I sistemi precedenti potrebbero avere la convalida di Secure Boot disabilitata nello shim. Come parte del processo di aggiornamento, questi sistemi saranno migrati per riabilitare la convalida di Secure Boot in shim e iscrivere una nuova chiave MOK quando applicabile.
Processo di generazione e firma della chiave MOK
Il processo di generazione e firma della chiave è leggermente diverso a seconda che si tratti di una nuova installazione o di un aggiornamento di un sistema che precedentemente eseguiva Ubuntu; questi due casi sono chiaramente indicati di seguito.
In tutti i casi, se il sistema non si sta avviando in modalità UEFI, non avverrà alcun passaggio speciale di firma del modulo del kernel o generazione della chiave.
Se Secure Boot è disabilitato, la generazione di MOK e l’iscrizione avviene ancora, in quanto l’utente può successivamente abilitare Secure Boot. Il sistema dovrebbe funzionare correttamente se questo è il caso.
L’utente installa Ubuntu su un nuovo sistema
L’utente passa attraverso il programma di installazione. All’inizio, quando si prepara all’installazione e solo se il sistema richiede moduli di terze parti per funzionare, all’utente viene richiesta una password di sistema che è chiaramente contrassegnata come necessaria dopo il completamento dell’installazione, e mentre il sistema viene installato, un nuovo MOK viene generato automaticamente senza ulteriori interazioni dell’utente.
I driver di terze parti o i moduli del kernel richiesti dal sistema saranno compilati automaticamente quando il pacchetto viene installato, e il processo di compilazione include una fase di firma. Il passo di firma utilizza automaticamente il MOK generato in precedenza per firmare il modulo, in modo che possa essere immediatamente caricato una volta che il sistema viene riavviato e il MOK è incluso nel database di fiducia del sistema.
Una volta che l’installazione è completa e il sistema viene riavviato, al primo avvio all’utente viene presentato il programma MokManager (parte dello shim loader installato), come una serie di pannelli in modalità testo che permettono all’utente di iscrivere il MOK generato. L’utente seleziona “Enroll MOK”, gli viene mostrata l’impronta digitale del certificato da iscrivere e gli viene richiesto di confermare l’iscrizione. Una volta confermata, il nuovo MOK verrà inserito nel firmware e all’utente verrà chiesto di riavviare il sistema.
Quando il sistema si riavvia, i driver di terze parti firmati dal MOK appena iscritto saranno caricati come necessario.
L’utente aggiorna un sistema Ubuntu abilitato UEFI a una nuova release in cui il sistema richiede driver di terze parti
Al momento dell’aggiornamento, i pacchetti shim e shim-firmati vengono aggiornati. Le attività post-installazione del pacchetto shim-signed procedono a generare un nuovo MOK, e richiedono all’utente una password che è chiaramente indicata come necessaria una volta che il processo di aggiornamento è completato e il sistema riavviato.
Durante l’aggiornamento, i pacchetti del kernel e i moduli di terze parti vengono aggiornati. I moduli di terze parti sono ricostruiti per i nuovi kernel e il loro processo di post-costruzione procede a firmarli automaticamente con il MOK.
Dopo l’aggiornamento, si raccomanda all’utente di riavviare il proprio sistema.
Al riavvio, all’utente viene presentato il programma MokManager (parte dello shim loader installato), come una serie di pannelli in modalità testo che permettono all’utente di iscrivere il MOK generato. L’utente seleziona “Enroll MOK”, gli viene mostrata l’impronta digitale del certificato da iscrivere e gli viene richiesto di confermare l’iscrizione. All’utente viene anche presentata una richiesta di riattivare la convalida di Secure Boot (nel caso in cui sia stata trovata disabilitata); e MokManager richiede nuovamente la conferma da parte dell’utente. Una volta che tutti i passi sono confermati, la convalida dello shim è riabilitata, il nuovo MOK sarà inserito nel firmware e all’utente sarà chiesto di riavviare il sistema.
Quando il sistema si riavvia, i driver di terze parti firmati dal MOK appena iscritto saranno caricati come necessario.
In tutti i casi, una volta che il sistema è in esecuzione con UEFI Secure Boot abilitato e una versione recente di shim; l’installazione di qualsiasi nuovo modulo DKMS (driver di terze parti) procederà a firmare il modulo costruito con il MOK. Questo avverrà senza l’interazione dell’utente se una chiave MOK valida esiste sul sistema e sembra essere già iscritta.
Se non esiste un MOK o il MOK esistente non è iscritto, una nuova chiave sarà creata automaticamente appena prima della firma e all’utente sarà richiesto di iscrivere la chiave fornendo una password che sarà richiesta al riavvio.