On 15/04/2011 20:59, Eric Wong wrote:
> Hello,
> 
> I'm not very knowledgeable about OpenSSL internals, but it appears
> RAND_bytes() is seeded with the pid of each process, and since pids get
> recycled, it's possible for two processes sharing a common parent to get
> the same random sequence over time if the common parent used the PRNG.

The prerequisite would be, surely, that:

a) The common parent (or one of its ancestors) caused the PRNG to be
initialised, and

b) The common parent did not use the PRNG in between the offending fork()s.

> This could arguably be a bug in every program using fork() + RAND_*()
> and they could use pthread_atfork() to call RAND_cleanup(), but I think
> OpenSSL should deal with it internally to make life easier for
> application authors :)

Rather than calling RAND_cleanup(), it would suffice to perturn the
state, e.g., mix in something each time fork() is called - it could even
be a constant - or extract some randomness.

Not so sure about pthread_atfork() - that would require pthread, of
course, and so is not a universal fix.

> 
> I have a trivial test program to illustrate the issue.  It's been
> tested with 0.9.8e-12.el5_4.6 on CentOS and 0.9.8g-15+lenny11 and
> 1.0.0d-2 on Debian.
> 
> also downloadable here: http://yhbt.net/test_openssl_prng_fork.c
> -------------------------------- 8< ------------------------------
> /*
>  * test program to demonstrate recycled PIDs can cause the PRNG to
>  * generate the same byte sequence.  This should output 2 identical
>  * lines after running for a while.
>  */
> #include <sys/types.h>
> #include <sys/wait.h>
> #include <unistd.h>
> #include <stdio.h>
> #include <openssl/rand.h>
> 
> static void dump_random(void)
> {
>       int i;
>       unsigned char buf[4];
> 
>       RAND_bytes(buf, sizeof(buf));
>       printf("pid=%d ", getpid());
>       for (i = 0; i < sizeof(buf); i++)
>               printf("\\x%02x", buf[i]);
>       puts("");
> }
> 
> int main(void)
> {
>       pid_t pid, xpid;
> 
>       /* PRNG needs to be initialized in original process to reproduce */
>       RAND_bytes((unsigned char *)&pid, sizeof(pid));
> 
>       pid = fork();
>       if (pid == 0) {
>               dump_random();
>               return 0;
>       } else if (pid > 0) {
>               wait(NULL);
> 
>               do {
>                       xpid = fork();
>                       if (xpid == 0) {
>                               if (getpid() == pid)
>                                       dump_random();
>                               return 0;
>                       } else if (xpid > 0) {
>                               wait(NULL);
>                       } else {
>                               perror("fork");
>                       }
>               } while (pid != xpid);
>       } else {
>               perror("fork");
>               return 1;
>       }
> 
>       return 0;
> }


-- 
http://www.apache-ssl.org/ben.html           http://www.links.org/

"There is no limit to what a man can do or how far he can go if he
doesn't mind who gets the credit." - Robert Woodruff
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [email protected]

Reply via email to