openssl s_server: don't use sendto() with connected UDP socket
[openssl.git] / apps / speed.c
index 462e3e7cfe790bb2c35d4896d401a14cceb5e26b..40e990408ab92fa73d5b92c02ad15fb651f3d5b2 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 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,33 +8,20 @@
  * 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 ECDH_SECONDS    10
+#define EdDSA_SECONDS   10
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
 #include "apps.h"
+#include "progs.h"
 #include <openssl/crypto.h>
 #include <openssl/rand.h>
 #include <openssl/err.h>
 # define NO_FORK
 #endif
 
-#undef BUFSIZE
-#define BUFSIZE (1024*16+1)
 #define MAX_MISALIGNMENT 63
-
-#define ALGOR_NUM       30
-#define SIZE_NUM        6
-#define PRIME_NUM       3
-#define RSA_NUM         7
-#define DSA_NUM         3
-
-#define EC_NUM          17
 #define MAX_ECDH_SIZE   256
 #define MISALIGN        64
 
+typedef struct openssl_speed_sec_st {
+    int sym;
+    int rsa;
+    int dsa;
+    int ecdsa;
+    int ecdh;
+    int eddsa;
+} openssl_speed_sec_t;
+
 static volatile int run = 0;
 
 static int mr = 0;
 static int usertime = 1;
 
-typedef struct loopargs_st {
-    ASYNC_JOB *inprogress_job;
-    ASYNC_WAIT_CTX *wait_ctx;
-    unsigned char *buf;
-    unsigned char *buf2;
-    unsigned char *buf_malloc;
-    unsigned char *buf2_malloc;
-    unsigned int siglen;
-#ifndef OPENSSL_NO_RSA
-    RSA *rsa_key[RSA_NUM];
-#endif
-#ifndef OPENSSL_NO_DSA
-    DSA *dsa_key[DSA_NUM];
-#endif
-#ifndef OPENSSL_NO_EC
-    EC_KEY *ecdsa[EC_NUM];
-    EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
-    unsigned char *secret_a;
-    unsigned char *secret_b;
-    size_t outlen[EC_NUM];
-#endif
-    EVP_CIPHER_CTX *ctx;
-    HMAC_CTX *hctx;
-    GCM128_CONTEXT *gcm_ctx;
-} loopargs_t;
-
 #ifndef OPENSSL_NO_MD2
 static int EVP_Digest_MD2_loop(void *args);
 #endif
@@ -207,7 +168,10 @@ static int AES_cbc_256_encrypt_loop(void *args);
 static int AES_ige_192_encrypt_loop(void *args);
 static int AES_ige_256_encrypt_loop(void *args);
 static int CRYPTO_gcm128_aad_loop(void *args);
+static int RAND_bytes_loop(void *args);
 static int EVP_Update_loop(void *args);
+static int EVP_Update_loop_ccm(void *args);
+static int EVP_Update_loop_aead(void *args);
 static int EVP_Digest_loop(void *args);
 #ifndef OPENSSL_NO_RSA
 static int RSA_sign_loop(void *args);
@@ -220,75 +184,53 @@ static int DSA_verify_loop(void *args);
 #ifndef OPENSSL_NO_EC
 static int ECDSA_sign_loop(void *args);
 static int ECDSA_verify_loop(void *args);
+static int EdDSA_sign_loop(void *args);
+static int EdDSA_verify_loop(void *args);
 #endif
-static int run_benchmark(int async_jobs, int (*loop_function) (void *),
-                         loopargs_t * loopargs);
 
 static double Time_F(int s);
-static void print_message(const char *s, long num, int length);
+static void print_message(const char *s, long num, int length, int tm);
 static void pkey_print_message(const char *str, const char *str2,
-                               long num, int bits, int sec);
+                               long num, unsigned int bits, int sec);
 static void print_result(int alg, int run_no, int count, double time_used);
 #ifndef NO_FORK
-static int do_multi(int multi);
+static int do_multi(int multi, int size_num);
 #endif
 
-static const char *names[ALGOR_NUM] = {
-    "md2", "mdc2", "md4", "md5", "hmac(md5)", "sha1", "rmd160", "rc4",
-    "des cbc", "des ede3", "idea cbc", "seed cbc",
-    "rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc",
-    "aes-128 cbc", "aes-192 cbc", "aes-256 cbc",
-    "camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc",
-    "evp", "sha256", "sha512", "whirlpool",
-    "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash"
-};
-
-static double results[ALGOR_NUM][SIZE_NUM];
-
-static const int lengths[SIZE_NUM] = {
+static const int lengths_list[] = {
     16, 64, 256, 1024, 8 * 1024, 16 * 1024
 };
+static const int *lengths = lengths_list;
 
-#ifndef OPENSSL_NO_RSA
-static double rsa_results[RSA_NUM][2];
-#endif
-#ifndef OPENSSL_NO_DSA
-static double dsa_results[DSA_NUM][2];
-#endif
-#ifndef OPENSSL_NO_EC
-static double ecdsa_results[EC_NUM][2];
-static double ecdh_results[EC_NUM][1];
-#endif
+static const int aead_lengths_list[] = {
+    2, 31, 136, 1024, 8 * 1024, 16 * 1024
+};
 
-#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
+#define START   0
+#define STOP    1
 
 #ifdef SIGALRM
-# if defined(__STDC__) || defined(sgi) || defined(_AIX)
-#  define SIGRETTYPE void
-# else
-#  define SIGRETTYPE int
-# endif
 
-static SIGRETTYPE sig_done(int sig);
-static SIGRETTYPE sig_done(int sig)
+static void alarmed(int sig)
 {
-    signal(SIGALRM, sig_done);
+    signal(SIGALRM, alarmed);
     run = 0;
 }
-#endif
 
-#define START   0
-#define STOP    1
+static double Time_F(int s)
+{
+    double ret = app_tminterval(s, usertime);
+    if (s == STOP)
+        alarm(0);
+    return ret;
+}
 
-#if defined(_WIN32)
+#elif defined(_WIN32)
 
-# if !defined(SIGALRM)
-#  define SIGALRM
-# endif
-static unsigned int lapse, schlock;
+# define SIGALRM -1
+
+static unsigned int lapse;
+static volatile unsigned int schlock;
 static void alarm_win32(unsigned int secs)
 {
     lapse = secs * 1000;
@@ -330,21 +272,23 @@ static double Time_F(int s)
     return ret;
 }
 #else
-
 static double Time_F(int s)
 {
-    double ret = app_tminterval(s, usertime);
-    if (s == STOP)
-        alarm(0);
-    return ret;
+    return app_tminterval(s, usertime);
 }
 #endif
 
-static void multiblock_speed(const EVP_CIPHER *evp_cipher);
+static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
+                             const openssl_speed_sec_t *seconds);
 
-static int found(const char *name, const OPT_PAIR *pairs, int *result)
+#define found(value, pairs, result)\
+    opt_found(value, result, pairs, OSSL_NELEM(pairs))
+static int opt_found(const char *name, unsigned int *result,
+                     const OPT_PAIR pairs[], unsigned int nbelem)
 {
-    for (; pairs->name; pairs++)
+    unsigned int idx;
+
+    for (idx = 0; idx < nbelem; ++idx, pairs++)
         if (strcmp(name, pairs->name) == 0) {
             *result = pairs->retval;
             return 1;
@@ -355,33 +299,43 @@ 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,
+    OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD
 } OPTION_CHOICE;
 
 const OPTIONS speed_options[] = {
     {OPT_HELP_STR, 1, '-', "Usage: %s [options] ciphers...\n"},
     {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
     {"help", OPT_HELP, '-', "Display this summary"},
-    {"evp", OPT_EVP, 's', "Use specified EVP cipher"},
+    {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"},
     {"decrypt", OPT_DECRYPT, '-',
      "Time decryption instead of encryption (only EVP)"},
-    {"mr", OPT_MR, '-', "Produce machine readable output"},
+    {"aead", OPT_AEAD, '-',
+     "Benchmark EVP-named AEAD cipher in TLS-like sequence"},
     {"mb", OPT_MB, '-',
-     "Enable (tls1.1) multi-block mode on evp_cipher requested with -evp"},
-    {"misalign", OPT_MISALIGN, 'n', "Amount to mis-align buffers"},
-    {"elapsed", OPT_ELAPSED, '-',
-     "Measure time in real time instead of CPU user time"},
+     "Enable (tls1>=1) multi-block mode on EVP-named cipher"},
+    {"mr", OPT_MR, '-', "Produce machine readable output"},
 #ifndef NO_FORK
     {"multi", OPT_MULTI, 'p', "Run benchmarks in parallel"},
 #endif
 #ifndef OPENSSL_NO_ASYNC
     {"async_jobs", OPT_ASYNCJOBS, 'p',
-     "Enable async mode and start pnum jobs"},
+     "Enable async mode and start specified number of jobs"},
 #endif
+    OPT_R_OPTIONS,
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
-    {NULL},
+    {"elapsed", OPT_ELAPSED, '-',
+     "Use wall-clock time instead of CPU user time as divisor"},
+    {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"},
+    {"seconds", OPT_SECONDS, 'p',
+     "Run benchmarks for specified amount of seconds"},
+    {"bytes", OPT_BYTES, 'p',
+     "Run [non-PKI] benchmarks on custom-sized buffer"},
+    {"misalign", OPT_MISALIGN, 'p',
+     "Use specified offset to mis-align buffers"},
+    {NULL}
 };
 
 #define D_MD2           0
@@ -414,7 +368,22 @@ const OPTIONS speed_options[] = {
 #define D_IGE_192_AES   27
 #define D_IGE_256_AES   28
 #define D_GHASH         29
-static OPT_PAIR doit_choices[] = {
+#define D_RAND          30
+/* name of algorithms to test */
+static const char *names[] = {
+    "md2", "mdc2", "md4", "md5", "hmac(md5)", "sha1", "rmd160", "rc4",
+    "des cbc", "des ede3", "idea cbc", "seed cbc",
+    "rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc",
+    "aes-128 cbc", "aes-192 cbc", "aes-256 cbc",
+    "camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc",
+    "evp", "sha256", "sha512", "whirlpool",
+    "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash",
+    "rand"
+};
+#define ALGOR_NUM       OSSL_NELEM(names)
+
+/* list of configured algorithm (remaining) */
+static const OPT_PAIR doit_choices[] = {
 #ifndef OPENSSL_NO_MD2
     {"md2", D_MD2},
 #endif
@@ -479,20 +448,24 @@ static OPT_PAIR doit_choices[] = {
     {"cast5", D_CBC_CAST},
 #endif
     {"ghash", D_GHASH},
-    {NULL}
+    {"rand", D_RAND}
 };
 
+static double results[ALGOR_NUM][OSSL_NELEM(lengths_list)];
+
 #ifndef OPENSSL_NO_DSA
 # define R_DSA_512       0
 # define R_DSA_1024      1
 # define R_DSA_2048      2
-static OPT_PAIR dsa_choices[] = {
+static const OPT_PAIR dsa_choices[] = {
     {"dsa512", R_DSA_512},
     {"dsa1024", R_DSA_1024},
-    {"dsa2048", R_DSA_2048},
-    {NULL},
+    {"dsa2048", R_DSA_2048}
 };
-#endif
+# define DSA_NUM         OSSL_NELEM(dsa_choices)
+
+static double dsa_results[DSA_NUM][2];  /* 2 ops: sign then verify */
+#endif  /* OPENSSL_NO_DSA */
 
 #define R_RSA_512       0
 #define R_RSA_1024      1
@@ -501,16 +474,20 @@ static OPT_PAIR dsa_choices[] = {
 #define R_RSA_4096      4
 #define R_RSA_7680      5
 #define R_RSA_15360     6
-static OPT_PAIR rsa_choices[] = {
+#ifndef OPENSSL_NO_RSA
+static const OPT_PAIR rsa_choices[] = {
     {"rsa512", R_RSA_512},
     {"rsa1024", R_RSA_1024},
     {"rsa2048", R_RSA_2048},
     {"rsa3072", R_RSA_3072},
     {"rsa4096", R_RSA_4096},
     {"rsa7680", R_RSA_7680},
-    {"rsa15360", R_RSA_15360},
-    {NULL}
+    {"rsa15360", R_RSA_15360}
 };
+# define RSA_NUM OSSL_NELEM(rsa_choices)
+
+static double rsa_results[RSA_NUM][2];  /* 2 ops: sign then verify */
+#endif /* OPENSSL_NO_RSA */
 
 #define R_EC_P160    0
 #define R_EC_P192    1
@@ -528,7 +505,14 @@ static OPT_PAIR rsa_choices[] = {
 #define R_EC_B283    13
 #define R_EC_B409    14
 #define R_EC_B571    15
-#define R_EC_X25519  16
+#define R_EC_BRP256R1  16
+#define R_EC_BRP256T1  17
+#define R_EC_BRP384R1  18
+#define R_EC_BRP384T1  19
+#define R_EC_BRP512R1  20
+#define R_EC_BRP512T1  21
+#define R_EC_X25519  22
+#define R_EC_X448    23
 #ifndef OPENSSL_NO_EC
 static OPT_PAIR ecdsa_choices[] = {
     {"ecdsap160", R_EC_P160},
@@ -547,10 +531,18 @@ static OPT_PAIR ecdsa_choices[] = {
     {"ecdsab283", R_EC_B283},
     {"ecdsab409", R_EC_B409},
     {"ecdsab571", R_EC_B571},
-    {NULL}
+    {"ecdsabrp256r1", R_EC_BRP256R1},
+    {"ecdsabrp256t1", R_EC_BRP256T1},
+    {"ecdsabrp384r1", R_EC_BRP384R1},
+    {"ecdsabrp384t1", R_EC_BRP384T1},
+    {"ecdsabrp512r1", R_EC_BRP512R1},
+    {"ecdsabrp512t1", R_EC_BRP512T1}
 };
+# define ECDSA_NUM       OSSL_NELEM(ecdsa_choices)
+
+static double ecdsa_results[ECDSA_NUM][2];    /* 2 ops: sign then verify */
 
-static OPT_PAIR ecdh_choices[] = {
+static const OPT_PAIR ecdh_choices[] = {
     {"ecdhp160", R_EC_P160},
     {"ecdhp192", R_EC_P192},
     {"ecdhp224", R_EC_P224},
@@ -567,10 +559,29 @@ static OPT_PAIR ecdh_choices[] = {
     {"ecdhb283", R_EC_B283},
     {"ecdhb409", R_EC_B409},
     {"ecdhb571", R_EC_B571},
+    {"ecdhbrp256r1", R_EC_BRP256R1},
+    {"ecdhbrp256t1", R_EC_BRP256T1},
+    {"ecdhbrp384r1", R_EC_BRP384R1},
+    {"ecdhbrp384t1", R_EC_BRP384T1},
+    {"ecdhbrp512r1", R_EC_BRP512R1},
+    {"ecdhbrp512t1", R_EC_BRP512T1},
     {"ecdhx25519", R_EC_X25519},
-    {NULL}
+    {"ecdhx448", R_EC_X448}
 };
-#endif
+# define EC_NUM       OSSL_NELEM(ecdh_choices)
+
+static double ecdh_results[EC_NUM][1];  /* 1 op: derivation */
+
+#define R_EC_Ed25519    0
+#define R_EC_Ed448      1
+static OPT_PAIR eddsa_choices[] = {
+    {"ed25519", R_EC_Ed25519},
+    {"ed448", R_EC_Ed448}
+};
+# define EdDSA_NUM       OSSL_NELEM(eddsa_choices)
+
+static double eddsa_results[EdDSA_NUM][2];    /* 2 ops: sign then verify */
+#endif /* OPENSSL_NO_EC */
 
 #ifndef SIGALRM
 # define COND(d) (count < (d))
@@ -580,10 +591,41 @@ static OPT_PAIR ecdh_choices[] = {
 # define COUNT(d) (count)
 #endif                          /* SIGALRM */
 
-static int testnum;
+typedef struct loopargs_st {
+    ASYNC_JOB *inprogress_job;
+    ASYNC_WAIT_CTX *wait_ctx;
+    unsigned char *buf;
+    unsigned char *buf2;
+    unsigned char *buf_malloc;
+    unsigned char *buf2_malloc;
+    unsigned char *key;
+    unsigned int siglen;
+    size_t sigsize;
+#ifndef OPENSSL_NO_RSA
+    RSA *rsa_key[RSA_NUM];
+#endif
+#ifndef OPENSSL_NO_DSA
+    DSA *dsa_key[DSA_NUM];
+#endif
+#ifndef OPENSSL_NO_EC
+    EC_KEY *ecdsa[ECDSA_NUM];
+    EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
+    EVP_MD_CTX *eddsa_ctx[EdDSA_NUM];
+    unsigned char *secret_a;
+    unsigned char *secret_b;
+    size_t outlen[EC_NUM];
+#endif
+    EVP_CIPHER_CTX *ctx;
+    HMAC_CTX *hctx;
+    GCM128_CONTEXT *gcm_ctx;
+} loopargs_t;
+static int run_benchmark(int async_jobs, int (*loop_function) (void *),
+                         loopargs_t * loopargs);
+
+static unsigned int testnum;
 
 /* Nb of iterations to do per algorithm and key-size */
-static long c[ALGOR_NUM][SIZE_NUM];
+static long c[ALGOR_NUM][OSSL_NELEM(lengths_list)];
 
 #ifndef OPENSSL_NO_MD2
 static int EVP_Digest_MD2_loop(void *args)
@@ -852,6 +894,17 @@ static int CRYPTO_gcm128_aad_loop(void *args)
     return count;
 }
 
+static int RAND_bytes_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    unsigned char *buf = tempargs->buf;
+    int count;
+
+    for (count = 0; COND(c[D_RAND][testnum]); count++)
+        RAND_bytes(buf, lengths[testnum]);
+    return count;
+}
+
 static long save_count = 0;
 static int decrypt = 0;
 static int EVP_Update_loop(void *args)
@@ -859,16 +912,65 @@ static int EVP_Update_loop(void *args)
     loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     EVP_CIPHER_CTX *ctx = tempargs->ctx;
-    int outl, count;
+    int outl, count, rc;
 #ifndef SIGALRM
     int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
 #endif
+    if (decrypt) {
+        for (count = 0; COND(nb_iter); count++) {
+            rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+            if (rc != 1) {
+                /* reset iv in case of counter overflow */
+                EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1);
+            }
+        }
+    } else {
+        for (count = 0; COND(nb_iter); count++) {
+            rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+            if (rc != 1) {
+                /* reset iv in case of counter overflow */
+                EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1);
+            }
+        }
+    }
     if (decrypt)
-        for (count = 0; COND(nb_iter); count++)
-            EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+        EVP_DecryptFinal_ex(ctx, buf, &outl);
     else
-        for (count = 0; COND(nb_iter); count++)
+        EVP_EncryptFinal_ex(ctx, buf, &outl);
+    return count;
+}
+
+/*
+ * CCM does not support streaming. For the purpose of performance measurement,
+ * each message is encrypted using the same (key,iv)-pair. Do not use this
+ * code in your application.
+ */
+static int EVP_Update_loop_ccm(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    unsigned char *buf = tempargs->buf;
+    EVP_CIPHER_CTX *ctx = tempargs->ctx;
+    int outl, count;
+    unsigned char tag[12];
+#ifndef SIGALRM
+    int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
+#endif
+    if (decrypt) {
+        for (count = 0; COND(nb_iter); count++) {
+            EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), tag);
+            /* reset iv */
+            EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
+            /* counter is reset on every update */
+            EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+        }
+    } else {
+        for (count = 0; COND(nb_iter); count++) {
+            /* restore iv length field */
+            EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
+            /* counter is reset on every update */
             EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+        }
+    }
     if (decrypt)
         EVP_DecryptFinal_ex(ctx, buf, &outl);
     else
@@ -876,6 +978,42 @@ static int EVP_Update_loop(void *args)
     return count;
 }
 
+/*
+ * To make AEAD benchmarking more relevant perform TLS-like operations,
+ * 13-byte AAD followed by payload. But don't use TLS-formatted AAD, as
+ * payload length is not actually limited by 16KB...
+ */
+static int EVP_Update_loop_aead(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    unsigned char *buf = tempargs->buf;
+    EVP_CIPHER_CTX *ctx = tempargs->ctx;
+    int outl, count;
+    unsigned char aad[13] = { 0xcc };
+    unsigned char faketag[16] = { 0xcc };
+#ifndef SIGALRM
+    int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
+#endif
+    if (decrypt) {
+        for (count = 0; COND(nb_iter); count++) {
+            EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
+            EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+                                sizeof(faketag), faketag);
+            EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
+            EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+            EVP_DecryptFinal_ex(ctx, buf + outl, &outl);
+        }
+    } else {
+        for (count = 0; COND(nb_iter); count++) {
+            EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv);
+            EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
+            EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+            EVP_EncryptFinal_ex(ctx, buf + outl, &outl);
+        }
+    }
+    return count;
+}
+
 static const EVP_MD *evp_md = NULL;
 static int EVP_Digest_loop(void *args)
 {
@@ -983,7 +1121,7 @@ static int DSA_verify_loop(void *args)
 #endif
 
 #ifndef OPENSSL_NO_EC
-static long ecdsa_c[EC_NUM][2];
+static long ecdsa_c[ECDSA_NUM][2];
 static int ECDSA_sign_loop(void *args)
 {
     loopargs_t *tempargs = *(loopargs_t **) args;
@@ -1041,6 +1179,48 @@ static int ECDH_EVP_derive_key_loop(void *args)
     return count;
 }
 
+static long eddsa_c[EdDSA_NUM][2];
+static int EdDSA_sign_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    unsigned char *buf = tempargs->buf;
+    EVP_MD_CTX **edctx = tempargs->eddsa_ctx;
+    unsigned char *eddsasig = tempargs->buf2;
+    size_t *eddsasigsize = &tempargs->sigsize;
+    int ret, count;
+
+    for (count = 0; COND(eddsa_c[testnum][0]); count++) {
+        ret = EVP_DigestSign(edctx[testnum], eddsasig, eddsasigsize, buf, 20);
+        if (ret == 0) {
+            BIO_printf(bio_err, "EdDSA sign failure\n");
+            ERR_print_errors(bio_err);
+            count = -1;
+            break;
+        }
+    }
+    return count;
+}
+
+static int EdDSA_verify_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    unsigned char *buf = tempargs->buf;
+    EVP_MD_CTX **edctx = tempargs->eddsa_ctx;
+    unsigned char *eddsasig = tempargs->buf2;
+    size_t eddsasigsize = tempargs->sigsize;
+    int ret, count;
+
+    for (count = 0; COND(eddsa_c[testnum][1]); count++) {
+        ret = EVP_DigestVerify(edctx[testnum], eddsasig, eddsasigsize, buf, 20);
+        if (ret != 1) {
+            BIO_printf(bio_err, "EdDSA verify failure\n");
+            ERR_print_errors(bio_err);
+            count = -1;
+            break;
+        }
+    }
+    return count;
+}
 #endif                          /* OPENSSL_NO_EC */
 
 static int run_benchmark(int async_jobs,
@@ -1200,25 +1380,29 @@ int speed_main(int argc, char **argv)
 {
     ENGINE *e = NULL;
     loopargs_t *loopargs = NULL;
-    int async_init = 0;
-    int loopargs_len = 0;
-    char *prog;
+    const char *prog;
     const char *engine_id = NULL;
     const EVP_CIPHER *evp_cipher = NULL;
     double d = 0.0;
     OPTION_CHOICE o;
-    int multiblock = 0, pr_header = 0;
+    int async_init = 0, multiblock = 0, pr_header = 0;
     int doit[ALGOR_NUM] = { 0 };
-    int ret = 1, i, k, misalign = 0;
+    int ret = 1, misalign = 0, lengths_single = 0, aead = 0;
     long count = 0;
+    unsigned int size_num = OSSL_NELEM(lengths_list);
+    unsigned int i, k, loop, loopargs_len = 0, async_jobs = 0;
+    int keylen;
+    int buflen;
 #ifndef NO_FORK
     int multi = 0;
 #endif
-    int async_jobs = 0;
 #if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \
     || !defined(OPENSSL_NO_EC)
     long rsa_count = 1;
 #endif
+    openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS,
+                                    ECDSA_SECONDS, ECDH_SECONDS,
+                                    EdDSA_SECONDS };
 
     /* What follows are the buffers and key material. */
 #ifndef OPENSSL_NO_RC5
@@ -1293,6 +1477,7 @@ int speed_main(int argc, char **argv)
         sizeof(test15360)
     };
     int rsa_doit[RSA_NUM] = { 0 };
+    int primes = RSA_DEFAULT_PRIME_NUM;
 #endif
 #ifndef OPENSSL_NO_DSA
     static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
@@ -1302,43 +1487,56 @@ int speed_main(int argc, char **argv)
     /*
      * We only test over the following curves as they are representative, To
      * add tests over more curves, simply add the curve NID and curve name to
-     * the following arrays and increase the EC_NUM value accordingly.
+     * the following arrays and increase the |ecdh_choices| list accordingly.
      */
-    static const unsigned int test_curves[EC_NUM] = {
-        /* Prime Curves */
-        NID_secp160r1, NID_X9_62_prime192v1, NID_secp224r1,
-        NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1,
-        /* Binary Curves */
-        NID_sect163k1, NID_sect233k1, NID_sect283k1,
-        NID_sect409k1, NID_sect571k1, NID_sect163r2,
-        NID_sect233r1, NID_sect283r1, NID_sect409r1,
-        NID_sect571r1,
-        /* Other */
-        NID_X25519
-    };
-    static const char *test_curves_names[EC_NUM] = {
+    static const struct {
+        const char *name;
+        unsigned int nid;
+        unsigned int bits;
+    } test_curves[] = {
         /* Prime Curves */
-        "secp160r1", "nistp192", "nistp224",
-        "nistp256", "nistp384", "nistp521",
+        {"secp160r1", NID_secp160r1, 160},
+        {"nistp192", NID_X9_62_prime192v1, 192},
+        {"nistp224", NID_secp224r1, 224},
+        {"nistp256", NID_X9_62_prime256v1, 256},
+        {"nistp384", NID_secp384r1, 384}, 
+        {"nistp521", NID_secp521r1, 521},
         /* Binary Curves */
-        "nistk163", "nistk233", "nistk283",
-        "nistk409", "nistk571", "nistb163",
-        "nistb233", "nistb283", "nistb409",
-        "nistb571",
-        /* Other */
-        "X25519"
+        {"nistk163", NID_sect163k1, 163},
+        {"nistk233", NID_sect233k1, 233}, 
+        {"nistk283", NID_sect283k1, 283},
+        {"nistk409", NID_sect409k1, 409},
+        {"nistk571", NID_sect571k1, 571},
+        {"nistb163", NID_sect163r2, 163},
+        {"nistb233", NID_sect233r1, 233},
+        {"nistb283", NID_sect283r1, 283},
+        {"nistb409", NID_sect409r1, 409},
+        {"nistb571", NID_sect571r1, 571},
+        {"brainpoolP256r1", NID_brainpoolP256r1, 256},
+        {"brainpoolP256t1", NID_brainpoolP256t1, 256},
+        {"brainpoolP384r1", NID_brainpoolP384r1, 384},
+        {"brainpoolP384t1", NID_brainpoolP384t1, 384},
+        {"brainpoolP512r1", NID_brainpoolP512r1, 512},
+        {"brainpoolP512t1", NID_brainpoolP512t1, 512},
+        /* Other and ECDH only ones */
+        {"X25519", NID_X25519, 253},
+        {"X448", NID_X448, 448}
     };
-    static const int test_curves_bits[EC_NUM] = {
-        160, 192, 224,
-        256, 384, 521,
-        163, 233, 283,
-        409, 571, 163,
-        233, 283, 409,
-        571, 253                /* X25519 */
+    static const struct {
+        const char *name;
+        unsigned int nid;
+        unsigned int bits;
+        size_t sigsize;
+    } test_ed_curves[] = {
+        /* EdDSA */
+        {"Ed25519", NID_ED25519, 253, 64},
+        {"Ed448", NID_ED448, 456, 114}
     };
-
-    int ecdsa_doit[EC_NUM] = { 0 };
+    int ecdsa_doit[ECDSA_NUM] = { 0 };
     int ecdh_doit[EC_NUM] = { 0 };
+    int eddsa_doit[EdDSA_NUM] = { 0 };
+    OPENSSL_assert(OSSL_NELEM(test_curves) >= EC_NUM);
+    OPENSSL_assert(OSSL_NELEM(test_ed_curves) >= EdDSA_NUM);
 #endif                          /* ndef OPENSSL_NO_EC */
 
     prog = opt_init(argc, argv, speed_options);
@@ -1357,6 +1555,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());
@@ -1393,6 +1592,10 @@ 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:
@@ -1416,6 +1619,26 @@ int speed_main(int argc, char **argv)
             goto end;
 #endif
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
+        case OPT_PRIMES:
+            if (!opt_int(opt_arg(), &primes))
+                goto end;
+            break;
+        case OPT_SECONDS:
+            seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa
+                        = seconds.ecdh = seconds.eddsa = atoi(opt_arg());
+            break;
+        case OPT_BYTES:
+            lengths_single = atoi(opt_arg());
+            lengths = &lengths_single;
+            size_num = 1;
+            break;
+        case OPT_AEAD:
+            aead = 1;
+            break;
         }
     }
     argc = opt_num_rest();
@@ -1438,17 +1661,11 @@ 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] =
-                rsa_doit[R_RSA_4096] = rsa_doit[R_RSA_7680] =
-                rsa_doit[R_RSA_15360] = 1;
+            for (loop = 0; loop < OSSL_NELEM(rsa_doit); loop++)
+                rsa_doit[loop] = 1;
             continue;
         }
         if (found(*argv, rsa_choices, &i)) {
@@ -1479,8 +1696,8 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_EC
         if (strcmp(*argv, "ecdsa") == 0) {
-            for (i = 0; i < EC_NUM; i++)
-                ecdsa_doit[i] = 1;
+            for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++)
+                ecdsa_doit[loop] = 1;
             continue;
         }
         if (found(*argv, ecdsa_choices, &i)) {
@@ -1488,19 +1705,56 @@ int speed_main(int argc, char **argv)
             continue;
         }
         if (strcmp(*argv, "ecdh") == 0) {
-            for (i = 0; i < EC_NUM; i++)
-                ecdh_doit[i] = 1;
+            for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++)
+                ecdh_doit[loop] = 1;
             continue;
         }
         if (found(*argv, ecdh_choices, &i)) {
             ecdh_doit[i] = 2;
             continue;
         }
+        if (strcmp(*argv, "eddsa") == 0) {
+            for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++)
+                eddsa_doit[loop] = 1;
+            continue;
+        }
+        if (found(*argv, eddsa_choices, &i)) {
+            eddsa_doit[i] = 2;
+            continue;
+        }
 #endif
         BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, *argv);
         goto end;
     }
 
+    /* Sanity checks */
+    if (aead) {
+        if (evp_cipher == NULL) {
+            BIO_printf(bio_err, "-aead can be used only with an AEAD cipher\n");
+            goto end;
+        } else if (!(EVP_CIPHER_flags(evp_cipher) &
+                     EVP_CIPH_FLAG_AEAD_CIPHER)) {
+            BIO_printf(bio_err, "%s is not an AEAD cipher\n",
+                       OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)));
+            goto end;
+        }
+    }
+    if (multiblock) {
+        if (evp_cipher == NULL) {
+            BIO_printf(bio_err,"-mb can be used only with a multi-block"
+                               " capable cipher\n");
+            goto end;
+        } else if (!(EVP_CIPHER_flags(evp_cipher) &
+                     EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
+            BIO_printf(bio_err, "%s is not a multi-block capable\n",
+                       OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)));
+            goto end;
+        } else if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with -mb");
+            goto end;
+        }
+    }
+
     /* Initialize the job pool if async mode is enabled */
     if (async_jobs > 0) {
         async_init = ASYNC_init_thread(async_jobs, async_jobs);
@@ -1524,10 +1778,15 @@ int speed_main(int argc, char **argv)
             }
         }
 
-        loopargs[i].buf_malloc =
-            app_malloc((int)BUFSIZE + MAX_MISALIGNMENT + 1, "input buffer");
-        loopargs[i].buf2_malloc =
-            app_malloc((int)BUFSIZE + MAX_MISALIGNMENT + 1, "input buffer");
+        buflen = lengths[size_num - 1];
+        if (buflen < 36)    /* size of random vector in RSA bencmark */
+            buflen = 36;
+        buflen += MAX_MISALIGNMENT + 1;
+        loopargs[i].buf_malloc = app_malloc(buflen, "input buffer");
+        loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer");
+        memset(loopargs[i].buf_malloc, 0, buflen);
+        memset(loopargs[i].buf2_malloc, 0, buflen);
+
         /* Align the start of buffers on a 64 byte boundary */
         loopargs[i].buf = loopargs[i].buf_malloc + misalign;
         loopargs[i].buf2 = loopargs[i].buf2_malloc + misalign;
@@ -1538,7 +1797,7 @@ int speed_main(int argc, char **argv)
     }
 
 #ifndef NO_FORK
-    if (multi && do_multi(multi))
+    if (multi && do_multi(multi, size_num))
         goto show_res;
 #endif
 
@@ -1559,10 +1818,12 @@ int speed_main(int argc, char **argv)
             dsa_doit[i] = 1;
 #endif
 #ifndef OPENSSL_NO_EC
-        for (i = 0; i < EC_NUM; i++)
-            ecdsa_doit[i] = 1;
-        for (i = 0; i < EC_NUM; i++)
-            ecdh_doit[i] = 1;
+        for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++)
+            ecdsa_doit[loop] = 1;
+        for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++)
+            ecdh_doit[loop] = 1;
+        for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++)
+            eddsa_doit[loop] = 1;
 #endif
     }
     for (i = 0; i < ALGOR_NUM; i++)
@@ -1576,6 +1837,10 @@ int speed_main(int argc, char **argv)
 
 #ifndef OPENSSL_NO_RSA
     for (i = 0; i < loopargs_len; i++) {
+        if (primes > RSA_DEFAULT_PRIME_NUM) {
+            /* for multi-prime RSA, skip this */
+            break;
+        }
         for (k = 0; k < RSA_NUM; k++) {
             const unsigned char *p;
 
@@ -1592,9 +1857,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
@@ -1674,8 +1939,9 @@ int speed_main(int argc, char **argv)
     c[D_IGE_192_AES][0] = count;
     c[D_IGE_256_AES][0] = count;
     c[D_GHASH][0] = count;
+    c[D_RAND][0] = count;
 
-    for (i = 1; i < SIZE_NUM; i++) {
+    for (i = 1; i < size_num; i++) {
         long l0, l1;
 
         l0 = (long)lengths[0];
@@ -1692,6 +1958,7 @@ int speed_main(int argc, char **argv)
         c[D_SHA512][i] = c[D_SHA512][0] * 4 * l0 / l1;
         c[D_WHIRLPOOL][i] = c[D_WHIRLPOOL][0] * 4 * l0 / l1;
         c[D_GHASH][i] = c[D_GHASH][0] * 4 * l0 / l1;
+        c[D_RAND][i] = c[D_RAND][0] * 4 * l0 / l1;
 
         l0 = (long)lengths[i - 1];
 
@@ -1826,22 +2093,50 @@ int speed_main(int argc, char **argv)
             }
         }
     }
+    /* repeated code good to factorize */
+    ecdh_c[R_EC_BRP256R1][0] = count / 1000;
+    for (i = R_EC_BRP384R1; i <= R_EC_BRP512R1; i += 2) {
+        ecdh_c[i][0] = ecdh_c[i - 2][0] / 2;
+        if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
+            ecdh_doit[i] = 0;
+        else {
+            if (ecdh_c[i][0] == 0) {
+                ecdh_c[i][0] = 1;
+            }
+        }
+    }
+    ecdh_c[R_EC_BRP256T1][0] = count / 1000;
+    for (i = R_EC_BRP384T1; i <= R_EC_BRP512T1; i += 2) {
+        ecdh_c[i][0] = ecdh_c[i - 2][0] / 2;
+        if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
+            ecdh_doit[i] = 0;
+        else {
+            if (ecdh_c[i][0] == 0) {
+                ecdh_c[i][0] = 1;
+            }
+        }
+    }
+    /* default iteration count for the last two EC Curves */
+    ecdh_c[R_EC_X25519][0] = count / 1800;
+    ecdh_c[R_EC_X448][0] = count / 7200;
+
+    eddsa_c[R_EC_Ed25519][0] = count / 1800;
+    eddsa_c[R_EC_Ed448][0] = count / 7200;
 #  endif
 
 # else
 /* not worth fixing */
 #  error "You cannot disable DES on systems without SIGALRM."
 # endif                         /* OPENSSL_NO_DES */
-#else
-# ifndef _WIN32
-    signal(SIGALRM, sig_done);
-# endif
+#elif SIGALRM > 0
+    signal(SIGALRM, alarmed);
 #endif                          /* SIGALRM */
 
 #ifndef OPENSSL_NO_MD2
     if (doit[D_MD2]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum],
+                          seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, EVP_Digest_MD2_loop, loopargs);
             d = Time_F(STOP);
@@ -1851,8 +2146,9 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_MDC2
     if (doit[D_MDC2]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum],
+                          seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, EVP_Digest_MDC2_loop, loopargs);
             d = Time_F(STOP);
@@ -1863,8 +2159,9 @@ int speed_main(int argc, char **argv)
 
 #ifndef OPENSSL_NO_MD4
     if (doit[D_MD4]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum],
+                          seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, EVP_Digest_MD4_loop, loopargs);
             d = Time_F(STOP);
@@ -1875,8 +2172,9 @@ int speed_main(int argc, char **argv)
 
 #ifndef OPENSSL_NO_MD5
     if (doit[D_MD5]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum],
+                          seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, MD5_loop, loopargs);
             d = Time_F(STOP);
@@ -1897,8 +2195,9 @@ int speed_main(int argc, char **argv)
 
             HMAC_Init_ex(loopargs[i].hctx, hmac_key, len, EVP_md5(), NULL);
         }
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum],
+                          seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, HMAC_loop, loopargs);
             d = Time_F(STOP);
@@ -1910,8 +2209,9 @@ int speed_main(int argc, char **argv)
     }
 #endif
     if (doit[D_SHA1]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum],
+                          seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, SHA1_loop, loopargs);
             d = Time_F(STOP);
@@ -1919,9 +2219,9 @@ int speed_main(int argc, char **argv)
         }
     }
     if (doit[D_SHA256]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_SHA256], c[D_SHA256][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, SHA256_loop, loopargs);
             d = Time_F(STOP);
@@ -1929,9 +2229,9 @@ int speed_main(int argc, char **argv)
         }
     }
     if (doit[D_SHA512]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_SHA512], c[D_SHA512][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, SHA512_loop, loopargs);
             d = Time_F(STOP);
@@ -1940,9 +2240,9 @@ int speed_main(int argc, char **argv)
     }
 #ifndef OPENSSL_NO_WHIRLPOOL
     if (doit[D_WHIRLPOOL]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs);
             d = Time_F(STOP);
@@ -1953,9 +2253,9 @@ int speed_main(int argc, char **argv)
 
 #ifndef OPENSSL_NO_RMD160
     if (doit[D_RMD160]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_RMD160], c[D_RMD160][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs);
             d = Time_F(STOP);
@@ -1965,8 +2265,9 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_RC4
     if (doit[D_RC4]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_RC4], c[D_RC4][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_RC4], c[D_RC4][testnum], lengths[testnum],
+                          seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, RC4_loop, loopargs);
             d = Time_F(STOP);
@@ -1976,9 +2277,9 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_DES
     if (doit[D_CBC_DES]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_CBC_DES], c[D_CBC_DES][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, DES_ncbc_encrypt_loop, loopargs);
             d = Time_F(STOP);
@@ -1987,9 +2288,9 @@ int speed_main(int argc, char **argv)
     }
 
     if (doit[D_EDE3_DES]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count =
                 run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs);
@@ -2000,9 +2301,9 @@ int speed_main(int argc, char **argv)
 #endif
 
     if (doit[D_CBC_128_AES]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_CBC_128_AES], c[D_CBC_128_AES][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count =
                 run_benchmark(async_jobs, AES_cbc_128_encrypt_loop, loopargs);
@@ -2011,9 +2312,9 @@ int speed_main(int argc, char **argv)
         }
     }
     if (doit[D_CBC_192_AES]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_CBC_192_AES], c[D_CBC_192_AES][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count =
                 run_benchmark(async_jobs, AES_cbc_192_encrypt_loop, loopargs);
@@ -2022,9 +2323,9 @@ int speed_main(int argc, char **argv)
         }
     }
     if (doit[D_CBC_256_AES]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_CBC_256_AES], c[D_CBC_256_AES][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count =
                 run_benchmark(async_jobs, AES_cbc_256_encrypt_loop, loopargs);
@@ -2034,9 +2335,9 @@ int speed_main(int argc, char **argv)
     }
 
     if (doit[D_IGE_128_AES]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_IGE_128_AES], c[D_IGE_128_AES][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count =
                 run_benchmark(async_jobs, AES_ige_128_encrypt_loop, loopargs);
@@ -2045,9 +2346,9 @@ int speed_main(int argc, char **argv)
         }
     }
     if (doit[D_IGE_192_AES]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_IGE_192_AES], c[D_IGE_192_AES][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count =
                 run_benchmark(async_jobs, AES_ige_192_encrypt_loop, loopargs);
@@ -2056,9 +2357,9 @@ int speed_main(int argc, char **argv)
         }
     }
     if (doit[D_IGE_256_AES]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_IGE_256_AES], c[D_IGE_256_AES][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count =
                 run_benchmark(async_jobs, AES_ige_256_encrypt_loop, loopargs);
@@ -2074,9 +2375,9 @@ int speed_main(int argc, char **argv)
                                 (unsigned char *)"0123456789ab", 12);
         }
 
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_GHASH], c[D_GHASH][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, CRYPTO_gcm128_aad_loop, loopargs);
             d = Time_F(STOP);
@@ -2092,9 +2393,9 @@ int speed_main(int argc, char **argv)
                        names[D_CBC_128_CML]);
             doit[D_CBC_128_CML] = 0;
         }
-        for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
             print_message(names[D_CBC_128_CML], c[D_CBC_128_CML][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             for (count = 0, run = 1; COND(c[D_CBC_128_CML][testnum]); count++)
                 Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
@@ -2110,9 +2411,9 @@ int speed_main(int argc, char **argv)
                        names[D_CBC_192_CML]);
             doit[D_CBC_192_CML] = 0;
         }
-        for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
             print_message(names[D_CBC_192_CML], c[D_CBC_192_CML][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             if (async_jobs > 0) {
                 BIO_printf(bio_err, "Async mode is not supported, exiting...");
                 exit(1);
@@ -2132,9 +2433,9 @@ int speed_main(int argc, char **argv)
                        names[D_CBC_256_CML]);
             doit[D_CBC_256_CML] = 0;
         }
-        for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
             print_message(names[D_CBC_256_CML], c[D_CBC_256_CML][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             for (count = 0, run = 1; COND(c[D_CBC_256_CML][testnum]); count++)
                 Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
@@ -2152,9 +2453,9 @@ int speed_main(int argc, char **argv)
                        names[D_CBC_IDEA]);
             doit[D_CBC_IDEA] = 0;
         }
-        for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
             print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             for (count = 0, run = 1; COND(c[D_CBC_IDEA][testnum]); count++)
                 IDEA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
@@ -2172,9 +2473,9 @@ int speed_main(int argc, char **argv)
                        names[D_CBC_SEED]);
             doit[D_CBC_SEED] = 0;
         }
-        for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
             print_message(names[D_CBC_SEED], c[D_CBC_SEED][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             for (count = 0, run = 1; COND(c[D_CBC_SEED][testnum]); count++)
                 SEED_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
@@ -2191,9 +2492,9 @@ int speed_main(int argc, char **argv)
                        names[D_CBC_RC2]);
             doit[D_CBC_RC2] = 0;
         }
-        for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
             print_message(names[D_CBC_RC2], c[D_CBC_RC2][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             if (async_jobs > 0) {
                 BIO_printf(bio_err, "Async mode is not supported, exiting...");
                 exit(1);
@@ -2215,9 +2516,9 @@ int speed_main(int argc, char **argv)
                        names[D_CBC_RC5]);
             doit[D_CBC_RC5] = 0;
         }
-        for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
             print_message(names[D_CBC_RC5], c[D_CBC_RC5][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             if (async_jobs > 0) {
                 BIO_printf(bio_err, "Async mode is not supported, exiting...");
                 exit(1);
@@ -2239,9 +2540,9 @@ int speed_main(int argc, char **argv)
                        names[D_CBC_BF]);
             doit[D_CBC_BF] = 0;
         }
-        for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
             print_message(names[D_CBC_BF], c[D_CBC_BF][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             for (count = 0, run = 1; COND(c[D_CBC_BF][testnum]); count++)
                 BF_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
@@ -2259,9 +2560,9 @@ int speed_main(int argc, char **argv)
                        names[D_CBC_CAST]);
             doit[D_CBC_CAST] = 0;
         }
-        for (testnum = 0; testnum < SIZE_NUM && async_init == 0; testnum++) {
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
             print_message(names[D_CBC_CAST], c[D_CBC_CAST][testnum],
-                          lengths[testnum]);
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             for (count = 0, run = 1; COND(c[D_CBC_CAST][testnum]); count++)
                 CAST_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
@@ -2272,65 +2573,85 @@ int speed_main(int argc, char **argv)
         }
     }
 #endif
+    if (doit[D_RAND]) {
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_RAND], c[D_RAND][testnum], lengths[testnum],
+                          seconds.sym);
+            Time_F(START);
+            count = run_benchmark(async_jobs, RAND_bytes_loop, loopargs);
+            d = Time_F(STOP);
+            print_result(D_RAND, testnum, count, d);
+        }
+    }
 
     if (doit[D_EVP]) {
-        if (multiblock && evp_cipher) {
-            if (!
-                (EVP_CIPHER_flags(evp_cipher) &
-                 EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
-                BIO_printf(bio_err, "%s is not multi-block capable\n",
-                           OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)));
+        if (evp_cipher != NULL) {
+            int (*loopfunc)(void *args) = EVP_Update_loop;
+
+            if (multiblock && (EVP_CIPHER_flags(evp_cipher) &
+                               EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
+                multiblock_speed(evp_cipher, lengths_single, &seconds);
+                ret = 0;
                 goto end;
             }
-            if (async_jobs > 0) {
-                BIO_printf(bio_err, "Async mode is not supported, exiting...");
-                exit(1);
+
+            names[D_EVP] = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
+
+            if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_CCM_MODE) {
+                loopfunc = EVP_Update_loop_ccm;
+            } else if (aead && (EVP_CIPHER_flags(evp_cipher) &
+                                EVP_CIPH_FLAG_AEAD_CIPHER)) {
+                loopfunc = EVP_Update_loop_aead;
+                if (lengths == lengths_list) {
+                    lengths = aead_lengths_list;
+                    size_num = OSSL_NELEM(aead_lengths_list);
+                }
             }
-            multiblock_speed(evp_cipher);
-            ret = 0;
-            goto end;
-        }
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            if (evp_cipher) {
 
-                names[D_EVP] = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
-                /*
-                 * -O3 -fschedule-insns messes up an optimization here!
-                 * names[D_EVP] somehow becomes NULL
-                 */
-                print_message(names[D_EVP], save_count, lengths[testnum]);
+            for (testnum = 0; testnum < size_num; testnum++) {
+                print_message(names[D_EVP], save_count, lengths[testnum],
+                              seconds.sym);
 
                 for (k = 0; k < loopargs_len; k++) {
                     loopargs[k].ctx = EVP_CIPHER_CTX_new();
-                    if (decrypt)
-                        EVP_DecryptInit_ex(loopargs[k].ctx, evp_cipher, NULL,
-                                           key16, iv);
-                    else
-                        EVP_EncryptInit_ex(loopargs[k].ctx, evp_cipher, NULL,
-                                           key16, iv);
+                    EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL, NULL,
+                                      iv, decrypt ? 0 : 1);
+
                     EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0);
+
+                    keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx);
+                    loopargs[k].key = app_malloc(keylen, "evp_cipher key");
+                    EVP_CIPHER_CTX_rand_key(loopargs[k].ctx, loopargs[k].key);
+                    EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
+                                      loopargs[k].key, NULL, -1);
+                    OPENSSL_clear_free(loopargs[k].key, keylen);
                 }
 
                 Time_F(START);
-                count = run_benchmark(async_jobs, EVP_Update_loop, loopargs);
+                count = run_benchmark(async_jobs, loopfunc, loopargs);
                 d = Time_F(STOP);
                 for (k = 0; k < loopargs_len; k++) {
                     EVP_CIPHER_CTX_free(loopargs[k].ctx);
                 }
+                print_result(D_EVP, testnum, count, d);
             }
-            if (evp_md) {
-                names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md));
-                print_message(names[D_EVP], save_count, lengths[testnum]);
+        } else if (evp_md != NULL) {
+            names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md));
+
+            for (testnum = 0; testnum < size_num; testnum++) {
+                print_message(names[D_EVP], save_count, lengths[testnum],
+                              seconds.sym);
                 Time_F(START);
                 count = run_benchmark(async_jobs, EVP_Digest_loop, loopargs);
                 d = Time_F(STOP);
+                print_result(D_EVP, testnum, count, d);
             }
-            print_result(D_EVP, testnum, count, d);
         }
     }
 
     for (i = 0; i < loopargs_len; i++)
-        RAND_bytes(loopargs[i].buf, 36);
+        if (RAND_bytes(loopargs[i].buf, 36) <= 0)
+            goto end;
 
 #ifndef OPENSSL_NO_RSA
     for (testnum = 0; testnum < RSA_NUM; testnum++) {
@@ -2338,6 +2659,34 @@ int speed_main(int argc, char **argv)
         if (!rsa_doit[testnum])
             continue;
         for (i = 0; i < loopargs_len; i++) {
+            if (primes > 2) {
+                /* we haven't set keys yet,  generate multi-prime RSA keys */
+                BIGNUM *bn = BN_new();
+
+                if (bn == NULL)
+                    goto end;
+                if (!BN_set_word(bn, RSA_F4)) {
+                    BN_free(bn);
+                    goto end;
+                }
+
+                BIO_printf(bio_err, "Generate multi-prime RSA key for %s\n",
+                           rsa_choices[testnum].name);
+
+                loopargs[i].rsa_key[testnum] = RSA_new();
+                if (loopargs[i].rsa_key[testnum] == NULL) {
+                    BN_free(bn);
+                    goto end;
+                }
+
+                if (!RSA_generate_multi_prime_key(loopargs[i].rsa_key[testnum],
+                                                  rsa_bits[testnum],
+                                                  primes, bn, NULL)) {
+                    BN_free(bn);
+                    goto end;
+                }
+                BN_free(bn);
+            }
             st = RSA_sign(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2,
                           &loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
             if (st == 0)
@@ -2351,14 +2700,14 @@ int speed_main(int argc, char **argv)
         } else {
             pkey_print_message("private", "rsa",
                                rsa_c[testnum][0], rsa_bits[testnum],
-                               RSA_SECONDS);
+                               seconds.rsa);
             /* RSA_blinding_on(rsa_key[testnum],NULL); */
             Time_F(START);
             count = run_benchmark(async_jobs, RSA_sign_loop, loopargs);
             d = Time_F(STOP);
             BIO_printf(bio_err,
                        mr ? "+R1:%ld:%d:%.2f\n"
-                       : "%ld %d bit private RSA's in %.2fs\n",
+                       : "%ld %u bits private RSA's in %.2fs\n",
                        count, rsa_bits[testnum], d);
             rsa_results[testnum][0] = (double)count / d;
             rsa_count = count;
@@ -2378,13 +2727,13 @@ int speed_main(int argc, char **argv)
         } else {
             pkey_print_message("public", "rsa",
                                rsa_c[testnum][1], rsa_bits[testnum],
-                               RSA_SECONDS);
+                               seconds.rsa);
             Time_F(START);
             count = run_benchmark(async_jobs, RSA_verify_loop, loopargs);
             d = Time_F(STOP);
             BIO_printf(bio_err,
                        mr ? "+R2:%ld:%d:%.2f\n"
-                       : "%ld %d bit public RSA's in %.2fs\n",
+                       : "%ld %u bits public RSA's in %.2fs\n",
                        count, rsa_bits[testnum], d);
             rsa_results[testnum][1] = (double)count / d;
         }
@@ -2398,12 +2747,10 @@ int speed_main(int argc, char **argv)
 #endif                          /* OPENSSL_NO_RSA */
 
     for (i = 0; i < loopargs_len; i++)
-        RAND_bytes(loopargs[i].buf, 36);
+        if (RAND_bytes(loopargs[i].buf, 36) <= 0)
+            goto end;
 
 #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])
@@ -2425,13 +2772,13 @@ int speed_main(int argc, char **argv)
         } else {
             pkey_print_message("sign", "dsa",
                                dsa_c[testnum][0], dsa_bits[testnum],
-                               DSA_SECONDS);
+                               seconds.dsa);
             Time_F(START);
             count = run_benchmark(async_jobs, DSA_sign_loop, loopargs);
             d = Time_F(STOP);
             BIO_printf(bio_err,
-                       mr ? "+R3:%ld:%d:%.2f\n"
-                       : "%ld %d bit DSA signs in %.2fs\n",
+                       mr ? "+R3:%ld:%u:%.2f\n"
+                       : "%ld %u bits DSA signs in %.2fs\n",
                        count, dsa_bits[testnum], d);
             dsa_results[testnum][0] = (double)count / d;
             rsa_count = count;
@@ -2451,13 +2798,13 @@ int speed_main(int argc, char **argv)
         } else {
             pkey_print_message("verify", "dsa",
                                dsa_c[testnum][1], dsa_bits[testnum],
-                               DSA_SECONDS);
+                               seconds.dsa);
             Time_F(START);
             count = run_benchmark(async_jobs, DSA_verify_loop, loopargs);
             d = Time_F(STOP);
             BIO_printf(bio_err,
-                       mr ? "+R4:%ld:%d:%.2f\n"
-                       : "%ld %d bit DSA verify in %.2fs\n",
+                       mr ? "+R4:%ld:%u:%.2f\n"
+                       : "%ld %u bits DSA verify in %.2fs\n",
                        count, dsa_bits[testnum], d);
             dsa_results[testnum][1] = (double)count / d;
         }
@@ -2471,17 +2818,14 @@ 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++) {
+    for (testnum = 0; testnum < ECDSA_NUM; testnum++) {
         int st = 1;
 
         if (!ecdsa_doit[testnum])
             continue;           /* Ignore Curve */
         for (i = 0; i < loopargs_len; i++) {
             loopargs[i].ecdsa[testnum] =
-                EC_KEY_new_by_curve_name(test_curves[testnum]);
+                EC_KEY_new_by_curve_name(test_curves[testnum].nid);
             if (loopargs[i].ecdsa[testnum] == NULL) {
                 st = 0;
                 break;
@@ -2510,15 +2854,15 @@ int speed_main(int argc, char **argv)
             } else {
                 pkey_print_message("sign", "ecdsa",
                                    ecdsa_c[testnum][0],
-                                   test_curves_bits[testnum], ECDSA_SECONDS);
+                                   test_curves[testnum].bits, seconds.ecdsa);
                 Time_F(START);
                 count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs);
                 d = Time_F(STOP);
 
                 BIO_printf(bio_err,
-                           mr ? "+R5:%ld:%d:%.2f\n" :
-                           "%ld %d bit ECDSA signs in %.2fs \n",
-                           count, test_curves_bits[testnum], d);
+                           mr ? "+R5:%ld:%u:%.2f\n" :
+                           "%ld %u bits ECDSA signs in %.2fs \n",
+                           count, test_curves[testnum].bits, d);
                 ecdsa_results[testnum][0] = (double)count / d;
                 rsa_count = count;
             }
@@ -2539,28 +2883,25 @@ int speed_main(int argc, char **argv)
             } else {
                 pkey_print_message("verify", "ecdsa",
                                    ecdsa_c[testnum][1],
-                                   test_curves_bits[testnum], ECDSA_SECONDS);
+                                   test_curves[testnum].bits, seconds.ecdsa);
                 Time_F(START);
                 count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs);
                 d = Time_F(STOP);
                 BIO_printf(bio_err,
-                           mr ? "+R6:%ld:%d:%.2f\n"
-                           : "%ld %d bit ECDSA verify in %.2fs\n",
-                           count, test_curves_bits[testnum], d);
+                           mr ? "+R6:%ld:%u:%.2f\n"
+                           : "%ld %u bits ECDSA verify in %.2fs\n",
+                           count, test_curves[testnum].bits, d);
                 ecdsa_results[testnum][1] = (double)count / d;
             }
 
             if (rsa_count <= 1) {
                 /* if longer than 10s, don't do any more */
-                for (testnum++; testnum < EC_NUM; testnum++)
+                for (testnum++; testnum < ECDSA_NUM; testnum++)
                     ecdsa_doit[testnum] = 0;
             }
         }
     }
 
-    if (RAND_status() != 1) {
-        RAND_seed(rnd_seed, sizeof rnd_seed);
-    }
     for (testnum = 0; testnum < EC_NUM; testnum++) {
         int ecdh_checks = 1;
 
@@ -2589,7 +2930,7 @@ int speed_main(int argc, char **argv)
              * 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 */
+            kctx = EVP_PKEY_CTX_new_id(test_curves[testnum].nid, NULL); /* keygen ctx from NID */
             if (!kctx) {
                 EVP_PKEY_CTX *pctx = NULL;
                 EVP_PKEY *params = NULL;
@@ -2620,7 +2961,7 @@ int speed_main(int argc, char **argv)
                        /* Set the curve by NID */
                        !EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
                                                                test_curves
-                                                               [testnum]) ||
+                                                               [testnum].nid) ||
                        /* Create the parameter object params */
                        !EVP_PKEY_paramgen(pctx, &params)) {
                     ecdh_checks = 0;
@@ -2637,7 +2978,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");
@@ -2692,6 +3033,8 @@ int speed_main(int argc, char **argv)
             loopargs[i].ecdh_ctx[testnum] = ctx;
             loopargs[i].outlen[testnum] = outlen;
 
+            EVP_PKEY_free(key_A);
+            EVP_PKEY_free(key_B);
             EVP_PKEY_CTX_free(kctx);
             kctx = NULL;
             EVP_PKEY_CTX_free(test_ctx);
@@ -2700,25 +3043,130 @@ int speed_main(int argc, char **argv)
         if (ecdh_checks != 0) {
             pkey_print_message("", "ecdh",
                                ecdh_c[testnum][0],
-                               test_curves_bits[testnum], ECDH_SECONDS);
+                               test_curves[testnum].bits, seconds.ecdh);
             Time_F(START);
             count =
                 run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs);
             d = Time_F(STOP);
             BIO_printf(bio_err,
                        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;
+                       "%ld %u-bits ECDH ops in %.2fs\n", count,
+                       test_curves[testnum].bits, d);
+            ecdh_results[testnum][0] = (double)count / d;
             rsa_count = count;
         }
 
         if (rsa_count <= 1) {
             /* if longer than 10s, don't do any more */
-            for (testnum++; testnum < EC_NUM; testnum++)
+            for (testnum++; testnum < OSSL_NELEM(ecdh_doit); testnum++)
                 ecdh_doit[testnum] = 0;
         }
     }
+
+    for (testnum = 0; testnum < EdDSA_NUM; testnum++) {
+        int st = 1;
+        EVP_PKEY *ed_pkey = NULL;
+        EVP_PKEY_CTX *ed_pctx = NULL;
+
+        if (!eddsa_doit[testnum])
+            continue;           /* Ignore Curve */
+        for (i = 0; i < loopargs_len; i++) {
+            loopargs[i].eddsa_ctx[testnum] = EVP_MD_CTX_new();
+            if (loopargs[i].eddsa_ctx[testnum] == NULL) {
+                st = 0;
+                break;
+            }
+
+            if ((ed_pctx = EVP_PKEY_CTX_new_id(test_ed_curves[testnum].nid, NULL))
+                    == NULL
+                || !EVP_PKEY_keygen_init(ed_pctx)
+                || !EVP_PKEY_keygen(ed_pctx, &ed_pkey)) {
+                st = 0;
+                EVP_PKEY_CTX_free(ed_pctx);
+                break;
+            }
+            EVP_PKEY_CTX_free(ed_pctx);
+
+            if (!EVP_DigestSignInit(loopargs[i].eddsa_ctx[testnum], NULL, NULL,
+                                    NULL, ed_pkey)) {
+                st = 0;
+                EVP_PKEY_free(ed_pkey);
+                break;
+            }
+            EVP_PKEY_free(ed_pkey);
+        }
+        if (st == 0) {
+            BIO_printf(bio_err, "EdDSA failure.\n");
+            ERR_print_errors(bio_err);
+            rsa_count = 1;
+        } else {
+            for (i = 0; i < loopargs_len; i++) {
+                /* Perform EdDSA signature test */
+                loopargs[i].sigsize = test_ed_curves[testnum].sigsize;
+                st = EVP_DigestSign(loopargs[i].eddsa_ctx[testnum],
+                                    loopargs[i].buf2, &loopargs[i].sigsize,
+                                    loopargs[i].buf, 20);
+                if (st == 0)
+                    break;
+            }
+            if (st == 0) {
+                BIO_printf(bio_err,
+                           "EdDSA sign failure.  No EdDSA sign will be done.\n");
+                ERR_print_errors(bio_err);
+                rsa_count = 1;
+            } else {
+                pkey_print_message("sign", test_ed_curves[testnum].name,
+                                   eddsa_c[testnum][0],
+                                   test_ed_curves[testnum].bits, seconds.eddsa);
+                Time_F(START);
+                count = run_benchmark(async_jobs, EdDSA_sign_loop, loopargs);
+                d = Time_F(STOP);
+
+                BIO_printf(bio_err,
+                           mr ? "+R8:%ld:%u:%s:%.2f\n" :
+                           "%ld %u bits %s signs in %.2fs \n",
+                           count, test_ed_curves[testnum].bits,
+                           test_ed_curves[testnum].name, d);
+                eddsa_results[testnum][0] = (double)count / d;
+                rsa_count = count;
+            }
+
+            /* Perform EdDSA verification test */
+            for (i = 0; i < loopargs_len; i++) {
+                st = EVP_DigestVerify(loopargs[i].eddsa_ctx[testnum],
+                                      loopargs[i].buf2, loopargs[i].sigsize,
+                                      loopargs[i].buf, 20);
+                if (st != 1)
+                    break;
+            }
+            if (st != 1) {
+                BIO_printf(bio_err,
+                           "EdDSA verify failure.  No EdDSA verify will be done.\n");
+                ERR_print_errors(bio_err);
+                eddsa_doit[testnum] = 0;
+            } else {
+                pkey_print_message("verify", test_ed_curves[testnum].name,
+                                   eddsa_c[testnum][1],
+                                   test_ed_curves[testnum].bits, seconds.eddsa);
+                Time_F(START);
+                count = run_benchmark(async_jobs, EdDSA_verify_loop, loopargs);
+                d = Time_F(STOP);
+                BIO_printf(bio_err,
+                           mr ? "+R9:%ld:%u:%s:%.2f\n"
+                           : "%ld %u bits %s verify in %.2fs\n",
+                           count, test_ed_curves[testnum].bits,
+                           test_ed_curves[testnum].name, d);
+                eddsa_results[testnum][1] = (double)count / d;
+            }
+
+            if (rsa_count <= 1) {
+                /* if longer than 10s, don't do any more */
+                for (testnum++; testnum < EdDSA_NUM; testnum++)
+                    eddsa_doit[testnum] = 0;
+            }
+        }
+    }
+
 #endif                          /* OPENSSL_NO_EC */
 #ifndef NO_FORK
  show_res:
@@ -2755,7 +3203,7 @@ int speed_main(int argc, char **argv)
                 ("The 'numbers' are in 1000s of bytes per second processed.\n");
             printf("type        ");
         }
-        for (testnum = 0; testnum < SIZE_NUM; testnum++)
+        for (testnum = 0; testnum < size_num; testnum++)
             printf(mr ? ":%d" : "%7d bytes", lengths[testnum]);
         printf("\n");
     }
@@ -2764,10 +3212,10 @@ int speed_main(int argc, char **argv)
         if (!doit[k])
             continue;
         if (mr)
-            printf("+F:%d:%s", k, names[k]);
+            printf("+F:%u:%s", k, names[k]);
         else
             printf("%-13s", names[k]);
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        for (testnum = 0; testnum < size_num; testnum++) {
             if (results[k][testnum] > 10000 && !mr)
                 printf(" %11.2fk", results[k][testnum] / 1e3);
             else
@@ -2813,7 +3261,7 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_EC
     testnum = 1;
-    for (k = 0; k < EC_NUM; k++) {
+    for (k = 0; k < OSSL_NELEM(ecdsa_doit); k++) {
         if (!ecdsa_doit[k])
             continue;
         if (testnum && !mr) {
@@ -2823,12 +3271,11 @@ int speed_main(int argc, char **argv)
 
         if (mr)
             printf("+F4:%u:%u:%f:%f\n",
-                   k, test_curves_bits[k],
+                   k, test_curves[k].bits,
                    ecdsa_results[k][0], ecdsa_results[k][1]);
         else
-            printf("%4u bit ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
-                   test_curves_bits[k],
-                   test_curves_names[k],
+            printf("%4u bits ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
+                   test_curves[k].bits, test_curves[k].name,
                    1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1],
                    ecdsa_results[k][0], ecdsa_results[k][1]);
     }
@@ -2843,14 +3290,33 @@ int speed_main(int argc, char **argv)
         }
         if (mr)
             printf("+F5:%u:%u:%f:%f\n",
-                   k, test_curves_bits[k],
+                   k, test_curves[k].bits,
                    ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
 
         else
-            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]);
+            printf("%4u bits ecdh (%s) %8.4fs %8.1f\n",
+                   test_curves[k].bits, test_curves[k].name,
+                   1.0 / ecdh_results[k][0], ecdh_results[k][0]);
+    }
+
+    testnum = 1;
+    for (k = 0; k < OSSL_NELEM(eddsa_doit); k++) {
+        if (!eddsa_doit[k])
+            continue;
+        if (testnum && !mr) {
+            printf("%30ssign    verify    sign/s verify/s\n", " ");
+            testnum = 0;
+        }
+
+        if (mr)
+            printf("+F6:%u:%u:%s:%f:%f\n",
+                   k, test_ed_curves[k].bits, test_ed_curves[k].name,
+                   eddsa_results[k][0], eddsa_results[k][1]);
+        else
+            printf("%4u bits EdDSA (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
+                   test_ed_curves[k].bits, test_ed_curves[k].name,
+                   1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1],
+                   eddsa_results[k][0], eddsa_results[k][1]);
     }
 #endif
 
@@ -2871,10 +3337,12 @@ int speed_main(int argc, char **argv)
             DSA_free(loopargs[i].dsa_key[k]);
 #endif
 #ifndef OPENSSL_NO_EC
-        for (k = 0; k < EC_NUM; k++) {
+        for (k = 0; k < ECDSA_NUM; k++)
             EC_KEY_free(loopargs[i].ecdsa[k]);
+        for (k = 0; k < EC_NUM; k++)
             EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]);
-        }
+        for (k = 0; k < EdDSA_NUM; k++)
+            EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]);
         OPENSSL_free(loopargs[i].secret_a);
         OPENSSL_free(loopargs[i].secret_b);
 #endif
@@ -2890,17 +3358,17 @@ int speed_main(int argc, char **argv)
     }
     OPENSSL_free(loopargs);
     release_engine(e);
-    return (ret);
+    return ret;
 }
 
-static void print_message(const char *s, long num, int length)
+static void print_message(const char *s, long num, int length, int tm)
 {
 #ifdef SIGALRM
     BIO_printf(bio_err,
                mr ? "+DT:%s:%d:%d\n"
-               : "Doing %s for %ds on %d size blocks: ", s, SECONDS, length);
+               : "Doing %s for %ds on %d size blocks: ", s, tm, length);
     (void)BIO_flush(bio_err);
-    alarm(SECONDS);
+    alarm(tm);
 #else
     BIO_printf(bio_err,
                mr ? "+DN:%s:%ld:%d\n"
@@ -2910,18 +3378,18 @@ static void print_message(const char *s, long num, int length)
 }
 
 static void pkey_print_message(const char *str, const char *str2, long num,
-                               int bits, int tm)
+                               unsigned int bits, int tm)
 {
 #ifdef SIGALRM
     BIO_printf(bio_err,
                mr ? "+DTP:%d:%s:%s:%d\n"
-               : "Doing %d bit %s %s's for %ds: ", bits, str, str2, tm);
+               : "Doing %u bits %s %s's for %ds: ", bits, str, str2, tm);
     (void)BIO_flush(bio_err);
     alarm(tm);
 #else
     BIO_printf(bio_err,
                mr ? "+DNP:%ld:%d:%s:%s\n"
-               : "Doing %ld %d bit %s %s's: ", num, bits, str, str2);
+               : "Doing %ld %u bits %s %s's: ", num, bits, str, str2);
     (void)BIO_flush(bio_err);
 #endif
 }
@@ -2947,7 +3415,7 @@ static char *sstrsep(char **string, const char *delim)
     if (**string == 0)
         return NULL;
 
-    memset(isdelim, 0, sizeof isdelim);
+    memset(isdelim, 0, sizeof(isdelim));
     isdelim[0] = 1;
 
     while (*delim) {
@@ -2967,14 +3435,14 @@ static char *sstrsep(char **string, const char *delim)
     return token;
 }
 
-static int do_multi(int multi)
+static int do_multi(int multi, int size_num)
 {
     int n;
     int fd[2];
     int *fds;
     static char sep[] = ":";
 
-    fds = malloc(sizeof(*fds) * multi);
+    fds = app_malloc(sizeof(*fds) * multi, "fd buffer for do_multi");
     for (n = 0; n < multi; ++n) {
         if (pipe(fd) == -1) {
             BIO_printf(bio_err, "pipe failure\n");
@@ -3008,7 +3476,7 @@ static int do_multi(int multi)
         char *p;
 
         f = fdopen(fds[n], "r");
-        while (fgets(buf, sizeof buf, f)) {
+        while (fgets(buf, sizeof(buf), f)) {
             p = strchr(buf, '\n');
             if (p)
                 *p = '\0';
@@ -3026,7 +3494,7 @@ static int do_multi(int multi)
                 p = buf + 3;
                 alg = atoi(sstrsep(&p, sep));
                 sstrsep(&p, sep);
-                for (j = 0; j < SIZE_NUM; ++j)
+                for (j = 0; j < size_num; ++j)
                     results[alg][j] += atof(sstrsep(&p, sep));
             } else if (strncmp(buf, "+F2:", 4) == 0) {
                 int k;
@@ -3081,11 +3549,20 @@ 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;
+            } else if (strncmp(buf, "+F6:", 4) == 0) {
+                int k;
+                double d;
 
+                p = buf + 4;
+                k = atoi(sstrsep(&p, sep));
+                sstrsep(&p, sep);
+
+                d = atof(sstrsep(&p, sep));
+                eddsa_results[k][0] += d;
+
+                d = atof(sstrsep(&p, sep));
+                eddsa_results[k][1] += d;
             }
 # endif
 
@@ -3103,25 +3580,39 @@ static int do_multi(int multi)
 }
 #endif
 
-static void multiblock_speed(const EVP_CIPHER *evp_cipher)
+static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
+                             const openssl_speed_sec_t *seconds)
 {
-    static int mblengths[] =
+    static const int mblengths_list[] =
         { 8 * 1024, 2 * 8 * 1024, 4 * 8 * 1024, 8 * 8 * 1024, 8 * 16 * 1024 };
-    int j, count, num = OSSL_NELEM(mblengths);
+    const int *mblengths = mblengths_list;
+    int j, count, keylen, num = OSSL_NELEM(mblengths_list);
     const char *alg_name;
-    unsigned char *inp, *out, no_key[32], no_iv[16];
+    unsigned char *inp, *out, *key, no_key[32], no_iv[16];
     EVP_CIPHER_CTX *ctx;
     double d = 0.0;
 
+    if (lengths_single) {
+        mblengths = &lengths_single;
+        num = 1;
+    }
+
     inp = app_malloc(mblengths[num - 1], "multiblock input buffer");
     out = app_malloc(mblengths[num - 1] + 1024, "multiblock output buffer");
     ctx = EVP_CIPHER_CTX_new();
-    EVP_EncryptInit_ex(ctx, evp_cipher, NULL, no_key, no_iv);
+    EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv);
+
+    keylen = EVP_CIPHER_CTX_key_length(ctx);
+    key = app_malloc(keylen, "evp_cipher key");
+    EVP_CIPHER_CTX_rand_key(ctx, key);
+    EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);
+    OPENSSL_clear_free(key, keylen);
+
     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key), no_key);
     alg_name = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
 
     for (j = 0; j < num; j++) {
-        print_message(alg_name, 0, mblengths[j]);
+        print_message(alg_name, 0, mblengths[j], seconds->sym);
         Time_F(START);
         for (count = 0, run = 1; run && count < 0x7fffffff; count++) {
             unsigned char aad[EVP_AEAD_TLS1_AAD_LEN];
@@ -3154,8 +3645,8 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher)
 
                 RAND_bytes(out, 16);
                 len += 16;
-                aad[11] = len >> 8;
-                aad[12] = len;
+                aad[11] = (unsigned char)(len >> 8);
+                aad[12] = (unsigned char)(len);
                 pad = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD,
                                           EVP_AEAD_TLS1_AAD_LEN, aad);
                 EVP_Cipher(ctx, out, inp, len + pad);