203 lines
6.6 KiB
C
203 lines
6.6 KiB
C
|
/*
|
||
|
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 <stdio.h>
|
||
|
#include <openssl/rand.h>
|
||
|
#include <windows.h>
|
||
|
//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<tlen;i++)acc += t[i];
|
||
|
if(acc!=0)return acc/(tlen);
|
||
|
return t[tlen];
|
||
|
}
|
||
|
|
||
|
|
||
|
/*############################################################
|
||
|
END OF FUNCTIONS FOR MEASURMENTS
|
||
|
##############################################################*/
|
||
|
|
||
|
|
||
|
/*############################################################
|
||
|
AUXILIARY FUNCTIONS
|
||
|
##############################################################*/
|
||
|
|
||
|
//storing generated random data
|
||
|
void store_Data(FILE * fp, void * pbBuffer){
|
||
|
fwrite(pbBuffer,sizeof(BYTE),RNG_BYTES_OUTPUT,fp);
|
||
|
if( feof(fp) ) {printf("Problem with %s file\n", (char*)fp);}
|
||
|
//else printf("File successfully create!\n");
|
||
|
}
|
||
|
|
||
|
//storing time datas of executions
|
||
|
void store_Time_Data(const char * name, uint64_t *t, size_t tlen,FILE * fp, double programRun){
|
||
|
uint64_t sum;
|
||
|
fprintf(fp, "%s\n",name);
|
||
|
for(size_t i=0;i<tlen;i++){
|
||
|
sum+=t[i];
|
||
|
// fprintf(fp, "%4.lld%s %llu %s\n", i+1, ".Time: ", t[i]," cpucycles");
|
||
|
if( feof(fp) ) {printf("Problem with %s file\n", name);}
|
||
|
}
|
||
|
fprintf(fp,"TOTAL: %llu cycles\nMEDIAN: %llu cpucycles\nAVERAGE: %llu cpucycles\nEXECUTED in %f s\n",sum, median(t, tlen),average(t, tlen),programRun);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*############################################################
|
||
|
END OF AUXILIARY FUNCTIONS
|
||
|
##############################################################*/
|
||
|
|
||
|
//interpretation of RAND_bytes api
|
||
|
int rand_bytes_API(FILE *timeFile, BYTE * pbdata){
|
||
|
FILE * fp=fopen("RAND_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_bytes(pbdata,RNG_BYTES_OUTPUT);
|
||
|
time[i] = cpucyclesE() - tick;
|
||
|
if(ret!=1){
|
||
|
printf("RAND_bytes Failed--> %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;
|
||
|
}
|