Observação:

Assinar Módulos do Kernel para Uso com Inicialização Segura UEFI

Este tutorial explica como assinar seus próprios módulos para usar com a Inicialização Segura UEFI no Oracle Linux com o Unbreakable Enterprise Kernel instalado. O tutorial também explica como adicionar seu próprio certificado ao chaveiro de certificado confiável do kernel, caso você esteja usando um kernel UEK R6 antes de UEK R6U3; e também como usar o utilitário mokutil para atualizar o shim de inicialização UEFI com o certificado de assinatura.

Aviso
Este tutorial destina-se a desenvolvedores que estão realizando testes de software. Não use os procedimentos deste tutorial em sistemas de produção suportados pela Oracle.

Pré-requisitos

Objetivos

Ao final deste tutorial, você poderá fazer o seguinte:

Instalando Pacotes Necessários

  1. Execute os comandos a seguir com base no seu 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. Reinicializar o sistema.

Criando um exemplo de módulo kernel personalizado

Para fins deste tutorial, criamos e criamos um módulo kernel personalizado de amostra. Na maioria dos casos, o módulo já é fornecido por um fornecedor externo e esta etapa não é necessária. O processo descrito aqui é para fins ilustrativos.

  1. Crie um diretório ~/hello.

  2. Crie o arquivo ~/hello/hello.c com as seguintes 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. Crie o arquivo ~/hello/Makefile com as seguintes 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. Crie e instale o módulo.

    cd ~/hello
    make && sudo make install
    
  5. Teste o módulo.

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

    Se o sistema estiver em execução no modo de Inicialização Segura, modprobe falhará porque o módulo ainda não é válido.

Criando certificados locais e assinando o módulo

  1. Crie um arquivo de configuração OpenSSL para criar um certificado de assinatura 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 os campos O, CN e emailAddress, insira valores mais apropriados.

  2. Gere um novo par de chaves pública/privada com base na nova configuração.

    Observe que o certificado é válido por 10 anos (3.650 dias).

    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 o certificado no formato PEM.

    openssl x509 -inform DER -in pubkey.der -out pubkey.pem
    
  4. Crie uma versão PKCS#12 do certificado.

    Especifique a senha de exportação quando solicitado.

    openssl pkcs12 -export -inkey priv.key -in pubkey.pem -name cert -out cert.p12
    
    Enter Export Password:
    Verifying - Enter Export Password:
    
  5. Assine o módulo usando a chave que você acabou de gerar.

    cd ~/certs
    sudo /usr/src/kernels/$(uname -r)/scripts/sign-file sha512 priv.key pubkey.der /lib/modules/$(uname -r)/extra/hello.ko
    
  6. Com o comando modinfo, verifique se o módulo está assinado com a chave que você criou.

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

Adicionando o certificado ao chaveiro confiável do kernel (UEK R6U2 e abaixo)

Observação:
você não precisará executar esta etapa se estiver executando o UEK R6U3 ou uma versão posterior. A implementação do Secure Boot no UEK R6U3 é atualizada para permitir o carregamento de módulos para módulos assinados com chaves que estão no banco de dados MOK. Para releases UEK R6 anteriores ao UEK R6U3, os módulos só poderão ser carregados se as chaves com as quais foram assinadas estiverem no chaveamento confiável incorporado do kernel.

  1. Crie um banco de dados NSS para usar com 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. Adicione a chave PCKS#12 ao banco de dados.

    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. Insira a chave no bzImage do kernel.

    Observação: Somente um certificado personalizado adicional pode ser adicionado ao kernel porque o tamanho compactado da imagem de inicialização do kernel não pode ser aumentado.

    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. Remova a assinatura do PE existente e redesigne o kernel com a nova, usando a senha do banco de dados NSS criada 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 o kernel assinado de volta para /boot.

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

Inscrevendo o certificado no banco de dados de chaves de Inicialização Segura UEFI

Para kernel UEK R6 anteriores ao UEK R6U3, você deve inscrever a chave que foi usada para assinar a imagem do kernel no banco de dados MOK. Para todos os outros kernels, a chave que é usada para assinar o módulo em si é inscrita no banco de dados. Essas chaves podem ser as mesmas se você usou a mesma chave para assinar o módulo e o kernel.

Observação: Para obter mais informações sobre como usar o utilitário mokutil, consulte https://docs.oracle.com/learn/mokutil-uefi/.

  1. Adicione a chave apropriada como uma Chave do Proprietário da Máquina (MOK) ao shim de inicialização UEFI. O comando mokutil import solicita que você digite uma senha que precisará ser fornecida na próxima etapa.

    sudo mokutil --import pubkey.der
    
    input password:
    input password again:
    
  2. Reinicialize sua máquina.

    Na reinicialização, o UEFI SHIM deve iniciar automaticamente o MokManager, que é usado para adicionar a chave MOK ao banco de dados da chave de Inicialização Segura UEFI.

    1. Pressione uma tecla para executar o Gerenciamento MOK.
      Certifique-se de pressionar uma tecla em até 10 segundos para interromper o processo de inicialização e adicionar a tecla MOK.
    2. Selecione Inscrever MOK.
    3. Selecione View key 0.
    4. Verifique se a chave corresponde aos valores desejados.
    5. Pressione qualquer tecla e selecione continuar.
    6. Selecione Sim para inscrever a chave.
    7. Forneça a senha usada quando você importou a chave usando mokutil.
    8. Selecione reboot.
  3. Verifique se o certificado está instalado no chaveiro confiável.

    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 se o módulo pode ser carregado com sucesso.

    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 Conhecidos

As seguintes versões do kernel no Oracle Linux 7 podem apresentar problemas ao aceitar um novo certificado, mantendo o mesmo tamanho compactado (ou menor) para o arquivo vmlinuz resultante. É recomendável atualizar para a versão mais recente disponível UEKR6 antes de iniciar este processo.

O problema de compactação não é observado nas versões equivalentes desses kernels no Oracle Linux 8.

Para obter mais informações

Mais Recursos de Aprendizagem

Explore outros laboratórios em docs.oracle.com/learn ou acesse mais conteúdo de aprendizado gratuito no canal YouTube do Oracle Learning. Além disso, visite education.oracle.com/learning-explorer para se tornar um Oracle Learning Explorer.

Para obter a documentação do produto, visite o Oracle Help Center.