Remove editor barf on updating copyright.
[openssl.git] / apps / speed.c
index 4447f73c493403b5de16022d530a72e7f926deed..36e885a594fcc99f2f0a7b944ae5d02adda41fe3 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
 
 #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>
 
-#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 1
+#include "../crypto/bn/bn_lcl.h"
+
+#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
@@ -197,15 +217,18 @@ 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);
-#ifdef HAVE_FORK
+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 PRIME_NUM      2
 #define RSA_NUM                4
 #define DSA_NUM                3
 
@@ -219,11 +242,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 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
@@ -259,9 +288,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)
        {
@@ -273,9 +305,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)
@@ -284,17 +318,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
 
@@ -320,9 +362,6 @@ int MAIN(int, char **);
 
 int MAIN(int argc, char **argv)
        {
-#ifndef OPENSSL_NO_ENGINE
-       ENGINE *e = NULL;
-#endif
        unsigned char *buf=NULL,*buf2=NULL;
        int mret=1;
        long count=0,save_count=0;
@@ -414,9 +453,8 @@ int MAIN(int argc, char **argv)
 #define MAX_BLOCK_SIZE 64
 #endif
        unsigned char DES_iv[8];
-       unsigned char iv[MAX_BLOCK_SIZE/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};
@@ -459,8 +497,14 @@ 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_COPRIME                        1
+       long prime_c[PRIME_NUM];
+
 #define        R_DSA_512       0
 #define        R_DSA_1024      1
 #define        R_DSA_2048      2
@@ -574,6 +618,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
@@ -587,7 +632,7 @@ int MAIN(int argc, char **argv)
        const EVP_CIPHER *evp_cipher=NULL;
        const EVP_MD *evp_md=NULL;
        int decrypt=0;
-#ifdef HAVE_FORK
+#ifndef NO_FORK
        int multi=0;
 #endif
 
@@ -630,9 +675,6 @@ int MAIN(int argc, char **argv)
                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)
                {
                BIO_printf(bio_err,"out of memory\n");
@@ -707,7 +749,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
@@ -715,7 +757,7 @@ int MAIN(int argc, char **argv)
                        j--;
                        }
 #endif
-#ifdef HAVE_FORK
+#ifndef NO_FORK
                else if ((argc > 0) && (strcmp(*argv,"-multi") == 0))
                        {
                        argc--;
@@ -887,6 +929,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
@@ -942,7 +988,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;
@@ -965,6 +1011,9 @@ 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-coprime") == 0)            prime_doit[D_PRIME_COPRIME]=1;
+               else
                        {
                        BIO_printf(bio_err,"Error: bad option or value\n");
                        BIO_printf(bio_err,"\n");
@@ -1091,6 +1140,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");
@@ -1103,7 +1153,7 @@ 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");
-#ifdef HAVE_FORK
+#ifndef NO_FORK
                        BIO_printf(bio_err,"-multi n        run n benchmarks in parallel.\n");
 #endif
                        goto end;
@@ -1113,7 +1163,7 @@ int MAIN(int argc, char **argv)
                j++;
                }
 
-#ifdef HAVE_FORK
+#ifndef NO_FORK
        if(multi && do_multi(multi))
                goto show_res;
 #endif
@@ -1129,6 +1179,14 @@ int MAIN(int argc, char **argv)
                        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++;
@@ -1215,7 +1273,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);
@@ -1248,26 +1307,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;
@@ -1287,6 +1348,10 @@ 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_COPRIME]=count;
+       
 #ifndef OPENSSL_NO_RSA
        rsa_c[R_RSA_512][0]=count/2000;
        rsa_c[R_RSA_512][1]=count/400;
@@ -1442,7 +1507,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);
@@ -1501,7 +1566,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);
                        }
@@ -1541,7 +1606,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);
                        }
@@ -1703,7 +1772,7 @@ int MAIN(int argc, char **argv)
                        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,buf,
+                               AES_ige_encrypt(buf,buf2,
                                        (unsigned long)lengths[j],&aes_ks1,
                                        iv,AES_ENCRYPT);
                        d=Time_F(STOP);
@@ -1717,7 +1786,7 @@ int MAIN(int argc, char **argv)
                        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,buf,
+                               AES_ige_encrypt(buf,buf2,
                                        (unsigned long)lengths[j],&aes_ks2,
                                        iv,AES_ENCRYPT);
                        d=Time_F(STOP);
@@ -1731,14 +1800,29 @@ int MAIN(int argc, char **argv)
                        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,buf,
+                               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
@@ -1934,6 +2018,52 @@ int MAIN(int argc, char **argv)
                        print_result(D_EVP,j,count,d);
                        }
                }
+       
+       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++)
+                       bn_probable_prime_dh(rnd, 1024, add, NULL, ctx);
+               
+               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_COPRIME])
+               {
+               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_COPRIME],
+                                                       prime_c[D_PRIME_COPRIME]);
+                       
+               Time_F(START);
+               for (count=0, run=1; COND(prime_c[D_PRIME_COPRIME]); count++)
+                       bn_probable_prime_dh_coprime_safe(rnd, 1024, add, NULL, ctx);
+               
+               d=Time_F(STOP);
+               prime_print_result(D_PRIME_COPRIME, count, d);
+               
+               BN_CTX_free(ctx);
+               BN_free(add);
+               BN_free(rnd);
+               
+               }
 
        RAND_pseudo_bytes(buf,36);
 #ifndef OPENSSL_NO_RSA
@@ -1994,7 +2124,7 @@ int MAIN(int argc, char **argv)
                                {
                                ret=RSA_verify(NID_md5_sha1, buf,36, buf2,
                                        rsa_num, rsa_key[j]);
-                               if (ret == 0)
+                               if (ret <= 0)
                                        {
                                        BIO_printf(bio_err,
                                                "RSA verify failure\n");
@@ -2324,7 +2454,7 @@ int MAIN(int argc, char **argv)
                }
        if (rnd_fake) RAND_cleanup();
 #endif
-#ifdef HAVE_FORK
+#ifndef NO_FORK
 show_res:
 #endif
        if(!mr)
@@ -2525,6 +2655,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)
        {
@@ -2532,7 +2679,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);
@@ -2550,7 +2697,15 @@ 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];
        }
 
-#ifdef HAVE_FORK
+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)
     {
     char isdelim[256];
@@ -2592,7 +2747,13 @@ 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())
                        {
                        close(fd[1]);
@@ -2602,7 +2763,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;
@@ -2685,6 +2850,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;
@@ -2706,6 +2872,7 @@ static int do_multi(int multi)
                                else
                                        dsa_results[k][1]=d;
                                }
+#endif
 #ifndef OPENSSL_NO_ECDSA
                        else if(!strncmp(buf,"+F4:",4))
                                {