In the previous article, we demonstrated that the buttons on a BWallet are indeed wired differently than on a Trezor.
This means that loading a signed Trezor firmware onto a BWallet isnt very useful. The 'unofficial firmware' warning pops up and the buttons do not work.
Perhaps the 'next best thing' would be to use the Trezor source code, modify only the lines to map the CPU pins to the buttons on the BWallet and compile ourselves.
So let's test it!
The lines to modify are in buttons.h:
-#define BTN_PIN_YES GPIO2
-#define BTN_PIN_NO GPIO5
+#define BTN_PIN_YES GPIO10
+#define BTN_PIN_NO GPIO12
Then compile as normal.
This creates the firmware image, but what gets flashed to the device requires a header on top that contains some metadata, including the signatures. Because we have no way of creating signatures that either a BWallet bootloader nor a Trezor bootloader would validate, we can steal the header from a firmware that Trezor distributes.
Here's a terrible python script that does just that (and breaks out the header fields for no good reason):
with open(sys.argv, 'r') as f:
data = f.read()
header = data[:256]
firmware = data[256:]
assert len(header) + len(firmware) == len(data)
(magic, codelen, idx1, idx2, idx3, flags, reserved, sig1, sig2, sig3) = struct.unpack("4sissss52s64s64s64s", header)
print "magic =\t%s" % binascii.hexlify(magic)
print "codelen =\t%s" % codelen
print "idx1 =\t%s" % binascii.hexlify(idx1)
print "idx2 =\t%s" % binascii.hexlify(idx2)
print "idx3 =\t%s" % binascii.hexlify(idx3)
print "flags =\t%s" % binascii.hexlify(flags)
print "rsvd =\t%s" % binascii.hexlify(reserved)
print "sig1 =\t%s" % binascii.hexlify(sig1)
print "sig2 =\t%s" % binascii.hexlify(sig2)
print "sig3 =\t%s" % binascii.hexlify(sig3)
with open("bzor.bin", "rb") as g:
payload = g.read()
with open("bzorwithheader.bin", "wb") as h:
h.write(header + payload)
passing in a valid trezor firmware:
$ python fwheaderswap.py trezor-1.2.1.bin
I should probably have fixed the magic bytes right in the script, but I did this separately like I did in the last post.
This yields this firmware that behaves exactly like a Trezor, but on a BWallet. Let's test the buttons:
$ python cmdtr.py get_entropy 32
<clicks the button>
And the buttons work!
This BWallet-Trezor hybrid will alert on boot that the firmware is 'unofficial' because the signature in the header was not created by a BWallet developer on the firmware we are running. Instead, I pulled the code directly from the Trezor repo, made a trivial change to support the BWallet button mappings, and compiled it myself.
It is true that when it boots up and warns that the firmware is not official, I have no way of telling if its running my compiled firmware, or if an evil hacker made modifications to my BWallet when I wasnt looking.
My solution? I won't leave my BWallet in a place where an evil hacker can get to it.
Also, I'm aware of this risk and will make informed, conscious decisions about how I use it.
Feel free to use the firmware above for yourself. But be aware that if you do choose to use it, you are trusting that I'm not an evil hacker :) I provide no warranty, guarantee, or promises about what will or won't happen if you choose to use it.
I recommend you follow the steps above and compile your own BWallet-compatable Trezor firmware.
blah blah, consider donating for more hardware wallet analysis: 1Adq8SP8WBWJGHyq8N3bGty8n1m9A3ms81