Nota:

Firma i moduli kernel da utilizzare con il boot sicuro UEFI

Questa esercitazione spiega come firmare i propri moduli da utilizzare con UEFI Secure Boot su Oracle Linux insieme a Unbreakable Enterprise Kernel installato. Il tutorial spiega anche come aggiungere il proprio certificato al portachiavi certificato attendibile del kernel nel caso in cui si stia utilizzando un kernel UEK R6 prima di UEK R6U3; e anche come utilizzare la utility mokutil per aggiornare la tabella di boot UEFI con il certificato di firma.

Avvertenza
Questa esercitazione è destinata agli sviluppatori che eseguono test software. Non utilizzare le procedure di questa esercitazione sui sistemi di produzione supportati da Oracle.

Prerequisiti

Obiettivi

Al termine dell'esercitazione, è necessario eseguire le operazioni riportate di seguito.

Installazione package richiesti

  1. Eseguire i comandi seguenti in base al sistema Oracle Linux.

    • Oracle Linux 8

      sudo dnf update
      sudo dnf group install "Development Tools"
      sudo dnf install kernel-uek kernel-uek-devel keyutils mokutil pesign
      
    • Oracle Linux 7

      sudo yum-config-manager --enable ol7_optional_latest
      sudo yum update
      sudo yum group install "Development Tools"
      sudo yum-config-manager --enable ol7_UEKR6 && yum-config-manager --disable ol7_UEKR5
      
  2. Riavvio del sistema.

Creazione di un modulo kernel personalizzato di esempio

Ai fini di questa esercitazione, creiamo e costruiamo un modulo kernel personalizzato di esempio. Nella maggior parte dei casi, il modulo è già fornito da un fornitore esterno e questo passo non è necessario. Il processo descritto qui è a scopo illustrativo.

  1. Creare una directory ~/hello.

  2. Creare il file ~/hello/hello.c con le voci seguenti:

    #include <linux/module.h>  
    #include <linux/kernel.h>  
    #include <linux/init.h>
    
    MODULE_LICENSE("GPL");  
    MODULE_AUTHOR("A.Developer");  
    MODULE_DESCRIPTION("Hello World Linux Kernel Module");
    
    static int __init hello_init(void)
    {  
      printk(KERN_INFO "Hello world!\n");  
      return 0;
    }
    
    static void __exit hello_exit(void)  
    {  
      printk(KERN_INFO "Unloading Hello world.\n");  
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    
  3. Creare il file ~/hello/Makefile con le voci seguenti:

    obj-m += hello.o
    
    all:  
      make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
    
    clean:  
      make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
    
    install:  
      cp hello.ko  /lib/modules/$(shell uname -r)/extra  
      depmod
    
  4. Creare e installare il modulo.

    cd ~/hello
    make && sudo make install
    
  5. Eseguire il test del modulo.

    sudo modprobe hello
    
    modprobe: ERROR: could not insert 'hello': Operation not permitted
    

    Se il sistema è in esecuzione in modalità Boot sicuro, modprobe non riesce perché il modulo non è ancora valido.

Creazione di certificati locali e firma del modulo

  1. Creare un file di configurazione OpenSSL per creare un certificato di firma locale.

    Tipo:

    cat >>/tmp/x509.conf <<EOF
    [ req ]
    default_bits = 4096
    distinguished_name = req_distinguished_name
    prompt = no
    string_mask = utf8only
    x509_extensions = extensions
    
    [ req_distinguished_name ]
    O = Module Signing Example
    CN = Module Signing Example Key
    emailAddress = first.last@example.com
    
    [ extensions ]
    basicConstraints=critical,CA:FALSE
    keyUsage=digitalSignature
    subjectKeyIdentifier=hash
    authorityKeyIdentifier=keyid
    EOF
    

    Per i campi O, CN e emailAddress, immettere valori più appropriati.

  2. Generare una nuova coppia di chiavi private/pubbliche in base alla nuova configurazione.

    Il certificato è valido per 10 anni (3.650 giorni).

    mkdir ~/certs
    cd ~/certs
    openssl req -x509 -new -nodes -utf8 -sha512 -days 3650 -batch -config /tmp/x509.conf -outform DER -out pubkey.der -keyout priv.key
    
    Generating a RSA private key
    ........................................................
    ............................++++
    writing new private key to 'priv.key'
    -----
    
  3. Esportare il certificato in formato PEM.

    openssl x509 -inform DER -in pubkey.der -out pubkey.pem
    
  4. Creare una versione PKCS#12 del certificato.

    Specificare la password di esportazione quando richiesto.

    openssl pkcs12 -export -inkey priv.key -in pubkey.pem -name cert -out cert.p12
    
    Enter Export Password:
    Verifying - Enter Export Password:
    
  5. Firmare il modulo utilizzando la chiave appena generata.

    cd ~/certs
    sudo /usr/src/kernels/$(uname -r)/scripts/sign-file sha512 priv.key pubkey.der /lib/modules/$(uname -r)/extra/hello.ko
    
  6. Con il comando modinfo, verificare che il modulo sia firmato con la chiave creata.

    modinfo hello
    
    filename:       /lib/modules/5.4.17-2036.103.3.1.el8uek.x86_64/extra/hello.ko
    description:    Hello World Linux Kernel Module
    author:         A.Developer
    license:        GPL
    srcversion:     D51FB4CF0B86314953EE797
    depends:        
    retpoline:      Y
    name:           hello
    vermagic:       5.4.17-2036.103.3.1.el8uek.x86_64 SMP mod_unload modversions 
    sig_id:         PKCS#7
    signer:         Module Signing Example Key
    sig_key:        AB:2C:E3:AB:87:D9:9C:6A:31:B8:80:20:D4:92:25:F3:9A:26:DC
    sig_hashalgo:   sha512
    signature:      9F:B0:25:CB:14:C1:C7:10:7F:60:1E:E6:66:82:64:58:91:1F:01:A5:
                    D9:03:1B:9C:2D:42:00:45:78:2B:FA:70:F8:C7:3B:1A:A2:42:00:09:
                    33:E0:81:1D:C6:E6:46:A5:FE:8B:9F:8C:3D:4E:A1:3A:05:52:ED:F6:
                    25:F9:88:98:D3:70:78:1D:7E:63:F3:73:C8:C8:14:C2:3A:52:B4:8F: 
                    ...
    

Aggiunta del certificato al keystore sicuro del kernel (UEK R6U2 e versioni successive)

Nota:
non è necessario eseguire questo passo se si utilizza UEK R6U3 o versione successiva. L'implementazione dell'avvio sicuro in UEK R6U3 viene aggiornata per consentire il caricamento del modulo per i moduli firmati con chiavi presenti nel database MOK. Per le release UEK R6 precedenti a UEK R6U3, i moduli possono essere caricati solo se le chiavi con cui sono firmate si trovano nel portachiavi sicuro incorporato del kernel.

  1. Creare un database NSS da utilizzare con pesign.

    cd ~/certs
    certutil -d . -N
    
    Enter a password which will be used to encrypt your keys.
    The password should be at least 8 characters long,
    and should contain at least one non-alphabetic character.
    
    Enter new password:
    Re-enter password:
    
  2. Aggiungere la chiave PCKS#12 al database.

    cd ~/certs
    pk12util -d . -i cert.p12
    
    Enter Password or Pin for "NSS Certificate DB":
    Enter password for PKCS12 file:
    pk12util: PKCS12 IMPORT SUCCESSFUL
    
  3. Inserire la chiave nel file bzImage del kernel.

    Nota: è possibile aggiungere al kernel solo un unico certificato personalizzato aggiuntivo in quanto la dimensione compressa dell'immagine di boot del kernel non può aumentare.

    cd ~/certs
    sudo /usr/src/kernels/$(uname -r)/scripts/insert-sys-cert -s /boot/System.map-$(uname -r) -z /boot/vmlinuz-$(uname -r) -c pubkey.der
    
    INFO:    Executing: gunzip <vmlinux-ceDv0X >vmlinux-rFFumH
    WARNING: Could not find the symbol table.
    INFO:    sym:    system_extra_cert
    INFO:    addr:   0xffffffff828915d6
    INFO:    size:   8194
    INFO:    offset: 0x1c915d6
    INFO:    sym:    system_extra_cert_used
    INFO:    addr:   0xffffffff828935d8
    INFO:    size:   0
    INFO:    offset: 0x1c935d8
    INFO:    sym:    system_certificate_list_size
    INFO:    addr:   0xffffffff828935e0
    INFO:    size:   0
    INFO:    offset: 0x1c935e0
    INFO:    Inserted the contents of pubkey.der into ffffffff828915d6.
    INFO:    Used 1481 bytes out of 8194 bytes reserved.
    INFO:    Executing: gzip -n -f -9 <vmlinux-rFFumH >vmlinux-5wHA2r
    
  4. Rimuovere la firma PE esistente e firmare nuovamente il kernel con quella nuova utilizzando la password del database NSS creata in precedenza.

    cd ~/certs
    sudo pesign -u 0 -i /boot/vmlinuz-$(uname -r) --remove-signature -o vmlinuz.unsigned
    sudo pesign -n . -c cert -i vmlinuz.unsigned -o vmlinuz.signed -s
    
    Enter Password or PIN for 'NSS Certificate DB":
    
  5. Copiare nuovamente il kernel firmato in /boot.

    cd ~/certs
    sudo cp -bf vmlinuz.signed /boot/vmlinuz-$(uname -r)
    

Iscrizione del certificato al database delle chiavi di boot sicuro UEFI

Per i kernel UEK R6 precedenti a UEK R6U3, è necessario registrare la chiave utilizzata per firmare l'immagine kernel nel database MOK. Per tutti gli altri kernel, la chiave utilizzata per firmare il modulo stesso è iscritta al database. Queste chiavi potrebbero essere le stesse se usate la stessa chiave per firmare il modulo e il kernel.

Nota: per ulteriori informazioni sull'uso della utility mokutil, vedere https://docs.oracle.com/learn/mokutil-uefi/.

  1. Aggiungere la chiave appropriata come chiave proprietario computer (MOK) alla partizione di boot UEFI. Il comando mokutil import richiede di immettere una password da fornire nel passo successivo.

    sudo mokutil --import pubkey.der
    
    input password:
    input password again:
    
  2. Riavviare il computer.

    Al reboot, lo SHIM UEFI dovrebbe avviare automaticamente MokManager, utilizzato per aggiungere la chiave MOK al database delle chiavi di boot sicuro UEFI.

    1. Premere un tasto per eseguire la gestione MOK.
      Fare clic su un tasto entro 10 secondi per interrompere il processo di boot per aggiungere il tasto MOK.
    2. Selezionare Iscrivi MOK.
    3. Selezionare Visualizza chiave 0.
    4. Verificare che la chiave corrisponda ai valori desiderati.
    5. Premere un tasto qualsiasi, quindi selezionare Continua.
    6. Selezionare Sì per registrare la chiave.
    7. Fornire la password utilizzata quando si importa la chiave utilizzando mokutil.
    8. Selezionare il riavvio.
  3. Verificare che il certificato sia installato nel keystore sicuro.

    sudo keyctl show %:.builtin_trusted_keys
    
    Keyring
     892034081 ---lswrv      0     0  keyring: .builtin_trusted_keys
     367808024 ---lswrv      0     0   \_ asymmetric: Oracle CA Server: fbcd3d4d950c6b2b0e01f0a146c5a4e3855ae704
     230958440 ---lswrv      0     0   \_ asymmetric: Module Signing Example Key: a43b4e638874b0656db2bc26216f56c0ac39f72b
     408597579 ---lswrv      0     0   \_ asymmetric: Oracle America, Inc.: Ksplice Kernel Module Signing Key: 09010ebef5545fa7c54b626ef518e077b5b1ee4c
     839574974 ---lswrv      0     0   \_ asymmetric: Oracle Linux Kernel Module Signing Key: 2bb352412969a3653f0eb6021763408ebb9bb5ab
    
  4. Verificare che il modulo possa essere caricato correttamente.

    sudo modprobe hello
    lsmod | grep hello
    hello                  16384  0
    
    dmesg | tail -2
    [  108.848848] hello: loading out-of-tree module taints kernel.
    [  108.849191] Hello world! 
    

Problemi noti

Le seguenti versioni del kernel su Oracle Linux 7 possono presentare problemi che accettano un nuovo certificato mantenendo la stessa dimensione compressa (o inferiore) per il file vmlinuz risultante. Si consiglia di eseguire l'aggiornamento alla release UEKR6 più recente disponibile prima di avviare questo processo.

Il problema di compressione non si osserva nelle versioni equivalenti di questi kernel su Oracle Linux 8.

Per ulteriori informazioni

Altre risorse di apprendimento

Esplora altri laboratori su docs.oracle.com/learn o accedi a più contenuti di apprendimento gratuito sul canale Oracle Learning YouTube. Inoltre, visitare education.oracle.com/learning-explorer per diventare Oracle Learning Explorer.

Per la documentazione del prodotto, visitare il sito Oracle Help Center.