/* ## ####################################################################### ## ## makernd - program for generation of random files suitable for one-time ## pads. Uses audio signal from soundcard input. ## ## Compilation parameters: ## cc -o makernd -lssl makernd.c ## ## Performs basic sanity check for sufficient entropy on the input. ## Reads 64 bytes from DSP, checks if there is at least one pair of ## adjanced bytes where the bytes are different by more than 16 ## (arbitrarily chosen value). This should be replaced with some kind ## of statistical analysis. The check is also done on each block read ## from the input, discarding suspicious input data. ## ## Reads blocks of 128 bytes from RANDOMINPUT, hashes them with MD5, ## outputs 16-byte blocks to output file and RANDOMDEV (so as the side ## effect it feeds the entropy pool). ## ## Takes one mandatory parameter (number of random bytes to produce) and ## one optional parameter (output file name - uses stdout if not present). ## ## ####################################################################### */ #include #include #include #include #include #define RANDOMDEV "/dev/urandom" #define RANDOMINPUT "/dev/dsprandom" char output[18]; FILE*fo,*frnd; void outputbinary(char*s,long n) { while(n>0) {fprintf(fo,"%c",s[0] & 0xff);s++;n--;} } // FIXME: replace with real statistical check int isinsufficiententropy(char*data,int n) { int t; for(t=0;t16)return 0; return 1; } int checkinputentropy(FILE*f) { char data[64]; fread(data,64,1,f); return isinsufficiententropy(data,64); } int output16bytes(FILE*f,long n) { char data[128]; MD5_CTX c; MD5_Init(&c); MD5_Update(&c,output,16); for(;;){fread(data,128,1,f); if(!isinsufficiententropy(data,128))break; fprintf(stderr,"Insufficient input entropy. Rereading block.\n");} MD5_Update(&c,data,128); MD5_Final(output,&c); if(n>16)n=16;if(n<0)n=0; outputbinary(output,n); if(frnd)fwrite(output,16,1,frnd); return 0; } int main(int argc,char*argv[]) { FILE*f; long n; if(argc<2) {printf("makernd [output.file]\n" "Creates LENGTH bytes of random numbers derived from "RANDOMINPUT", " "which should be a symlink to eg. /dev/dsp0 fed with analog signal " "from eg. a white noise generator.\n" "Outputs to stdout if output.file is not specified.\n" "Feeds the output also to "RANDOMDEV".\n"); return 0;} n=atol(argv[1]); if(n<=0) {fprintf(stderr,"Argument '%s' has to be greater than zero.\n",argv[1]); return 111;} f=fopen(RANDOMINPUT,"r"); if(!f) {perror("ERROR: Cannot open "RANDOMINPUT); fprintf(stderr,"Check if the symlink or device exists.\n"); return 111;} {int tmp; tmp=1; if(ioctl(fileno(f),SNDCTL_DSP_STEREO,&tmp)<0)fprintf(stderr,"SNDCTL_DSP_STEREO failed\n"); if(ioctl(fileno(f),SNDCTL_DSP_RESET,&tmp)<0)fprintf(stderr,"SNDCTL_DSP_RESET failed\n"); tmp=44100; if(ioctl(fileno(f),SNDCTL_DSP_SPEED,&tmp)<0)fprintf(stderr,"SNDCTL_DSP_SPEED failed\n"); } if(checkinputentropy(f)) {fprintf(stderr,"ERROR: Input entropy seems to be insufficient.\n" "No two adjanced bytes in "RANDOMINPUT" that are different by more than 16.\n" "Check the input signal volume.\n" "Cowardly refusing to create any output.\n"); return 1;} frnd=fopen(RANDOMDEV,"rw"); if(frnd){fread(output,16,1,frnd);} else{fprintf(stderr,"Cannot open "RANDOMDEV", cannot initialize output. Proceeding anyway.\n");} if(argc>2){fo=fopen(argv[2],"w"); if(!fo){perror("ERROR: Cannot open output file");return(111);}} else fo=stdout; while(n>0){output16bytes(f,n);n-=16; fprintf(stderr,"%i \r",n);} fclose(f);fclose(frnd); fprintf(stderr,"Finished.\n"); return 0; }