xref: /openssl/test/timing_load_creds.c (revision adf289b5)
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