1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
// 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;
}
|