-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; }