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 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 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 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 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 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