<!-- The markdown twin of https://kleidos.dev/es/security/, converted from that page at build time. The page is the original; this is the same words with the markup taken off. The site was last changed on 2026-10-25. -->

# Seguridad

A un gestor de contraseñas hay que juzgarlo por aquello que lo ataca, así que aquí está la lista: veinte amenazas con su identificador, cuarenta y cinco controles que las responden y cinco de los riesgos aceptados y no resueltos.

No puedo pedirte que te creas nada de esto. El repositorio está privado mientras preparo la primera versión, así que puedes leer estas afirmaciones pero no el código que hay detrás, y nadie de fuera del proyecto ha revisado ni una cosa ni la otra. La última sección de esta página trata de eso, y es la que yo leería primero.

**20**

amenazas dentro del alcance

**6**

declaradas fuera del alcance

**45**

controles, cada uno con el fichero que lo implementa

**13**

entradas del registro que citan un CVE o un aviso publicado

En esta página

1. [Amenazas](https://kleidos.dev/#model)

2. [Preguntas](https://kleidos.dev/#threats)

3. [Controles](https://kleidos.dev/#controls)

4. [Riesgos aceptados](https://kleidos.dev/#residual)

5. [No verificable](https://kleidos.dev/#verify)

## De qué hay que defenderlo

Cada amenaza que el diseño responde lleva un identificador estable, de T1 a T20, y cada documento que responde a algunas de ellas dice a cuáles. Hay seis más declaradas fuera de alcance, con su motivo, y eso importa lo mismo: un modelo de amenazas que lo cubre todo no cubre nada.

9 de las veinte

### Alguien tiene el dispositivo

Leer la flash, adivinar el PIN en la pantalla, adivinarlo fuera del dispositivo tras copiar la flash, mover o reetiquetar registros dentro de la flash, devolver la bóveda entera a un estado anterior, usar el puerto de depuración, poner una sonda en el bus de la memoria externa, probar un PIN retirado contra una copia antigua de los metadatos de la bóveda y adivinar la clave de la bóveda a partir de un número aleatorio débil y luego comprobarla contra esos metadatos con un solo HMAC.

docs/security/vault-encryption.md

5 de las veinte

### Alguien está dentro del alcance de radio

Escuchar las pulsaciones o los anuncios, colocarse en medio de un emparejamiento, sobrescribir un vínculo ya existente, escribir en un equipo antes de que el emparejamiento termine y agotar la batería abusando de los parámetros de conexión.

docs/security/ble.md

2 de las veinte

### Alguien entra en la red de administración

Llegar a entrar en el punto de acceso y, una vez dentro, saltarse el token de sesión del panel.

docs/security/wifi-admin-portal.md

1 de las veinte

### Una actualización arranca mal

La que hay que deshacer sin un cable, porque el dispositivo está en el bolsillo de alguien y la imagen mala es justo la que acaba de arrancar.

docs/security/ota-and-boot.md

1 de las veinte

### Un secreto acaba en un log

La que causa quien programa y no quien ataca: una contraseña, un PIN o una clave que acaba en una línea de log, en un anuncio de Bluetooth o en una respuesta que no exigía autenticación.

docs/security/key-material-and-logging.md

2 de las veinte

### Una actualización llega manipulada, o una dependencia tiene un fallo conocido

Una imagen de firmware manipulada que se acepta como legítima y una vulnerabilidad publicada en una dependencia fijada que llega a una compilación.

docs/security/cve-register.md

Fuera de alcance, y dicho en voz alta en vez de omitido: un ordenador ya comprometido que captura las pulsaciones que Kleidos escribe, porque escribirlas es el producto entero; un atacante que destape el chip o le inyecte fallos, porque no hay elemento seguro ni carcasa que delate una manipulación; los canales laterales de consumo y electromagnéticos, sobre los que no afirmo nada; una imagen de firmware manipulada antes de que tú la grabes; y elegir la credencial equivocada, o escribir la correcta en el campo equivocado, que el dispositivo no puede ver.

Está escrito en docs/security/threat-model.md.

## Las seis con las que llegas

Cada una es una pregunta tal como se hace de verdad, luego la respuesta, y luego, en cinco de las seis, la parte que la respuesta no cubre. Un control contado sin su límite es exactamente el tipo de afirmación de seguridad que esta página existe para no hacer.

**Alguien se lleva el dispositivo. ¿Cuánto tiempo tiene?**

Cuatro PIN equivocados lo bloquean un rato, siete lo bloquean más tiempo y el décimo borra la bóveda, todos los vínculos de Bluetooth y todas las redes de administración guardadas, en ese orden, y el contador se pone a cero al final, cuando la bóveda ya no está. La cuenta sobrevive a un corte de corriente porque se escribe antes de comprobar el PIN y no después: quitar la batería a mitad de un intento sigue costando el intento.

Lo que eso no cubre

Un PIN de cuatro cifras son diez mil combinaciones, y cuatro cifras es la longitud por defecto. Se ofrecen seis y ocho cifras y, en las placas con teclado o con pantalla táctil, una contraseña. Lo que hace soportable un PIN corto es el bloqueo, no el PIN.

Amenazas: T2

docs/security/pin-and-bruteforce.md

**Alguien desuelda la flash y la lee. ¿Qué se encuentra?**

La bóveda, como texto cifrado. Cada fichero de la bóveda va en AES-256-CBC con una etiqueta HMAC-SHA256 sobre el texto cifrado, y la etiqueta se verifica antes de descifrar nada: una clave equivocada y un fichero manipulado reciben la misma respuesta, que es un rechazo y no un resultado ilegible. El PIN pasa por PBKDF2-SHA256 (175 000 iteraciones en las placas ESP32-S3 y 40 000 en las clásicas, cada valor ajustado a unos dos segundos de desbloqueo) hasta una clave que comprueba el desbloqueo y desenvuelve la clave aleatoria propia de la bóveda, y las claves con que se cifran los registros salen de esa clave aleatoria.

Lo que eso no cubre

En las compilaciones abiertas el almacén de ajustes que hay junto a la bóveda no va cifrado, así que la misma copia trae además, en claro, las claves de los vínculos de Bluetooth (suficientes para descifrar una grabación de lo que el dispositivo escribió en un ordenador emparejado), el contador de intentos, el registro de auditoría, los ajustes y la contraseña de la red de administración si elegiste dejar una fija. Y el cifrado de la propia bóveda es todo lo que hay: quien tenga la imagen de la flash puede probar PIN tras PIN fuera del dispositivo, tan rápido como se lo permita su hardware, y lo único que lo frena son las iteraciones y la longitud de tu PIN. La compilación endurecida cifra la flash y los ajustes y mezcla un secreto propio del dispositivo, lo que hace que un intento fuera del dispositivo necesite ese chip exacto: en las placas de ESP32 clásico, un valor aleatorio guardado en los ajustes cifrados, que solo ese chip puede descifrar, y en las placas ESP32-S3, una clave dentro de los fusibles del chip, que se graba con un paso que ya existe y que todavía no he ejecutado en ninguna placa.

Amenazas: T1, T3

docs/security/vault-encryption.md

**Alguien graba el tráfico Bluetooth. ¿Puede leer la contraseña?**

El enlace es solo Bluetooth LE Secure Connections (el emparejamiento antiguo se rechaza de plano). Cada característica del servicio de teclado exige un enlace cifrado con una clave de dieciséis bytes antes de que se llegue siquiera a su manejador, y los informes, que son los que llevan las pulsaciones, exigen además que ese enlace esté autenticado; como la comparación numérica es el único emparejamiento que se acepta, un enlace cifrado siempre está autenticado. Cada ráfaga de pulsaciones vuelve a comprobar que el enlace sigue cifrado, sigue autenticado y sigue vinculado antes de enviar, y cada notificación dentro de la ráfaga lo comprueba otra vez. El dispositivo se anuncia con una dirección privada que cambia cada quince minutos.

Amenazas: T6

docs/security/ble.md

**¿Puede otra cosa hacerse pasar por el ordenador que emparejé?**

El emparejamiento es por comparación numérica: seis cifras en la pantalla del propio dispositivo, que confirmas a mano. Una petición para volver a emparejar un vínculo que ya existe se deniega por omisión y hay que confirmarla en el dispositivo, y una confirmación que caduca cuenta como una negativa y no como un sí.

Lo que eso no cubre

Antes de expulsar el vínculo más antiguo cuando la tabla está llena, se pregunta igual, y en la tabla caben cuatro. En las placas de ESP32 clásico, la lista de admisión del controlador y la dirección privada rotatoria no pueden estar activas a la vez: la pila rechaza la lista mientras la dirección está activa, así que esas placas conservan la privacidad de la dirección y no la lista.

Amenazas: T7, T8

docs/security/ble.md

**El panel de administración es un servidor web dentro de un gestor de contraseñas. ¿En serio?**

Solo funciona mientras tú lo pides, sobre un punto de acceso exclusivamente WPA3, con protección de tramas de gestión y un máximo de un cliente. La contraseña del punto de acceso aparece en tu pantalla desbloqueada y, salvo que elijas dejar una fija, se genera nueva en cada sesión y solo sobrevive al único reinicio que provoca una actualización, para que tu navegador pueda volver a conectarse. La página pide un token de sesión al cargarse, a una ruta limitada a treinta peticiones por minuto desde cada dirección. Todas las rutas a las que llama después, salvo la que sube una actualización, llevan ese token, que se compara en tiempo constante y caduca tras cinco minutos de inactividad; la de la actualización pide en su lugar la contraseña de subida, comparada de la misma forma. Todas comparten un límite de ochenta peticiones por minuto. Solo la propia página, y la redirección que lleva hasta ella desde cualquier otra ruta, se sirven sin límite alguno. El Bluetooth y el Wi-Fi no funcionan nunca a la vez: cada sesión de Bluetooth tiene un dueño que la detiene, y a este panel se llega solo después de esa parada.

Lo que eso no cubre

Dentro de esa red, el panel se fía de quien haya entrado. Es el diseño y no un descuido: un cliente, una red que vive unos minutos, una contraseña que lees en el dispositivo. Pero significa que el código QR de la pantalla lo deberías escanear tú, y en privado. Y si eliges dejar una contraseña fija para todas las sesiones, quien la lea una vez se la queda, y en las compilaciones abiertas se guarda sin cifrar en los ajustes del dispositivo, donde una copia de la flash la delata.

Amenazas: T11, T12

docs/security/wifi-admin-portal.md

**¿Qué pasa cuando algo de lo que enlaza el firmware tiene un CVE?**

Hay un registro: trece de sus entradas citan un CVE o un aviso publicado, y dos responden a un fallo conocido para el que nadie ha publicado ninguno. Cada una dice si Kleidos está afectado y por qué, con enlace a su fuente pública. De todas esas entradas, once citan una línea de este repositorio como prueba; las otras cuatro se apoyan en un razonamiento: el compilador con el que se compila la flota, la criptografía que usa el firmware o lo que necesita el fallo para dispararse. Tres figuran como riesgo aceptado, y las tres están en la pila de Bluetooth que trae el framework. Una está en la capa de enlace del controlador de radio, por debajo del host que maneja este código. Las otras dos están en ese host, en el código que lee lo que le envía el controlador, y las dos necesitan que el controlador envíe algo que no debe: el controlador forma parte del chip, así que un atacante por radio tendría que comprometerlo antes. Y una de las dos solo puede colgar el dispositivo, que se reinicia sin poner en riesgo ninguna pulsación ni ningún emparejamiento. Las tres se cierran cuando el framework traiga la versión corregida de esa pila.

Lo que eso no cubre

Es un registro de lo que se ha publicado y se ha mirado, que no es un registro de lo que hay. Lo que enlaza el firmware está nombrado y fijado. ESP-IDF 6.0.3 (que trae el host de Bluetooth y la pila de Wi-Fi), mbedTLS 4.1.1 con TF-PSA-Crypto 1.1.1 y ArduinoJson 7.4.3 lo están hasta la última cifra, y la 1.22.1 de LittleFS la fijan los ficheros de bloqueo versionados, porque su manifiesto acepta cualquier 1.x desde la 1.10.2. Así que subir una versión es un acto deliberado y no una deriva, y hoy eso es toda la historia de la cadena de suministro.

Amenazas: T17

docs/security/cve-register.md

## Qué las responde

Una sola tabla cruza cada uno de los cuarenta y cinco controles con la amenaza que mitiga, el aviso que atiende si hay alguno, el fichero que lo implementa, la norma que sigue si sigue alguna y cómo comprobarlo. Aquí están agrupados por lo que protegen.

### La bóveda en reposo

Cifrar y luego autenticar, con verificación antes de descifrar; un sobre por registro que autentica el tipo, la ranura y la generación del propio registro, para que no se pueda mover, reetiquetar ni devolver por separado; una clave de cifrado de claves sacada del PIN que solo comprueba el desbloqueo y desenvuelve una clave aleatoria de la bóveda, y de esa clave de la bóveda, claves distintas, cada una con su etiqueta, que cifran y autentican los registros; y, en las compilaciones endurecidas, un secreto propio del dispositivo mezclado en la derivación del PIN: una clave dentro de los fusibles del chip en el ESP32-S3 y un valor aleatorio guardado en los ajustes cifrados en el ESP32 clásico.

docs/security/vault-encryption.md

### El PIN

Comparación en tiempo constante; el contador de intentos incrementado antes de la derivación y no después; el bloqueo escalonado; y una sola rutina de borrado a la que tiene que llamar toda superficie que destruya una bóveda: la pantalla, el panel, la consola serie y la recuperación de arranque por igual, con el contador puesto a cero al final.

docs/security/pin-and-bruteforce.md

### El enlace Bluetooth

Solo Secure Connections, comparación numérica, cifrado exigido en todo el servicio de teclado y autenticación en los informes que llevan las pulsaciones, una recomprobación en vivo por pulsación y por notificación, una dirección privada rotatoria, confirmación antes de reemparejar o de expulsar un vínculo, y una política que acota los parámetros de conexión que un equipo puede pedir.

docs/security/ble.md

### El panel de administración

WPA3 con protección de tramas de gestión y un solo cliente; un token de sesión sacado al azar en cada sesión y una contraseña de subida que en cada sesión se deriva de ese token y de la clave de la bóveda; límites de peticiones por dirección en todas las rutas salvo la propia página y su redirección; y una única puerta compartida que coteja el secreto de desbloqueo con la bóveda antes de ejecutar cualquier ruta que destruya algo, conectada al mismo bloqueo que usa el desbloqueo del dispositivo.

docs/security/wifi-admin-portal.md

### El arranque y las actualizaciones

En las compilaciones endurecidas: arranque verificado con firmas RSA-3072, cifrado de la flash en el propio chip (XTS-AES-128 en el ESP32-S3, y en el ESP32 clásico el esquema AES-256 propio de ese chip), ajustes cifrados, el modo de descarga por serie del chip desactivado en los fusibles, la negativa a instalar una versión inferior a la que se está ejecutando, y la vuelta atrás que ejecuta el gestor de arranque cuando una imagen nueva no se declara sana a tiempo. Activarlo es definitivo: el primer arranque de una compilación endurecida escribe los fusibles del chip, y eso no se deshace.

docs/security/ota-and-boot.md

### Material de clave y logs

Una única macro de log que lleva escrita dentro la prohibición de que una credencial acabe en un log; vectores de clave puestos a cero y ranuras de clave de la plataforma destruidas; un asignador que borra la memoria del JSON que construye el panel; un registro de auditoría que recibe un identificador de evento y al que no se le puede pasar una credencial; y una lista de lo único que puede vivir en la RAM externa.

docs/security/key-material-and-logging.md

### Las copias de seguridad

Un sobre aparte con 600 000 iteraciones y una contraseña tuya; al restaurar, el recifrado con las claves del dispositivo que recibe la copia, para que pueda viajar entre placas; y un único camino de copia sellada compartido por el panel y la ranura de tarjeta, en vez de dos que podrían contradecirse.

docs/security/vault-encryption.md

La tabla está escrita para quien audite el dispositivo, y por eso cada fila señala el código en vez de describirlo. Es el documento que le daría a un revisor, y es el documento que nadie de fuera del proyecto ha leído.

Está escrito en docs/security/audit-dossier.md.

## Lo que está aceptado y no resuelto

Aquí van cinco de los riesgos que el diseño reconoce y no cierra; el modelo de amenazas y el expediente de auditoría recogen los demás. El primero está vigente hoy, y es el que a mí me gustaría que me contaran si estuviera leyendo la página de otro.

### Un PIN retirado sigue abriendo la bóveda actual

Cambiar el PIN vuelve a envolver la clave de la bóveda en lugar de generar una nueva. Así que el PIN viejo, más cualquier copia del fichero de metadatos de la bóveda hecha antes del cambio, recupera la clave que está en uso ahora, y con ella todas las credenciales escritas desde entonces. Ese fichero puede salir de la flash. También puede salir de una copia de seguridad sellada hecha antes del cambio, para quien tenga además la contraseña de esa copia. Hace falta acceso de lectura al texto cifrado actual y ninguno de escritura. El recifrado completo de la bóveda, que sí rota la clave, se mantiene y se ofrece como una acción explícita, en el dispositivo y en el panel. Destruye o vuelve a hacer cualquier copia de seguridad anterior al cambio de PIN.

Amenazas: T19

docs/security/vault-encryption.md

### En las compilaciones abiertas no se puede detectar un retroceso de toda la bóveda

Cada registro lleva un contador de generación, así que ninguno se puede devolver por separado. Restaurar la bóveda entera (los metadatos y todos los registros juntos) a un estado anterior y coherente pasa todas las comprobaciones, porque los contadores retroceden con ella. En las compilaciones endurecidas, la flash cifrada y el arranque verificado impiden que un atacante falsifique ese estado, pero no que reproduzca uno capturado de ese mismo dispositivo.

Amenazas: T5

docs/security/audit-dossier.md

### Por defecto, el PIN es corto

Cuatro cifras son diez mil combinaciones. Se ofrecen seis y ocho, y una contraseña en las placas en las que se puede teclear. Lo que hace soportable el PIN corto son el bloqueo y el borrado, y los dos son defensas en línea: no hacen nada contra quien ya tiene la flash.

Amenazas: T2

docs/security/pin-and-bruteforce.md

### Las placas clásicas no pueden tener los dos tipos de privacidad de Bluetooth

En un ESP32 clásico, la dirección rotatoria que gestiona la pila y la lista de admisión del controlador se excluyen entre sí: para la segunda, la pila responde que no es compatible. Esas placas conservan la dirección rotatoria; las ESP32-S3 tienen las dos.

Amenazas: T6

docs/security/ble.md

### Tres placas no tienen compilación endurecida

El Plus 1.1, el Plus SE y el CoreInk llevan 4 MB de flash, que no dan para dos ranuras de actualización y un gestor de arranque firmado. Frente a una flash robada dependen solo del cifrado de la bóveda, y se actualizan regrabándolos enteros.

Amenazas: T1, T16

docs/security/flash-and-production.md

## Lo que no puedes comprobar

Lee esta parte antes de decidir nada.

- El repositorio está privado. Cada afirmación de arriba señala un fichero (una ruta, muchas veces una línea) y no puedes abrir ninguno. Te estoy pidiendo que te creas la descripción de un código que no puedes leer, y esa es la forma más débil que tiene una afirmación de seguridad. Abrir el repositorio es un paso de la hoja de ruta y no está hecho.

- Nadie independiente lo ha revisado. El firmware lo escribí yo, y el modelo de amenazas, la matriz de controles y el registro que lo describen también. Quien revisa su propio trabajo encuentra una clase de problemas distinta de la que encuentra quien revisa el ajeno.

- La compilación endurecida (la que lleva arranque verificado, flash cifrada y la clave atada al chip) todavía no funciona de principio a fin en un dispositivo. En las placas ESP32-S3, la clave del chip que esa compilación necesita la graba un paso que ya existe y que todavía no he ejecutado en ninguna placa. Cada frase de esta página que dice «compilación endurecida» describe algo que no he terminado.

- Es la versión 0.1.0 y no hay ninguna publicada. Nada de esto lo ha usado nadie más que yo.

- Las primitivas son estándar, dos de ellas vienen de una biblioteca, y la forma de ensamblarlas no está revisada. AES-256-CBC y HMAC-SHA256 pasan por mbedTLS 4.1 y su interfaz PSA, la misma versión en el dispositivo y en las pruebas que ejecuto en un ordenador. Las otras dos son mías. PBKDF2-SHA256, la derivación que protege la bóveda, maneja directamente el periférico SHA del chip en el ESP32-S3, y en el ESP32 clásico y en el ordenador ejecuta un SHA-256 escrito para este proyecto; HKDF-SHA256 la construí a mano sobre ese HMAC. Así que las pruebas del ordenador nunca ejecutan la derivación del S3: la del S3 y la del ordenador dan los mismos bytes porque ambas se comprueban contra el mismo vector de prueba publicado, no porque compartan código. Si las he escrito y ensamblado bien es exactamente la pregunta que contestaría una revisión.

Si quieres una sola frase: esto es el intento serio de una persona de hacer un gestor de contraseñas en hardware, documentado con detalle y revisado por nadie.
