Add loaded dynamic ENGINEs to list.
[openssl.git] / apps / speed.c
index 9e20b7217c2b57ae23c929d8c353e58453747125..92324186f42916121dc1e49aa1cbadf45e00462c 100644 (file)
@@ -1,4 +1,4 @@
-/* apps/speed.c */
+/* apps/speed.c -*- mode:C; c-file-style: "eay" -*- */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * 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.
+ *
+ */
 
 /* most of this code has been pilfered from my libdes speed.c program */
 
+#ifndef OPENSSL_NO_SPEED
+
 #undef SECONDS
 #define SECONDS                3       
 #define RSA_SECONDS    10
 #define DSA_SECONDS    10
+#define ECDSA_SECONDS   10
+#define ECDH_SECONDS    10
 
 /* 11-Sep-92 Andrew Daviel   Support for Silicon Graphics IRIX added */
 /* 06-Apr-92 Luke Brennan    Support for VMS and add extra signal calls */
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <signal.h>
+
 #include <string.h>
 #include <math.h>
 #include "apps.h"
-#ifdef NO_STDIO
+#ifdef OPENSSL_NO_STDIO
 #define APPS_WIN16
 #endif
-#include "crypto.h"
-#include "rand.h"
-#include "err.h"
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#if !defined(OPENSSL_SYS_MSDOS)
+#include OPENSSL_UNISTD
+#endif
 
-#ifndef MSDOS
-#define TIMES
+#ifndef OPENSSL_SYS_NETWARE
+#include <signal.h>
 #endif
 
-#ifndef VMS
-#ifndef _IRIX
-#include <time.h>
+#if defined(_WIN32) || defined(__CYGWIN__)
+#include <windows.h>
+# if defined(__CYGWIN__) && !defined(_WIN32)
+  /* <windows.h> should define _WIN32, which normally is mutually
+   * exclusive with __CYGWIN__, but if it didn't... */
+#  define _WIN32
+  /* this is done because Cygwin alarm() fails sometimes. */
+# endif
 #endif
-#ifdef TIMES
-#include <sys/types.h>
-#include <sys/times.h>
+
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_DES
+#include <openssl/des.h>
 #endif
-#else /* VMS */
-#include <types.h>
-struct tms {
-       time_t tms_utime;
-       time_t tms_stime;
-       time_t tms_uchild;      /* I dunno...  */
-       time_t tms_uchildsys;   /* so these names are a guess :-) */
-       }
+#ifndef OPENSSL_NO_AES
+#include <openssl/aes.h>
 #endif
-#ifndef TIMES
-#include <sys/timeb.h>
+#ifndef OPENSSL_NO_CAMELLIA
+#include <openssl/camellia.h>
 #endif
-
-#if defined(sun) || defined(__ultrix)
-#define _POSIX_SOURCE
-#include <limits.h>
-#include <sys/param.h>
+#ifndef OPENSSL_NO_MD2
+#include <openssl/md2.h>
 #endif
-
-#ifndef NO_DES
-#include "des.h"
+#ifndef OPENSSL_NO_MDC2
+#include <openssl/mdc2.h>
 #endif
-#ifndef NO_MD2
-#include "md2.h"
+#ifndef OPENSSL_NO_MD4
+#include <openssl/md4.h>
 #endif
-#ifndef NO_MDC2
-#include "mdc2.h"
+#ifndef OPENSSL_NO_MD5
+#include <openssl/md5.h>
 #endif
-#ifndef NO_MD5
-#include "md5.h"
-#include "hmac.h"
-#include "evp.h"
+#ifndef OPENSSL_NO_HMAC
+#include <openssl/hmac.h>
 #endif
-#ifndef NO_SHA1
-#include "sha.h"
+#include <openssl/evp.h>
+#ifndef OPENSSL_NO_SHA
+#include <openssl/sha.h>
 #endif
-#ifndef NO_RMD160
-#include "ripemd.h"
+#ifndef OPENSSL_NO_RIPEMD
+#include <openssl/ripemd.h>
 #endif
-#ifndef NO_RC4
-#include "rc4.h"
+#ifndef OPENSSL_NO_WHIRLPOOL
+#include <openssl/whrlpool.h>
 #endif
-#ifndef NO_RC5
-#include "rc5.h"
+#ifndef OPENSSL_NO_RC4
+#include <openssl/rc4.h>
 #endif
-#ifndef NO_RC2
-#include "rc2.h"
+#ifndef OPENSSL_NO_RC5
+#include <openssl/rc5.h>
 #endif
-#ifndef NO_IDEA
-#include "idea.h"
+#ifndef OPENSSL_NO_RC2
+#include <openssl/rc2.h>
 #endif
-#ifndef NO_BLOWFISH
-#include "blowfish.h"
+#ifndef OPENSSL_NO_IDEA
+#include <openssl/idea.h>
 #endif
-#ifndef NO_CAST
-#include "cast.h"
+#ifndef OPENSSL_NO_SEED
+#include <openssl/seed.h>
 #endif
-#ifndef NO_RSA
-#include "rsa.h"
+#ifndef OPENSSL_NO_BF
+#include <openssl/blowfish.h>
 #endif
-#include "x509.h"
+#ifndef OPENSSL_NO_CAST
+#include <openssl/cast.h>
+#endif
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
 #include "./testrsa.h"
-#ifndef NO_DSA
+#endif
+#include <openssl/x509.h>
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
 #include "./testdsa.h"
 #endif
+#ifndef OPENSSL_NO_ECDSA
+#include <openssl/ecdsa.h>
+#endif
+#ifndef OPENSSL_NO_ECDH
+#include <openssl/ecdh.h>
+#endif
+#include <openssl/modes.h>
 
-/* The following if from times(3) man page.  It may need to be changed */
-#ifndef HZ
-# ifndef CLK_TCK
-#  ifndef _BSD_CLK_TCK_ /* FreeBSD hack */
-#   ifndef VMS
-#    define HZ 100.0
-#   else /* VMS */
-#    define HZ 100.0
-#   endif
-#  else /* _BSD_CLK_TCK_ */
-#   define HZ ((double)_BSD_CLK_TCK_)
-#  endif
-# else /* CLK_TCK */
-#  define HZ ((double)CLK_TCK)
+#ifndef HAVE_FORK
+# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_NETWARE)
+#  define HAVE_FORK 0
+# else
+#  define HAVE_FORK 1
 # endif
 #endif
 
+#if HAVE_FORK
+#undef NO_FORK
+#else
+#define NO_FORK
+#endif
+
 #undef BUFSIZE
 #define BUFSIZE        ((long)1024*8+1)
 int run=0;
 
-#ifndef NOPROTO
+static int mr=0;
+static int usertime=1;
+
 static double Time_F(int s);
-static void print_message(char *s,long num,int length);
-static void pkey_print_message(char *str,char *str2,long num,int bits,int sec);
-#else
-static double Time_F();
-static void print_message();
-static void pkey_print_message();
+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 sec);
+static void print_result(int alg,int run_no,int count,double time_used);
+#ifndef NO_FORK
+static int do_multi(int multi);
+#endif
+
+#define ALGOR_NUM      30
+#define SIZE_NUM       5
+#define RSA_NUM                4
+#define DSA_NUM                3
+
+#define EC_NUM       16
+#define MAX_ECDH_SIZE 256
+
+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]={16,64,256,1024,8*1024};
+#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_ECDSA
+static double ecdsa_results[EC_NUM][2];
+#endif
+#ifndef OPENSSL_NO_ECDH
+static double ecdh_results[EC_NUM][1];
+#endif
+
+#if defined(OPENSSL_NO_DSA) && !(defined(OPENSSL_NO_ECDSA) && defined(OPENSSL_NO_ECDH))
+static const char rnd_seed[] = "string to make the random number generator think it has entropy";
+static int rnd_fake = 0;
 #endif
 
 #ifdef SIGALRM
@@ -198,14 +264,8 @@ static void pkey_print_message();
 #define SIGRETTYPE int
 #endif 
 
-#ifndef NOPROTO
 static SIGRETTYPE sig_done(int sig);
-#else
-static SIGRETTYPE sig_done();
-#endif
-
-static SIGRETTYPE sig_done(sig)
-int sig;
+static SIGRETTYPE sig_done(int sig)
        {
        signal(SIGALRM,sig_done);
        run=0;
@@ -218,120 +278,220 @@ int sig;
 #define START  0
 #define STOP   1
 
-static double Time_F(s)
-int s;
+#if defined(_WIN32)
+
+#if !defined(SIGALRM)
+# define SIGALRM
+#endif
+static unsigned int lapse,schlock;
+static void alarm_win32(unsigned int secs) { lapse = secs*1000; }
+#define alarm alarm_win32
+
+static DWORD WINAPI sleepy(VOID *arg)
+       {
+       schlock = 1;
+       Sleep(lapse);
+       run = 0;
+       return 0;
+       }
+
+static double Time_F(int s)
        {
        double ret;
-#ifdef TIMES
-       static struct tms tstart,tend;
+       static HANDLE thr;
 
        if (s == START)
                {
-               times(&tstart);
-               return(0);
+               schlock = 0;
+               thr = CreateThread(NULL,4096,sleepy,NULL,0,NULL);
+               if (thr==NULL)
+                       {
+                       DWORD ret=GetLastError();
+                       BIO_printf(bio_err,"unable to CreateThread (%d)",ret);
+                       ExitProcess(ret);
+                       }
+               while (!schlock) Sleep(0);      /* scheduler spinlock   */
+               ret = app_tminterval(s,usertime);
                }
        else
                {
-               times(&tend);
-               ret=((double)(tend.tms_utime-tstart.tms_utime))/HZ;
-               return((ret < 1e-3)?1e-3:ret);
+               ret = app_tminterval(s,usertime);
+               if (run) TerminateThread(thr,0);
+               CloseHandle(thr);
                }
-#else /* !times() */
-       static struct timeb tstart,tend;
-       long i;
 
-       if (s == START)
-               {
-               ftime(&tstart);
-               return(0);
-               }
-       else
-               {
-               ftime(&tend);
-               i=(long)tend.millitm-(long)tstart.millitm;
-               ret=((double)(tend.time-tstart.time))+((double)i)/1000.0;
-               return((ret < 0.001)?0.001:ret);
-               }
+       return ret;
+       }
+#else
+
+static double Time_F(int s)
+       {
+       double ret = app_tminterval(s,usertime);
+       if (s == STOP) alarm(0);
+       return ret;
+       }
 #endif
+
+
+#ifndef OPENSSL_NO_ECDH
+static const int KDF1_SHA1_len = 20;
+static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
+       {
+#ifndef OPENSSL_NO_SHA
+       if (*outlen < SHA_DIGEST_LENGTH)
+               return NULL;
+       else
+               *outlen = SHA_DIGEST_LENGTH;
+       return SHA1(in, inlen, out);
+#else
+       return NULL;
+#endif /* OPENSSL_NO_SHA */
        }
+#endif /* OPENSSL_NO_ECDH */
+
 
-int MAIN(argc,argv)
-int argc;
-char **argv;
+int MAIN(int, char **);
+
+int MAIN(int argc, char **argv)
        {
        unsigned char *buf=NULL,*buf2=NULL;
-       int ret=1;
-#define ALGOR_NUM      14
-#define SIZE_NUM       5
-#define RSA_NUM                4
-#define DSA_NUM                3
-       long count,rsa_count;
-       int i,j,k,rsa_num,rsa_num2;
-#ifndef NO_MD2
+       int mret=1;
+       long count=0,save_count=0;
+       int i,j,k;
+#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA)
+       long rsa_count;
+#endif
+#ifndef OPENSSL_NO_RSA
+       unsigned rsa_num;
+#endif
+       unsigned char md[EVP_MAX_MD_SIZE];
+#ifndef OPENSSL_NO_MD2
        unsigned char md2[MD2_DIGEST_LENGTH];
 #endif
-#ifndef NO_MDC2
+#ifndef OPENSSL_NO_MDC2
        unsigned char mdc2[MDC2_DIGEST_LENGTH];
 #endif
-#ifndef NO_MD5
+#ifndef OPENSSL_NO_MD4
+       unsigned char md4[MD4_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_MD5
        unsigned char md5[MD5_DIGEST_LENGTH];
        unsigned char hmac[MD5_DIGEST_LENGTH];
 #endif
-#ifndef NO_SHA1
+#ifndef OPENSSL_NO_SHA
        unsigned char sha[SHA_DIGEST_LENGTH];
+#ifndef OPENSSL_NO_SHA256
+       unsigned char sha256[SHA256_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_SHA512
+       unsigned char sha512[SHA512_DIGEST_LENGTH];
+#endif
+#endif
+#ifndef OPENSSL_NO_WHIRLPOOL
+       unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH];
 #endif
-#ifndef NO_RMD160
+#ifndef OPENSSL_NO_RIPEMD
        unsigned char rmd160[RIPEMD160_DIGEST_LENGTH];
 #endif
-#ifndef NO_RC4
+#ifndef OPENSSL_NO_RC4
        RC4_KEY rc4_ks;
 #endif
-#ifndef NO_RC5
+#ifndef OPENSSL_NO_RC5
        RC5_32_KEY rc5_ks;
 #endif
-#ifndef NO_RC2
+#ifndef OPENSSL_NO_RC2
        RC2_KEY rc2_ks;
 #endif
-#ifndef NO_IDEA
+#ifndef OPENSSL_NO_IDEA
        IDEA_KEY_SCHEDULE idea_ks;
 #endif
-#ifndef NO_BLOWFISH
+#ifndef OPENSSL_NO_SEED
+       SEED_KEY_SCHEDULE seed_ks;
+#endif
+#ifndef OPENSSL_NO_BF
        BF_KEY bf_ks;
 #endif
-#ifndef NO_CAST
+#ifndef OPENSSL_NO_CAST
        CAST_KEY cast_ks;
 #endif
-       static unsigned char key16[16]=
+       static const unsigned char key16[16]=
                {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
                 0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12};
-       unsigned char iv[8];
-#ifndef NO_DES
-       static des_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0};
-       static des_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12};
-       static des_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
-       des_key_schedule sch,sch2,sch3;
+#ifndef OPENSSL_NO_AES
+       static const unsigned char key24[24]=
+               {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
+                0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,
+                0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
+       static const unsigned char key32[32]=
+               {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
+                0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,
+                0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,
+                0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,0x56};
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+       static const unsigned char ckey24[24]=
+               {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
+                0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,
+                0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
+       static const unsigned char ckey32[32]=
+               {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,
+                0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,
+                0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,
+                0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34,0x56};
+#endif
+#ifndef OPENSSL_NO_AES
+#define MAX_BLOCK_SIZE 128
+#else
+#define MAX_BLOCK_SIZE 64
+#endif
+       unsigned char DES_iv[8];
+       unsigned char iv[2*MAX_BLOCK_SIZE/8];
+#ifndef OPENSSL_NO_DES
+       static DES_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0};
+       static DES_cblock key2={0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12};
+       static DES_cblock key3={0x56,0x78,0x9a,0xbc,0xde,0xf0,0x12,0x34};
+       DES_key_schedule sch;
+       DES_key_schedule sch2;
+       DES_key_schedule sch3;
+#endif
+#ifndef OPENSSL_NO_AES
+       AES_KEY aes_ks1, aes_ks2, aes_ks3;
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+       CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3;
 #endif
 #define        D_MD2           0
 #define        D_MDC2          1
-#define        D_MD5           2
-#define        D_HMAC          3
-#define        D_SHA1          4
-#define D_RMD160       5
-#define        D_RC4           6
-#define        D_CBC_DES       7
-#define        D_EDE3_DES      8
-#define        D_CBC_IDEA      9
-#define        D_CBC_RC2       10
-#define        D_CBC_RC5       11
-#define        D_CBC_BF        12
-#define        D_CBC_CAST      13
-       double d,results[ALGOR_NUM][SIZE_NUM];
-       static int lengths[SIZE_NUM]={8,64,256,1024,8*1024};
+#define        D_MD4           2
+#define        D_MD5           3
+#define        D_HMAC          4
+#define        D_SHA1          5
+#define D_RMD160       6
+#define        D_RC4           7
+#define        D_CBC_DES       8
+#define        D_EDE3_DES      9
+#define        D_CBC_IDEA      10
+#define        D_CBC_SEED      11
+#define        D_CBC_RC2       12
+#define        D_CBC_RC5       13
+#define        D_CBC_BF        14
+#define        D_CBC_CAST      15
+#define D_CBC_128_AES  16
+#define D_CBC_192_AES  17
+#define D_CBC_256_AES  18
+#define D_CBC_128_CML   19 
+#define D_CBC_192_CML   20
+#define D_CBC_256_CML   21 
+#define D_EVP          22
+#define D_SHA256       23      
+#define D_SHA512       24
+#define D_WHIRLPOOL    25
+#define D_IGE_128_AES   26
+#define D_IGE_192_AES   27
+#define D_IGE_256_AES   28
+#define D_GHASH                29
+       double d=0.0;
        long c[ALGOR_NUM][SIZE_NUM];
-       static char *names[ALGOR_NUM]={
-               "md2","mdc2","md5","hmac(md5)","sha1","rmd160","rc4",
-               "des cbc","des ede3","idea cbc",
-               "rc2 cbc","rc5-32/12 cbc","blowfish cbc","cast cbc"};
 #define        R_DSA_512       0
 #define        R_DSA_1024      1
 #define        R_DSA_2048      2
@@ -339,10 +499,27 @@ char **argv;
 #define        R_RSA_1024      1
 #define        R_RSA_2048      2
 #define        R_RSA_4096      3
+
+#define R_EC_P160    0
+#define R_EC_P192    1 
+#define R_EC_P224    2
+#define R_EC_P256    3
+#define R_EC_P384    4
+#define R_EC_P521    5
+#define R_EC_K163    6
+#define R_EC_K233    7
+#define R_EC_K283    8
+#define R_EC_K409    9
+#define R_EC_K571    10
+#define R_EC_B163    11
+#define R_EC_B233    12
+#define R_EC_B283    13
+#define R_EC_B409    14
+#define R_EC_B571    15
+
+#ifndef OPENSSL_NO_RSA
        RSA *rsa_key[RSA_NUM];
        long rsa_c[RSA_NUM][2];
-#ifndef NO_RSA
-       double rsa_results[RSA_NUM][2];
        static unsigned int rsa_bits[RSA_NUM]={512,1024,2048,4096};
        static unsigned char *rsa_data[RSA_NUM]=
                {test512,test1024,test2048,test4096};
@@ -350,44 +527,148 @@ char **argv;
                sizeof(test512),sizeof(test1024),
                sizeof(test2048),sizeof(test4096)};
 #endif
-#ifndef NO_DSA
+#ifndef OPENSSL_NO_DSA
        DSA *dsa_key[DSA_NUM];
        long dsa_c[DSA_NUM][2];
-       double dsa_results[DSA_NUM][2];
        static unsigned int dsa_bits[DSA_NUM]={512,1024,2048};
 #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. 
+        */
+       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
+       }; 
+       static const char * test_curves_names[EC_NUM] = 
+       {
+       /* Prime Curves */
+       "secp160r1",
+       "nistp192",
+       "nistp224",
+       "nistp256",
+       "nistp384",
+       "nistp521",
+       /* Binary Curves */
+       "nistk163",
+       "nistk233",
+       "nistk283",
+       "nistk409",
+       "nistk571",
+       "nistb163",
+       "nistb233",
+       "nistb283",
+       "nistb409",
+       "nistb571"
+       };
+       static int test_curves_bits[EC_NUM] =
+        {
+        160, 192, 224, 256, 384, 521,
+        163, 233, 283, 409, 571,
+        163, 233, 283, 409, 571
+        };
+
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+       unsigned char ecdsasig[256];
+       unsigned int ecdsasiglen;
+       EC_KEY *ecdsa[EC_NUM];
+       long ecdsa_c[EC_NUM][2];
+#endif
+
+#ifndef OPENSSL_NO_ECDH
+       EC_KEY *ecdh_a[EC_NUM], *ecdh_b[EC_NUM];
+       unsigned char secret_a[MAX_ECDH_SIZE], secret_b[MAX_ECDH_SIZE];
+       int secret_size_a, secret_size_b;
+       int ecdh_checks = 0;
+       int secret_idx = 0;
+       long ecdh_c[EC_NUM][2];
+#endif
+
        int rsa_doit[RSA_NUM];
        int dsa_doit[DSA_NUM];
+#ifndef OPENSSL_NO_ECDSA
+       int ecdsa_doit[EC_NUM];
+#endif
+#ifndef OPENSSL_NO_ECDH
+        int ecdh_doit[EC_NUM];
+#endif
        int doit[ALGOR_NUM];
        int pr_header=0;
+       const EVP_CIPHER *evp_cipher=NULL;
+       const EVP_MD *evp_md=NULL;
+       int decrypt=0;
+#ifndef NO_FORK
+       int multi=0;
+#endif
+
+#ifndef TIMES
+       usertime=-1;
+#endif
 
        apps_startup();
-#ifdef NO_DSA
+       memset(results, 0, sizeof(results));
+#ifndef OPENSSL_NO_DSA
        memset(dsa_key,0,sizeof(dsa_key));
 #endif
+#ifndef OPENSSL_NO_ECDSA
+       for (i=0; i<EC_NUM; i++) ecdsa[i] = NULL;
+#endif
+#ifndef OPENSSL_NO_ECDH
+       for (i=0; i<EC_NUM; i++)
+               {
+               ecdh_a[i] = NULL;
+               ecdh_b[i] = NULL;
+               }
+#endif
+
 
        if (bio_err == NULL)
                if ((bio_err=BIO_new(BIO_s_file())) != NULL)
                        BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
 
-#ifndef NO_RSA
+       if (!load_config(bio_err, NULL))
+               goto end;
+
+#ifndef OPENSSL_NO_RSA
        memset(rsa_key,0,sizeof(rsa_key));
        for (i=0; i<RSA_NUM; i++)
                rsa_key[i]=NULL;
 #endif
 
-       if ((buf=(unsigned char *)Malloc((int)BUFSIZE)) == NULL)
+       if ((buf=(unsigned char *)OPENSSL_malloc((int)BUFSIZE)) == NULL)
                {
                BIO_printf(bio_err,"out of memory\n");
                goto end;
                }
-       if ((buf2=(unsigned char *)Malloc((int)BUFSIZE)) == NULL)
+       if ((buf2=(unsigned char *)OPENSSL_malloc((int)BUFSIZE)) == NULL)
                {
                BIO_printf(bio_err,"out of memory\n");
                goto end;
                }
 
        memset(c,0,sizeof(c));
+       memset(DES_iv,0,sizeof(DES_iv));
        memset(iv,0,sizeof(iv));
 
        for (i=0; i<ALGOR_NUM; i++)
@@ -396,35 +677,140 @@ char **argv;
                rsa_doit[i]=0;
        for (i=0; i<DSA_NUM; i++)
                dsa_doit[i]=0;
+#ifndef OPENSSL_NO_ECDSA
+       for (i=0; i<EC_NUM; i++)
+               ecdsa_doit[i]=0;
+#endif
+#ifndef OPENSSL_NO_ECDH
+       for (i=0; i<EC_NUM; i++)
+               ecdh_doit[i]=0;
+#endif
+
        
        j=0;
        argc--;
        argv++;
        while (argc)
                {
-#ifndef NO_MD2
+               if      ((argc > 0) && (strcmp(*argv,"-elapsed") == 0))
+                       {
+                       usertime = 0;
+                       j--;    /* Otherwise, -elapsed gets confused with
+                                  an algorithm. */
+                       }
+               else if ((argc > 0) && (strcmp(*argv,"-evp") == 0))
+                       {
+                       argc--;
+                       argv++;
+                       if(argc == 0)
+                               {
+                               BIO_printf(bio_err,"no EVP given\n");
+                               goto end;
+                               }
+                       evp_cipher=EVP_get_cipherbyname(*argv);
+                       if(!evp_cipher)
+                               {
+                               evp_md=EVP_get_digestbyname(*argv);
+                               }
+                       if(!evp_cipher && !evp_md)
+                               {
+                               BIO_printf(bio_err,"%s is an unknown cipher or digest\n",*argv);
+                               goto end;
+                               }
+                       doit[D_EVP]=1;
+                       }
+               else if (argc > 0 && !strcmp(*argv,"-decrypt"))
+                       {
+                       decrypt=1;
+                       j--;    /* Otherwise, -elapsed gets confused with
+                                  an algorithm. */
+                       }
+#ifndef OPENSSL_NO_ENGINE
+               else if ((argc > 0) && (strcmp(*argv,"-engine") == 0))
+                       {
+                       argc--;
+                       argv++;
+                       if(argc == 0)
+                               {
+                               BIO_printf(bio_err,"no engine given\n");
+                               goto end;
+                               }
+                        setup_engine(bio_err, *argv, 0);
+                       /* j will be increased again further down.  We just
+                          don't want speed to confuse an engine with an
+                          algorithm, especially when none is given (which
+                          means all of them should be run) */
+                       j--;
+                       }
+#endif
+#ifndef NO_FORK
+               else if ((argc > 0) && (strcmp(*argv,"-multi") == 0))
+                       {
+                       argc--;
+                       argv++;
+                       if(argc == 0)
+                               {
+                               BIO_printf(bio_err,"no multi count given\n");
+                               goto end;
+                               }
+                       multi=atoi(argv[0]);
+                       if(multi <= 0)
+                           {
+                               BIO_printf(bio_err,"bad multi count\n");
+                               goto end;
+                               }                               
+                       j--;    /* Otherwise, -mr gets confused with
+                                  an algorithm. */
+                       }
+#endif
+               else if (argc > 0 && !strcmp(*argv,"-mr"))
+                       {
+                       mr=1;
+                       j--;    /* Otherwise, -mr gets confused with
+                                  an algorithm. */
+                       }
+               else
+#ifndef OPENSSL_NO_MD2
                if      (strcmp(*argv,"md2") == 0) doit[D_MD2]=1;
                else
 #endif
-#ifndef NO_MDC2
+#ifndef OPENSSL_NO_MDC2
                        if (strcmp(*argv,"mdc2") == 0) doit[D_MDC2]=1;
                else
 #endif
-#ifndef NO_MD5
+#ifndef OPENSSL_NO_MD4
+                       if (strcmp(*argv,"md4") == 0) doit[D_MD4]=1;
+               else
+#endif
+#ifndef OPENSSL_NO_MD5
                        if (strcmp(*argv,"md5") == 0) doit[D_MD5]=1;
                else
 #endif
-#ifndef NO_MD5
+#ifndef OPENSSL_NO_MD5
                        if (strcmp(*argv,"hmac") == 0) doit[D_HMAC]=1;
                else
 #endif
-#ifndef NO_SHA1
+#ifndef OPENSSL_NO_SHA
                        if (strcmp(*argv,"sha1") == 0) doit[D_SHA1]=1;
                else
-                       if (strcmp(*argv,"sha") == 0) doit[D_SHA1]=1;
+                       if (strcmp(*argv,"sha") == 0)   doit[D_SHA1]=1,
+                                                       doit[D_SHA256]=1,
+                                                       doit[D_SHA512]=1;
+               else
+#ifndef OPENSSL_NO_SHA256
+                       if (strcmp(*argv,"sha256") == 0) doit[D_SHA256]=1;
+               else
+#endif
+#ifndef OPENSSL_NO_SHA512
+                       if (strcmp(*argv,"sha512") == 0) doit[D_SHA512]=1;
+               else
+#endif
+#endif
+#ifndef OPENSSL_NO_WHIRLPOOL
+                       if (strcmp(*argv,"whirlpool") == 0) doit[D_WHIRLPOOL]=1;
                else
 #endif
-#ifndef NO_RMD160
+#ifndef OPENSSL_NO_RIPEMD
                        if (strcmp(*argv,"ripemd") == 0) doit[D_RMD160]=1;
                else
                        if (strcmp(*argv,"rmd160") == 0) doit[D_RMD160]=1;
@@ -432,31 +818,48 @@ char **argv;
                        if (strcmp(*argv,"ripemd160") == 0) doit[D_RMD160]=1;
                else
 #endif
-#ifndef NO_RC4
+#ifndef OPENSSL_NO_RC4
                        if (strcmp(*argv,"rc4") == 0) doit[D_RC4]=1;
                else 
 #endif
-#ifndef NO_DEF
+#ifndef OPENSSL_NO_DES
                        if (strcmp(*argv,"des-cbc") == 0) doit[D_CBC_DES]=1;
                else    if (strcmp(*argv,"des-ede3") == 0) doit[D_EDE3_DES]=1;
                else
 #endif
-#ifndef NO_RSA
-#ifdef RSAref
+#ifndef OPENSSL_NO_AES
+                       if (strcmp(*argv,"aes-128-cbc") == 0) doit[D_CBC_128_AES]=1;
+               else    if (strcmp(*argv,"aes-192-cbc") == 0) doit[D_CBC_192_AES]=1;
+               else    if (strcmp(*argv,"aes-256-cbc") == 0) doit[D_CBC_256_AES]=1;
+               else    if (strcmp(*argv,"aes-128-ige") == 0) doit[D_IGE_128_AES]=1;
+               else    if (strcmp(*argv,"aes-192-ige") == 0) doit[D_IGE_192_AES]=1;
+               else    if (strcmp(*argv,"aes-256-ige") == 0) doit[D_IGE_256_AES]=1;
+                else
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+                       if (strcmp(*argv,"camellia-128-cbc") == 0) doit[D_CBC_128_CML]=1;
+               else    if (strcmp(*argv,"camellia-192-cbc") == 0) doit[D_CBC_192_CML]=1;
+               else    if (strcmp(*argv,"camellia-256-cbc") == 0) doit[D_CBC_256_CML]=1;
+               else
+#endif
+#ifndef OPENSSL_NO_RSA
+#if 0 /* was: #ifdef RSAref */
                        if (strcmp(*argv,"rsaref") == 0) 
                        {
-                       RSA_set_default_method(RSA_PKCS1_RSAref());
+                       RSA_set_default_openssl_method(RSA_PKCS1_RSAref());
                        j--;
                        }
                else
 #endif
-                       if (strcmp(*argv,"ssleay") == 0) 
+#ifndef RSA_NULL
+                       if (strcmp(*argv,"openssl") == 0) 
                        {
                        RSA_set_default_method(RSA_PKCS1_SSLeay());
                        j--;
                        }
                else
-#endif /* !NO_RSA */
+#endif
+#endif /* !OPENSSL_NO_RSA */
                     if (strcmp(*argv,"dsa512") == 0) dsa_doit[R_DSA_512]=2;
                else if (strcmp(*argv,"dsa1024") == 0) dsa_doit[R_DSA_1024]=2;
                else if (strcmp(*argv,"dsa2048") == 0) dsa_doit[R_DSA_2048]=2;
@@ -465,34 +868,39 @@ char **argv;
                else if (strcmp(*argv,"rsa2048") == 0) rsa_doit[R_RSA_2048]=2;
                else if (strcmp(*argv,"rsa4096") == 0) rsa_doit[R_RSA_4096]=2;
                else
-#ifndef NO_RC2
+#ifndef OPENSSL_NO_RC2
                     if (strcmp(*argv,"rc2-cbc") == 0) doit[D_CBC_RC2]=1;
                else if (strcmp(*argv,"rc2") == 0) doit[D_CBC_RC2]=1;
                else
 #endif
-#ifndef NO_RC5
+#ifndef OPENSSL_NO_RC5
                     if (strcmp(*argv,"rc5-cbc") == 0) doit[D_CBC_RC5]=1;
                else if (strcmp(*argv,"rc5") == 0) doit[D_CBC_RC5]=1;
                else
 #endif
-#ifndef NO_IDEA
+#ifndef OPENSSL_NO_IDEA
                     if (strcmp(*argv,"idea-cbc") == 0) doit[D_CBC_IDEA]=1;
                else if (strcmp(*argv,"idea") == 0) doit[D_CBC_IDEA]=1;
                else
 #endif
-#ifndef NO_BLOWFISH
+#ifndef OPENSSL_NO_SEED
+                    if (strcmp(*argv,"seed-cbc") == 0) doit[D_CBC_SEED]=1;
+               else if (strcmp(*argv,"seed") == 0) doit[D_CBC_SEED]=1;
+               else
+#endif
+#ifndef OPENSSL_NO_BF
                     if (strcmp(*argv,"bf-cbc") == 0) doit[D_CBC_BF]=1;
                else if (strcmp(*argv,"blowfish") == 0) doit[D_CBC_BF]=1;
                else if (strcmp(*argv,"bf") == 0) doit[D_CBC_BF]=1;
                else
 #endif
-#ifndef NO_CAST
+#ifndef OPENSSL_NO_CAST
                     if (strcmp(*argv,"cast-cbc") == 0) doit[D_CBC_CAST]=1;
                else if (strcmp(*argv,"cast") == 0) doit[D_CBC_CAST]=1;
                else if (strcmp(*argv,"cast5") == 0) doit[D_CBC_CAST]=1;
                else
 #endif
-#ifndef NO_DES
+#ifndef OPENSSL_NO_DES
                        if (strcmp(*argv,"des") == 0)
                        {
                        doit[D_CBC_DES]=1;
@@ -500,7 +908,29 @@ char **argv;
                        }
                else
 #endif
-#ifndef NO_RSA
+#ifndef OPENSSL_NO_AES
+                       if (strcmp(*argv,"aes") == 0)
+                       {
+                       doit[D_CBC_128_AES]=1;
+                       doit[D_CBC_192_AES]=1;
+                       doit[D_CBC_256_AES]=1;
+                       }
+               else if (strcmp(*argv,"ghash") == 0)
+                       {
+                       doit[D_GHASH]=1;
+                       }
+               else
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+                       if (strcmp(*argv,"camellia") == 0)
+                       {
+                       doit[D_CBC_128_CML]=1;
+                       doit[D_CBC_192_CML]=1;
+                       doit[D_CBC_256_CML]=1;
+                       }
+               else
+#endif
+#ifndef OPENSSL_NO_RSA
                        if (strcmp(*argv,"rsa") == 0)
                        {
                        rsa_doit[R_RSA_512]=1;
@@ -510,43 +940,204 @@ char **argv;
                        }
                else
 #endif
-#ifndef NO_DSA
+#ifndef OPENSSL_NO_DSA
                        if (strcmp(*argv,"dsa") == 0)
                        {
                        dsa_doit[R_DSA_512]=1;
                        dsa_doit[R_DSA_1024]=1;
+                       dsa_doit[R_DSA_2048]=1;
+                       }
+               else
+#endif
+#ifndef OPENSSL_NO_ECDSA
+                    if (strcmp(*argv,"ecdsap160") == 0) ecdsa_doit[R_EC_P160]=2;
+               else if (strcmp(*argv,"ecdsap192") == 0) ecdsa_doit[R_EC_P192]=2;
+               else if (strcmp(*argv,"ecdsap224") == 0) ecdsa_doit[R_EC_P224]=2;
+               else if (strcmp(*argv,"ecdsap256") == 0) ecdsa_doit[R_EC_P256]=2;
+               else if (strcmp(*argv,"ecdsap384") == 0) ecdsa_doit[R_EC_P384]=2;
+               else if (strcmp(*argv,"ecdsap521") == 0) ecdsa_doit[R_EC_P521]=2;
+               else if (strcmp(*argv,"ecdsak163") == 0) ecdsa_doit[R_EC_K163]=2;
+               else if (strcmp(*argv,"ecdsak233") == 0) ecdsa_doit[R_EC_K233]=2;
+               else if (strcmp(*argv,"ecdsak283") == 0) ecdsa_doit[R_EC_K283]=2;
+               else if (strcmp(*argv,"ecdsak409") == 0) ecdsa_doit[R_EC_K409]=2;
+               else if (strcmp(*argv,"ecdsak571") == 0) ecdsa_doit[R_EC_K571]=2;
+               else if (strcmp(*argv,"ecdsab163") == 0) ecdsa_doit[R_EC_B163]=2;
+               else if (strcmp(*argv,"ecdsab233") == 0) ecdsa_doit[R_EC_B233]=2;
+               else if (strcmp(*argv,"ecdsab283") == 0) ecdsa_doit[R_EC_B283]=2;
+               else if (strcmp(*argv,"ecdsab409") == 0) ecdsa_doit[R_EC_B409]=2;
+               else if (strcmp(*argv,"ecdsab571") == 0) ecdsa_doit[R_EC_B571]=2;
+               else if (strcmp(*argv,"ecdsa") == 0)
+                       {
+                       for (i=0; i < EC_NUM; i++)
+                               ecdsa_doit[i]=1;
+                       }
+               else
+#endif
+#ifndef OPENSSL_NO_ECDH
+                    if (strcmp(*argv,"ecdhp160") == 0) ecdh_doit[R_EC_P160]=2;
+               else if (strcmp(*argv,"ecdhp192") == 0) ecdh_doit[R_EC_P192]=2;
+               else if (strcmp(*argv,"ecdhp224") == 0) ecdh_doit[R_EC_P224]=2;
+               else if (strcmp(*argv,"ecdhp256") == 0) ecdh_doit[R_EC_P256]=2;
+               else if (strcmp(*argv,"ecdhp384") == 0) ecdh_doit[R_EC_P384]=2;
+               else if (strcmp(*argv,"ecdhp521") == 0) ecdh_doit[R_EC_P521]=2;
+               else if (strcmp(*argv,"ecdhk163") == 0) ecdh_doit[R_EC_K163]=2;
+               else if (strcmp(*argv,"ecdhk233") == 0) ecdh_doit[R_EC_K233]=2;
+               else if (strcmp(*argv,"ecdhk283") == 0) ecdh_doit[R_EC_K283]=2;
+               else if (strcmp(*argv,"ecdhk409") == 0) ecdh_doit[R_EC_K409]=2;
+               else if (strcmp(*argv,"ecdhk571") == 0) ecdh_doit[R_EC_K571]=2;
+               else if (strcmp(*argv,"ecdhb163") == 0) ecdh_doit[R_EC_B163]=2;
+               else if (strcmp(*argv,"ecdhb233") == 0) ecdh_doit[R_EC_B233]=2;
+               else if (strcmp(*argv,"ecdhb283") == 0) ecdh_doit[R_EC_B283]=2;
+               else if (strcmp(*argv,"ecdhb409") == 0) ecdh_doit[R_EC_B409]=2;
+               else if (strcmp(*argv,"ecdhb571") == 0) ecdh_doit[R_EC_B571]=2;
+               else if (strcmp(*argv,"ecdh") == 0)
+                       {
+                       for (i=0; i < EC_NUM; i++)
+                               ecdh_doit[i]=1;
                        }
                else
 #endif
                        {
-                       BIO_printf(bio_err,"bad value, pick one of\n");
-                       BIO_printf(bio_err,"md2      mdc2       md5      hmac      sha1    rmd160\n");
-#ifndef NO_IDEA
+                       BIO_printf(bio_err,"Error: bad option or value\n");
+                       BIO_printf(bio_err,"\n");
+                       BIO_printf(bio_err,"Available values:\n");
+#ifndef OPENSSL_NO_MD2
+                       BIO_printf(bio_err,"md2      ");
+#endif
+#ifndef OPENSSL_NO_MDC2
+                       BIO_printf(bio_err,"mdc2     ");
+#endif
+#ifndef OPENSSL_NO_MD4
+                       BIO_printf(bio_err,"md4      ");
+#endif
+#ifndef OPENSSL_NO_MD5
+                       BIO_printf(bio_err,"md5      ");
+#ifndef OPENSSL_NO_HMAC
+                       BIO_printf(bio_err,"hmac     ");
+#endif
+#endif
+#ifndef OPENSSL_NO_SHA1
+                       BIO_printf(bio_err,"sha1     ");
+#endif
+#ifndef OPENSSL_NO_SHA256
+                       BIO_printf(bio_err,"sha256   ");
+#endif
+#ifndef OPENSSL_NO_SHA512
+                       BIO_printf(bio_err,"sha512   ");
+#endif
+#ifndef OPENSSL_NO_WHIRLPOOL
+                       BIO_printf(bio_err,"whirlpool");
+#endif
+#ifndef OPENSSL_NO_RIPEMD160
+                       BIO_printf(bio_err,"rmd160");
+#endif
+#if !defined(OPENSSL_NO_MD2) || !defined(OPENSSL_NO_MDC2) || \
+    !defined(OPENSSL_NO_MD4) || !defined(OPENSSL_NO_MD5) || \
+    !defined(OPENSSL_NO_SHA1) || !defined(OPENSSL_NO_RIPEMD160) || \
+    !defined(OPENSSL_NO_WHIRLPOOL)
+                       BIO_printf(bio_err,"\n");
+#endif
+
+#ifndef OPENSSL_NO_IDEA
                        BIO_printf(bio_err,"idea-cbc ");
 #endif
-#ifndef NO_RC2
+#ifndef OPENSSL_NO_SEED
+                       BIO_printf(bio_err,"seed-cbc ");
+#endif
+#ifndef OPENSSL_NO_RC2
                        BIO_printf(bio_err,"rc2-cbc  ");
 #endif
-#ifndef NO_RC5
+#ifndef OPENSSL_NO_RC5
                        BIO_printf(bio_err,"rc5-cbc  ");
 #endif
-#ifndef NO_BLOWFISH
+#ifndef OPENSSL_NO_BF
                        BIO_printf(bio_err,"bf-cbc");
 #endif
-#if !defined(NO_IDEA) && !defined(NO_RC2) && !defined(NO_BLOWFISH) && !defined(NO_RC5)
+#if !defined(OPENSSL_NO_IDEA) || !defined(OPENSSL_NO_SEED) || !defined(OPENSSL_NO_RC2) || \
+    !defined(OPENSSL_NO_BF) || !defined(OPENSSL_NO_RC5)
                        BIO_printf(bio_err,"\n");
 #endif
+#ifndef OPENSSL_NO_DES
                        BIO_printf(bio_err,"des-cbc  des-ede3 ");
-#ifndef NO_RC4
+#endif
+#ifndef OPENSSL_NO_AES
+                       BIO_printf(bio_err,"aes-128-cbc aes-192-cbc aes-256-cbc ");
+                       BIO_printf(bio_err,"aes-128-ige aes-192-ige aes-256-ige ");
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+                       BIO_printf(bio_err,"\n");
+                       BIO_printf(bio_err,"camellia-128-cbc camellia-192-cbc camellia-256-cbc ");
+#endif
+#ifndef OPENSSL_NO_RC4
                        BIO_printf(bio_err,"rc4");
 #endif
-#ifndef NO_RSA
-                       BIO_printf(bio_err,"\nrsa512   rsa1024  rsa2048  rsa4096\n");
+                       BIO_printf(bio_err,"\n");
+
+#ifndef OPENSSL_NO_RSA
+                       BIO_printf(bio_err,"rsa512   rsa1024  rsa2048  rsa4096\n");
+#endif
+
+#ifndef OPENSSL_NO_DSA
+                       BIO_printf(bio_err,"dsa512   dsa1024  dsa2048\n");
+#endif
+#ifndef OPENSSL_NO_ECDSA
+                       BIO_printf(bio_err,"ecdsap160 ecdsap192 ecdsap224 ecdsap256 ecdsap384 ecdsap521\n");
+                       BIO_printf(bio_err,"ecdsak163 ecdsak233 ecdsak283 ecdsak409 ecdsak571\n");
+                       BIO_printf(bio_err,"ecdsab163 ecdsab233 ecdsab283 ecdsab409 ecdsab571\n");
+                       BIO_printf(bio_err,"ecdsa\n");
+#endif
+#ifndef OPENSSL_NO_ECDH
+                       BIO_printf(bio_err,"ecdhp160  ecdhp192  ecdhp224  ecdhp256  ecdhp384  ecdhp521\n");
+                       BIO_printf(bio_err,"ecdhk163  ecdhk233  ecdhk283  ecdhk409  ecdhk571\n");
+                       BIO_printf(bio_err,"ecdhb163  ecdhb233  ecdhb283  ecdhb409  ecdhb571\n");
+                       BIO_printf(bio_err,"ecdh\n");
+#endif
+
+#ifndef OPENSSL_NO_IDEA
+                       BIO_printf(bio_err,"idea     ");
+#endif
+#ifndef OPENSSL_NO_SEED
+                       BIO_printf(bio_err,"seed     ");
+#endif
+#ifndef OPENSSL_NO_RC2
+                       BIO_printf(bio_err,"rc2      ");
+#endif
+#ifndef OPENSSL_NO_DES
+                       BIO_printf(bio_err,"des      ");
+#endif
+#ifndef OPENSSL_NO_AES
+                       BIO_printf(bio_err,"aes      ");
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+                       BIO_printf(bio_err,"camellia ");
+#endif
+#ifndef OPENSSL_NO_RSA
+                       BIO_printf(bio_err,"rsa      ");
+#endif
+#ifndef OPENSSL_NO_BF
+                       BIO_printf(bio_err,"blowfish");
 #endif
-#ifndef NO_DSA
-                       BIO_printf(bio_err,"\ndsa512   dsa1024  dsa2048\n");
+#if !defined(OPENSSL_NO_IDEA) || !defined(OPENSSL_NO_SEED) || \
+    !defined(OPENSSL_NO_RC2) || !defined(OPENSSL_NO_DES) || \
+    !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_BF) || \
+    !defined(OPENSSL_NO_AES) || !defined(OPENSSL_NO_CAMELLIA)
+                       BIO_printf(bio_err,"\n");
+#endif
+
+                       BIO_printf(bio_err,"\n");
+                       BIO_printf(bio_err,"Available options:\n");
+#if defined(TIMES) || defined(USE_TOD)
+                       BIO_printf(bio_err,"-elapsed        measure time in real time instead of CPU user time.\n");
+#endif
+#ifndef OPENSSL_NO_ENGINE
+                       BIO_printf(bio_err,"-engine e       use engine e, possibly a hardware device.\n");
+#endif
+                       BIO_printf(bio_err,"-evp e          use EVP e.\n");
+                       BIO_printf(bio_err,"-decrypt        time decryption instead of encryption (only EVP).\n");
+                       BIO_printf(bio_err,"-mr             produce machine readable output.\n");
+#ifndef NO_FORK
+                       BIO_printf(bio_err,"-multi n        run n benchmarks in parallel.\n");
 #endif
-                       BIO_printf(bio_err,"idea     rc2      des      rsa    blowfish\n");
                        goto end;
                        }
                argc--;
@@ -554,27 +1145,41 @@ char **argv;
                j++;
                }
 
+#ifndef NO_FORK
+       if(multi && do_multi(multi))
+               goto show_res;
+#endif
+
        if (j == 0)
                {
                for (i=0; i<ALGOR_NUM; i++)
-                       doit[i]=1;
+                       {
+                       if (i != D_EVP)
+                               doit[i]=1;
+                       }
                for (i=0; i<RSA_NUM; i++)
                        rsa_doit[i]=1;
                for (i=0; i<DSA_NUM; i++)
                        dsa_doit[i]=1;
+#ifndef OPENSSL_NO_ECDSA
+               for (i=0; i<EC_NUM; i++)
+                       ecdsa_doit[i]=1;
+#endif
+#ifndef OPENSSL_NO_ECDH
+               for (i=0; i<EC_NUM; i++)
+                       ecdh_doit[i]=1;
+#endif
                }
        for (i=0; i<ALGOR_NUM; i++)
                if (doit[i]) pr_header++;
 
-#ifndef TIMES
-       BIO_printf(bio_err,"To get the most accurate results, try to run this\n");
-       BIO_printf(bio_err,"program when this computer is idle.\n");
-#endif
+       if (usertime == 0 && !mr)
+               BIO_printf(bio_err,"You have chosen to measure elapsed time instead of user CPU time.\n");
 
-#ifndef NO_RSA
+#ifndef OPENSSL_NO_RSA
        for (i=0; i<RSA_NUM; i++)
                {
-               unsigned char *p;
+               const unsigned char *p;
 
                p=rsa_data[i];
                rsa_key[i]=d2i_RSAPrivateKey(NULL,&p,rsa_data_length[i]);
@@ -586,7 +1191,9 @@ char **argv;
 #if 0
                else
                        {
-                       BIO_printf(bio_err,"Loaded RSA key, %d bit modulus and e= 0x",BN_num_bits(rsa_key[i]->n));
+                       BIO_printf(bio_err,mr ? "+RK:%d:"
+                                  : "Loaded RSA key, %d bit modulus and e= 0x",
+                                  BN_num_bits(rsa_key[i]->n));
                        BN_print(bio_err,rsa_key[i]->e);
                        BIO_printf(bio_err,"\n");
                        }
@@ -594,51 +1201,69 @@ char **argv;
                }
 #endif
 
-#ifndef NO_DSA
+#ifndef OPENSSL_NO_DSA
        dsa_key[0]=get_dsa512();
        dsa_key[1]=get_dsa1024();
        dsa_key[2]=get_dsa2048();
 #endif
 
-#ifndef NO_DES
-       des_set_key((C_Block *)key,sch);
-       des_set_key((C_Block *)key2,sch2);
-       des_set_key((C_Block *)key3,sch3);
-#endif
-#ifndef NO_IDEA
+#ifndef OPENSSL_NO_DES
+       DES_set_key_unchecked(&key,&sch);
+       DES_set_key_unchecked(&key2,&sch2);
+       DES_set_key_unchecked(&key3,&sch3);
+#endif
+#ifndef OPENSSL_NO_AES
+       AES_set_encrypt_key(key16,128,&aes_ks1);
+       AES_set_encrypt_key(key24,192,&aes_ks2);
+       AES_set_encrypt_key(key32,256,&aes_ks3);
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+       Camellia_set_key(key16,128,&camellia_ks1);
+       Camellia_set_key(ckey24,192,&camellia_ks2);
+       Camellia_set_key(ckey32,256,&camellia_ks3);
+#endif
+#ifndef OPENSSL_NO_IDEA
        idea_set_encrypt_key(key16,&idea_ks);
 #endif
-#ifndef NO_RC4
+#ifndef OPENSSL_NO_SEED
+       SEED_set_key(key16,&seed_ks);
+#endif
+#ifndef OPENSSL_NO_RC4
        RC4_set_key(&rc4_ks,16,key16);
 #endif
-#ifndef NO_RC2
+#ifndef OPENSSL_NO_RC2
        RC2_set_key(&rc2_ks,16,key16,128);
 #endif
-#ifndef NO_RC5
+#ifndef OPENSSL_NO_RC5
        RC5_32_set_key(&rc5_ks,16,key16,12);
 #endif
-#ifndef NO_BLOWFISH
+#ifndef OPENSSL_NO_BF
        BF_set_key(&bf_ks,16,key16);
 #endif
-#ifndef NO_CAST
+#ifndef OPENSSL_NO_CAST
        CAST_set_key(&cast_ks,16,key16);
 #endif
-
+#ifndef OPENSSL_NO_RSA
        memset(rsa_c,0,sizeof(rsa_c));
+#endif
 #ifndef SIGALRM
+#ifndef OPENSSL_NO_DES
        BIO_printf(bio_err,"First we calculate the approximate speed ...\n");
        count=10;
        do      {
-               long i;
+               long it;
                count*=2;
                Time_F(START);
-               for (i=count; i; i--)
-                       des_ecb_encrypt((C_Block *)buf,(C_Block *)buf,
-                               &(sch[0]),DES_ENCRYPT);
+               for (it=count; it; it--)
+                       DES_ecb_encrypt((DES_cblock *)buf,
+                               (DES_cblock *)buf,
+                               &sch,DES_ENCRYPT);
                d=Time_F(STOP);
                } while (d <3);
+       save_count=count;
        c[D_MD2][0]=count/10;
        c[D_MDC2][0]=count/10;
+       c[D_MD4][0]=count;
        c[D_MD5][0]=count;
        c[D_HMAC][0]=count;
        c[D_SHA1][0]=count;
@@ -647,19 +1272,37 @@ char **argv;
        c[D_CBC_DES][0]=count;
        c[D_EDE3_DES][0]=count/3;
        c[D_CBC_IDEA][0]=count;
+       c[D_CBC_SEED][0]=count;
        c[D_CBC_RC2][0]=count;
        c[D_CBC_RC5][0]=count;
        c[D_CBC_BF][0]=count;
        c[D_CBC_CAST][0]=count;
+       c[D_CBC_128_AES][0]=count;
+       c[D_CBC_192_AES][0]=count;
+       c[D_CBC_256_AES][0]=count;
+       c[D_CBC_128_CML][0]=count;
+       c[D_CBC_192_CML][0]=count;
+       c[D_CBC_256_CML][0]=count;
+       c[D_SHA256][0]=count;
+       c[D_SHA512][0]=count;
+       c[D_WHIRLPOOL][0]=count;
+       c[D_IGE_128_AES][0]=count;
+       c[D_IGE_192_AES][0]=count;
+       c[D_IGE_256_AES][0]=count;
+       c[D_GHASH][0]=count;
 
        for (i=1; i<SIZE_NUM; i++)
                {
                c[D_MD2][i]=c[D_MD2][0]*4*lengths[0]/lengths[i];
                c[D_MDC2][i]=c[D_MDC2][0]*4*lengths[0]/lengths[i];
+               c[D_MD4][i]=c[D_MD4][0]*4*lengths[0]/lengths[i];
                c[D_MD5][i]=c[D_MD5][0]*4*lengths[0]/lengths[i];
                c[D_HMAC][i]=c[D_HMAC][0]*4*lengths[0]/lengths[i];
                c[D_SHA1][i]=c[D_SHA1][0]*4*lengths[0]/lengths[i];
                c[D_RMD160][i]=c[D_RMD160][0]*4*lengths[0]/lengths[i];
+               c[D_SHA256][i]=c[D_SHA256][0]*4*lengths[0]/lengths[i];
+               c[D_SHA512][i]=c[D_SHA512][0]*4*lengths[0]/lengths[i];
+               c[D_WHIRLPOOL][i]=c[D_WHIRLPOOL][0]*4*lengths[0]/lengths[i];
                }
        for (i=1; i<SIZE_NUM; i++)
                {
@@ -671,11 +1314,22 @@ char **argv;
                c[D_CBC_DES][i]=c[D_CBC_DES][i-1]*l0/l1;
                c[D_EDE3_DES][i]=c[D_EDE3_DES][i-1]*l0/l1;
                c[D_CBC_IDEA][i]=c[D_CBC_IDEA][i-1]*l0/l1;
+               c[D_CBC_SEED][i]=c[D_CBC_SEED][i-1]*l0/l1;
                c[D_CBC_RC2][i]=c[D_CBC_RC2][i-1]*l0/l1;
                c[D_CBC_RC5][i]=c[D_CBC_RC5][i-1]*l0/l1;
                c[D_CBC_BF][i]=c[D_CBC_BF][i-1]*l0/l1;
                c[D_CBC_CAST][i]=c[D_CBC_CAST][i-1]*l0/l1;
+               c[D_CBC_128_AES][i]=c[D_CBC_128_AES][i-1]*l0/l1;
+               c[D_CBC_192_AES][i]=c[D_CBC_192_AES][i-1]*l0/l1;
+               c[D_CBC_256_AES][i]=c[D_CBC_256_AES][i-1]*l0/l1;
+               c[D_CBC_128_CML][i]=c[D_CBC_128_CML][i-1]*l0/l1;
+               c[D_CBC_192_CML][i]=c[D_CBC_192_CML][i-1]*l0/l1;
+               c[D_CBC_256_CML][i]=c[D_CBC_256_CML][i-1]*l0/l1;
+               c[D_IGE_128_AES][i]=c[D_IGE_128_AES][i-1]*l0/l1;
+               c[D_IGE_192_AES][i]=c[D_IGE_192_AES][i-1]*l0/l1;
+               c[D_IGE_256_AES][i]=c[D_IGE_256_AES][i-1]*l0/l1;
                }
+#ifndef OPENSSL_NO_RSA
        rsa_c[R_RSA_512][0]=count/2000;
        rsa_c[R_RSA_512][1]=count/400;
        for (i=1; i<RSA_NUM; i++)
@@ -693,7 +1347,9 @@ char **argv;
                                }
                        }                               
                }
+#endif
 
+#ifndef OPENSSL_NO_DSA
        dsa_c[R_DSA_512][0]=count/1000;
        dsa_c[R_DSA_512][1]=count/1000/2;
        for (i=1; i<DSA_NUM; i++)
@@ -711,71 +1367,197 @@ char **argv;
                                }
                        }                               
                }
-
-#define COND(d)        (count < (d))
-#define COUNT(d) (d)
-#else
-#define COND(c)        (run)
-#define COUNT(d) (count)
-       signal(SIGALRM,sig_done);
 #endif
 
-#ifndef NO_MD2
-       if (doit[D_MD2])
+#ifndef OPENSSL_NO_ECDSA
+       ecdsa_c[R_EC_P160][0]=count/1000;
+       ecdsa_c[R_EC_P160][1]=count/1000/2;
+       for (i=R_EC_P192; i<=R_EC_P521; i++)
                {
-               for (j=0; j<SIZE_NUM; j++)
+               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))
+                       ecdsa_doit[i]=0;
+               else
                        {
-                       print_message(names[D_MD2],c[D_MD2][j],lengths[j]);
-                       Time_F(START);
-                       for (count=0,run=1; COND(c[D_MD2][j]); count++)
-                               MD2(buf,(unsigned long)lengths[j],&(md2[0]));
-                       d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_MD2],d);
-                       results[D_MD2][j]=((double)count)/d*lengths[j];
+                       if (ecdsa_c[i] == 0)
+                               {
+                               ecdsa_c[i][0]=1;
+                               ecdsa_c[i][1]=1;
+                               }
                        }
                }
-#endif
-#ifndef NO_MDC2
-       if (doit[D_MDC2])
+       ecdsa_c[R_EC_K163][0]=count/1000;
+       ecdsa_c[R_EC_K163][1]=count/1000/2;
+       for (i=R_EC_K233; i<=R_EC_K571; i++)
                {
-               for (j=0; j<SIZE_NUM; j++)
+               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))
+                       ecdsa_doit[i]=0;
+               else
                        {
-                       print_message(names[D_MDC2],c[D_MDC2][j],lengths[j]);
-                       Time_F(START);
-                       for (count=0,run=1; COND(c[D_MDC2][j]); count++)
-                               MDC2(buf,(unsigned long)lengths[j],&(mdc2[0]));
-                       d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_MDC2],d);
-                       results[D_MDC2][j]=((double)count)/d*lengths[j];
+                       if (ecdsa_c[i] == 0)
+                               {
+                               ecdsa_c[i][0]=1;
+                               ecdsa_c[i][1]=1;
+                               }
                        }
                }
-#endif
-
-#ifndef NO_MD5
-       if (doit[D_MD5])
+       ecdsa_c[R_EC_B163][0]=count/1000;
+       ecdsa_c[R_EC_B163][1]=count/1000/2;
+       for (i=R_EC_B233; i<=R_EC_B571; i++)
                {
-               for (j=0; j<SIZE_NUM; j++)
+               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))
+                       ecdsa_doit[i]=0;
+               else
                        {
-                       print_message(names[D_MD5],c[D_MD5][j],lengths[j]);
-                       Time_F(START);
-                       for (count=0,run=1; COND(c[D_MD5][j]); count++)
-                               MD5(&(buf[0]),(unsigned long)lengths[j],&(md5[0]));
-                       d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_MD5],d);
-                       results[D_MD5][j]=((double)count)/d*lengths[j];
+                       if (ecdsa_c[i] == 0)
+                               {
+                               ecdsa_c[i][0]=1;
+                               ecdsa_c[i][1]=1;
+                               }
                        }
                }
 #endif
 
-#ifndef NO_MD5
-       if (doit[D_HMAC])
+#ifndef OPENSSL_NO_ECDH
+       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))
+                       ecdh_doit[i]=0;
+               else
+                       {
+                       if (ecdh_c[i] == 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))
+                       ecdh_doit[i]=0;
+               else
+                       {
+                       if (ecdh_c[i] == 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))
+                       ecdh_doit[i]=0;
+               else
+                       {
+                       if (ecdh_c[i] == 0)
+                               {
+                               ecdh_c[i][0]=1;
+                               ecdh_c[i][1]=1;
+                               }
+                       }
+               }
+#endif
+
+#define COND(d)        (count < (d))
+#define COUNT(d) (d)
+#else
+/* not worth fixing */
+# error "You cannot disable DES on systems without SIGALRM."
+#endif /* OPENSSL_NO_DES */
+#else
+#define COND(c)        (run && count<0x7fffffff)
+#define COUNT(d) (count)
+#ifndef _WIN32
+       signal(SIGALRM,sig_done);
+#endif
+#endif /* SIGALRM */
+
+#ifndef OPENSSL_NO_MD2
+       if (doit[D_MD2])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_MD2],c[D_MD2][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_MD2][j]); count++)
+                               EVP_Digest(buf,(unsigned long)lengths[j],&(md2[0]),NULL,EVP_md2(),NULL);
+                       d=Time_F(STOP);
+                       print_result(D_MD2,j,count,d);
+                       }
+               }
+#endif
+#ifndef OPENSSL_NO_MDC2
+       if (doit[D_MDC2])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_MDC2],c[D_MDC2][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_MDC2][j]); count++)
+                               EVP_Digest(buf,(unsigned long)lengths[j],&(mdc2[0]),NULL,EVP_mdc2(),NULL);
+                       d=Time_F(STOP);
+                       print_result(D_MDC2,j,count,d);
+                       }
+               }
+#endif
+
+#ifndef OPENSSL_NO_MD4
+       if (doit[D_MD4])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_MD4],c[D_MD4][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_MD4][j]); count++)
+                               EVP_Digest(&(buf[0]),(unsigned long)lengths[j],&(md4[0]),NULL,EVP_md4(),NULL);
+                       d=Time_F(STOP);
+                       print_result(D_MD4,j,count,d);
+                       }
+               }
+#endif
+
+#ifndef OPENSSL_NO_MD5
+       if (doit[D_MD5])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_MD5],c[D_MD5][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_MD5][j]); count++)
+                               MD5(buf,lengths[j],md5);
+                       d=Time_F(STOP);
+                       print_result(D_MD5,j,count,d);
+                       }
+               }
+#endif
+
+#if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_HMAC)
+       if (doit[D_HMAC])
                {
                HMAC_CTX hctx;
-               HMAC_Init(&hctx,(unsigned char *)"This is a key...",
-                       16,EVP_md5());
+
+               HMAC_CTX_init(&hctx);
+               HMAC_Init_ex(&hctx,(unsigned char *)"This is a key...",
+                       16,EVP_md5(), NULL);
 
                for (j=0; j<SIZE_NUM; j++)
                        {
@@ -783,18 +1565,17 @@ char **argv;
                        Time_F(START);
                        for (count=0,run=1; COND(c[D_HMAC][j]); count++)
                                {
-                               HMAC_Init(&hctx,NULL,0,NULL);
-                                HMAC_Update(&hctx,buf,lengths[j]);
-                                HMAC_Final(&hctx,&(hmac[0]),NULL);
+                               HMAC_Init_ex(&hctx,NULL,0,NULL,NULL);
+                               HMAC_Update(&hctx,buf,lengths[j]);
+                               HMAC_Final(&hctx,&(hmac[0]),NULL);
                                }
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_HMAC],d);
-                       results[D_HMAC][j]=((double)count)/d*lengths[j];
+                       print_result(D_HMAC,j,count,d);
                        }
+               HMAC_CTX_cleanup(&hctx);
                }
 #endif
-#ifndef NO_SHA1
+#ifndef OPENSSL_NO_SHA
        if (doit[D_SHA1])
                {
                for (j=0; j<SIZE_NUM; j++)
@@ -802,15 +1583,63 @@ char **argv;
                        print_message(names[D_SHA1],c[D_SHA1][j],lengths[j]);
                        Time_F(START);
                        for (count=0,run=1; COND(c[D_SHA1][j]); count++)
-                               SHA1(buf,(unsigned long)lengths[j],&(sha[0]));
+#if 0
+                               EVP_Digest(buf,(unsigned long)lengths[j],&(sha[0]),NULL,EVP_sha1(),NULL);
+#else
+                               SHA1(buf,lengths[j],sha);
+#endif
+                       d=Time_F(STOP);
+                       print_result(D_SHA1,j,count,d);
+                       }
+               }
+
+#ifndef OPENSSL_NO_SHA256
+       if (doit[D_SHA256])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_SHA256],c[D_SHA256][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_SHA256][j]); count++)
+                               SHA256(buf,lengths[j],sha256);
+                       d=Time_F(STOP);
+                       print_result(D_SHA256,j,count,d);
+                       }
+               }
+#endif
+
+#ifndef OPENSSL_NO_SHA512
+       if (doit[D_SHA512])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_SHA512],c[D_SHA512][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_SHA512][j]); count++)
+                               SHA512(buf,lengths[j],sha512);
+                       d=Time_F(STOP);
+                       print_result(D_SHA512,j,count,d);
+                       }
+               }
+#endif
+#endif
+
+#ifndef OPENSSL_NO_WHIRLPOOL
+       if (doit[D_WHIRLPOOL])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_WHIRLPOOL],c[D_WHIRLPOOL][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_WHIRLPOOL][j]); count++)
+                               WHIRLPOOL(buf,lengths[j],whirlpool);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_SHA1],d);
-                       results[D_SHA1][j]=((double)count)/d*lengths[j];
+                       print_result(D_WHIRLPOOL,j,count,d);
                        }
                }
 #endif
-#ifndef NO_RMD160
+
+#ifndef OPENSSL_NO_RIPEMD
        if (doit[D_RMD160])
                {
                for (j=0; j<SIZE_NUM; j++)
@@ -818,15 +1647,13 @@ char **argv;
                        print_message(names[D_RMD160],c[D_RMD160][j],lengths[j]);
                        Time_F(START);
                        for (count=0,run=1; COND(c[D_RMD160][j]); count++)
-                               RIPEMD160(buf,(unsigned long)lengths[j],&(rmd160[0]));
+                               EVP_Digest(buf,(unsigned long)lengths[j],&(rmd160[0]),NULL,EVP_ripemd160(),NULL);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_RMD160],d);
-                       results[D_RMD160][j]=((double)count)/d*lengths[j];
+                       print_result(D_RMD160,j,count,d);
                        }
                }
 #endif
-#ifndef NO_RC4
+#ifndef OPENSSL_NO_RC4
        if (doit[D_RC4])
                {
                for (j=0; j<SIZE_NUM; j++)
@@ -837,13 +1664,11 @@ char **argv;
                                RC4(&rc4_ks,(unsigned int)lengths[j],
                                        buf,buf);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_RC4],d);
-                       results[D_RC4][j]=((double)count)/d*lengths[j];
+                       print_result(D_RC4,j,count,d);
                        }
                }
 #endif
-#ifndef NO_DES
+#ifndef OPENSSL_NO_DES
        if (doit[D_CBC_DES])
                {
                for (j=0; j<SIZE_NUM; j++)
@@ -851,14 +1676,10 @@ char **argv;
                        print_message(names[D_CBC_DES],c[D_CBC_DES][j],lengths[j]);
                        Time_F(START);
                        for (count=0,run=1; COND(c[D_CBC_DES][j]); count++)
-                               des_ncbc_encrypt((C_Block *)buf,
-                                       (C_Block *)buf,
-                                       (long)lengths[j],sch,
-                                       (C_Block *)&(iv[0]),DES_ENCRYPT);
+                               DES_ncbc_encrypt(buf,buf,lengths[j],&sch,
+                                                &DES_iv,DES_ENCRYPT);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_CBC_DES],d);
-                       results[D_CBC_DES][j]=((double)count)/d*lengths[j];
+                       print_result(D_CBC_DES,j,count,d);
                        }
                }
 
@@ -869,18 +1690,164 @@ char **argv;
                        print_message(names[D_EDE3_DES],c[D_EDE3_DES][j],lengths[j]);
                        Time_F(START);
                        for (count=0,run=1; COND(c[D_EDE3_DES][j]); count++)
-                               des_ede3_cbc_encrypt((C_Block *)buf,
-                                       (C_Block *)buf,
-                                       (long)lengths[j],sch,sch2,sch3,
-                                       (C_Block *)&(iv[0]),DES_ENCRYPT);
+                               DES_ede3_cbc_encrypt(buf,buf,lengths[j],
+                                                    &sch,&sch2,&sch3,
+                                                    &DES_iv,DES_ENCRYPT);
+                       d=Time_F(STOP);
+                       print_result(D_EDE3_DES,j,count,d);
+                       }
+               }
+#endif
+#ifndef OPENSSL_NO_AES
+       if (doit[D_CBC_128_AES])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_CBC_128_AES],c[D_CBC_128_AES][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_CBC_128_AES][j]); count++)
+                               AES_cbc_encrypt(buf,buf,
+                                       (unsigned long)lengths[j],&aes_ks1,
+                                       iv,AES_ENCRYPT);
+                       d=Time_F(STOP);
+                       print_result(D_CBC_128_AES,j,count,d);
+                       }
+               }
+       if (doit[D_CBC_192_AES])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_CBC_192_AES],c[D_CBC_192_AES][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_CBC_192_AES][j]); count++)
+                               AES_cbc_encrypt(buf,buf,
+                                       (unsigned long)lengths[j],&aes_ks2,
+                                       iv,AES_ENCRYPT);
+                       d=Time_F(STOP);
+                       print_result(D_CBC_192_AES,j,count,d);
+                       }
+               }
+       if (doit[D_CBC_256_AES])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_CBC_256_AES],c[D_CBC_256_AES][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_CBC_256_AES][j]); count++)
+                               AES_cbc_encrypt(buf,buf,
+                                       (unsigned long)lengths[j],&aes_ks3,
+                                       iv,AES_ENCRYPT);
+                       d=Time_F(STOP);
+                       print_result(D_CBC_256_AES,j,count,d);
+                       }
+               }
+
+       if (doit[D_IGE_128_AES])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_IGE_128_AES],c[D_IGE_128_AES][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_IGE_128_AES][j]); count++)
+                               AES_ige_encrypt(buf,buf2,
+                                       (unsigned long)lengths[j],&aes_ks1,
+                                       iv,AES_ENCRYPT);
+                       d=Time_F(STOP);
+                       print_result(D_IGE_128_AES,j,count,d);
+                       }
+               }
+       if (doit[D_IGE_192_AES])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_IGE_192_AES],c[D_IGE_192_AES][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_IGE_192_AES][j]); count++)
+                               AES_ige_encrypt(buf,buf2,
+                                       (unsigned long)lengths[j],&aes_ks2,
+                                       iv,AES_ENCRYPT);
+                       d=Time_F(STOP);
+                       print_result(D_IGE_192_AES,j,count,d);
+                       }
+               }
+       if (doit[D_IGE_256_AES])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_IGE_256_AES],c[D_IGE_256_AES][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_IGE_256_AES][j]); count++)
+                               AES_ige_encrypt(buf,buf2,
+                                       (unsigned long)lengths[j],&aes_ks3,
+                                       iv,AES_ENCRYPT);
+                       d=Time_F(STOP);
+                       print_result(D_IGE_256_AES,j,count,d);
+                       }
+               }
+       if (doit[D_GHASH])
+               {
+               GCM128_CONTEXT *ctx = CRYPTO_gcm128_new(&aes_ks1,(block128_f)AES_encrypt);
+               CRYPTO_gcm128_setiv (ctx,(unsigned char *)"0123456789ab",12);
+
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_GHASH],c[D_GHASH][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_GHASH][j]); count++)
+                               CRYPTO_gcm128_aad(ctx,buf,lengths[j]);
+                       d=Time_F(STOP);
+                       print_result(D_GHASH,j,count,d);
+                       }
+               CRYPTO_gcm128_release(ctx);
+               }
+
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+       if (doit[D_CBC_128_CML])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_CBC_128_CML],c[D_CBC_128_CML][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_CBC_128_CML][j]); count++)
+                               Camellia_cbc_encrypt(buf,buf,
+                                       (unsigned long)lengths[j],&camellia_ks1,
+                                       iv,CAMELLIA_ENCRYPT);
+                       d=Time_F(STOP);
+                       print_result(D_CBC_128_CML,j,count,d);
+                       }
+               }
+       if (doit[D_CBC_192_CML])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_CBC_192_CML],c[D_CBC_192_CML][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_CBC_192_CML][j]); count++)
+                               Camellia_cbc_encrypt(buf,buf,
+                                       (unsigned long)lengths[j],&camellia_ks2,
+                                       iv,CAMELLIA_ENCRYPT);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_EDE3_DES],d);
-                       results[D_EDE3_DES][j]=((double)count)/d*lengths[j];
+                       print_result(D_CBC_192_CML,j,count,d);
                        }
                }
+       if (doit[D_CBC_256_CML])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_CBC_256_CML],c[D_CBC_256_CML][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_CBC_256_CML][j]); count++)
+                               Camellia_cbc_encrypt(buf,buf,
+                                       (unsigned long)lengths[j],&camellia_ks3,
+                                       iv,CAMELLIA_ENCRYPT);
+                       d=Time_F(STOP);
+                       print_result(D_CBC_256_CML,j,count,d);
+                       }
+               }
+
 #endif
-#ifndef NO_IDEA
+#ifndef OPENSSL_NO_IDEA
        if (doit[D_CBC_IDEA])
                {
                for (j=0; j<SIZE_NUM; j++)
@@ -890,15 +1857,28 @@ char **argv;
                        for (count=0,run=1; COND(c[D_CBC_IDEA][j]); count++)
                                idea_cbc_encrypt(buf,buf,
                                        (unsigned long)lengths[j],&idea_ks,
-                                       (unsigned char *)&(iv[0]),IDEA_ENCRYPT);
+                                       iv,IDEA_ENCRYPT);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_CBC_IDEA],d);
-                       results[D_CBC_IDEA][j]=((double)count)/d*lengths[j];
+                       print_result(D_CBC_IDEA,j,count,d);
                        }
                }
 #endif
-#ifndef NO_RC2
+#ifndef OPENSSL_NO_SEED
+       if (doit[D_CBC_SEED])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_CBC_SEED],c[D_CBC_SEED][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_CBC_SEED][j]); count++)
+                               SEED_cbc_encrypt(buf,buf,
+                                       (unsigned long)lengths[j],&seed_ks,iv,1);
+                       d=Time_F(STOP);
+                       print_result(D_CBC_SEED,j,count,d);
+                       }
+               }
+#endif
+#ifndef OPENSSL_NO_RC2
        if (doit[D_CBC_RC2])
                {
                for (j=0; j<SIZE_NUM; j++)
@@ -908,15 +1888,13 @@ char **argv;
                        for (count=0,run=1; COND(c[D_CBC_RC2][j]); count++)
                                RC2_cbc_encrypt(buf,buf,
                                        (unsigned long)lengths[j],&rc2_ks,
-                                       (unsigned char *)&(iv[0]),RC2_ENCRYPT);
+                                       iv,RC2_ENCRYPT);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_CBC_RC2],d);
-                       results[D_CBC_RC2][j]=((double)count)/d*lengths[j];
+                       print_result(D_CBC_RC2,j,count,d);
                        }
                }
 #endif
-#ifndef NO_RC5
+#ifndef OPENSSL_NO_RC5
        if (doit[D_CBC_RC5])
                {
                for (j=0; j<SIZE_NUM; j++)
@@ -926,15 +1904,13 @@ char **argv;
                        for (count=0,run=1; COND(c[D_CBC_RC5][j]); count++)
                                RC5_32_cbc_encrypt(buf,buf,
                                        (unsigned long)lengths[j],&rc5_ks,
-                                       (unsigned char *)&(iv[0]),RC5_ENCRYPT);
+                                       iv,RC5_ENCRYPT);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_CBC_RC5],d);
-                       results[D_CBC_RC5][j]=((double)count)/d*lengths[j];
+                       print_result(D_CBC_RC5,j,count,d);
                        }
                }
 #endif
-#ifndef NO_BLOWFISH
+#ifndef OPENSSL_NO_BF
        if (doit[D_CBC_BF])
                {
                for (j=0; j<SIZE_NUM; j++)
@@ -944,15 +1920,13 @@ char **argv;
                        for (count=0,run=1; COND(c[D_CBC_BF][j]); count++)
                                BF_cbc_encrypt(buf,buf,
                                        (unsigned long)lengths[j],&bf_ks,
-                                       (unsigned char *)&(iv[0]),BF_ENCRYPT);
+                                       iv,BF_ENCRYPT);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_CBC_BF],d);
-                       results[D_CBC_BF][j]=((double)count)/d*lengths[j];
+                       print_result(D_CBC_BF,j,count,d);
                        }
                }
 #endif
-#ifndef NO_CAST
+#ifndef OPENSSL_NO_CAST
        if (doit[D_CBC_CAST])
                {
                for (j=0; j<SIZE_NUM; j++)
@@ -962,66 +1936,140 @@ char **argv;
                        for (count=0,run=1; COND(c[D_CBC_CAST][j]); count++)
                                CAST_cbc_encrypt(buf,buf,
                                        (unsigned long)lengths[j],&cast_ks,
-                                       (unsigned char *)&(iv[0]),CAST_ENCRYPT);
+                                       iv,CAST_ENCRYPT);
                        d=Time_F(STOP);
-                       BIO_printf(bio_err,"%ld %s's in %.2fs\n",
-                               count,names[D_CBC_CAST],d);
-                       results[D_CBC_CAST][j]=((double)count)/d*lengths[j];
+                       print_result(D_CBC_CAST,j,count,d);
                        }
                }
 #endif
 
-       RAND_bytes(buf,30);
-#ifndef NO_RSA
+       if (doit[D_EVP])
+               {
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       if (evp_cipher)
+                               {
+                               EVP_CIPHER_CTX ctx;
+                               int outl;
+
+                               names[D_EVP]=OBJ_nid2ln(evp_cipher->nid);
+                               /* -O3 -fschedule-insns messes up an
+                                * optimization here!  names[D_EVP]
+                                * somehow becomes NULL */
+                               print_message(names[D_EVP],save_count,
+                                       lengths[j]);
+
+                               EVP_CIPHER_CTX_init(&ctx);
+                               if(decrypt)
+                                       EVP_DecryptInit_ex(&ctx,evp_cipher,NULL,key16,iv);
+                               else
+                                       EVP_EncryptInit_ex(&ctx,evp_cipher,NULL,key16,iv);
+                               EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+                               Time_F(START);
+                               if(decrypt)
+                                       for (count=0,run=1; COND(save_count*4*lengths[0]/lengths[j]); count++)
+                                               EVP_DecryptUpdate(&ctx,buf,&outl,buf,lengths[j]);
+                               else
+                                       for (count=0,run=1; COND(save_count*4*lengths[0]/lengths[j]); count++)
+                                               EVP_EncryptUpdate(&ctx,buf,&outl,buf,lengths[j]);
+                               if(decrypt)
+                                       EVP_DecryptFinal_ex(&ctx,buf,&outl);
+                               else
+                                       EVP_EncryptFinal_ex(&ctx,buf,&outl);
+                               d=Time_F(STOP);
+                               EVP_CIPHER_CTX_cleanup(&ctx);
+                               }
+                       if (evp_md)
+                               {
+                               names[D_EVP]=OBJ_nid2ln(evp_md->type);
+                               print_message(names[D_EVP],save_count,
+                                       lengths[j]);
+
+                               Time_F(START);
+                               for (count=0,run=1; COND(save_count*4*lengths[0]/lengths[j]); count++)
+                                       EVP_Digest(buf,lengths[j],&(md[0]),NULL,evp_md,NULL);
+
+                               d=Time_F(STOP);
+                               }
+                       print_result(D_EVP,j,count,d);
+                       }
+               }
+
+       RAND_pseudo_bytes(buf,36);
+#ifndef OPENSSL_NO_RSA
        for (j=0; j<RSA_NUM; j++)
                {
+               int ret;
                if (!rsa_doit[j]) continue;
-               rsa_num=RSA_private_encrypt(30,buf,buf2,rsa_key[j],
-                       RSA_PKCS1_PADDING);
-               pkey_print_message("private","rsa",rsa_c[j][0],rsa_bits[j],
-                       RSA_SECONDS);
-/*             RSA_blinding_on(rsa_key[j],NULL); */
-               Time_F(START);
-               for (count=0,run=1; COND(rsa_c[j][0]); count++)
+               ret=RSA_sign(NID_md5_sha1, buf,36, buf2, &rsa_num, rsa_key[j]);
+               if (ret == 0)
+                       {
+                       BIO_printf(bio_err,"RSA sign failure.  No RSA sign will be done.\n");
+                       ERR_print_errors(bio_err);
+                       rsa_count=1;
+                       }
+               else
                        {
-                       rsa_num=RSA_private_encrypt(30,buf,buf2,rsa_key[j],
-                               RSA_PKCS1_PADDING);
-                       if (rsa_num <= 0)
+                       pkey_print_message("private","rsa",
+                               rsa_c[j][0],rsa_bits[j],
+                               RSA_SECONDS);
+/*                     RSA_blinding_on(rsa_key[j],NULL); */
+                       Time_F(START);
+                       for (count=0,run=1; COND(rsa_c[j][0]); count++)
                                {
-                               BIO_printf(bio_err,"RSA private encrypt failure\n");
-                               ERR_print_errors(bio_err);
-                               count=1;
-                               break;
+                               ret=RSA_sign(NID_md5_sha1, buf,36, buf2,
+                                       &rsa_num, rsa_key[j]);
+                               if (ret == 0)
+                                       {
+                                       BIO_printf(bio_err,
+                                               "RSA sign failure\n");
+                                       ERR_print_errors(bio_err);
+                                       count=1;
+                                       break;
+                                       }
                                }
+                       d=Time_F(STOP);
+                       BIO_printf(bio_err,mr ? "+R1:%ld:%d:%.2f\n"
+                                  : "%ld %d bit private RSA's in %.2fs\n",
+                                  count,rsa_bits[j],d);
+                       rsa_results[j][0]=d/(double)count;
+                       rsa_count=count;
                        }
-               d=Time_F(STOP);
-               BIO_printf(bio_err,"%ld %d bit private RSA's in %.2fs\n",
-                       count,rsa_bits[j],d);
-               rsa_results[j][0]=d/(double)count;
-               rsa_count=count;
 
 #if 1
-               rsa_num2=RSA_public_decrypt(rsa_num,buf2,buf,rsa_key[j],
-                       RSA_PKCS1_PADDING);
-               pkey_print_message("public","rsa",rsa_c[j][1],rsa_bits[j],
-                       RSA_SECONDS);
-               Time_F(START);
-               for (count=0,run=1; COND(rsa_c[j][1]); count++)
+               ret=RSA_verify(NID_md5_sha1, buf,36, buf2, rsa_num, rsa_key[j]);
+               if (ret <= 0)
+                       {
+                       BIO_printf(bio_err,"RSA verify failure.  No RSA verify will be done.\n");
+                       ERR_print_errors(bio_err);
+                       rsa_doit[j] = 0;
+                       }
+               else
                        {
-                       rsa_num2=RSA_public_decrypt(rsa_num,buf2,buf,rsa_key[j],
-                               RSA_PKCS1_PADDING);
-                       if (rsa_num2 <= 0)
+                       pkey_print_message("public","rsa",
+                               rsa_c[j][1],rsa_bits[j],
+                               RSA_SECONDS);
+                       Time_F(START);
+                       for (count=0,run=1; COND(rsa_c[j][1]); count++)
                                {
-                               BIO_printf(bio_err,"RSA public encrypt failure\n");
-                               ERR_print_errors(bio_err);
-                               count=1;
-                               break;
+                               ret=RSA_verify(NID_md5_sha1, buf,36, buf2,
+                                       rsa_num, rsa_key[j]);
+                               if (ret <= 0)
+                                       {
+                                       BIO_printf(bio_err,
+                                               "RSA verify failure\n");
+                                       ERR_print_errors(bio_err);
+                                       count=1;
+                                       break;
+                                       }
                                }
+                       d=Time_F(STOP);
+                       BIO_printf(bio_err,mr ? "+R2:%ld:%d:%.2f\n"
+                                  : "%ld %d bit public RSA's in %.2fs\n",
+                                  count,rsa_bits[j],d);
+                       rsa_results[j][1]=d/(double)count;
                        }
-               d=Time_F(STOP);
-               BIO_printf(bio_err,"%ld %d bit public RSA's in %.2fs\n",
-                       count,rsa_bits[j],d);
-               rsa_results[j][1]=d/(double)count;
 #endif
 
                if (rsa_count <= 1)
@@ -1033,59 +2081,89 @@ char **argv;
                }
 #endif
 
-       RAND_bytes(buf,20);
-#ifndef NO_DSA
+       RAND_pseudo_bytes(buf,20);
+#ifndef OPENSSL_NO_DSA
+       if (RAND_status() != 1)
+               {
+               RAND_seed(rnd_seed, sizeof rnd_seed);
+               rnd_fake = 1;
+               }
        for (j=0; j<DSA_NUM; j++)
                {
                unsigned int kk;
+               int ret;
 
                if (!dsa_doit[j]) continue;
-               DSA_generate_key(dsa_key[j]);
+/*             DSA_generate_key(dsa_key[j]); */
 /*             DSA_sign_setup(dsa_key[j],NULL); */
-               rsa_num=DSA_sign(EVP_PKEY_DSA,buf,20,buf2,
+               ret=DSA_sign(EVP_PKEY_DSA,buf,20,buf2,
                        &kk,dsa_key[j]);
-               pkey_print_message("sign","dsa",dsa_c[j][0],dsa_bits[j],
-                       DSA_SECONDS);
-               Time_F(START);
-               for (count=0,run=1; COND(dsa_c[j][0]); count++)
+               if (ret == 0)
+                       {
+                       BIO_printf(bio_err,"DSA sign failure.  No DSA sign will be done.\n");
+                       ERR_print_errors(bio_err);
+                       rsa_count=1;
+                       }
+               else
                        {
-                       rsa_num=DSA_sign(EVP_PKEY_DSA,buf,20,buf2,
-                               &kk,dsa_key[j]);
-                       if (rsa_num <= 0)
+                       pkey_print_message("sign","dsa",
+                               dsa_c[j][0],dsa_bits[j],
+                               DSA_SECONDS);
+                       Time_F(START);
+                       for (count=0,run=1; COND(dsa_c[j][0]); count++)
                                {
-                               BIO_printf(bio_err,"DSA sign failure\n");
-                               ERR_print_errors(bio_err);
-                               count=1;
-                               break;
+                               ret=DSA_sign(EVP_PKEY_DSA,buf,20,buf2,
+                                       &kk,dsa_key[j]);
+                               if (ret == 0)
+                                       {
+                                       BIO_printf(bio_err,
+                                               "DSA sign failure\n");
+                                       ERR_print_errors(bio_err);
+                                       count=1;
+                                       break;
+                                       }
                                }
+                       d=Time_F(STOP);
+                       BIO_printf(bio_err,mr ? "+R3:%ld:%d:%.2f\n"
+                                  : "%ld %d bit DSA signs in %.2fs\n",
+                                  count,dsa_bits[j],d);
+                       dsa_results[j][0]=d/(double)count;
+                       rsa_count=count;
                        }
-               d=Time_F(STOP);
-               BIO_printf(bio_err,"%ld %d bit DSA signs in %.2fs\n",
-                       count,dsa_bits[j],d);
-               dsa_results[j][0]=d/(double)count;
-               rsa_count=count;
 
-               rsa_num2=DSA_verify(EVP_PKEY_DSA,buf,20,buf2,
+               ret=DSA_verify(EVP_PKEY_DSA,buf,20,buf2,
                        kk,dsa_key[j]);
-               pkey_print_message("verify","dsa",dsa_c[j][1],dsa_bits[j],
-                       DSA_SECONDS);
-               Time_F(START);
-               for (count=0,run=1; COND(dsa_c[j][1]); count++)
+               if (ret <= 0)
+                       {
+                       BIO_printf(bio_err,"DSA verify failure.  No DSA verify will be done.\n");
+                       ERR_print_errors(bio_err);
+                       dsa_doit[j] = 0;
+                       }
+               else
                        {
-                       rsa_num2=DSA_verify(EVP_PKEY_DSA,buf,20,buf2,
-                               kk,dsa_key[j]);
-                       if (rsa_num2 <= 0)
+                       pkey_print_message("verify","dsa",
+                               dsa_c[j][1],dsa_bits[j],
+                               DSA_SECONDS);
+                       Time_F(START);
+                       for (count=0,run=1; COND(dsa_c[j][1]); count++)
                                {
-                               BIO_printf(bio_err,"DSA verify failure\n");
-                               ERR_print_errors(bio_err);
-                               count=1;
-                               break;
+                               ret=DSA_verify(EVP_PKEY_DSA,buf,20,buf2,
+                                       kk,dsa_key[j]);
+                               if (ret <= 0)
+                                       {
+                                       BIO_printf(bio_err,
+                                               "DSA verify failure\n");
+                                       ERR_print_errors(bio_err);
+                                       count=1;
+                                       break;
+                                       }
                                }
+                       d=Time_F(STOP);
+                       BIO_printf(bio_err,mr ? "+R4:%ld:%d:%.2f\n"
+                                  : "%ld %d bit DSA verify in %.2fs\n",
+                                  count,dsa_bits[j],d);
+                       dsa_results[j][1]=d/(double)count;
                        }
-               d=Time_F(STOP);
-               BIO_printf(bio_err,"%ld %d bit DSA verify in %.2fs\n",
-                       count,dsa_bits[j],d);
-               dsa_results[j][1]=d/(double)count;
 
                if (rsa_count <= 1)
                        {
@@ -1094,134 +2172,667 @@ char **argv;
                                dsa_doit[j]=0;
                        }
                }
+       if (rnd_fake) RAND_cleanup();
+#endif
+
+#ifndef OPENSSL_NO_ECDSA
+       if (RAND_status() != 1) 
+               {
+               RAND_seed(rnd_seed, sizeof rnd_seed);
+               rnd_fake = 1;
+               }
+       for (j=0; j<EC_NUM; j++) 
+               {
+               int ret;
+
+               if (!ecdsa_doit[j]) continue; /* Ignore Curve */ 
+               ecdsa[j] = EC_KEY_new_by_curve_name(test_curves[j]);
+               if (ecdsa[j] == NULL) 
+                       {
+                       BIO_printf(bio_err,"ECDSA failure.\n");
+                       ERR_print_errors(bio_err);
+                       rsa_count=1;
+                       } 
+               else 
+                       {
+#if 1
+                       EC_KEY_precompute_mult(ecdsa[j], NULL);
+#endif
+                       /* Perform ECDSA signature test */
+                       EC_KEY_generate_key(ecdsa[j]);
+                       ret = ECDSA_sign(0, buf, 20, ecdsasig, 
+                               &ecdsasiglen, ecdsa[j]);
+                       if (ret == 0) 
+                               {
+                               BIO_printf(bio_err,"ECDSA sign failure.  No ECDSA sign will be done.\n");
+                               ERR_print_errors(bio_err);
+                               rsa_count=1;
+                               } 
+                       else 
+                               {
+                               pkey_print_message("sign","ecdsa",
+                                       ecdsa_c[j][0], 
+                                       test_curves_bits[j],
+                                       ECDSA_SECONDS);
+
+                               Time_F(START);
+                               for (count=0,run=1; COND(ecdsa_c[j][0]);
+                                       count++) 
+                                       {
+                                       ret=ECDSA_sign(0, buf, 20, 
+                                               ecdsasig, &ecdsasiglen,
+                                               ecdsa[j]);
+                                       if (ret == 0) 
+                                               {
+                                               BIO_printf(bio_err, "ECDSA sign failure\n");
+                                               ERR_print_errors(bio_err);
+                                               count=1;
+                                               break;
+                                               }
+                                       }
+                               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[j], d);
+                               ecdsa_results[j][0]=d/(double)count;
+                               rsa_count=count;
+                               }
+
+                       /* Perform ECDSA verification test */
+                       ret=ECDSA_verify(0, buf, 20, ecdsasig, 
+                               ecdsasiglen, ecdsa[j]);
+                       if (ret != 1) 
+                               {
+                               BIO_printf(bio_err,"ECDSA verify failure.  No ECDSA verify will be done.\n");
+                               ERR_print_errors(bio_err);
+                               ecdsa_doit[j] = 0;
+                               } 
+                       else 
+                               {
+                               pkey_print_message("verify","ecdsa",
+                               ecdsa_c[j][1],
+                               test_curves_bits[j],
+                               ECDSA_SECONDS);
+                               Time_F(START);
+                               for (count=0,run=1; COND(ecdsa_c[j][1]); count++) 
+                                       {
+                                       ret=ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[j]);
+                                       if (ret != 1) 
+                                               {
+                                               BIO_printf(bio_err, "ECDSA verify failure\n");
+                                               ERR_print_errors(bio_err);
+                                               count=1;
+                                               break;
+                                               }
+                                       }
+                               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[j], d);
+                               ecdsa_results[j][1]=d/(double)count;
+                               }
+
+                       if (rsa_count <= 1) 
+                               {
+                               /* if longer than 10s, don't do any more */
+                               for (j++; j<EC_NUM; j++)
+                               ecdsa_doit[j]=0;
+                               }
+                       }
+               }
+       if (rnd_fake) RAND_cleanup();
 #endif
 
-       fprintf(stdout,"%s\n",SSLeay_version(SSLEAY_VERSION));
+#ifndef OPENSSL_NO_ECDH
+       if (RAND_status() != 1)
+               {
+               RAND_seed(rnd_seed, sizeof rnd_seed);
+               rnd_fake = 1;
+               }
+       for (j=0; j<EC_NUM; j++)
+               {
+               if (!ecdh_doit[j]) continue;
+               ecdh_a[j] = EC_KEY_new_by_curve_name(test_curves[j]);
+               ecdh_b[j] = EC_KEY_new_by_curve_name(test_curves[j]);
+               if ((ecdh_a[j] == NULL) || (ecdh_b[j] == NULL))
+                       {
+                       BIO_printf(bio_err,"ECDH failure.\n");
+                       ERR_print_errors(bio_err);
+                       rsa_count=1;
+                       }
+               else
+                       {
+                       /* generate two ECDH key pairs */
+                       if (!EC_KEY_generate_key(ecdh_a[j]) ||
+                               !EC_KEY_generate_key(ecdh_b[j]))
+                               {
+                               BIO_printf(bio_err,"ECDH key generation failure.\n");
+                               ERR_print_errors(bio_err);
+                               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, outlen;
+                               void *(*kdf)(const void *in, size_t inlen, void *out, size_t *xoutlen);
+                               field_size = EC_GROUP_get_degree(EC_KEY_get0_group(ecdh_a[j]));
+                               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(secret_a, outlen,
+                                       EC_KEY_get0_public_key(ecdh_b[j]),
+                                       ecdh_a[j], kdf);
+                               secret_size_b = ECDH_compute_key(secret_b, outlen,
+                                       EC_KEY_get0_public_key(ecdh_a[j]),
+                                       ecdh_b[j], 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 (secret_a[secret_idx] != 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;            
+                                       }
+
+                               pkey_print_message("","ecdh",
+                               ecdh_c[j][0], 
+                               test_curves_bits[j],
+                               ECDH_SECONDS);
+                               Time_F(START);
+                               for (count=0,run=1; COND(ecdh_c[j][0]); count++)
+                                       {
+                                       ECDH_compute_key(secret_a, outlen,
+                                       EC_KEY_get0_public_key(ecdh_b[j]),
+                                       ecdh_a[j], kdf);
+                                       }
+                               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[j], d);
+                               ecdh_results[j][0]=d/(double)count;
+                               rsa_count=count;
+                               }
+                       }
+
+
+               if (rsa_count <= 1)
+                       {
+                       /* if longer than 10s, don't do any more */
+                       for (j++; j<EC_NUM; j++)
+                       ecdh_doit[j]=0;
+                       }
+               }
+       if (rnd_fake) RAND_cleanup();
+#endif
+#ifndef NO_FORK
+show_res:
+#endif
+       if(!mr)
+               {
+               fprintf(stdout,"%s\n",SSLeay_version(SSLEAY_VERSION));
         fprintf(stdout,"%s\n",SSLeay_version(SSLEAY_BUILT_ON));
-       printf("options:");
-       printf("%s ",BN_options());
-#ifndef NO_MD2
-       printf("%s ",MD2_options());
+               printf("options:");
+               printf("%s ",BN_options());
+#ifndef OPENSSL_NO_MD2
+               printf("%s ",MD2_options());
+#endif
+#ifndef OPENSSL_NO_RC4
+               printf("%s ",RC4_options());
 #endif
-#ifndef NO_RC4
-       printf("%s ",RC4_options());
+#ifndef OPENSSL_NO_DES
+               printf("%s ",DES_options());
 #endif
-#ifndef NO_DES
-       printf("%s ",des_options());
+#ifndef OPENSSL_NO_AES
+               printf("%s ",AES_options());
 #endif
-#ifndef NO_IDEA
-       printf("%s ",idea_options());
+#ifndef OPENSSL_NO_IDEA
+               printf("%s ",idea_options());
 #endif
-#ifndef NO_BLOWFISH
-       printf("%s ",BF_options());
+#ifndef OPENSSL_NO_BF
+               printf("%s ",BF_options());
 #endif
-       fprintf(stdout,"\n%s\n",SSLeay_version(SSLEAY_CFLAGS));
+               fprintf(stdout,"\n%s\n",SSLeay_version(SSLEAY_CFLAGS));
+               }
 
        if (pr_header)
                {
-               fprintf(stdout,"The 'numbers' are in 1000s of bytes per second processed.\n"); 
-               fprintf(stdout,"type        ");
+               if(mr)
+                       fprintf(stdout,"+H");
+               else
+                       {
+                       fprintf(stdout,"The 'numbers' are in 1000s of bytes per second processed.\n"); 
+                       fprintf(stdout,"type        ");
+                       }
                for (j=0;  j<SIZE_NUM; j++)
-                       fprintf(stdout,"%7d bytes",lengths[j]);
+                       fprintf(stdout,mr ? ":%d" : "%7d bytes",lengths[j]);
                fprintf(stdout,"\n");
                }
 
        for (k=0; k<ALGOR_NUM; k++)
                {
                if (!doit[k]) continue;
-               fprintf(stdout,"%-13s",names[k]);
+               if(mr)
+                       fprintf(stdout,"+F:%d:%s",k,names[k]);
+               else
+                       fprintf(stdout,"%-13s",names[k]);
                for (j=0; j<SIZE_NUM; j++)
                        {
-                       if (results[k][j] > 10000)
+                       if (results[k][j] > 10000 && !mr)
                                fprintf(stdout," %11.2fk",results[k][j]/1e3);
                        else
-                               fprintf(stdout," %11.2f ",results[k][j]);
+                               fprintf(stdout,mr ? ":%.2f" : " %11.2f ",results[k][j]);
                        }
                fprintf(stdout,"\n");
                }
-#ifndef NO_RSA
+#ifndef OPENSSL_NO_RSA
        j=1;
        for (k=0; k<RSA_NUM; k++)
                {
                if (!rsa_doit[k]) continue;
-               if (j)
+               if (j && !mr)
                        {
                        printf("%18ssign    verify    sign/s verify/s\n"," ");
                        j=0;
                        }
-               fprintf(stdout,"rsa %4d bits %8.4fs %8.4fs %8.1f %8.1f",
-                       rsa_bits[k],rsa_results[k][0],rsa_results[k][1],
-                       1.0/rsa_results[k][0],1.0/rsa_results[k][1]);
-               fprintf(stdout,"\n");
+               if(mr)
+                       fprintf(stdout,"+F2:%u:%u:%f:%f\n",
+                               k,rsa_bits[k],rsa_results[k][0],
+                               rsa_results[k][1]);
+               else
+                       fprintf(stdout,"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]);
                }
 #endif
-#ifndef NO_DSA
+#ifndef OPENSSL_NO_DSA
        j=1;
        for (k=0; k<DSA_NUM; k++)
                {
                if (!dsa_doit[k]) continue;
-               if (j)  {
+               if (j && !mr)
+                       {
                        printf("%18ssign    verify    sign/s verify/s\n"," ");
                        j=0;
                        }
-               fprintf(stdout,"dsa %4d bits %8.4fs %8.4fs %8.1f %8.1f",
-                       dsa_bits[k],dsa_results[k][0],dsa_results[k][1],
-                       1.0/dsa_results[k][0],1.0/dsa_results[k][1]);
-               fprintf(stdout,"\n");
+               if(mr)
+                       fprintf(stdout,"+F3:%u:%u:%f:%f\n",
+                               k,dsa_bits[k],dsa_results[k][0],dsa_results[k][1]);
+               else
+                       fprintf(stdout,"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]);
+               }
+#endif
+#ifndef OPENSSL_NO_ECDSA
+       j=1;
+       for (k=0; k<EC_NUM; k++)
+               {
+               if (!ecdsa_doit[k]) continue;
+               if (j && !mr)
+                       {
+                       printf("%30ssign    verify    sign/s verify/s\n"," ");
+                       j=0;
+                       }
+
+               if (mr)
+                       fprintf(stdout,"+F4:%u:%u:%f:%f\n", 
+                               k, test_curves_bits[k],
+                               ecdsa_results[k][0],ecdsa_results[k][1]);
+               else
+                       fprintf(stdout,
+                               "%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]);
+               }
+#endif
+
+
+#ifndef OPENSSL_NO_ECDH
+       j=1;
+       for (k=0; k<EC_NUM; k++)
+               {
+               if (!ecdh_doit[k]) continue;
+               if (j && !mr)
+                       {
+                       printf("%30sop      op/s\n"," ");
+                       j=0;
+                       }
+               if (mr)
+                       fprintf(stdout,"+F5:%u:%u:%f:%f\n",
+                               k, test_curves_bits[k],
+                               ecdh_results[k][0], 1.0/ecdh_results[k][0]);
+
+               else
+                       fprintf(stdout,"%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]);
                }
 #endif
-       ret=0;
+
+       mret=0;
+
 end:
-       if (buf != NULL) Free(buf);
-       if (buf2 != NULL) Free(buf2);
-#ifndef NO_RSA
+       ERR_print_errors(bio_err);
+       if (buf != NULL) OPENSSL_free(buf);
+       if (buf2 != NULL) OPENSSL_free(buf2);
+#ifndef OPENSSL_NO_RSA
        for (i=0; i<RSA_NUM; i++)
                if (rsa_key[i] != NULL)
                        RSA_free(rsa_key[i]);
 #endif
-#ifndef NO_DSA
+#ifndef OPENSSL_NO_DSA
        for (i=0; i<DSA_NUM; i++)
                if (dsa_key[i] != NULL)
                        DSA_free(dsa_key[i]);
 #endif
-       EXIT(ret);
+
+#ifndef OPENSSL_NO_ECDSA
+       for (i=0; i<EC_NUM; i++)
+               if (ecdsa[i] != NULL)
+                       EC_KEY_free(ecdsa[i]);
+#endif
+#ifndef OPENSSL_NO_ECDH
+       for (i=0; i<EC_NUM; i++)
+       {
+               if (ecdh_a[i] != NULL)
+                       EC_KEY_free(ecdh_a[i]);
+               if (ecdh_b[i] != NULL)
+                       EC_KEY_free(ecdh_b[i]);
        }
+#endif
 
-static void print_message(s,num,length)
-char *s;
-long num;
-int length;
+       apps_shutdown();
+       OPENSSL_EXIT(mret);
+       }
+
+static void print_message(const char *s, long num, int length)
        {
 #ifdef SIGALRM
-       BIO_printf(bio_err,"Doing %s for %ds on %d size blocks: ",s,SECONDS,length);
-       BIO_flush(bio_err);
+       BIO_printf(bio_err,mr ? "+DT:%s:%d:%d\n"
+                  : "Doing %s for %ds on %d size blocks: ",s,SECONDS,length);
+       (void)BIO_flush(bio_err);
        alarm(SECONDS);
 #else
-       BIO_printf(bio_err,"Doing %s %ld times on %d size blocks: ",s,num,length);
-       BIO_flush(bio_err);
+       BIO_printf(bio_err,mr ? "+DN:%s:%ld:%d\n"
+                  : "Doing %s %ld times on %d size blocks: ",s,num,length);
+       (void)BIO_flush(bio_err);
 #endif
 #ifdef LINT
        num=num;
 #endif
        }
 
-static void pkey_print_message(str,str2,num,bits,tm)
-char *str;
-char *str2;
-long num;
-int bits;
-int tm;
+static void pkey_print_message(const char *str, const char *str2, long num,
+       int bits, int tm)
        {
 #ifdef SIGALRM
-       BIO_printf(bio_err,"Doing %d bit %s %s's for %ds: ",bits,str,str2,tm);
-       BIO_flush(bio_err);
-       alarm(RSA_SECONDS);
+       BIO_printf(bio_err,mr ? "+DTP:%d:%s:%s:%d\n"
+                          : "Doing %d bit %s %s's for %ds: ",bits,str,str2,tm);
+       (void)BIO_flush(bio_err);
+       alarm(tm);
 #else
-       BIO_printf(bio_err,"Doing %ld %d bit %s %s's: ",num,bits,str,str2);
-       BIO_flush(bio_err);
+       BIO_printf(bio_err,mr ? "+DNP:%ld:%d:%s:%s\n"
+                          : "Doing %ld %d bit %s %s's: ",num,bits,str,str2);
+       (void)BIO_flush(bio_err);
 #endif
 #ifdef LINT
        num=num;
 #endif
        }
 
+static void print_result(int alg,int run_no,int count,double time_used)
+       {
+       BIO_printf(bio_err,mr ? "+R:%d:%s:%f\n"
+                  : "%d %s's in %.2fs\n",count,names[alg],time_used);
+       results[alg][run_no]=((double)count)/time_used*lengths[run_no];
+       }
+
+#ifndef NO_FORK
+static char *sstrsep(char **string, const char *delim)
+    {
+    char isdelim[256];
+    char *token = *string;
+
+    if (**string == 0)
+        return NULL;
+
+    memset(isdelim, 0, sizeof isdelim);
+    isdelim[0] = 1;
+
+    while (*delim)
+        {
+        isdelim[(unsigned char)(*delim)] = 1;
+        delim++;
+        }
+
+    while (!isdelim[(unsigned char)(**string)])
+        {
+        (*string)++;
+        }
+
+    if (**string)
+        {
+        **string = 0;
+        (*string)++;
+        }
+
+    return token;
+    }
+
+static int do_multi(int multi)
+       {
+       int n;
+       int fd[2];
+       int *fds;
+       static char sep[]=":";
+
+       fds=malloc(multi*sizeof *fds);
+       for(n=0 ; n < multi ; ++n)
+               {
+               if (pipe(fd) == -1)
+                       {
+                       fprintf(stderr, "pipe failure\n");
+                       exit(1);
+                       }
+               fflush(stdout);
+               fflush(stderr);
+               if(fork())
+                       {
+                       close(fd[1]);
+                       fds[n]=fd[0];
+                       }
+               else
+                       {
+                       close(fd[0]);
+                       close(1);
+                       if (dup(fd[1]) == -1)
+                               {
+                               fprintf(stderr, "dup failed\n");
+                               exit(1);
+                               }
+                       close(fd[1]);
+                       mr=1;
+                       usertime=0;
+                       free(fds);
+                       return 0;
+                       }
+               printf("Forked child %d\n",n);
+               }
+
+       /* for now, assume the pipe is long enough to take all the output */
+       for(n=0 ; n < multi ; ++n)
+               {
+               FILE *f;
+               char buf[1024];
+               char *p;
+
+               f=fdopen(fds[n],"r");
+               while(fgets(buf,sizeof buf,f))
+                       {
+                       p=strchr(buf,'\n');
+                       if(p)
+                               *p='\0';
+                       if(buf[0] != '+')
+                               {
+                               fprintf(stderr,"Don't understand line '%s' from child %d\n",
+                                               buf,n);
+                               continue;
+                               }
+                       printf("Got: %s from %d\n",buf,n);
+                       if(!strncmp(buf,"+F:",3))
+                               {
+                               int alg;
+                               int j;
+
+                               p=buf+3;
+                               alg=atoi(sstrsep(&p,sep));
+                               sstrsep(&p,sep);
+                               for(j=0 ; j < SIZE_NUM ; ++j)
+                                       results[alg][j]+=atof(sstrsep(&p,sep));
+                               }
+                       else if(!strncmp(buf,"+F2:",4))
+                               {
+                               int k;
+                               double d;
+                               
+                               p=buf+4;
+                               k=atoi(sstrsep(&p,sep));
+                               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;
+
+                               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;
+                               }
+                       else if(!strncmp(buf,"+F2:",4))
+                               {
+                               int k;
+                               double d;
+                               
+                               p=buf+4;
+                               k=atoi(sstrsep(&p,sep));
+                               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;
+
+                               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;
+                               }
+#ifndef OPENSSL_NO_DSA
+                       else if(!strncmp(buf,"+F3:",4))
+                               {
+                               int k;
+                               double d;
+                               
+                               p=buf+4;
+                               k=atoi(sstrsep(&p,sep));
+                               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;
+
+                               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;
+                               }
+#endif
+#ifndef OPENSSL_NO_ECDSA
+                       else if(!strncmp(buf,"+F4:",4))
+                               {
+                               int k;
+                               double d;
+                               
+                               p=buf+4;
+                               k=atoi(sstrsep(&p,sep));
+                               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;
+
+                               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 
+
+#ifndef OPENSSL_NO_ECDH
+                       else if(!strncmp(buf,"+F5:",4))
+                               {
+                               int k;
+                               double d;
+                               
+                               p=buf+4;
+                               k=atoi(sstrsep(&p,sep));
+                               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;
+
+                               }
+#endif
+
+                       else if(!strncmp(buf,"+H:",3))
+                               {
+                               }
+                       else
+                               fprintf(stderr,"Unknown type '%s' from child %d\n",buf,n);
+                       }
+
+               fclose(f);
+               }
+       free(fds);
+       return 1;
+       }
+#endif
+#endif