Update copyright year
[openssl.git] / apps / speed.c
index 160841d040b104f99cba29e8ac549f591299a666..506737d05fc6947d840d3f1ffb496a891bd3e09c 100644 (file)
@@ -1,86 +1,27 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-/* ====================================================================
- * 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.
+/*
+ * Copyright 1995-2019 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
  */
 
 #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>
 #include <openssl/modes.h>
 
 #ifndef HAVE_FORK
-# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS)
+# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VXWORKS)
 #  define HAVE_FORK 0
 # else
 #  define HAVE_FORK 1
 # 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];
-    EC_KEY *ecdh_a[EC_NUM];
-    EC_KEY *ecdh_b[EC_NUM];
-    unsigned char *secret_a;
-    unsigned char *secret_b;
-#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
@@ -254,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);
@@ -267,74 +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 ECDH_compute_key_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 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;
@@ -376,33 +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
 
-#ifndef OPENSSL_NO_EC
-static const int KDF1_SHA1_len = 20;
-static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
-                       size_t *outlen)
-{
-    if (*outlen < SHA_DIGEST_LENGTH)
-        return NULL;
-    *outlen = SHA_DIGEST_LENGTH;
-    return SHA1(in, inlen, out);
-}
-#endif                         /* OPENSSL_NO_EC */
+static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
+                             const openssl_speed_sec_t *seconds);
 
-static void multiblock_speed(const EVP_CIPHER *evp_cipher);
-
-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;
@@ -413,31 +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;
 
-OPTIONS speed_options[] = {
+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)"},
+    {"aead", OPT_AEAD, '-',
+     "Benchmark EVP-named AEAD cipher in TLS-like sequence"},
+    {"mb", OPT_MB, '-',
+     "Enable (tls1>=1) multi-block mode on EVP-named cipher"},
     {"mr", OPT_MR, '-', "Produce machine readable output"},
-    {"mb", OPT_MB, '-'},
-    {"misalign", OPT_MISALIGN, 'n', "Amount to mis-align buffers"},
-    {"elapsed", OPT_ELAPSED, '-',
-     "Measure time in real time instead of CPU user time"},
 #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"},
+    {"async_jobs", OPT_ASYNCJOBS, 'p',
+     "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
@@ -470,7 +368,22 @@ 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
@@ -482,8 +395,6 @@ static OPT_PAIR doit_choices[] = {
 #endif
 #ifndef OPENSSL_NO_MD5
     {"md5", D_MD5},
-#endif
-#ifndef OPENSSL_NO_MD5
     {"hmac", D_HMAC},
 #endif
     {"sha1", D_SHA1},
@@ -537,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
@@ -559,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
@@ -586,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},
@@ -605,9 +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}
 };
-static OPT_PAIR ecdh_choices[] = {
+# define ECDSA_NUM       OSSL_NELEM(ecdsa_choices)
+
+static double ecdsa_results[ECDSA_NUM][2];    /* 2 ops: sign then verify */
+
+static const OPT_PAIR ecdh_choices[] = {
     {"ecdhp160", R_EC_P160},
     {"ecdhp192", R_EC_P192},
     {"ecdhp224", R_EC_P224},
@@ -624,33 +559,87 @@ 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))
 # define COUNT(d) (d)
 #else
-# define COND(c) (run && count<0x7fffffff)
+# define COND(unused_cond) (run && count<0x7fffffff)
 # define COUNT(d) (count)
-#endif                         /* SIGALRM */
+#endif                          /* SIGALRM */
+
+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 int testnum;
-static char *engine_id = NULL;
+static unsigned int testnum;
 
+/* Nb of iterations to do per algorithm and key-size */
+static long c[ALGOR_NUM][OSSL_NELEM(lengths_list)];
 
 #ifndef OPENSSL_NO_MD2
 static int EVP_Digest_MD2_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char md2[MD2_DIGEST_LENGTH];
     int count;
-    for (count = 0; COND(c[D_MD2][testnum]); count++)
-        EVP_Digest(buf, (unsigned long)lengths[testnum], &(md2[0]), NULL,
-                EVP_md2(), NULL);
+
+    for (count = 0; COND(c[D_MD2][testnum]); count++) {
+        if (!EVP_Digest(buf, (size_t)lengths[testnum], md2, NULL, EVP_md2(),
+                        NULL))
+            return -1;
+    }
     return count;
 }
 #endif
@@ -658,13 +647,16 @@ static int EVP_Digest_MD2_loop(void *args)
 #ifndef OPENSSL_NO_MDC2
 static int EVP_Digest_MDC2_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char mdc2[MDC2_DIGEST_LENGTH];
     int count;
-    for (count = 0; COND(c[D_MDC2][testnum]); count++)
-        EVP_Digest(buf, (unsigned long)lengths[testnum], &(mdc2[0]), NULL,
-                EVP_mdc2(), NULL);
+
+    for (count = 0; COND(c[D_MDC2][testnum]); count++) {
+        if (!EVP_Digest(buf, (size_t)lengths[testnum], mdc2, NULL, EVP_mdc2(),
+                        NULL))
+            return -1;
+    }
     return count;
 }
 #endif
@@ -672,13 +664,16 @@ static int EVP_Digest_MDC2_loop(void *args)
 #ifndef OPENSSL_NO_MD4
 static int EVP_Digest_MD4_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char md4[MD4_DIGEST_LENGTH];
     int count;
-    for (count = 0; COND(c[D_MD4][testnum]); count++)
-        EVP_Digest(&(buf[0]), (unsigned long)lengths[testnum], &(md4[0]),
-                NULL, EVP_md4(), NULL);
+
+    for (count = 0; COND(c[D_MD4][testnum]); count++) {
+        if (!EVP_Digest(buf, (size_t)lengths[testnum], md4, NULL, EVP_md4(),
+                        NULL))
+            return -1;
+    }
     return count;
 }
 #endif
@@ -686,7 +681,7 @@ static int EVP_Digest_MD4_loop(void *args)
 #ifndef OPENSSL_NO_MD5
 static int MD5_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char md5[MD5_DIGEST_LENGTH];
     int count;
@@ -697,15 +692,16 @@ static int MD5_loop(void *args)
 
 static int HMAC_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     HMAC_CTX *hctx = tempargs->hctx;
     unsigned char hmac[MD5_DIGEST_LENGTH];
     int count;
+
     for (count = 0; COND(c[D_HMAC][testnum]); count++) {
         HMAC_Init_ex(hctx, NULL, 0, NULL, NULL);
         HMAC_Update(hctx, buf, lengths[testnum]);
-        HMAC_Final(hctx, &(hmac[0]), NULL);
+        HMAC_Final(hctx, hmac, NULL);
     }
     return count;
 }
@@ -713,7 +709,7 @@ static int HMAC_loop(void *args)
 
 static int SHA1_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char sha[SHA_DIGEST_LENGTH];
     int count;
@@ -724,7 +720,7 @@ static int SHA1_loop(void *args)
 
 static int SHA256_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char sha256[SHA256_DIGEST_LENGTH];
     int count;
@@ -735,7 +731,7 @@ static int SHA256_loop(void *args)
 
 static int SHA512_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char sha512[SHA512_DIGEST_LENGTH];
     int count;
@@ -747,7 +743,7 @@ static int SHA512_loop(void *args)
 #ifndef OPENSSL_NO_WHIRLPOOL
 static int WHIRLPOOL_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH];
     int count;
@@ -760,13 +756,15 @@ static int WHIRLPOOL_loop(void *args)
 #ifndef OPENSSL_NO_RMD160
 static int EVP_Digest_RMD160_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char rmd160[RIPEMD160_DIGEST_LENGTH];
     int count;
-    for (count = 0; COND(c[D_RMD160][testnum]); count++)
-        EVP_Digest(buf, (unsigned long)lengths[testnum], &(rmd160[0]), NULL,
-                EVP_ripemd160(), NULL);
+    for (count = 0; COND(c[D_RMD160][testnum]); count++) {
+        if (!EVP_Digest(buf, (size_t)lengths[testnum], &(rmd160[0]),
+                        NULL, EVP_ripemd160(), NULL))
+            return -1;
+    }
     return count;
 }
 #endif
@@ -775,11 +773,11 @@ static int EVP_Digest_RMD160_loop(void *args)
 static RC4_KEY rc4_ks;
 static int RC4_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     int count;
     for (count = 0; COND(c[D_RC4][testnum]); count++)
-        RC4(&rc4_ks, (unsigned int)lengths[testnum], buf, buf);
+        RC4(&rc4_ks, (size_t)lengths[testnum], buf, buf);
     return count;
 }
 #endif
@@ -791,24 +789,23 @@ static DES_key_schedule sch2;
 static DES_key_schedule sch3;
 static int DES_ncbc_encrypt_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     int count;
     for (count = 0; COND(c[D_CBC_DES][testnum]); count++)
         DES_ncbc_encrypt(buf, buf, lengths[testnum], &sch,
-                &DES_iv, DES_ENCRYPT);
+                         &DES_iv, DES_ENCRYPT);
     return count;
 }
 
 static int DES_ede3_cbc_encrypt_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     int count;
     for (count = 0; COND(c[D_EDE3_DES][testnum]); count++)
         DES_ede3_cbc_encrypt(buf, buf, lengths[testnum],
-                &sch, &sch2, &sch3,
-                &DES_iv, DES_ENCRYPT);
+                             &sch, &sch2, &sch3, &DES_iv, DES_ENCRYPT);
     return count;
 }
 #endif
@@ -819,82 +816,76 @@ static unsigned char iv[2 * MAX_BLOCK_SIZE / 8];
 static AES_KEY aes_ks1, aes_ks2, aes_ks3;
 static int AES_cbc_128_encrypt_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     int count;
     for (count = 0; COND(c[D_CBC_128_AES][testnum]); count++)
         AES_cbc_encrypt(buf, buf,
-                (unsigned long)lengths[testnum], &aes_ks1,
-                iv, AES_ENCRYPT);
+                        (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT);
     return count;
 }
 
 static int AES_cbc_192_encrypt_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     int count;
     for (count = 0; COND(c[D_CBC_192_AES][testnum]); count++)
         AES_cbc_encrypt(buf, buf,
-                (unsigned long)lengths[testnum], &aes_ks2,
-                iv, AES_ENCRYPT);
+                        (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT);
     return count;
 }
 
 static int AES_cbc_256_encrypt_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     int count;
     for (count = 0; COND(c[D_CBC_256_AES][testnum]); count++)
         AES_cbc_encrypt(buf, buf,
-                (unsigned long)lengths[testnum], &aes_ks3,
-                iv, AES_ENCRYPT);
+                        (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT);
     return count;
 }
 
 static int AES_ige_128_encrypt_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char *buf2 = tempargs->buf2;
     int count;
     for (count = 0; COND(c[D_IGE_128_AES][testnum]); count++)
         AES_ige_encrypt(buf, buf2,
-                (unsigned long)lengths[testnum], &aes_ks1,
-                iv, AES_ENCRYPT);
+                        (size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT);
     return count;
 }
 
 static int AES_ige_192_encrypt_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char *buf2 = tempargs->buf2;
     int count;
     for (count = 0; COND(c[D_IGE_192_AES][testnum]); count++)
         AES_ige_encrypt(buf, buf2,
-                (unsigned long)lengths[testnum], &aes_ks2,
-                iv, AES_ENCRYPT);
+                        (size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT);
     return count;
 }
 
 static int AES_ige_256_encrypt_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char *buf2 = tempargs->buf2;
     int count;
     for (count = 0; COND(c[D_IGE_256_AES][testnum]); count++)
         AES_ige_encrypt(buf, buf2,
-                (unsigned long)lengths[testnum], &aes_ks3,
-                iv, AES_ENCRYPT);
+                        (size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT);
     return count;
 }
 
 static int CRYPTO_gcm128_aad_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     GCM128_CONTEXT *gcm_ctx = tempargs->gcm_ctx;
     int count;
@@ -903,23 +894,83 @@ 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)
 {
-    loopargs_t *tempargs = (loopargs_t *)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(save_count * 4 * lengths[0] / lengths[testnum]);
-                count++)
-            EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
+        EVP_DecryptFinal_ex(ctx, buf, &outl);
     else
-        for (count = 0;
-                COND(save_count * 4 * lengths[0] / lengths[testnum]);
-                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
@@ -927,29 +978,69 @@ 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)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char md[EVP_MAX_MD_SIZE];
     int count;
-    for (count = 0;
-            COND(save_count * 4 * lengths[0] / lengths[testnum]); count++)
-        EVP_Digest(buf, lengths[testnum], &(md[0]), NULL, evp_md, NULL);
+#ifndef SIGALRM
+    int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
+#endif
 
+    for (count = 0; COND(nb_iter); count++) {
+        if (!EVP_Digest(buf, lengths[testnum], md, NULL, evp_md, NULL))
+            return -1;
+    }
     return count;
 }
 
 #ifndef OPENSSL_NO_RSA
-static long rsa_c[RSA_NUM][2];
+static long rsa_c[RSA_NUM][2];  /* # RSA iteration test */
 
 static int RSA_sign_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char *buf2 = tempargs->buf2;
-    unsigned int *rsa_num = tempargs->siglen;
+    unsigned int *rsa_num = &tempargs->siglen;
     RSA **rsa_key = tempargs->rsa_key;
     int ret, count;
     for (count = 0; COND(rsa_c[testnum][0]); count++) {
@@ -966,14 +1057,15 @@ static int RSA_sign_loop(void *args)
 
 static int RSA_verify_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char *buf2 = tempargs->buf2;
-    unsigned int rsa_num = *(tempargs->siglen);
+    unsigned int rsa_num = tempargs->siglen;
     RSA **rsa_key = tempargs->rsa_key;
     int ret, count;
     for (count = 0; COND(rsa_c[testnum][1]); count++) {
-        ret = RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
+        ret =
+            RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
         if (ret <= 0) {
             BIO_printf(bio_err, "RSA verify failure\n");
             ERR_print_errors(bio_err);
@@ -989,11 +1081,11 @@ static int RSA_verify_loop(void *args)
 static long dsa_c[DSA_NUM][2];
 static int DSA_sign_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char *buf2 = tempargs->buf2;
     DSA **dsa_key = tempargs->dsa_key;
-    unsigned int *siglen = tempargs->siglen;
+    unsigned int *siglen = &tempargs->siglen;
     int ret, count;
     for (count = 0; COND(dsa_c[testnum][0]); count++) {
         ret = DSA_sign(0, buf, 20, buf2, siglen, dsa_key[testnum]);
@@ -1009,11 +1101,11 @@ static int DSA_sign_loop(void *args)
 
 static int DSA_verify_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     unsigned char *buf2 = tempargs->buf2;
     DSA **dsa_key = tempargs->dsa_key;
-    unsigned int siglen = *(tempargs->siglen);
+    unsigned int siglen = tempargs->siglen;
     int ret, count;
     for (count = 0; COND(dsa_c[testnum][1]); count++) {
         ret = DSA_verify(0, buf, 20, buf2, siglen, dsa_key[testnum]);
@@ -1029,18 +1121,17 @@ 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;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     EC_KEY **ecdsa = tempargs->ecdsa;
     unsigned char *ecdsasig = tempargs->buf2;
-    unsigned int *ecdsasiglen = tempargs->siglen;
+    unsigned int *ecdsasiglen = &tempargs->siglen;
     int ret, count;
     for (count = 0; COND(ecdsa_c[testnum][0]); count++) {
-        ret = ECDSA_sign(0, buf, 20,
-                ecdsasig, ecdsasiglen, ecdsa[testnum]);
+        ret = ECDSA_sign(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]);
         if (ret == 0) {
             BIO_printf(bio_err, "ECDSA sign failure\n");
             ERR_print_errors(bio_err);
@@ -1053,15 +1144,14 @@ static int ECDSA_sign_loop(void *args)
 
 static int ECDSA_verify_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
+    loopargs_t *tempargs = *(loopargs_t **) args;
     unsigned char *buf = tempargs->buf;
     EC_KEY **ecdsa = tempargs->ecdsa;
     unsigned char *ecdsasig = tempargs->buf2;
-    unsigned int ecdsasiglen = *(tempargs->siglen);
+    unsigned int ecdsasiglen = tempargs->siglen;
     int ret, count;
     for (count = 0; COND(ecdsa_c[testnum][1]); count++) {
-        ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen,
-                ecdsa[testnum]);
+        ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]);
         if (ret != 1) {
             BIO_printf(bio_err, "ECDSA verify failure\n");
             ERR_print_errors(bio_err);
@@ -1072,64 +1162,107 @@ static int ECDSA_verify_loop(void *args)
     return count;
 }
 
-static int outlen;
-static void *(*kdf) (const void *in, size_t inlen, void *out,
-        size_t *xoutlen);
+/* ******************************************************************** */
+static long ecdh_c[EC_NUM][1];
 
-static int ECDH_compute_key_loop(void *args)
+static int ECDH_EVP_derive_key_loop(void *args)
 {
-    loopargs_t *tempargs = (loopargs_t *)args;
-    EC_KEY **ecdh_a = tempargs->ecdh_a;
-    EC_KEY **ecdh_b = tempargs->ecdh_b;
-    unsigned char *secret_a = tempargs->secret_a;
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    EVP_PKEY_CTX *ctx = tempargs->ecdh_ctx[testnum];
+    unsigned char *derived_secret = tempargs->secret_a;
     int count;
-    for (count = 0; COND(ecdh_c[testnum][0]); count++) {
-        ECDH_compute_key(secret_a, outlen,
-                EC_KEY_get0_public_key(ecdh_b[testnum]),
-                ecdh_a[testnum], kdf);
+    size_t *outlen = &(tempargs->outlen[testnum]);
+
+    for (count = 0; COND(ecdh_c[testnum][0]); count++)
+        EVP_PKEY_derive(ctx, derived_secret, outlen);
+
+    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;
 }
-#endif
 
+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, int (*loop_function)(void *), loopargs_t *loopargs)
+static int run_benchmark(int async_jobs,
+                         int (*loop_function) (void *), loopargs_t * loopargs)
 {
     int job_op_count = 0;
     int total_op_count = 0;
     int num_inprogress = 0;
-    int error = 0;
-    int i = 0;
+    int error = 0, i = 0, ret = 0;
     OSSL_ASYNC_FD job_fd = 0;
     size_t num_job_fds = 0;
 
     run = 1;
 
     if (async_jobs == 0) {
-        return loop_function((void *)loopargs);
+        return loop_function((void *)&loopargs);
     }
 
-
     for (i = 0; i < async_jobs && !error; i++) {
-        switch (ASYNC_start_job(&(loopargs[i].inprogress_job), loopargs[i].wait_ctx,
-                                &job_op_count, loop_function,
-                                (void *)(loopargs + i), sizeof(loopargs_t))) {
-            case ASYNC_PAUSE:
-                ++num_inprogress;
-                break;
-            case ASYNC_FINISH:
-                if (job_op_count == -1) {
-                    error = 1;
-                } else {
-                    total_op_count += job_op_count;
-                }
-                break;
-            case ASYNC_NO_JOBS:
-            case ASYNC_ERR:
-                BIO_printf(bio_err, "Failure in the job\n");
-                ERR_print_errors(bio_err);
+        loopargs_t *looparg_item = loopargs + i;
+
+        /* Copy pointer content (looparg_t item address) into async context */
+        ret = ASYNC_start_job(&loopargs[i].inprogress_job, loopargs[i].wait_ctx,
+                              &job_op_count, loop_function,
+                              (void *)&looparg_item, sizeof(looparg_item));
+        switch (ret) {
+        case ASYNC_PAUSE:
+            ++num_inprogress;
+            break;
+        case ASYNC_FINISH:
+            if (job_op_count == -1) {
                 error = 1;
-                break;
+            } else {
+                total_op_count += job_op_count;
+            }
+            break;
+        case ASYNC_NO_JOBS:
+        case ASYNC_ERR:
+            BIO_printf(bio_err, "Failure in the job\n");
+            ERR_print_errors(bio_err);
+            error = 1;
+            break;
         }
     }
 
@@ -1147,14 +1280,16 @@ static int run_benchmark(int async_jobs, int (*loop_function)(void *), loopargs_
             if (loopargs[i].inprogress_job == NULL)
                 continue;
 
-            if (!ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, NULL, &num_job_fds)
-                    || num_job_fds > 1) {
+            if (!ASYNC_WAIT_CTX_get_all_fds
+                (loopargs[i].wait_ctx, NULL, &num_job_fds)
+                || num_job_fds > 1) {
                 BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n");
                 ERR_print_errors(bio_err);
                 error = 1;
                 break;
             }
-            ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd, &num_job_fds);
+            ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd,
+                                       &num_job_fds);
             FD_SET(job_fd, &waitfdset);
             if (job_fd > max_fd)
                 max_fd = job_fd;
@@ -1162,9 +1297,9 @@ static int run_benchmark(int async_jobs, int (*loop_function)(void *), loopargs_
 
         if (max_fd >= (OSSL_ASYNC_FD)FD_SETSIZE) {
             BIO_printf(bio_err,
-                    "Error: max_fd (%d) must be smaller than FD_SETSIZE (%d). "
-                    "Decrease the value of async_jobs\n",
-                    max_fd, FD_SETSIZE);
+                       "Error: max_fd (%d) must be smaller than FD_SETSIZE (%d). "
+                       "Decrease the value of async_jobs\n",
+                       max_fd, FD_SETSIZE);
             ERR_print_errors(bio_err);
             error = 1;
             break;
@@ -1189,46 +1324,51 @@ static int run_benchmark(int async_jobs, int (*loop_function)(void *), loopargs_
             if (loopargs[i].inprogress_job == NULL)
                 continue;
 
-            if (!ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, NULL, &num_job_fds)
-                    || num_job_fds > 1) {
+            if (!ASYNC_WAIT_CTX_get_all_fds
+                (loopargs[i].wait_ctx, NULL, &num_job_fds)
+                || num_job_fds > 1) {
                 BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n");
                 ERR_print_errors(bio_err);
                 error = 1;
                 break;
             }
-            ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd, &num_job_fds);
+            ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd,
+                                       &num_job_fds);
 
 #if defined(OPENSSL_SYS_UNIX)
             if (num_job_fds == 1 && !FD_ISSET(job_fd, &waitfdset))
                 continue;
 #elif defined(OPENSSL_SYS_WINDOWS)
-            if (num_job_fds == 1 &&
-                    !PeekNamedPipe(job_fd, NULL, 0, NULL, &avail, NULL) && avail > 0)
+            if (num_job_fds == 1
+                && !PeekNamedPipe(job_fd, NULL, 0, NULL, &avail, NULL)
+                && avail > 0)
                 continue;
 #endif
 
-            switch (ASYNC_start_job(&(loopargs[i].inprogress_job), loopargs[i].wait_ctx,
-                        &job_op_count, loop_function, (void *)(loopargs + i),
-                        sizeof(loopargs_t))) {
-                case ASYNC_PAUSE:
-                    break;
-                case ASYNC_FINISH:
-                    if (job_op_count == -1) {
-                        error = 1;
-                    } else {
-                        total_op_count += job_op_count;
-                    }
-                    --num_inprogress;
-                    loopargs[i].inprogress_job = NULL;
-                    break;
-                case ASYNC_NO_JOBS:
-                case ASYNC_ERR:
-                    --num_inprogress;
-                    loopargs[i].inprogress_job = NULL;
-                    BIO_printf(bio_err, "Failure in the job\n");
-                    ERR_print_errors(bio_err);
+            ret = ASYNC_start_job(&loopargs[i].inprogress_job,
+                                  loopargs[i].wait_ctx, &job_op_count,
+                                  loop_function, (void *)(loopargs + i),
+                                  sizeof(loopargs_t));
+            switch (ret) {
+            case ASYNC_PAUSE:
+                break;
+            case ASYNC_FINISH:
+                if (job_op_count == -1) {
                     error = 1;
-                    break;
+                } else {
+                    total_op_count += job_op_count;
+                }
+                --num_inprogress;
+                loopargs[i].inprogress_job = NULL;
+                break;
+            case ASYNC_NO_JOBS:
+            case ASYNC_ERR:
+                --num_inprogress;
+                loopargs[i].inprogress_job = NULL;
+                BIO_printf(bio_err, "Failure in the job\n");
+                ERR_print_errors(bio_err);
+                error = 1;
+                break;
             }
         }
     }
@@ -1238,27 +1378,33 @@ static int run_benchmark(int async_jobs, int (*loop_function)(void *), loopargs_
 
 int speed_main(int argc, char **argv)
 {
+    ENGINE *e = NULL;
     loopargs_t *loopargs = NULL;
-    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, doit[ALGOR_NUM], pr_header = 0;
-#ifndef OPENSSL_NO_DSA
-    int dsa_doit[DSA_NUM];
-#endif
-    int rsa_doit[RSA_NUM];
-    int ret = 1, i, k, misalign = 0;
-    long c[ALGOR_NUM][SIZE_NUM], count = 0, save_count = 0;
+    int async_init = 0, multiblock = 0, pr_header = 0;
+    int doit[ALGOR_NUM] = { 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;
-    /* What follows are the buffers and key material. */
-#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA)
+#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
     RC5_32_KEY rc5_ks;
 #endif
@@ -1318,94 +1464,80 @@ int speed_main(int argc, char **argv)
     };
 #endif
 #ifndef OPENSSL_NO_RSA
-    static unsigned int rsa_bits[RSA_NUM] = {
+    static const unsigned int rsa_bits[RSA_NUM] = {
         512, 1024, 2048, 3072, 4096, 7680, 15360
     };
-    static unsigned char *rsa_data[RSA_NUM] = {
+    static const unsigned char *rsa_data[RSA_NUM] = {
         test512, test1024, test2048, test3072, test4096, test7680, test15360
     };
-    static int rsa_data_length[RSA_NUM] = {
+    static const int rsa_data_length[RSA_NUM] = {
         sizeof(test512), sizeof(test1024),
         sizeof(test2048), sizeof(test3072),
         sizeof(test4096), sizeof(test7680),
         sizeof(test15360)
     };
+    int rsa_doit[RSA_NUM] = { 0 };
+    int primes = RSA_DEFAULT_PRIME_NUM;
 #endif
 #ifndef OPENSSL_NO_DSA
-    static unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
+    static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
+    int dsa_doit[DSA_NUM] = { 0 };
 #endif
 #ifndef OPENSSL_NO_EC
     /*
      * 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 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 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}
     };
-#endif
-#ifndef OPENSSL_NO_EC
-    int ecdsa_doit[EC_NUM];
-    int secret_size_a, secret_size_b;
-    int ecdh_checks = 1;
-    int secret_idx = 0;
-    long ecdh_c[EC_NUM][2];
-    int ecdh_doit[EC_NUM];
-#endif
-
-    memset(results, 0, sizeof(results));
-
-    memset(c, 0, sizeof(c));
-#ifndef OPENSSL_NO_DES
-    memset(DES_iv, 0, sizeof(DES_iv));
-#endif
-    memset(iv, 0, sizeof(iv));
-
-    for (i = 0; i < ALGOR_NUM; i++)
-        doit[i] = 0;
-    for (i = 0; i < RSA_NUM; i++)
-        rsa_doit[i] = 0;
-#ifndef OPENSSL_NO_DSA
-    for (i = 0; i < DSA_NUM; i++)
-        dsa_doit[i] = 0;
-#endif
-#ifndef OPENSSL_NO_EC
-    for (i = 0; i < EC_NUM; i++)
-        ecdsa_doit[i] = 0;
-    for (i = 0; i < EC_NUM; i++)
-        ecdh_doit[i] = 0;
-#endif
-
-    misalign = 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);
     while ((o = opt_next()) != OPT_EOF) {
@@ -1423,12 +1555,13 @@ 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());
             if (evp_cipher == NULL && evp_md == NULL) {
                 BIO_printf(bio_err,
-                           "%s: %s  an unknown cipher or digest\n",
+                           "%s: %s is an unknown cipher or digest\n",
                            prog, opt_arg());
                 goto end;
             }
@@ -1459,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:
@@ -1475,6 +1612,32 @@ int speed_main(int argc, char **argv)
             break;
         case OPT_MB:
             multiblock = 1;
+#ifdef OPENSSL_NO_MULTIBLOCK
+            BIO_printf(bio_err,
+                       "%s: -mb specified but multi-block support is disabled\n",
+                       prog);
+            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;
         }
     }
@@ -1482,7 +1645,7 @@ int speed_main(int argc, char **argv)
     argv = opt_rest();
 
     /* Remaining arguments are algorithms. */
-    for ( ; *argv; argv++) {
+    for (; *argv; argv++) {
         if (found(*argv, doit_choices, &i)) {
             doit[i] = 1;
             continue;
@@ -1498,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)) {
@@ -1528,21 +1685,19 @@ int speed_main(int argc, char **argv)
         }
 #endif
         if (strcmp(*argv, "aes") == 0) {
-            doit[D_CBC_128_AES] = doit[D_CBC_192_AES] =
-                doit[D_CBC_256_AES] = 1;
+            doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1;
             continue;
         }
 #ifndef OPENSSL_NO_CAMELLIA
         if (strcmp(*argv, "camellia") == 0) {
-            doit[D_CBC_128_CML] = doit[D_CBC_192_CML] =
-                doit[D_CBC_256_CML] = 1;
+            doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1;
             continue;
         }
 #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)) {
@@ -1550,29 +1705,68 @@ 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) {
-        if (!ASYNC_init_thread(async_jobs, async_jobs)) {
+        async_init = ASYNC_init_thread(async_jobs, async_jobs);
+        if (!async_init) {
             BIO_printf(bio_err, "Error creating the ASYNC job pool\n");
             goto end;
         }
     }
 
     loopargs_len = (async_jobs == 0 ? 1 : async_jobs);
-    loopargs = app_malloc(loopargs_len * sizeof(loopargs_t), "array of loopargs");
+    loopargs =
+        app_malloc(loopargs_len * sizeof(loopargs_t), "array of loopargs");
     memset(loopargs, 0, loopargs_len * sizeof(loopargs_t));
 
     for (i = 0; i < loopargs_len; i++) {
@@ -1584,12 +1778,18 @@ 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;
-        loopargs[i].siglen = app_malloc(sizeof(unsigned int), "signature length");
 #ifndef OPENSSL_NO_EC
         loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a");
         loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b");
@@ -1597,29 +1797,33 @@ 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
 
     /* Initialize the engine after the fork */
-    (void)setup_engine(engine_id, 0);
+    e = setup_engine(engine_id, 0);
 
     /* No parameters; turn on everything. */
     if ((argc == 0) && !doit[D_EVP]) {
         for (i = 0; i < ALGOR_NUM; i++)
             if (i != D_EVP)
                 doit[i] = 1;
+#ifndef OPENSSL_NO_RSA
         for (i = 0; i < RSA_NUM; i++)
             rsa_doit[i] = 1;
+#endif
 #ifndef OPENSSL_NO_DSA
         for (i = 0; i < DSA_NUM; i++)
             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++)
@@ -1633,14 +1837,19 @@ 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;
 
             p = rsa_data[k];
-            loopargs[i].rsa_key[k] = d2i_RSAPrivateKey(NULL, &p, rsa_data_length[k]);
+            loopargs[i].rsa_key[k] =
+                d2i_RSAPrivateKey(NULL, &p, rsa_data_length[k]);
             if (loopargs[i].rsa_key[k] == NULL) {
-                BIO_printf(bio_err, "internal error loading RSA key number %d\n",
-                        k);
+                BIO_printf(bio_err,
+                           "internal error loading RSA key number %d\n", k);
                 goto end;
             }
         }
@@ -1648,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
@@ -1685,10 +1894,7 @@ int speed_main(int argc, char **argv)
     BF_set_key(&bf_ks, 16, key16);
 #endif
 #ifndef OPENSSL_NO_CAST
-    CAST_set_key(&cast_ks, 16, key16);
-#endif
-#ifndef OPENSSL_NO_RSA
-    memset(rsa_c, 0, sizeof(rsa_c));
+    CAST_set_key(&cast_ks, 16, key16);
 #endif
 #ifndef SIGALRM
 # ifndef OPENSSL_NO_DES
@@ -1733,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];
@@ -1751,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];
 
@@ -1780,11 +1988,11 @@ int speed_main(int argc, char **argv)
     for (i = 1; i < RSA_NUM; i++) {
         rsa_c[i][0] = rsa_c[i - 1][0] / 8;
         rsa_c[i][1] = rsa_c[i - 1][1] / 4;
-        if ((rsa_doit[i] <= 1) && (rsa_c[i][0] == 0))
+        if (rsa_doit[i] <= 1 && rsa_c[i][0] == 0)
             rsa_doit[i] = 0;
         else {
             if (rsa_c[i][0] == 0) {
-                rsa_c[i][0] = 1;
+                rsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
                 rsa_c[i][1] = 20;
             }
         }
@@ -1797,11 +2005,11 @@ int speed_main(int argc, char **argv)
     for (i = 1; i < DSA_NUM; i++) {
         dsa_c[i][0] = dsa_c[i - 1][0] / 4;
         dsa_c[i][1] = dsa_c[i - 1][1] / 4;
-        if ((dsa_doit[i] <= 1) && (dsa_c[i][0] == 0))
+        if (dsa_doit[i] <= 1 && dsa_c[i][0] == 0)
             dsa_doit[i] = 0;
         else {
-            if (dsa_c[i] == 0) {
-                dsa_c[i][0] = 1;
+            if (dsa_c[i][0] == 0) {
+                dsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
                 dsa_c[i][1] = 1;
             }
         }
@@ -1814,10 +2022,10 @@ int speed_main(int argc, char **argv)
     for (i = R_EC_P192; i <= R_EC_P521; i++) {
         ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
         ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
-        if ((ecdsa_doit[i] <= 1) && (ecdsa_c[i][0] == 0))
+        if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
             ecdsa_doit[i] = 0;
         else {
-            if (ecdsa_c[i] == 0) {
+            if (ecdsa_c[i][0] == 0) {
                 ecdsa_c[i][0] = 1;
                 ecdsa_c[i][1] = 1;
             }
@@ -1828,10 +2036,10 @@ int speed_main(int argc, char **argv)
     for (i = R_EC_K233; i <= R_EC_K571; i++) {
         ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
         ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
-        if ((ecdsa_doit[i] <= 1) && (ecdsa_c[i][0] == 0))
+        if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
             ecdsa_doit[i] = 0;
         else {
-            if (ecdsa_c[i] == 0) {
+            if (ecdsa_c[i][0] == 0) {
                 ecdsa_c[i][0] = 1;
                 ecdsa_c[i][1] = 1;
             }
@@ -1842,10 +2050,10 @@ int speed_main(int argc, char **argv)
     for (i = R_EC_B233; i <= R_EC_B571; i++) {
         ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
         ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
-        if ((ecdsa_doit[i] <= 1) && (ecdsa_c[i][0] == 0))
+        if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
             ecdsa_doit[i] = 0;
         else {
-            if (ecdsa_c[i] == 0) {
+            if (ecdsa_c[i][0] == 0) {
                 ecdsa_c[i][0] = 1;
                 ecdsa_c[i][1] = 1;
             }
@@ -1853,63 +2061,82 @@ int speed_main(int argc, char **argv)
     }
 
     ecdh_c[R_EC_P160][0] = count / 1000;
-    ecdh_c[R_EC_P160][1] = count / 1000;
     for (i = R_EC_P192; i <= R_EC_P521; i++) {
         ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
-        ecdh_c[i][1] = ecdh_c[i - 1][1] / 2;
-        if ((ecdh_doit[i] <= 1) && (ecdh_c[i][0] == 0))
+        if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
             ecdh_doit[i] = 0;
         else {
-            if (ecdh_c[i] == 0) {
+            if (ecdh_c[i][0] == 0) {
                 ecdh_c[i][0] = 1;
-                ecdh_c[i][1] = 1;
             }
         }
     }
     ecdh_c[R_EC_K163][0] = count / 1000;
-    ecdh_c[R_EC_K163][1] = count / 1000;
     for (i = R_EC_K233; i <= R_EC_K571; i++) {
         ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
-        ecdh_c[i][1] = ecdh_c[i - 1][1] / 2;
-        if ((ecdh_doit[i] <= 1) && (ecdh_c[i][0] == 0))
+        if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
             ecdh_doit[i] = 0;
         else {
-            if (ecdh_c[i] == 0) {
+            if (ecdh_c[i][0] == 0) {
                 ecdh_c[i][0] = 1;
-                ecdh_c[i][1] = 1;
             }
         }
     }
     ecdh_c[R_EC_B163][0] = count / 1000;
-    ecdh_c[R_EC_B163][1] = count / 1000;
     for (i = R_EC_B233; i <= R_EC_B571; i++) {
         ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
-        ecdh_c[i][1] = ecdh_c[i - 1][1] / 2;
-        if ((ecdh_doit[i] <= 1) && (ecdh_c[i][0] == 0))
+        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;
+            }
+        }
+    }
+    /* 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) {
+            if (ecdh_c[i][0] == 0) {
                 ecdh_c[i][0] = 1;
-                ecdh_c[i][1] = 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
-#endif                         /* SIGALRM */
+# endif                         /* OPENSSL_NO_DES */
+#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);
@@ -1919,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);
@@ -1931,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);
@@ -1943,18 +2172,20 @@ 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);
             print_result(D_MD5, testnum, count, d);
         }
     }
-#endif
 
-#ifndef OPENSSL_NO_MD5
     if (doit[D_HMAC]) {
+        static const char hmac_key[] = "This is a key...";
+        int len = strlen(hmac_key);
+
         for (i = 0; i < loopargs_len; i++) {
             loopargs[i].hctx = HMAC_CTX_new();
             if (loopargs[i].hctx == NULL) {
@@ -1962,11 +2193,11 @@ int speed_main(int argc, char **argv)
                 exit(1);
             }
 
-            HMAC_Init_ex(loopargs[i].hctx, (unsigned char *)"This is a key...",
-                    16, EVP_md5(), NULL);
+            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);
@@ -1978,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);
@@ -1987,8 +2219,9 @@ int speed_main(int argc, char **argv)
         }
     }
     if (doit[D_SHA256]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_SHA256], c[D_SHA256][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_SHA256], c[D_SHA256][testnum],
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, SHA256_loop, loopargs);
             d = Time_F(STOP);
@@ -1996,19 +2229,20 @@ int speed_main(int argc, char **argv)
         }
     }
     if (doit[D_SHA512]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_SHA512], c[D_SHA512][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_SHA512], c[D_SHA512][testnum],
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, SHA512_loop, loopargs);
             d = Time_F(STOP);
             print_result(D_SHA512, testnum, count, d);
         }
     }
-
 #ifndef OPENSSL_NO_WHIRLPOOL
     if (doit[D_WHIRLPOOL]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum],
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs);
             d = Time_F(STOP);
@@ -2019,8 +2253,9 @@ int speed_main(int argc, char **argv)
 
 #ifndef OPENSSL_NO_RMD160
     if (doit[D_RMD160]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_RMD160], c[D_RMD160][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_RMD160], c[D_RMD160][testnum],
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs);
             d = Time_F(STOP);
@@ -2030,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);
@@ -2041,8 +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++) {
-            print_message(names[D_CBC_DES], c[D_CBC_DES][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_CBC_DES], c[D_CBC_DES][testnum],
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, DES_ncbc_encrypt_loop, loopargs);
             d = Time_F(STOP);
@@ -2051,10 +2288,12 @@ int speed_main(int argc, char **argv)
     }
 
     if (doit[D_EDE3_DES]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum],
+                          lengths[testnum], seconds.sym);
             Time_F(START);
-            count = run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs);
+            count =
+                run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs);
             d = Time_F(STOP);
             print_result(D_EDE3_DES, testnum, count, d);
         }
@@ -2062,74 +2301,83 @@ 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);
+            count =
+                run_benchmark(async_jobs, AES_cbc_128_encrypt_loop, loopargs);
             d = Time_F(STOP);
             print_result(D_CBC_128_AES, testnum, count, d);
         }
     }
     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);
+            count =
+                run_benchmark(async_jobs, AES_cbc_192_encrypt_loop, loopargs);
             d = Time_F(STOP);
             print_result(D_CBC_192_AES, testnum, count, d);
         }
     }
     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);
+            count =
+                run_benchmark(async_jobs, AES_cbc_256_encrypt_loop, loopargs);
             d = Time_F(STOP);
             print_result(D_CBC_256_AES, testnum, count, d);
         }
     }
 
     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);
+            count =
+                run_benchmark(async_jobs, AES_ige_128_encrypt_loop, loopargs);
             d = Time_F(STOP);
             print_result(D_IGE_128_AES, testnum, count, d);
         }
     }
     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);
+            count =
+                run_benchmark(async_jobs, AES_ige_192_encrypt_loop, loopargs);
             d = Time_F(STOP);
             print_result(D_IGE_192_AES, testnum, count, d);
         }
     }
     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);
+            count =
+                run_benchmark(async_jobs, AES_ige_256_encrypt_loop, loopargs);
             d = Time_F(STOP);
             print_result(D_IGE_256_AES, testnum, count, d);
         }
     }
     if (doit[D_GHASH]) {
         for (i = 0; i < loopargs_len; i++) {
-            loopargs[i].gcm_ctx = CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt);
-            CRYPTO_gcm128_setiv(loopargs[i].gcm_ctx, (unsigned char *)"0123456789ab", 12);
+            loopargs[i].gcm_ctx =
+                CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt);
+            CRYPTO_gcm128_setiv(loopargs[i].gcm_ctx,
+                                (unsigned char *)"0123456789ab", 12);
         }
 
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_GHASH], c[D_GHASH][testnum], lengths[testnum]);
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_GHASH], c[D_GHASH][testnum],
+                          lengths[testnum], seconds.sym);
             Time_F(START);
             count = run_benchmark(async_jobs, CRYPTO_gcm128_aad_loop, loopargs);
             d = Time_F(STOP);
@@ -2138,29 +2386,34 @@ int speed_main(int argc, char **argv)
         for (i = 0; i < loopargs_len; i++)
             CRYPTO_gcm128_release(loopargs[i].gcm_ctx);
     }
-
 #ifndef OPENSSL_NO_CAMELLIA
     if (doit[D_CBC_128_CML]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with %s\n",
+                       names[D_CBC_128_CML]);
+            doit[D_CBC_128_CML] = 0;
+        }
+        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]);
-            if (async_jobs > 0) {
-                BIO_printf(bio_err, "Async mode is not supported, exiting...");
-                exit(1);
-            }
+                          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,
-                                     (unsigned long)lengths[testnum], &camellia_ks1,
+                                     (size_t)lengths[testnum], &camellia_ks1,
                                      iv, CAMELLIA_ENCRYPT);
             d = Time_F(STOP);
             print_result(D_CBC_128_CML, testnum, count, d);
         }
     }
     if (doit[D_CBC_192_CML]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with %s\n",
+                       names[D_CBC_192_CML]);
+            doit[D_CBC_192_CML] = 0;
+        }
+        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);
@@ -2168,24 +2421,25 @@ int speed_main(int argc, char **argv)
             Time_F(START);
             for (count = 0, run = 1; COND(c[D_CBC_192_CML][testnum]); count++)
                 Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
-                                     (unsigned long)lengths[testnum], &camellia_ks2,
+                                     (size_t)lengths[testnum], &camellia_ks2,
                                      iv, CAMELLIA_ENCRYPT);
             d = Time_F(STOP);
             print_result(D_CBC_192_CML, testnum, count, d);
         }
     }
     if (doit[D_CBC_256_CML]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
+        if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with %s\n",
+                       names[D_CBC_256_CML]);
+            doit[D_CBC_256_CML] = 0;
+        }
+        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]);
-            if (async_jobs > 0) {
-                BIO_printf(bio_err, "Async mode is not supported, exiting...");
-                exit(1);
-            }
+                          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,
-                                     (unsigned long)lengths[testnum], &camellia_ks3,
+                                     (size_t)lengths[testnum], &camellia_ks3,
                                      iv, CAMELLIA_ENCRYPT);
             d = Time_F(STOP);
             print_result(D_CBC_256_CML, testnum, count, d);
@@ -2194,16 +2448,18 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_IDEA
     if (doit[D_CBC_IDEA]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][testnum], lengths[testnum]);
-            if (async_jobs > 0) {
-                BIO_printf(bio_err, "Async mode is not supported, exiting...");
-                exit(1);
-            }
+        if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with %s\n",
+                       names[D_CBC_IDEA]);
+            doit[D_CBC_IDEA] = 0;
+        }
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+            print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][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,
-                                 (unsigned long)lengths[testnum], &idea_ks,
+                                 (size_t)lengths[testnum], &idea_ks,
                                  iv, IDEA_ENCRYPT);
             d = Time_F(STOP);
             print_result(D_CBC_IDEA, testnum, count, d);
@@ -2212,16 +2468,18 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_SEED
     if (doit[D_CBC_SEED]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_CBC_SEED], c[D_CBC_SEED][testnum], lengths[testnum]);
-            if (async_jobs > 0) {
-                BIO_printf(bio_err, "Async mode is not supported, exiting...");
-                exit(1);
-            }
+        if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with %s\n",
+                       names[D_CBC_SEED]);
+            doit[D_CBC_SEED] = 0;
+        }
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+            print_message(names[D_CBC_SEED], c[D_CBC_SEED][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,
-                                 (unsigned long)lengths[testnum], &seed_ks, iv, 1);
+                                 (size_t)lengths[testnum], &seed_ks, iv, 1);
             d = Time_F(STOP);
             print_result(D_CBC_SEED, testnum, count, d);
         }
@@ -2229,8 +2487,14 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_RC2
     if (doit[D_CBC_RC2]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_CBC_RC2], c[D_CBC_RC2][testnum], lengths[testnum]);
+        if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with %s\n",
+                       names[D_CBC_RC2]);
+            doit[D_CBC_RC2] = 0;
+        }
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+            print_message(names[D_CBC_RC2], c[D_CBC_RC2][testnum],
+                          lengths[testnum], seconds.sym);
             if (async_jobs > 0) {
                 BIO_printf(bio_err, "Async mode is not supported, exiting...");
                 exit(1);
@@ -2238,7 +2502,7 @@ int speed_main(int argc, char **argv)
             Time_F(START);
             for (count = 0, run = 1; COND(c[D_CBC_RC2][testnum]); count++)
                 RC2_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
-                                (unsigned long)lengths[testnum], &rc2_ks,
+                                (size_t)lengths[testnum], &rc2_ks,
                                 iv, RC2_ENCRYPT);
             d = Time_F(STOP);
             print_result(D_CBC_RC2, testnum, count, d);
@@ -2247,8 +2511,14 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_RC5
     if (doit[D_CBC_RC5]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_CBC_RC5], c[D_CBC_RC5][testnum], lengths[testnum]);
+        if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with %s\n",
+                       names[D_CBC_RC5]);
+            doit[D_CBC_RC5] = 0;
+        }
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+            print_message(names[D_CBC_RC5], c[D_CBC_RC5][testnum],
+                          lengths[testnum], seconds.sym);
             if (async_jobs > 0) {
                 BIO_printf(bio_err, "Async mode is not supported, exiting...");
                 exit(1);
@@ -2256,7 +2526,7 @@ int speed_main(int argc, char **argv)
             Time_F(START);
             for (count = 0, run = 1; COND(c[D_CBC_RC5][testnum]); count++)
                 RC5_32_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
-                                   (unsigned long)lengths[testnum], &rc5_ks,
+                                   (size_t)lengths[testnum], &rc5_ks,
                                    iv, RC5_ENCRYPT);
             d = Time_F(STOP);
             print_result(D_CBC_RC5, testnum, count, d);
@@ -2265,16 +2535,18 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_BF
     if (doit[D_CBC_BF]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_CBC_BF], c[D_CBC_BF][testnum], lengths[testnum]);
-            if (async_jobs > 0) {
-                BIO_printf(bio_err, "Async mode is not supported, exiting...");
-                exit(1);
-            }
+        if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with %s\n",
+                       names[D_CBC_BF]);
+            doit[D_CBC_BF] = 0;
+        }
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+            print_message(names[D_CBC_BF], c[D_CBC_BF][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,
-                               (unsigned long)lengths[testnum], &bf_ks,
+                               (size_t)lengths[testnum], &bf_ks,
                                iv, BF_ENCRYPT);
             d = Time_F(STOP);
             print_result(D_CBC_BF, testnum, count, d);
@@ -2283,81 +2555,103 @@ int speed_main(int argc, char **argv)
 #endif
 #ifndef OPENSSL_NO_CAST
     if (doit[D_CBC_CAST]) {
-        for (testnum = 0; testnum < SIZE_NUM; testnum++) {
-            print_message(names[D_CBC_CAST], c[D_CBC_CAST][testnum], lengths[testnum]);
-            if (async_jobs > 0) {
-                BIO_printf(bio_err, "Async mode is not supported, exiting...");
-                exit(1);
-            }
+        if (async_jobs > 0) {
+            BIO_printf(bio_err, "Async mode is not supported with %s\n",
+                       names[D_CBC_CAST]);
+            doit[D_CBC_CAST] = 0;
+        }
+        for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
+            print_message(names[D_CBC_CAST], c[D_CBC_CAST][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,
-                                 (unsigned long)lengths[testnum], &cast_ks,
+                                 (size_t)lengths[testnum], &cast_ks,
                                  iv, CAST_ENCRYPT);
             d = Time_F(STOP);
             print_result(D_CBC_CAST, testnum, count, d);
         }
     }
 #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]) {
-#ifdef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
-        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;
-        }
-#endif
-        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++) {
@@ -2365,8 +2659,36 @@ 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]);
+                          &loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
             if (st == 0)
                 break;
         }
@@ -2377,22 +2699,23 @@ int speed_main(int argc, char **argv)
             rsa_count = 1;
         } else {
             pkey_print_message("private", "rsa",
-                               rsa_c[testnum][0], rsa_bits[testnum], RSA_SECONDS);
+                               rsa_c[testnum][0], rsa_bits[testnum],
+                               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] = d / (double)count;
+            rsa_results[testnum][0] = (double)count / d;
             rsa_count = count;
         }
 
         for (i = 0; i < loopargs_len; i++) {
             st = RSA_verify(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2,
-                            *(loopargs[i].siglen), loopargs[i].rsa_key[testnum]);
+                            loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
             if (st <= 0)
                 break;
         }
@@ -2403,15 +2726,16 @@ int speed_main(int argc, char **argv)
             rsa_doit[testnum] = 0;
         } else {
             pkey_print_message("public", "rsa",
-                               rsa_c[testnum][1], rsa_bits[testnum], RSA_SECONDS);
+                               rsa_c[testnum][1], rsa_bits[testnum],
+                               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] = d / (double)count;
+            rsa_results[testnum][1] = (double)count / d;
         }
 
         if (rsa_count <= 1) {
@@ -2420,15 +2744,13 @@ int speed_main(int argc, char **argv)
                 rsa_doit[testnum] = 0;
         }
     }
-#endif
+#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])
@@ -2438,7 +2760,7 @@ int speed_main(int argc, char **argv)
         /* DSA_sign_setup(dsa_key[testnum],NULL); */
         for (i = 0; i < loopargs_len; i++) {
             st = DSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2,
-                          loopargs[i].siglen, loopargs[i].dsa_key[testnum]);
+                          &loopargs[i].siglen, loopargs[i].dsa_key[testnum]);
             if (st == 0)
                 break;
         }
@@ -2449,21 +2771,22 @@ int speed_main(int argc, char **argv)
             rsa_count = 1;
         } else {
             pkey_print_message("sign", "dsa",
-                               dsa_c[testnum][0], dsa_bits[testnum], DSA_SECONDS);
+                               dsa_c[testnum][0], dsa_bits[testnum],
+                               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] = d / (double)count;
+            dsa_results[testnum][0] = (double)count / d;
             rsa_count = count;
         }
 
         for (i = 0; i < loopargs_len; i++) {
             st = DSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2,
-                            *(loopargs[i].siglen), loopargs[i].dsa_key[testnum]);
+                            loopargs[i].siglen, loopargs[i].dsa_key[testnum]);
             if (st <= 0)
                 break;
         }
@@ -2474,15 +2797,16 @@ int speed_main(int argc, char **argv)
             dsa_doit[testnum] = 0;
         } else {
             pkey_print_message("verify", "dsa",
-                               dsa_c[testnum][1], dsa_bits[testnum], DSA_SECONDS);
+                               dsa_c[testnum][1], dsa_bits[testnum],
+                               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] = d / (double)count;
+            dsa_results[testnum][1] = (double)count / d;
         }
 
         if (rsa_count <= 1) {
@@ -2491,19 +2815,17 @@ int speed_main(int argc, char **argv)
                 dsa_doit[testnum] = 0;
         }
     }
-#endif
+#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]);
+            loopargs[i].ecdsa[testnum] =
+                EC_KEY_new_by_curve_name(test_curves[testnum].nid);
             if (loopargs[i].ecdsa[testnum] == NULL) {
                 st = 0;
                 break;
@@ -2519,7 +2841,8 @@ int speed_main(int argc, char **argv)
                 /* Perform ECDSA signature test */
                 EC_KEY_generate_key(loopargs[i].ecdsa[testnum]);
                 st = ECDSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2,
-                                loopargs[i].siglen, loopargs[i].ecdsa[testnum]);
+                                &loopargs[i].siglen,
+                                loopargs[i].ecdsa[testnum]);
                 if (st == 0)
                     break;
             }
@@ -2531,23 +2854,24 @@ 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);
-                ecdsa_results[testnum][0] = d / (double)count;
+                           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;
             }
 
             /* Perform ECDSA verification test */
             for (i = 0; i < loopargs_len; i++) {
                 st = ECDSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2,
-                                  *(loopargs[i].siglen), loopargs[i].ecdsa[testnum]);
+                                  loopargs[i].siglen,
+                                  loopargs[i].ecdsa[testnum]);
                 if (st != 1)
                     break;
             }
@@ -2559,121 +2883,291 @@ 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);
-                ecdsa_results[testnum][1] = d / (double)count;
+                           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;
             }
         }
     }
-#endif
 
-#ifndef OPENSSL_NO_EC
-    if (RAND_status() != 1) {
-        RAND_seed(rnd_seed, sizeof rnd_seed);
-    }
     for (testnum = 0; testnum < EC_NUM; testnum++) {
+        int ecdh_checks = 1;
+
         if (!ecdh_doit[testnum])
             continue;
+
         for (i = 0; i < loopargs_len; i++) {
-            loopargs[i].ecdh_a[testnum] = EC_KEY_new_by_curve_name(test_curves[testnum]);
-            loopargs[i].ecdh_b[testnum] = EC_KEY_new_by_curve_name(test_curves[testnum]);
-            if (loopargs[i].ecdh_a[testnum] == NULL ||
-                loopargs[i].ecdh_b[testnum] == NULL) {
-                ecdh_checks = 0;
-                break;
+            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;
+
+            /* 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);
             }
-        }
-        if (ecdh_checks == 0) {
-            BIO_printf(bio_err, "ECDH failure.\n");
-            ERR_print_errors(bio_err);
-            rsa_count = 1;
-        } else {
-            for (i = 0; i < loopargs_len; i++) {
-                /* generate two ECDH key pairs */
-                if (!EC_KEY_generate_key(loopargs[i].ecdh_a[testnum]) ||
-                        !EC_KEY_generate_key(loopargs[i].ecdh_b[testnum])) {
-                    BIO_printf(bio_err, "ECDH key generation failure.\n");
+
+            /* 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].nid, 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);
-                    ecdh_checks = 0;
                     rsa_count = 1;
-                } else {
-                    /*
-                     * If field size is not more than 24 octets, then use SHA-1
-                     * hash of result; otherwise, use result (see section 4.8 of
-                     * draft-ietf-tls-ecc-03.txt).
-                     */
-                    int field_size;
-                    field_size =
-                        EC_GROUP_get_degree(EC_KEY_get0_group(loopargs[i].ecdh_a[testnum]));
-                    if (field_size <= 24 * 8) {
-                        outlen = KDF1_SHA1_len;
-                        kdf = KDF1_SHA1;
-                    } else {
-                        outlen = (field_size + 7) / 8;
-                        kdf = NULL;
-                    }
-                    secret_size_a =
-                        ECDH_compute_key(loopargs[i].secret_a, outlen,
-                                EC_KEY_get0_public_key(loopargs[i].ecdh_b[testnum]),
-                                loopargs[i].ecdh_a[testnum], kdf);
-                    secret_size_b =
-                        ECDH_compute_key(loopargs[i].secret_b, outlen,
-                                EC_KEY_get0_public_key(loopargs[i].ecdh_a[testnum]),
-                                loopargs[i].ecdh_b[testnum], kdf);
-                    if (secret_size_a != secret_size_b)
-                        ecdh_checks = 0;
-                    else
-                        ecdh_checks = 1;
-
-                    for (secret_idx = 0; (secret_idx < secret_size_a)
-                            && (ecdh_checks == 1); secret_idx++) {
-                        if (loopargs[i].secret_a[secret_idx] != loopargs[i].secret_b[secret_idx])
-                            ecdh_checks = 0;
-                    }
-
-                    if (ecdh_checks == 0) {
-                        BIO_printf(bio_err, "ECDH computations don't match.\n");
-                        ERR_print_errors(bio_err);
-                        rsa_count = 1;
-                        break;
-                    }
+                    break;
                 }
-                if (ecdh_checks != 0) {
-                    pkey_print_message("", "ecdh",
-                            ecdh_c[testnum][0],
-                            test_curves_bits[testnum], ECDH_SECONDS);
-                    Time_F(START);
-                    count = run_benchmark(async_jobs, ECDH_compute_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;
-                    rsa_count = count;
+
+                if (            /* Create the context for parameter generation */
+                       !(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) ||
+                       /* Initialise the parameter generation */
+                       !EVP_PKEY_paramgen_init(pctx) ||
+                       /* Set the curve by NID */
+                       !EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
+                                                               test_curves
+                                                               [testnum].nid) ||
+                       /* Create the parameter object params */
+                       !EVP_PKEY_paramgen(pctx, &params)) {
+                    ecdh_checks = 0;
+                    BIO_printf(bio_err, "ECDH EC params init failure.\n");
+                    ERR_print_errors(bio_err);
+                    rsa_count = 1;
+                    break;
                 }
+                /* Create the context for the key generation */
+                kctx = EVP_PKEY_CTX_new(params, NULL);
+
+                EVP_PKEY_free(params);
+                params = NULL;
+                EVP_PKEY_CTX_free(pctx);
+                pctx = 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");
+                ERR_print_errors(bio_err);
+                rsa_count = 1;
+                break;
+            }
+
+            if (!EVP_PKEY_keygen(kctx, &key_A) || /* generate secret key A */
+                !EVP_PKEY_keygen(kctx, &key_B) || /* generate secret key B */
+                !(ctx = EVP_PKEY_CTX_new(key_A, NULL)) || /* derivation ctx from skeyA */
+                !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");
+                ERR_print_errors(bio_err);
+                rsa_count = 1;
+                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_free(key_A);
+            EVP_PKEY_free(key_B);
+            EVP_PKEY_CTX_free(kctx);
+            kctx = NULL;
+            EVP_PKEY_CTX_free(test_ctx);
+            test_ctx = NULL;
+        }
+        if (ecdh_checks != 0) {
+            pkey_print_message("", "ecdh",
+                               ecdh_c[testnum][0],
+                               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 %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;
         }
     }
-#endif
+
+    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:
 #endif
@@ -2709,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");
     }
@@ -2718,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
@@ -2743,8 +3237,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
@@ -2761,13 +3255,13 @@ 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
     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) {
@@ -2777,18 +3271,15 @@ 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],
-                   ecdsa_results[k][0], ecdsa_results[k][1],
-                   1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1]);
+            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]);
     }
-#endif
 
-#ifndef OPENSSL_NO_EC
     testnum = 1;
     for (k = 0; k < EC_NUM; k++) {
         if (!ecdh_doit[k])
@@ -2799,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
 
@@ -2817,50 +3327,48 @@ int speed_main(int argc, char **argv)
     for (i = 0; i < loopargs_len; i++) {
         OPENSSL_free(loopargs[i].buf_malloc);
         OPENSSL_free(loopargs[i].buf2_malloc);
-        OPENSSL_free(loopargs[i].siglen);
-    }
+
 #ifndef OPENSSL_NO_RSA
-    for (i = 0; i < loopargs_len; i++) {
         for (k = 0; k < RSA_NUM; k++)
             RSA_free(loopargs[i].rsa_key[k]);
-    }
 #endif
 #ifndef OPENSSL_NO_DSA
-    for (i = 0; i < loopargs_len; i++) {
         for (k = 0; k < DSA_NUM; k++)
             DSA_free(loopargs[i].dsa_key[k]);
-    }
 #endif
-
 #ifndef OPENSSL_NO_EC
-    for (i = 0; i < loopargs_len; i++) {
-        for (k = 0; k < EC_NUM; k++) {
+        for (k = 0; k < ECDSA_NUM; k++)
             EC_KEY_free(loopargs[i].ecdsa[k]);
-            EC_KEY_free(loopargs[i].ecdh_a[k]);
-            EC_KEY_free(loopargs[i].ecdh_b[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
+    }
+
     if (async_jobs > 0) {
         for (i = 0; i < loopargs_len; i++)
             ASYNC_WAIT_CTX_free(loopargs[i].wait_ctx);
+    }
 
+    if (async_init) {
         ASYNC_cleanup_thread();
     }
     OPENSSL_free(loopargs);
-    return (ret);
+    release_engine(e);
+    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"
@@ -2870,24 +3378,28 @@ 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
 }
 
 static void print_result(int alg, int run_no, int count, double time_used)
 {
+    if (count == -1) {
+        BIO_puts(bio_err, "EVP error!\n");
+        exit(1);
+    }
     BIO_printf(bio_err,
                mr ? "+R:%d:%s:%f\n"
                : "%d %s's in %.2fs\n", count, names[alg], time_used);
@@ -2903,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) {
@@ -2923,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");
@@ -2964,13 +3476,14 @@ 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';
             if (buf[0] != '+') {
-                BIO_printf(bio_err, "Don't understand line '%s' from child %d\n",
-                        buf, n);
+                BIO_printf(bio_err,
+                           "Don't understand line '%s' from child %d\n", buf,
+                           n);
                 continue;
             }
             printf("Got: %s from %d\n", buf, n);
@@ -2981,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;
@@ -2992,16 +3505,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) {
@@ -3013,16 +3520,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
@@ -3035,23 +3536,21 @@ 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;
-            }
-# endif
+                ecdsa_results[k][1] += d;
+            } else if (strncmp(buf, "+F5:", 4) == 0) {
+                int k;
+                double d;
 
-# ifndef OPENSSL_NO_EC
-            else if (strncmp(buf, "+F5:", 4) == 0) {
+                p = buf + 4;
+                k = atoi(sstrsep(&p, sep));
+                sstrsep(&p, sep);
+
+                d = atof(sstrsep(&p, sep));
+                ecdh_results[k][0] += d;
+            } else if (strncmp(buf, "+F6:", 4) == 0) {
                 int k;
                 double d;
 
@@ -3060,18 +3559,18 @@ 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;
+                eddsa_results[k][0] += d;
 
+                d = atof(sstrsep(&p, sep));
+                eddsa_results[k][1] += d;
             }
 # endif
 
             else if (strncmp(buf, "+H:", 3) == 0) {
                 ;
             } else
-                BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf, n);
+                BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf,
+                           n);
         }
 
         fclose(f);
@@ -3081,26 +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_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key),
-                        no_key);
+    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];
@@ -3133,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);