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

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.

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 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.

  1. 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

  2. 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

  3. 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

  4. 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

  5. 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.

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.