Skip to main content
ZeroKeyUSB guarda todos los secretos dentro de una EEPROM externa ST M24C64-WMN6TP (64 Kbit = 8 KB). El firmware gestiona lecturas y escrituras con cuidado, respetando los límites de página y manteniendo todos los datos de credenciales cifrados en reposo.

Mapa de memoria

La EEPROM está organizada en una zona de configuración (primeros ~220 bytes) y una zona de credenciales (resto):

Estructura del slot de credencial

Cada uno de los 61 slots de credenciales ocupa 4 páginas consecutivas de 32 bytes en EEPROM (128 bytes en total): Cada página de 32 bytes contiene:
  • 16 bytes de texto plano (rellenados con 0xFF) cifrados como dos bloques AES-128 CBC
  • El cifrado usa el IV global del dispositivo más la clave maestra AES que vive dentro del slot 8 del ATECC — las rondas del cifrador corren en el chip, nunca en el MCU.
No hay un byte status o CRC separado por página. Los slots vacíos se escriben como blancos 0xFF cifrados durante silentEraseAll().

Cálculo de dirección de página

Donde:
  • FIRST_CREDENTIAL_PAGE se calcula a partir de CONFIG_TOTP_META_END redondeado al siguiente límite de 32 bytes.
  • slotIndex va de 0 a 61.
  • pageIndex va de 0 (sitio) a 3 (TOTP).

Secuencia de escritura

La función writeEepromPage() escribe 32 bytes en una dirección alineada a página:
  1. Comprueba la presencia de EEPROM vía Wire.beginTransmission() + test de ACK.
  2. Envía la dirección de 2 bytes (MSB primero) seguida de 32 bytes de datos.
  3. Espera 10 ms para el ciclo de escritura interno de la EEPROM.
  4. Devuelve true si Wire.endTransmission() no reportó error.
Para escrituras relacionadas con seguridad que cruzan límites de página (p. ej. IV de 16 bytes, hash de PIN de 32 bytes), eepromWriteRaw() en zerokey-security.cpp divide los datos en los límites de 32 bytes para evitar el comportamiento de wrap-around de direcciones del M24C64.

Secuencia de lectura

readEepromPage() lee exactamente 32 bytes:
  1. Envía la dirección de 2 bytes vía escritura I²C.
  2. Emite Wire.requestFrom(eepromAddress, 32).
  3. Lee todos los bytes disponibles al buffer de salida.
  4. Rellena con ceros los bytes no recibidos (lectura parcial = error).

Metadatos TOTP

Cada slot de credencial tiene una entrada de metadatos TOTP de 2 bytes en la zona de configuración: Los metadatos se leen/escriben independientemente de las páginas de credenciales para permitir detección rápida de TOTP sin descifrar el slot completo.

Características de desgaste

  • La M24C64-WMN6TP soporta >1 millón de ciclos de escritura por página (garantía del datasheet).
  • Las páginas de credenciales solo se reescriben cuando el usuario edita un campo o importa datos.
  • Las páginas de la zona de configuración (IV, hash de PIN, umbral) se escriben durante el aprovisionamiento y cambios de PIN — eventos infrecuentes.
  • El epoch TOTP en 0x0040 se actualiza cada vez que el usuario sincroniza la hora o genera un código — es la ubicación más escrita.
  • Como las credenciales suelen ser estáticas, la vida útil esperada de la EEPROM supera las décadas de uso normal.

Resolución de problemas

Ninguna credencial descifrada toca memoria persistente sin acción explícita del usuario. El texto plano solo existe en SRAM durante la sesión activa.