Skip to content

fix: require a TC Code to enable TC Flash Hash at Boot - #966

Open
Thanatos9404 wants to merge 2 commits into
selfcustody:developfrom
Thanatos9404:fix/813-tc-flash-hash-needs-tc-code
Open

Thanatos9404 wants to merge 2 commits into
selfcustody:developfrom
Thanatos9404:fix/813-tc-flash-hash-needs-tc-code

Conversation

@Thanatos9404

Copy link
Copy Markdown

What is this PR for?

Fixes #813

Settings > Security > TC Flash Hash at Boot could be set to True even when no Tamper Check Code was stored. At boot, tc_code_verification() returns early when there is no TC Code file, so the option silently did nothing while the menu showed it as enabled.

Now, if the user tries to switch it to True without a TC Code, Krux flashes the existing "Set a tamper check code first" error (the same one Tools > Flash Tools > TC Flash Hash already shows) and the value stays False. It uses ctx.tc_code_enabled, which boot.py and enter_modify_tc_code() already keep up to date.

Some details:

  • With a TC Code set, the option toggles exactly as before.
  • Switching it to False is always allowed, so a True that was saved before the TC Code went away (for example settings kept on the SD card after erasing user's data) can still be cleared.
  • The prompt that offers to enable it right after creating a TC Code is unchanged.
  • No new strings, so no translation changes. The warning reuses an already translated message.

This only touches the settings page logic and adds one sentence to the settings docs. It does not change the TC Code storage, hashing or the boot flow.

Changes made to:

  • Code
  • Tests
  • Docs
  • CHANGELOG

Did you build the code and tested on device?

  • Yes, build and tested on

Not tested on a device. Tested with the test suite:

  • uv run pytest --cache-clear tests/pages/test_settings_page.py: 34 passed. The new test_enable_boot_flash_hash_without_tc_code fails on current develop and passes with this change. The other two new tests (enable with a TC Code, disable a stored value without a TC Code) cover the cases that should keep working.
  • uv run poe test-simple: 1197 passed, 1 xfailed
  • uv run poe lint-src: 10.00/10
  • black --check src tests: unchanged
  • uv run poe i18n validate and uv run poe vulture: OK

What is the purpose of this pull request?

  • Bug fix
  • New feature
  • Docs update
  • Other

TC Flash Hash at Boot only runs when a Tamper Check Code is stored, so
turning it on without one had no effect and gave a false sense of
protection. The setting now refuses True when no TC Code is set,
reusing the existing "Set a tamper check code first" warning, and stays
False. Turning it off is always allowed, so a value loaded from older
settings can still be cleared.

Fixes selfcustody#813
@qlrd

qlrd commented Oct 21, 2026

Copy link
Copy Markdown
Member

cc @tadeubas

@HarshPopat23

Copy link
Copy Markdown

Host-side Tested ACK on fb40181, compared with 2937a29.

Confirmed that enabling without a TC Code is rejected, normal toggling with a code works, and a previously stored True can still be disabled without a code. The regression test fails on the base and passes here.

All 34 settings tests and 17 additional edge cases passed, including repeated attempts, touch controls, persistence, cancellation, and enabling after code creation. Full suite: 1,197 passed, 1 expected failure.

No blocking findings. No firmware build or physical-device testing; GitHub CI still requires maintainer approval.

LGTM form my side.

Comment on lines +455 to +459
elif setting.attr == "boot_flash_hash":
# Without a TC Code there is nothing to verify at boot
if new_category and not self.ctx.tc_code_enabled:
self.flash_error(t("Set a tamper check code first"))
Settings().security.boot_flash_hash = False

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you check and verify this finding?

Some Swipes and long-presses leave the value unchanged but still trigger it (:387, :397). If the saved value is True with no TC Code, such a press shows "Set a tamper check code first" and turns the option off, although the user never tried to enable it. The resulting state is the right one; only the message is misleading. Worth to check if is necessary to compare against current_category and/or be left as is.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any thoughts on that @Thanatos9404 ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the finding was right, and I fixed it in dcdf382. category_setting now passes new_category != current_category to _category_change_special_cases, so the error and the reset only happen when a press actually changes the value. A swipe or long-press on a stored True with no TC Code is now a no-op, and test_unchanged_press_keeps_stored_boot_flash_hash_quiet covers that on all devices.

Comment thread tests/pages/test_settings_page.py Outdated
assert mock_file.write_data == b""


def test_enable_boot_flash_hash_without_tc_code(m5stickv, mocker):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests done with m5stickv only. IMO is good to test with all devices in current global context.

Comment thread docs/getting-started/settings.en.md Outdated
Comment on lines +166 to +168
A [Tamper Check Code](#tamper-check-code) must be set first. Otherwise, Krux
shows a warning and keeps this option disabled.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A [Tamper Check Code](#tamper-check-code) must be set first. Otherwise, Krux
shows a warning and keeps this option disabled.
A [Tamper Check Code](#tamper-check-code) must be set first. Otherwise, Krux shows an error and keeps this option disabled.

Presses that leave the value unchanged no longer show the TC Code error. Tests now run on every device.
@Thanatos9404

Copy link
Copy Markdown
Author

Thanks for the review. Pushed dcdf382: the TC Code error now only shows when the value actually changes, so swipes and long-presses on a stored True no longer trigger it. I applied the docs wording as suggested. The boot_flash_hash tests now use the multiple_devices fixture (all 7 devices), plus a new test for the unchanged-press case.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants