in

Assinatura de inicialização segura no UBUNTU

Todo o conceito de inicialização segura exige que exista uma cadeia de confiança, desde a primeira coisa carregada pelo hardware até os módulos do kernel.

Todo o conceito de inicialização segura no Ubuntu exige que exista uma cadeia de confiança, desde a primeira coisa carregada pelo hardware (o código do firmware), até as últimas coisas carregadas pelo sistema operacional como parte do kernel: os módulos . Em outras palavras, não apenas o firmware e o bootloader requerem assinaturas, o kernel e os módulos também. As pessoas geralmente não mudam tanto o firmware ou o bootloader, mas e quanto a reconstruir um kernel ou adicionar módulos extras fornecidos pelos fabricantes de hardware?

Assinatura de inicialização segura no UBUNTU

Ubuntu boot seguro

A história de inicialização segura no Ubuntu inclui o fato de que você pode querer construir seu próprio kernel (mas esperamos que você possa apenas usar o kernel genérico que enviamos no arquivo), e que você pode instalar seus próprios módulos de kernel. Isso significa assinar binários UEFI e módulos do kernel, o que pode ser feito com seu próprio conjunto de ferramentas.

Mas, primeiro, mais informações sobre a cadeia de confiança usada para inicialização segura.

Certificados em shim

Para começar a assinar coisas para UEFI Secure Boot, você precisa criar um certificado X509 que pode ser importado no firmware; diretamente através do firmware do fabricante, ou mais facilmente, por meio de shim.

Criar um certificado para uso em UEFI Secure Boot é relativamente simples. O openssl pode fazer isso executando alguns comandos SSL. Agora, precisamos criar um certificado SSL para assinatura de módulo …

Primeiro, vamos criar algumas configurações para permitir que o openssl saiba o que queremos criar (vamos chamá-lo de ‘openssl.cnf’):

# Esta definição impede as seguintes linhas de obstrução se o HOME não for
# definiram.
HOME = .
RANDFILE = $ENV::HOME/.rnd
[ req ]
distinguished_name = req_distinguished_name
x509_extensions = v3
string_mask = utf8only
prompt = no
[ req_distinguished_name ]
countryName = CA
stateOrProvinceName = Quebec
localityName = Montreal
0.organizationName = cyphermox
commonName = Secure Boot Signing
emailAddress = [email protected]
[ v3 ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical,CA:FALSE
extendedKeyUsage = codeSigning,1.3.6.1.4.1.311.10.3.6,1.3.6.1.4.1.2312.16.1.2
nsComment = “OpenSSL Generated Certificate”

Atualize os valores em “[req_distinguished_name]” ou livre-se dessa seção completamente (junto com o campo “distinguished_name”) e remova o campo “prompt”. Em seguida, o openssl solicitará os valores que você deseja definir para a identificação do certificado.

A identificação em si não importa muito, mas alguns dos valores posteriores são importantes: por exemplo, queremos ter certeza de que “1.3.6.1.4.1.2312.16.1.2” está incluído em extendedKeyUsage, e é esse OID que vai dizer shim é um certificado de assinatura de módulo.

Então, podemos começar a parte divertida: criar as chaves privadas e públicas.

openssl req -config ./openssl.cnf \
-new -x509 -newkey rsa: 2048 \
-nodes -days 36500 -outform DER \
-keyout “MOK.priv” \
-out “MOK.der”

Este comando criará a parte privada e pública do certificado para assinar coisas. Você precisa de ambos os arquivos para assinar; e apenas a parte pública (MOK.der) para registrar a chave no shim.

Registrando a chave

Dando continuidade ao processo de inicialização segura no Ubuntu, agora para garantir a inicialzação segurno no Ubuntu, vamos registrar a chave que acabamos de criar no shim. Isso faz com que seja aceito como uma chave de assinatura válida para qualquer módulo que o kernel deseja carregar, bem como uma chave válida se você quiser construir seu próprio gerenciador de inicialização ou kernels (desde que você não inclua isso ‘1.3. 6.1.4.1.2312.16.1.2 ‘OID discutido anteriormente).

Para registrar uma chave, use o comando mokutil:

sudo mokutil --import MOK.der

Siga as instruções para inserir uma senha que será usada para garantir que você realmente deseja registrar a chave em um minuto.

Feito isso, reinicie. Antes de carregar o GRUB, o shim mostrará uma tela azul (que na verdade é outra parte do projeto do shim chamada “MokManager”). use essa tela para selecionar “Inscrever MOK” e siga os menus para concluir o processo de inscrição. Você também pode ver algumas das propriedades da chave que está tentando adicionar, apenas para ter certeza de que é realmente a correta usando “Exibir chave”. O MokManager pedirá a senha que digitamos antes ao executar o mokutil; e salvará a chave e reiniciaremos novamente.

Vamos assinar coisas

Antes de assinarmos, vamos ter certeza de que a chave que adicionamos realmente é vista pelo kernel. Para fazer isso, podemos examinar / proc / keys:

$ sudo cat / proc / keys
0020f22a I--Q--- 1 perm 0b0b0000 0 0 user invocation_id: 16
0022a089 I------ 2 perm 1f0b0000 0 0 keyring .builtin_trusted_keys: 1
003462c9 I--Q--- 2 perm 3f030000 0 0 keyring _ses: 1
00709f1c I--Q--- 1 perm 0b0b0000 0 0 user invocation_id: 16
00f488cc I--Q--- 2 perm 3f030000 0 0 keyring _ses: 1
[…]
1dcb85e2 I ------ 1 perm 1f030000 0 0 assimetri Chave de kernel gerada automaticamente em tempo de compilação: eae8fa5ee6c91603c031c81226b2df4b135df7d2: X509.rsa 135df7d2 []
[…]

Apenas certifique-se de que existe uma chave com os atributos (commonName, etc.) que você inseriu anteriormente

Para assinar módulos do kernel, podemos usar o comando kmodsign:

kmodsign sha512 MOK.priv MOK.der module.ko

module.ko
deve ser o nome do arquivo de um módulo do kernel que você deseja assinar. A assinatura será anexada a ela pelo kmodsign, mas se você preferir manter a assinatura separada e concatená-la no módulo você mesmo, pode fazer isso também (consulte ‘kmosign –help’).

Você pode validar se o módulo está assinado verificando se ele inclui a string ‘~ Module signature appended ~’:

$ hexdump -Cv module.ko | tail -n 5
00002c20 10 14 08 cd eb 67 a8 3d ac 82 e1 1d 46 b5 5c 91 |…..g.=….F.\.|
00002c30 9c cb 47 f7 c9 77 00 00 02 00 00 00 00 00 00 00 |..G..w……….|
00002c40 02 9e 7e 4d 6f 64 75 6c 65 20 73 69 67 6e 61 74 |..~Module signat|
00002c50 75 72 65 20 61 70 70 65 6e 64 65 64 7e 0a |ure appended~.|
00002c5e

Você também pode usar o hexdump dessa forma para verificar se a chave de assinatura é a que você criou.

E quanto aos kernels e bootloaders?

Para assinar um kernel customizado ou qualquer outro binário EFI que você deseja carregar por shim, você precisará usar um comando diferente: sbsign. Infelizmente, precisaremos do certificado em um formato diferente neste caso.

Vamos converter o certificado que criamos anteriormente em PEM:

openssl x509 -em MOK.der -inform DER -outform PEM -out MOK.pem

Agora, podemos usar isso para assinar nosso binário EFI:

sbsign --key MOK.priv --cert MOK.pem my_binary.efi --output my_binary.efi.signed

Contanto que a chave de assinatura esteja registrada no shim e não contenha o OID anterior (já que isso limita o uso da chave para a assinatura do módulo do kernel), o binário deve ser carregado perfeitamente pelo shim.

Fazendo assinaturas fora do shim

Se você não quiser usar shim para lidar com chaves (mas eu recomendo que você use), você precisará criar certificados diferentes; sendo um deles o PK (Platform Key) do sistema, que você pode registrar no firmware diretamente via KeyTool ou alguma ferramenta de firmware fornecida com seu sistema.

Dando continuidade ao processo de inicialização segura no Ubuntu, não iremos elaborar os passos para cadastrar as chaves no firmware, pois tende a variar de sistema para sistema, mas a ideia principal é colocar o sistema em “Modo de Configuração” de Boot Seguro; execute o KeyTool (que é seu próprio binário EFI que você mesmo pode construir e executar) e registrar as chaves – primeiro instalando as chaves KEK e DB e finalizando com o PK. Esses arquivos precisam estar disponíveis em alguma partição FAT.

Eu tenho esse script para gerar os certificados e arquivos corretos; que posso compartilhar (e ele mesmo é copiado de algum lugar, não me lembro):

#! / bin / bash
echo -n “Digite um nome comum para incorporar nas chaves:”
read NAME
openssl req -new -x509 -newkey rsa:2048 -subj “/CN=$NAME PK/” -keyout PK.key \
-out PK.crt -days 3650 -nodes -sha256
openssl req -new -x509 -newkey rsa:2048 -subj “/CN=$NAME KEK/” -keyout KEK.key \
-out KEK.crt -days 3650 -nodes -sha256
openssl req -new -x509 -newkey rsa:2048 -subj “/CN=$NAME DB/” -keyout DB.key \
-out DB.crt -days 3650 -nodes -sha256
openssl x509 -in PK.crt -out PK.cer -outform DER
openssl x509 -in KEK.crt -out KEK.cer -outform DER
openssl x509 -in DB.crt -out DB.cer -outform DER
GUID=`python -c ‘import uuid; print str(uuid.uuid1())’`
echo $GUID > myGUID.txt
cert-to-efi-sig-list -g $GUID PK.crt PK.esl
cert-to-efi-sig-list -g $GUID KEK.crt KEK.esl
cert-to-efi-sig-list -g $GUID DB.crt DB.esl
rm -f noPK.esl
touch noPK.esl
sign-efi-sig-list -t “$(date --date=’1 second’ +’%Y-%m-%d %H:%M:%S’)” \
-k PK.key -c PK.crt PK PK.esl PK.auth
sign-efi-sig-list -t “$(date --date=’1 second’ +’%Y-%m-%d %H:%M:%S’)” \
-k PK.key -c PK.crt PK noPK.esl noPK.auth
chmod 0600 *.key
echo “”
echo “”
echo “”
echo “Para usar com o KeyTool, copie os arquivos * .auth e * .esl para um FAT USB”
echo “unidade flash ou para a partição do sistema EFI (ESP).”
echo “Para uso com a maioria dos gerenciadores de chaves integrados dos UEFIs, copie os arquivos * .cer.”
echo “”

A mesma lógica aplica-se anteriormente: assine coisas usando sbsign ou kmodsign conforme necessário (use os arquivos .crt com sbsign e os arquivos .cer com kmodsign); e, desde que as chaves estejam devidamente registradas no firmware ou no shim, elas serão carregadas com sucesso.

O que está por vir para a inicialização segura no Ubuntu

Assinar coisas é complexo – você precisa criar certificados SSL, inscrevê-los no firmware ou shim … Você precisa ter um bom conhecimento prévio de como a inicialização segura funciona e quais comandos são usados. É bastante óbvio que isso não está ao alcance de todos e, em primeiro lugar, é uma experiência um tanto ruim. Por esse motivo, estamos trabalhando para tornar mais fácil a criação, inscrição e assinaturas de chaves ao instalar os módulos DKMS.

update-secureboot-policy logo deverá permitir que você gere e registre uma chave; e o DKMS será capaz de assinar coisas sozinho usando essa chave.

Conclusão

Como pode ser observado neste tutorial, o uso do certificado digital está a cada dia mais presente de modo a ampliar a segurança dos UBUNTU e demais sistemas operacionais LINUX, Bem como dar segurança desde boot até o carregamento dos módulos do Kernel.

Fonte: UBUNTU

Segue abaixo mais alguns artigos sobre os temas abordados nesta matéria.

Lançado Linux Lite 5.2 baseado no Ubuntu 20.04.1 LTS

LINUX – conheça comandos básicos e mais úteis

Gerencie a expiração dos certificados de SSL