[openssl-dev] Plea for a new public OpenSSL RNG API
Dr. Matthias St. Pierre
Matthias.St.Pierre at ncp-e.com
Wed Aug 30 05:54:45 UTC 2017
Hi Rich,
> I think the only way to do that in the DRBG model is to treat it as “additional input” and do a generate
> call. I think that would achieve the same effect, but it wouldn’t delay any possible seeding of randomness
> that the DRBG itself needs at some point.
You're right, well, almost. The implementation of drbg_add() (which implements RAND_add()) could be actually as simple as this little function:
static int drbg_add(const void *buf, int num, double randomness)
{
int ret = 0;
CRYPTO_THREAD_write_lock(rand_drbg.lock);
ret = RAND_DRBG_reseed(&rand_drbg, buf, num);
err:
CRYPTO_THREAD_unlock(rand_drbg.lock);
return ret;
}
The problem is that currently this would create a circular dependency, because now RAND_add() is involved both in pushing and in pulling entropy.
RAND_add() -> drbg_add() -> RAND_DRBG_reseed() -> get_entropy() -> get_entropy_from_system() -> RAND_poll_ex() -> RAND_add()
Using RAND_DRBG_generate() instead of RAND_DRBG_reseed() does not solve the problem, because the former can occasionally trigger a reseed. I already have the solution in my mind how to break up this vicious circle, but I need some time to write it down. Here is a sketch:
1) Use RAND_add() only for pushing to break the circular dependency
===================================================================
Add a new function rand_drbg_add() which is identical to RAND_DRBG_reseed(), except that it does not pull fresh entropy (and consequently does not reset the reseed_counter). Then the left hand side of the becomes
RAND_add() -> drbg_add() -> rand_drbg_add()
The code of drbg_add() and rand_drbg_add() is at the end of this mail. (This is the easy part :-) )
2) Reorganize the backend code for pulling entropy
==================================================
Reorganize get_entropy_from_system() in a way that it collects the entropy in the way it was originally intended, without calling RAND_add() and without using this evil fixed size 'rand_bytes' buffer, from which I tried to dissuade you ever since, Rich (no offence ;-) )
This part is more complicated, because one has to be careful not to break RAND_poll() for applications which don't use the default RAND_OpenSSL() method.
So please give me some time, I will try to turn my ideas into a PR.
Matthias
___
drbg_lib.c:
/*
* Mix in the specified data without reseeding |drbg|.
*
* Used by drbg_add() only.
*
* Similar to RAND_DRBG_reseed(), but there is no call to
* get_entropy() and the reseed_counter is not reset
*/
int rand_drbg_add(RAND_DRBG *drbg,
const unsigned char *adin, size_t adinlen)
{
if (drbg->state == DRBG_ERROR) {
RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_IN_ERROR_STATE);
return 0;
}
if (drbg->state == DRBG_UNINITIALISED) {
RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_NOT_INSTANTIATED);
return 0;
}
if (adin == NULL)
adinlen = 0;
else if (adinlen > drbg->max_adinlen) {
RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
return 0;
}
drbg->state = DRBG_ERROR;
if (!ctr_reseed(drbg, NULL, 0, adin, adinlen))
goto end;
drbg->state = DRBG_READY;
end:
if (drbg->state == DRBG_READY)
return 1;
return 0;
}
...
static int drbg_add(const void *buf, int num, double randomness)
{
int ret = 0;
CRYPTO_THREAD_write_lock(rand_drbg.lock);
ret = rand_drbg_add(&rand_drbg, buf, num);
err:
CRYPTO_THREAD_unlock(rand_drbg.lock);
return ret;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 4328 bytes
Desc: not available
URL: <http://mta.openssl.org/pipermail/openssl-dev/attachments/20170830/e08c190d/attachment.bin>
More information about the openssl-dev
mailing list