Nota:

Firmar módulos de núcleo para usar con el inicio seguro UEFI

En este tutorial se explica cómo firmar sus propios módulos para usar con el inicio seguro de UEFI en Oracle Linux con Unbreakable Enterprise Kernel instalado. En el tutorial también se explica cómo agregar su propio certificado a la clave de certificado de confianza del núcleo en el caso de que esté utilizando un núcleo UEK R6 antes de UEK R6U3; y también cómo usar la utilidad mokutil para actualizar el límite de inicio UEFI con el certificado de firma.

Advertencia
Este tutorial está destinado a desarrolladores que realizan pruebas de software. No utilice los procedimientos de este tutorial en los sistemas de producción soportados por Oracle.

Requisitos

Objetivos

Al final de este tutorial, debe poder hacer lo siguiente:

Instalando Paquetes Necesarios

  1. Ejecute los siguientes comandos en función del 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. Reinicie el sistema.

Creación de un ejemplo de módulo de núcleo personalizado

Para este tutorial, creamos y creamos un ejemplo de módulo de núcleo personalizado. En la mayoría de los casos, el módulo ya lo proporciona un proveedor externo y este paso no es necesario. El proceso descrito aquí tiene fines ilustrativos.

  1. Cree un directorio ~/hello.

  2. Cree el archivo ~/hello/hello.c con las siguientes entradas:

    #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. Cree el archivo ~/hello/Makefile con las siguientes entradas:

    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. Cree y, a continuación, instale el módulo.

    cd ~/hello
    make && sudo make install
    
  5. Pruebe el módulo.

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

    Si el sistema se está ejecutando en modo de inicio seguro, modprobe falla porque el módulo aún no es válido.

Creación de certificados locales y firma del módulo

  1. Cree un archivo de configuración OpenSSL para crear un certificado de firma local.

    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
    

    Para los campos O, CN y emailAddress, introduzca valores que sean más adecuados.

  2. Genere un nuevo par de claves privadas/públicas en función de la nueva configuración.

    Tenga en cuenta que el certificado es válido durante 10 años (3.650 días).

    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. Exporte el certificado en formato PEM.

    openssl x509 -inform DER -in pubkey.der -out pubkey.pem
    
  4. Cree una versión PKCS#12 del certificado.

    Especifique la contraseña de exportación cuando se le solicite.

    openssl pkcs12 -export -inkey priv.key -in pubkey.pem -name cert -out cert.p12
    
    Enter Export Password:
    Verifying - Enter Export Password:
    
  5. Firme el módulo con la clave que acaba de generar.

    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 el comando modinfo, verifique que el módulo esté firmado con la clave que ha creado.

    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: 
                    ...
    

Agregación del certificado al teclado de confianza del núcleo (UEK R6U2 e inferior)

Nota:
No es necesario realizar este paso si ejecuta UEK R6U3 o posterior. La implementación de inicio seguro en UEK R6U3 se actualiza para permitir la carga del módulo para módulos firmados con claves en la base de datos MOK. Para las versiones de UEK R6 anteriores a UEK R6U3, los módulos solo pueden cargarse si las claves con las que están firmadas están en el teclado de confianza incorporado del núcleo.

  1. Cree una base de datos NSS para utilizarla 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. Agregue la clave PCKS#12 a la base de datos.

    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. Inserte la clave en el bzImage del núcleo.

    Nota: Sólo se puede agregar un único certificado personalizado adicional al núcleo porque el tamaño comprimido de la imagen de inicio del núcleo no puede aumentar.

    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. Elimine la firma de PE existente y vuelva a firmar el núcleo con el nuevo mediante la contraseña de base de datos NSS que creó anteriormente.

    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. Copie el núcleo firmado de nuevo a /boot.

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

Inscripción del certificado en la base de datos de claves de inicio seguro de UEFI

Para los núcleos UEK R6 anteriores a UEK R6U3, debe inscribir la clave que se utilizó para firmar la imagen del núcleo en la base de datos MOK. Para todos los demás núcleos, la clave que se utiliza para firmar el módulo en sí se inscribe en la base de datos. Estas claves pueden ser las mismas si ha utilizado la misma clave para firmar el módulo y el núcleo.

Nota: Para obtener más información sobre el uso de la utilidad mokutil, consulte https://docs.oracle.com/learn/mokutil-uefi/.

  1. Agregue la clave adecuada como clave de propietario de máquina (MOK) al simulador de inicio UEFI. El comando mokutil import le solicita que introduzca una contraseña que deberá proporcionar en el siguiente paso.

    sudo mokutil --import pubkey.der
    
    input password:
    input password again:
    
  2. Reinicie el equipo.

    Al reiniciar, UEFI SHIM debe iniciar automáticamente MokManager, que se utiliza para agregar la clave MOK a la base de datos de claves de inicio segura UEFI.

    1. Pulse una tecla para realizar la gestión de MOK.
      Asegúrese de pulsar una tecla en 10 segundos para interrumpir el proceso de inicio y agregar la tecla MOK.
    2. Seleccione Enroll MOK.
    3. Seleccione la tecla de vista 0.
    4. Verifique que la clave coincida con los valores que desea.
    5. Pulse cualquier tecla y, a continuación, seleccione Continue.
    6. Seleccione Sí para inscribir la clave.
    7. Proporcione la contraseña utilizada al importar la clave mediante mokutil.
    8. Seleccione reboot (Reiniciar).
  3. Verifique que el certificado esté instalado en el teclado de confianza.

    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. Verifique que el módulo se pueda cargar correctamente.

    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! 
    

Problemas conocidos

Las siguientes versiones del núcleo en Oracle Linux 7 pueden tener problemas para aceptar un nuevo certificado y, al mismo tiempo, mantener el mismo tamaño comprimido (o menor) para el archivo vmlinuz resultante. Se recomienda actualizar a la última versión disponible de UEKR6 antes de iniciar este proceso.

El problema de compresión no se observa en las versiones equivalentes de estos núcleos en Oracle Linux 8.

Para más información

Más recursos de aprendizaje

Explore otras prácticas en docs.oracle.com/learn o acceda a contenido de aprendizaje más gratuito en el canal YouTube de Oracle Learning. Además, visite education.oracle.com/learning-explorer para convertirse en un explorador de formación de Oracle.

Para obtener documentación sobre los productos, visite Oracle Help Center.