Document default section and library configuration
[openssl.git] / apps / speed.c
index 5a1d92b43c75d0525735c5f93fb0bce07bde7193..1fef0d31c0bf4aa1a0ed1309951b7efa941e722a 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -7,23 +8,8 @@
  * https://www.openssl.org/source/license.html
  */
 
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * The ECDH and ECDSA speed test software is originally written by
- * Sumit Gupta of Sun Microsystems Laboratories.
- *
- */
-
 #undef SECONDS
 #define SECONDS                 3
-#define PRIME_SECONDS   10
 #define RSA_SECONDS             10
 #define DSA_SECONDS             10
 #define ECDSA_SECONDS   10
 
 #define ALGOR_NUM       30
 #define SIZE_NUM        6
-#define PRIME_NUM       3
 #define RSA_NUM         7
 #define DSA_NUM         3
 
@@ -144,9 +129,6 @@ static volatile int run = 0;
 static int mr = 0;
 static int usertime = 1;
 
-typedef void *(*kdf_fn) (const void *in, size_t inlen, void *out,
-                         size_t *xoutlen);
-
 typedef struct loopargs_st {
     ASYNC_JOB *inprogress_job;
     ASYNC_WAIT_CTX *wait_ctx;
@@ -167,7 +149,6 @@ typedef struct loopargs_st {
     unsigned char *secret_a;
     unsigned char *secret_b;
     size_t outlen[EC_NUM];
-    kdf_fn kdf;
 #endif
     EVP_CIPHER_CTX *ctx;
     HMAC_CTX *hctx;
@@ -264,11 +245,6 @@ static double ecdsa_results[EC_NUM][2];
 static double ecdh_results[EC_NUM][1];
 #endif
 
-#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
-static const char rnd_seed[] =
-    "string to make the random number generator think it has entropy";
-#endif
-
 #ifdef SIGALRM
 # if defined(__STDC__) || defined(sgi) || defined(_AIX)
 #  define SIGRETTYPE void
@@ -292,7 +268,8 @@ static SIGRETTYPE sig_done(int sig)
 # if !defined(SIGALRM)
 #  define SIGALRM
 # endif
-static unsigned int lapse, schlock;
+static unsigned int lapse;
+static volatile unsigned int schlock;
 static void alarm_win32(unsigned int secs)
 {
     lapse = secs * 1000;
@@ -359,7 +336,7 @@ static int found(const char *name, const OPT_PAIR *pairs, int *result)
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
-    OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS
+    OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS speed_options[] = {
@@ -382,6 +359,7 @@ const OPTIONS speed_options[] = {
     {"async_jobs", OPT_ASYNCJOBS, 'p',
      "Enable async mode and start pnum jobs"},
 #endif
+    OPT_R_OPTIONS,
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
@@ -1040,11 +1018,8 @@ static int ECDH_EVP_derive_key_loop(void *args)
     size_t *outlen = &(tempargs->outlen[testnum]);
 
     for (count = 0; COND(ecdh_c[testnum][0]); count++)
-        if (EVP_PKEY_derive(ctx, derived_secret, outlen) <= 0) {
-            BIO_printf(bio_err, "ECDH EVP_PKEY_derive failure\n");
-            ERR_print_errors(bio_err);
-            break;
-        }
+        EVP_PKEY_derive(ctx, derived_secret, outlen);
+
     return count;
 }
 
@@ -1221,7 +1196,7 @@ int speed_main(int argc, char **argv)
 #ifndef NO_FORK
     int multi = 0;
 #endif
-    int async_jobs = 0;
+    unsigned int async_jobs = 0;
 #if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \
     || !defined(OPENSSL_NO_EC)
     long rsa_count = 1;
@@ -1364,6 +1339,7 @@ int speed_main(int argc, char **argv)
             usertime = 0;
             break;
         case OPT_EVP:
+            evp_md = NULL;
             evp_cipher = EVP_get_cipherbyname(opt_arg());
             if (evp_cipher == NULL)
                 evp_md = EVP_get_digestbyname(opt_arg());
@@ -1400,6 +1376,12 @@ int speed_main(int argc, char **argv)
                            prog);
                 goto opterr;
             }
+            if (async_jobs > 99999) {
+                BIO_printf(bio_err,
+                           "%s: too many async_jobs\n",
+                           prog);
+                goto opterr;
+            }
 #endif
             break;
         case OPT_MISALIGN:
@@ -1423,6 +1405,10 @@ int speed_main(int argc, char **argv)
             goto end;
 #endif
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -1445,12 +1431,8 @@ int speed_main(int argc, char **argv)
             continue;
         }
 #ifndef OPENSSL_NO_RSA
-# ifndef RSA_NULL
-        if (strcmp(*argv, "openssl") == 0) {
-            RSA_set_default_method(RSA_PKCS1_OpenSSL());
+        if (strcmp(*argv, "openssl") == 0)
             continue;
-        }
-# endif
         if (strcmp(*argv, "rsa") == 0) {
             rsa_doit[R_RSA_512] = rsa_doit[R_RSA_1024] =
                 rsa_doit[R_RSA_2048] = rsa_doit[R_RSA_3072] =
@@ -1599,9 +1581,9 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_DSA
     for (i = 0; i < loopargs_len; i++) {
-        loopargs[i].dsa_key[0] = get_dsa512();
-        loopargs[i].dsa_key[1] = get_dsa1024();
-        loopargs[i].dsa_key[2] = get_dsa2048();
+        loopargs[i].dsa_key[0] = get_dsa(512);
+        loopargs[i].dsa_key[1] = get_dsa(1024);
+        loopargs[i].dsa_key[2] = get_dsa(2048);
     }
 #endif
 #ifndef OPENSSL_NO_DES
@@ -2281,7 +2263,6 @@ int speed_main(int argc, char **argv)
 #endif
 
     if (doit[D_EVP]) {
-#ifdef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
         if (multiblock && evp_cipher) {
             if (!
                 (EVP_CIPHER_flags(evp_cipher) &
@@ -2298,7 +2279,6 @@ int speed_main(int argc, char **argv)
             ret = 0;
             goto end;
         }
-#endif
         for (testnum = 0; testnum < SIZE_NUM; testnum++) {
             if (evp_cipher) {
 
@@ -2369,7 +2349,7 @@ int speed_main(int argc, char **argv)
                        mr ? "+R1:%ld:%d:%.2f\n"
                        : "%ld %d bit private RSA's in %.2fs\n",
                        count, rsa_bits[testnum], d);
-            rsa_results[testnum][0] = d / (double)count;
+            rsa_results[testnum][0] = (double)count / d;
             rsa_count = count;
         }
 
@@ -2395,7 +2375,7 @@ int speed_main(int argc, char **argv)
                        mr ? "+R2:%ld:%d:%.2f\n"
                        : "%ld %d bit public RSA's in %.2fs\n",
                        count, rsa_bits[testnum], d);
-            rsa_results[testnum][1] = d / (double)count;
+            rsa_results[testnum][1] = (double)count / d;
         }
 
         if (rsa_count <= 1) {
@@ -2410,9 +2390,6 @@ int speed_main(int argc, char **argv)
         RAND_bytes(loopargs[i].buf, 36);
 
 #ifndef OPENSSL_NO_DSA
-    if (RAND_status() != 1) {
-        RAND_seed(rnd_seed, sizeof rnd_seed);
-    }
     for (testnum = 0; testnum < DSA_NUM; testnum++) {
         int st = 0;
         if (!dsa_doit[testnum])
@@ -2442,7 +2419,7 @@ int speed_main(int argc, char **argv)
                        mr ? "+R3:%ld:%d:%.2f\n"
                        : "%ld %d bit DSA signs in %.2fs\n",
                        count, dsa_bits[testnum], d);
-            dsa_results[testnum][0] = d / (double)count;
+            dsa_results[testnum][0] = (double)count / d;
             rsa_count = count;
         }
 
@@ -2468,7 +2445,7 @@ int speed_main(int argc, char **argv)
                        mr ? "+R4:%ld:%d:%.2f\n"
                        : "%ld %d bit DSA verify in %.2fs\n",
                        count, dsa_bits[testnum], d);
-            dsa_results[testnum][1] = d / (double)count;
+            dsa_results[testnum][1] = (double)count / d;
         }
 
         if (rsa_count <= 1) {
@@ -2480,9 +2457,6 @@ int speed_main(int argc, char **argv)
 #endif                          /* OPENSSL_NO_DSA */
 
 #ifndef OPENSSL_NO_EC
-    if (RAND_status() != 1) {
-        RAND_seed(rnd_seed, sizeof rnd_seed);
-    }
     for (testnum = 0; testnum < EC_NUM; testnum++) {
         int st = 1;
 
@@ -2528,7 +2502,7 @@ int speed_main(int argc, char **argv)
                            mr ? "+R5:%ld:%d:%.2f\n" :
                            "%ld %d bit ECDSA signs in %.2fs \n",
                            count, test_curves_bits[testnum], d);
-                ecdsa_results[testnum][0] = d / (double)count;
+                ecdsa_results[testnum][0] = (double)count / d;
                 rsa_count = count;
             }
 
@@ -2556,7 +2530,7 @@ int speed_main(int argc, char **argv)
                            mr ? "+R6:%ld:%d:%.2f\n"
                            : "%ld %d bit ECDSA verify in %.2fs\n",
                            count, test_curves_bits[testnum], d);
-                ecdsa_results[testnum][1] = d / (double)count;
+                ecdsa_results[testnum][1] = (double)count / d;
             }
 
             if (rsa_count <= 1) {
@@ -2567,9 +2541,6 @@ int speed_main(int argc, char **argv)
         }
     }
 
-    if (RAND_status() != 1) {
-        RAND_seed(rnd_seed, sizeof rnd_seed);
-    }
     for (testnum = 0; testnum < EC_NUM; testnum++) {
         int ecdh_checks = 1;
 
@@ -2578,17 +2549,50 @@ int speed_main(int argc, char **argv)
 
         for (i = 0; i < loopargs_len; i++) {
             EVP_PKEY_CTX *kctx = NULL;
+            EVP_PKEY_CTX *test_ctx = NULL;
             EVP_PKEY_CTX *ctx = NULL;
             EVP_PKEY *key_A = NULL;
             EVP_PKEY *key_B = NULL;
             size_t outlen;
+            size_t test_outlen;
 
-            if (testnum == R_EC_X25519) {
-                kctx = EVP_PKEY_CTX_new_id(test_curves[testnum], NULL); /* keygen ctx from NID */
-            } else {
+            /* Ensure that the error queue is empty */
+            if (ERR_peek_error()) {
+                BIO_printf(bio_err,
+                           "WARNING: the error queue contains previous unhandled errors.\n");
+                ERR_print_errors(bio_err);
+            }
+
+            /* Let's try to create a ctx directly from the NID: this works for
+             * curves like Curve25519 that are not implemented through the low
+             * level EC interface.
+             * If this fails we try creating a EVP_PKEY_EC generic param ctx,
+             * then we set the curve by NID before deriving the actual keygen
+             * ctx for that specific curve. */
+            kctx = EVP_PKEY_CTX_new_id(test_curves[testnum], NULL); /* keygen ctx from NID */
+            if (!kctx) {
                 EVP_PKEY_CTX *pctx = NULL;
                 EVP_PKEY *params = NULL;
 
+                /* If we reach this code EVP_PKEY_CTX_new_id() failed and a
+                 * "int_ctx_new:unsupported algorithm" error was added to the
+                 * error queue.
+                 * We remove it from the error queue as we are handling it. */
+                unsigned long error = ERR_peek_error(); /* peek the latest error in the queue */
+                if (error == ERR_peek_last_error() && /* oldest and latest errors match */
+                    /* check that the error origin matches */
+                    ERR_GET_LIB(error) == ERR_LIB_EVP &&
+                    ERR_GET_FUNC(error) == EVP_F_INT_CTX_NEW &&
+                    ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM)
+                    ERR_get_error(); /* pop error from queue */
+                if (ERR_peek_error()) {
+                    BIO_printf(bio_err,
+                               "Unhandled error in the error queue during ECDH init.\n");
+                    ERR_print_errors(bio_err);
+                    rsa_count = 1;
+                    break;
+                }
+
                 if (            /* Create the context for parameter generation */
                        !(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) ||
                        /* Initialise the parameter generation */
@@ -2600,7 +2604,7 @@ int speed_main(int argc, char **argv)
                        /* Create the parameter object params */
                        !EVP_PKEY_paramgen(pctx, &params)) {
                     ecdh_checks = 0;
-                    BIO_printf(bio_err, "ECDH init failure.\n");
+                    BIO_printf(bio_err, "ECDH EC params init failure.\n");
                     ERR_print_errors(bio_err);
                     rsa_count = 1;
                     break;
@@ -2613,7 +2617,7 @@ int speed_main(int argc, char **argv)
                 EVP_PKEY_CTX_free(pctx);
                 pctx = NULL;
             }
-            if (!kctx ||        /* keygen ctx is not null */
+            if (kctx == NULL ||      /* keygen ctx is not null */
                 !EVP_PKEY_keygen_init(kctx) /* init keygen ctx */ ) {
                 ecdh_checks = 0;
                 BIO_printf(bio_err, "ECDH keygen failure.\n");
@@ -2628,6 +2632,7 @@ int speed_main(int argc, char **argv)
                 !EVP_PKEY_derive_init(ctx) || /* init derivation ctx */
                 !EVP_PKEY_derive_set_peer(ctx, key_B) || /* set peer pubkey in ctx */
                 !EVP_PKEY_derive(ctx, NULL, &outlen) || /* determine max length */
+                outlen == 0 ||  /* ensure outlen is a valid size */
                 outlen > MAX_ECDH_SIZE /* avoid buffer overflow */ ) {
                 ecdh_checks = 0;
                 BIO_printf(bio_err, "ECDH key generation failure.\n");
@@ -2636,11 +2641,41 @@ int speed_main(int argc, char **argv)
                 break;
             }
 
+            /* Here we perform a test run, comparing the output of a*B and b*A;
+             * we try this here and assume that further EVP_PKEY_derive calls
+             * never fail, so we can skip checks in the actually benchmarked
+             * code, for maximum performance. */
+            if (!(test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) || /* test ctx from skeyB */
+                !EVP_PKEY_derive_init(test_ctx) || /* init derivation test_ctx */
+                !EVP_PKEY_derive_set_peer(test_ctx, key_A) || /* set peer pubkey in test_ctx */
+                !EVP_PKEY_derive(test_ctx, NULL, &test_outlen) || /* determine max length */
+                !EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) || /* compute a*B */
+                !EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) || /* compute b*A */
+                test_outlen != outlen /* compare output length */ ) {
+                ecdh_checks = 0;
+                BIO_printf(bio_err, "ECDH computation failure.\n");
+                ERR_print_errors(bio_err);
+                rsa_count = 1;
+                break;
+            }
+
+            /* Compare the computation results: CRYPTO_memcmp() returns 0 if equal */
+            if (CRYPTO_memcmp(loopargs[i].secret_a,
+                              loopargs[i].secret_b, outlen)) {
+                ecdh_checks = 0;
+                BIO_printf(bio_err, "ECDH computations don't match.\n");
+                ERR_print_errors(bio_err);
+                rsa_count = 1;
+                break;
+            }
+
             loopargs[i].ecdh_ctx[testnum] = ctx;
             loopargs[i].outlen[testnum] = outlen;
 
             EVP_PKEY_CTX_free(kctx);
             kctx = NULL;
+            EVP_PKEY_CTX_free(test_ctx);
+            test_ctx = NULL;
         }
         if (ecdh_checks != 0) {
             pkey_print_message("", "ecdh",
@@ -2654,7 +2689,7 @@ int speed_main(int argc, char **argv)
                        mr ? "+R7:%ld:%d:%.2f\n" :
                        "%ld %d-bit ECDH ops in %.2fs\n", count,
                        test_curves_bits[testnum], d);
-            ecdh_results[testnum][0] = d / (double)count;
+            ecdh_results[testnum][0] = (double)count / d;
             rsa_count = count;
         }
 
@@ -2734,8 +2769,8 @@ int speed_main(int argc, char **argv)
                    k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]);
         else
             printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
-                   rsa_bits[k], rsa_results[k][0], rsa_results[k][1],
-                   1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1]);
+                   rsa_bits[k], 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1],
+                   rsa_results[k][0], rsa_results[k][1]);
     }
 #endif
 #ifndef OPENSSL_NO_DSA
@@ -2752,8 +2787,8 @@ int speed_main(int argc, char **argv)
                    k, dsa_bits[k], dsa_results[k][0], dsa_results[k][1]);
         else
             printf("dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
-                   dsa_bits[k], dsa_results[k][0], dsa_results[k][1],
-                   1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1]);
+                   dsa_bits[k], 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1],
+                   dsa_results[k][0], dsa_results[k][1]);
     }
 #endif
 #ifndef OPENSSL_NO_EC
@@ -2774,8 +2809,8 @@ int speed_main(int argc, char **argv)
             printf("%4u bit ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
                    test_curves_bits[k],
                    test_curves_names[k],
-                   ecdsa_results[k][0], ecdsa_results[k][1],
-                   1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1]);
+                   1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1],
+                   ecdsa_results[k][0], ecdsa_results[k][1]);
     }
 
     testnum = 1;
@@ -2795,7 +2830,7 @@ int speed_main(int argc, char **argv)
             printf("%4u bit ecdh (%s) %8.4fs %8.1f\n",
                    test_curves_bits[k],
                    test_curves_names[k],
-                   ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
+                   1.0 / ecdh_results[k][0], ecdh_results[k][0]);
     }
 #endif
 
@@ -2982,16 +3017,10 @@ static int do_multi(int multi)
                 sstrsep(&p, sep);
 
                 d = atof(sstrsep(&p, sep));
-                if (n)
-                    rsa_results[k][0] = 1 / (1 / rsa_results[k][0] + 1 / d);
-                else
-                    rsa_results[k][0] = d;
+                rsa_results[k][0] += d;
 
                 d = atof(sstrsep(&p, sep));
-                if (n)
-                    rsa_results[k][1] = 1 / (1 / rsa_results[k][1] + 1 / d);
-                else
-                    rsa_results[k][1] = d;
+                rsa_results[k][1] += d;
             }
 # ifndef OPENSSL_NO_DSA
             else if (strncmp(buf, "+F3:", 4) == 0) {
@@ -3003,16 +3032,10 @@ static int do_multi(int multi)
                 sstrsep(&p, sep);
 
                 d = atof(sstrsep(&p, sep));
-                if (n)
-                    dsa_results[k][0] = 1 / (1 / dsa_results[k][0] + 1 / d);
-                else
-                    dsa_results[k][0] = d;
+                dsa_results[k][0] += d;
 
                 d = atof(sstrsep(&p, sep));
-                if (n)
-                    dsa_results[k][1] = 1 / (1 / dsa_results[k][1] + 1 / d);
-                else
-                    dsa_results[k][1] = d;
+                dsa_results[k][1] += d;
             }
 # endif
 # ifndef OPENSSL_NO_EC
@@ -3025,16 +3048,10 @@ static int do_multi(int multi)
                 sstrsep(&p, sep);
 
                 d = atof(sstrsep(&p, sep));
-                if (n)
-                    ecdsa_results[k][0] = 1 / (1 / ecdsa_results[k][0] + 1 / d);
-                else
-                    ecdsa_results[k][0] = d;
+                ecdsa_results[k][0] += d;
 
                 d = atof(sstrsep(&p, sep));
-                if (n)
-                    ecdsa_results[k][1] = 1 / (1 / ecdsa_results[k][1] + 1 / d);
-                else
-                    ecdsa_results[k][1] = d;
+                ecdsa_results[k][1] += d;
             } else if (strncmp(buf, "+F5:", 4) == 0) {
                 int k;
                 double d;
@@ -3044,11 +3061,7 @@ static int do_multi(int multi)
                 sstrsep(&p, sep);
 
                 d = atof(sstrsep(&p, sep));
-                if (n)
-                    ecdh_results[k][0] = 1 / (1 / ecdh_results[k][0] + 1 / d);
-                else
-                    ecdh_results[k][0] = d;
-
+                ecdh_results[k][0] += d;
             }
 # endif