Home | History | Annotate | Line # | Download | only in test
      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 #if !defined(RUSAGE_SELF) && defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
     98 #include <sys/times.h>
     99 #endif
    100 
    101 int main(int ac, char **av)
    102 {
    103 #if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
    104     int i, debug = 0, count = 100, what = 'c';
    105     struct stat sb;
    106     FILE *fp;
    107     char *contents;
    108 #if !defined(RUSAGE_SELF)
    109     struct tms rus;
    110     struct timeval u_start, u_end, u_elapsed;
    111     struct timeval s_start, s_end, s_elapsed;
    112 #else
    113     struct rusage start, end, elapsed;
    114 #endif
    115     struct timeval e_start, e_end, e_elapsed;
    116 
    117     /* Parse JCL. */
    118     prog = av[0];
    119     while ((i = getopt(ac, av, "c:dw:")) != EOF) {
    120         switch (i) {
    121         default:
    122             usage();
    123             break;
    124         case 'c':
    125             if ((count = atoi(optarg)) < 0)
    126                 usage();
    127             break;
    128         case 'd':
    129             debug = 1;
    130             break;
    131         case 'w':
    132             if (optarg[1] != '\0')
    133                 usage();
    134             switch (*optarg) {
    135             default:
    136                 usage();
    137                 break;
    138             case 'c':
    139             case 'p':
    140                 what = *optarg;
    141                 break;
    142             }
    143             break;
    144         }
    145     }
    146     ac -= optind;
    147     av += optind;
    148 
    149     /* Read input file. */
    150     if (av[0] == NULL)
    151         usage();
    152     if (stat(av[0], &sb) < 0) {
    153         perror(av[0]);
    154         exit(EXIT_FAILURE);
    155     }
    156     contents = OPENSSL_malloc(sb.st_size + 1);
    157     if (contents == NULL) {
    158         perror("malloc");
    159         exit(EXIT_FAILURE);
    160     }
    161     fp = fopen(av[0], "r");
    162     if ((long)fread(contents, 1, sb.st_size, fp) != sb.st_size) {
    163         perror("fread");
    164         exit(EXIT_FAILURE);
    165     }
    166     contents[sb.st_size] = '\0';
    167     fclose(fp);
    168     if (debug)
    169         printf(">%s<\n", contents);
    170 
    171     /* Try to prep system cache, etc. */
    172     for (i = 10; i > 0; i--) {
    173         switch (what) {
    174         case 'c':
    175             readx509(contents, (int)sb.st_size);
    176             break;
    177         case 'p':
    178             readpkey(contents, (int)sb.st_size);
    179             break;
    180         }
    181     }
    182 
    183     if (gettimeofday(&e_start, NULL) < 0) {
    184         perror("elapsed start");
    185         exit(EXIT_FAILURE);
    186     }
    187 #if !defined(RUSAGE_SELF)
    188     times(&rus);
    189     u_start.tv_sec = rus.tms_utime / CLOCKS_PER_SEC;
    190     u_start.tv_usec = (rus.tms_utime * 1000000) / CLOCKS_PER_SEC;
    191     s_start.tv_sec = rus.tms_stime / CLOCKS_PER_SEC;
    192     s_start.tv_usec = (rus.tms_stime * 1000000) / CLOCKS_PER_SEC;
    193 #else
    194     if (getrusage(RUSAGE_SELF, &start) < 0) {
    195         perror("start");
    196         exit(EXIT_FAILURE);
    197     }
    198 #endif
    199     for (i = count; i > 0; i--) {
    200         switch (what) {
    201         case 'c':
    202             readx509(contents, (int)sb.st_size);
    203             break;
    204         case 'p':
    205             readpkey(contents, (int)sb.st_size);
    206             break;
    207         }
    208     }
    209 #if !defined(RUSAGE_SELF)
    210     times(&rus);
    211     u_end.tv_sec = rus.tms_utime / CLOCKS_PER_SEC;
    212     u_end.tv_usec = (rus.tms_utime * 1000000) / CLOCKS_PER_SEC;
    213     s_end.tv_sec = rus.tms_stime / CLOCKS_PER_SEC;
    214     s_end.tv_usec = (rus.tms_stime * 1000000) / CLOCKS_PER_SEC;
    215 #else
    216     if (getrusage(RUSAGE_SELF, &end) < 0) {
    217         perror("getrusage");
    218         exit(EXIT_FAILURE);
    219     }
    220 #endif
    221     if (gettimeofday(&e_end, NULL) < 0) {
    222         perror("gettimeofday");
    223         exit(EXIT_FAILURE);
    224     }
    225 
    226 #if !defined(RUSAGE_SELF)
    227     timersub(&u_end, &u_start, &u_elapsed);
    228     timersub(&s_end, &s_start, &s_elapsed);
    229 #else
    230     timersub(&end.ru_utime, &start.ru_stime, &elapsed.ru_stime);
    231     timersub(&end.ru_utime, &start.ru_utime, &elapsed.ru_utime);
    232 #endif
    233     timersub(&e_end, &e_start, &e_elapsed);
    234 #if !defined(RUSAGE_SELF)
    235     print_timeval("user     ", &u_elapsed);
    236     print_timeval("sys      ", &s_elapsed);
    237 #else
    238     print_timeval("user     ", &elapsed.ru_utime);
    239     print_timeval("sys      ", &elapsed.ru_stime);
    240 #endif
    241     if (debug)
    242         print_timeval("elapsed??", &e_elapsed);
    243 
    244     OPENSSL_free(contents);
    245     return EXIT_SUCCESS;
    246 #else
    247     fprintf(stderr,
    248         "This tool is not supported on this platform for lack of POSIX1.2001 support\n");
    249     exit(EXIT_FAILURE);
    250 #endif
    251 }
    252