-rw-r--r-- 3297 librandombytes-20240318/command/randombytes-info.c raw
// version 20230904
// public domain
// djb
// 20230904: added -lm, -lrandombytes
// 20230126: initial release
#include <stdio.h>
#include <stdlib.h>
#include <math.h> // -lm
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <randombytes.h> // -lrandombytes
static void die_perm(const char *why)
{
fprintf(stderr,"randombytes-info: fatal: %s\n",why);
exit(100);
}
static void die_temp(const char *why,const char *why2)
{
if (why2)
fprintf(stderr,"randombytes-info: fatal: %s: %s\n",why,why2);
else
fprintf(stderr,"randombytes-info: fatal: %s\n",why);
exit(111);
}
static void fullread(int fd,unsigned char *x,long long xbytes)
{
while (xbytes > 0) {
int r = 16777216;
if (xbytes < r) r = xbytes;
errno = 0;
r = read(fd,x,r);
if (r == 0) die_temp("read failed","unexpected EOF");
if (r < 0 && errno == EINTR) continue;
if (r < 0) die_temp("read failed",strerror(errno));
x += r;
xbytes -= r;
}
}
static void fullwrite(int fd,unsigned char *x,long long xbytes)
{
while (xbytes > 0) {
int w = 16777216;
if (xbytes < w) w = xbytes;
errno = 0;
w = write(fd,x,w);
if (w == 0) continue;
if (w < 0 && errno == EINTR) continue;
if (w < 0) die_temp("write failed",strerror(errno));
x += w;
xbytes -= w;
}
}
static void test_fork(void)
{
unsigned char x[32];
unsigned char y[32];
int pi[2];
pid_t child;
int j;
if (pipe(pi) != 0)
die_temp("pipe failed",strerror(errno));
child = fork();
if (child < 0)
die_temp("fork failed",strerror(errno));
randombytes(x,sizeof x);
if (child == 0) {
close(pi[0]);
fullwrite(pi[1],x,sizeof x);
exit(0);
}
close(pi[1]);
fullread(pi[0],y,sizeof y);
close(pi[0]);
printf("randombytes test_fork x ");
for (j = 0;j < sizeof x;++j) printf("%02x",x[j]);
printf("\n");
printf("randombytes test_fork y ");
for (j = 0;j < sizeof y;++j) printf("%02x",y[j]);
printf("\n");
fflush(stdout);
if (memcmp(x,y,sizeof y) == 0)
die_perm("RNG failure: 32 bytes match after fork");
}
#define TIMINGS 16
static void speed(void)
{
unsigned char x[16384];
struct timeval tv[TIMINGS];
double t[TIMINGS-1];
double avg;
double variance;
long long bytes, iters, i, j;
bytes = 1;
while (bytes <= sizeof x) {
for (iters = 1;iters <= 64;iters *= 2) {
for (i = 0;i < TIMINGS;++i) {
gettimeofday(&tv[i],0);
for (j = 0;j < iters;++j)
randombytes(x,bytes);
}
printf("randombytes timing bytes %lld iters %lld ns/byte",bytes,iters);
for (i = 1;i < TIMINGS;++i)
t[i-1] = ((tv[i].tv_sec-tv[i-1].tv_sec)*1000000000.0+(tv[i].tv_usec-tv[i-1].tv_usec)*1000.0)/(iters*bytes);
avg = 0;
for (i = 1;i < TIMINGS;++i)
avg += t[i-1];
avg /= TIMINGS-1;
variance = 0;
for (i = 1;i < TIMINGS;++i)
variance += (t[i-1]-avg)*(t[i-1]-avg);
variance /= TIMINGS-1;
printf(" %lf +- %lf\n",avg,sqrt(variance));
fflush(stdout);
}
if (bytes >= sizeof x) break;
bytes *= 128;
}
}
int main()
{
printf("randombytes source %s\n",randombytes_source());
fflush(stdout);
test_fork();
speed();
return 0;
}