/* Organization: Technical University of Kosice (TUKE), Department: Department of Electronics and Multimedia Telecommunications (DEMT/KEMT), Faculties: Faculty of Electrical Engineering and Informatics (FEI), Feld of study: Informatics, Study program: Computer Networks, School year: 3., Bachelor study, 2020/2021, Author: Marek Rohac -- MR, Compiler: Winlibs GCC -- MinGW-W64 x86_64-posix-seh, built by Brecht Sanders, v. 10.2.0, -- also works with GCC 11.1.0, compile: gcc openssl_rng.c -I./include -L./lib -llibcrypto -g -Wall -Wextra -o ossl version: 1.0 , 20.05.2021. Description: This program is only for educational purposes. Program use 2 different OpenSSL APIs to generate random data RAND_bytes and RAND_priv_bytes Usage: In macro RNG_BYTES_OUTPUT define how much random bytes you want by one cycle. Then define number of cycles in macro RNG_CYCLES Program then generate output according APIs and save values to .bin files with name by current API */ #define __USE_MINGW_ANSI_STDIO #include #include #include //we use windows header for time measurment APIs and some variable types #define RNG_BYTES_OUTPUT INT_MAX #define RNG_CYCLES 16 //16xINT_MAX=32GB /*############################################################ FUNCTIONS FOR MEASURMENTS ##############################################################*/ //MACROS FOR EASIER TIMER MEASURMENT, VIA WINAPI QueryPerformanceCounter #define TIMER_INIT \ LARGE_INTEGER frequency; \ LARGE_INTEGER t1,t2; \ double elapsedTime; \ QueryPerformanceFrequency(&frequency); /** Use to start the performance timer */ #define TIMER_START QueryPerformanceCounter(&t1); /* Use to stop the performance timer and output the result to the standard stream. Less verbose than \c TIMER_STOP_VERBOSE */ #define TIMER_STOP \ QueryPerformanceCounter(&t2); \ elapsedTime=(double)(t2.QuadPart-t1.QuadPart)/frequency.QuadPart; /* divide frequency.QuadPart by 1000.0 if you want time in ms also you can multiply by 1000 t2.QuadPart and t1.QuadPart before dividing you will get time in nanosecond precision.*/ /* ================================================================================= https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf CYCLES * AverageCycles* 1/ghzOfProcessor * 10^-9 = cca execution CPUTIME */ //cpucyclesS -- start measurment static __inline__ uint64_t cpucyclesS(){ unsigned cycles_low, cycles_high; __asm__ volatile ("CPUID\n\t" "RDTSC\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low):: "%rax", "%rbx", "%rcx", "%rdx"); return (((uint64_t)cycles_high << 32) | cycles_low ); } //cpucyclesE -- end measurment static __inline__ uint64_t cpucyclesE(){ unsigned cycles_low, cycles_high; __asm__ volatile ("RDTSCP\n\t" "mov %%edx, %0\n\t" "mov %%eax, %1\n\t" "CPUID\n\t": "=r" (cycles_high), "=r" (cycles_low):: "%rax", "%rbx", "%rcx", "%rdx"); return (((uint64_t)cycles_high << 32) | cycles_low ); } /* compare for qsort */ static int cmp_llu(const void *a, const void*b) { if(*(uint64_t *)a < *(uint64_t *)b) return -1; if(*(uint64_t *)a > *(uint64_t *)b) return 1; return 0; } /* calculating of median value from measurment */ static uint64_t median(uint64_t *l, size_t llen) { if (llen<=1) {printf("Not enought values for median\n"); return l[llen-1]; } qsort(l,llen,sizeof(uint64_t),cmp_llu); if(llen%2) return l[llen/2]; else return (l[llen/2-1]+l[llen/2])/2; } /* calculating of average value from measurment */ static uint64_t average(uint64_t *t, size_t tlen) { uint64_t acc=0; size_t i; for(i=0;i %d. cycle\n",i); } store_Data(fp,pbdata); } TIMER_STOP} store_Time_Data("RAND_bytes:",time,RNG_CYCLES,timeFile, elapsedTime); fclose(fp); return 0; } //interpretation of RAND_priv_bytes api int rand_priv_bytes_API(FILE *timeFile, BYTE * pbdata){ FILE * fp=fopen("RAND_priv_bytes.bin","ab+"); int ret=0; uint64_t time[RNG_CYCLES], tick; TIMER_INIT {TIMER_START for (int i = 0; i < RNG_CYCLES; i++){ tick = cpucyclesS(); ret= RAND_priv_bytes(pbdata,RNG_BYTES_OUTPUT); time[i] = cpucyclesE() - tick; if(ret!=1){ printf("RAND_priv_bytes Failed--> %d. cycle\n",i); } store_Data(fp,pbdata); } TIMER_STOP} store_Time_Data("RAND_priv_bytes:",time,RNG_CYCLES,timeFile, elapsedTime); fclose(fp); return 0; } int main(){ BYTE * data =(BYTE*)malloc(sizeof(BYTE)*RNG_BYTES_OUTPUT); FILE * timeFile=fopen("ossl.txt","a+"); int ret=0; TIMER_INIT {TIMER_START ret+=rand_bytes_API(timeFile,data); ret+=rand_priv_bytes_API(timeFile,data); TIMER_STOP} printf("Program executed in: %f sec\n",elapsedTime); fclose(timeFile); free(data); return 0; }