/* 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 Compiling: gcc ./amdINC/secrng.c amdSPRNG.c -Wall -g -I./amdINC -mrdrnd -mrdseed -o amdSPRNG , Version: 1.1, 19.05.2021. Description: This program is only for educational purposes. Program use 4 AMD APIs (defined in secrng.h) to generate random bytes: is_RDRAND_supported(); is_RDSEED_supported(); get_rdseed_bytes_arr(unsigned char *rng_arr, unsigned int N, unsigned int retry_count) get_rdrand_bytes_arr(unsigned char *rng_arr, unsigned int N, unsigned int retry_count) Usage: In macro N define how much random bytes you want per one generating. CYCLES then defined how much times you want to repeat generating process Program then generate output according APIs and save values to .bin files with name by current RD name */ #define __USE_MINGW_ANSI_STDIO #include #include #include #include #include "secrng.h" // count of API calls #define CYCLES 1024 // output size per API call in Bytes #define N 16384 // ULONG_MAX should be same as UINT_MAX -- 4GB //N x CYCLES = output size in bytes //33554432 B == 32 MB //16777216 B == 16 MB //16384 B == 16kB //retry count if rng fails #define NT 15 //Macros For time measurments #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=(float)(t2.QuadPart-t1.QuadPart)/frequency.QuadPart; // divide frequency.QuadPart by 1000.0 if you want time in ms /* function to measure speed of generating process (output is number of number of cpu cycles) CYCLES * AverageCycles* 1/ghzOfProcessor * 10^-9 = cca execution CPUTIME Inspiration by --> https://github.com/newhopecrypto/newhope/tree/master/ref - MR: asm changed to __asm__ for newer c standard support (before we need -std=gnu99 to compile) */ /* int64_t cpucycles(void) { uint64_t result; //function use rdts instruction and shift higher values from reg where rdtsc store values //(rax, rdx) __asm__ volatile(".byte 15;.byte 49;shlq $32,%%rdx;orq %%rdx,%%rax" : "=a" (result) :: "%rdx"); return result; } ================================================================================= REPLACED BY CPUID/RDTSC/RDTSCP INSTRUCTIONS -->below-->cpucyclesS(),cpucyclesE() ***FOR BETTER PRECISIOUS*** ================================================================================= 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