trezor / trezor-firmware

:lock: Trezor Firmware Monorepo
https://trezor.io
Other
1.36k stars 660 forks source link

Use salt from the SD card for encrypted storage #307

Closed prusnak closed 5 years ago

prusnak commented 5 years ago

Depends on merging https://github.com/trezor/trezor-firmware/pull/264

If the file named /trezor/entropy is found on the SD card during the boot, open the file, hash it and use the result as an extra entropy when initializing the encrypted storage.

We need to discuss the following: 1) how do we transition from regular storage to storage+sd_entropy storage (i.e. do we only allow this via the process on Trezor or can a user create their own entropy file manually on PC?) 2) do we need to store a special flag in the storage? (bool use_sd_card_entropy) - this would be very helpful, but we might need to initialize the storage twice?

andrewkozlik commented 5 years ago

Terminology I propose using the term "SD salt" or "external salt" rather than "entropy". The reason is that this data will be combined with the PIN using PBKDF2 and it will be appended to the salt parameter which currently consists of "random salt" stored in the NV RAM and "hardware salt".

Requirements

Implementation details

Possible future features to consider

prusnak commented 5 years ago

This would increase flash degradation, so it should be an optional setting.

Maybe we can do the following trick to avoid flash degradation when replacing the salt:

  1. keep the original salt file
  2. store the new salt in salt.new
  3. erase salt file
  4. rename salt.new to salt

This might force FAT to use new blocks every time for a new entropy file, but we should test it. Also it is a non atomic operation.

matejcik commented 5 years ago
  1. keep the original salt file
  2. store the new salt in salt.new
  3. erase salt file
  4. rename salt.new to salt

this makes old salts recoverable. is that a problem? it doesn't seem to be, but?

andrewkozlik commented 5 years ago
  1. keep the original salt file
  2. store the new salt in salt.new
  3. erase salt file
  4. rename salt.new to salt

this makes old salts recoverable. is that a problem? it doesn't seem to be, but?

Making old salts recoverable would be a bit problematic. Consider a scenario where an attacker tampers with the Trezor and manages to read out the internal NVRAM, then at some later time the attacker gains access to the SD card. If the user suspects that somebody tampered with their Trezor, then they could regenerate the salt and think they are safe. But if old salts are recoverable then the attacker could still decrypt the state of the storage as it was at the moment of tampering and gain access to the seed. On the other hand if the attacker gained access to the Trezor, then they could have done worse things. For example replaced the user's Trezor with a fake one, which would send all data from the SD card to the attacker as soon as it is plugged in.

In any case, I assumed that in step 3 above we would overwrite the original salt file with random data. To be more precise:

  1. keep the original salt file
  2. store the new salt in salt.new
  3. reencrypt the DEK and SAK using the new salt
  4. overwrite salt file with random data
  5. rename salt.new to salt
matejcik commented 5 years ago

In any case, I assumed that in step 3 above we would overwrite the original salt file with random data. To be more precise:

That makes the exercise pointless from the flash wear standpoint.

But in any case we are still wearing out the FAT segment. Isn't this a moot point though? How susceptible are today's SD cards to flash wear?

andrewkozlik commented 5 years ago

I started work on this feature: https://github.com/trezor/trezor-firmware/tree/andrewkozlik/sd-salt. The implementation seems to be working well on the emulator, but I haven't had time to test it all that much. I didn't do any testing whatsoever on the device. @stick please have a look to check that I am using the SD card and FATFS correctly.

TODOs

Notes In the core code I refer to the salt as "SD card salt", but in the storage code I refer to it as "external salt". Right now it's the same thing, but later on the external salt will be a combination of different salts from different sources.

Note that when this is merged with the FIDO2 branch, the check_pin() function in core/src/apps/webauthn/init.py will need to take retrieve the salt. This is similar to the change made in recovery_device/init.py.

It would be good to delegate the whole PIN checking procedure to a separate function, because it is getting complicated - get PIN from user, check if SD salt is in use, get salt from SD card, check PIN. Right now this code is duplicated in various forms in several places.

Testing Some test scenarios that come to mind:

andrewkozlik commented 5 years ago

The implementation is finished, but I think we still need to make a final decision on the naming of this feature. In case "SD card salt" is not suitable, it would be best to change the message name (SdSalt) and trezorctl command name (currently sd-salt) accordingly before merging. I prepared a short description of this feature for the wiki, which might help us identify some key words:

This feature serves as additional protection against physical attacks. When it is enabled, a randomly generated secret is stored on the SD card. During every PIN checking and unlocking operation this secret is combined with the entered PIN value to decrypt data stored on the device. Simply put, the device gets bound to the SD card and cannot be unlocked without it. However, if the SD card is lost or damaged the device can still be factory-reset or recovered using the backup seed.

Some names that come to mind (with trezorctl command and example usage):

  1. SD card protect: sd-protect, "secure your Trezor with SD card protection"
  2. SD card salt: sd-salt, "secure your Trezor with with SD card salt"
  3. SD card lock: sd-lock, "lock your Trezor with an SD card"
  4. SD card encryption: sd-encrypt, "encrypt the storage with SD card salt"
  5. SD card binding: sd-bind, "bind your Trezor with an SD card"
  6. SD card key: sd-key, "secure your Trezor with SD card key"
  7. SD card armor: sd-armor, "secure your Trezor with SD card armor"
prusnak commented 5 years ago

Let's have a vote on Monday :-)

andrewkozlik commented 5 years ago

The results of the vote, "+" indicates a vote for, "-" indicates a vote against:

(-1, +4) sd-protect: +@tsusanka , -@ciny , +@hiviah , +@prusnak , +@bentonoliver (-2, +1) sd-salt: -@tsusanka , +@hiviah , -@prusnak (-1, +0) sd-lock: -@prusnak (-3, +0) sd-encrypt: -@andrewkozlik , -@onvej , -@prusnak (-0, +2) sd-bind: +@tsusanka , +@bentonoliver (-2, +0) sd-key: -@onvej , -@prusnak

(I am not sure I captured all votes, so feel free to edit the above.)

Some opinions that people expressed:

@bentonoliver, @hiviah any opinions?

hiviah commented 5 years ago

I think actually "salt" means something to many users who heard at least something about cryptography. "sd-protect" would be second, but it's too generic.

So

bentonoliver commented 5 years ago

++ sd-bind ++ sd-protect Because both describe the intended result (as opposed to "salt" or "key").

prusnak commented 5 years ago

Closed via #526

andrewkozlik commented 5 years ago

Testing @sorooris

You will need two FAT32-formatted SD cards. You will also need to be using the current version of trezorctl. Clone the trezor-firmware repo if you don't have it yet and execute the following:

cd trezor-firmware
git checkout master
git pull
pipenv shell
# Type any trezorctl commands into this shell.

There is one new command for this feature in trezorctl: trezorctl sd-protect --help trezorctl sd-protect enable trezorctl sd-protect refresh trezorctl sd-protect disable

Basic flow:

  1. Insert SD card when Trezor is powered down.
  2. Power up.
  3. Run trezorctl sd-protect enable. Verify that the device asks for confirmation. Note: We are still experiencing random failures when writing to the SD card, so if this step fails, then try repeating it several times. Verify that it fails gracefully.
  4. Remove SD card and restart. Verify that the device cannot be unlocked without the SD card and user is informed.
  5. Power down, insert the same SD card, power up. Verify that the device can be unlocked successfully.
  6. Run trezorctl sd-protect disable. Verify that the device asks for confirmation.
  7. Remove SD card and restart. Verify that the device can be unlocked without the SD card.

Scenarios (some copied from above for convenience):