159191Skris/* unused */
259191Skris
355714Skris/* crypto/bn/expspeed.c */
455714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
555714Skris * All rights reserved.
655714Skris *
755714Skris * This package is an SSL implementation written
855714Skris * by Eric Young (eay@cryptsoft.com).
955714Skris * The implementation was written so as to conform with Netscapes SSL.
10280304Sjkim *
1155714Skris * This library is free for commercial and non-commercial use as long as
1255714Skris * the following conditions are aheared to.  The following conditions
1355714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1455714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1555714Skris * included with this distribution is covered by the same copyright terms
1655714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
17280304Sjkim *
1855714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1955714Skris * the code are not to be removed.
2055714Skris * If this package is used in a product, Eric Young should be given attribution
2155714Skris * as the author of the parts of the library used.
2255714Skris * This can be in the form of a textual message at program startup or
2355714Skris * in documentation (online or textual) provided with the package.
24280304Sjkim *
2555714Skris * Redistribution and use in source and binary forms, with or without
2655714Skris * modification, are permitted provided that the following conditions
2755714Skris * are met:
2855714Skris * 1. Redistributions of source code must retain the copyright
2955714Skris *    notice, this list of conditions and the following disclaimer.
3055714Skris * 2. Redistributions in binary form must reproduce the above copyright
3155714Skris *    notice, this list of conditions and the following disclaimer in the
3255714Skris *    documentation and/or other materials provided with the distribution.
3355714Skris * 3. All advertising materials mentioning features or use of this software
3455714Skris *    must display the following acknowledgement:
3555714Skris *    "This product includes cryptographic software written by
3655714Skris *     Eric Young (eay@cryptsoft.com)"
3755714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3855714Skris *    being used are not cryptographic related :-).
39280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from
4055714Skris *    the apps directory (application code) you must include an acknowledgement:
4155714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
42280304Sjkim *
4355714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4455714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4555714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4655714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4755714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4855714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4955714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5055714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5155714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5255714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5355714Skris * SUCH DAMAGE.
54280304Sjkim *
5555714Skris * The licence and distribution terms for any publically available version or
5655714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5755714Skris * copied and put under another distribution licence
5855714Skris * [including the GNU Public Licence.]
5955714Skris */
6055714Skris
6155714Skris/* most of this code has been pilfered from my libdes speed.c program */
6255714Skris
63280304Sjkim#define BASENUM 5000
64109998Smarkm#define NUM_START 0
65109998Smarkm
66280304Sjkim/*
67280304Sjkim * determine timings for modexp, modmul, modsqr, gcd, Kronecker symbol,
68280304Sjkim * modular inverse, or modular square roots
69280304Sjkim */
70109998Smarkm#define TEST_EXP
71109998Smarkm#undef TEST_MUL
72109998Smarkm#undef TEST_SQR
73109998Smarkm#undef TEST_GCD
74109998Smarkm#undef TEST_KRON
75109998Smarkm#undef TEST_INV
76109998Smarkm#undef TEST_SQRT
77280304Sjkim#define P_MOD_64 9              /* least significant 6 bits for prime to be
78280304Sjkim                                 * used for BN_sqrt timings */
79109998Smarkm
80109998Smarkm#if defined(TEST_EXP) + defined(TEST_MUL) + defined(TEST_SQR) + defined(TEST_GCD) + defined(TEST_KRON) + defined(TEST_INV) +defined(TEST_SQRT) != 1
81280304Sjkim# error "choose one test"
82109998Smarkm#endif
83109998Smarkm
84109998Smarkm#if defined(TEST_INV) || defined(TEST_SQRT)
85280304Sjkim# define C_PRIME
86109998Smarkmstatic void genprime_cb(int p, int n, void *arg);
87109998Smarkm#endif
88109998Smarkm
8955714Skris#undef PROG
9055714Skris#define PROG bnspeed_main
9155714Skris
9255714Skris#include <stdio.h>
9355714Skris#include <stdlib.h>
9455714Skris#include <signal.h>
9555714Skris#include <string.h>
9655714Skris#include <openssl/crypto.h>
9755714Skris#include <openssl/err.h>
98109998Smarkm#include <openssl/rand.h>
9955714Skris
100109998Smarkm#if !defined(OPENSSL_SYS_MSDOS) && (!defined(OPENSSL_SYS_VMS) || defined(__DECC)) && !defined(OPENSSL_SYS_MACOSX)
101280304Sjkim# define TIMES
10255714Skris#endif
10355714Skris
10455714Skris#ifndef _IRIX
105280304Sjkim# include <time.h>
10655714Skris#endif
10755714Skris#ifdef TIMES
108280304Sjkim# include <sys/types.h>
109280304Sjkim# include <sys/times.h>
11055714Skris#endif
11155714Skris
112280304Sjkim/*
113280304Sjkim * Depending on the VMS version, the tms structure is perhaps defined. The
114280304Sjkim * __TMS macro will show if it was.  If it wasn't defined, we should undefine
115280304Sjkim * TIMES, since that tells the rest of the program how things should be
116280304Sjkim * handled.  -- Richard Levitte
117280304Sjkim */
118109998Smarkm#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__TMS)
119280304Sjkim# undef TIMES
12055714Skris#endif
12155714Skris
12255714Skris#ifndef TIMES
123280304Sjkim# include <sys/timeb.h>
12455714Skris#endif
12555714Skris
12655714Skris#if defined(sun) || defined(__ultrix)
127280304Sjkim# define _POSIX_SOURCE
128280304Sjkim# include <limits.h>
129280304Sjkim# include <sys/param.h>
13055714Skris#endif
13155714Skris
13255714Skris#include <openssl/bn.h>
13355714Skris#include <openssl/x509.h>
13455714Skris
13555714Skris/* The following if from times(3) man page.  It may need to be changed */
13655714Skris#ifndef HZ
13755714Skris# ifndef CLK_TCK
138280304Sjkim#  ifndef _BSD_CLK_TCK_         /* FreeBSD hack */
139280304Sjkim#   define HZ   100.0
140280304Sjkim#  else                         /* _BSD_CLK_TCK_ */
14155714Skris#   define HZ ((double)_BSD_CLK_TCK_)
14255714Skris#  endif
143280304Sjkim# else                          /* CLK_TCK */
14455714Skris#  define HZ ((double)CLK_TCK)
14555714Skris# endif
14655714Skris#endif
14755714Skris
14855714Skris#undef BUFSIZE
149280304Sjkim#define BUFSIZE ((long)1024*8)
150280304Sjkimint run = 0;
15155714Skris
15255714Skrisstatic double Time_F(int s);
153280304Sjkim#define START   0
154280304Sjkim#define STOP    1
15555714Skris
15655714Skrisstatic double Time_F(int s)
157280304Sjkim{
158280304Sjkim    double ret;
15955714Skris#ifdef TIMES
160280304Sjkim    static struct tms tstart, tend;
16155714Skris
162280304Sjkim    if (s == START) {
163280304Sjkim        times(&tstart);
164280304Sjkim        return (0);
165280304Sjkim    } else {
166280304Sjkim        times(&tend);
167280304Sjkim        ret = ((double)(tend.tms_utime - tstart.tms_utime)) / HZ;
168280304Sjkim        return ((ret < 1e-3) ? 1e-3 : ret);
169280304Sjkim    }
170280304Sjkim#else                           /* !times() */
171280304Sjkim    static struct timeb tstart, tend;
172280304Sjkim    long i;
17355714Skris
174280304Sjkim    if (s == START) {
175280304Sjkim        ftime(&tstart);
176280304Sjkim        return (0);
177280304Sjkim    } else {
178280304Sjkim        ftime(&tend);
179280304Sjkim        i = (long)tend.millitm - (long)tstart.millitm;
180280304Sjkim        ret = ((double)(tend.time - tstart.time)) + ((double)i) / 1000.0;
181280304Sjkim        return ((ret < 0.001) ? 0.001 : ret);
182280304Sjkim    }
18355714Skris#endif
184280304Sjkim}
18555714Skris
186280304Sjkim#define NUM_SIZES       7
187109998Smarkm#if NUM_START > NUM_SIZES
188280304Sjkim# error "NUM_START > NUM_SIZES"
189109998Smarkm#endif
190280304Sjkimstatic int sizes[NUM_SIZES] = { 128, 256, 512, 1024, 2048, 4096, 8192 };
19155714Skris
192280304Sjkimstatic int mul_c[NUM_SIZES] =
193280304Sjkim    { 8 * 8 * 8 * 8 * 8 * 8, 8 * 8 * 8 * 8 * 8, 8 * 8 * 8 * 8, 8 * 8 * 8,
194280304Sjkim    8 * 8, 8, 1
195280304Sjkim};
196280304Sjkim
197280304Sjkim/*
198280304Sjkim * static int sizes[NUM_SIZES]={59,179,299,419,539};
199280304Sjkim */
200280304Sjkim
201109998Smarkm#define RAND_SEED(string) { const char str[] = string; RAND_seed(string, sizeof str); }
202109998Smarkm
203280304Sjkimvoid do_mul_exp(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx);
20455714Skris
20555714Skrisint main(int argc, char **argv)
206280304Sjkim{
207280304Sjkim    BN_CTX *ctx;
208280304Sjkim    BIGNUM *a, *b, *c, *r;
20955714Skris
210109998Smarkm#if 1
211280304Sjkim    if (!CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0))
212280304Sjkim        abort();
213109998Smarkm#endif
214109998Smarkm
215280304Sjkim    ctx = BN_CTX_new();
216280304Sjkim    a = BN_new();
217280304Sjkim    b = BN_new();
218280304Sjkim    c = BN_new();
219280304Sjkim    r = BN_new();
22055714Skris
221280304Sjkim    while (!RAND_status())
222280304Sjkim        /* not enough bits */
223280304Sjkim        RAND_SEED("I demand a manual recount!");
224109998Smarkm
225280304Sjkim    do_mul_exp(r, a, b, c, ctx);
226280304Sjkim    return 0;
227280304Sjkim}
22855714Skris
22955714Skrisvoid do_mul_exp(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx)
230280304Sjkim{
231280304Sjkim    int i, k;
232280304Sjkim    double tm;
233280304Sjkim    long num;
23455714Skris
235280304Sjkim    num = BASENUM;
236280304Sjkim    for (i = NUM_START; i < NUM_SIZES; i++) {
237109998Smarkm#ifdef C_PRIME
238280304Sjkim# ifdef TEST_SQRT
239280304Sjkim        if (!BN_set_word(a, 64))
240280304Sjkim            goto err;
241280304Sjkim        if (!BN_set_word(b, P_MOD_64))
242280304Sjkim            goto err;
243280304Sjkim#  define ADD a
244280304Sjkim#  define REM b
245280304Sjkim# else
246280304Sjkim#  define ADD NULL
247280304Sjkim#  define REM NULL
248280304Sjkim# endif
249280304Sjkim        if (!BN_generate_prime(c, sizes[i], 0, ADD, REM, genprime_cb, NULL))
250280304Sjkim            goto err;
251280304Sjkim        putc('\n', stderr);
252280304Sjkim        fflush(stderr);
253109998Smarkm#endif
25455714Skris
255280304Sjkim        for (k = 0; k < num; k++) {
256280304Sjkim            if (k % 50 == 0) {  /* Average over num/50 different choices of
257280304Sjkim                                 * random numbers. */
258280304Sjkim                if (!BN_pseudo_rand(a, sizes[i], 1, 0))
259280304Sjkim                    goto err;
26055714Skris
261280304Sjkim                if (!BN_pseudo_rand(b, sizes[i], 1, 0))
262280304Sjkim                    goto err;
263109998Smarkm
264109998Smarkm#ifndef C_PRIME
265280304Sjkim                if (!BN_pseudo_rand(c, sizes[i], 1, 1))
266280304Sjkim                    goto err;
267109998Smarkm#endif
268109998Smarkm
269280304Sjkim#ifdef TEST_SQRT
270280304Sjkim                if (!BN_mod_sqr(a, a, c, ctx))
271280304Sjkim                    goto err;
272280304Sjkim                if (!BN_mod_sqr(b, b, c, ctx))
273280304Sjkim                    goto err;
274109998Smarkm#else
275280304Sjkim                if (!BN_nnmod(a, a, c, ctx))
276280304Sjkim                    goto err;
277280304Sjkim                if (!BN_nnmod(b, b, c, ctx))
278280304Sjkim                    goto err;
279109998Smarkm#endif
280109998Smarkm
281280304Sjkim                if (k == 0)
282280304Sjkim                    Time_F(START);
283280304Sjkim            }
284109998Smarkm#if defined(TEST_EXP)
285280304Sjkim            if (!BN_mod_exp(r, a, b, c, ctx))
286280304Sjkim                goto err;
287109998Smarkm#elif defined(TEST_MUL)
288280304Sjkim            {
289280304Sjkim                int i = 0;
290280304Sjkim                for (i = 0; i < 50; i++)
291280304Sjkim                    if (!BN_mod_mul(r, a, b, c, ctx))
292280304Sjkim                        goto err;
293280304Sjkim            }
294109998Smarkm#elif defined(TEST_SQR)
295280304Sjkim            {
296280304Sjkim                int i = 0;
297280304Sjkim                for (i = 0; i < 50; i++) {
298280304Sjkim                    if (!BN_mod_sqr(r, a, c, ctx))
299280304Sjkim                        goto err;
300280304Sjkim                    if (!BN_mod_sqr(r, b, c, ctx))
301280304Sjkim                        goto err;
302280304Sjkim                }
303280304Sjkim            }
304109998Smarkm#elif defined(TEST_GCD)
305280304Sjkim            if (!BN_gcd(r, a, b, ctx))
306280304Sjkim                goto err;
307280304Sjkim            if (!BN_gcd(r, b, c, ctx))
308280304Sjkim                goto err;
309280304Sjkim            if (!BN_gcd(r, c, a, ctx))
310280304Sjkim                goto err;
311109998Smarkm#elif defined(TEST_KRON)
312280304Sjkim            if (-2 == BN_kronecker(a, b, ctx))
313280304Sjkim                goto err;
314280304Sjkim            if (-2 == BN_kronecker(b, c, ctx))
315280304Sjkim                goto err;
316280304Sjkim            if (-2 == BN_kronecker(c, a, ctx))
317280304Sjkim                goto err;
318109998Smarkm#elif defined(TEST_INV)
319280304Sjkim            if (!BN_mod_inverse(r, a, c, ctx))
320280304Sjkim                goto err;
321280304Sjkim            if (!BN_mod_inverse(r, b, c, ctx))
322280304Sjkim                goto err;
323280304Sjkim#else                           /* TEST_SQRT */
324280304Sjkim            if (!BN_mod_sqrt(r, a, c, ctx))
325280304Sjkim                goto err;
326280304Sjkim            if (!BN_mod_sqrt(r, b, c, ctx))
327280304Sjkim                goto err;
328109998Smarkm#endif
329280304Sjkim        }
330280304Sjkim        tm = Time_F(STOP);
331280304Sjkim        printf(
332109998Smarkm#if defined(TEST_EXP)
333280304Sjkim                  "modexp %4d ^ %4d %% %4d"
334109998Smarkm#elif defined(TEST_MUL)
335280304Sjkim                  "50*modmul %4d %4d %4d"
336109998Smarkm#elif defined(TEST_SQR)
337280304Sjkim                  "100*modsqr %4d %4d %4d"
338109998Smarkm#elif defined(TEST_GCD)
339280304Sjkim                  "3*gcd %4d %4d %4d"
340109998Smarkm#elif defined(TEST_KRON)
341280304Sjkim                  "3*kronecker %4d %4d %4d"
342109998Smarkm#elif defined(TEST_INV)
343280304Sjkim                  "2*inv %4d %4d mod %4d"
344280304Sjkim#else                           /* TEST_SQRT */
345280304Sjkim                  "2*sqrt [prime == %d (mod 64)] %4d %4d mod %4d"
346109998Smarkm#endif
347280304Sjkim                  " -> %8.6fms %5.1f (%ld)\n",
348109998Smarkm#ifdef TEST_SQRT
349280304Sjkim                  P_MOD_64,
350109998Smarkm#endif
351280304Sjkim                  sizes[i], sizes[i], sizes[i], tm * 1000.0 / num,
352280304Sjkim                  tm * mul_c[i] / num, num);
353280304Sjkim        num /= 7;
354280304Sjkim        if (num <= 0)
355280304Sjkim            num = 1;
356280304Sjkim    }
357280304Sjkim    return;
35855714Skris
359109998Smarkm err:
360280304Sjkim    ERR_print_errors_fp(stderr);
361280304Sjkim}
36255714Skris
363109998Smarkm#ifdef C_PRIME
364109998Smarkmstatic void genprime_cb(int p, int n, void *arg)
365280304Sjkim{
366280304Sjkim    char c = '*';
367109998Smarkm
368280304Sjkim    if (p == 0)
369280304Sjkim        c = '.';
370280304Sjkim    if (p == 1)
371280304Sjkim        c = '+';
372280304Sjkim    if (p == 2)
373280304Sjkim        c = '*';
374280304Sjkim    if (p == 3)
375280304Sjkim        c = '\n';
376280304Sjkim    putc(c, stderr);
377280304Sjkim    fflush(stderr);
378280304Sjkim    (void)n;
379280304Sjkim    (void)arg;
380280304Sjkim}
381109998Smarkm#endif
382