[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