Cybernetic Entomology: Mismatch of purpose and requirement in libraries
Case Study: Bitcoin and OpenSSL
February, 2014: Because OpenSSL’s purpose was different from Bitcoin’s requirement, a change which was a bugfix in the context of OpenSSL created a new bug for Bitcoin.
Bitcoin was using OpenSSL to check the validity of encrypted blocks already in its blockchain – blocks that had been transmitted and accepted months or even years previously. OpenSSL’s purpose is in securing communications today, this hour, this minute.
When encrypted data can appear in any of multiple possible formats, it can lead to different cryptographic hashes or signatures for the “same” data. This weakens some protocols because it can lead to leaking information, transmitting things redundantly, or letting an attacker see the same payload encrypted by closely-related keys, etc.
OpenSSL’s maintainers responded to a perceived possible vulnerability that allowed things to appear in any of multiple formats by first issuing a version of OpenSSL that would only produce a single format, then followed it up 2 months or so later with a version of OpenSSL that would reject all other formats as incorrect. This is in accord with OpenSSL’s purpose, fixed bugs in some other protocols, and made it easier to avoid bugs while writing new protocols with OpenSSL. But it introduced a bug for the Bitcoin protocol.
There were blocks in the Bitcoin blockchain, that had been accepted as part of the distributed consensus history months or even years previously, which used one or more of those other formats. This caused Bitcoin clients linked against the new version of the OpenSSL library to reject the first such block and the entirety of the consensus blockchain that followed it. These clients were therefore ignorant of all entries into Bitcoin’s public ledger later than that block. Although no such attack actually took place, they were vulnerable to double-spending fraud because they could have been tricked into accepting new blocks that directly contradicted the accepted consensus.
Checklist questions:
- Bird’s Eye: For each external library your program uses, does its purpose exactly match the requirement that you are using it for? If not, then the possibility of future changes to or bugfixes in that library is a risk to your software.
- Treetop: Is there any external library you’re using, whose bugs or misfeatures your software relies on for its correctness? Every such library represents a near-certainty of eventual failure due to a bug fix in it.
- Snail’s Eye: Are you using an external library intended to check the format of data in transit to (also or instead) check the format of static or historical data? If such an external library continues to be maintained, a future change in that library WILL eventually break your application. If the external library does not continue to be maintained, then you will have to replace it anyway.