[openssl-project] Entropy seeding the DRBG

Dr. Matthias St. Pierre Matthias.St.Pierre at ncp-e.com
Wed Apr 4 00:29:31 UTC 2018

Since both pull requests mentioned by Richard were reviewed and approved
by me, I would to add a few remarks on those two pull requests:

Ad #5401:  Switch the DRBGs from AES-128-CTR to AES-256-CTR

> The requirement change from 128 to 256 happened with this commit:
>     commit 32bda2b2e4900308cb025020d8c8692e1d3c2ba9
>     Author: Kurt Roeckx <kurt at roeckx.be>
>     Date:   Sun Feb 18 19:16:13 2018 +0100
>         Switch the DRBGs from AES-128-CTR to AES-256-CTR
>         Reviewed-by: Dr. Matthias St. Pierre
<Matthias.St.Pierre at ncp-e.com>
>         GH: #5401

At first I was reluctant whether this increase was really necessary,
because AFAIK a security level of 128 bit is still considered sufficient
for most use cases. But Kurt argumented that OpenSSL supports encryption
algorithms with a security level of 256 bit in TLS (like AES-256-CTR),
so it is necessary that the random generator provides this level of
security. This sounded reasonable and after checking that the Linux
Random Number Generator was seeded with 256 bits of entropy
<http://www.chronox.de/lrng/doc/lrng.html>, I followed his arguments.

My original intention was to have the security strength configurable
with an option like --with-rand-strength=[128,192,256]. One could even
have chosen different defaults for different platforms. But this
approach was in conflict with Kurts argument above, stating that TLS
can't support 256 bit encryption algorithms if the underlying random
generator does not support this security level. So my TODO was dropped
in the above commit, see

IMHO there is no alternative to commit
32bda2b2e4900308cb025020d8c8692e1d3c2ba9, unless we say we only support
128 bit encryption algorithms.

Ad #5503:  Make sure we use a nonce when a nonce is required

> And then there's this one, which did the added 50%:
>     commit 2a70d65b99e1f2376be705d18bca88703b7e774a
>     Author:     Kurt Roeckx <kurt at roeckx.be>
>     AuthorDate: Sat Mar 3 23:19:03 2018 +0100
>     Commit:     Kurt Roeckx <kurt at roeckx.be>
>     CommitDate: Sun Apr 1 21:11:26 2018 +0200
>         Make sure we use a nonce when a nonce is required
>         If a nonce is required and the get_nonce callback is NULL,
request 50%
>         more entropy following NIST SP800-90Ar1 section 9.1.
>         Reviewed-by: Dr. Matthias St. Pierre
<Matthias.St.Pierre at ncp-e.com>
>         GH: #5503

This pull request started initially when Kurt noticed that the NIST
standard requires the use of a nonce during instantiation, when a
derivation function is used, and that we were not providing
get_nonce()/cleanup_nonce() callbacks ourselves 

The use of the nonce is mandated by section of Nist SP 800-90Ar1:

> Instantiation When a Derivation Function is Used
>    When instantiation is performed using this method, the entropy
input may or may not have full entropy; in either case, a nonce is required

In Section 8.6.7 verious methods to obtain a nonce are discussed, see
also <https://github.com/openssl/openssl/pull/5503#issuecomment-371960392>:

>    8.6.7 Nonce
>    A nonce may be required in the construction of a seed during
instantiation in order to provide a security cushion to block certain
attacks. The nonce shall be either:
>      a. A value with at least (security_strength/2) bits of entropy, or
>      b. A value that is expected to repeat no more often than a
(security_strength/2)-bit random string would be expected to repeat.
>    A nonce may be composed of one (or more) of the following
components (other components may also be appropriate):
>    1. A random value that is generated anew for each nonce, using an
approved random bit generator.
>    2. A timestamp of sufficient resolution (detail) so that it is
different each time it is used.
>    3. A monotonically increasing sequence number, or
>    4. A combination of a timestamp and a monotonically increasing
sequence number, such that the sequence number is reset when and only
when the timestamp changes. For example, a timestamp may show the date
but not the time of day, so a sequence number is appended that will not
repeat during a particular day.
> For case 1 above, the random value could be acquired from the same
source and at the same time as the entropy input. In this case, the seed
could be considered to be constructed from an “extra strong” entropy
input and the optional personalization string, where the entropy for the
entropy input is equal to or greater than (3/2 security_strength) bits.

I argued for using variant 4
while Kurt favoured variant 1
And he is still convinced that variant 1 is the best solution:

Am 03.04.2018 um 18:54 schrieb Kurt Roeckx:
> There is an alternative to that 50% extra, but it's not making sense
to me.

Contrary, to Kurt, I believe that the other variants are preferrable to
variant 1, because they are not so wasteful regarding entropy
requirements. So my proposal would be to implement the required
get_entropy()/cleanup_entropy() callbacks explicitely and go for variant
4. This would mean that not more than the minimum 256 bit of entropy is
needed. In theory solution 4 sounds simple: use a combination of a 64
bit timestamp and a 64 bit atomic counter as the 128 bit nonce. I say
"in theory", because I think of what a struggle we had with 64 bit
timers in https://github.com/openssl/openssl/pull/4757.

Somebody might argue that variant 3 is much simpler to implement. But as
far as I understood it, the nonce must be unique over all instantiations
accross multiple application instances. (I wouldn't be unhappy if
someone would prove me wrong here.)

Given the final beta stadium of 1.1.1, it is maybe the best solution for
the moment to revert pull request #5503 for 1.1.1 (i.e. don't care about
the nonce) and redo it correctly for the FIPS evaluation (post-1.1.1
resp. 1.2). As Rich already said multiple times: the random generator we
have now is much better already than anything we had before.


TL;DR:  Here's the summary:

  - leave pull request #5401 as it is for release 1.1.1  (or state that
we only support 128 bit encryption)
  - repair pull request #5503, or better revert it for 1.1.1 and
reimplement it correctly for post-1.1.1 resp. 1.2

More information about the openssl-project mailing list