[openssl-dev] [openssl.org #4055] FIPS Object Module User Guide corrections needed for (*get_entropy)()

Steve Marquess marquess at openssl.com
Thu Oct 1 17:05:56 UTC 2015


On 09/21/2015 08:00 PM, Gibbons, Lee D via RT wrote:
> This is to highlight a bug in the FIPS Object Module 2.10 and corrective documentation in its User Guide.
> 
> The User Guide for the FIPS Object Module 2.10 describes the (*get_entropy)() callback:
> 
>                 size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char **pout,
>            int entropy, size_t min_len, size_t max_len)
> 
>                 "A call to this function requests entropy bits of entropy in a buffer of between min_len and
>                 max_len size bytes inclusive. The values of these are mechanism specific and taken from
>                 SP800-90 tables. This callback should then return the amount of data in the buffer *pout and the
>                 length in the return value, or zero in case of being unable to retrieve sufficient entropy."
> 
> The caller of (*get_entropy)() is the static function fips_get_entropy(). Notice how it constructs the <entropy> value, which should be in bits:
> 
>      rv = dctx->get_entropy(dctx, &tout, entropy + bl,
>                 min_len + bl, max_len + bl);
>      *pout = tout + bl;
>      if (rv < (min_len + bl) || (rv % bl))
>            return 0;
> 
> The "entropy + bl" expression is mixing types, adding bits and bytes together. Anyone defining a (*get_entropy)() callback had better ignore the <entropy> parameter. What's more, the callback had better return <min_len> rounded up to a dctx->entropy_blocklen boundary or face failure. The User Guide mentions none of this.
> 
> I realize the FIPS Object Module is frozen. The documentation should be corrected to expose the real restrictions on the callback.

Doug, it took awhile to respond to this because I had to check with one
of my smarter colleagues (Steve Henson in this case). He confirms the
bug, which fortunately is easy to work around and only matters when an
application supplies external entropy callbacks (which few will).
Documenting it coherently is another matter.

Entropy is a bit of a mess in FIPS 140-2 due to the mandated continuous
PRNG test which is completely useless and it very clearly doesn't fit
properly with the new DRBGs and especially not entropy sources. For the
#1747 validation we specifically asked if it was required were told said
yes.

The poor fit with entropy sources is that it's perfectly legal for an
entropy source to provide the entropy in a non-uniform way. Say 256
bits of entropy at the start of a large buffer and the rest nothing (but
not all zeroes!). If the input to the PRNG test is supplied as a big
buffer like that the DRBG continuous test will compare the first block
against the rest and then discard the first block which might remove a
disproportionate amount of entropy. So after pondering a bit I came up
with the following new text for section 6.1.1 of the User Guide. Any
errors of omission or commission are mine, not Steve's:

----(addition to Section 6.1.1)

Few applications provide external entropy callbacks, but due to a bug in
the callback code those that do define a (*get_entropy)() callback
should have that return at least two full "blocks" of entropy. This is
because the FIPS 140-2 mandated continuous PRNG test has to be applied
to the entropy source. It has to compare consecutive blocks (discarding
the first) which means the entropy source needs to supply a multiple of
the block size.  The solution isn't obvious so a detailed discusson follows.

FIPS_drbg_get_strength() returns the strength of the DRBG context which
is the number of bits of entropy needed to seed the DRBG without the
continuous PRNG test. When an application adds its own entropy callbacks
it has to tell the FIPS module what the block length of the entropy
source is.

So arguably the entropy parameter with the continuous PRNG test is:

    FIPS_drbg_get_strength(dctx) + block_length * 8

But, that calculation determines a maximum value and an entropy source
could conceivably supply less. For instance, suppose we want 256 bits of
entropy and the callback supplies it as high grade entropy uniformly in
a 32 byte buffer (the absolute minimum) and has a 16 byte block length.
An extra block is needed for the PRNG test so we should supply a 48 byte
buffer (three blocks) and effectively 384 bits of entropy.

Now suppose we have a low grade entropy source which provides just 1 bit
of entropy per byte. Again assume it is uniform (e.g. we don't get 8
bits of entropy in byte 1 and nothing in the next 7). Again lets have a
block size of 16 bytes.  This time to get 256 bits of entropy the source
must provides it in a 256 byte buffer. An extra block is required which
makes 272 bytes but because we only have 1 bit of entropy per byte it
just needs to supply 272 bits of entropy.

----

-Steve M.

-- 
Steve Marquess
OpenSSL Software Foundation, Inc.
1829 Mount Ephraim Road
Adamstown, MD  21710
USA
+1 877 673 6775 s/b
+1 301 874 2571 direct
marquess at opensslfoundation.com
marquess at openssl.com
gpg/pgp key: http://openssl.com/docs/0x6D1892F5.asc


More information about the openssl-dev mailing list