9e478dfe24b8ba1448ee86346edc3a44280ee12c
[openssl.git] / crypto / bn / bntest.c
1 /* crypto/bn/bntest.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 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62
63 #include "openssl/e_os.h"
64
65 #include <openssl/bio.h>
66 #include <openssl/bn.h>
67 #include <openssl/rand.h>
68 #include <openssl/x509.h>
69 #include <openssl/err.h>
70
71 #ifdef WINDOWS
72 #include "../bio/bss_file.c"
73 #endif
74
75 const int num0 = 100; /* number of tests */
76 const int num1 = 50;  /* additional tests for some functions */
77 const int num2 = 5;   /* number of tests for slow functions */
78
79 int test_add(BIO *bp);
80 int test_sub(BIO *bp);
81 int test_lshift1(BIO *bp);
82 int test_lshift(BIO *bp,BN_CTX *ctx,BIGNUM *a_);
83 int test_rshift1(BIO *bp);
84 int test_rshift(BIO *bp,BN_CTX *ctx);
85 int test_div(BIO *bp,BN_CTX *ctx);
86 int test_div_recp(BIO *bp,BN_CTX *ctx);
87 int test_mul(BIO *bp);
88 int test_sqr(BIO *bp,BN_CTX *ctx);
89 int test_mont(BIO *bp,BN_CTX *ctx);
90 int test_mod(BIO *bp,BN_CTX *ctx);
91 int test_mod_mul(BIO *bp,BN_CTX *ctx);
92 int test_mod_exp(BIO *bp,BN_CTX *ctx);
93 int test_exp(BIO *bp,BN_CTX *ctx);
94 int test_kron(BIO *bp,BN_CTX *ctx);
95 int rand_neg(void);
96 static int results=0;
97
98 #ifdef NO_STDIO
99 #define APPS_WIN16
100 #include "bss_file.c"
101 #endif
102
103 static unsigned char lst[]="\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
104 "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
105
106 static const char rnd_seed[] = "string to make the random number generator think it has entropy";
107
108 static void message(BIO *out, char *m)
109         {
110         fprintf(stderr, "test %s\n", m);
111 #if defined(linux) || defined(__FreeBSD__) /* can we use GNU bc features? */
112         BIO_puts(out, "print \"test ");
113         BIO_puts(out, m);
114         BIO_puts(out, "\\n\"\n");
115 #endif
116         }
117
118 int main(int argc, char *argv[])
119         {
120         BN_CTX *ctx;
121         BIO *out;
122         char *outfile=NULL;
123
124         results = 0;
125
126         RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_rand may fail, and we don't
127                                                * even check its return value
128                                                * (which we should) */
129
130         argc--;
131         argv++;
132         while (argc >= 1)
133                 {
134                 if (strcmp(*argv,"-results") == 0)
135                         results=1;
136                 else if (strcmp(*argv,"-out") == 0)
137                         {
138                         if (--argc < 1) break;
139                         outfile= *(++argv);
140                         }
141                 argc--;
142                 argv++;
143                 }
144
145
146         ctx=BN_CTX_new();
147         if (ctx == NULL) exit(1);
148
149         out=BIO_new(BIO_s_file());
150         if (out == NULL) exit(1);
151         if (outfile == NULL)
152                 {
153                 BIO_set_fp(out,stdout,BIO_NOCLOSE);
154                 }
155         else
156                 {
157                 if (!BIO_write_filename(out,outfile))
158                         {
159                         perror(outfile);
160                         exit(1);
161                         }
162                 }
163
164         if (!results)
165                 BIO_puts(out,"obase=16\nibase=16\n");
166
167         message(out,"BN_add");
168         if (!test_add(out)) goto err;
169         BIO_flush(out);
170
171         message(out,"BN_sub");
172         if (!test_sub(out)) goto err;
173         BIO_flush(out);
174
175         message(out,"BN_lshift1");
176         if (!test_lshift1(out)) goto err;
177         BIO_flush(out);
178
179         message(out,"BN_lshift (fixed)");
180         if (!test_lshift(out,ctx,BN_bin2bn(lst,sizeof(lst)-1,NULL)))
181             goto err;
182         BIO_flush(out);
183
184         message(out,"BN_lshift");
185         if (!test_lshift(out,ctx,NULL)) goto err;
186         BIO_flush(out);
187
188         message(out,"BN_rshift1");
189         if (!test_rshift1(out)) goto err;
190         BIO_flush(out);
191
192         message(out,"BN_rshift");
193         if (!test_rshift(out,ctx)) goto err;
194         BIO_flush(out);
195
196         message(out,"BN_sqr");
197         if (!test_sqr(out,ctx)) goto err;
198         BIO_flush(out);
199
200         message(out,"BN_mul");
201         if (!test_mul(out)) goto err;
202         BIO_flush(out);
203
204         message(out,"BN_div");
205         if (!test_div(out,ctx)) goto err;
206         BIO_flush(out);
207
208         message(out,"BN_div_recp");
209         if (!test_div_recp(out,ctx)) goto err;
210         BIO_flush(out);
211
212         message(out,"BN_mod");
213         if (!test_mod(out,ctx)) goto err;
214         BIO_flush(out);
215
216         message(out,"BN_mod_mul");
217         if (!test_mod_mul(out,ctx)) goto err;
218         BIO_flush(out);
219
220         message(out,"BN_mont");
221         if (!test_mont(out,ctx)) goto err;
222         BIO_flush(out);
223
224         message(out,"BN_mod_exp");
225         if (!test_mod_exp(out,ctx)) goto err;
226         BIO_flush(out);
227
228         message(out,"BN_exp");
229         if (!test_exp(out,ctx)) goto err;
230         BIO_flush(out);
231
232         message(out,"BN_kronecker");
233         if (!test_kron(out,ctx)) goto err;
234         BIO_flush(out);
235
236         BN_CTX_free(ctx);
237         BIO_free(out);
238
239 /**/
240         exit(0);
241 err:
242         BIO_puts(out,"1\n"); /* make sure the Perl script fed by bc notices
243                               * the failure, see test_bn in test/Makefile.ssl*/
244         BIO_flush(out);
245         ERR_load_crypto_strings();
246         ERR_print_errors_fp(stderr);
247         exit(1);
248         return(1);
249         }
250
251 int test_add(BIO *bp)
252         {
253         BIGNUM a,b,c;
254         int i;
255         int j;
256
257         BN_init(&a);
258         BN_init(&b);
259         BN_init(&c);
260
261         BN_rand(&a,512,0,0);
262         for (i=0; i<num0; i++)
263                 {
264                 BN_rand(&b,450+i,0,0);
265                 a.neg=rand_neg();
266                 b.neg=rand_neg();
267                 if (bp == NULL)
268                         for (j=0; j<10000; j++)
269                                 BN_add(&c,&a,&b);
270                 BN_add(&c,&a,&b);
271                 if (bp != NULL)
272                         {
273                         if (!results)
274                                 {
275                                 BN_print(bp,&a);
276                                 BIO_puts(bp," + ");
277                                 BN_print(bp,&b);
278                                 BIO_puts(bp," - ");
279                                 }
280                         BN_print(bp,&c);
281                         BIO_puts(bp,"\n");
282                         }
283                 a.neg=!a.neg;
284                 b.neg=!b.neg;
285                 BN_add(&c,&c,&b);
286                 BN_add(&c,&c,&a);
287                 if(!BN_is_zero(&c))
288                     {
289                     fprintf(stderr,"Add test failed!\n");
290                     return 0;
291                     }
292                 }
293         BN_free(&a);
294         BN_free(&b);
295         BN_free(&c);
296         return(1);
297         }
298
299 int test_sub(BIO *bp)
300         {
301         BIGNUM a,b,c;
302         int i;
303         int j;
304
305         BN_init(&a);
306         BN_init(&b);
307         BN_init(&c);
308
309         for (i=0; i<num0+num1; i++)
310                 {
311                 if (i < num1)
312                         {
313                         BN_rand(&a,512,0,0);
314                         BN_copy(&b,&a);
315                         if (BN_set_bit(&a,i)==0) return(0);
316                         BN_add_word(&b,i);
317                         }
318                 else
319                         {
320                         BN_rand(&b,400+i-num1,0,0);
321                         a.neg=rand_neg();
322                         b.neg=rand_neg();
323                         }
324                 if (bp == NULL)
325                         for (j=0; j<10000; j++)
326                                 BN_sub(&c,&a,&b);
327                 BN_sub(&c,&a,&b);
328                 if (bp != NULL)
329                         {
330                         if (!results)
331                                 {
332                                 BN_print(bp,&a);
333                                 BIO_puts(bp," - ");
334                                 BN_print(bp,&b);
335                                 BIO_puts(bp," - ");
336                                 }
337                         BN_print(bp,&c);
338                         BIO_puts(bp,"\n");
339                         }
340                 BN_add(&c,&c,&b);
341                 BN_sub(&c,&c,&a);
342                 if(!BN_is_zero(&c))
343                     {
344                     fprintf(stderr,"Subtract test failed!\n");
345                     return 0;
346                     }
347                 }
348         BN_free(&a);
349         BN_free(&b);
350         BN_free(&c);
351         return(1);
352         }
353
354 int test_div(BIO *bp, BN_CTX *ctx)
355         {
356         BIGNUM a,b,c,d,e;
357         int i;
358         int j;
359
360         BN_init(&a);
361         BN_init(&b);
362         BN_init(&c);
363         BN_init(&d);
364         BN_init(&e);
365
366         for (i=0; i<num0+num1; i++)
367                 {
368                 if (i < num1)
369                         {
370                         BN_rand(&a,400,0,0);
371                         BN_copy(&b,&a);
372                         BN_lshift(&a,&a,i);
373                         BN_add_word(&a,i);
374                         }
375                 else
376                         BN_rand(&b,50+3*(i-num1),0,0);
377                 a.neg=rand_neg();
378                 b.neg=rand_neg();
379                 if (bp == NULL)
380                         for (j=0; j<100; j++)
381                                 BN_div(&d,&c,&a,&b,ctx);
382                 BN_div(&d,&c,&a,&b,ctx);
383                 if (bp != NULL)
384                         {
385                         if (!results)
386                                 {
387                                 BN_print(bp,&a);
388                                 BIO_puts(bp," / ");
389                                 BN_print(bp,&b);
390                                 BIO_puts(bp," - ");
391                                 }
392                         BN_print(bp,&d);
393                         BIO_puts(bp,"\n");
394
395                         if (!results)
396                                 {
397                                 BN_print(bp,&a);
398                                 BIO_puts(bp," % ");
399                                 BN_print(bp,&b);
400                                 BIO_puts(bp," - ");
401                                 }
402                         BN_print(bp,&c);
403                         BIO_puts(bp,"\n");
404                         }
405                 BN_mul(&e,&d,&b,ctx);
406                 BN_add(&d,&e,&c);
407                 BN_sub(&d,&d,&a);
408                 if(!BN_is_zero(&d))
409                     {
410                     fprintf(stderr,"Division test failed!\n");
411                     return 0;
412                     }
413                 }
414         BN_free(&a);
415         BN_free(&b);
416         BN_free(&c);
417         BN_free(&d);
418         BN_free(&e);
419         return(1);
420         }
421
422 int test_div_recp(BIO *bp, BN_CTX *ctx)
423         {
424         BIGNUM a,b,c,d,e;
425         BN_RECP_CTX recp;
426         int i;
427         int j;
428
429         BN_RECP_CTX_init(&recp);
430         BN_init(&a);
431         BN_init(&b);
432         BN_init(&c);
433         BN_init(&d);
434         BN_init(&e);
435
436         for (i=0; i<num0+num1; i++)
437                 {
438                 if (i < num1)
439                         {
440                         BN_rand(&a,400,0,0);
441                         BN_copy(&b,&a);
442                         BN_lshift(&a,&a,i);
443                         BN_add_word(&a,i);
444                         }
445                 else
446                         BN_rand(&b,50+3*(i-num1),0,0);
447                 a.neg=rand_neg();
448                 b.neg=rand_neg();
449                 BN_RECP_CTX_set(&recp,&b,ctx);
450                 if (bp == NULL)
451                         for (j=0; j<100; j++)
452                                 BN_div_recp(&d,&c,&a,&recp,ctx);
453                 BN_div_recp(&d,&c,&a,&recp,ctx);
454                 if (bp != NULL)
455                         {
456                         if (!results)
457                                 {
458                                 BN_print(bp,&a);
459                                 BIO_puts(bp," / ");
460                                 BN_print(bp,&b);
461                                 BIO_puts(bp," - ");
462                                 }
463                         BN_print(bp,&d);
464                         BIO_puts(bp,"\n");
465
466                         if (!results)
467                                 {
468                                 BN_print(bp,&a);
469                                 BIO_puts(bp," % ");
470                                 BN_print(bp,&b);
471                                 BIO_puts(bp," - ");
472                                 }
473                         BN_print(bp,&c);
474                         BIO_puts(bp,"\n");
475                         }
476                 BN_mul(&e,&d,&b,ctx);
477                 BN_add(&d,&e,&c);
478                 BN_sub(&d,&d,&a);
479                 if(!BN_is_zero(&d))
480                     {
481                     fprintf(stderr,"Reciprocal division test failed!\n");
482                     fprintf(stderr,"a=");
483                     BN_print_fp(stderr,&a);
484                     fprintf(stderr,"\nb=");
485                     BN_print_fp(stderr,&b);
486                     fprintf(stderr,"\n");
487                     return 0;
488                     }
489                 }
490         BN_free(&a);
491         BN_free(&b);
492         BN_free(&c);
493         BN_free(&d);
494         BN_free(&e);
495         BN_RECP_CTX_free(&recp);
496         return(1);
497         }
498
499 int test_mul(BIO *bp)
500         {
501         BIGNUM a,b,c,d,e;
502         int i;
503         int j;
504         BN_CTX ctx;
505
506         BN_CTX_init(&ctx);
507         BN_init(&a);
508         BN_init(&b);
509         BN_init(&c);
510         BN_init(&d);
511         BN_init(&e);
512
513         for (i=0; i<num0+num1; i++)
514                 {
515                 if (i <= num1)
516                         {
517                         BN_rand(&a,100,0,0);
518                         BN_rand(&b,100,0,0);
519                         }
520                 else
521                         BN_rand(&b,i-num1,0,0);
522                 a.neg=rand_neg();
523                 b.neg=rand_neg();
524                 if (bp == NULL)
525                         for (j=0; j<100; j++)
526                                 BN_mul(&c,&a,&b,&ctx);
527                 BN_mul(&c,&a,&b,&ctx);
528                 if (bp != NULL)
529                         {
530                         if (!results)
531                                 {
532                                 BN_print(bp,&a);
533                                 BIO_puts(bp," * ");
534                                 BN_print(bp,&b);
535                                 BIO_puts(bp," - ");
536                                 }
537                         BN_print(bp,&c);
538                         BIO_puts(bp,"\n");
539                         }
540                 BN_div(&d,&e,&c,&a,&ctx);
541                 BN_sub(&d,&d,&b);
542                 if(!BN_is_zero(&d) || !BN_is_zero(&e))
543                     {
544                     fprintf(stderr,"Multiplication test failed!\n");
545                     return 0;
546                     }
547                 }
548         BN_free(&a);
549         BN_free(&b);
550         BN_free(&c);
551         BN_free(&d);
552         BN_free(&e);
553         BN_CTX_free(&ctx);
554         return(1);
555         }
556
557 int test_sqr(BIO *bp, BN_CTX *ctx)
558         {
559         BIGNUM a,c,d,e;
560         int i;
561         int j;
562
563         BN_init(&a);
564         BN_init(&c);
565         BN_init(&d);
566         BN_init(&e);
567
568         for (i=0; i<num0; i++)
569                 {
570                 BN_rand(&a,40+i*10,0,0);
571                 a.neg=rand_neg();
572                 if (bp == NULL)
573                         for (j=0; j<100; j++)
574                                 BN_sqr(&c,&a,ctx);
575                 BN_sqr(&c,&a,ctx);
576                 if (bp != NULL)
577                         {
578                         if (!results)
579                                 {
580                                 BN_print(bp,&a);
581                                 BIO_puts(bp," * ");
582                                 BN_print(bp,&a);
583                                 BIO_puts(bp," - ");
584                                 }
585                         BN_print(bp,&c);
586                         BIO_puts(bp,"\n");
587                         }
588                 BN_div(&d,&e,&c,&a,ctx);
589                 BN_sub(&d,&d,&a);
590                 if(!BN_is_zero(&d) || !BN_is_zero(&e))
591                     {
592                     fprintf(stderr,"Square test failed!\n");
593                     return 0;
594                     }
595                 }
596         BN_free(&a);
597         BN_free(&c);
598         BN_free(&d);
599         BN_free(&e);
600         return(1);
601         }
602
603 int test_mont(BIO *bp, BN_CTX *ctx)
604         {
605         BIGNUM a,b,c,d,A,B;
606         BIGNUM n;
607         int i;
608         int j;
609         BN_MONT_CTX *mont;
610
611         BN_init(&a);
612         BN_init(&b);
613         BN_init(&c);
614         BN_init(&d);
615         BN_init(&A);
616         BN_init(&B);
617         BN_init(&n);
618
619         mont=BN_MONT_CTX_new();
620
621         BN_rand(&a,100,0,0); /**/
622         BN_rand(&b,100,0,0); /**/
623         for (i=0; i<num2; i++)
624                 {
625                 int bits = (200*(i+1))/num2;
626
627                 if (bits == 0)
628                         continue;
629                 BN_rand(&n,bits,0,1);
630                 BN_MONT_CTX_set(mont,&n,ctx);
631
632                 BN_nnmod(&a,&a,&n,ctx);
633                 BN_nnmod(&b,&b,&n,ctx);
634
635                 BN_to_montgomery(&A,&a,mont,ctx);
636                 BN_to_montgomery(&B,&b,mont,ctx);
637
638                 if (bp == NULL)
639                         for (j=0; j<100; j++)
640                                 BN_mod_mul_montgomery(&c,&A,&B,mont,ctx);/**/
641                 BN_mod_mul_montgomery(&c,&A,&B,mont,ctx);/**/
642                 BN_from_montgomery(&A,&c,mont,ctx);/**/
643                 if (bp != NULL)
644                         {
645                         if (!results)
646                                 {
647 #ifdef undef
648 fprintf(stderr,"%d * %d %% %d\n",
649 BN_num_bits(&a),
650 BN_num_bits(&b),
651 BN_num_bits(mont->N));
652 #endif
653                                 BN_print(bp,&a);
654                                 BIO_puts(bp," * ");
655                                 BN_print(bp,&b);
656                                 BIO_puts(bp," % ");
657                                 BN_print(bp,&(mont->N));
658                                 BIO_puts(bp," - ");
659                                 }
660                         BN_print(bp,&A);
661                         BIO_puts(bp,"\n");
662                         }
663                 BN_mod_mul(&d,&a,&b,&n,ctx);
664                 BN_sub(&d,&d,&A);
665                 if(!BN_is_zero(&d))
666                     {
667                     fprintf(stderr,"Montgomery multiplication test failed!\n");
668                     return 0;
669                     }
670                 }
671         BN_MONT_CTX_free(mont);
672         BN_free(&a);
673         BN_free(&b);
674         BN_free(&c);
675         BN_free(&d);
676         BN_free(&A);
677         BN_free(&B);
678         BN_free(&n);
679         return(1);
680         }
681
682 int test_mod(BIO *bp, BN_CTX *ctx)
683         {
684         BIGNUM *a,*b,*c,*d,*e;
685         int i;
686         int j;
687
688         a=BN_new();
689         b=BN_new();
690         c=BN_new();
691         d=BN_new();
692         e=BN_new();
693
694         BN_rand(a,1024,0,0); /**/
695         for (i=0; i<num0; i++)
696                 {
697                 BN_rand(b,450+i*10,0,0); /**/
698                 a->neg=rand_neg();
699                 b->neg=rand_neg();
700                 if (bp == NULL)
701                         for (j=0; j<100; j++)
702                                 BN_mod(c,a,b,ctx);/**/
703                 BN_mod(c,a,b,ctx);/**/
704                 if (bp != NULL)
705                         {
706                         if (!results)
707                                 {
708                                 BN_print(bp,a);
709                                 BIO_puts(bp," % ");
710                                 BN_print(bp,b);
711                                 BIO_puts(bp," - ");
712                                 }
713                         BN_print(bp,c);
714                         BIO_puts(bp,"\n");
715                         }
716                 BN_div(d,e,a,b,ctx);
717                 BN_sub(e,e,c);
718                 if(!BN_is_zero(e))
719                     {
720                     fprintf(stderr,"Modulo test failed!\n");
721                     return 0;
722                     }
723                 }
724         BN_free(a);
725         BN_free(b);
726         BN_free(c);
727         BN_free(d);
728         BN_free(e);
729         return(1);
730         }
731
732 int test_mod_mul(BIO *bp, BN_CTX *ctx)
733         {
734         BIGNUM *a,*b,*c,*d,*e;
735         int i;
736
737         a=BN_new();
738         b=BN_new();
739         c=BN_new();
740         d=BN_new();
741         e=BN_new();
742
743         BN_rand(c,1024,0,0); /**/
744         for (i=0; i<num0; i++)
745                 {
746                 BN_rand(a,475+i*10,0,0); /**/
747                 BN_rand(b,425+i*11,0,0); /**/
748                 a->neg=rand_neg();
749                 b->neg=rand_neg();
750         /*      if (bp == NULL)
751                         for (j=0; j<100; j++)
752                                 BN_mod_mul(d,a,b,c,ctx);*/ /**/
753
754                 if (!BN_mod_mul(e,a,b,c,ctx))
755                         {
756                         unsigned long l;
757
758                         while ((l=ERR_get_error()))
759                                 fprintf(stderr,"ERROR:%s\n",
760                                         ERR_error_string(l,NULL));
761                         exit(1);
762                         }
763                 if (bp != NULL)
764                         {
765                         if (!results)
766                                 {
767                                 BN_print(bp,a);
768                                 BIO_puts(bp," * ");
769                                 BN_print(bp,b);
770                                 BIO_puts(bp," % ");
771                                 BN_print(bp,c);
772                                 if ((a->neg ^ b->neg) && !BN_is_zero(e))
773                                         {
774                                         /* If  (a*b) % c  is negative,  c  must be added
775                                          * in order to obtain the normalized remainder
776                                          * (new with OpenSSL 0.9.7, previous versions of
777                                          * BN_mod_mul could generate negative results)
778                                          */
779                                         BIO_puts(bp," + ");
780                                         BN_print(bp,c);
781                                         }
782                                 BIO_puts(bp," - ");
783                                 }
784                         BN_print(bp,e);
785                         BIO_puts(bp,"\n");
786                         }
787                 BN_mul(d,a,b,ctx);
788                 BN_sub(d,d,e);
789                 BN_div(a,b,d,c,ctx);
790                 if(!BN_is_zero(b))
791                     {
792                     fprintf(stderr,"Modulo multiply test failed!\n");
793                     ERR_print_errors_fp(stderr);
794                     return 0;
795                     }
796                 }
797         BN_free(a);
798         BN_free(b);
799         BN_free(c);
800         BN_free(d);
801         BN_free(e);
802         return(1);
803         }
804
805 int test_mod_exp(BIO *bp, BN_CTX *ctx)
806         {
807         BIGNUM *a,*b,*c,*d,*e;
808         int i;
809
810         a=BN_new();
811         b=BN_new();
812         c=BN_new();
813         d=BN_new();
814         e=BN_new();
815
816         BN_rand(c,30,0,1); /* must be odd for montgomery */
817         for (i=0; i<num2; i++)
818                 {
819                 BN_rand(a,20+i*5,0,0); /**/
820                 BN_rand(b,2+i,0,0); /**/
821
822                 if (!BN_mod_exp(d,a,b,c,ctx))
823                         return(00);
824
825                 if (bp != NULL)
826                         {
827                         if (!results)
828                                 {
829                                 BN_print(bp,a);
830                                 BIO_puts(bp," ^ ");
831                                 BN_print(bp,b);
832                                 BIO_puts(bp," % ");
833                                 BN_print(bp,c);
834                                 BIO_puts(bp," - ");
835                                 }
836                         BN_print(bp,d);
837                         BIO_puts(bp,"\n");
838                         }
839                 BN_exp(e,a,b,ctx);
840                 BN_sub(e,e,d);
841                 BN_div(a,b,e,c,ctx);
842                 if(!BN_is_zero(b))
843                     {
844                     fprintf(stderr,"Modulo exponentiation test failed!\n");
845                     return 0;
846                     }
847                 }
848         BN_free(a);
849         BN_free(b);
850         BN_free(c);
851         BN_free(d);
852         BN_free(e);
853         return(1);
854         }
855
856 int test_exp(BIO *bp, BN_CTX *ctx)
857         {
858         BIGNUM *a,*b,*d,*e,*one;
859         int i;
860
861         a=BN_new();
862         b=BN_new();
863         d=BN_new();
864         e=BN_new();
865         one=BN_new();
866         BN_one(one);
867
868         for (i=0; i<num2; i++)
869                 {
870                 BN_rand(a,20+i*5,0,0); /**/
871                 BN_rand(b,2+i,0,0); /**/
872
873                 if (!BN_exp(d,a,b,ctx))
874                         return(00);
875
876                 if (bp != NULL)
877                         {
878                         if (!results)
879                                 {
880                                 BN_print(bp,a);
881                                 BIO_puts(bp," ^ ");
882                                 BN_print(bp,b);
883                                 BIO_puts(bp," - ");
884                                 }
885                         BN_print(bp,d);
886                         BIO_puts(bp,"\n");
887                         }
888                 BN_one(e);
889                 for( ; !BN_is_zero(b) ; BN_sub(b,b,one))
890                     BN_mul(e,e,a,ctx);
891                 BN_sub(e,e,d);
892                 if(!BN_is_zero(e))
893                     {
894                     fprintf(stderr,"Exponentiation test failed!\n");
895                     return 0;
896                     }
897                 }
898         BN_free(a);
899         BN_free(b);
900         BN_free(d);
901         BN_free(e);
902         BN_free(one);
903         return(1);
904         }
905
906 static void genprime_cb(int p, int n, void *arg)
907         {
908         char c='*';
909
910         if (p == 0) c='.';
911         if (p == 1) c='+';
912         if (p == 2) c='*';
913         if (p == 3) c='\n';
914         putc(c, stderr);
915         fflush(stderr);
916         (void)n;
917         (void)arg;
918         }
919
920 int test_kron(BIO *bp, BN_CTX *ctx)
921         {
922         BIGNUM *a,*b,*r;
923         int i;
924         int legendre, kronecker;
925         int ret = 0;
926
927         a = BN_new();
928         b = BN_new();
929         r = BN_new();
930         if (a == NULL || b == NULL || r == NULL) goto err;
931         
932         /* We test BN_kronecker(a, b, ctx) just for  b  odd (Jacobi symbol).
933          * In this case we know that if  b  is prime, then BN_kronecker(a, b, ctx)
934          * is congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol).
935          * So we generate a random prime  b  and compare these values
936          * for a number of random  a's.  (That is, we run the Solovay-Strassen
937          * primality test to confirm that  b  is prime, except that we
938          * don't want to test whether  b  is prime but whether BN_kronecker
939          * works.) */
940
941         if (!BN_generate_prime(b, 512, 0, NULL, NULL, genprime_cb, NULL)) goto err;
942         putc('\n', stderr);
943         if (1 != BN_is_prime(b, 10, NULL, ctx, NULL))
944                 {
945                 fprintf(stderr, "BN_is_prime failed\n");
946                 goto err;
947                 }
948
949         for (i = 0; i < num0; i++)
950                 {
951                 if (!BN_rand(a, 512, 0, 0)) goto err;
952                 if (!BN_nnmod(a, a, b, ctx)) goto err;
953                 
954                 /* r := (b-1)/2  (note that b is odd) */
955                 if (!BN_copy(r, b)) goto err;
956                 if (!BN_sub_word(r, 1)) goto err;
957                 if (!BN_rshift1(r, r)) goto err;
958                 /* r := a^r mod b */
959                 if (!BN_mod_exp(r, a, r, b, ctx)) goto err;
960
961                 if (BN_is_word(r, 1))
962                         legendre = 1;
963                 else
964                         {
965                         if (!BN_add_word(r, 1)) goto err;
966                         if (0 != BN_cmp(r, b))
967                                 {
968                                 fprintf(stderr, "Legendre symbol computation failed\n");
969                                 goto err;
970                                 }
971                         legendre = -1;
972                         }
973
974                 kronecker = BN_kronecker(a, b, ctx);
975                 if (kronecker < -1) goto err;
976                 
977                 if (legendre != kronecker)
978                         {
979                         fprintf(stderr, "legendre != kronecker; a = ");
980                         BN_print_fp(stderr, a);
981                         fprintf(stderr, ", a = ");
982                         BN_print_fp(stderr, b);
983                         fprintf(stderr, "\n");
984                         goto err;
985                         }
986
987                 putc('.', stderr);
988                 fflush(stderr);
989                 }
990
991         putc('\n', stderr);
992         fflush(stderr);
993         ret = 1;
994  err:
995         if (a != NULL) BN_free(a);
996         if (b != NULL) BN_free(b);
997         if (r != NULL) BN_free(r);
998         return ret;
999         }
1000
1001 int test_lshift(BIO *bp,BN_CTX *ctx,BIGNUM *a_)
1002         {
1003         BIGNUM *a,*b,*c,*d;
1004         int i;
1005
1006         b=BN_new();
1007         c=BN_new();
1008         d=BN_new();
1009         BN_one(c);
1010
1011         if(a_)
1012             a=a_;
1013         else
1014             {
1015             a=BN_new();
1016             BN_rand(a,200,0,0); /**/
1017             a->neg=rand_neg();
1018             }
1019         for (i=0; i<num0; i++)
1020                 {
1021                 BN_lshift(b,a,i+1);
1022                 BN_add(c,c,c);
1023                 if (bp != NULL)
1024                         {
1025                         if (!results)
1026                                 {
1027                                 BN_print(bp,a);
1028                                 BIO_puts(bp," * ");
1029                                 BN_print(bp,c);
1030                                 BIO_puts(bp," - ");
1031                                 }
1032                         BN_print(bp,b);
1033                         BIO_puts(bp,"\n");
1034                         }
1035                 BN_mul(d,a,c,ctx);
1036                 BN_sub(d,d,b);
1037                 if(!BN_is_zero(d))
1038                     {
1039                     fprintf(stderr,"Left shift test failed!\n");
1040                     fprintf(stderr,"a=");
1041                     BN_print_fp(stderr,a);
1042                     fprintf(stderr,"\nb=");
1043                     BN_print_fp(stderr,b);
1044                     fprintf(stderr,"\nc=");
1045                     BN_print_fp(stderr,c);
1046                     fprintf(stderr,"\nd=");
1047                     BN_print_fp(stderr,d);
1048                     fprintf(stderr,"\n");
1049                     return 0;
1050                     }
1051                 }
1052         BN_free(a);
1053         BN_free(b);
1054         BN_free(c);
1055         BN_free(d);
1056         return(1);
1057         }
1058
1059 int test_lshift1(BIO *bp)
1060         {
1061         BIGNUM *a,*b,*c;
1062         int i;
1063
1064         a=BN_new();
1065         b=BN_new();
1066         c=BN_new();
1067
1068         BN_rand(a,200,0,0); /**/
1069         a->neg=rand_neg();
1070         for (i=0; i<num0; i++)
1071                 {
1072                 BN_lshift1(b,a);
1073                 if (bp != NULL)
1074                         {
1075                         if (!results)
1076                                 {
1077                                 BN_print(bp,a);
1078                                 BIO_puts(bp," * 2");
1079                                 BIO_puts(bp," - ");
1080                                 }
1081                         BN_print(bp,b);
1082                         BIO_puts(bp,"\n");
1083                         }
1084                 BN_add(c,a,a);
1085                 BN_sub(a,b,c);
1086                 if(!BN_is_zero(a))
1087                     {
1088                     fprintf(stderr,"Left shift one test failed!\n");
1089                     return 0;
1090                     }
1091                 
1092                 BN_copy(a,b);
1093                 }
1094         BN_free(a);
1095         BN_free(b);
1096         BN_free(c);
1097         return(1);
1098         }
1099
1100 int test_rshift(BIO *bp,BN_CTX *ctx)
1101         {
1102         BIGNUM *a,*b,*c,*d,*e;
1103         int i;
1104
1105         a=BN_new();
1106         b=BN_new();
1107         c=BN_new();
1108         d=BN_new();
1109         e=BN_new();
1110         BN_one(c);
1111
1112         BN_rand(a,200,0,0); /**/
1113         a->neg=rand_neg();
1114         for (i=0; i<num0; i++)
1115                 {
1116                 BN_rshift(b,a,i+1);
1117                 BN_add(c,c,c);
1118                 if (bp != NULL)
1119                         {
1120                         if (!results)
1121                                 {
1122                                 BN_print(bp,a);
1123                                 BIO_puts(bp," / ");
1124                                 BN_print(bp,c);
1125                                 BIO_puts(bp," - ");
1126                                 }
1127                         BN_print(bp,b);
1128                         BIO_puts(bp,"\n");
1129                         }
1130                 BN_div(d,e,a,c,ctx);
1131                 BN_sub(d,d,b);
1132                 if(!BN_is_zero(d))
1133                     {
1134                     fprintf(stderr,"Right shift test failed!\n");
1135                     return 0;
1136                     }
1137                 }
1138         BN_free(a);
1139         BN_free(b);
1140         BN_free(c);
1141         BN_free(d);
1142         BN_free(e);
1143         return(1);
1144         }
1145
1146 int test_rshift1(BIO *bp)
1147         {
1148         BIGNUM *a,*b,*c;
1149         int i;
1150
1151         a=BN_new();
1152         b=BN_new();
1153         c=BN_new();
1154
1155         BN_rand(a,200,0,0); /**/
1156         a->neg=rand_neg();
1157         for (i=0; i<num0; i++)
1158                 {
1159                 BN_rshift1(b,a);
1160                 if (bp != NULL)
1161                         {
1162                         if (!results)
1163                                 {
1164                                 BN_print(bp,a);
1165                                 BIO_puts(bp," / 2");
1166                                 BIO_puts(bp," - ");
1167                                 }
1168                         BN_print(bp,b);
1169                         BIO_puts(bp,"\n");
1170                         }
1171                 BN_sub(c,a,b);
1172                 BN_sub(c,c,b);
1173                 if(!BN_is_zero(c) && !BN_is_one(c))
1174                     {
1175                     fprintf(stderr,"Right shift one test failed!\n");
1176                     return 0;
1177                     }
1178                 BN_copy(a,b);
1179                 }
1180         BN_free(a);
1181         BN_free(b);
1182         BN_free(c);
1183         return(1);
1184         }
1185
1186 int rand_neg(void)
1187         {
1188         static unsigned int neg=0;
1189         static int sign[8]={0,0,0,1,1,0,1,1};
1190
1191         return(sign[(neg++)%8]);
1192         }