Inicialização segura no i.MX6

Inicialização segura no i.MX6


Ao desenvolver qualquer projeto para sistemas embarcados, o desenvolvedor deve resolver dois problemas adicionais:

  • Como proteger o firmware contra falsificação no produto;
  • Como proteger o software da cópia.

Este artigo descreve como proteger o processador i.MX6 de alterar o carregador de inicialização no produto e complicar o processo de cópia do firmware.



Introdução


Proteger a propriedade intelectual, caso o projeto bare metal [1] ajude principalmente um complexo de hardware, presente no microcontrolador e externo. Exemplos são dados em um site respeitável [2] . Métodos de software adicionais, como [3] são usados, no entanto, são baseados no mecanismo de proteção desconhecido. Isso se deve ao baixo poder de computação dos dispositivos e ao inconveniente de implementar a geração dinâmica de firmware.

Quando o SoC entra em jogo com sistemas operacionais como o Linux, a proteção precisa ser organizada simultaneamente em vários níveis:

  • Nível final da aplicação
  • Nível do sistema operacional
  • Nível do carregador de inicialização

No caso de obter acesso em qualquer um dos níveis, é fácil influenciar o software de outros níveis e fazer alterações nas interações entre níveis.
Os exemplos mais simples: seu software instalado no Linux se comunica através do protocolo UART (por exemplo, através de / dev / ttyACM0) com um microcontrolador. Um invasor que obtém acesso ao sistema usa o mesmo recurso UART e repete pacotes enviados aleatoriamente. Ou, por exemplo, se o driver estiver embutido no kernel, o invasor recompila o kernel reescrevendo o código do driver UART de outra maneira. A aplicação final não sabe o que está acontecendo.

O que é inicialização segura e por que é necessário?


O primeiro nível de proteção do seu software no sistema de destino é a inicialização segura. A seguir, a inicialização segura é explicada para processadores da família i.MX6.

A inicialização segura no i.MX6 é implementada por meio do High Assurance Boot (HAB) e pode executar duas funções:

  • modo de segurança
  • download criptografado.

Neste artigo, descreverei o processo de garantir o carregamento seguro do processador. O I.MX6 também implementa um algoritmo que fornece criptografia para o carregador de inicialização. No entanto, seu uso requer a geração de um gerenciador de inicialização exclusivo para cada produto, pois utiliza uma função de criptografia exclusiva para cada processador. Este é um procedimento inconveniente na série, então não o descrevi. Se você tem algo a dizer sobre esse assunto, ficarei feliz em ouvir.
A inicialização segura tenta garantir que o carregador de inicialização seja iniciado no seu produto, com o kernel que você carregou nele.

Sobre a definição que eu dei inicialização segura. A inicialização segura não impede que você copie o produto. Sim, isso torna o procedimento mais difícil, mas não muito. O carregador de inicialização não pode assinar todo o FS, portanto, não fornece proteção no nível do SO e no nível do aplicativo final. Tudo funciona de forma clássica: por meio de criptografia assimétrica. Vou descrever o processo nos dedos, que pode ser lido mais profundamente em [4]. O carregador de inicialização indica o script para o HAB, onde as áreas de memória assinadas são indicadas e onde está a assinatura digital. A chave pública está pré-localizada na memória do processador One time programable (OTP). Ao carregar, o script verifica a área de memória especificada usando a assinatura digital anexada e uma chave com fio. Se o teste falhar, o processador não inicia o download. A operação HAB também deve ser ativada definindo um pouco na região da memória OTP.

Desvantagens da inicialização segura:

  • Se o HAB não estiver ativado, o firmware ainda será iniciado. Isso significa que, sem adicionar. métodos de proteção, seu firmware será executado em uma cópia do produto. Para impedir que isso aconteça, o carregador de inicialização deve ativar o HAB independentemente na inicialização. Mas, inserindo uma unidade flash USB em outro produto e esquecendo de atualizar a chave pública, você pode jogar fora o processador.
  • Ao acessar a memória do processador, você pode copiar a chave pública, isso é suficiente para copiar o produto.

Implementação


Em geral, existem muitos artigos em inglês [5] [6] na Internet sobre o tópico de implementação, mas nenhum método proposto decolou de uma vez e os links para o software começaram a morrer, então decidi salvá-lo como um artigo principalmente para mim, quando Voltarei a esta questão no futuro.

Primeiro você precisa baixar o seguinte software: ferramenta de assinatura de código [7] e os scripts necessários para gerar chaves e assinatura. No arquivo especificado, eu removi todos os utilitários e bibliotecas desnecessários, pois existem muitas coisas não utilizadas para nossa tarefa.

Em seguida, você precisa gerar as chaves:

cd ${CST_PATH}/release/keys
echo ${serial} > serial //8 ,     
echo ${password} >  key_pass.txt //   ,     
echo ${password} >>  key_pass.txt //
./hab4_pki_tree.sh //     
Do you want to use an existing CA key (y/n)?: n 
Do you want to use Elliptic Curve Cryptography (y/n)?: n
Enter key length in bits for PKI tree: 4096
Enter PKI tree duration (years): 10
How many Super Root Keys should be generated? 4
Do you want the SRK certificates to have the CA flag set? (y/n)?: y
 ../linux64/bin/srktool -h 4 -t SRK_1_2_3_4_table.bin -e SRK_1_2_3_4_fuse.bin \
 -d sha256 -c ./SRK1_sha256_4096_65537_v3_ca_crt.pem,\
./SRK2_sha256_4096_65537_v3_ca_crt.pem,./SRK3_sha256_4096_65537_v3_ca_crt.pem,\
./SRK4_sha256_4096_65537_v3_ca_crt.pem -f 1

O script de geração de chaves levanta as questões acima. Dei um exemplo de opções padrão. A resposta para eles determina como as chaves e parâmetros gerados das chaves geradas serão chamados. Considere com outros comandos. Em seguida, lemos a chave pública necessária para gravar no processador. Usaremos um script conveniente de [5] para isso .

cd ${CST_PATH}/release/linux64/bin
./var-u-boot_fuse_commands.sh 
fuse prog 3 0 0xFFFFFFFF //   uboot.
fuse prog 3 1 0xFFFFFFFF //     
fuse prog 3 2 0xFFFFFFFF //       .
fuse prog 3 3 0xFFFFFFFF //  -   .
fuse prog 3 4 0xFFFFFFFF //      .
fuse prog 3 5 0xFFFFFFFF //
fuse prog 3 6 0xFFFFFFFF  //
fuse prog 3 7 0xFFFFFFFF //

Esta tarefa pode ser aplicada ao uboot com SPL integrado ou com SPL e uboot separados (versão rocko, por exemplo). Estou escrevendo um release para que você saiba onde eles são usados ​​como padrão. Se você mesmo compilar o uboot, provavelmente o seu SPL será integrado ao uboot. Um ponto importante no carregador de inicialização defconfig é adicionar as seguintes opções:

CONFIG_SECURE_BOOT=y
CONFIG_SYS_FSL_HAS_SEC=y 
#define CONFIG_SYS_FSL_SEC_COMPAT    4 /* HAB version */
#define CONFIG_FSL_CAAM
#define CONFIG_CMD_DEKBLOB
#define CONFIG_SYS_FSL_SEC_LE
#define CONFIG_FAT_WRITE

Essas opções ativam drivers para trabalhar com módulos de hardware. Tudo é como no menuconfig para Linux. Ao compilar o carregador de inicialização, use o modo detalhado (remova V = 1. A montagem com este parâmetro está escrita no guia. No entanto, eu mesmo a limpei). Nesse caso, informações sobre o endereço do ponto de entrada e outras coisas necessárias para gravar uma assinatura digital são adicionadas aos logs de compilação. Após a compilação, precisamos dos seguintes arquivos de saída:

  • u-boot-ivt.img
  • u-boot-ivt.img.log
  • SPL
  • SPL.log

copie-os para $ {CST_PATH} / release / linux64 / bin. Em seguida, você precisa executar um script bastante simples.

Descrição detalhada do procedimento de script
(*.csf). , :

  • .

. , ( ).

:

Image Name:   U-Boot 2019 //  U-boot
Created:      XXXXXX
Image Type:   ARM U-Boot Firmware with HABv4 IVT (uncompressed)
Data Size:    339904 Bytes = 331.94 KiB = 0.32 MiB
Load Address: 17800000
Entry Point:  00000000
HAB Blocks:   0x177fffc0   0x0000   0x00051020

Image Type:   Freescale IMX Boot Image //  SPL
Image Ver:    2 (i.MX53/6/7 compatible)
Mode:         DCD
Data Size:    61440 Bytes = 60.00 KiB = 0.06 MiB
Load Address: 00907420
Entry Point:  00908000
HAB Blocks:   00907400 00000000 0000cc00
DCD Blocks:   00910000 0000002c 00000004

«HAB Blocks». ,

cd ${CST_PATH}/release/linux64/bin
./cst --o u-boot_csf.bin --i u-boot.csf
cat u-boot-ivt.img u-boot_csf.bin > u-boot_signed.img


Tanto quanto me lembro no caso do SPL integrado, provavelmente tudo funcionará da mesma maneira, mas vale a pena conferir. Não me lembro agora e não comecei a compilar ao escrever este artigo.

cd ${CST_PATH}/release/linux64/bin
SOC=mx6 ./var-som_sign_image.sh SPL u-boot-ivt.img

De acordo com os resultados do script, você obterá dois arquivos: SPL_signed, u-boot-ivt.img_signed, que deve ser gravado no disco do sistema de destino. Aplico um exemplo de script de gravação ao sistema de destino. Sem sudo, para não atirar acidentalmente na perna.

dd if=SPL_signed of=${DEVICE(/dev/sd*)} bs=1K seek=1; sync
dd if=u-boot-ivt.img_signed of=${DEVICE(/dev/sd*)} bs=1K seek=69; sync

Depois de gravar em um meio em branco, você deve obter um gerenciador de inicialização sem um kernel que trava no console, pois ele não encontra o dtb e o kernel. No console, você pode verificar se o que você fez ou não realmente funciona. Na presença de evento - algo deu errado. Importante: se o gerenciador de inicialização for compilado sem o suporte ao HAB, também não haverá erros.

hab_status
HAB Configuration: 0xf0, HAB State: 0x66
No HAB Events Found!

O último passo é ativar o HAB, a atenção é um comando único, não pode ser corrigido, portanto, tenha cuidado

fuse prog 0 6 0x2

Conclusão


Não comecei a descrever o processo de integrar tudo isso ao yocto, mas tenho que guardar segredos. No entanto, isso é viável e não requer muito tempo.

referência


[1] software embarcado com bare metal que roda diretamente no hardware sem nenhuma abstração na forma de sistemas operacionais
[2] we.easyelectronics.ru/Soft/zaschita-ustroystva-ot-vzloma-i-kopirovaniya.html
[3] ] habr.com/en/post/350602
[4] HAB4_API.pdf em github.com/BMValeev/CST_TOOL
[5] variwiki.com/index.php?title=High_Assurance_Boot
[6] boundarydevices.com/high-assurance-boot -hab-dummies
[7] github.com/BMValeev/CST_TOOL

All Articles