1 /*
2 * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12
13 #include <openssl/e_os2.h>
14
15 #ifdef OPENSSL_SYS_UNIX
16 # include <sys/stat.h>
17 # include <sys/resource.h>
18 # include <openssl/pem.h>
19 # include <openssl/x509.h>
20 # include <openssl/err.h>
21 # include <openssl/bio.h>
22 # include "internal/e_os.h"
23 # if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
24
25 # ifndef timersub
26 /* struct timeval * subtraction; a must be greater than or equal to b */
27 # define timersub(a, b, res) \
28 do { \
29 (res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
30 if ((a)->tv_usec < (b)->tv_usec) { \
31 (res)->tv_usec = (a)->tv_usec + 1000000 - (b)->tv_usec; \
32 --(res)->tv_sec; \
33 } else { \
34 (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
35 } \
36 } while(0)
37 # endif
38
39 static char *prog;
40
readx509(const char * contents,int size)41 static void readx509(const char *contents, int size)
42 {
43 X509 *x = NULL;
44 BIO *b = BIO_new_mem_buf(contents, size);
45
46 if (b == NULL) {
47 ERR_print_errors_fp(stderr);
48 exit(EXIT_FAILURE);
49 }
50 PEM_read_bio_X509(b, &x, 0, NULL);
51 if (x == NULL) {
52 ERR_print_errors_fp(stderr);
53 exit(EXIT_FAILURE);
54 }
55 X509_free(x);
56 BIO_free(b);
57 }
58
readpkey(const char * contents,int size)59 static void readpkey(const char *contents, int size)
60 {
61 BIO *b = BIO_new_mem_buf(contents, size);
62 EVP_PKEY *pkey;
63
64 if (b == NULL) {
65 ERR_print_errors_fp(stderr);
66 exit(EXIT_FAILURE);
67 }
68 pkey = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
69 if (pkey == NULL) {
70 ERR_print_errors_fp(stderr);
71 exit(EXIT_FAILURE);
72 }
73
74 EVP_PKEY_free(pkey);
75 BIO_free(b);
76 }
77
print_timeval(const char * what,struct timeval * tp)78 static void print_timeval(const char *what, struct timeval *tp)
79 {
80 printf("%s %d sec %d microsec\n", what, (int)tp->tv_sec, (int)tp->tv_usec);
81 }
82
usage(void)83 static void usage(void)
84 {
85 fprintf(stderr, "Usage: %s [flags] pem-file\n", prog);
86 fprintf(stderr, "Flags, with the default being '-wc':\n");
87 fprintf(stderr, " -c # Repeat count\n");
88 fprintf(stderr, " -d Debugging output (minimal)\n");
89 fprintf(stderr, " -w<T> What to load T is a single character:\n");
90 fprintf(stderr, " c for cert\n");
91 fprintf(stderr, " p for private key\n");
92 exit(EXIT_FAILURE);
93 }
94 # endif
95 #endif
96
main(int ac,char ** av)97 int main(int ac, char **av)
98 {
99 #if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
100 int i, debug = 0, count = 100, what = 'c';
101 struct stat sb;
102 FILE *fp;
103 char *contents;
104 struct rusage start, end, elapsed;
105 struct timeval e_start, e_end, e_elapsed;
106
107 /* Parse JCL. */
108 prog = av[0];
109 while ((i = getopt(ac, av, "c:dw:")) != EOF) {
110 switch (i) {
111 default:
112 usage();
113 break;
114 case 'c':
115 if ((count = atoi(optarg)) < 0)
116 usage();
117 break;
118 case 'd':
119 debug = 1;
120 break;
121 case 'w':
122 if (optarg[1] != '\0')
123 usage();
124 switch (*optarg) {
125 default:
126 usage();
127 break;
128 case 'c':
129 case 'p':
130 what = *optarg;
131 break;
132 }
133 break;
134 }
135 }
136 ac -= optind;
137 av += optind;
138
139 /* Read input file. */
140 if (av[0] == NULL)
141 usage();
142 if (stat(av[0], &sb) < 0) {
143 perror(av[0]);
144 exit(EXIT_FAILURE);
145 }
146 contents = OPENSSL_malloc(sb.st_size + 1);
147 if (contents == NULL) {
148 perror("malloc");
149 exit(EXIT_FAILURE);
150 }
151 fp = fopen(av[0], "r");
152 if ((long)fread(contents, 1, sb.st_size, fp) != sb.st_size) {
153 perror("fread");
154 exit(EXIT_FAILURE);
155 }
156 contents[sb.st_size] = '\0';
157 fclose(fp);
158 if (debug)
159 printf(">%s<\n", contents);
160
161 /* Try to prep system cache, etc. */
162 for (i = 10; i > 0; i--) {
163 switch (what) {
164 case 'c':
165 readx509(contents, (int)sb.st_size);
166 break;
167 case 'p':
168 readpkey(contents, (int)sb.st_size);
169 break;
170 }
171 }
172
173 if (gettimeofday(&e_start, NULL) < 0) {
174 perror("elapsed start");
175 exit(EXIT_FAILURE);
176 }
177 if (getrusage(RUSAGE_SELF, &start) < 0) {
178 perror("start");
179 exit(EXIT_FAILURE);
180 }
181 for (i = count; i > 0; i--) {
182 switch (what) {
183 case 'c':
184 readx509(contents, (int)sb.st_size);
185 break;
186 case 'p':
187 readpkey(contents, (int)sb.st_size);
188 break;
189 }
190 }
191 if (getrusage(RUSAGE_SELF, &end) < 0) {
192 perror("getrusage");
193 exit(EXIT_FAILURE);
194 }
195 if (gettimeofday(&e_end, NULL) < 0) {
196 perror("gettimeofday");
197 exit(EXIT_FAILURE);
198 }
199
200 timersub(&end.ru_utime, &start.ru_stime, &elapsed.ru_stime);
201 timersub(&end.ru_utime, &start.ru_utime, &elapsed.ru_utime);
202 timersub(&e_end, &e_start, &e_elapsed);
203 print_timeval("user ", &elapsed.ru_utime);
204 print_timeval("sys ", &elapsed.ru_stime);
205 if (debug)
206 print_timeval("elapsed??", &e_elapsed);
207
208 OPENSSL_free(contents);
209 return EXIT_SUCCESS;
210 #else
211 fprintf(stderr,
212 "This tool is not supported on this platform for lack of POSIX1.2001 support\n");
213 exit(EXIT_FAILURE);
214 #endif
215 }
216