Skip to main content
ZeroKeyUSB stores every secret inside an external ST M24C64-WMN6TP EEPROM (64 Kbit = 8 KB). The firmware manages reads and writes carefully, respecting page boundaries and keeping all credential data encrypted at rest.

Memory map

The EEPROM is organized into a configuration zone (first ~220 bytes) and a credential zone (remainder):

Credential slot structure

Each of the 61 credential slots occupies 4 consecutive 32-byte EEPROM pages (128 bytes total): Each 32-byte page contains:
  • 16 bytes of plaintext (padded with 0xFF) encrypted as two AES-128 CBC blocks
  • The encryption uses the device-wide IV plus the AES master key that lives inside ATECC slot 8 — the cipher rounds run on the chip, never on the MCU.
There is no separate status byte or CRC per page. Empty slots are written as encrypted 0xFF blanks during silentEraseAll().

Page address calculation

Where:
  • FIRST_CREDENTIAL_PAGE is computed from CONFIG_TOTP_META_END rounded up to the next 32-byte boundary.
  • slotIndex ranges from 0 to 61.
  • pageIndex ranges from 0 (site) to 3 (TOTP).

Write sequence

The writeEepromPage() function writes 32 bytes at a page-aligned address:
  1. Check EEPROM presence via Wire.beginTransmission() + ACK test.
  2. Send 2-byte address (MSB first) followed by 32 data bytes.
  3. Wait 10 ms for the EEPROM internal write cycle.
  4. Return true if Wire.endTransmission() reported no error.
For security-related writes that cross page boundaries (e.g., 16-byte IV, 32-byte PIN hash), eepromWriteRaw() in zerokey-security.cpp splits the data at 32-byte page boundaries to avoid the M24C64’s address wrap-around behavior.

Read sequence

readEepromPage() reads exactly 32 bytes:
  1. Send 2-byte address via I²C write.
  2. Issue Wire.requestFrom(eepromAddress, 32).
  3. Read all available bytes into the output buffer.
  4. Zero-fill any bytes not received (partial read = error).

TOTP metadata

Each credential slot has a 2-byte TOTP metadata entry in the config zone: Metadata is read/written independently of credential pages to allow quick TOTP detection without decrypting the entire slot.

Wear characteristics

  • The M24C64-WMN6TP supports >1 million write cycles per page (datasheet guarantee).
  • Credential pages are only rewritten when the user edits a field or imports data.
  • Config zone pages (IV, PIN hash, threshold) are written during provisioning and PIN changes — infrequent events.
  • The TOTP epoch at 0x0040 is updated each time the user syncs time or generates a code — this is the most-written location.
  • Because credentials are typically static, expected EEPROM lifespan exceeds decades of normal use.

Troubleshooting

No decrypted credential ever touches persistent memory without explicit user action. Plaintext exists only in SRAM during the active session.