Skip to content

Conversation

@sipa
Copy link
Member

@sipa sipa commented Apr 16, 2016

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.

src/random.cpp Outdated
Copy link
Member

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.

Copy link
Member Author

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.

@sipa sipa force-pushed the betterrng branch 2 times, most recently from cb5aede to 3a68c3a Compare April 16, 2016 11:08
@gmaxwell
Copy link
Contributor

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.

@kirkalx
Copy link
Contributor

kirkalx commented Apr 17, 2016

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
Copy link
Contributor

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, will fix.

Copy link
Member Author

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?

Copy link
Member

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.

Copy link
Member

@laanwj laanwj Apr 20, 2016

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.

Copy link
Contributor

@dcousens dcousens Apr 21, 2016

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?

Copy link
Member Author

@sipa sipa Apr 21, 2016 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@laanwj laanwj Apr 22, 2016

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.

@sipa
Copy link
Member Author

sipa commented Apr 23, 2016

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?

@kirkalx
Copy link
Contributor

kirkalx commented Apr 24, 2016

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...

@laanwj
Copy link
Member

laanwj commented Apr 25, 2016

Adding the ability to install an error handler seems reasonable, but doing it correctly would require locking primitives

Couldn't you just require that the error handler is set from initialization before use of any of the functions? (e.g. AppInit2).
You don't have to support the scenario where the error handler is changed while your function is being called.
For example http and httprpc also have setup that has to be done in a single-threaded fashion before the module is used.

In any case I'm fine with doing that in another PR.

should use of /dev/urandom be protected by a HAVE_URANDOM or similar? Or is support for it universal on supported non-Windows systems?

I think /dev/random is universal on UN*X, urandom is less common but most BSDs seem to have it, some only as a link to /dev/random.

@sipa
Copy link
Member Author

sipa commented Apr 25, 2016

On OSX /dev/urandom exists but does the same as /dev/random

@sipa
Copy link
Member Author

sipa commented May 5, 2016

Anything left to do here?

@gmaxwell
Copy link
Contributor

gmaxwell commented May 20, 2016

ACK (but someone should test on Windows).

@paveljanik
Copy link
Contributor

ACK ecc7110

Can't test on Windows though.

@paveljanik
Copy link
Contributor

RfM

@sipa
Copy link
Member Author

sipa commented May 24, 2016

@paveljanik ?

@paveljanik
Copy link
Contributor

paveljanik commented May 24, 2016

Ready for Merge

Hmm, but no testing yet on Windows.

@sipa
Copy link
Member Author

sipa commented May 28, 2016

Tested by compiling using depends/ for win64, and then running bitcoin-qt.exe on native Windows 7 64-bit, and typing getnewaddress few times in the debug console. The resulting addresses were all different.

@sipa sipa merged commit 628cf14 into bitcoin:master May 30, 2016
sipa added a commit that referenced this pull request May 30, 2016
628cf14 Don't use assert for catching randomness failures (Pieter Wuille)
fa2637a Always require OS randomness when generating secret keys (Pieter Wuille)
codablock pushed a commit to codablock/dash that referenced this pull request Dec 21, 2017
…et keys

628cf14 Don't use assert for catching randomness failures (Pieter Wuille)
fa2637a Always require OS randomness when generating secret keys (Pieter Wuille)
andvgal pushed a commit to energicryptocurrency/gen2-energi that referenced this pull request Jan 6, 2019
…et keys

628cf14 Don't use assert for catching randomness failures (Pieter Wuille)
fa2637a Always require OS randomness when generating secret keys (Pieter Wuille)
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants