// Persistent state: master secret, signature counter and resident credentials. #pragma once #include #include #include "cred.h" #define RK_SLOTS 64 #define RK_MAX_USER_ID 64 #define RK_MAX_RP_ID 128 #define RK_MAX_NAME 64 // One resident (discoverable) credential. Exactly one 512-byte flash slot. typedef struct { uint32_t magic; // managed by storage.c uint32_t created; // signature counter at creation, orders credentials uint8_t rp_id_hash[32]; uint8_t cred_id[CRED_ID_LEN]; uint8_t user_id_len; uint8_t user_id[RK_MAX_USER_ID]; uint8_t rp_id_len; char rp_id[RK_MAX_RP_ID]; uint8_t user_name_len; char user_name[RK_MAX_NAME]; uint8_t display_name_len; char display_name[RK_MAX_NAME]; uint8_t reserved[99]; } rk_record_t; _Static_assert(sizeof(rk_record_t) == 512, "rk_record_t must fill one slot"); void storage_init(void); const uint8_t *storage_master_secret(void); // Increments the global signature counter and returns the new value. uint32_t storage_counter_next(void); // Generates a new master secret and deletes all resident credentials and the PIN. void storage_reset(void); // Returns false if the slot does not hold a credential. bool storage_rk_read(int slot, rk_record_t *out); // Stores a credential, replacing any with the same RP and user ID. Returns a // CTAP status code. int storage_rk_save(const rk_record_t *rec); void storage_rk_delete(int slot); // PIN state. The PIN itself is never stored, only LEFT(SHA-256(PIN), 16). typedef struct { bool set; uint8_t retries; uint8_t hash[16]; } pin_state_t; // Returns false if no PIN state was saved since the last reset. bool storage_pin_load(pin_state_t *out); void storage_pin_save(const pin_state_t *state);