From 6c60a37e8acec9bc72f15e33943cbfa4deed7bf2 Mon Sep 17 00:00:00 2001 From: Szczepan Zalega Date: Tue, 20 Aug 2019 11:19:22 +0200 Subject: [PATCH] Add initial STATE migration code --- fido2/data_migration.c | 87 ++++++++++++++++++++++++++++++++++++++++++ fido2/data_migration.h | 15 ++++++++ 2 files changed, 102 insertions(+) create mode 100644 fido2/data_migration.c create mode 100644 fido2/data_migration.h diff --git a/fido2/data_migration.c b/fido2/data_migration.c new file mode 100644 index 0000000..e4cbcf1 --- /dev/null +++ b/fido2/data_migration.c @@ -0,0 +1,87 @@ +// Copyright 2019 SoloKeys Developers +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +#include "data_migration.h" +#include "log.h" +#include "device.h" +#include "crypto.h" + +// TODO move from macro to function/assert for better readability? +#define check(x) assert(state_prev_0xff->x == state_tmp_ptr->x); +#define check_buf(x) assert(memcmp(state_prev_0xff->x, state_tmp_ptr->x, sizeof(state_tmp_ptr->x)) == 0); + +bool migrate_from_FF_to_01(AuthenticatorState* state_previous_ptr, AuthenticatorState* state_tmp_ptr){ + // Calculate PIN hash, and replace PIN raw storage with it; add version to structure + // other ingredients do not change + if (state_tmp_ptr->data_version != 0xFF) + return false; + + static_assert(sizeof(AuthenticatorState_0xFF) <= sizeof(AuthenticatorState), "New state structure is smaller, than current one, which is not handled"); + + AuthenticatorState_0xFF* state_prev_0xff = (AuthenticatorState_0xFF *) state_previous_ptr; + + if (ctap_generate_rng(state_tmp_ptr->PIN_SALT, sizeof(state_tmp_ptr->PIN_SALT)) != 1) { + printf2(TAG_ERR, "Error, rng failed\n"); + return false; + } + if (state_prev_0xff->is_pin_set){ + crypto_sha256_init(); + crypto_sha256_update(state_prev_0xff->pin_code, state_prev_0xff->pin_code_length); + uint8_t intermediateHash[32]; + crypto_sha256_final(intermediateHash); + + crypto_sha256_init(); + crypto_sha256_update(intermediateHash, 16); + memset(intermediateHash, 0, sizeof(intermediateHash)); + crypto_sha256_update(state_tmp_ptr->PIN_SALT, sizeof(state_tmp_ptr->PIN_SALT)); + crypto_sha256_final(state_tmp_ptr->PIN_CODE_HASH); + } + + state_tmp_ptr->_reserved = 0xFF; + state_tmp_ptr->data_version = 1; + + check(is_pin_set); + check(rk_stored); + check(remaining_tries); + check_buf(key_lens); + check_buf(key_space); + + return true; +} + +void save_migrated_state(AuthenticatorState *state_tmp_ptr) { + memmove(&STATE, state_tmp_ptr, sizeof(AuthenticatorState)); + authenticator_write_state(state_tmp_ptr, 0); + authenticator_write_state(state_tmp_ptr, 1); +} + +void do_migration_if_required(AuthenticatorState* state_current){ + // Currently handles only state structures with the same size, or bigger + // FIXME rework to raw buffers with fixed size to allow state structure size decrease + if(!state_current->is_initialized) + return; + + AuthenticatorState state_tmp; + AuthenticatorState state_previous; + authenticator_read_state(&state_previous); + authenticator_read_state(&state_tmp); + if(state_current->data_version == 0xFF){ + printf2(TAG_ERR, "Running migration\n"); + bool success = migrate_from_FF_to_01(&state_previous, &state_tmp); + if (!success){ + printf2(TAG_ERR, "Failed migration from 0xFF to 1\n"); + // FIXME discuss migration failure behavior + goto return_cleanup; + } + dump_hex1(TAG_ERR, (void*)&state_tmp, sizeof(state_tmp)); + dump_hex1(TAG_ERR, (void*)&state_previous, sizeof(state_previous)); + save_migrated_state(&state_tmp); + } + return_cleanup: + memset(&state_tmp, 0, sizeof(AuthenticatorState)); + memset(&state_previous, 0, sizeof(AuthenticatorState)); +} diff --git a/fido2/data_migration.h b/fido2/data_migration.h new file mode 100644 index 0000000..ffdd9b7 --- /dev/null +++ b/fido2/data_migration.h @@ -0,0 +1,15 @@ +// Copyright 2019 SoloKeys Developers +// +// Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be +// copied, modified, or distributed except according to those terms. + +#ifndef FIDO2_PR_DATA_MIGRATION_H +#define FIDO2_PR_DATA_MIGRATION_H + +#include "storage.h" + +void do_migration_if_required(AuthenticatorState* state_current); + +#endif //FIDO2_PR_DATA_MIGRATION_H