Fix WIN32 build by disabling bn* calls.
[openssl.git] / apps / speed.c
index cf5b8b7001b63b48a8c58603261d073995302337..c99c7863c5f6f613d93a9c6c4e30a11e6c113b4d 100644 (file)
 #ifndef OPENSSL_NO_SPEED
 
 #undef SECONDS
-#define SECONDS                3       
-#define RSA_SECONDS    10
-#define DSA_SECONDS    10
+#define SECONDS                        3       
+#define PRIME_SECONDS  10      
+#define RSA_SECONDS            10
+#define DSA_SECONDS            10
 #define ECDSA_SECONDS   10
 #define ECDH_SECONDS    10
 
@@ -92,9 +93,6 @@
 #include <string.h>
 #include <math.h>
 #include "apps.h"
-#ifdef OPENSSL_NO_STDIO
-#define APPS_WIN16
-#endif
 #include <openssl/crypto.h>
 #include <openssl/rand.h>
 #include <openssl/err.h>
 #include <signal.h>
 #endif
 
-#ifdef _WIN32
+#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
 
 #include <openssl/bn.h>
 #ifndef OPENSSL_NO_ECDH
 #include <openssl/ecdh.h>
 #endif
+#include <openssl/modes.h>
+
+#include "../crypto/bn/bn_lcl.h"
 
-#if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_NETWARE)
-# define NO_FORK 1
-#elif HAVE_FORK
-# undef NO_FORK
+#ifndef HAVE_FORK
+# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || 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 1
+#define NO_FORK
 #endif
 
 #undef BUFSIZE
-#define BUFSIZE        ((long)1024*8+1)
+#define BUFSIZE        (1024*8+1)
+#define MAX_MISALIGNMENT 63
+
 int run=0;
 
 static int mr=0;
@@ -201,16 +216,19 @@ static int usertime=1;
 
 static double Time_F(int s);
 static void print_message(const char *s,long num,int length);
+static void prime_print_message(const char *s, long num);
 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);
+static void prime_print_result(int alg, int count, double time_used);
 #ifndef NO_FORK
 static int do_multi(int multi);
 #endif
 
-#define ALGOR_NUM      29
+#define ALGOR_NUM      30
 #define SIZE_NUM       5
-#define RSA_NUM                4
+#define PRIME_NUM      3
+#define RSA_NUM                7
 #define DSA_NUM                3
 
 #define EC_NUM       16
@@ -223,11 +241,17 @@ static const char *names[ALGOR_NUM]={
   "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"};
+  "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};
+static const char *prime_names[PRIME_NUM]={
+  "prime trial division", "prime trial division retry", "prime coprime" };
+#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
@@ -263,9 +287,12 @@ static SIGRETTYPE sig_done(int sig)
 
 #if defined(_WIN32)
 
-#define SIGALRM
+#if !defined(SIGALRM)
+# define SIGALRM
+#endif
 static unsigned int lapse,schlock;
-static void alarm(unsigned int secs) { lapse = secs*1000; }
+static void alarm_win32(unsigned int secs) { lapse = secs*1000; }
+#define alarm alarm_win32
 
 static DWORD WINAPI sleepy(VOID *arg)
        {
@@ -277,9 +304,11 @@ static DWORD WINAPI sleepy(VOID *arg)
 
 static double Time_F(int s)
        {
+       double ret;
+       static HANDLE thr;
+
        if (s == START)
                {
-               HANDLE  thr;
                schlock = 0;
                thr = CreateThread(NULL,4096,sleepy,NULL,0,NULL);
                if (thr==NULL)
@@ -288,17 +317,25 @@ static double Time_F(int s)
                        BIO_printf(bio_err,"unable to CreateThread (%d)",ret);
                        ExitProcess(ret);
                        }
-               CloseHandle(thr);               /* detach the thread    */
                while (!schlock) Sleep(0);      /* scheduler spinlock   */
+               ret = app_tminterval(s,usertime);
+               }
+       else
+               {
+               ret = app_tminterval(s,usertime);
+               if (run) TerminateThread(thr,0);
+               CloseHandle(thr);
                }
 
-       return app_tminterval(s,usertime);
+       return ret;
        }
 #else
 
 static double Time_F(int s)
        {
-       return app_tminterval(s,usertime);
+       double ret = app_tminterval(s,usertime);
+       if (s == STOP) alarm(0);
+       return ret;
        }
 #endif
 
@@ -319,14 +356,13 @@ static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
        }
 #endif /* OPENSSL_NO_ECDH */
 
+static void multiblock_speed(const EVP_CIPHER *evp_cipher);
 
 int MAIN(int, char **);
 
 int MAIN(int argc, char **argv)
        {
-#ifndef OPENSSL_NO_ENGINE
-       ENGINE *e = NULL;
-#endif
+       unsigned char *buf_malloc=NULL, *buf2_malloc=NULL;
        unsigned char *buf=NULL,*buf2=NULL;
        int mret=1;
        long count=0,save_count=0;
@@ -420,7 +456,6 @@ int MAIN(int argc, char **argv)
        unsigned char DES_iv[8];
        unsigned char iv[2*MAX_BLOCK_SIZE/8];
 #ifndef OPENSSL_NO_DES
-       DES_cblock *buf_as_des_cblock = NULL;
        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};
@@ -463,15 +498,26 @@ int MAIN(int argc, char **argv)
 #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];
+
+#define D_PRIME_TRIAL_DIVISION                 0
+#define D_PRIME_TRIAL_DIVISION_RETRY   1
+#define D_PRIME_COPRIME                                        2
+#ifndef OPENSSL_SYS_WIN32
+       long prime_c[PRIME_NUM];
+#endif
 #define        R_DSA_512       0
 #define        R_DSA_1024      1
 #define        R_DSA_2048      2
 #define        R_RSA_512       0
 #define        R_RSA_1024      1
 #define        R_RSA_2048      2
-#define        R_RSA_4096      3
+#define        R_RSA_3072      3
+#define        R_RSA_4096      4
+#define        R_RSA_7680      5
+#define        R_RSA_15360     6
 
 #define R_EC_P160    0
 #define R_EC_P192    1 
@@ -493,12 +539,14 @@ int MAIN(int argc, char **argv)
 #ifndef OPENSSL_NO_RSA
        RSA *rsa_key[RSA_NUM];
        long rsa_c[RSA_NUM][2];
-       static unsigned int rsa_bits[RSA_NUM]={512,1024,2048,4096};
+       static unsigned int rsa_bits[RSA_NUM]={512,1024,2048,3072,4096,7680,15360};
        static unsigned char *rsa_data[RSA_NUM]=
-               {test512,test1024,test2048,test4096};
+               {test512,test1024,test2048,test3072,test4096,test7680,test15360};
        static int rsa_data_length[RSA_NUM]={
                sizeof(test512),sizeof(test1024),
-               sizeof(test2048),sizeof(test4096)};
+               sizeof(test2048),sizeof(test3072),
+               sizeof(test4096),sizeof(test7680),
+               sizeof(test15360)};
 #endif
 #ifndef OPENSSL_NO_DSA
        DSA *dsa_key[DSA_NUM];
@@ -578,6 +626,7 @@ int MAIN(int argc, char **argv)
        long ecdh_c[EC_NUM][2];
 #endif
 
+       int prime_doit[PRIME_NUM];
        int rsa_doit[RSA_NUM];
        int dsa_doit[DSA_NUM];
 #ifndef OPENSSL_NO_ECDSA
@@ -594,6 +643,8 @@ int MAIN(int argc, char **argv)
 #ifndef NO_FORK
        int multi=0;
 #endif
+       int multiblock=0;
+       int misalign=MAX_MISALIGNMENT+1;
 
 #ifndef TIMES
        usertime=-1;
@@ -629,20 +680,21 @@ int MAIN(int argc, char **argv)
                rsa_key[i]=NULL;
 #endif
 
-       if ((buf=(unsigned char *)OPENSSL_malloc((int)BUFSIZE)) == NULL)
+       if ((buf_malloc=(unsigned char *)OPENSSL_malloc(BUFSIZE+misalign)) == NULL)
                {
                BIO_printf(bio_err,"out of memory\n");
                goto end;
                }
-#ifndef OPENSSL_NO_DES
-       buf_as_des_cblock = (DES_cblock *)buf;
-#endif
-       if ((buf2=(unsigned char *)OPENSSL_malloc((int)BUFSIZE)) == NULL)
+       if ((buf2_malloc=(unsigned char *)OPENSSL_malloc(BUFSIZE+misalign)) == NULL)
                {
                BIO_printf(bio_err,"out of memory\n");
                goto end;
                }
 
+       misalign = 0;   /* set later and buf/buf2 are adjusted accordingly */
+       buf=buf_malloc;
+       buf2=buf2_malloc;
+
        memset(c,0,sizeof(c));
        memset(DES_iv,0,sizeof(DES_iv));
        memset(iv,0,sizeof(iv));
@@ -661,6 +713,8 @@ int MAIN(int argc, char **argv)
        for (i=0; i<EC_NUM; i++)
                ecdh_doit[i]=0;
 #endif
+       for (i=0; i<PRIME_NUM; i++)
+               prime_doit[i]=0;
 
        
        j=0;
@@ -711,7 +765,7 @@ int MAIN(int argc, char **argv)
                                BIO_printf(bio_err,"no engine given\n");
                                goto end;
                                }
-                        e = setup_engine(bio_err, *argv, 0);
+                        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
@@ -745,6 +799,30 @@ int MAIN(int argc, char **argv)
                        j--;    /* Otherwise, -mr gets confused with
                                   an algorithm. */
                        }
+               else if (argc > 0 && !strcmp(*argv,"-mb"))
+                       {
+                       multiblock=1;
+                       j--;
+                       }
+               else if (argc > 0 && !strcmp(*argv,"-misalign"))
+                       {
+                       argc--;
+                       argv++;
+                       if (argc == 0)
+                               {
+                               BIO_printf(bio_err,"no misalignment given\n");
+                               goto end;
+                               }
+                       misalign=atoi(argv[0]);
+                       if (misalign<0 || misalign>MAX_MISALIGNMENT)
+                               {
+                               BIO_printf(bio_err,"misalignment is outsize permitted range 0-%d\n",MAX_MISALIGNMENT);
+                               goto end;
+                               }
+                       buf=buf_malloc+misalign;
+                       buf2=buf2_malloc+misalign;
+                       j--;
+                       }
                else
 #ifndef OPENSSL_NO_MD2
                if      (strcmp(*argv,"md2") == 0) doit[D_MD2]=1;
@@ -842,7 +920,10 @@ int MAIN(int argc, char **argv)
                else if (strcmp(*argv,"rsa512") == 0) rsa_doit[R_RSA_512]=2;
                else if (strcmp(*argv,"rsa1024") == 0) rsa_doit[R_RSA_1024]=2;
                else if (strcmp(*argv,"rsa2048") == 0) rsa_doit[R_RSA_2048]=2;
+               else if (strcmp(*argv,"rsa3072") == 0) rsa_doit[R_RSA_3072]=2;
                else if (strcmp(*argv,"rsa4096") == 0) rsa_doit[R_RSA_4096]=2;
+               else if (strcmp(*argv,"rsa7680") == 0) rsa_doit[R_RSA_7680]=2;
+               else if (strcmp(*argv,"rsa15360") == 0) rsa_doit[R_RSA_15360]=2;
                else
 #ifndef OPENSSL_NO_RC2
                     if (strcmp(*argv,"rc2-cbc") == 0) doit[D_CBC_RC2]=1;
@@ -891,6 +972,10 @@ int MAIN(int argc, char **argv)
                        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
@@ -908,7 +993,10 @@ int MAIN(int argc, char **argv)
                        rsa_doit[R_RSA_512]=1;
                        rsa_doit[R_RSA_1024]=1;
                        rsa_doit[R_RSA_2048]=1;
+                       rsa_doit[R_RSA_3072]=1;
                        rsa_doit[R_RSA_4096]=1;
+                       rsa_doit[R_RSA_7680]=1;
+                       rsa_doit[R_RSA_15360]=1;
                        }
                else
 #endif
@@ -946,7 +1034,7 @@ int MAIN(int argc, char **argv)
                else
 #endif
 #ifndef OPENSSL_NO_ECDH
-                    if (strcmp(*argv,"ecdhp160") == 0) ecdh_doit[R_EC_P160]=2;
+                        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;
@@ -969,6 +1057,18 @@ int MAIN(int argc, char **argv)
                        }
                else
 #endif
+                        if (strcmp(*argv,"prime-trial-division") == 0)
+                       prime_doit[D_PRIME_TRIAL_DIVISION] = 1;
+               else if (strcmp(*argv,"prime-trial-division-retry") == 0)
+                       prime_doit[D_PRIME_TRIAL_DIVISION_RETRY] = 1;
+               else if (strcmp(*argv,"prime-coprime") == 0)
+                       prime_doit[D_PRIME_COPRIME] = 1;
+               else if (strcmp(*argv,"prime") == 0)
+                       {
+                       for (i=0; i < PRIME_NUM; i++)
+                               prime_doit[i]=1;
+                       }
+               else
                        {
                        BIO_printf(bio_err,"Error: bad option or value\n");
                        BIO_printf(bio_err,"\n");
@@ -1046,7 +1146,8 @@ int MAIN(int argc, char **argv)
                        BIO_printf(bio_err,"\n");
 
 #ifndef OPENSSL_NO_RSA
-                       BIO_printf(bio_err,"rsa512   rsa1024  rsa2048  rsa4096\n");
+                       BIO_printf(bio_err,"rsa512   rsa1024  rsa2048  rsa3072  rsa4096\n");
+                       BIO_printf(bio_err,"rsa7680  rsa15360\n");
 #endif
 
 #ifndef OPENSSL_NO_DSA
@@ -1095,6 +1196,7 @@ int MAIN(int argc, char **argv)
     !defined(OPENSSL_NO_AES) || !defined(OPENSSL_NO_CAMELLIA)
                        BIO_printf(bio_err,"\n");
 #endif
+                       BIO_printf(bio_err,"prime-trial-division  prime-coprime\n");
 
                        BIO_printf(bio_err,"\n");
                        BIO_printf(bio_err,"Available options:\n");
@@ -1107,6 +1209,8 @@ int MAIN(int argc, char **argv)
                        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");
+                       BIO_printf(bio_err,"-mb             perform multi-block benchmark (for specific ciphers)\n");
+                       BIO_printf(bio_err,"-misalign n     perform benchmark with misaligned data\n");
 #ifndef NO_FORK
                        BIO_printf(bio_err,"-multi n        run n benchmarks in parallel.\n");
 #endif
@@ -1227,7 +1331,8 @@ int MAIN(int argc, char **argv)
                count*=2;
                Time_F(START);
                for (it=count; it; it--)
-                       DES_ecb_encrypt(buf_as_des_cblock,buf_as_des_cblock,
+                       DES_ecb_encrypt((DES_cblock *)buf,
+                               (DES_cblock *)buf,
                                &sch,DES_ENCRYPT);
                d=Time_F(STOP);
                } while (d <3);
@@ -1260,26 +1365,28 @@ int MAIN(int argc, char **argv)
        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++)
                {
                long l0,l1;
 
-               l0=(long)lengths[i-1];
+               l0=(long)lengths[0];
                l1=(long)lengths[i];
+               
+               c[D_MD2][i]=c[D_MD2][0]*4*l0/l1;
+               c[D_MDC2][i]=c[D_MDC2][0]*4*l0/l1;
+               c[D_MD4][i]=c[D_MD4][0]*4*l0/l1;
+               c[D_MD5][i]=c[D_MD5][0]*4*l0/l1;
+               c[D_HMAC][i]=c[D_HMAC][0]*4*l0/l1;
+               c[D_SHA1][i]=c[D_SHA1][0]*4*l0/l1;
+               c[D_RMD160][i]=c[D_RMD160][0]*4*l0/l1;
+               c[D_SHA256][i]=c[D_SHA256][0]*4*l0/l1;
+               c[D_SHA512][i]=c[D_SHA512][0]*4*l0/l1;
+               c[D_WHIRLPOOL][i]=c[D_WHIRLPOOL][0]*4*l0/l1;
+
+               l0=(long)lengths[i-1];
+               
                c[D_RC4][i]=c[D_RC4][i-1]*l0/l1;
                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;
@@ -1299,6 +1406,11 @@ int MAIN(int argc, char **argv)
                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;
                }
+               
+       prime_c[D_PRIME_TRIAL_DIVISION]=count;
+       prime_c[D_PRIME_TRIAL_DIVISION_RETRY]=count;
+       prime_c[D_PRIME_COPRIME]=count;
+       
 #ifndef OPENSSL_NO_RSA
        rsa_c[R_RSA_512][0]=count/2000;
        rsa_c[R_RSA_512][1]=count/400;
@@ -1454,7 +1566,7 @@ int MAIN(int argc, char **argv)
 # error "You cannot disable DES on systems without SIGALRM."
 #endif /* OPENSSL_NO_DES */
 #else
-#define COND(c)        (run)
+#define COND(c)        (run && count<0x7fffffff)
 #define COUNT(d) (count)
 #ifndef _WIN32
        signal(SIGALRM,sig_done);
@@ -1513,7 +1625,7 @@ int MAIN(int argc, char **argv)
                        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++)
-                               EVP_Digest(&(buf[0]),(unsigned long)lengths[j],&(md5[0]),NULL,EVP_get_digestbyname("md5"),NULL);
+                               MD5(buf,lengths[j],md5);
                        d=Time_F(STOP);
                        print_result(D_MD5,j,count,d);
                        }
@@ -1553,7 +1665,11 @@ int MAIN(int argc, 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++)
+#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);
                        }
@@ -1750,7 +1866,22 @@ int MAIN(int argc, char **argv)
                        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
@@ -1896,6 +2027,19 @@ int MAIN(int argc, char **argv)
 
        if (doit[D_EVP])
                {
+#ifdef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
+               if (multiblock && evp_cipher)
+                       {
+                       if (!(EVP_CIPHER_flags(evp_cipher)&EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK))
+                               {
+                               fprintf(stderr,"%s is not multi-block capable\n",OBJ_nid2ln(evp_cipher->nid));
+                               goto end;
+                               }
+                       multiblock_speed(evp_cipher);
+                       mret=0;
+                       goto end;
+                       }
+#endif
                for (j=0; j<SIZE_NUM; j++)
                        {
                        if (evp_cipher)
@@ -1946,7 +2090,67 @@ int MAIN(int argc, char **argv)
                        print_result(D_EVP,j,count,d);
                        }
                }
-
+#ifndef OPENSSL_SYS_WIN32
+       if (prime_doit[D_PRIME_TRIAL_DIVISION])
+               {
+               BIGNUM *rnd = BN_new();
+               BIGNUM *add = BN_new();
+               BN_CTX *ctx = BN_CTX_new();
+               
+               BN_set_word(add, 2);
+               prime_print_message(prime_names[D_PRIME_TRIAL_DIVISION],
+                                                       prime_c[D_PRIME_TRIAL_DIVISION]);
+                       
+               Time_F(START);
+               for (count=0, run=1; COND(prime_c[D_PRIME_TRIAL_DIVISION]); count++)
+                       if (!bn_probable_prime_dh(rnd, 1024, add, NULL, ctx)) count--;
+               
+               d=Time_F(STOP);
+               prime_print_result(D_PRIME_TRIAL_DIVISION, count, d);
+               
+               BN_CTX_free(ctx);
+               BN_free(add);
+               BN_free(rnd);
+               }
+       
+       if (prime_doit[D_PRIME_TRIAL_DIVISION_RETRY])
+               {
+               BIGNUM *rnd = BN_new();
+               BN_CTX *ctx = BN_CTX_new();
+               
+               prime_print_message(prime_names[D_PRIME_TRIAL_DIVISION_RETRY],
+                                                       prime_c[D_PRIME_TRIAL_DIVISION_RETRY]);
+                       
+               Time_F(START);
+               for (count=0, run=1; COND(prime_c[D_PRIME_TRIAL_DIVISION_RETRY]); count++)
+                       if (!bn_probable_prime_dh_retry(rnd, 1024, ctx)) count--;
+               
+               d=Time_F(STOP);
+               prime_print_result(D_PRIME_TRIAL_DIVISION_RETRY, count, d);
+               
+               BN_CTX_free(ctx);
+               BN_free(rnd);
+               }
+       
+       if (prime_doit[D_PRIME_COPRIME])
+               {
+               BIGNUM *rnd = BN_new();
+               BN_CTX *ctx = BN_CTX_new();
+               
+               prime_print_message(prime_names[D_PRIME_COPRIME],
+                                                       prime_c[D_PRIME_COPRIME]);
+                       
+               Time_F(START);
+               for (count=0, run=1; COND(prime_c[D_PRIME_COPRIME]); count++)
+                       if (!bn_probable_prime_dh_coprime(rnd, 1024, ctx)) count--;
+               
+               d=Time_F(STOP);
+               prime_print_result(D_PRIME_COPRIME, count, d);
+               
+               BN_CTX_free(ctx);
+               BN_free(rnd);
+               }
+#endif
        RAND_pseudo_bytes(buf,36);
 #ifndef OPENSSL_NO_RSA
        for (j=0; j<RSA_NUM; j++)
@@ -2488,8 +2692,8 @@ show_res:
 
 end:
        ERR_print_errors(bio_err);
-       if (buf != NULL) OPENSSL_free(buf);
-       if (buf2 != NULL) OPENSSL_free(buf2);
+       if (buf_malloc != NULL) OPENSSL_free(buf_malloc);
+       if (buf2_malloc != NULL) OPENSSL_free(buf2_malloc);
 #ifndef OPENSSL_NO_RSA
        for (i=0; i<RSA_NUM; i++)
                if (rsa_key[i] != NULL)
@@ -2537,6 +2741,23 @@ static void print_message(const char *s, long num, int length)
 #endif
        }
 
+static void prime_print_message(const char *s, long num)
+       {
+#ifdef SIGALRM
+       BIO_printf(bio_err,mr ? "+DT:%s:%d\n"
+                  : "Doing %s for %ds: ", s, PRIME_SECONDS);
+       (void)BIO_flush(bio_err);
+       alarm(PRIME_SECONDS);
+#else
+       BIO_printf(bio_err,mr ? "+DN:%s:%ld\n"
+                  : "Doing %s %ld times: ", s, num);
+       (void)BIO_flush(bio_err);
+#endif
+#ifdef LINT
+       num=num;
+#endif
+       }
+
 static void pkey_print_message(const char *str, const char *str2, long num,
        int bits, int tm)
        {
@@ -2544,7 +2765,7 @@ static void pkey_print_message(const char *str, const char *str2, long num,
        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(RSA_SECONDS);
+       alarm(tm);
 #else
        BIO_printf(bio_err,mr ? "+DNP:%ld:%d:%s:%s\n"
                           : "Doing %ld %d bit %s %s's: ",num,bits,str,str2);
@@ -2562,6 +2783,14 @@ static void print_result(int alg,int run_no,int count,double time_used)
        results[alg][run_no]=((double)count)/time_used*lengths[run_no];
        }
 
+static void prime_print_result(int alg, int count, double time_used)
+       {
+       BIO_printf(bio_err,
+                          mr ? "+R:%d:%s:%f:%f\n" : "%d %s's in %.2fs (%.2f microseconds / run)\n",
+                          count, prime_names[alg], time_used,
+                          time_used / ((double)count) * 1000000);
+       }
+
 #ifndef NO_FORK
 static char *sstrsep(char **string, const char *delim)
     {
@@ -2604,7 +2833,11 @@ static int do_multi(int multi)
        fds=malloc(multi*sizeof *fds);
        for(n=0 ; n < multi ; ++n)
                {
-               pipe(fd);
+               if (pipe(fd) == -1)
+                       {
+                       fprintf(stderr, "pipe failure\n");
+                       exit(1);
+                       }
                fflush(stdout);
                fflush(stderr);
                if(fork())
@@ -2616,7 +2849,11 @@ static int do_multi(int multi)
                        {
                        close(fd[0]);
                        close(1);
-                       dup(fd[1]);
+                       if (dup(fd[1]) == -1)
+                               {
+                               fprintf(stderr, "dup failed\n");
+                               exit(1);
+                               }
                        close(fd[1]);
                        mr=1;
                        usertime=0;
@@ -2699,6 +2936,7 @@ static int do_multi(int multi)
                                else
                                        rsa_results[k][1]=d;
                                }
+#ifndef OPENSSL_NO_DSA
                        else if(!strncmp(buf,"+F3:",4))
                                {
                                int k;
@@ -2720,6 +2958,7 @@ static int do_multi(int multi)
                                else
                                        dsa_results[k][1]=d;
                                }
+#endif
 #ifndef OPENSSL_NO_ECDSA
                        else if(!strncmp(buf,"+F4:",4))
                                {
@@ -2776,4 +3015,109 @@ static int do_multi(int multi)
        return 1;
        }
 #endif
+
+static void multiblock_speed(const EVP_CIPHER *evp_cipher)
+       {
+       static int mblengths[]={8*1024,2*8*1024,4*8*1024,8*8*1024,8*16*1024};
+       int j,count,num=sizeof(lengths)/sizeof(lengths[0]);
+       const char *alg_name;
+       unsigned char *inp,*out,no_key[32],no_iv[16];
+       EVP_CIPHER_CTX ctx;
+       double d=0.0;
+
+       inp = OPENSSL_malloc(mblengths[num-1]);
+       out = OPENSSL_malloc(mblengths[num-1]+1024);
+
+       EVP_CIPHER_CTX_init(&ctx);
+       EVP_EncryptInit_ex(&ctx,evp_cipher,NULL,no_key,no_iv);
+       EVP_CIPHER_CTX_ctrl(&ctx,EVP_CTRL_AEAD_SET_MAC_KEY,sizeof(no_key),no_key);
+       alg_name=OBJ_nid2ln(evp_cipher->nid);
+
+       for (j=0; j<num; j++)
+               {
+               print_message(alg_name,0,mblengths[j]);
+               Time_F(START);
+               for (count=0,run=1; run && count<0x7fffffff; count++)
+                       {
+                       unsigned char aad[13];
+                       EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
+                       size_t len = mblengths[j];
+                       int packlen;
+
+                       memset(aad,0,8);/* avoid uninitialized values */
+                       aad[8] = 23;    /* SSL3_RT_APPLICATION_DATA */
+                       aad[9] = 3;     /* version */
+                       aad[10] = 2;
+                       aad[11] = 0;    /* length */
+                       aad[12] = 0;
+                       mb_param.out = NULL;
+                       mb_param.inp = aad;
+                       mb_param.len = len;
+                       mb_param.interleave = 8;
+
+                       packlen=EVP_CIPHER_CTX_ctrl(&ctx,
+                                       EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
+                                       sizeof(mb_param),&mb_param);
+
+                       if (packlen>0)
+                               {
+                               mb_param.out = out;
+                               mb_param.inp = inp;
+                               mb_param.len = len;
+                               EVP_CIPHER_CTX_ctrl(&ctx,
+                                       EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
+                                       sizeof(mb_param),&mb_param);
+                               }
+                       else
+                               {
+                               int pad;
+
+                               RAND_bytes(out,16);
+                               len+=16;
+                               aad[11] = len>>8;
+                               aad[12] = len;
+                               pad=EVP_CIPHER_CTX_ctrl(&ctx,
+                                       EVP_CTRL_AEAD_TLS1_AAD,13,aad);
+                               EVP_Cipher(&ctx,out,inp,len+pad);
+                               }
+                       }
+               d=Time_F(STOP);
+               BIO_printf(bio_err,mr ? "+R:%d:%s:%f\n"
+                       : "%d %s's in %.2fs\n",count,"evp",d);
+               results[D_EVP][j]=((double)count)/d*mblengths[j];
+               }
+
+       if (mr)
+               {
+               fprintf(stdout,"+H");
+               for (j=0; j<num; j++)
+                       fprintf(stdout,":%d",mblengths[j]);
+               fprintf(stdout,"\n");
+               fprintf(stdout,"+F:%d:%s",D_EVP,alg_name);
+               for (j=0; j<num; j++)
+                       fprintf(stdout,":%.2f",results[D_EVP][j]);
+               fprintf(stdout,"\n");
+               }
+       else
+               {
+               fprintf(stdout,"The 'numbers' are in 1000s of bytes per second processed.\n"); 
+               fprintf(stdout,"type                    ");
+               for (j=0;  j<num; j++)
+                       fprintf(stdout,"%7d bytes",mblengths[j]);
+               fprintf(stdout,"\n");
+               fprintf(stdout,"%-24s",alg_name);
+
+               for (j=0; j<num; j++)
+                       {
+                       if (results[D_EVP][j] > 10000)
+                               fprintf(stdout," %11.2fk",results[D_EVP][j]/1e3);
+                       else
+                               fprintf(stdout," %11.2f ",results[D_EVP][j]);
+                       }
+               fprintf(stdout,"\n");
+               }
+
+       OPENSSL_free(inp);
+       OPENSSL_free(out);
+       }
 #endif