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.
10296465Sdelphij *
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).
17296465Sdelphij *
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.
24296465Sdelphij *
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 :-).
39296465Sdelphij * 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)"
42296465Sdelphij *
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.
54296465Sdelphij *
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
63296465Sdelphij#define BASENUM 5000
64109998Smarkm#define NUM_START 0
65109998Smarkm
66296465Sdelphij/*
67296465Sdelphij * determine timings for modexp, modmul, modsqr, gcd, Kronecker symbol,
68296465Sdelphij * modular inverse, or modular square roots
69296465Sdelphij */
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
77296465Sdelphij#define P_MOD_64 9              /* least significant 6 bits for prime to be
78296465Sdelphij                                 * 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
81296465Sdelphij# error "choose one test"
82109998Smarkm#endif
83109998Smarkm
84109998Smarkm#if defined(TEST_INV) || defined(TEST_SQRT)
85296465Sdelphij# 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)
101296465Sdelphij# define TIMES
10255714Skris#endif
10355714Skris
10455714Skris#ifndef _IRIX
105296465Sdelphij# include <time.h>
10655714Skris#endif
10755714Skris#ifdef TIMES
108296465Sdelphij# include <sys/types.h>
109296465Sdelphij# include <sys/times.h>
11055714Skris#endif
11155714Skris
112296465Sdelphij/*
113296465Sdelphij * Depending on the VMS version, the tms structure is perhaps defined. The
114296465Sdelphij * __TMS macro will show if it was.  If it wasn't defined, we should undefine
115296465Sdelphij * TIMES, since that tells the rest of the program how things should be
116296465Sdelphij * handled.  -- Richard Levitte
117296465Sdelphij */
118109998Smarkm#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__TMS)
119296465Sdelphij# undef TIMES
12055714Skris#endif
12155714Skris
12255714Skris#ifndef TIMES
123296465Sdelphij# include <sys/timeb.h>
12455714Skris#endif
12555714Skris
12655714Skris#if defined(sun) || defined(__ultrix)
127296465Sdelphij# define _POSIX_SOURCE
128296465Sdelphij# include <limits.h>
129296465Sdelphij# 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
138296465Sdelphij#  ifndef _BSD_CLK_TCK_         /* FreeBSD hack */
139296465Sdelphij#   define HZ   100.0
140296465Sdelphij#  else                         /* _BSD_CLK_TCK_ */
14155714Skris#   define HZ ((double)_BSD_CLK_TCK_)
14255714Skris#  endif
143296465Sdelphij# else                          /* CLK_TCK */
14455714Skris#  define HZ ((double)CLK_TCK)
14555714Skris# endif
14655714Skris#endif
14755714Skris
14855714Skris#undef BUFSIZE
149296465Sdelphij#define BUFSIZE ((long)1024*8)
150296465Sdelphijint run = 0;
15155714Skris
15255714Skrisstatic double Time_F(int s);
153296465Sdelphij#define START   0
154296465Sdelphij#define STOP    1
15555714Skris
15655714Skrisstatic double Time_F(int s)
157296465Sdelphij{
158296465Sdelphij    double ret;
15955714Skris#ifdef TIMES
160296465Sdelphij    static struct tms tstart, tend;
16155714Skris
162296465Sdelphij    if (s == START) {
163296465Sdelphij        times(&tstart);
164296465Sdelphij        return (0);
165296465Sdelphij    } else {
166296465Sdelphij        times(&tend);
167296465Sdelphij        ret = ((double)(tend.tms_utime - tstart.tms_utime)) / HZ;
168296465Sdelphij        return ((ret < 1e-3) ? 1e-3 : ret);
169296465Sdelphij    }
170296465Sdelphij#else                           /* !times() */
171296465Sdelphij    static struct timeb tstart, tend;
172296465Sdelphij    long i;
17355714Skris
174296465Sdelphij    if (s == START) {
175296465Sdelphij        ftime(&tstart);
176296465Sdelphij        return (0);
177296465Sdelphij    } else {
178296465Sdelphij        ftime(&tend);
179296465Sdelphij        i = (long)tend.millitm - (long)tstart.millitm;
180296465Sdelphij        ret = ((double)(tend.time - tstart.time)) + ((double)i) / 1000.0;
181296465Sdelphij        return ((ret < 0.001) ? 0.001 : ret);
182296465Sdelphij    }
18355714Skris#endif
184296465Sdelphij}
18555714Skris
186296465Sdelphij#define NUM_SIZES       7
187109998Smarkm#if NUM_START > NUM_SIZES
188296465Sdelphij# error "NUM_START > NUM_SIZES"
189109998Smarkm#endif
190296465Sdelphijstatic int sizes[NUM_SIZES] = { 128, 256, 512, 1024, 2048, 4096, 8192 };
19155714Skris
192296465Sdelphijstatic int mul_c[NUM_SIZES] =
193296465Sdelphij    { 8 * 8 * 8 * 8 * 8 * 8, 8 * 8 * 8 * 8 * 8, 8 * 8 * 8 * 8, 8 * 8 * 8,
194296465Sdelphij    8 * 8, 8, 1
195296465Sdelphij};
196296465Sdelphij
197296465Sdelphij/*
198296465Sdelphij * static int sizes[NUM_SIZES]={59,179,299,419,539};
199296465Sdelphij */
200296465Sdelphij
201109998Smarkm#define RAND_SEED(string) { const char str[] = string; RAND_seed(string, sizeof str); }
202109998Smarkm
203296465Sdelphijvoid do_mul_exp(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx);
20455714Skris
20555714Skrisint main(int argc, char **argv)
206296465Sdelphij{
207296465Sdelphij    BN_CTX *ctx;
208296465Sdelphij    BIGNUM *a, *b, *c, *r;
20955714Skris
210109998Smarkm#if 1
211296465Sdelphij    if (!CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0))
212296465Sdelphij        abort();
213109998Smarkm#endif
214109998Smarkm
215296465Sdelphij    ctx = BN_CTX_new();
216296465Sdelphij    a = BN_new();
217296465Sdelphij    b = BN_new();
218296465Sdelphij    c = BN_new();
219296465Sdelphij    r = BN_new();
22055714Skris
221296465Sdelphij    while (!RAND_status())
222296465Sdelphij        /* not enough bits */
223296465Sdelphij        RAND_SEED("I demand a manual recount!");
224109998Smarkm
225296465Sdelphij    do_mul_exp(r, a, b, c, ctx);
226296465Sdelphij    return 0;
227296465Sdelphij}
22855714Skris
22955714Skrisvoid do_mul_exp(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx)
230296465Sdelphij{
231296465Sdelphij    int i, k;
232296465Sdelphij    double tm;
233296465Sdelphij    long num;
23455714Skris
235296465Sdelphij    num = BASENUM;
236296465Sdelphij    for (i = NUM_START; i < NUM_SIZES; i++) {
237109998Smarkm#ifdef C_PRIME
238296465Sdelphij# ifdef TEST_SQRT
239296465Sdelphij        if (!BN_set_word(a, 64))
240296465Sdelphij            goto err;
241296465Sdelphij        if (!BN_set_word(b, P_MOD_64))
242296465Sdelphij            goto err;
243296465Sdelphij#  define ADD a
244296465Sdelphij#  define REM b
245296465Sdelphij# else
246296465Sdelphij#  define ADD NULL
247296465Sdelphij#  define REM NULL
248296465Sdelphij# endif
249296465Sdelphij        if (!BN_generate_prime(c, sizes[i], 0, ADD, REM, genprime_cb, NULL))
250296465Sdelphij            goto err;
251296465Sdelphij        putc('\n', stderr);
252296465Sdelphij        fflush(stderr);
253109998Smarkm#endif
25455714Skris
255296465Sdelphij        for (k = 0; k < num; k++) {
256296465Sdelphij            if (k % 50 == 0) {  /* Average over num/50 different choices of
257296465Sdelphij                                 * random numbers. */
258296465Sdelphij                if (!BN_pseudo_rand(a, sizes[i], 1, 0))
259296465Sdelphij                    goto err;
26055714Skris
261296465Sdelphij                if (!BN_pseudo_rand(b, sizes[i], 1, 0))
262296465Sdelphij                    goto err;
263109998Smarkm
264109998Smarkm#ifndef C_PRIME
265296465Sdelphij                if (!BN_pseudo_rand(c, sizes[i], 1, 1))
266296465Sdelphij                    goto err;
267109998Smarkm#endif
268109998Smarkm
269296465Sdelphij#ifdef TEST_SQRT
270296465Sdelphij                if (!BN_mod_sqr(a, a, c, ctx))
271296465Sdelphij                    goto err;
272296465Sdelphij                if (!BN_mod_sqr(b, b, c, ctx))
273296465Sdelphij                    goto err;
274109998Smarkm#else
275296465Sdelphij                if (!BN_nnmod(a, a, c, ctx))
276296465Sdelphij                    goto err;
277296465Sdelphij                if (!BN_nnmod(b, b, c, ctx))
278296465Sdelphij                    goto err;
279109998Smarkm#endif
280109998Smarkm
281296465Sdelphij                if (k == 0)
282296465Sdelphij                    Time_F(START);
283296465Sdelphij            }
284109998Smarkm#if defined(TEST_EXP)
285296465Sdelphij            if (!BN_mod_exp(r, a, b, c, ctx))
286296465Sdelphij                goto err;
287109998Smarkm#elif defined(TEST_MUL)
288296465Sdelphij            {
289296465Sdelphij                int i = 0;
290296465Sdelphij                for (i = 0; i < 50; i++)
291296465Sdelphij                    if (!BN_mod_mul(r, a, b, c, ctx))
292296465Sdelphij                        goto err;
293296465Sdelphij            }
294109998Smarkm#elif defined(TEST_SQR)
295296465Sdelphij            {
296296465Sdelphij                int i = 0;
297296465Sdelphij                for (i = 0; i < 50; i++) {
298296465Sdelphij                    if (!BN_mod_sqr(r, a, c, ctx))
299296465Sdelphij                        goto err;
300296465Sdelphij                    if (!BN_mod_sqr(r, b, c, ctx))
301296465Sdelphij                        goto err;
302296465Sdelphij                }
303296465Sdelphij            }
304109998Smarkm#elif defined(TEST_GCD)
305296465Sdelphij            if (!BN_gcd(r, a, b, ctx))
306296465Sdelphij                goto err;
307296465Sdelphij            if (!BN_gcd(r, b, c, ctx))
308296465Sdelphij                goto err;
309296465Sdelphij            if (!BN_gcd(r, c, a, ctx))
310296465Sdelphij                goto err;
311109998Smarkm#elif defined(TEST_KRON)
312296465Sdelphij            if (-2 == BN_kronecker(a, b, ctx))
313296465Sdelphij                goto err;
314296465Sdelphij            if (-2 == BN_kronecker(b, c, ctx))
315296465Sdelphij                goto err;
316296465Sdelphij            if (-2 == BN_kronecker(c, a, ctx))
317296465Sdelphij                goto err;
318109998Smarkm#elif defined(TEST_INV)
319296465Sdelphij            if (!BN_mod_inverse(r, a, c, ctx))
320296465Sdelphij                goto err;
321296465Sdelphij            if (!BN_mod_inverse(r, b, c, ctx))
322296465Sdelphij                goto err;
323296465Sdelphij#else                           /* TEST_SQRT */
324296465Sdelphij            if (!BN_mod_sqrt(r, a, c, ctx))
325296465Sdelphij                goto err;
326296465Sdelphij            if (!BN_mod_sqrt(r, b, c, ctx))
327296465Sdelphij                goto err;
328109998Smarkm#endif
329296465Sdelphij        }
330296465Sdelphij        tm = Time_F(STOP);
331296465Sdelphij        printf(
332109998Smarkm#if defined(TEST_EXP)
333296465Sdelphij                  "modexp %4d ^ %4d %% %4d"
334109998Smarkm#elif defined(TEST_MUL)
335296465Sdelphij                  "50*modmul %4d %4d %4d"
336109998Smarkm#elif defined(TEST_SQR)
337296465Sdelphij                  "100*modsqr %4d %4d %4d"
338109998Smarkm#elif defined(TEST_GCD)
339296465Sdelphij                  "3*gcd %4d %4d %4d"
340109998Smarkm#elif defined(TEST_KRON)
341296465Sdelphij                  "3*kronecker %4d %4d %4d"
342109998Smarkm#elif defined(TEST_INV)
343296465Sdelphij                  "2*inv %4d %4d mod %4d"
344296465Sdelphij#else                           /* TEST_SQRT */
345296465Sdelphij                  "2*sqrt [prime == %d (mod 64)] %4d %4d mod %4d"
346109998Smarkm#endif
347296465Sdelphij                  " -> %8.6fms %5.1f (%ld)\n",
348109998Smarkm#ifdef TEST_SQRT
349296465Sdelphij                  P_MOD_64,
350109998Smarkm#endif
351296465Sdelphij                  sizes[i], sizes[i], sizes[i], tm * 1000.0 / num,
352296465Sdelphij                  tm * mul_c[i] / num, num);
353296465Sdelphij        num /= 7;
354296465Sdelphij        if (num <= 0)
355296465Sdelphij            num = 1;
356296465Sdelphij    }
357296465Sdelphij    return;
35855714Skris
359109998Smarkm err:
360296465Sdelphij    ERR_print_errors_fp(stderr);
361296465Sdelphij}
36255714Skris
363109998Smarkm#ifdef C_PRIME
364109998Smarkmstatic void genprime_cb(int p, int n, void *arg)
365296465Sdelphij{
366296465Sdelphij    char c = '*';
367109998Smarkm
368296465Sdelphij    if (p == 0)
369296465Sdelphij        c = '.';
370296465Sdelphij    if (p == 1)
371296465Sdelphij        c = '+';
372296465Sdelphij    if (p == 2)
373296465Sdelphij        c = '*';
374296465Sdelphij    if (p == 3)
375296465Sdelphij        c = '\n';
376296465Sdelphij    putc(c, stderr);
377296465Sdelphij    fflush(stderr);
378296465Sdelphij    (void)n;
379296465Sdelphij    (void)arg;
380296465Sdelphij}
381109998Smarkm#endif
382