BachelorWork/appendixes/BC_ZK/openssl_rng.c

203 lines
6.6 KiB
C
Raw Permalink Normal View History

2021-05-24 20:44:55 +00:00
/*
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;
}