-
Notifications
You must be signed in to change notification settings - Fork 6
Backups
There are two categories of backups, a FULL DEVICE backup, and a Vault only backup of TOTP and/or passwords.
Vault TOTP/passwords only via vaultbackup-rs (good to do periodically if you've added new secrets, whether there is a new Xous release or not)
Preparation (this should be done on a trusted computer, and disconnect from the network after installing the dependencies if you don't want to risk your unencrypted secrets getting synced anywhere)
- Install rust+cargo with rustup
- If you run
cargo run
from thevaultbackup-rs
folder it should start downloading dependencies and will eventually fail due to some non-Rust system packages that need installed. - Install your distro's version of
gcc
hidapi-dev
protobuf-compiler
(aka protoc), and if you are lucky the associated packages pulled in will satisfy all the necessary dependencies, if not, look for a package that provides the thing missing in the error message. - Run
cargo run
again and it should print the help output ofvaultbackup-rs
. - Read the README for how to perform a backup/restore.
FULL DEVICE backup (good to do prior to updating Xous, even though the migrations have been fairly smooth so far)
- Main menu selection -> "Prepare backups"
- Select "yes" to performing the backup. Once the process is started, it cannot be stopped because the system is put into a pre-shutdown state to ensure the PDDB is not modified between the checksum computation and when the backup runs.
- Wait about 1 minute while the entire PDDB is checksummed
- Enter your
root
password - Write down the BIP-39 wordlist. This is your backup key. It will be the same for every backup of the same device, unless specifically re-keyed.
- Optionally verify your transcription by typing it back in.
- Wait until a modal pops up with a QR code directing to this page.
- Plug the device into a computer via USB.
- Run
python3 xous-core/tools/backup.py
: this script.- If you have not previously connected to Precursor via USB, you may need to set up your host by following the installation instructions here.
- To quickly grab the dependencies required for
backup.py
, runpip install precursorupdater --upgrade
and it will pull in pretty much everything you need.
- The backup will be named
backup_%Y%m%d_%H%M%S.pddb
(has the timestamp not a placeholder, but is in the format ofdate +'%Y%m%d_%H%M%S
). Store it separately from your backup/upgrade/root key.
- Plug the target device into your computer.
- Locate your
restore.py
script and yourbackup.pddb
file into the same directory.
- Run
restore.py
- Answer
y
to proceed. Optionally check the restore suite for sanity. - Wait about 30 minutes to 2 hours, depending upon the speed of your host's USB.
- Enter your BIP-39 backup key on the screen of the target device
- Enter your
root
password - Wait about 5 minutes for the system to commit your backup key block to the new device
- Reboot your device by inserting a paperclip in the lower right hand corner. You may get a black screen noting something about a mismatch of keys until you do this.
- If you are restoring to the same device you created the backup from, you're done.
- If you are restoring to a different device, follow the next set of instructions.
- On boot, you will be asked for your
unlock PIN
(not your root password -- this is the screen unlock PIN). - You will then be asked to unlock any secret Bases that may exist in your PDDB. Failure to unlock a secret Basis at this point is likely equivalent to deleting the Basis.
- Once all the secret Bases have been unlocked, the rekeying process will proceed. It will take between 5-30 minutes, depending on the amount of data you have in the device.
- You're done.
- Backups restored to a new device lose some amount of deniability, as the preferred algorithm is a
fast rekey
which only salts about 10% of the unused space to create some "fuzz" if someone were to do a ciphertext diff of the backup and the rekeyed restore. If you require full deniability, runpddb churn
and be prepared to wait a while as 100% of the disk is turned over. - Backups restored to a new device have the backup key reset to 0. You will need to create a new backup key for the new device.
This flow is for devices that were permanently fused, but bricked and you have the backup key.
If you have a fused device that is bricked and you never did a backup, there is NO RECOVERY (and there is NO WARRANTY service for this state -- permanently sealed devices with no fusing is done at your own risk!).
Note: as of July 2022, this is just an outline of the recovery flow. The scripts mentioned below still need to be created.
- Download and copy the off-line Raspberry Pi image to a microSD card that you will destroy upon completion of the procedure.
- The image contains Python3 plus the collection of scripts in the
betrusted-scripts
repository, plus it is configured to have its network drivers permanently disabled. - Copy the
backup.pddb
file, along with the latest device firmware (xous.img
,soc_csr.bin
,loader.bin
) to a USB drive. - Copy these four files to the Pi, in a
precursors
directory parallel to thebetrusted-scripts
directory.
- Connect a naive Precursor to the Pi via USB.
- Run the
restore-usb.py
script. - Enter your BIP-39 key list directly on the Pi console (there is no network connection!)
- The script will:
- Encrypt
soc_csr.bin
to your backup key (which is also your FPGA key on the bricked device) - Burn the
xous.img
,soc_csr.bin
,loader.bin
, andbackup.pddb
to your device - Set the "restore" block
- Encrypt
- Reboot the device. You will have to use the paperclip hole on the lower right corner to force a SoC reload.
- In an abundance of caution, securely dispose of the microSD card. There are no intentional copies of your secret keys stored on it, but, we can't guarantee that.
- The device should now pick up that a restoration is in progress, and proceed from step 5 in the "normal" restoration flow.
As a hardware security device, there is an inherent risk in doing any backups of Precursor: the whole idea of a hardware security module (HSM) is that the secret keys are generated within the module and never leave the boundaries of the module, giving one a strong cryptographic guarantee on the confidentiality of data secured by the HSM.
The problem with this approach is that if you lose or damage the HSM, your data is also lost forever. Because hardware has a finite lifetime and disasters can and do happen, one must carefully weigh the risk of the loss of secrets kept in a single device, versus the risk of having backups of the secrets - backups that, by their very nature, could be compromised. Bear in mind that one of the most common reasons people lose cryptocurrency is the loss of private keys or the passwords used to secure the keys.
The backup methodology described here aims to restore a device has been lost, damaged, stolen, or seized. It will not recover a lost password -- if you lose your password, your data is lost with it.
Significantly, backups are not compulsory or automatic -- thus users who find it more appropriate to keep all their secrets in one basket can rest assured that unless they run this procedure, their secret keys remain within the four corners of their device.
From the user's perspective, there are two artifacts produced by the backup process:
- A BIP-39 word list that is the secret key. It will be the same key for every backup of the same device, unless specifically re-keyed.
- An encrypted image that can be stored almost anywhere, so long as the secret key is safe.
This word list must be kept secret. Write it directly to a piece of paper and hide it or place it in a safe. Do not copy this into any electronic form. The cryptocurrency community has numerous durable and fireproof methods for keeping BIP-39 wordlists safe.
The encrypted image can be copied and kept anywhere. Read the technical details below for some small caveats.
Your unlock PIN and update passwords are not backed up. Neither are the names of any secret Basis or their passwords.
This means even with the secret key and the backup image, an adversary still cannot freely access all the data within the PDDB: they must also have your passwords.
As always, it's up to you to keep your passwords safe.
The BIP-39 word list is the AES-256 key that is used to encrypt the SoC image. If you never set the AES-256 key (most developers have not), you will find that the BIP-39 word list is trivial, as you are using the "all zeroes" key.
The encrypted image consists of:
- A copy of the PDDB. All data structures are encrypted by the root key block.
- A copy of the root key block within the SoC, encrypted with the secret key.
The free space cache within the PDDB has an observable structure; an adversary with historical copies of this may be able to make some loose assertions about the amount of data contained within the PDDB. If you are storing bulk data (>20-ish MiB) within the PDDB and need it to be deniable, do not keep a backup history. Only keep the most recent backup copy.
The key block consists of:
A plaintext header with:
- Version number of the key block
- Version number of xous.img
- Version number of soc_csr.bin
- Version number of the EC
- Version number of the WF200
- Timestamp in seconds since epoch UTC of the creation date
- A flag to indicate whether the operation is a backup or a restore operation
The encrypted key block with:
- Version number of the key block
- Version number of xous.img
- Version number of soc_csr.bin
- Version number of the EC
- Version number of the WF200
- Timestamp in seconds since epoch UTC of the creation date
- The root key block itself
- A key commitment structure
This section specifies the desired user experience. I wrote this before writing any code, so until this line is deleted it may not actually reflect what was actually implemented.
- Main menu selection -> PDDB submenu
- PDDB submenu -> "Prepare backups"
- Dialog box, originating from
rootkeys
prompts for system update password -
rootkeys
extracts its key block, and wraps it in AES-GCM-SIV with key commitment. - The encrypted block is placed at offset 0x01D7_F000 in the FLASH ROM, with the "backup" flag set (one page before the PDDB start)
- A BIP-39 representation of the AES-256 key is displayed in a notification modal
- The user is given an opportunity to re-enter their key to check if it is written down correctly. If they pick yes, a modal will pop up to have them enter the key; if not, this step is skipped.
- Once modal is dismissed, a new modal is popped up instructing the user to plug the device into a computer. This also sets the USB mode to permissive (debug mode active, readout enabled)
- User plugs the device into a host computer with USB
- User runs a script
python3 ./tools/backup.py
which will automatically copy the PDDB and the root key block, and concatenate them into a file namedbackup.pddb
. The script will halt the device while the backup is running to prevent consistency errors in the PDDB readout. - The backup script will reboot the device once finished.
- On boot,
rootkeys
will check to see if 0x01D7_F000 is blank. If it is not, and the "backup" flag is set, it will automatically erase the staged backup keys.
- User will marshall their
backup.pddb
file. - The user may also optionally line up an appropriate
xous.img
,soc_csr.bin
,loader.img
,ec_fw.bin
so that the OS matches the version of the PDDB that was backed up. - The user plugs a naive Precursor device into their host, or a bootable, previously fused device. NOTE: if your device was previously fused but it is unbootable, you will need the aid of a third party device to recover it. See the next flow.
- The user runs a script
python3 ./tools/restore.py
. This will:- (If no images are specified) Check the
backup.pddb
file for the versions required ofxous.img
,soc_csr.bin
,loader.img
and attempt to download those images from the CI server. - Write all of the firmware artifacts to the Precursor device
- Write the key block to the Precursor device, with the "restore" flag set
- Instruct the user to reboot the device by inserting a paperclip in the lower right hand hole to re-load the gateware
- (If no images are specified) Check the
- On boot, the
rootkeys
server will check the block at 0x01D7_F000 and find it is not blank, and has the "restore" flag set. It will:- Check the EC revision. If it is not correct, it will automatically update the EC, and force a reboot of the device.
- Test to see if the "all 0's" key works to decrypt the image (as a dev convenience). If not, it will
- Prompt the user to enter their BIP-39 decryption key on the device.
- (future fetaure) Ask the user if they want to burn the eFuse now.
- Provision the key block into the gateware either:
- Encrypting to the "0" key if no eFuse burning is requested
- Encrypting to the existing BIP39 key and burn the eFuse if requested
- Delete the block at 0x01D7_F000 so the process does not repeat itself
- Ask the user to reboot the device using the paperclip to reload the SoC with new keys
- IMPORTANT If no eFuse burning was requested, the SoC will be encrypted with the "all zeroes" key. This is an insecure state, but probably the go-to for developers for now. This can be remedied by either running the BBRAM key burn or the eFuse burn (once ungated).
This flow is for devices that were permanently fused, but bricked and you have the backup key.
If you have a fused device that is bricked and you never did a backup, there is NO RECOVERY (and there is NO WARRANTY service for this state -- permanently sealed devices with no fusing is done at your own risk!).
Note: as of July 2022, this is just an outline of the recovery flow. The scripts mentioned below still need to be created.
- Download and copy the off-line Raspberry Pi image to a microSD card that you will destroy upon completion of the procedure.
- The image contains Python3 plus the collection of scripts in the
betrusted-scripts
repository, plus it is configured to have its network drivers permanently disabled. - Copy the
backup.pddb
file, along with the latest device firmware (xous.img
,soc_csr.bin
,loader.bin
) to a USB drive. - Copy these four files to the Pi, in a
precursors
directory parallel to thebetrusted-scripts
directory.
- Connect a naive Precursor to the Pi via USB.
- Run the
restore-usb.py
script. - Enter your BIP-39 key list directly on the Pi console (there is no network connection!)
- The script will:
- Encrypt
soc_csr.bin
to your backup key (which is also your FPGA key on the bricked device) - Burn the
xous.img
,soc_csr.bin
,loader.bin
, andbackup.pddb
to your device - Set the "restore" block
- Encrypt
- Reboot the device. You will have to use the paperclip hole on the lower right corner to force a SoC reload.
- In an abundance of caution, securely dispose of the microSD card. There are no intentional copies of your secret keys stored on it, but, we can't guarantee that.
- The device should now pick up that a restoration is in progress, and proceed from step 5 in the "normal" restoration flow.
Old notes on how to do backup/restore before self-restore was possible.
- Download and copy the off-line Raspberry Pi image to a microSD card that you will destroy upon completion of the procedure.
- The image contains Python3 plus the collection of scripts in the
betrusted-scripts
repository, plus it is configured to have its network drivers permanently disabled. - Copy the
backup.pddb
file, along with the latest device firmware (xous.img
,soc_csr.bin
,loader.bin
) to a USB drive. - Copy these four files to the Pi, in a
precursors
directory parallel to thebetrusted-scripts
directory.
From here, you have a choose-your-own adventure: restore by USB, or by Pi HAT.
Option 1: Restore by USB
This option is inherently less secure and more cumbersome, because you can't burn device fuses by USB.
- Connect a naive Precursor to the Pi via USB.
- Run the
restore-usb.py
script. - Enter your BIP-39 key list directly on the Pi console (there is no network connection!)
- The script will:
- Decrypt your root keys
- Inject them into the
soc_csr.bin
file - Burn the
xous.img
,soc_csr.bin
,loader.bin
, andbackup.pddb
to your device
- Reboot the device. You will have to use the paperclip hole on the lower right corner to force a SoC reload.
- In an abundance of caution, securely dispose of the microSD card. There are no intentional copies of your secret keys stored on it, but, we can't guarantee that.
- VERY IMPORTANT -- re-key your device. This will re-create a fresh BIP-39 key list, and re-encrypt your SoC to that key. If you fail to do this, your device will be encrypted to the "all zeroes" key, which is not secure.
Option 2: Restore by Pi HAT
- Connect a naive Precursor to the Pi via the Pi HAT.
- Run the
restore-hat.py
script. - Enter your BIP-39 key list directly on the Pi console (there is no network connection!)
- The script will:
- Decrypt your root keys
- Inject them into the
soc_csr.bin
file - Burn the
xous.img
,soc_csr.bin
,loader.bin
, andbackup.pddb
to your device - Re-encrypt
soc_csr.bin
to your BIP-39 master key - Set the AES-256 key via BBRAM on your SoC.
- Reboot the device. You will have to use the paperclip hole on the lower right corner to force a SoC reload.
- In an abundance of caution, securely dispose of the microSD card. There are no intentional copies of your secret keys stored on it, but, we can't guarantee that.
- At this point you may also elect to burn the AES-256 BBRAM key to eFuses on your device, so you don't have to worry about losing your data if you let the battery run down.
Note that in this flow, your BIP-39 key remains the same as before. We'll eventually introduce support for re-keying, so if a new key was desired this is a thing that could be accommodated.