Files
Skey/src/storage.h
T
ckochandClaude Opus 5.5 6c7e6ab5f5 Skey: a FIDO2 security key on the Raspberry Pi Pico
Firmware for the Pico / Pico 2 that acts as a USB FIDO2 authenticator:
CTAP2 and U2F, passkeys, BOOTSEL as the touch button, and clientPIN with
PIN/UV auth protocols 1 and 2. A host simulator runs the same core so the
python-fido2 test suite exercises it without hardware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:07:38 -04:00

61 lines
1.7 KiB
C

// Persistent state: master secret, signature counter and resident credentials.
#pragma once
#include <stdbool.h>
#include <stdint.h>
#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);