Skip to content

Commit b945d9e

Browse files
committed
sys/fido2: update flash handling based on flashpage API extension
1 parent 4011bd9 commit b945d9e

4 files changed

Lines changed: 64 additions & 34 deletions

File tree

sys/fido2/ctap/Kconfig

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,22 @@ config FIDO2_CTAP_UP_BUTTON_FLANK_RISING
8484

8585
endchoice
8686

87-
config FIDO2_CTAP_FLASH_START_PAGE
88-
int "First flash page to store data in"
89-
default -1
87+
config FIDO2_CTAP_NUM_FLASHPAGES
88+
int "Amount of flashpages to use"
89+
range 2 256
90+
default 4
9091
help
91-
Configuring this incorrectly can lead to firmware corruption so make sure
92-
the flash page is located after the firmware.
92+
Configure how many flashpages are used to store FIDO2 CTAP data.
93+
94+
To save a credential in flash memory, roughly 156 bytes are needed. This
95+
number might change slightly depending on the flash block size.
96+
Therefore, if one wants to e.g. save 40 credentials and the flashpage
97+
size is 4096 bytes roughly 156 * 40 / 4096 (2) flashpages are needed.
98+
To save authenticator state data one additional flashpage is needed.
99+
So in total one has to configure 3 to save 40 credentials.
100+
101+
Configuring the amount too high can lead to loss of FIDO2 data as a
102+
result of firmware updates when using riotboot in two slot mode.
93103

94104
rsource "transport/Kconfig"
95105

sys/fido2/ctap/ctap.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,8 @@ static int _find_matching_rks(ctap_resident_key_t *rks, size_t rks_len,
15301530
static int _save_rk(ctap_resident_key_t *rk)
15311531
{
15321532
int ret;
1533-
int page_num = CTAP_FLASH_RK_START_PAGE, offset_into_page = 0;
1533+
int page_num = fido2_ctap_mem_get_rk_start_page();
1534+
int offset_into_page = 0;
15341535
bool equal = false;
15351536
ctap_resident_key_t rk_tmp = { 0 };
15361537

@@ -1792,12 +1793,12 @@ static int _ctap_decrypt_rk(ctap_resident_key_t *rk, ctap_cred_id_t *id)
17921793

17931794
static int _write_state_to_flash(const ctap_state_t *state)
17941795
{
1795-
return fido2_ctap_mem_write(state, CTAP_FLASH_STATE_PAGE, 0, CTAP_FLASH_STATE_SZ);
1796+
return fido2_ctap_mem_write(state, fido2_ctap_mem_get_state_flashpage_number(), 0, CTAP_FLASH_STATE_SZ);
17961797
}
17971798

17981799
static int _read_state_from_flash(ctap_state_t *state)
17991800
{
1800-
return fido2_ctap_mem_read(state, CTAP_FLASH_STATE_PAGE, 0, sizeof(*state));
1801+
return fido2_ctap_mem_read(state, fido2_ctap_mem_get_state_flashpage_number(), 0, sizeof(*state));
18011802
}
18021803

18031804
static int _write_rk_to_flash(const ctap_resident_key_t *rk, int page, int offset)

sys/fido2/ctap/ctap_mem.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,30 +41,33 @@ static uint16_t _max_rk_amnt;
4141
static bool _flash_is_erased(int page, int offset, size_t len);
4242

4343
/**
44-
* @brief Get amount of flashpages
44+
* @brief Get available amount of flashpages to store resident keys
4545
*/
46-
static unsigned _amount_of_flashpages(void);
46+
static unsigned _amount_flashpages_rk(void);
4747

4848
int fido2_ctap_mem_init(void)
4949
{
5050
int ret;
51+
unsigned start = fido2_ctap_mem_get_rk_start_page();
52+
unsigned amount = _amount_flashpages_rk();
5153

5254
ret = mtd_init(&_mtd_dev);
5355

5456
if (ret < 0) {
5557
return ret;
5658
}
5759

58-
for (unsigned i = CTAP_FLASH_RK_START_PAGE; i < _amount_of_flashpages(); i++) {
60+
for (unsigned i = start; i < start + amount; i++) {
5961
_max_rk_amnt += flashpage_size(i) / CTAP_FLASH_RK_SZ;
6062
}
6163

6264
return CTAP2_OK;
6365
}
6466

65-
static unsigned _amount_of_flashpages(void)
67+
static unsigned _amount_flashpages_rk(void)
6668
{
67-
return _mtd_dev.sector_count * _mtd_dev.pages_per_sector;
69+
/* -1 because first page holds authenticator state information */
70+
return CONFIG_FIDO2_CTAP_NUM_FLASHPAGES - 1;
6871
}
6972

7073
int fido2_ctap_mem_read(void *buf, uint32_t page, uint32_t offset, uint32_t len)
@@ -127,8 +130,10 @@ uint16_t fido2_ctap_mem_get_max_rk_amount(void)
127130
int fido2_ctap_mem_get_flashpage_number_of_rk(uint16_t rk_idx)
128131
{
129132
uint16_t idx = 0;
133+
unsigned start = fido2_ctap_mem_get_rk_start_page();
134+
unsigned amount = _amount_flashpages_rk();
130135

131-
for (unsigned i = CTAP_FLASH_RK_START_PAGE; i < _amount_of_flashpages(); i++) {
136+
for (unsigned i = start; i < start + amount; i++) {
132137
idx += flashpage_size(i) / CTAP_FLASH_RK_SZ;
133138

134139
if (idx >= rk_idx) {
@@ -142,8 +147,10 @@ int fido2_ctap_mem_get_flashpage_number_of_rk(uint16_t rk_idx)
142147
int fido2_ctap_mem_get_offset_of_rk_into_flashpage(uint16_t rk_idx)
143148
{
144149
uint16_t idx = 0;
150+
unsigned start = fido2_ctap_mem_get_rk_start_page();
151+
unsigned amount = _amount_flashpages_rk();
145152

146-
for (unsigned i = CTAP_FLASH_RK_START_PAGE; i < _amount_of_flashpages(); i++) {
153+
for (unsigned i = start; i < start + amount; i++) {
147154
uint16_t old_idx = idx;
148155
idx += flashpage_size(i) / CTAP_FLASH_RK_SZ;
149156

@@ -154,3 +161,13 @@ int fido2_ctap_mem_get_offset_of_rk_into_flashpage(uint16_t rk_idx)
154161

155162
return -1;
156163
}
164+
165+
unsigned fido2_ctap_mem_get_state_flashpage_number(void)
166+
{
167+
return flashpage_last_free() - CONFIG_FIDO2_CTAP_NUM_FLASHPAGES + 1;
168+
}
169+
170+
unsigned fido2_ctap_mem_get_rk_start_page(void)
171+
{
172+
return fido2_ctap_mem_get_state_flashpage_number() + 1;
173+
}

sys/include/fido2/ctap/ctap_mem.h

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,28 +41,16 @@ extern "C" {
4141
/** @} */
4242

4343
/**
44-
* @brief First flash page to store data in
45-
*
46-
* @note This can corrupt firmware if CTAP_FLASH_START_PAGE is set to a
47-
* flash page containing firmware. Therefore make sure that CTAP_FLASH_START_PAGE
48-
* is located after the firmware.
44+
* @brief Default amount of flashpages to use
4945
*/
50-
#if defined(CONFIG_FIDO2_CTAP_FLASH_START_PAGE) && \
51-
(CONFIG_FIDO2_CTAP_FLASH_START_PAGE >= 0)
52-
#define CTAP_FLASH_START_PAGE CONFIG_FIDO2_CTAP_FLASH_START_PAGE
53-
#else
54-
#define CTAP_FLASH_START_PAGE (FLASHPAGE_NUMOF - 4)
46+
#ifndef CONFIG_FIDO2_CTAP_NUM_FLASHPAGES
47+
#define CONFIG_FIDO2_CTAP_NUM_FLASHPAGES 4
5548
#endif
5649

57-
/**
58-
* @brief Start page for storing resident keys
59-
*/
60-
#define CTAP_FLASH_RK_START_PAGE CTAP_FLASH_START_PAGE
61-
62-
/**
63-
* @brief Page for storing authenticator state information
64-
*/
65-
#define CTAP_FLASH_STATE_PAGE CTAP_FLASH_RK_START_PAGE - 1
50+
#if CONFIG_FIDO2_CTAP_NUM_FLASHPAGES <= 2 || \
51+
CONFIG_FIDO2_CTAP_NUM_FLASHPAGES >= FLASHPAGE_NUMOF
52+
#error "ctap_mem.h: Configured number of flashpages is invalid"
53+
#endif
6654

6755
/**
6856
* @brief Calculate padding needed to align struct size for saving to flash
@@ -155,6 +143,20 @@ int fido2_ctap_mem_get_flashpage_number_of_rk(uint16_t rk_idx);
155143
*/
156144
int fido2_ctap_mem_get_offset_of_rk_into_flashpage(uint16_t rk_idx);
157145

146+
/**
147+
* @brief Get page number for storing authenticator state information
148+
*
149+
* @return page number
150+
*/
151+
unsigned fido2_ctap_mem_get_state_flashpage_number(void);
152+
153+
/**
154+
* @brief Get start page for storing resident keys
155+
*
156+
* @return page number
157+
*/
158+
unsigned fido2_ctap_mem_get_rk_start_page(void);
159+
158160
#ifdef __cplusplus
159161
}
160162
#endif

0 commit comments

Comments
 (0)