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>
This commit is contained in:
commit
6c7e6ab5f5
41 files changed
+4218
No files matched your search
@@ -0,0 +1,60 @@
|
||||
// The BOOTSEL button doubles as the touch button.
|
||||
#include "button.h"
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/structs/ioqspi.h"
|
||||
#include "hardware/structs/sio.h"
|
||||
#include "hardware/sync.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define SAMPLE_INTERVAL_MS 10
|
||||
#define DEBOUNCE_MS 30
|
||||
#define QSPI_SS_INDEX 1
|
||||
|
||||
static bool pressed;
|
||||
static uint32_t last_sample_ms;
|
||||
static uint32_t last_change_ms;
|
||||
static bool press_pending;
|
||||
static uint32_t press_ms;
|
||||
|
||||
// BOOTSEL pulls the flash chip-select line low. Reading it means briefly
|
||||
// releasing that line, so flash is unusable: run from RAM with interrupts off.
|
||||
static bool __no_inline_not_in_flash_func(bootsel_pressed)(void) {
|
||||
uint32_t irq = save_and_disable_interrupts();
|
||||
hw_write_masked(&ioqspi_hw->io[QSPI_SS_INDEX].ctrl, GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
|
||||
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
|
||||
for (volatile int i = 0; i < 1000; i++) {
|
||||
// let the line settle; sleep functions live in flash
|
||||
}
|
||||
#if PICO_RP2040
|
||||
bool down = !(sio_hw->gpio_hi_in & (1u << QSPI_SS_INDEX));
|
||||
#else
|
||||
bool down = !(sio_hw->gpio_hi_in & SIO_GPIO_HI_IN_QSPI_CSN_BITS);
|
||||
#endif
|
||||
hw_write_masked(&ioqspi_hw->io[QSPI_SS_INDEX].ctrl, GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB,
|
||||
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
|
||||
restore_interrupts(irq);
|
||||
return down;
|
||||
}
|
||||
|
||||
void button_poll(void) {
|
||||
uint32_t now = platform_millis();
|
||||
if (now - last_sample_ms < SAMPLE_INTERVAL_MS) return;
|
||||
last_sample_ms = now;
|
||||
|
||||
bool down = bootsel_pressed();
|
||||
if (down == pressed || now - last_change_ms < DEBOUNCE_MS) return;
|
||||
pressed = down;
|
||||
last_change_ms = now;
|
||||
if (pressed) {
|
||||
press_pending = true;
|
||||
press_ms = now;
|
||||
}
|
||||
}
|
||||
|
||||
bool platform_button_take_press(uint32_t max_age_ms) {
|
||||
button_poll();
|
||||
if (!press_pending) return false;
|
||||
press_pending = false;
|
||||
return platform_millis() - press_ms <= max_age_ms;
|
||||
}
|
||||
Reference in new issue
Block a user