A proteção contra leitura e gravação do ESP32 é algo desejado por qualquer pessoa que trabalha com esse microcontrolador da Espressif, porém esse processo pode ser um tanto trabalhoso e com algumas margens para erro que podem até inutilizar o ESP.
1. Proteção contra leitura e gravação do ESP32 e Arduino IDE
Existem alguns conteúdos na internet ensinando como fazer esse processo e particularmente testei vários desses métodos, porém o grande problema é que a grande maioria usa exemplo com a IDE da Espressif o que dificulta o avanço de desenvolvedores que usam a IDE do Arduino.
Porém o processo de proteção contra leitura e gravação neste post será universal para qualquer IDE que for usar, mas os exemplo aqui serão todos com Arduino IDE.
Para que você consiga prosseguir com esse post, será necessário consultar nosso post sobre “Flash download Tools ESP32“, pois há informações fundamentais que serão usadas no processo de proteção contra leitura e gravação.
2. Instalando pacotes necessários
Para fazer tudo isso acontecer, vamos precisar instalar o ESP-IDF no computador, tem suporte para todos os sistemas operacionais. Para baixar basta clicar aqui e escolher seu sistema operacional, após isso abra o terminal “ESP-IDF CMD”
O CMD/terminal será toda nossa interface que usaremos para fazer todo o processo de proteção, nele termos acesso a 4 aplicativos que serão:
esptool.py: Usado para fazer leitura, consultas e gravações no ESP;espefuse.py: Usado para modificar e proteger os eFuse;especure.py: Usado para criar chaves e criptografar binários;idf.py: Tudo que uma IDE faria, mas não iremos usar ele.
3. Iniciando processo de proteção do ESP32
Antes mesmo de você começar a fazer isso, lembre-se que o erro é algo comum e que neste caso pode resultar na perda do ESP32, então dê preferência a realizar este processo em um ESP no qual seja fácil para descartar. Se todo o processo a seguir for realizado da forma correta, nada de ruim vai acontecer!
Como vamos usar os três primeiros programas anteriormente citados, então vamos abrir três “ESP-IDF” para deixar o processo mais organizado. Além disso é necessário escolher um programa do Arduino IDE para que possamos usar em nossos testes, escolha o que te agradar, mas é bom ter um LED piscando para ter feedback visual.
3.1 Observação
Ao fazer esse processo de proteção contra leitura e gravação, toda vez que for gravar no ESP32 no qual você escolheu para criptografar, será necessário fazer a criptografia dos binários e depois grava-los do ESP. Ou seja, não será mais possível usar diretamente da IDE do Arduino, você vai até conseguir gravar, porém o código não rodará.
3.2 Passo a passo de como realizar proteção contra leitura e gravação do ESP32
Se você tem ciência do que será feito e já tem tudo em mãos, então basta começarmos com o passo a passo. Caso essa seja sua primeira vez que faz isso, preste bastante atenção com cada passo, leia primeiro todo o post de forma bem atenciosa e depois realize o processo, pois a afobação pode resultar em resultados não esperados.
3.2.1 Gere um projeto blink ou escolha um projeto já existente
Abra sua IDE com o projeto escolhido ou monte um mini projeto para ficar piscando o LED, faça o upload para o ESP32 e verifique se funciona.
3.2.2 Exportar binários do projeto do Arduino para uma pasta
Crie uma pasta destinada apenas para esse tutorial de criptografia, isso é altamente recomendado para todo processo em que você for fazer em seus produtos, pois a desorganização pode ser algo catastrófico nesse caso.
Imagine uma produção de um produto com ESP32 onde você fez todo esse processo de proteção, mas ai a chave é perdida, dos produtos que saíram da fabrica deixaram de receber novas atualizações por ter simplesmente perdido a chave.
3.2.3 Gerar uma chave de criptografia
Vamos de fato começar o processo de proteção, inicie um ESP-IDF caso não tenha iniciado anteriormente. Em seguida vamos realizar o seguinte comando a seguir:
espsecure.py generate_flash_encryption_key "<diretorio\nome_da_chave.bin>"
3.2.3.1 Observação
É importante que você faça esse processo uma única vez, não fica realizando ele para não subscrever a chave anteriormente gerada, caso esteja no mesmo diretório. Se subscrever a chave, após já ter feito todo processo de proteção, pegue um bolo e acenda uma vela e bata parabéns para você, pois tu acabou de perder um ESP32 ou um lote […]
3.2.4 Criptografar todos os arquivos binários do projeto do Arduino IDE
Vá até o diretório aonde você colocou os binários do projeto do Arduino IDE, crie uma pasta “encrypted” para ajudar a identificar onde estão os binários criptografados.
Em seguida, vamos pegar cada binário e criptografar um a um. Vale ressaltar que esse comando a seguir tem uma ordem meio estranha, pois o destino de saída (já criptografado) do arquivo vem primeiro e o destino de entrada (não criptografado) vem depois.
espsecure.py encrypt_flash_data --keyfile "<diretorio\nome_da_chave.bin>" --address 0x01000 -o "<diretorio\encrypted\0x01000.bin>" "<diretorio\0x01000.bin>"
espsecure.py encrypt_flash_data --keyfile "<diretorio\nome_da_chave.bin>" --address 0x0e000 -o "<diretorio\encrypted\nome_do_arquivo.bin>" "<diretorio\0x0e000.bin>"
espsecure.py encrypt_flash_data --keyfile "<diretorio\nome_da_chave.bin>" --address 0x08000 -o "<diretorio\encrypted\nome_do_projeto.partitions.bin>" "<diretorio\nome_do_projeto.ino.partitions.bin>"
espsecure.py encrypt_flash_data --keyfile "<diretorio\nome_da_chave.bin>" --address 0x10000 -o "<diretorio\encrypted\nome_do_projeto.bin>" "<diretorio\nome_do_projeto.ino.bin>"
3.2.4.1 Observação
Esse processo pode dar errado, mas o erro aqui é bem tranquilo, pois não é algo que possa vim a impedir de novas gravações. O que é preciso se atentar é apenas no arquivo e a sua respectiva posição na memória.
Outro ponto bastante importante é que a depender da IDE, pode haver menos arquivos binários ou mais, porém se seguir a mesma lógica dos comandos acima, vai funcionar com toda certeza.
3.2.5 Analisar eFuses em um ESP sem proteção
Este processo não é um processo que vai mudar algo no ESP, apenas vai servir como um feedback para sabermos o estado de cada eFuse do ESP, para isso basta dar o seguinte comando:
espefuse.py --port COM<numero da porta> summary
Vamos mexer em dois eFuses e um será modificado automaticamente ao gravar a chave de criptografia. Na imagem a seguir é possível ver que os eFuses marcados estão zerados, indicando que estão desprotegidos.

3.2.6 Gravar chave de criptografia no ESP
Essa ação é uma ação única, então a chave que você escolher não poderá ser modificada após a gravação da chave. Para gravar a chave no esp basta realizar o seguinte comando:
espefuse.py --port COM<numero da porta> burn_key flash_encryption "<diretorio/nome_da_chave.bin>"
Após dar o comando, aparecerá uma mensagem de confirmação avisando que esse processo é um processo irreversível e caso queria de fato prosseguir, basta escrever BURN. Ao confirmar, você poderá consultar summary os dois primeiros registros da imagem anterior e verá que eles mudaram.
3.2.7 Habilitar eFuses de proteção
Aqui é o ponto onde a maioria dos tutoriais ficam confusos, nesse ponto é aonde geralmente usam o idf.py menuconfig, porém a ideia aqui é deixar essa proteção o mais genérico possível de modo que funcione independente de IDE. Para modificar os eFuses responsáveis por habilitar a leitura criptografada, basta realizar esses comandos:
espefuse.py --port COM<numero da porta> burn_efuse FLASH_CRYPT_CNT 1
espefuse.py --port COM<numero da porta> burn_efuse FLASH_CRYPT_CONFIG 0x0F

Se você confirmou ambos os comandos com o BURN certamente os eFuses foram gravados, para confirmar veja se o FLASH_CRYPT_CNT mudou para 1 R/W e o FLASH_CRYPT_CONFIG mudou para 15 R/W.
8 – Proteção adicional nos eFuses
Uma proteção a mais que pode ser feita no eFuse é queimar a gravação dele, ou seja, não será mais possível gravar nenhum valor nos eFuses responsáveis pela proteção. Essa proteção vai impedir permanentemente qualquer tipo de possível alteração a mais.
Fazer este processo antes do processo anterior vai deixar o ESP incapaz de ser criptografado, pois vai cortar completamente a chance de gravação do eFuse. Certifique-se através do summary para confirmar se de fato o processos anteriores foram realizados, caso esteja, prossiga com os seguintes comandos:
espefuse.py --port COM<numero da porta> write_protect_efuse WR_DIS
espefuse.py --port COM<numero da porta> write_protect_efuse FLASH_CRYPT_CNT

Após realizar esses comandos e consultar novamente o summary é possível notar que nesses eFuse ficarão com R/- ao invés de R/W, isso indica que a queima funcionou.

9 – Gravando binários no ESP32 via esptool
Enfim, ó ultimo passo! Este passo vai fazer a gravação via esptool.py que é o mesmo processo que o Arduino faz, porém agora nosso ESP32 só aceita binários criptografados e por isso temos que fazer isso manualmente. Se você tentar usar o Flash download tools verá que não funciona, pois irá detectar proteção, então tem que ser via esse método mesmo. Para fazer a gravação basta realizar este comando a seguir:
esptool.py --chip ESP32 --port COM<numero da porta> --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x1000 "<diretorio\encrypted\0x01000.bin>" 0x8000 "<diretorio\encrypted\nome_do_projeto.partitions.bin>" 0xe000 "<diretorio\encrypted\0x0e000.bin>" 0x10000 "<diretorio\encrypted\nome_do_projeto.bin>"

Pronto!! Agora é só verificar se o projeto estar funcionando adequadamente. Para isso dê um reset na placa e veja se da sinal positivo de vida, em caso negativo o ESP ficará reiniciando em loop, se isso correr reveja todos os passos.
