Crypt-PQClean-Sign
view release on metacpan or search on metacpan
pqclean/common/randombytes.c view on Meta::CPAN
}
}
do {
retcode = close(fd);
} while (retcode == -1 && errno == EINTR);
if (strategy == PROC) {
do {
retcode = fclose(proc_file);
} while (retcode == -1 && errno == EINTR);
}
if (retcode_error != 0) {
return retcode_error;
}
return retcode;
}
static int randombytes_linux_randombytes_urandom(void *buf, size_t n) {
int fd;
size_t offset = 0, count;
ssize_t tmp;
do {
fd = open("/dev/urandom", O_RDONLY);
} while (fd == -1 && errno == EINTR);
if (fd == -1) {
return -1;
}
if (randombytes_linux_wait_for_entropy(fd) == -1) {
return -1;
}
while (n > 0) {
count = n <= SSIZE_MAX ? n : SSIZE_MAX;
tmp = read(fd, (char *)buf + offset, count);
if (tmp == -1 && (errno == EAGAIN || errno == EINTR)) {
continue;
}
if (tmp == -1) {
return -1; /* Unrecoverable IO error */
}
offset += tmp;
n -= tmp;
}
close(fd);
assert(n == 0);
return 0;
}
#endif /* defined(__linux__) && !defined(SYS_getrandom) */
#if defined(BSD)
static int randombytes_bsd_randombytes(void *buf, size_t n) {
arc4random_buf(buf, n);
return 0;
}
#endif /* defined(BSD) */
#if defined(__EMSCRIPTEN__)
static int randombytes_js_randombytes_nodejs(void *buf, size_t n) {
const int ret = EM_ASM_INT({
var crypto;
try {
crypto = require('crypto');
} catch (error) {
return -2;
}
try {
writeArrayToMemory(crypto.randomBytes($1), $0);
return 0;
} catch (error) {
return -1;
}
}, buf, n);
switch (ret) {
case 0:
return 0;
case -1:
errno = EINVAL;
return -1;
case -2:
errno = ENOSYS;
return -1;
}
assert(false); // Unreachable
}
#endif /* defined(__EMSCRIPTEN__) */
int randombytes(uint8_t *output, size_t n) {
void *buf = (void *)output;
#if defined(__EMSCRIPTEN__)
return randombytes_js_randombytes_nodejs(buf, n);
#elif defined(__linux__)
# if defined(USE_GLIBC)
/* Use getrandom system call */
return randombytes_linux_randombytes_getrandom(buf, n);
# elif defined(SYS_getrandom)
/* Use getrandom system call */
return randombytes_linux_randombytes_getrandom(buf, n);
# else
/* When we have enough entropy, we can read from /dev/urandom */
return randombytes_linux_randombytes_urandom(buf, n);
# endif
#elif defined(BSD)
/* Use arc4random system call */
return randombytes_bsd_randombytes(buf, n);
#elif defined(_WIN32)
/* Use windows API */
return randombytes_win32_randombytes(buf, n);
#elif defined(__wasi__)
/* Use WASI */
return randombytes_wasi_randombytes(buf, n);
#else
# error "randombytes(...) is not supported on this platform"
#endif
}
( run in 3.134 seconds using v1.01-cache-2.11-cpan-995e09ba956 )