Keep Your Pins Long, and Your Peace of Mind Intact
Keep Your Pins Long and Your Peace of Mind Intact
We’ve been talking to a friendly Bitcoin wallet hacker who goes by the name @LazyNinja. He has developed a partial proof-of-concept for a device that would try all possible PIN codes on a stolen Coldcard.
His approach is a MitM (Man in the Middle) between the chip used to store secrets on the Coldcard (the ATECC508A) and the main microprocessor. It requires cutting a trace on the PCB and inserting a circuit. He has not constructed a machine to press the buttons yet, so his demo is limited to his own finger-speed.
His approach would require stealing your Coldcard, cracking the case open and performing very detailed soldering work. It’s not something that could happen quickly either (more on that below).
The Coldcard Mk2 has hardware and firmware changes in place already address these concerns… along with the mechanical buttons everyone prefers.
Should I be worried?
Not if you used a decent PIN! His approach takes between 5 and 10 seconds per PIN attempt (these are his numbers and are unconfirmed). Although we allow very short PIN codes—even just four digits (2+2) for development—as explained in our documentation, best practice is using an eight digit PIN code (4+4), which is what we recommend. If your PIN has eight or more digits, you can stop reading now and go back to watching the BTC price. LazyNinja’s device is not a threat because it would take about 15 years to try all eight-digit combinations. (Even a six digit PIN—which again is not something we recommend—would take 60 days to crack.)
You also don’t need to worry unless your Coldcard has been stolen. We recommend keeping all your Bitcoin wallets secure in a safe and secure spot which is secure against physical theft.
But what went wrong?
Normally, when a person is attempting pin codes, we have a delay system that makes it impossible to try more than a few codes quickly. LazyNinja found a way around this which requires his hardware, a change in the PCB, and some code on another micro board.
Shortly after he disclosed the bug to us, we reworked the communication between the 508A and the main micro. There were a few code paths where we “trusted” the answer from the 508A. Those are the cases he is intercepting and changing. (Note that this only allows him to bypass the rate-limiting on PIN attempts, and it still doesn’t give him the secrets without first finding the right PIN.)
The Firmware Fix
We have made changes in our communication with the 508A so that we never trust any of the answers it gives back. An MitM on the bus will not be able to mislead the main micro (see below for more tech details).
These changes will be in bootrom version 1.1.0. Once a Coldcard leaves the factory, it’s impossible to change anything in the bootrom, and that’s important or else it would be possible to get a Coldcard to run unsigned firmware and generally become a trojan horse. As a result, the bootrom is not upgradable, ever.
You can view the code changes in
this diff on github.
The changes are on branch bl-hardening
for now, but will be merged onto
master shortly. The interesting changes are in stm32/bootloader/ae.c
and pins.c
.
Like the entire Coldcard firmware, the bootrom is open source, and we have a white paper which covers the technical details of how we use the 508A, and the PIN policies in general, available here.
Hardware Mitigation
We also have made it much more difficult to access the PCB trace that connects the 508A and main micro (which you need to do to be “in the middle”).
In the new Coldcard Mk2, the trace is hidden underneath both chips it connects. It is possible still to intercept it, but it will require removing the 508A from the board, and using a socket. Certainly that is still possbile to do, but please keep in mind that your attacker will be desoldering/resoldering a chip that has the funds in it. Any slip will secure your funds by the release of the magic smoke inside the chip.
The blue wire marked ONEWIRE will need to be intercepted on the Coldcard Mark 2. For reference, that trace is 0.15mm wide and it’s blue because it’s on the back of the board, under the main micro along that section.
(Aside: “SHOOT HERE” is an addition for those who want a specific aim point when destroying a Coldcard at 25 yards. It points to the 508A, but would also impact the main micro which is behind it.)
More Technical Details
How can we use a chip without trusting it, you might ask? That’s the great thing about the using the 508A as a secure element: smarter people than us have designed the chip’s protocol and we just need to use it right.
The old code would check a PIN by doing a CheckMac
operation.
This uploads a hash of the PIN to the 508A, and asks the chip to
verify it to unlock access to a secret. The command returns one
byte saying if it worked or not. (If it worked, then the secrets
inside the 508A are also available to reading at that point, meaning
the state of the 508A has changed.) That one byte response should
not be trusted since a MitM can change it, and we did trust it in
some cases. The secrets were not unlocked (because the state of the
508A is not actually changed by the MitM) but you’ve mislead the
main micro, and that’s what lead to inappropriately reseting the
PIN rate-limiting.
The new code uses the GenDig
(Generate Digest) command instead.
This takes the same inputs as a CheckMac
but instead of changing
the state of the 508A, it returns the 32-byte digest that the 508A
has calculated. A MitM can observe that digest, but it’s not practical
to fake it, because of it’s length and the fact that it’s a hash
of secrets held only in the 508A and main micro. (The hash itself
is not sensitive, because a nonce is mixed into it.)
We have also beefed up a number of other instances where the output of the 508A was trusted more than needed. Many of those cases don’t seem useful to an attacker, but we fixed them anyway.
Bootrom space is very limited (32k) so we did have to simplify some of the wonderful graphics in order to free space for the new code. There is also a new screen to show when we detect a MitM attack underway. It’s very basic because we don’t expect anyone to see it:
The full set of bootrom displays can be found here for the new version while the old version is here.
Thanks!
We’d like to thank LazyNinja for being responsible in his disclosure of this issue, and thank him for spending his own time investigating the security of the Coldcard and helping to protect the Bitcoin community.
He’s been a real pleasure to work with, so please give him all due credit!