SERIE
Firmware de Kleidos: tres decisiones bajo restricciones duras
Tres decisiones de ingeniería de Kleidos, un gestor de contraseñas hardware construido sobre un ESP32-S3. Sin sistema operativo en el que delegar, sin red a la que llamar, sin permisos de sistema de ficheros tras los que esconderse y con un presupuesto de flash que hace que cada elección de diseño cueste algo visible. Leídas juntas muestran qué aspecto tiene la ingeniería de seguridad cuando no están disponibles las salidas de emergencia habituales.
Por qué estas tres van juntas
Cada artículo aísla una decisión y la sigue hasta la medición que la justificó. Es deliberado: en un microcontrolador casi toda elección interesante es un intercambio contra un presupuesto fijo —bytes de flash, RAM, milisegundos, entropía— y una decisión defendida en abstracto suele ser una decisión que nunca se pagó de verdad. Los números de estos artículos son los de la compilación, incluidos los que salieron peor de lo esperado.
El dispositivo vuelve además el modelo de amenaza inusualmente concreto. Un gestor de contraseñas hardware es una cosa que un atacante puede tener en la mano. Ese único hecho elimina la mayoría de las suposiciones sobre las que se apoya la literatura general de seguridad: no hay un servidor de confianza que limite la tasa del atacante, no hay una cuenta que bloquear, no hay un llavero del sistema operativo al que delegar y no hay forma de guardar un secreto por el mero hecho de no escribirlo, porque el atacante puede leer la flash. Dos de los tres artículos son consecuencia directa de eso.
El tercer hilo es que ninguna de estas decisiones se tomó aislada de las otras. El pool compacto de cadenas existe en parte porque el trabajo criptográfico necesitaba la flash que liberó. El paso de autenticación del formato de bóveda es lo que hace que el comportamiento fail-closed de la derivación de claves sea observable y no teórico. Leerlos en orden enseña el presupuesto moviéndose de un subsistema a otro, que es la parte del trabajo embebido que rara vez sobrevive hasta el texto final.
Léelas en este orden
El orden va de la restricción más barata de entender a la de consecuencias más afiladas. Cada entrada indica qué decisión resuelve.
Parte 1
Lo que el linker no hará: empaquetar cadenas i18n en un MCU
Empieza por el presupuesto de flash, porque es la restricción que da forma a todo lo demás. Un dispositivo con interfaz en cinco idiomas almacena muchísimas cadenas cortas, y la representación ingenua —un array de punteros por idioma— gasta una fracción sorprendente de su coste en los punteros y no en el texto. El artículo recorre un generador de tiempo de compilación que empaqueta todas las traducciones en un único blob direccionado por offsets de 16 bits, deduplicando las cadenas idénticas entre idiomas, y cuenta lo que eso ahorró de verdad. Es también la entrada más suave: nada de criptografía, solo una medición y un generador.
Parte 2
Una bóveda con bloqueo ante fallos: Encrypt-then-MAC en un MCU
Después, el fichero para el que existe el dispositivo. Una bóveda que descifra antes de autenticar procesará encantada las modificaciones de un atacante, y en un microcontrolador las consecuencias de analizar texto plano controlado por el atacante no son abstractas. El artículo cubre encrypt-then-MAC, por qué el MAC se verifica sobre el texto cifrado antes de descifrar un solo byte, y cómo se estructura la ruta de lectura para que cualquier fallo —truncamiento, un bit cambiado, un fichero sustituido— termine en un rechazo y no en un resultado parcial. Fail-closed es una propiedad de la ruta de código, no de la intención, y este es el artículo que enseña la diferencia.
Parte 3
Un PIN de 4 dígitos basta: claves vinculadas al ESP32-S3
Por último, la clave que la abre. El usuario elige un PIN de cuatro dígitos, y ningún número de iteraciones salva a un secreto de cuatro dígitos frente a un atacante que tiene el contenido de la flash y una máquina de escritorio: el espacio de claves entero son diez mil candidatos. La respuesta es hacer imposible la derivación fuera del dispositivo mezclando un secreto que nunca sale de él —una clave HMAC respaldada por eFuse que la CPU puede usar pero no leer— y pasarlo por HKDF junto con el PIN. El artículo explica por qué esto es un argumento de ligadura al dispositivo y no de fortaleza, y es franco sobre lo que no protege.
Hacia dónde sigue esto
Las siguientes preguntas obvias son las de la frontera del dispositivo más que las de su interior: cómo se autentican las actualizaciones de firmware, cómo interactúan el arranque seguro y el cifrado de flash con el secreto en eFuse del que depende el tercer artículo, y qué puede recuperar todavía un atacante con acceso físico y un laboratorio. Merecen sus propios artículos y no un párrafo aquí, porque las respuestas honestas hablan de límites, no de soluciones.
Kleidos es un proyecto privado y su repositorio no es público, así que estos artículos llevan el razonamiento y las mediciones en lugar de un enlace para clonar. Todo lo descrito es reproducible desde el propio artículo: el generador del pool de cadenas es un script de compilación cuyo algoritmo está detallado, y las construcciones criptográficas son primitivas estándar compuestas en un orden que se enuncia, que es la parte que importa y la que más veces se hace mal.
Qué no cubre esta serie
No hay capítulo de hardware —ni esquemático, ni carcasa, ni cadena de suministro— ni de diseño de interfaz. El alcance son decisiones de firmware con consecuencia de seguridad o de recursos, y por eso no aparecen por ningún lado ni el driver de la pantalla ni la rutina antirrebotes de los botones, que dieron trabajo real. Tampoco es una serie de tutoriales: ninguno de los tres artículos es una guía paso a paso, y seguirlos requiere estar cómodo con C++ sobre metal desnudo y con el vocabulario de la criptografía aplicada.