-
-
Notifications
You must be signed in to change notification settings - Fork 721
Tropic wear leveling #6136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Tropic wear leveling #6136
Changes from 2 commits
ea5ddb6
0bd6f2e
7f38f53
efea952
55a745a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| [T3W1] Introduce wear leveling of mac-and-destroy slots in Tropic. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,29 @@ | |
| // Maximum time to wait for Tropic to boot. Chosen arbitrarily. | ||
| #define TROPIC_BOOT_TIMEOUT_MS 1000 | ||
|
|
||
| // KEK masks used in PIN verification | ||
| #define TROPIC_KEK_MASKS_PRIVILEGED_SLOT 128 | ||
| #define TROPIC_KEK_MASKS_UNPRIVILEGED_SLOT 256 | ||
|
|
||
| // Mac-and-destroy slots used in PIN verification | ||
| #define TROPIC_FIRST_MAC_AND_DESTROY_SLOT_PRIVILEGED 0 | ||
| #define TROPIC_FIRST_MAC_AND_DESTROY_SLOT_UNPRIVILEGED 64 | ||
| #define TROPIC_MAC_AND_DESTROY_SLOTS_COUNT 64 | ||
|
|
||
| // The value by which the index of the first mac-and-destroy slot is shifted | ||
| // before every pin change.The value is a coprime to | ||
| // TROPIC_MAC_AND_DESTROY_SLOTS_COUNT to ensure that | ||
| // `get_mac_and_destroy_slot(i, change_pin_counter)` achieves the maximum | ||
| // possible period in `change_pin_counter`. | ||
| #define TROPIC_MAC_AND_DESTROY_SHIFT 11 | ||
|
|
||
| // The slot that stores the number of times the PIN has been changed. | ||
| // Since the counter can only be decremented, its acutal value is | ||
| // TROPIC_CHANGE_COUNTER_SLOT_MAX_VALUE minus the number of PIN changes. This | ||
| // slot is used both for both privileged and the unprivileged sessions. | ||
| #define TROPIC_CHANGE_COUNTER_SLOT MCOUNTER_INDEX_4 | ||
| #define TROPIC_CHANGE_COUNTER_SLOT_MAX_VALUE 0xfffffffe | ||
|
|
||
| typedef struct { | ||
| bool initialized; | ||
| bool session_started; | ||
|
|
@@ -370,11 +393,16 @@ void tropic_random_buffer_time(uint32_t *time_ms) { | |
| // Defined in tropic01.c | ||
| void tropic_set_ui_progress(tropic_ui_progress_t f); | ||
|
|
||
| static mac_and_destroy_slot_t get_first_mac_and_destroy_slot( | ||
| tropic_driver_t *drv) { | ||
| return drv->pairing_key_index == TROPIC_UNPRIVILEGED_PAIRING_KEY_SLOT | ||
| ? TROPIC_FIRST_MAC_AND_DESTROY_SLOT_UNPRIVILEGED | ||
| : TROPIC_FIRST_MAC_AND_DESTROY_SLOT_PRIVILEGED; | ||
| static mac_and_destroy_slot_t get_mac_and_destroy_slot( | ||
| uint16_t pin_index, uint32_t change_pin_counter) { | ||
| mac_and_destroy_slot_t first_slot_index = | ||
| g_tropic_driver.pairing_key_index == TROPIC_UNPRIVILEGED_PAIRING_KEY_SLOT | ||
| ? TROPIC_FIRST_MAC_AND_DESTROY_SLOT_UNPRIVILEGED | ||
| : TROPIC_FIRST_MAC_AND_DESTROY_SLOT_PRIVILEGED; | ||
|
|
||
| return first_slot_index + | ||
| (change_pin_counter * TROPIC_MAC_AND_DESTROY_SHIFT + pin_index) % | ||
| TROPIC_MAC_AND_DESTROY_SLOTS_COUNT; | ||
| } | ||
|
|
||
| static uint16_t get_kek_masks_slot(tropic_driver_t *drv) { | ||
|
|
@@ -395,8 +423,85 @@ static void lt_r_mem_data_write_time(uint32_t *time_ms) { | |
| *time_ms += 77; | ||
| } | ||
|
|
||
| static void lt_mcounter_get_time(uint32_t *time_ms) { *time_ms += 51; } | ||
|
|
||
| static void lt_mcounter_update_time(uint32_t *time_ms) { *time_ms += 51; } | ||
|
|
||
| static void lt_r_mem_data_erase_time(uint32_t *time_ms) { *time_ms += 55; } | ||
|
|
||
| static uint32_t change_pin_counter_cached = 0; | ||
| static bool is_change_pin_counter_cached = false; | ||
|
|
||
| static bool get_change_pin_counter(uint32_t *change_pin_counter) { | ||
| tropic_driver_t *drv = &g_tropic_driver; | ||
|
|
||
| if (is_change_pin_counter_cached) { | ||
| *change_pin_counter = change_pin_counter_cached; | ||
| return true; | ||
| } | ||
|
|
||
| lt_ret_t ret = lt_mcounter_get(&drv->handle, TROPIC_CHANGE_COUNTER_SLOT, | ||
| change_pin_counter); | ||
| if (ret == LT_L3_COUNTER_INVALID) { | ||
| // The counter has not been initialized yet | ||
| *change_pin_counter = 0; | ||
| change_pin_counter_cached = *change_pin_counter; | ||
| is_change_pin_counter_cached = true; | ||
| return true; | ||
| } | ||
|
|
||
| if (ret != LT_OK) { | ||
| return false; | ||
| } | ||
|
|
||
| *change_pin_counter = | ||
| TROPIC_CHANGE_COUNTER_SLOT_MAX_VALUE - *change_pin_counter; | ||
| change_pin_counter_cached = *change_pin_counter; | ||
| is_change_pin_counter_cached = true; | ||
onvej-sl marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| return true; | ||
| } | ||
|
|
||
| static void get_change_pin_counter_time(uint32_t *time_ms) { | ||
| if (!is_change_pin_counter_cached) { | ||
| lt_mcounter_get_time(time_ms); | ||
| } | ||
| } | ||
|
|
||
| static bool update_change_pin_counter() { | ||
| tropic_driver_t *drv = &g_tropic_driver; | ||
| lt_ret_t ret = LT_FAIL; | ||
|
|
||
| ret = lt_mcounter_update(&drv->handle, TROPIC_CHANGE_COUNTER_SLOT); | ||
| if (ret == LT_L3_COUNTER_INVALID) { | ||
| // The counter has not been initialized yet | ||
| ret = lt_mcounter_init(&drv->handle, TROPIC_CHANGE_COUNTER_SLOT, | ||
| TROPIC_CHANGE_COUNTER_SLOT_MAX_VALUE - 1); | ||
| if (ret != LT_OK) { | ||
| return false; | ||
| } | ||
| change_pin_counter_cached = 1; | ||
| is_change_pin_counter_cached = true; | ||
| return true; | ||
| } | ||
|
|
||
| if (ret != LT_OK) { | ||
| return false; | ||
| } | ||
|
|
||
| if (is_change_pin_counter_cached) { | ||
| change_pin_counter_cached++; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| static void update_change_pin_counter_time(uint32_t *time_ms) { | ||
| lt_mcounter_update_time(time_ms); | ||
| // Ignore the time of `lt_mcounter_init()` since we cannot easily determine | ||
| // whether it will be executed. | ||
| } | ||
|
|
||
| bool tropic_pin_stretch(tropic_ui_progress_t ui_progress, uint16_t pin_index, | ||
| uint8_t stretched_pin[TROPIC_MAC_AND_DESTROY_SIZE]) { | ||
| if (pin_index >= PIN_MAX_TRIES) { | ||
|
|
@@ -412,14 +517,18 @@ bool tropic_pin_stretch(tropic_ui_progress_t ui_progress, uint16_t pin_index, | |
| goto cleanup; | ||
| } | ||
|
|
||
| mac_and_destroy_slot_t first_slot_index = get_first_mac_and_destroy_slot(drv); | ||
|
|
||
| uint8_t digest[TROPIC_MAC_AND_DESTROY_SIZE] = {0}; | ||
|
|
||
| hmac_sha256(stretched_pin, TROPIC_MAC_AND_DESTROY_SIZE, NULL, 0, digest); | ||
|
|
||
| if (lt_mac_and_destroy(&drv->handle, first_slot_index + pin_index, digest, | ||
| digest) != LT_OK) { | ||
| uint32_t change_pin_counter = 0; | ||
| if (!get_change_pin_counter(&change_pin_counter)) { | ||
| goto cleanup; | ||
| } | ||
|
|
||
| if (lt_mac_and_destroy( | ||
| &drv->handle, get_mac_and_destroy_slot(pin_index, change_pin_counter), | ||
| digest, digest) != LT_OK) { | ||
| goto cleanup; | ||
| } | ||
|
|
||
|
|
@@ -435,6 +544,7 @@ bool tropic_pin_stretch(tropic_ui_progress_t ui_progress, uint16_t pin_index, | |
| } | ||
|
|
||
| void tropic_pin_stretch_time(uint32_t *time_ms) { | ||
| get_change_pin_counter_time(time_ms); | ||
| lt_mac_and_destroy_time(time_ms); | ||
| } | ||
|
|
||
|
|
@@ -456,11 +566,15 @@ bool tropic_pin_reset_slots( | |
|
|
||
| uint8_t output[TROPIC_MAC_AND_DESTROY_SIZE] = {0}; | ||
|
|
||
| mac_and_destroy_slot_t first_slot_index = get_first_mac_and_destroy_slot(drv); | ||
| uint32_t change_pin_counter = 0; | ||
| if (!get_change_pin_counter(&change_pin_counter)) { | ||
| goto cleanup; | ||
| } | ||
|
|
||
| for (int i = 0; i <= pin_index; i++) { | ||
| if (lt_mac_and_destroy(&drv->handle, first_slot_index + i, reset_key, | ||
| output) != LT_OK) { | ||
| if (lt_mac_and_destroy(&drv->handle, | ||
| get_mac_and_destroy_slot(i, change_pin_counter), | ||
| reset_key, output) != LT_OK) { | ||
| goto cleanup; | ||
| } | ||
| } | ||
|
|
@@ -475,6 +589,7 @@ bool tropic_pin_reset_slots( | |
| } | ||
|
|
||
| void tropic_pin_reset_slots_time(uint32_t *time_ms, uint16_t pin_index) { | ||
| get_change_pin_counter_time(time_ms); | ||
|
||
| for (int i = 0; i <= pin_index; i++) { | ||
| lt_mac_and_destroy_time(time_ms); | ||
| } | ||
|
|
@@ -497,30 +612,38 @@ bool tropic_pin_set( | |
| goto cleanup; | ||
| } | ||
|
|
||
| if (!update_change_pin_counter()) { | ||
| goto cleanup; | ||
| } | ||
| uint32_t change_pin_counter = 0; | ||
| if (!get_change_pin_counter(&change_pin_counter)) { | ||
| goto cleanup; | ||
| } | ||
|
|
||
| uint8_t output[TROPIC_MAC_AND_DESTROY_SIZE] = {0}; | ||
| uint8_t digest[TROPIC_MAC_AND_DESTROY_SIZE] = {0}; | ||
|
|
||
| mac_and_destroy_slot_t first_slot_index = get_first_mac_and_destroy_slot(drv); | ||
|
|
||
| for (int i = 0; i < PIN_MAX_TRIES; i++) { | ||
| if (lt_mac_and_destroy(&drv->handle, first_slot_index + i, reset_key, | ||
| output) != LT_OK) { | ||
| mac_and_destroy_slot_t slot_index = | ||
| get_mac_and_destroy_slot(i, change_pin_counter); | ||
|
|
||
| if (lt_mac_and_destroy(&drv->handle, slot_index, reset_key, output) != | ||
| LT_OK) { | ||
| goto cleanup; | ||
| } | ||
|
|
||
| hmac_sha256(stretched_pins[i], TROPIC_MAC_AND_DESTROY_SIZE, NULL, 0, | ||
| digest); | ||
|
|
||
| if (lt_mac_and_destroy(&drv->handle, first_slot_index + i, digest, | ||
| digest) != LT_OK) { | ||
| if (lt_mac_and_destroy(&drv->handle, slot_index, digest, digest) != LT_OK) { | ||
| goto cleanup; | ||
| } | ||
|
|
||
| hmac_sha256(stretched_pins[i], TROPIC_MAC_AND_DESTROY_SIZE, digest, | ||
| sizeof(digest), stretched_pins[i]); | ||
|
|
||
| if (lt_mac_and_destroy(&drv->handle, first_slot_index + i, reset_key, | ||
| output) != LT_OK) { | ||
| if (lt_mac_and_destroy(&drv->handle, slot_index, reset_key, output) != | ||
| LT_OK) { | ||
| goto cleanup; | ||
| } | ||
| } | ||
|
|
@@ -537,6 +660,8 @@ bool tropic_pin_set( | |
|
|
||
| void tropic_pin_set_time(uint32_t *time_ms) { | ||
| rng_fill_buffer_strong_time(time_ms); | ||
| update_change_pin_counter_time(time_ms); | ||
| get_change_pin_counter_time(time_ms); | ||
|
||
| for (int i = 0; i < PIN_MAX_TRIES; i++) { | ||
| lt_mac_and_destroy_time(time_ms); | ||
| lt_mac_and_destroy_time(time_ms); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.