diff --git a/firmware/config.c b/firmware/config.c index 520effd2a0..980d130585 100644 --- a/firmware/config.c +++ b/firmware/config.c @@ -53,20 +53,21 @@ static const uint32_t CONFIG_MAGIC_V10 = 0x726f7473; // 'stor' as uint32_t static const uint16_t KEY_UUID = 0 | APP | FLAG_PUBLIC; // bytes(12) static const uint16_t KEY_VERSION = 1 | APP; // uint32 -static const uint16_t KEY_NODE = 2 | APP; // node -static const uint16_t KEY_MNEMONIC = 3 | APP; // string(241) -static const uint16_t KEY_PASSPHRASE_PROTECTION = 4 | APP; // bool -static const uint16_t KEY_LANGUAGE = 5 | APP | FLAG_PUBLIC; // string(17) -static const uint16_t KEY_LABEL = 6 | APP | FLAG_PUBLIC; // string(33) -static const uint16_t KEY_IMPORTED = 7 | APP; // bool -static const uint16_t KEY_HOMESCREEN = 8 | APP | FLAG_PUBLIC; // bytes(1024) +static const uint16_t KEY_MNEMONIC = 2 | APP; // string(241) +static const uint16_t KEY_LANGUAGE = 3 | APP | FLAG_PUBLIC; // string(17) +static const uint16_t KEY_LABEL = 4 | APP | FLAG_PUBLIC; // string(33) +static const uint16_t KEY_PASSPHRASE_PROTECTION = 5 | APP; // bool +static const uint16_t KEY_HOMESCREEN = 6 | APP | FLAG_PUBLIC; // bytes(1024) +static const uint16_t KEY_NEEDS_BACKUP = 7 | APP; // bool +static const uint16_t KEY_FLAGS = 8 | APP; // uint32 static const uint16_t KEY_U2F_COUNTER = 9 | APP | FLAG_PUBLIC; // uint32 -static const uint16_t KEY_NEEDS_BACKUP = 10 | APP; // bool -static const uint16_t KEY_FLAGS = 11 | APP; // uint32 -static const uint16_t KEY_U2F_ROOT = 12 | APP; // node -static const uint16_t KEY_UNFINISHED_BACKUP = 13 | APP; // bool -static const uint16_t KEY_AUTO_LOCK_DELAY_MS = 14 | APP; // uint32 -static const uint16_t KEY_NO_BACKUP = 15 | APP; // bool +static const uint16_t KEY_UNFINISHED_BACKUP = 11 | APP; // bool +static const uint16_t KEY_AUTO_LOCK_DELAY_MS = 12 | APP; // uint32 +static const uint16_t KEY_NO_BACKUP = 13 | APP; // bool +static const uint16_t KEY_INITIALIZED = 14 | APP | FLAG_PUBLIC; // uint32 +static const uint16_t KEY_NODE = 15 | APP; // node +static const uint16_t KEY_IMPORTED = 16 | APP; // bool +static const uint16_t KEY_U2F_ROOT = 17 | APP | FLAG_PUBLIC; // node // The PIN value corresponding to an empty PIN. static const uint32_t PIN_EMPTY = 1; @@ -290,7 +291,9 @@ static bool config_upgrade_v10(void) storage_set(KEY_UUID, config_uuid, sizeof(config_uuid)); storage_set(KEY_VERSION, &CONFIG_VERSION, sizeof(CONFIG_VERSION)); if (config.has_node) { - storage_set(KEY_NODE, &config.node, sizeof(config.node)); + if (sectrue == storage_set(KEY_NODE, &config.node, sizeof(config.node))) { + config_set_bool(KEY_INITIALIZED, true); + } } if (config.has_mnemonic) { config_setMnemonic(config.mnemonic); @@ -402,7 +405,9 @@ static void config_setNode(const HDNodeType *node) { storageHDNode.private_key.size = 32; memcpy(storageHDNode.private_key.bytes, node->private_key.bytes, 32); } - storage_set(KEY_NODE, &storageHDNode, sizeof(storageHDNode)); + if (sectrue == storage_set(KEY_NODE, &storageHDNode, sizeof(storageHDNode))) { + config_set_bool(KEY_INITIALIZED, true); + } } #if DEBUG_LINK @@ -628,21 +633,33 @@ bool config_getHomescreen(uint8_t *dest, uint16_t dest_size) return true; } -void config_setMnemonic(const char *mnemonic) +bool config_setMnemonic(const char *mnemonic) { if (mnemonic == NULL) { - return; + return false; } if (sectrue != storage_set(KEY_MNEMONIC, mnemonic, strnlen(mnemonic, MAX_MNEMONIC_LEN))) { - return; + return false; + } + + if (sectrue != config_set_bool(KEY_INITIALIZED, true)) { + storage_delete(KEY_MNEMONIC); + return false; } StorageHDNode u2fNode; memzero(&u2fNode, sizeof(u2fNode)); config_compute_u2froot(mnemonic, &u2fNode); - storage_set(KEY_U2F_ROOT, &u2fNode, sizeof(u2fNode)); + secbool ret = storage_set(KEY_U2F_ROOT, &u2fNode, sizeof(u2fNode)); memzero(&u2fNode, sizeof(u2fNode)); + + if (sectrue != ret) { + storage_delete(KEY_MNEMONIC); + storage_delete(KEY_INITIALIZED); + return false; + } + return true; } bool config_hasNode(void) @@ -756,7 +773,7 @@ bool session_isPinCached(void) bool config_isInitialized(void) { - return config_has_key(KEY_NODE) || config_has_key(KEY_MNEMONIC); + return config_get_bool(KEY_INITIALIZED); } bool config_isImported(void) diff --git a/firmware/config.h b/firmware/config.h index 8bde314da0..a44b6f29f3 100644 --- a/firmware/config.h +++ b/firmware/config.h @@ -111,7 +111,7 @@ void session_cachePassphrase(const char *passphrase); bool session_isPassphraseCached(void); bool session_getState(const uint8_t *salt, uint8_t *state, const char *passphrase); -void config_setMnemonic(const char *mnemonic); +bool config_setMnemonic(const char *mnemonic); bool config_containsMnemonic(const char *mnemonic); bool config_hasMnemonic(void); bool config_getMnemonic(char *dest, uint16_t dest_size); diff --git a/firmware/fsm_msg_common.h b/firmware/fsm_msg_common.h index 25fef38382..93e2d8abcd 100644 --- a/firmware/fsm_msg_common.h +++ b/firmware/fsm_msg_common.h @@ -63,7 +63,7 @@ void fsm_msgGetFeatures(const GetFeatures *msg) } resp->has_initialized = true; resp->initialized = config_isInitialized(); - resp->has_imported = true; resp->imported = config_isImported(); + resp->has_imported = config_hasKey(KEY_IMPORTED); resp->imported = config_isImported(); resp->has_pin_cached = true; resp->pin_cached = session_isPinCached(); resp->has_passphrase_cached = true; resp->passphrase_cached = session_isPassphraseCached(); resp->has_needs_backup = true; resp->needs_backup = config_needsBackup(); @@ -180,6 +180,8 @@ void fsm_msgGetEntropy(const GetEntropy *msg) void fsm_msgLoadDevice(const LoadDevice *msg) { + CHECK_PIN + CHECK_NOT_INITIALIZED layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("I take the risk"), NULL, _("Loading private seed"), _("is not recommended."), _("Continue only if you"), _("know what you are"), _("doing!"), NULL); @@ -204,6 +206,8 @@ void fsm_msgLoadDevice(const LoadDevice *msg) void fsm_msgResetDevice(const ResetDevice *msg) { + CHECK_PIN + CHECK_NOT_INITIALIZED CHECK_PARAM(!msg->has_strength || msg->strength == 128 || msg->strength == 192 || msg->strength == 256, _("Invalid seed strength")); @@ -331,6 +335,8 @@ void fsm_msgApplySettings(const ApplySettings *msg) void fsm_msgApplyFlags(const ApplyFlags *msg) { + CHECK_PIN + if (msg->has_flags) { config_applyFlags(msg->flags); } @@ -339,10 +345,10 @@ void fsm_msgApplyFlags(const ApplyFlags *msg) void fsm_msgRecoveryDevice(const RecoveryDevice *msg) { + CHECK_PIN + const bool dry_run = msg->has_dry_run ? msg->dry_run : false; - if (dry_run) { - CHECK_PIN - } else { + if (!dry_run) { CHECK_NOT_INITIALIZED } diff --git a/firmware/protect.c b/firmware/protect.c index 0d416c41ec..423c2fd985 100644 --- a/firmware/protect.c +++ b/firmware/protect.c @@ -180,17 +180,20 @@ void protectPinUiCallback(uint32_t wait, uint32_t progress) bool protectPin(bool use_cached) { - if (!config_hasPin() || (use_cached && session_isPinCached())) { + if (use_cached && session_isPinCached()) { return true; } // TODO If maximum number of PIN attempts: // error_shutdown("Too many wrong PIN", "attempts. Storage has", "been wiped.", NULL, "Please unplug", "the device."); - const char *pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_Current, _("Please enter current PIN:")); - if (!pin) { - fsm_sendFailure(FailureType_Failure_PinCancelled, NULL); - return false; + const char *pin = ""; + if (config_hasPin()) { + pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_Current, _("Please enter current PIN:")); + if (!pin) { + fsm_sendFailure(FailureType_Failure_PinCancelled, NULL); + return false; + } } usbTiny(1); diff --git a/firmware/recovery.c b/firmware/recovery.c index c12dda3afa..f7e5460fc8 100644 --- a/firmware/recovery.c +++ b/firmware/recovery.c @@ -164,13 +164,16 @@ static void recovery_done(void) { // New mnemonic is valid. if (!dry_run) { // Update mnemonic on config. - config_setMnemonic(new_mnemonic); - memzero(new_mnemonic, sizeof(new_mnemonic)); - if (!enforce_wordlist) { - // not enforcing => mark config as imported - config_setImported(true); + if (config_setMnemonic(new_mnemonic)) { + if (!enforce_wordlist) { + // not enforcing => mark config as imported + config_setImported(true); + } + fsm_sendSuccess(_("Device recovered")); + } else { + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to store mnemonic")); } - fsm_sendSuccess(_("Device recovered")); + memzero(new_mnemonic, sizeof(new_mnemonic)); } else { // Inform the user about new mnemonic correctness (as well as whether it is the same as the current one). bool match = (config_isInitialized() && config_containsMnemonic(new_mnemonic)); diff --git a/firmware/reset.c b/firmware/reset.c index 0765fe595f..58479ab2ee 100644 --- a/firmware/reset.c +++ b/firmware/reset.c @@ -97,6 +97,8 @@ void reset_entropy(const uint8_t *ext_entropy, uint32_t len) fsm_sendFailure(FailureType_Failure_UnexpectedMessage, _("Not in Reset mode")); return; } + awaiting_entropy = false; + SHA256_CTX ctx; sha256_Init(&ctx); sha256_Update(&ctx, int_entropy, 32); @@ -104,7 +106,6 @@ void reset_entropy(const uint8_t *ext_entropy, uint32_t len) sha256_Final(&ctx, int_entropy); const char* mnemonic = mnemonic_from_data(int_entropy, strength / 8); memzero(int_entropy, 32); - awaiting_entropy = false; if (skip_backup || no_backup) { if (no_backup) { @@ -112,8 +113,11 @@ void reset_entropy(const uint8_t *ext_entropy, uint32_t len) } else { config_setNeedsBackup(true); } - config_setMnemonic(mnemonic); - fsm_sendSuccess(_("Device successfully initialized")); + if (config_setMnemonic(mnemonic)) { + fsm_sendSuccess(_("Device successfully initialized")); + } else { + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to store mnemonic")); + } layoutHome(); } else { reset_backup(false, mnemonic); @@ -169,8 +173,11 @@ void reset_backup(bool separated, const char* mnemonic) fsm_sendSuccess(_("Seed successfully backed up")); } else { config_setNeedsBackup(false); - config_setMnemonic(mnemonic); - fsm_sendSuccess(_("Device successfully initialized")); + if (config_setMnemonic(mnemonic)) { + fsm_sendSuccess(_("Device successfully initialized")); + } else { + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to store mnemonic")); + } } layoutHome(); }