Import of old SSLeay release: SSLeay 0.9.1b (unreleased)
[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(argc,argv)
106 int argc;
107 char **argv;
108         {
109         PARMS p;
110         BN_MONT_CTX *mont;
111         int size=0,num;
112         char *name;
113         int type=P_EXP;
114
115         mont=BN_MONT_CTX_new();
116         p.mont=NULL;
117         p.ctx=BN_CTX_new();
118         BN_init(&p.r);
119         BN_init(&p.a);
120         BN_init(&p.b);
121         BN_init(&p.c);
122         BN_init(&p.low);
123         p.w=0;
124
125         for (;;)
126                 {
127                 if (argc > 1)
128                         {
129                         if (argv[1][0] == '-')
130                                 {
131                                 switch(argv[1][1])
132                                         {
133                                 case 'e': type=P_EXP; break;
134                                 case 'm': type=P_MUL; break;
135                                 case 's': type=P_SQR; break;
136                                 case 'l': type=P_MULL; break;
137                                 case 'h': type=P_MULH; break;
138                                 case 'r': type=P_MRED; break;
139                                 default:
140                                         fprintf(stderr,"options: -[emslhr]\n");
141                                         exit(1);
142                                         }
143                                 }
144                         else
145                                 {
146                                 size=atoi(argv[1]);
147                                 }
148                         argc--;
149                         argv++;
150                         }
151                 else
152                         break;
153                 }
154         if (size == 0)
155                 size=DEFAULT_SIZE;
156
157         printf("bit size:%5d\n",size);
158
159         BN_rand(&p.a,size,1,0);
160         BN_rand(&p.b,size,1,0);
161         BN_rand(&p.c,size,1,1);
162         BN_mod(&p.a,&p.a,&p.c,p.ctx);
163         BN_mod(&p.b,&p.b,&p.c,p.ctx);
164         p.w=(p.a.top+1)/2;
165
166         BN_mul(&p.low,&p.a,&p.b,p.ctx);
167         p.low.top=p.a.top;
168         
169         switch(type)
170                 {
171         case P_EXP:
172                 p.name="r=a^b%c";
173                 p.func=do_mul_exp;
174                 p.mont=mont;
175                 break;
176         case P_MUL:
177                 p.name="r=a*b";
178                 p.func=do_mul;
179                 break;
180         case P_SQR:
181                 p.name="r=a*a";
182                 p.func=do_sqr;
183                 break;
184         case P_MULL:
185                 p.name="r=low(a*b)";
186                 p.func=do_mul_low;
187                 break;
188         case P_MULH:
189                 p.name="r=high(a*b)";
190                 p.func=do_mul_high;
191                 break;
192         case P_MRED:
193                 p.name="r=montgomery_reduction(a)";
194                 p.func=do_from_montgomery;
195                 p.mont=mont;
196                 break;
197         default:
198                 fprintf(stderr,"options: -[emslhr]\n");
199                 exit(1);
200                 }
201
202         num=time_it(DEFAULT_TIME,&p);
203         do_it(num,&p);
204         }
205
206 void do_it(num,p)
207 int num;
208 PARMS *p;
209         {
210         char *start,*end;
211         int i,j,number;
212         double d;
213
214         start=ms_time_new();
215         end=ms_time_new();
216
217         number=BN_num_bits_word((BN_ULONG)BN_num_bits(&(p->c)))-
218                 BN_num_bits_word(BN_BITS2)+2;
219         for (i=number-1; i >=0; i--)
220                 {
221                 if (i == 1) continue;
222                 BN_set_params(i,i,i,1);
223                 if (p->mont != NULL)
224                         BN_MONT_CTX_set(p->mont,&(p->c),p->ctx);
225
226                 printf("Timing %5d (%2d bit) %2d %2d %2d %2d :",
227                         (1<<i)*BN_BITS2,i,
228                                 BN_get_params(0),
229                                 BN_get_params(1),
230                                 BN_get_params(2),
231                                 BN_get_params(3));
232                 fflush(stdout);
233
234                 ms_time_get(start);
235                 p->func(num,p);
236                 ms_time_get(end);
237                 d=ms_time_diff(start,end);
238                 printf("%6.6f sec, or %d in %.4f seconds\n",
239                         (double)d/num,num,d);
240                 }
241         }
242
243 int time_it(sec,p)
244 int sec;
245 PARMS *p;
246         {
247         char *start,*end;
248         int i,j;
249         double d;
250
251         if (p->mont != NULL)
252                 BN_MONT_CTX_set(p->mont,&(p->c),p->ctx);
253
254         start=ms_time_new();
255         end=ms_time_new();
256
257         i=1;
258         for (;;)
259                 {
260                 if (verbose)
261                         printf("timing %s for %d interations\n",p->name,i);
262
263                 ms_time_get(start);
264                 p->func(i,p);
265                 ms_time_get(end);
266                 d=ms_time_diff(start,end);
267
268                 if      (d < 0.01) i*=100;
269                 else if (d < 0.1 ) i*=10;
270                 else if (d > (double)sec) break;
271                 else
272                         {
273                         i=(int)(1.0*i*sec/d);
274                         break;
275                         }
276                 }
277         if (verbose)
278                 printf("using %d interations\n",i);
279         return(i);
280         }
281
282 void do_mul_exp(num,p)
283 int num;
284 PARMS *p;
285         {
286         int i;
287
288         for (i=0; i<num; i++)
289                 BN_mod_exp_mont(&(p->r),&(p->a),&(p->b),&(p->c),
290                         p->ctx,p->mont);
291         }
292
293 void do_mul(num,p)
294 int num;
295 PARMS *p;
296         {
297         int i;
298
299         for (i=0; i<num; i++)
300                 BN_mul(&(p->r),&(p->a),&(p->b),p->ctx);
301         }
302
303 void do_sqr(num,p)
304 int num;
305 PARMS *p;
306         {
307         int i;
308
309         for (i=0; i<num; i++)
310                         BN_sqr(&(p->r),&(p->a),p->ctx);
311         }
312
313 void do_mul_low(num,p)
314 int num;
315 PARMS *p;
316         {
317         int i;
318         
319         for (i=0; i<num; i++)
320                 BN_mul_low(&(p->r),&(p->a),&(p->b),p->w,p->ctx);
321         }
322
323 void do_mul_high(num,p)
324 int num;
325 PARMS *p;
326         {
327         int i;
328
329         for (i=0; i<num; i++)
330                 BN_mul_low(&(p->r),&(p->a),&(p->b),&(p->low),p->w,p->ctx);
331         }
332
333 void do_from_montgomery(num,p)
334 int num;
335 PARMS *p;
336         {
337         int i;
338         
339         for (i=0; i<num; i++)
340                 BN_from_montgomery(&(p->r),&(p->a),p->mont,p->ctx);
341         }
342