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