1 /* Last modified on Sat Aug 28 14:30:11 PDT 1999 by murray */
2 
3 #include <errno.h>
4 #include <stdint.h>
5 #include <stdio.h>
6 #include <time.h>
7 #include <sys/types.h>
8 #include <unistd.h>
9 
10 #include <openssl/opensslv.h>    /* for OPENSSL_VERSION_NUMBER */
11 #include <openssl/rand.h>
12 
13 #define BATCHSIZE 1000000
14 #define BILLION 1000000000
15 #define HISTSIZE 2500
16 #define NSPERBUCKET 1
17 #define MAXHISTLINES 10
18 
19 /* hack for libntp */
20 const char *progname = "foo";
21 
getpid_average(void)22 static int getpid_average(void) {
23         int err;
24         struct timespec start, stop;
25         uint64_t sec, nanos;
26 
27         err = clock_gettime(CLOCK_REALTIME, &start);
28         if (-1 == err) {
29                 printf("clock_gettime(CLOCK_REALTIME) didn't work, err %d\n", errno);
30                 return -1;
31         }
32 
33         clock_gettime(CLOCK_REALTIME, &start);
34         for (int i = 0; i < BATCHSIZE; i++) {
35                 getpid();
36         }
37         clock_gettime(CLOCK_REALTIME, &stop);
38 
39         /* Beware of overflowing 32 bits. */
40         sec = (stop.tv_sec-start.tv_sec);
41         nanos = sec*BILLION + (stop.tv_nsec-start.tv_nsec);
42         return nanos/BATCHSIZE;
43 
44 }
45 
clock_average(void)46 static int clock_average(void) {
47         int err;
48         struct timespec start, stop;
49         uint64_t sec, nanos;
50 
51         err = clock_gettime(CLOCK_REALTIME, &start);
52         if (-1 == err) {
53                 printf("clock_gettime(CLOCK_REALTIME) didn't work, err %d\n", errno);
54                 return -1;
55         }
56 
57         clock_gettime(CLOCK_REALTIME, &start);
58         for (int i = 0; i < BATCHSIZE; i++) {
59                 clock_gettime(CLOCK_REALTIME, &stop);
60         }
61         clock_gettime(CLOCK_REALTIME, &stop);
62 
63         /* Beware of overflowing 32 bits. */
64         sec = (stop.tv_sec-start.tv_sec);
65         nanos = sec*BILLION + (stop.tv_nsec-start.tv_nsec);
66         return nanos/BATCHSIZE;
67 
68 }
69 
do_average(void)70 static int do_average(void) {
71 	long int sum = 0;
72 	struct timespec start, stop;
73 	uint64_t sec, nanos;
74 
75 	clock_gettime(CLOCK_REALTIME, &start);
76 	for (int i = 0; i < BATCHSIZE; i++) {
77 		sum += random();
78 	}
79 	clock_gettime(CLOCK_REALTIME, &stop);
80 
81 	/* Beware of overflowing 32 bits. */
82 	sec = (stop.tv_sec-start.tv_sec);
83 	nanos = sec*BILLION + (stop.tv_nsec-start.tv_nsec);
84 	return nanos/BATCHSIZE;
85 }
86 
do_avg_bytes(unsigned int bytes)87 static int do_avg_bytes(unsigned int bytes) {
88 	int err = 0;
89 	struct timespec start, stop;
90 	uint64_t sec, nanos;
91 	unsigned char rnd[512];
92 
93 	if (bytes > sizeof(rnd)) {
94 		printf("## do_avg_bytes - too big\n");
95 		exit(1);
96 	}
97 
98 	clock_gettime(CLOCK_REALTIME, &start);
99 	for (int i = 0; i < BATCHSIZE; i++) {
100             err += RAND_bytes((unsigned char *)&rnd, bytes);
101 	}
102 	clock_gettime(CLOCK_REALTIME, &stop);
103 
104 	if (BATCHSIZE != err) {
105 		printf("## do_avg_bytes: troubles from RAND_bytes, %d\n",
106 			BATCHSIZE-err);
107 		exit(1);
108 	}
109 
110 	/* Beware of overflowing 32 bits. */
111 	sec = (stop.tv_sec-start.tv_sec);
112 	nanos = sec*BILLION + (stop.tv_nsec-start.tv_nsec);
113 	return nanos/BATCHSIZE;
114 }
115 
116 #if (OPENSSL_VERSION_NUMBER > 0x1010100fL)
do_avg_priv(unsigned int bytes)117 static int do_avg_priv(unsigned int bytes) {
118 	int err = 0;
119 	struct timespec start, stop;
120 	uint64_t sec, nanos;
121 	unsigned char rnd[512];
122 
123 	if (bytes > sizeof(rnd)) {
124 		printf("## do_avg_priv - too big\n");
125 		exit(1);
126 	}
127 
128 	clock_gettime(CLOCK_REALTIME, &start);
129 	for (int i = 0; i < BATCHSIZE; i++) {
130             err += RAND_priv_bytes((unsigned char *)&rnd, bytes);
131 	}
132 	clock_gettime(CLOCK_REALTIME, &stop);
133 
134 	if (BATCHSIZE != err) {
135 		printf("## do_avg_priv: troubles from RAND_bytes, %d\n",
136 			BATCHSIZE-err);
137 		exit(1);
138 	}
139 
140 	/* Beware of overflowing 32 bits. */
141 	sec = (stop.tv_sec-start.tv_sec);
142 	nanos = sec*BILLION + (stop.tv_nsec-start.tv_nsec);
143 	return nanos/BATCHSIZE;
144 }
145 #endif
146 
do_fastest(void)147 static int do_fastest(void) {
148 	int sum = 0;
149 	struct timespec start, stop;
150 	uint64_t sec, nanos, fastest = 999999999;
151 
152 	for (int i = 0; i < BATCHSIZE; i++) {
153                 clock_gettime(CLOCK_REALTIME, &start);
154 		/* coverity[dc,weak_crypto] */
155 		sum += random();
156 		clock_gettime(CLOCK_REALTIME, &stop);
157 		sec = (stop.tv_sec-start.tv_sec);
158 		nanos = sec*BILLION + (stop.tv_nsec-start.tv_nsec);
159 		if (nanos < fastest) {
160 			fastest = nanos;
161 		}
162 	}
163 
164 	return fastest;
165 }
166 
do_fast_bytes(unsigned bytes)167 static int do_fast_bytes(unsigned bytes) {
168 	int err = 0;
169 	struct timespec start, stop;
170 	uint64_t sec, nanos, fastest = 999999999;
171 	unsigned char rnd[512];
172 
173 	if (bytes > sizeof(rnd)) {
174 		printf("## do_fast_bytes - too big\n");
175 		exit(1);
176 	}
177 
178 	for (int i = 0; i < BATCHSIZE; i++) {
179                 clock_gettime(CLOCK_REALTIME, &start);
180                 err += RAND_bytes((unsigned char *)&rnd, bytes);
181 		clock_gettime(CLOCK_REALTIME, &stop);
182 		sec = (stop.tv_sec-start.tv_sec);
183 		nanos = sec*BILLION + (stop.tv_nsec-start.tv_nsec);
184 		if (nanos < fastest) {
185 			fastest = nanos;
186 		}
187 	}
188 
189 	if (BATCHSIZE != err) {
190 		printf("## do_fast_bytes: troubles from RAND_bytes, %d\n",
191 			BATCHSIZE-err);
192 		exit(1);
193 	}
194 
195 	return fastest;
196 }
197 
198 #if (OPENSSL_VERSION_NUMBER > 0x1010100fL)
do_fast_priv(unsigned bytes)199 static int do_fast_priv(unsigned bytes) {
200 	int err = 0;
201 	struct timespec start, stop;
202 	uint64_t sec, nanos, fastest = 999999999;
203 	unsigned char rnd[512];
204 
205 	if (bytes > sizeof(rnd)) {
206 		printf("## do_fast_priv - too big\n");
207 		exit(1);
208 	}
209 
210 	for (int i = 0; i < BATCHSIZE; i++) {
211                 clock_gettime(CLOCK_REALTIME, &start);
212                 err += RAND_priv_bytes((unsigned char *)&rnd, bytes);
213 		clock_gettime(CLOCK_REALTIME, &stop);
214 		sec = (stop.tv_sec-start.tv_sec);
215 		nanos = sec*BILLION + (stop.tv_nsec-start.tv_nsec);
216 		if (nanos < fastest) {
217 			fastest = nanos;
218 		}
219 	}
220 
221 	if (BATCHSIZE != err) {
222 		printf("## do_fast_priv: troubles from RAND_bytes, %d\n",
223 			BATCHSIZE-err);
224 		exit(1);
225 	}
226 
227 	return fastest;
228 }
229 #endif
230 
do_bytes(int bytes)231 static void do_bytes(int bytes) {
232 	int average = do_avg_bytes(bytes);
233 	int fastest = do_fast_bytes(bytes);
234 	printf("RAND_bytes():      %5d %8d %4d\n", average, fastest, bytes);
235 	fflush(stdout);
236 }
237 
238 #if (OPENSSL_VERSION_NUMBER > 0x1010100fL)
do_priv(int bytes)239 static void do_priv(int bytes) {
240 	int average = do_avg_priv(bytes);
241 	int fastest = do_fast_priv(bytes);
242 	printf("RAND_priv_bytes(): %5d %8d %4d\n", average, fastest, bytes);
243 	fflush(stdout);
244 }
245 #endif
246 
main(int argc,char * argv[])247 int main(int argc, char *argv[]) {
248 	int average, fastest;
249 
250 	(void)argc;  /* Squash unused warnings */
251 	(void)argv;
252 
253 	printf("Running on %s\n", OPENSSL_VERSION_TEXT);
254 	printf(" times in ns         avg  fastest  lng\n");
255 
256 	average = getpid_average();
257 	printf("getpid():          %5d            (simple kernel call)\n",
258 		average);
259 
260 	average = clock_average();
261 	printf("clock_gettime:     %5d            (overhead of fastest)\n",
262 		average);
263 
264 	average = do_average();
265 	fastest = do_fastest();
266 	printf("random():          %5d %8d\n", average, fastest);
267 	fflush(stdout);
268 
269 	do_bytes(4);
270 	do_bytes(16);
271 	do_bytes(32);
272 	do_bytes(160);
273 	do_bytes(320);
274 
275 #if (OPENSSL_VERSION_NUMBER > 0x1010100fL)
276 	do_priv(4);
277 	do_priv(16);
278 	do_priv(32);
279 	do_priv(160);
280 	do_priv(320);
281 #endif
282 
283 	return 0;
284 
285 }
286 
287