-rw-r--r-- 1672 librandombytes-20240318/kernel/getrandom_wrapper.c raw
// version 20230126 // public domain // djb // planned long-term cleanup: // once all systems support getrandom() via sys/random.h, // get rid of the other options and the SIGSYS handling #include <unistd.h> // automatic-alternatives 5 #ifdef getrandom_wrapper_5 #include "getrandom_wrapper.h" int getrandom_wrapper_ready(void) { return 0; } void getrandom_wrapper(void *x,long long xbytes) { for (;;) pause(); } #else #include <errno.h> #include <signal.h> #ifdef getrandom_wrapper_1 #include <sys/random.h> #endif #ifdef getrandom_wrapper_2 #include <linux/random.h> #endif #ifdef getrandom_wrapper_3 #include <syscall.h> #define getrandom(a,b,c) syscall(SYS_getrandom,a,b,c) #endif #ifdef getrandom_wrapper_4 #include <syscall.h> #define getrandom(a,b,c) syscall(__NR_getrandom,a,b,c) #endif #include "getrandom_wrapper.h" static int getrandom_wrapper_ready_core(void) { char ch; int r; for (;;) { errno = 0; r = getrandom(&ch,1,0); if (r == 1) return 1; if (r == -1 && errno == ENOSYS) return 0; if (r == -1 && errno == EPERM) return 0; // QNAP bug if (r == -1 && errno == EINVAL) return 0; } } int getrandom_wrapper_ready(void) { struct sigaction old_sigsys; int result; sigaction(SIGSYS,0,&old_sigsys); signal(SIGSYS,SIG_IGN); result = getrandom_wrapper_ready_core(); sigaction(SIGSYS,&old_sigsys,0); return result; } void getrandom_wrapper(void *x,long long xbytes) { while (xbytes > 0) { int todo = 1048576; if (xbytes < 1048576) todo = xbytes; todo = getrandom(x,todo,0); if (todo < 1) { sleep(1); continue; } x += todo; xbytes -= todo; } } #endif