Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verification of firmware update #114

Open
matty279 opened this issue Jan 23, 2024 · 18 comments
Open

Verification of firmware update #114

matty279 opened this issue Jan 23, 2024 · 18 comments

Comments

@matty279
Copy link

I downloaded the latest Jade firmware update using the following Python script:

./jade_ota.py --download-firmware --hw-target jade1.1 --release stable --write-compressed

I managed to download the following files:

1.0.27_noradio_1118208_fw.bin
1.0.27_noradio_1118208_fw.bin.hash

Note that the download fails unless the “build” directory exists. I would suggest that the script create the “build” directory.

The SHA256 hash of “1.0.27_noradio_1118208_fw.bin” doesn’t match the contents of “1.0.27_noradio_1118208_fw.bin.hash”:

b2b67f5943ca4c1ae0c7fc3733352dbb4b644add5a174111547e5bd7f77d7171

image

Can you please clarify how to verify “1.0.27_noradio_1118208_fw.bin” and whether the hash itself can be separately verified?

@JamieDriver
Copy link
Collaborator

JamieDriver commented Jan 24, 2024

./jade_ota.py is really more of an internal script used during automated testing than a script intended for users - you may find ./update_jade_fw.py more user-friendly - it looks at the plugged jade to determine the 'hw_target' (uploading the wrong 'target' to hw is not recommended - it should be harmless and produce an 'INVALID_FW' error, but it's not something we test (all possible combinations of) on a regular basis!).

Of course you are free to use jade_ota.py as you show above (* see below). I suppose it has the upper hand if you decidedly don't want to plug the jade in to an internet-connected machine, but yes, it may make some assumptions as it was written to run as part of the automated CI process.

That said, I'll take your suggestion on board and tweak it to create the build dir if not present, thanks.

NOTE: (*) again because of its history/intended use, the script assumes it should upload the fw to jade by default. If you also pass '--skipserial --skipble' it will just save the fw locally and not try to upload/update jade.

@JamieDriver
Copy link
Collaborator

JamieDriver commented Jan 24, 2024

Ok, to answer your actual question ;-) :

1.0.27_noradio_1118208_fw.bin
1.0.27_noradio_1118208_fw.bin.hash

The former is a compressed 'full' firmware image binary - ie. the entirety of the '1.0.27 noradio' fw.
The latter contains the hash of the uncompressed final firmware image - ie. the hash of the '1.0.27 noradio' fw that jade will boot/run.
( NOTE: We also offer 'from fwA to fwB' delta/diff patches - in this case the .hash file would have the hash of the final
fw jade will run - so eg. 'anything-to-1.0.27-noradio' would all have the same .hash file - the hash of the '1.0.27 noradio' fw that jade will boot/run after the diff has been applied to existing/running fw.)

Should you run the jade_ota.py script again to upload the firmware to Jade (./jade_ota.py --fwfile build/1.0.27_noradio_1118208_fw.bin) the script will read that .hash file and pass the hash to Jade before it uploads any firmware - you should see it on screen when confirming the upgrade.

If you go ahead, the compressed firmware (or delta patch) is uploaded to Jade. When complete, Jade checks the hash of the final firmware image it now has ready to boot matches that uploaded/inspected/confirmed by you (if mismatch, the fw is discarded and not finalised for booting).

If you have downloaded a full firmware image, such as you have above, you can uncompress it and check the hash matches that in the file (ofc this doesn't work for deltas, which need to be applied to a base as well as being uncompressed).
eg:

cp build/1.0.27_noradio_1118208_fw.bin ./1.0.27_noradio_fw_image.gz
pigz -z -d ./1.0.27_noradio_fw_image.gz
sha256sum ./1.0.27_noradio_fw_image

(because of the compression used, I don't think normal 'gzip -d' works ... although pigz wants the file suffixed .gz ... odd ... might depend on your version of gzip, might need additional arguments, not sure ...)

At that point the sha should match (and uncomp[ressed file size should be that in the original filename - in this case 1118208).

We (Blockstream) really ought to provide a signed file of fw hashes, or secure web page with them listed, or something similar. This is something we are aware of.

NOTE: a firmware image won't update/boot/run on an official Jade device unless it has been signed by Blockstream.

@JamieDriver
Copy link
Collaborator

Also, if you want to go the whole hog, and verify that the fw image you have download indeed corresponds to the source code in this repo at the 1.0.27 tag - see REPRODUCIBLE.md

@matty279
Copy link
Author

Thanks Jamie that was very helpful. I had difficulties executing these scripts on Windows but they ran successfully on Mac OS and I was able to download the firmware upgrade files and verify the hash.

I executed the following command to upgrade the firmware :

python3 ./jade_ota.py --fwfile build/1.0.27_noradio_1118208_fw.bin

However, the following exception was thrown:

File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/subprocess.py", line 1026, in init
self._execute_child(args, executable, preexec_fn, close_fds,
File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/subprocess.py", line 1950, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: '/usr/bin/bt-agent'

I tried to manually create the directory '/usr/bin/bt-agent' in the root of the cloned repository and execute the script again but this was unsuccessful.

Also, can you please confirm whether the Jade must be unlocked to execute a firmware upgrade?

@matty279 matty279 reopened this Jan 24, 2024
@matty279
Copy link
Author

I inadvertently closed the ticket...

@JamieDriver
Copy link
Collaborator

JamieDriver commented Jan 24, 2024

Ahh sorry, try: ./jade_ota.py --no-ble --fwfile build/1.0.27_noradio_1118208_fw.bin

An uninitialised Jade does not need to be unlocked - ota upgrade can just run.

If the jade is initialised with a PIN-protected wallet, it will need to be unlocked with pin first - but the jade_ota.py script should handle that ...

@matty279
Copy link
Author

I executed the following script:

./jade_ota.py --no-ble --fwfile build/1.0.27_noradio_1118208_fw.bin

The following exception was thrown:

jade_ota.py: error: unrecognized arguments: --no-ble

@JamieDriver
Copy link
Collaborator

--skipble - third time lucky ... 🤞

NOTE: ./jade_ota.py --help to get all the options/arguments etc.

@matty279
Copy link
Author

I disconnected my Mac from the network, connected the Jade and executed the following script:

./jade_ota.py --skipble --fwfile build/1.0.27_noradio_1118208_fw.bin

This invoked the Jade which displayed the following screen:

image

I entered the PIN and the following displayed:

image

Clicking on "Yes" just looped back to the same error.

I then entered QR mode, performed a blind oracle PIN unlock and then executed the script again and the same sequence repeated with the following displaying on the Jade:

image

As you previously indicated:

"If the jade is initialised with a PIN-protected wallet, it will need to be unlocked with pin first - but the jade_ota.py script should handle that ..."

Unlocking the Jade before executing the script did not resolve the issue.

What is the process of the script unlocking the Jade?

@JamieDriver
Copy link
Collaborator

As it says, that first error suggests networking errors - ie. it cannot reach the blind oracle to unlock the wallet.
If you have a Jade with a PIN-protected wallet, you must usually unlock it to use it - this involves a network roundtrip. I assume this usually works ?

If you have a Jade with a PIN-protected wallet, you cannot update the firmware without first entering the PIN and unlocking the wallet (otherwise an attacker could temporarily take your jade, upload malicious firmware, and put it back where they found it ...).

If you unlock Jade using QR codes this is only unlocked for 'QR - mode' - ie you cannot send it data over USB.
(Similarly, if you unlock using USB, you (or an attacker) can't start sending it messages over Bluetooth.) So if you unlock with QRs, then try to send firmware over USB, it will still be asking you to unlock over USB (again, to verify it is you sending those messages/trying to upload fw).

tl;dr:
Jade can operate in a 'connected' fashion, where it encrypts your wallet data in flash, and needs a PIN (and a handshake with a remote blind oracle server (*)) to unlock, or it can operate in a totally stateless/disconnected fashion where you scan a QR code you keep (containing the wallet seed data) every time you want to use it. (Different people view the security risks of each model differently/have different perspectives on the tradeoffs/prefer one or the other ...)

However, while you can 'mix and match' to some degree, once you've opted for PIN-protection several features will require the PIN to be entered correctly before they are allowed to run. Specifically, in the PIN-protected model you must unlock with PIN before you can update the firmware.

NOTE (*): by default Jade will use a blind oracle server hosted by Blockstream, but you can if you prefer run your own server - see https://help.blockstream.com/hc/en-us/articles/12800132096793-Set-up-a-personal-blind-oracle

@matty279
Copy link
Author

I have only used the QR PIN unlock method to date so I am unfamiliar with other mechanisms of unlocking the Jade. If "Unlock Jade" is selected, a message displays "Connect via USB/BLE to a companion app and select your Jade to unlock with your PIN".

Can any of the companion apps listed in the following article be used to unlock the Jade with its PIN or does this require the Blockstream Green app?

https://help.blockstream.com/hc/en-us/articles/9601453403801-Download-a-companion-app-for-Jade

@JamieDriver
Copy link
Collaborator

Ah ok, so you usually use QR unlock - cool beans. Aside: You'll be pleased to know that in the next release we plan to improve that to only being one QR scan each way (rather than the existing two-each-way) - ie webapp scans jade, jade scans webapp, done. And the QR codes will be fewer frames each, so all in all should be much easier/quicker than it is today.

Ok, the ota script will handle the pin-unlocking of Jade - I don't understand why you are getting these network errors - I assume you could reach the network in order to download the firmware in the first place ?
Have you deliberately disconnected the machine from the internet ?
Can you ping jadefw.blockstream.com ? That's the site that hosts the firmware images. What about ping jadepin.blockstream.com ? That's the pin blind oracle server. Or are you already using a bespoke server ?

While any Green app (or Sparrow, Specter, Electrum, HWI ...) can unlock Jade, they will all need access to the internet and be able to reach the blind oracle. But you don't need them, the ota script should be able to do it itself.

Or try ./jade_auth.py ... or ./update_jade_fw.py (even if you abandon any update).

In any case, if you disconnect Jade from the USB, it will lock itself again (again, to prevent an attacker grabbing it from your machine and plugging it into their own and using it). So you need to unlock jade on the same machine you are going to use to upgrade it.

The issue here is those network errors when you try to unlock.

@matty279
Copy link
Author

Thanks for the update on QR unlock. That is a good improvement.

I have deliberately disconnected the machine from the internet. What I am trying to achieve is to upgrade Jade's firmware without connecting it to an internet connected device. I have succeeded to download an offline copy of the latest firmware. The next challenge is how to unlock the Jade and install the offline firmware onto it without connecting the machine to the internet and without factory resetting the Jade.

@JamieDriver
Copy link
Collaborator

It is not possible to unlock a PIN-protected Jade wallet without connecting to the blind oracle server - in theory you could run your own server and plug Jade physically into that machine (or at least into the same LAN) to do the fw upgrade (telling jade it's blind oracle was at a 'localhost' url). [ But this would involve resetting the wallet on Jade, as you can't move from one blind oracle server to another without re-creating the wallet (so it persists the oracle secret to the new oracle). ]
(and ofc your blind oracle server needs to be reachable from wherever you plan to use Jade - eg if you ran your oracle at home without any bridge/nat/routes from the outside, your Jade would only be 'unlockable' from your house/LAN ...)

If you do not want Jade connected to the machine at the same time that the machine is connected to the internet, but at the same time use a PIN-(and hence remote-server)-protected wallet ... you're a bit stuck re: fw updates atm I'm afraid.
You need the internet to unlock the Jade, but you don't want the internet connected (as you view it as a security risk?)

In a future version of the hw, we plan to to able to use SD-cards and other USB storage devices for fw updates (and psbt signing etc), which should satisfy your use-case. But I'm afraid that won't be workable on the existing hw.

(We have also considered transferring the fw via QRs - but it will take a very long time to transfer across and it has yet to be decided whether it's practically viable).

In the interim, you could:
Connect the machine to the internet

  • Download the firmware
  • Do your hash/source-code etc verification of the fw
  • Connect Jade and unlock it (using jade_auth.py)

Disconnect the machine from the internet

  • Update jade using jade_ota.py or update_jade_fw.py

OR (assuming you have an easily-scanned qr code backup of your seed data, or don't mind typing the words again...)

  • enter the wrong PIN 3 times - this wipes the wallet
  • fw update should then work without requiring unlock
  • re-initialise jade/wallet

I know, both of these options are what you would rather avoid ...

Atm we deliberately disallow unlocking with QRs and then going ahead and accepting messages over USB, as (most?) QR users want to be reassured that if they unlock via QR, the only way to meaningfully interact with Jade is via QRs.

@matty279
Copy link
Author

The absolute best (air-gapped) practice is for the hardware wallet to never connect to an internet connected device. Coldcard supports this using a micro SD card and a verifiable firmware update file downloaded from their website. I think this is the best way to achieve air-gapped firmware updates. With updating Jade's firmware, I might need to either just connect to an internet connected device, perform a factory reset or wait for future developments. Another workaround might be to block all internet traffic but allow access to required sites while the Jade is connected for the firmware update.

Is it just jadefw.blockstream.com and jadepin.blockstream.com for which access is required for unlocking and updating firmware via the Blockstream Green app?

Thank you for the detailed information. It has been very helpful and is appreciated.

@JamieDriver
Copy link
Collaborator

JamieDriver commented Jan 26, 2024

Agree with you re: 'best practice' and as I say we are looking at the usb-storage (eg. micro-sd reader) for the next iteration of the hw.
atm the only way to acheive what you are after is to use jade in totally stateless 'QR mode' where the seed info is not kept in jade flash but on a paper or metal sheet (eg in the form of a CompactSeedQR) which is entered/scanned every time you want to use the hww. (But ofc has the disadvantage that you then have your [unencrypted] seed on a bit of paper ...).
But yes, we are aware of these challenges.

Is it just jadefw.blockstream.com and jadepin.blockstream.com for which access is required for unlocking and updating firmware via the Blockstream Green app?

jadefw.blockstream.com - firmware images hosted here
jadepin.blockstream.com - the default Blockstream-hosted blind oracle

These should be all that is required.

NOTE: the reason we use a remote blind oracle to assist in decrypting the wallet, is that jade has no 'secure element' hw on board. The reason jade has no 'secure element' on board, is that these use 'closed source' software, and we are committed to keeping jade based on open source libraries. It's all about the tradeoffs .. 🙃

@matty279
Copy link
Author

matty279 commented Jan 26, 2024

In the end I decided to factory reset my Jades, upgrade firmware using Blockstream Green and restore.

I understand the importance of supporting open source Bitcoin only projects. I found out about Jade from the following YouTube channel that promotes Jade and Coldcard as the premier (Bitcoin) hardware wallets:

https://www.youtube.com/@Bitcoin_University

I'll be happy to upgrade my Jade hardware as new features such as support for SD cards is released. Keep up the good work.

@JamieDriver
Copy link
Collaborator

Many thanks for your comments and the useful discussion! 🚀

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

No branches or pull requests

2 participants