mirror of
https://github.com/jedisct1/libsodium.git
synced 2026-08-25 08:37:13 +09:00
Add randombytes_sysrandom and use that as the default randombytes impl.
This commit is contained in:
@@ -75,6 +75,8 @@ libsodium_la_SOURCES = \
|
||||
randombytes/randombytes.c \
|
||||
randombytes/randombytes_salsa20_random.c \
|
||||
randombytes/randombytes_salsa20_random.h \
|
||||
randombytes/randombytes_sysrandom.c \
|
||||
randombytes/randombytes_sysrandom.h \
|
||||
version.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#ifndef __SALSA20_RANDOM_H__
|
||||
#define __SALSA20_RANDOM_H__ 1
|
||||
#ifndef randombytes_salsa20_random_H
|
||||
#define randombytes_salsa20_random_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
#ifndef randombytes_sysrandom_H
|
||||
#define randombytes_sysrandom_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char *sysrandom_implementation_name(void);
|
||||
|
||||
uint32_t sysrandom(void);
|
||||
void sysrandom_stir(void);
|
||||
uint32_t sysrandom_uniform(const uint32_t upper_bound);
|
||||
void sysrandom_buf(void * const buf, const size_t size);
|
||||
int sysrandom_close(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -5,15 +5,15 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include "randombytes.h"
|
||||
#include "randombytes_salsa20_random.h"
|
||||
#include "randombytes_sysrandom.h"
|
||||
|
||||
static randombytes_implementation implementation = {
|
||||
.randombytes_implementation_name = salsa20_random_implementation_name,
|
||||
.randombytes_random = salsa20_random,
|
||||
.randombytes_stir = salsa20_random_stir,
|
||||
.randombytes_uniform = salsa20_random_uniform,
|
||||
.randombytes_buf = salsa20_random_buf,
|
||||
.randombytes_close = salsa20_random_close
|
||||
.randombytes_implementation_name = sysrandom_implementation_name,
|
||||
.randombytes_random = sysrandom,
|
||||
.randombytes_stir = sysrandom_stir,
|
||||
.randombytes_uniform = sysrandom_uniform,
|
||||
.randombytes_buf = sysrandom_buf,
|
||||
.randombytes_close = sysrandom_close
|
||||
};
|
||||
|
||||
int
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#ifndef _WIN32
|
||||
# include <poll.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "randombytes_sysrandom.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <Windows.h>
|
||||
# include <Wincrypt.h>
|
||||
#endif
|
||||
|
||||
#define COMPILER_ASSERT(X) (void) sizeof(char[(X) ? 1 : -1])
|
||||
|
||||
typedef struct SysRandom_ {
|
||||
#ifdef _WIN32
|
||||
HCRYPTPROV hcrypt_prov;
|
||||
#endif
|
||||
int random_data_source_fd;
|
||||
_Bool initialized;
|
||||
} SysRandom;
|
||||
|
||||
static SysRandom stream = {
|
||||
.random_data_source_fd = -1,
|
||||
.initialized = 0
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
static ssize_t
|
||||
safe_read(const int fd, void * const buf_, size_t count)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *) buf_;
|
||||
ssize_t readnb;
|
||||
|
||||
do {
|
||||
while ((readnb = read(fd, buf, count)) < (ssize_t) 0 &&
|
||||
errno == EINTR);
|
||||
if (readnb < (ssize_t) 0) {
|
||||
return readnb;
|
||||
}
|
||||
if (readnb == (ssize_t) 0) {
|
||||
break;
|
||||
}
|
||||
count -= (size_t) readnb;
|
||||
buf += readnb;
|
||||
} while (count > (ssize_t) 0);
|
||||
|
||||
return (ssize_t) (buf - (unsigned char *) buf_);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
static int
|
||||
sysrandom_random_dev_open(void)
|
||||
{
|
||||
static const char * const devices[] = {
|
||||
# ifndef USE_BLOCKING_RANDOM
|
||||
"/dev/arandom", "/dev/urandom",
|
||||
# endif
|
||||
"/dev/random", NULL
|
||||
};
|
||||
const char * const *device = devices;
|
||||
|
||||
do {
|
||||
if (access(*device, F_OK | R_OK) == 0) {
|
||||
return open(*device, O_RDONLY);
|
||||
}
|
||||
device++;
|
||||
} while (*device != NULL);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
sysrandom_init(void)
|
||||
{
|
||||
if ((stream.random_data_source_fd =
|
||||
sysrandom_random_dev_open()) == -1) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
static void
|
||||
sysrandom_init(void)
|
||||
{
|
||||
if (! CryptAcquireContext(&stream.hcrypt_prov, NULL, NULL,
|
||||
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
sysrandom_stir(void)
|
||||
{
|
||||
if (stream.initialized == 0) {
|
||||
sysrandom_init();
|
||||
stream.initialized = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sysrandom_stir_if_needed(void)
|
||||
{
|
||||
if (stream.initialized == 0) {
|
||||
sysrandom_stir();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sysrandom_close(void)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (stream.random_data_source_fd != -1 &&
|
||||
close(stream.random_data_source_fd) == 0) {
|
||||
stream.random_data_source_fd = -1;
|
||||
stream.initialized = 0;
|
||||
ret = 0;
|
||||
}
|
||||
#else /* _WIN32 */
|
||||
if (stream.initialized != 0 &&
|
||||
CryptReleaseContext(stream.hcrypt_prov, 0)) {
|
||||
stream.initialized = 0;
|
||||
ret = 0;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
sysrandom(void)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
sysrandom_stir_if_needed();
|
||||
sysrandom_buf(&r, sizeof r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
sysrandom_buf(void * const buf, const size_t size)
|
||||
{
|
||||
sysrandom_stir_if_needed();
|
||||
#ifdef ULONG_LONG_MAX
|
||||
assert(size <= ULONG_LONG_MAX);
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
if (safe_read(stream.random_data_source_fd, buf, size) != (ssize_t) size) {
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
if (! CryptGenRandom(stream.hcrypt_prov, buf, size)) {
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* sysrandom_uniform() derives from OpenBSD's arc4random_uniform()
|
||||
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
|
||||
*/
|
||||
|
||||
uint32_t
|
||||
sysrandom_uniform(const uint32_t upper_bound)
|
||||
{
|
||||
uint32_t min;
|
||||
uint32_t r;
|
||||
|
||||
if (upper_bound < 2) {
|
||||
return 0;
|
||||
}
|
||||
min = (uint32_t) (-upper_bound % upper_bound);
|
||||
for (;;) {
|
||||
r = sysrandom();
|
||||
if (r >= min) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r % upper_bound;
|
||||
}
|
||||
|
||||
const char *
|
||||
sysrandom_implementation_name(void)
|
||||
{
|
||||
return "sysrandom";
|
||||
}
|
||||
Reference in New Issue
Block a user