예제 #1
0
파일: random.c 프로젝트: Hamper/LineIRCd
/*
 * init_random, written by Syzop.
 * This function tries to initialize the arc4 random number generator securely.
 */
void init_random()
{
struct {
#ifdef USE_SSL
	char egd[32];			/* from EGD */
#endif
#ifndef _WIN32
	struct timeval nowt;	/* time */
	char rnd[32];			/* /dev/urandom */
#else
	MEMORYSTATUS mstat;		/* memory status */
	struct _timeb nowt;		/* time */
#endif
} rdat;

unsigned int seed, egd = 0;
time_t now = TStime();
int n;

#ifndef _WIN32
struct timeval nowt;
int fd;
#else
MEMORYSTATUS mstat;
struct _timeb nowt;
#endif

	arc4_init();

	/* Grab non-OS specific "random" data */
#ifdef USE_SSL
 #if OPENSSL_VERSION_NUMBER >= 0x000907000
	if (EGD_PATH) {
		n = RAND_query_egd_bytes(EGD_PATH, rdat.egd, sizeof(rdat.egd));
	}
 #endif
#endif

	/* Grab OS specific "random" data */
#ifndef _WIN32
	gettimeofday(&rdat.nowt, NULL);
	fd = open("/dev/urandom", O_RDONLY);
	if (fd) {
		n = read(fd, &rdat.rnd, sizeof(rdat.rnd));
		Debug((DEBUG_INFO, "init_random: read from /dev/urandom returned %d", n));
		close(fd);
	}
	/* TODO: more!?? */
#else
	_ftime(&rdat.nowt);
	GlobalMemoryStatus (&rdat.mstat);
#endif	

	arc4_addrandom(&rdat, sizeof(rdat));

	/* NOTE: addtional entropy is added by add_entropy_* function(s) */
}
예제 #2
0
/*
 * Try the various seeding methods in turn, exit when successful.
 *
 * TODO(DRBG): If more than one entropy source is available, is it
 * preferable to stop as soon as enough entropy has been collected
 * (as favored by @rsalz) or should one rather be defensive and add
 * more entropy than requested and/or from different sources?
 *
 * Currently, the user can select multiple entropy sources in the
 * configure step, yet in practice only the first available source
 * will be used. A more flexible solution has been requested, but
 * currently it is not clear how this can be achieved without
 * overengineering the problem. There are many parameters which
 * could be taken into account when selecting the order and amount
 * of input from the different entropy sources (trust, quality,
 * possibility of blocking).
 */
size_t rand_pool_acquire_entropy(RAND_POOL *pool)
{
#  ifdef OPENSSL_RAND_SEED_NONE
    return rand_pool_entropy_available(pool);
#  else
    size_t bytes_needed;
    size_t entropy_available = 0;
    unsigned char *buffer;

#   ifdef OPENSSL_RAND_SEED_GETRANDOM
    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
    buffer = rand_pool_add_begin(pool, bytes_needed);
    if (buffer != NULL) {
        size_t bytes = 0;

        if (syscall_random(buffer, bytes_needed) == (int)bytes_needed)
            bytes = bytes_needed;

        rand_pool_add_end(pool, bytes, 8 * bytes);
        entropy_available = rand_pool_entropy_available(pool);
    }
    if (entropy_available > 0)
        return entropy_available;
#   endif

#   if defined(OPENSSL_RAND_SEED_LIBRANDOM)
    {
        /* Not yet implemented. */
    }
#   endif

#   ifdef OPENSSL_RAND_SEED_DEVRANDOM
    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
    {
        size_t i;

        for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) {
            const int fd = get_random_device(i);

            if (fd == -1)
                continue;
            buffer = rand_pool_add_begin(pool, bytes_needed);
            if (buffer != NULL) {
                const ssize_t n = read(fd, buffer, bytes_needed);

                if (n <= 0) {
                    close_random_device(i);
                    continue;
                }

                rand_pool_add_end(pool, n, 8 * n);
            }
            if (!keep_random_devices_open)
                close_random_device(i);

            bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
        }
        entropy_available = rand_pool_entropy_available(pool);
        if (entropy_available > 0)
            return entropy_available;
    }
#   endif

#   ifdef OPENSSL_RAND_SEED_RDTSC
    entropy_available = rand_acquire_entropy_from_tsc(pool);
    if (entropy_available > 0)
        return entropy_available;
#   endif

#   ifdef OPENSSL_RAND_SEED_RDCPU
    entropy_available = rand_acquire_entropy_from_cpu(pool);
    if (entropy_available > 0)
        return entropy_available;
#   endif

#   ifdef OPENSSL_RAND_SEED_EGD
    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
    if (bytes_needed > 0) {
        static const char *paths[] = { DEVRANDOM_EGD, NULL };
        int i;

        for (i = 0; paths[i] != NULL; i++) {
            buffer = rand_pool_add_begin(pool, bytes_needed);
            if (buffer != NULL) {
                size_t bytes = 0;
                int num = RAND_query_egd_bytes(paths[i],
                                               buffer, (int)bytes_needed);
                if (num == (int)bytes_needed)
                    bytes = bytes_needed;

                rand_pool_add_end(pool, bytes, 8 * bytes);
                entropy_available = rand_pool_entropy_available(pool);
            }
            if (entropy_available > 0)
                return entropy_available;
        }
    }
#   endif

    return rand_pool_entropy_available(pool);
#  endif
}
예제 #3
0
/*
 * Try the various seeding methods in turn, exit when successful.
 *
 * TODO(DRBG): If more than one entropy source is available, is it
 * preferable to stop as soon as enough entropy has been collected
 * (as favored by @rsalz) or should one rather be defensive and add
 * more entropy than requested and/or from different sources?
 *
 * Currently, the user can select multiple entropy sources in the
 * configure step, yet in practice only the first available source
 * will be used. A more flexible solution has been requested, but
 * currently it is not clear how this can be achieved without
 * overengineering the problem. There are many parameters which
 * could be taken into account when selecting the order and amount
 * of input from the different entropy sources (trust, quality,
 * possibility of blocking).
 */
size_t rand_pool_acquire_entropy(RAND_POOL *pool)
{
#  if defined(OPENSSL_RAND_SEED_NONE)
    return rand_pool_entropy_available(pool);
#  else
    size_t bytes_needed;
    size_t entropy_available = 0;
    unsigned char *buffer;

#   if defined(OPENSSL_RAND_SEED_GETRANDOM)
    {
        ssize_t bytes;
        /* Maximum allowed number of consecutive unsuccessful attempts */
        int attempts = 3;

        bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
        while (bytes_needed != 0 && attempts-- > 0) {
            buffer = rand_pool_add_begin(pool, bytes_needed);
            bytes = syscall_random(buffer, bytes_needed);
            if (bytes > 0) {
                rand_pool_add_end(pool, bytes, 8 * bytes);
                bytes_needed -= bytes;
                attempts = 3; /* reset counter after successful attempt */
            } else if (bytes < 0 && errno != EINTR) {
                break;
            }
        }
    }
    entropy_available = rand_pool_entropy_available(pool);
    if (entropy_available > 0)
        return entropy_available;
#   endif

#   if defined(OPENSSL_RAND_SEED_LIBRANDOM)
    {
        /* Not yet implemented. */
    }
#   endif

#   if defined(OPENSSL_RAND_SEED_DEVRANDOM)
    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
    {
        size_t i;

        for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) {
            ssize_t bytes = 0;
            /* Maximum allowed number of consecutive unsuccessful attempts */
            int attempts = 3;
            const int fd = get_random_device(i);

            if (fd == -1)
                continue;

            while (bytes_needed != 0 && attempts-- > 0) {
                buffer = rand_pool_add_begin(pool, bytes_needed);
                bytes = read(fd, buffer, bytes_needed);

                if (bytes > 0) {
                    rand_pool_add_end(pool, bytes, 8 * bytes);
                    bytes_needed -= bytes;
                    attempts = 3; /* reset counter after successful attempt */
                } else if (bytes < 0 && errno != EINTR) {
                    break;
                }
            }
            if (bytes < 0 || !keep_random_devices_open)
                close_random_device(i);

            bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
        }
        entropy_available = rand_pool_entropy_available(pool);
        if (entropy_available > 0)
            return entropy_available;
    }
#   endif

#   if defined(OPENSSL_RAND_SEED_RDTSC)
    entropy_available = rand_acquire_entropy_from_tsc(pool);
    if (entropy_available > 0)
        return entropy_available;
#   endif

#   if defined(OPENSSL_RAND_SEED_RDCPU)
    entropy_available = rand_acquire_entropy_from_cpu(pool);
    if (entropy_available > 0)
        return entropy_available;
#   endif

#   if defined(OPENSSL_RAND_SEED_EGD)
    bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
    if (bytes_needed > 0) {
        static const char *paths[] = { DEVRANDOM_EGD, NULL };
        int i;

        for (i = 0; paths[i] != NULL; i++) {
            buffer = rand_pool_add_begin(pool, bytes_needed);
            if (buffer != NULL) {
                size_t bytes = 0;
                int num = RAND_query_egd_bytes(paths[i],
                                               buffer, (int)bytes_needed);
                if (num == (int)bytes_needed)
                    bytes = bytes_needed;

                rand_pool_add_end(pool, bytes, 8 * bytes);
                entropy_available = rand_pool_entropy_available(pool);
            }
            if (entropy_available > 0)
                return entropy_available;
        }
    }
#   endif

    return rand_pool_entropy_available(pool);
#  endif
}