Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use getrandom() in Linux instead of /dev/urandom #13

Open
oittaa opened this issue Jul 9, 2018 · 1 comment
Open

Use getrandom() in Linux instead of /dev/urandom #13

oittaa opened this issue Jul 9, 2018 · 1 comment

Comments

@oittaa
Copy link

oittaa commented Jul 9, 2018

Using getrandom() instead of opening /dev/urandom is the preferred way to get random bytes in modern Linux systems.

Something like the following could be used in src/random/random.c:

/********************************************************************************************
* Hardware-based random number generation function
*
* It uses /dev/urandom in Linux and CNG's BCryptGenRandom function in Windows
*********************************************************************************************/ 

#include "random.h"
#include <stdlib.h>
#if defined(__WINDOWS__)
    #include <windows.h>
    #include <bcrypt.h>
#elif defined(__LINUX__)
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/random.h>
    #include <errno.h>
    static int lock = -1;
    static int getrandom_works = 1;
#endif

#define passed 0 
#define failed 1


static __inline void delay(unsigned int count)
{
    while (count--) {}
}


int randombytes(unsigned char* random_array, unsigned long long nbytes)
{ // Generation of "nbytes" of random values
    
#if defined(__WINDOWS__)   
    if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, random_array, (unsigned long)nbytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
        return failed;
    }

#elif defined(__LINUX__)
    int r, n = (int)nbytes, count = 0;
    
    if (getrandom_works == 1) {
        errno = 0;
        while (n > 0) {
            r = getrandom(random_array+count, n, 0);
            if (r < 0) {
                if (errno == EINTR) {
                    /* retry getrandom() if it was interrupted by a signal */
                    continue;
                }
                getrandom_works = 0;
                break;
            }
            count += r;
            n -= r;
        }
        if (n == 0) {
            return passed;
        }
    }

    if (lock == -1) {
        do {
            lock = open("/dev/urandom", O_RDONLY);
            if (lock == -1) {
                delay(0xFFFFF);
            }
        } while (lock == -1);
    }

    while (n > 0) {
        do {
            r = read(lock, random_array+count, n);
            if (r == -1) {
                delay(0xFFFF);
            }
        } while (r == -1);
        count += r;
        n -= r;
    }
#endif

    return passed;
}
oittaa added a commit to oittaa/PQCrypto-SIDH that referenced this issue Jul 10, 2018
@rdp
Copy link

rdp commented Nov 1, 2022

Was this faster?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants