2d04184c885419111e7f8100da9e1c158b20bc75
[openssl.git] / crypto / bn / bn_opts.c
1 /* crypto/bn/expspeed.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 /* most of this code has been pilfered from my libdes speed.c program */
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <signal.h>
64 #include <string.h>
65 #include "crypto.h"
66 #include "tmdiff.h"
67 #include "bn.h"
68 #include "err.h"
69
70 #define DEFAULT_SIZE    512
71 #define DEFAULT_TIME    3
72
73 int verbose=1;
74
75 typedef struct parms_st
76         {
77         char *name;
78         void (*func)();
79         BIGNUM r;
80         BIGNUM a;
81         BIGNUM b;
82         BIGNUM c;
83         BIGNUM low;
84         BN_CTX *ctx;
85         BN_MONT_CTX *mont;
86         int w;
87         } PARMS;
88
89 void do_mul_exp(int num,PARMS *p);
90 void do_mul(int num,PARMS *p);
91 void do_sqr(int num,PARMS *p);
92 void do_mul_low(int num,PARMS *p);
93 void do_mul_high(int num,PARMS *p);
94 void do_from_montgomery(int num,PARMS *p);
95 int time_it(int sec, PARMS *p);
96 void do_it(int sec, PARMS *p);
97
98 #define P_EXP   1
99 #define P_MUL   2
100 #define P_SQR   3
101 #define P_MULL  4
102 #define P_MULH  5
103 #define P_MRED  6
104
105 int main(int argc, char **argv)
106         {
107         PARMS p;
108         BN_MONT_CTX *mont;
109         int size=0,num;
110         char *name;
111         int type=P_EXP;
112
113         mont=BN_MONT_CTX_new();
114         p.mont=NULL;
115         p.ctx=BN_CTX_new();
116         BN_init(&p.r);
117         BN_init(&p.a);
118         BN_init(&p.b);
119         BN_init(&p.c);
120         BN_init(&p.low);
121         p.w=0;
122
123         for (;;)
124                 {
125                 if (argc > 1)
126                         {
127                         if (argv[1][0] == '-')
128                                 {
129                                 switch(argv[1][1])
130                                         {
131                                 case 'e': type=P_EXP; break;
132                                 case 'm': type=P_MUL; break;
133                                 case 's': type=P_SQR; break;
134                                 case 'l': type=P_MULL; break;
135                                 case 'h': type=P_MULH; break;
136                                 case 'r': type=P_MRED; break;
137                                 default:
138                                         fprintf(stderr,"options: -[emslhr]\n");
139                                         exit(1);
140                                         }
141                                 }
142                         else
143                                 {
144                                 size=atoi(argv[1]);
145                                 }
146                         argc--;
147                         argv++;
148                         }
149                 else
150                         break;
151                 }
152         if (size == 0)
153                 size=DEFAULT_SIZE;
154
155         printf("bit size:%5d\n",size);
156
157         BN_rand(&p.a,size,1,0);
158         BN_rand(&p.b,size,1,0);
159         BN_rand(&p.c,size,1,1);
160         BN_mod(&p.a,&p.a,&p.c,p.ctx);
161         BN_mod(&p.b,&p.b,&p.c,p.ctx);
162         p.w=(p.a.top+1)/2;
163
164         BN_mul(&p.low,&p.a,&p.b,p.ctx);
165         p.low.top=p.a.top;
166         
167         switch(type)
168                 {
169         case P_EXP:
170                 p.name="r=a^b%c";
171                 p.func=do_mul_exp;
172                 p.mont=mont;
173                 break;
174         case P_MUL:
175                 p.name="r=a*b";
176                 p.func=do_mul;
177                 break;
178         case P_SQR:
179                 p.name="r=a*a";
180                 p.func=do_sqr;
181                 break;
182         case P_MULL:
183                 p.name="r=low(a*b)";
184                 p.func=do_mul_low;
185                 break;
186         case P_MULH:
187                 p.name="r=high(a*b)";
188                 p.func=do_mul_high;
189                 break;
190         case P_MRED:
191                 p.name="r=montgomery_reduction(a)";
192                 p.func=do_from_montgomery;
193                 p.mont=mont;
194                 break;
195         default:
196                 fprintf(stderr,"options: -[emslhr]\n");
197                 exit(1);
198                 }
199
200         num=time_it(DEFAULT_TIME,&p);
201         do_it(num,&p);
202         }
203
204 void do_it(int num, PARMS *p)
205         {
206         char *start,*end;
207         int i,j,number;
208         double d;
209
210         start=ms_time_new();
211         end=ms_time_new();
212
213         number=BN_num_bits_word((BN_ULONG)BN_num_bits(&(p->c)))-
214                 BN_num_bits_word(BN_BITS2)+2;
215         for (i=number-1; i >=0; i--)
216                 {
217                 if (i == 1) continue;
218                 BN_set_params(i,i,i,1);
219                 if (p->mont != NULL)
220                         BN_MONT_CTX_set(p->mont,&(p->c),p->ctx);
221
222                 printf("Timing %5d (%2d bit) %2d %2d %2d %2d :",
223                         (1<<i)*BN_BITS2,i,
224                                 BN_get_params(0),
225                                 BN_get_params(1),
226                                 BN_get_params(2),
227                                 BN_get_params(3));
228                 fflush(stdout);
229
230                 ms_time_get(start);
231                 p->func(num,p);
232                 ms_time_get(end);
233                 d=ms_time_diff(start,end);
234                 printf("%6.6f sec, or %d in %.4f seconds\n",
235                         (double)d/num,num,d);
236                 }
237         }
238
239 int time_it(int sec, PARMS *p)
240         {
241         char *start,*end;
242         int i,j;
243         double d;
244
245         if (p->mont != NULL)
246                 BN_MONT_CTX_set(p->mont,&(p->c),p->ctx);
247
248         start=ms_time_new();
249         end=ms_time_new();
250
251         i=1;
252         for (;;)
253                 {
254                 if (verbose)
255                         printf("timing %s for %d interations\n",p->name,i);
256
257                 ms_time_get(start);
258                 p->func(i,p);
259                 ms_time_get(end);
260                 d=ms_time_diff(start,end);
261
262                 if      (d < 0.01) i*=100;
263                 else if (d < 0.1 ) i*=10;
264                 else if (d > (double)sec) break;
265                 else
266                         {
267                         i=(int)(1.0*i*sec/d);
268                         break;
269                         }
270                 }
271         if (verbose)
272                 printf("using %d interations\n",i);
273         return(i);
274         }
275
276 void do_mul_exp(int num, PARMS *p)
277         {
278         int i;
279
280         for (i=0; i<num; i++)
281                 BN_mod_exp_mont(&(p->r),&(p->a),&(p->b),&(p->c),
282                         p->ctx,p->mont);
283         }
284
285 void do_mul(int num, PARMS *p)
286         {
287         int i;
288
289         for (i=0; i<num; i++)
290                 BN_mul(&(p->r),&(p->a),&(p->b),p->ctx);
291         }
292
293 void do_sqr(int num, PARMS *p)
294         {
295         int i;
296
297         for (i=0; i<num; i++)
298                         BN_sqr(&(p->r),&(p->a),p->ctx);
299         }
300
301 void do_mul_low(int num, PARMS *p)
302         {
303         int i;
304         
305         for (i=0; i<num; i++)
306                 BN_mul_low(&(p->r),&(p->a),&(p->b),p->w,p->ctx);
307         }
308
309 void do_mul_high(int num, PARMS *p)
310         {
311         int i;
312
313         for (i=0; i<num; i++)
314                 BN_mul_low(&(p->r),&(p->a),&(p->b),&(p->low),p->w,p->ctx);
315         }
316
317 void do_from_montgomery(int num, PARMS *p)
318         {
319         int i;
320         
321         for (i=0; i<num; i++)
322                 BN_from_montgomery(&(p->r),&(p->a),p->mont,p->ctx);
323         }
324