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 #ifndef _WIN32
14 # include <sys/stat.h>
15 # include <openssl/pem.h>
16 # include <openssl/x509.h>
17 # include <openssl/err.h>
18 # include <openssl/bio.h>
19 # include <../include/internal/e_os.h>
20 # if defined(OPENSSL_SYS_UNIX)
21 # include <sys/resource.h>
22 # endif
23
24 static char *prog;
25
readx509(const char * contents,int size)26 static void readx509(const char *contents, int size)
27 {
28 X509 *x = NULL;
29 BIO *b = BIO_new_mem_buf(contents, size);
30
31 if (b == NULL) {
32 ERR_print_errors_fp(stderr);
33 exit(EXIT_FAILURE);
34 }
35 PEM_read_bio_X509(b, &x, 0, NULL);
36 if (x == NULL) {
37 ERR_print_errors_fp(stderr);
38 exit(EXIT_FAILURE);
39 }
40 X509_free(x);
41 BIO_free(b);
42 }
43
readpkey(const char * contents,int size)44 static void readpkey(const char *contents, int size)
45 {
46 BIO *b = BIO_new_mem_buf(contents, size);
47 EVP_PKEY *pkey;
48
49 if (b == NULL) {
50 ERR_print_errors_fp(stderr);
51 exit(EXIT_FAILURE);
52 }
53 pkey = PEM_read_bio_PrivateKey(b, NULL, NULL, NULL);
54 if (pkey == NULL) {
55 ERR_print_errors_fp(stderr);
56 exit(EXIT_FAILURE);
57 }
58
59 EVP_PKEY_free(pkey);
60 BIO_free(b);
61 }
62
print_timeval(const char * what,struct timeval * tp)63 static void print_timeval(const char *what, struct timeval *tp)
64 {
65 printf("%s %d sec %d microsec\n", what, (int)tp->tv_sec, (int)tp->tv_usec);
66 }
67
usage(void)68 static void usage(void)
69 {
70 fprintf(stderr, "Usage: %s [flags] pem-file\n", prog);
71 fprintf(stderr, "Flags, with the default being '-wc':\n");
72 fprintf(stderr, " -c # Repeat count\n");
73 fprintf(stderr, " -d Debugging output (minimal)\n");
74 fprintf(stderr, " -w<T> What to load T is a single character:\n");
75 fprintf(stderr, " c for cert\n");
76 fprintf(stderr, " p for private key\n");
77 exit(EXIT_FAILURE);
78 }
79 #endif
80
main(int ac,char ** av)81 int main(int ac, char **av)
82 {
83 #ifndef _WIN32
84 int i, debug = 0, count = 100, what = 'c';
85 struct stat sb;
86 FILE *fp;
87 char *contents;
88 struct rusage start, end, elapsed;
89 struct timeval e_start, e_end, e_elapsed;
90
91 /* Parse JCL. */
92 prog = av[0];
93 while ((i = getopt(ac, av, "c:dw:")) != EOF) {
94 switch (i) {
95 default:
96 usage();
97 break;
98 case 'c':
99 if ((count = atoi(optarg)) < 0)
100 usage();
101 break;
102 case 'd':
103 debug = 1;
104 break;
105 case 'w':
106 if (optarg[1] != '\0')
107 usage();
108 switch (*optarg) {
109 default:
110 usage();
111 break;
112 case 'c':
113 case 'p':
114 what = *optarg;
115 break;
116 }
117 break;
118 }
119 }
120 ac -= optind;
121 av += optind;
122
123 /* Read input file. */
124 if (av[0] == NULL)
125 usage();
126 if (stat(av[0], &sb) < 0) {
127 perror(av[0]);
128 exit(EXIT_FAILURE);
129 }
130 contents = OPENSSL_malloc(sb.st_size + 1);
131 if (contents == NULL) {
132 perror("malloc");
133 exit(EXIT_FAILURE);
134 }
135 fp = fopen(av[0], "r");
136 if ((long)fread(contents, 1, sb.st_size, fp) != sb.st_size) {
137 perror("fread");
138 exit(EXIT_FAILURE);
139 }
140 contents[sb.st_size] = '\0';
141 fclose(fp);
142 if (debug)
143 printf(">%s<\n", contents);
144
145 /* Try to prep system cache, etc. */
146 for (i = 10; i > 0; i--) {
147 switch (what) {
148 case 'c':
149 readx509(contents, (int)sb.st_size);
150 break;
151 case 'p':
152 readpkey(contents, (int)sb.st_size);
153 break;
154 }
155 }
156
157 if (gettimeofday(&e_start, NULL) < 0) {
158 perror("elapsed start");
159 exit(EXIT_FAILURE);
160 }
161 if (getrusage(RUSAGE_SELF, &start) < 0) {
162 perror("start");
163 exit(EXIT_FAILURE);
164 }
165 for (i = count; i > 0; i--) {
166 switch (what) {
167 case 'c':
168 readx509(contents, (int)sb.st_size);
169 break;
170 case 'p':
171 readpkey(contents, (int)sb.st_size);
172 break;
173 }
174 }
175 if (getrusage(RUSAGE_SELF, &end) < 0) {
176 perror("getrusage");
177 exit(EXIT_FAILURE);
178 }
179 if (gettimeofday(&e_end, NULL) < 0) {
180 perror("gettimeofday");
181 exit(EXIT_FAILURE);
182 }
183
184 timersub(&end.ru_utime, &start.ru_stime, &elapsed.ru_stime);
185 timersub(&end.ru_utime, &start.ru_utime, &elapsed.ru_utime);
186 timersub(&e_end, &e_start, &e_elapsed);
187 print_timeval("user ", &elapsed.ru_utime);
188 print_timeval("sys ", &elapsed.ru_stime);
189 if (debug)
190 print_timeval("elapsed??", &e_elapsed);
191
192 OPENSSL_free(contents);
193 return EXIT_SUCCESS;
194 #else
195 fprintf(stderr, "This tool is not supported on Windows\n");
196 exit(EXIT_FAILURE);
197 #endif
198 }
199