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;
    }



Attachment: smime.p7s
Description: S/MIME cryptographic signature

-- 
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev

Reply via email to