#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
typedef void(* issue_t)(uint8_t*, size_t);
#if defined(__linux__) && defined(SYS_getrandom)
void issue(uint8_t *out, size_t outlen) {
while(outlen > 0) {
ssize_t ret = syscall(SYS_getrandom, out, outlen, 0);
if((ret == -1) && (errno == EINTR)) {
continue;
}
else if(ret == -1) {
fprintf(stderr, "Error while executing syscall getrandom\n");
abort();
}
out += ret;
outlen -= ret;
}
}
#else
void issue(uint8_t *out, size_t outlen) {
int fd = -1;
while(fd == -1) {
fd = open("/dev/urandom", O_RDONLY);
if((fd == -1) && (errno == EINTR)) {
continue;
}
else if(fd == -1) {
fprintf(stderr, "Error while opening /dev/urandom\n");
abort();
}
}
while(outlen > 0) {
ssize_t ret = read(fd, out, outlen);
if((ret == -1) && (errno == EINTR)) {
continue;
}
else if(ret == -1) {
close(fd);
fprintf(stderr, "Error while reading from /dev/urandom\n");
abort();
}
out += ret;
outlen -= ret;
}
close(fd);
}
#endif
int main(void) {
uint8_t out[1] = {0};
size_t size = 1;
// this test has no secret variables from the start, but the randomness from
// /dev/urandom or SYS_getrandom may be the input to some function generating
// a secret
// declarations and markup here
volatile issue_t func = issue;
func(out, size);
return 0;
}
See the compilation results with different optimization levels on GodBolt.