-
Notifications
You must be signed in to change notification settings - Fork 38.6k
Always require OS randomness when generating secret keys #7891
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
Conversation
src/random.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look safe without a retry. read() doesn't guarantee the entire buffer gets filled ever, afaik.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe there are some guarantees for reading from /dev/urandom always providing at least up to some number of bytes when requested, but it's better to be safe. I've replaced it with a loop.
cb5aede to
3a68c3a
Compare
|
meta-concept-ack. A reasonable separation of concerns in the migration off of openssl is time of use addition of OS entropy, a replacement CSPRNG, and replacement seeding. Each of these can be done independently Taking OS entropy at time of use for long term keys is a basic, sensible thing to do and protects users against flaws in the either the OS rng or the process CSPRNG. The specific combiner used here seems reasonable to me. |
|
Concept ACK. Minor point though: should use of /dev/urandom be protected by a HAVE_URANDOM or similar? Or is support for it universal on supported non-Windows systems? |
src/random.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be doing something stronger than assert here. If the code is compiled with assertions disabled, this code would be incorrect. Assertions should be used for invariants, not error handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, will fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... abort() or raise a C++ exception or depend on ui_interface.h (yuck) to call ThreadSafeMessageBox?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's not really a good way to do a global abort at the moment from this place.
AbortNode() is the closest, it shows a message and does a more graceful shutdown, but that would introduce a dependency on main.cpp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid the main dependency, and if you want to structure this as a library, maybe add a function to register a fatal error handler? (which we would point to AbortNode, then raise an exception to kill the current thread). It could still call abort() if nothing registered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Raise an exception is the most appropriate action here.
If it isn't thorough enough, maybe catch it at a higher level and then call AbortNode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exceptions should be for reasonably-normal problems which the application could, in principle, handle (it may still AbortNode of them, obviously). This is not one of them.
Really this is more territory for a fatal error handler routine.
|
Added a commit that uses LogPrintf + abort() in case of randomness failure. Adding the ability to install an error handler seems reasonable, but doing it correctly would require locking primitives~~, which would cause libconsensus to end up depending on boost again~~. After the C++11 switchover this will be much easier, and I'd prefer to do that in a separate PR then. EDIT: I'm wrong, libconsensus does not depend on random. Still, can we keep error handling for another PR? |
|
Perhaps RandFailure() could take a reason param (which would cover my concern above about relying on /dev/urandom to be present), but as you say, error handling for another PR... |
Couldn't you just require that the error handler is set from initialization before use of any of the functions? (e.g. AppInit2). In any case I'm fine with doing that in another PR.
I think |
|
On OSX /dev/urandom exists but does the same as /dev/random |
|
Anything left to do here? |
|
ACK (but someone should test on Windows). |
|
ACK ecc7110 Can't test on Windows though. |
|
RfM |
|
Ready for Merge Hmm, but no testing yet on Windows. |
|
Tested by compiling using depends/ for win64, and then running bitcoin-qt.exe on native Windows 7 64-bit, and typing |
With concerns about OpenSSL's RNG increasing, we should just always require OS randomness in addition to our normal randomness source when generating keys. This is an infrequent operation (especially since signing was switched to using deterministic nonces), so this should not hurt performance at all.
In addition, get rid of the random calls to RandAddPerfMonData, which were generally correlated with places where keys or signatures were generated. Better just do it whenever we actually need that kind of assurance.
This does add a dependency from random on crypto, which makes bitcoin-cli now link in crypto. That's unfortunate, and the randomness utilities should probably moved to a different lib, but I'm not doing that now.