2022/10/25

Secure Boot con ESP32c3

Primero hay que leer atentamente la documentación y cuantos más clicks hagas en los links que tiene más vas a comprender todo, elegí para la v4.4. Puse ESP32c3 en el título pero probablemente aplica a Secure Boot V2, que incluye al menos ESP32s2.


El primer programa que se ejecuta es el que está en la ROM, también llamado FSB (First Stage Bootloader), que entre otras cosas se fija si el eFuse de secure boot está activado, ponele que sí. Luego busca el SSB (Second Stage Bootloader) y si tiene hasta 3 firmas agregadas. Utiliza las hasta 3 public keys que pueden haber en los eFuses y si alguna firma está ok, ejecuta el SSB.

 

Arranque normal
Arranque normal


Arranque seguro
Arranque seguro

 

Este hace lo mismo para cada imagen que haya en el resto de la memoria hasta encontrar una válida. Luego, de la aplicación, copia a memoria los datos y programa correspondientes y mapea a la memoria los datos y programas que vayan a quedar en la EEPROM. Por último ejecuta la aplicación.

Para poder llegar a esta situación, tenemos que hacer algunas cositas:

 

Generar las claves

 

En la carpeta de tu elección, pero luego el pem va en cada proyecto.

$ openssl genrsa -out secure_boot_signing_key.pem 3072

No te olvides de agregar un *.pem a tu .gitignore, si llegás a versionar esto, pensá que podrías revocar el certificado en el chip pero sólo tenés lugar para tres.

 

Toolchain


Bajar todo el entorno de esp-idf según las instrucciones del paso 4. Si ya lo tenías de antes, es conveniente que lo actualices.

$ cd ~/esp/esp-idf

$ git pull --recurse-modules

$ ./install.sh esp32,esp32c3,esp32s2

 

Tu proyecto


Para este ejemplo usé CIBS/esp32c3-secure-boot, que es lo mismo que esp32c3-pinout. De un modo u otro, activar el entorno

$ . export.sh

Ir a tu proyecto, si lo tenías ya construido, hacelo papilla con

$ rm -rf build

Para empezar de cero:

$ idf.py set-target esp32c3
$ idf.py menuconfig

# Security features
[*] Enable hardware Secure Boot in bootloader (READ DOCS FIRST)
   Select secure boot version (Enable Secure Boot version 2)  --->
   (X) Enable Secure Boot version 2
[*] Sign binaries during build (NEW)
   (secure_boot_signing_key.pem) Secure boot private signing key (NEW)

# Partition Table  --->
(0xa000) Offset of partition table

 

Ese 0xa000 en lugar del 0x8000 original podría ser opcional pero en mis pruebas dijo:


Bootloader binary size 0x8c30 bytes is too large for partition table offset 0x8000. Bootloader binary can be maximum 0x8000 (32768) bytes unless the partition table offset is increased in the Partition Table section of the project configuration menu.

La tentación es poner 0x8d00, pero tras varias iteraciones, mejor 0xa000, más que por ahí dice que debe ser múltipo de 0x1000.


$ idf.py build

En algún punto va a tirar dos mensajes, uno que gentilmente explica como agregarle firmas al bootloader:

To sign the bootloader with additional private keys.
    /home/iot/.espressif/python_env/idf4.4_py3.10_env/bin/python /home/iot/esp/esp-idf/components/esptool_py/esptool/espsecure.py sign_data -k secure_boot_signing_key2.pem -v 2 --append_signatures -o signed_bootloader.bin build/bootloader/bootloader.bin 

Y otro de cómo grabarlo, hay que hacerlo a mano, sólo cuando hay nuevas keys.


/home/iot/.espressif/python_env/idf4.4_py3.10_env/bin/python  /home/iot/esp/esp-idf/components/esptool_py/esptool/esptool.py --chip esp32c3 --port=(PORT) --baud=(BAUD) --before=default_reset --after=no_reset --no-stub write_flash --flash_mode dio --flash_freq 80m --flash_size 2MB 0x0 /home/iot/ceiot_base/CIBS/esp32c3-secure-boot/build/bootloader/bootloader.bin


¿Qué ponemos en PORT y BAUD?

PORT = /dev/ttyUSB0

BAUD = 115200


Ambos salen de haber visto alguna vez la salida de idf.py monitor:

--- idf_monitor on /dev/ttyUSB0 115200 ---


Luego

$ idf.py flash

$ idf.py monitor

 

Resultados


La primera vez, tal como dice la documentación, sirve para activar, hace falta un reset

Último arranque inseguro

Desde la próxima vez que arranque:


Primer arranque seguro

Notá tanto la diferencia del FSB (en negro) como la del SSB (en verde).

Este proceso en dibujitos:


Setup bootloader
Setup bootloader



Setup App
Setup App



A mi no me salió de una tán fácil, no encontraba la tabla de particiones, no había nada en ésta, horas...


Una de las tantas fallas...
Una de las tantas fallas...

2022/09/28

Nerdearla 2022 Open de todo, la previa

El taller en realidad no es tan taller, ¿cuántas personas del ámbito de nerdearla tienen una edu-ciaa-fpga, el entorno armado e interés en hacer un taller de esto? Mmmh, poquita. En realidad es una charla larga, es que hay mucho tema pero aprovecho para que quien tenga la edu-ciaa-fpga y ganas, pueda ir probando en el momento, tipo taller.

Tal como he contado mi experiencia en https://seguridad-agile.blogspot.com/2021/09/h4ck3d-2021-configuracion-basica.html, el proceso para poder generar el bitstream es larguísimo. Para facilitar la vida de quien lo haga, he tomado la virtual que uso habitualmente y le apliqué un proceso de limpieza, sanitización y compresión para ahorrar ancho de banda por un lado y para ahorrar espacio en el disco de quien la instale por el otro.


En mis últimos proyectos similares he utilizado para las virtuales Ubuntu Server con xorg y openbox, pero puede ser demasiado minimalista para otras personas, así que en lugar de rehacerlo con Ubuntu Server, reduciendo aún más el tamaño de la imagen, me concentré en quitar. El proceso de limpieza fue eliminar toda aplicación superflua, caches, logs, los repositorios utilizados para la construcción de las toolchains, lo que sea, esto quizás lo detalle en otro post uno de estos días.

Las precauciones que he tomado al exportar es cambiar la contraseñas y fundamentalmente eliminar de .ssh la key que uso para github. Tras el proceso de zerofill y compactación, no debería quedar ningún rastro forense, pero como no tengo garantías, de todos modos también eliminé la key en github.

Reformulando, eliminé la key en github para no tener ningún problema de robo de credenciales y de modo secundario la purgué en la imagen para que nadie que no ha leído esto la encuentre y piense que fuí descuidado. Y fundamentalmente para predicar con el ejemplo.

El repo consideré borrarlo también y que hicieras git clone, pero de un modo u otro tenías que bajarlo, así que lo dejé.


Durante la charla/taller lo que iré mostrando es el proceso asumiendo que ya tenés todo instalado y funcionando, comprenderás que no voy a poder en ese momento resolver ningún problema. Para poder participar del taller probando los ejemplos, es necesario que ejecutes la siguiente secuencia de operaciones, que terminaría en la grabación del bitstream a la placa y como control deberías tener algunos leds cambiantes en la placa y en la terminal serial un menú.

 

Pasos

 

Asumo que si estás jugando con FPGA y más edu-ciaa-fpga, ya tenés bastante experiencia con linux y virtualización. Aún así, cualquier problema que tengas agregalo a los comentarios abajo e iré completando el instructivo.

 

El anfitrión

 

Tenés que agregar tu usuarios a estos grupos:

$ sudo addgroup "$USER" vboxusers

$ sudo addgroup "$USER" dialout

 

Instalá el Extension Pack si no lo tenés.


La imagen

 

La imagen exportada a OVA ocupa unos 3GB y está en un drive.

La virtual importada ocupa al menos 9.3 GB, con el uso no debería crecer mucho, pero considerá que la partición es de 30 GB. Es un Linux Mint 19 o 20, lo cual provée un entorno gráfico agradable.

Desde VirtualBox elegí "File", "Import Appliance"

Yo la uso con 8GB de RAM, pero seguro que anda con menos, mucho menos, tipo 3GB.

Configurá networking en modo bridge 

 

Arranque


Luego la arrancás, el usuario es "Charly", la clave "educiaa", abrís una terminal y averiguás la IP:

$ ip a

El repo está en:

$ cd ~/Desktop/repo/github/cpantel/evilcodesequence

 

El bitstream

 

$ make PROGRAM=fulldemo system 

 

El flasheo

 

Para evitar tener que conectar la placa a la virtual, que es bastante sencillo pero puede ser fuente de inconvenientes, el flasheo se hará desde el anfitrión si es linux, si es windows, vas a tener que hacerle funcionar el USB y flashear desde la VM, vemos luego.

En el anfitrion, ejecutar una sola vez:


$ scp charly@192.168.1.xx:/usr/local/bin/iceprog .


Luego, para cada nueva regeneración del bistream:


$ scp charly@192.168.1.xx:/home/charly/Desktop/REPO/github/cpantel/evilCodeSequence/BUILD/top.bin .

$ ./iceprog top.bin

 

si dice 

 

./iceprog: error while loading shared libraries: libftdi.so.1: cannot open shared object file: No such file or directory

 

Es por que te falta

 

$ sudo apt install libftdi1


Si optaras por conectar directamente la placa a la VM


$ make PROGRAM=fulldemo flash


Considerá que flashear desde el anfitrión que es MUCHO MUCHO más rápido.

Luego, usando tu programa favorito a /dev/ttyUSB1 con velocidad 9600, tendrías que ver algo como esto:

 

Menu
Menu

Jugá con las opciones, mejor la (1) LEDS pues el resto está a medio implementar en la imagen.

Contactame ANTES del taller si algo no te funciona, durante el taller no va a haber tiempo.

Hay otras maneras de obtener un entorno equivalente, ya sea que lo hagas vos de cero o que uses docker, es irrelevante siempre y cuando puedas compilar el programa, construir el bitstream y flashearlo, proveo la virtual como una facilidad.