This is a first-cut at improving the callback mechanisms used in
[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  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60  *
61  * Portions of the attached software ("Contribution") are developed by 
62  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
63  *
64  * The Contribution is licensed pursuant to the Eric Young open source
65  * license provided above.
66  *
67  * The binary polynomial arithmetic software is originally written by 
68  * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
69  *
70  */
71
72 /* Until the key-gen callbacks are modified to use newer prototypes, we allow
73  * deprecated functions for openssl-internal code */
74 #ifdef OPENSSL_NO_DEPRECATED
75 #undef OPENSSL_NO_DEPRECATED
76 #endif
77
78 #include <stdio.h>
79 #include <stdlib.h>
80 #include <string.h>
81
82 #include "e_os.h"
83
84 #include <openssl/bio.h>
85 #include <openssl/bn.h>
86 #include <openssl/rand.h>
87 #include <openssl/x509.h>
88 #include <openssl/err.h>
89
90 #ifdef OPENSSL_SYS_WINDOWS
91 #include "../bio/bss_file.c"
92 #endif
93
94 const int num0 = 100; /* number of tests */
95 const int num1 = 50;  /* additional tests for some functions */
96 const int num2 = 5;   /* number of tests for slow functions */
97
98 int test_add(BIO *bp);
99 int test_sub(BIO *bp);
100 int test_lshift1(BIO *bp);
101 int test_lshift(BIO *bp,BN_CTX *ctx,BIGNUM *a_);
102 int test_rshift1(BIO *bp);
103 int test_rshift(BIO *bp,BN_CTX *ctx);
104 int test_div(BIO *bp,BN_CTX *ctx);
105 int test_div_recp(BIO *bp,BN_CTX *ctx);
106 int test_mul(BIO *bp);
107 int test_sqr(BIO *bp,BN_CTX *ctx);
108 int test_mont(BIO *bp,BN_CTX *ctx);
109 int test_mod(BIO *bp,BN_CTX *ctx);
110 int test_mod_mul(BIO *bp,BN_CTX *ctx);
111 int test_mod_exp(BIO *bp,BN_CTX *ctx);
112 int test_exp(BIO *bp,BN_CTX *ctx);
113 int test_gf2m_add(BIO *bp);
114 int test_gf2m_mod(BIO *bp);
115 int test_gf2m_mod_mul(BIO *bp,BN_CTX *ctx);
116 int test_gf2m_mod_sqr(BIO *bp,BN_CTX *ctx);
117 int test_gf2m_mod_inv(BIO *bp,BN_CTX *ctx);
118 int test_gf2m_mod_div(BIO *bp,BN_CTX *ctx);
119 int test_gf2m_mod_exp(BIO *bp,BN_CTX *ctx);
120 int test_gf2m_mod_sqrt(BIO *bp,BN_CTX *ctx);
121 int test_gf2m_mod_solve_quad(BIO *bp,BN_CTX *ctx);
122 int test_kron(BIO *bp,BN_CTX *ctx);
123 int test_sqrt(BIO *bp,BN_CTX *ctx);
124 int rand_neg(void);
125 static int results=0;
126
127 #ifdef OPENSSL_NO_STDIO
128 #define APPS_WIN16
129 #include "bss_file.c"
130 #endif
131
132 static unsigned char lst[]="\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
133 "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
134
135 static const char rnd_seed[] = "string to make the random number generator think it has entropy";
136
137 static void message(BIO *out, char *m)
138         {
139         fprintf(stderr, "test %s\n", m);
140         BIO_puts(out, "print \"test ");
141         BIO_puts(out, m);
142         BIO_puts(out, "\\n\"\n");
143         }
144
145 int main(int argc, char *argv[])
146         {
147         BN_CTX *ctx;
148         BIO *out;
149         char *outfile=NULL;
150
151         results = 0;
152
153         RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
154
155         argc--;
156         argv++;
157         while (argc >= 1)
158                 {
159                 if (strcmp(*argv,"-results") == 0)
160                         results=1;
161                 else if (strcmp(*argv,"-out") == 0)
162                         {
163                         if (--argc < 1) break;
164                         outfile= *(++argv);
165                         }
166                 argc--;
167                 argv++;
168                 }
169
170
171         ctx=BN_CTX_new();
172         if (ctx == NULL) EXIT(1);
173
174         out=BIO_new(BIO_s_file());
175         if (out == NULL) EXIT(1);
176         if (outfile == NULL)
177                 {
178                 BIO_set_fp(out,stdout,BIO_NOCLOSE);
179                 }
180         else
181                 {
182                 if (!BIO_write_filename(out,outfile))
183                         {
184                         perror(outfile);
185                         EXIT(1);
186                         }
187                 }
188
189         if (!results)
190                 BIO_puts(out,"obase=16\nibase=16\n");
191
192         message(out,"BN_add");
193         if (!test_add(out)) goto err;
194         BIO_flush(out);
195
196         message(out,"BN_sub");
197         if (!test_sub(out)) goto err;
198         BIO_flush(out);
199
200         message(out,"BN_lshift1");
201         if (!test_lshift1(out)) goto err;
202         BIO_flush(out);
203
204         message(out,"BN_lshift (fixed)");
205         if (!test_lshift(out,ctx,BN_bin2bn(lst,sizeof(lst)-1,NULL)))
206             goto err;
207         BIO_flush(out);
208
209         message(out,"BN_lshift");
210         if (!test_lshift(out,ctx,NULL)) goto err;
211         BIO_flush(out);
212
213         message(out,"BN_rshift1");
214         if (!test_rshift1(out)) goto err;
215         BIO_flush(out);
216
217         message(out,"BN_rshift");
218         if (!test_rshift(out,ctx)) goto err;
219         BIO_flush(out);
220
221         message(out,"BN_sqr");
222         if (!test_sqr(out,ctx)) goto err;
223         BIO_flush(out);
224
225         message(out,"BN_mul");
226         if (!test_mul(out)) goto err;
227         BIO_flush(out);
228
229         message(out,"BN_div");
230         if (!test_div(out,ctx)) goto err;
231         BIO_flush(out);
232
233         message(out,"BN_div_recp");
234         if (!test_div_recp(out,ctx)) goto err;
235         BIO_flush(out);
236
237         message(out,"BN_mod");
238         if (!test_mod(out,ctx)) goto err;
239         BIO_flush(out);
240
241         message(out,"BN_mod_mul");
242         if (!test_mod_mul(out,ctx)) goto err;
243         BIO_flush(out);
244
245         message(out,"BN_mont");
246         if (!test_mont(out,ctx)) goto err;
247         BIO_flush(out);
248
249         message(out,"BN_mod_exp");
250         if (!test_mod_exp(out,ctx)) goto err;
251         BIO_flush(out);
252
253         message(out,"BN_exp");
254         if (!test_exp(out,ctx)) goto err;
255         BIO_flush(out);
256
257         message(out,"BN_kronecker");
258         if (!test_kron(out,ctx)) goto err;
259         BIO_flush(out);
260
261         message(out,"BN_mod_sqrt");
262         if (!test_sqrt(out,ctx)) goto err;
263         BIO_flush(out);
264
265         message(out,"BN_GF2m_add");
266         if (!test_gf2m_add(out)) goto err;
267         BIO_flush(out);
268
269         message(out,"BN_GF2m_mod");
270         if (!test_gf2m_mod(out)) goto err;
271         BIO_flush(out);
272
273         message(out,"BN_GF2m_mod_mul");
274         if (!test_gf2m_mod_mul(out,ctx)) goto err;
275         BIO_flush(out);
276
277         message(out,"BN_GF2m_mod_sqr");
278         if (!test_gf2m_mod_sqr(out,ctx)) goto err;
279         BIO_flush(out);
280
281         message(out,"BN_GF2m_mod_inv");
282         if (!test_gf2m_mod_inv(out,ctx)) goto err;
283         BIO_flush(out);
284
285         message(out,"BN_GF2m_mod_div");
286         if (!test_gf2m_mod_div(out,ctx)) goto err;
287         BIO_flush(out);
288
289         message(out,"BN_GF2m_mod_exp");
290         if (!test_gf2m_mod_exp(out,ctx)) goto err;
291         BIO_flush(out);
292
293         message(out,"BN_GF2m_mod_sqrt");
294         if (!test_gf2m_mod_sqrt(out,ctx)) goto err;
295         BIO_flush(out);
296
297         message(out,"BN_GF2m_mod_solve_quad");
298         if (!test_gf2m_mod_solve_quad(out,ctx)) goto err;
299         BIO_flush(out);
300
301         BN_CTX_free(ctx);
302         BIO_free(out);
303
304 /**/
305         EXIT(0);
306 err:
307         BIO_puts(out,"1\n"); /* make sure the Perl script fed by bc notices
308                               * the failure, see test_bn in test/Makefile.ssl*/
309         BIO_flush(out);
310         ERR_load_crypto_strings();
311         ERR_print_errors_fp(stderr);
312         EXIT(1);
313         return(1);
314         }
315
316 int test_add(BIO *bp)
317         {
318         BIGNUM a,b,c;
319         int i;
320
321         BN_init(&a);
322         BN_init(&b);
323         BN_init(&c);
324
325         BN_bntest_rand(&a,512,0,0);
326         for (i=0; i<num0; i++)
327                 {
328                 BN_bntest_rand(&b,450+i,0,0);
329                 a.neg=rand_neg();
330                 b.neg=rand_neg();
331                 BN_add(&c,&a,&b);
332                 if (bp != NULL)
333                         {
334                         if (!results)
335                                 {
336                                 BN_print(bp,&a);
337                                 BIO_puts(bp," + ");
338                                 BN_print(bp,&b);
339                                 BIO_puts(bp," - ");
340                                 }
341                         BN_print(bp,&c);
342                         BIO_puts(bp,"\n");
343                         }
344                 a.neg=!a.neg;
345                 b.neg=!b.neg;
346                 BN_add(&c,&c,&b);
347                 BN_add(&c,&c,&a);
348                 if(!BN_is_zero(&c))
349                     {
350                     fprintf(stderr,"Add test failed!\n");
351                     return 0;
352                     }
353                 }
354         BN_free(&a);
355         BN_free(&b);
356         BN_free(&c);
357         return(1);
358         }
359
360 int test_sub(BIO *bp)
361         {
362         BIGNUM a,b,c;
363         int i;
364
365         BN_init(&a);
366         BN_init(&b);
367         BN_init(&c);
368
369         for (i=0; i<num0+num1; i++)
370                 {
371                 if (i < num1)
372                         {
373                         BN_bntest_rand(&a,512,0,0);
374                         BN_copy(&b,&a);
375                         if (BN_set_bit(&a,i)==0) return(0);
376                         BN_add_word(&b,i);
377                         }
378                 else
379                         {
380                         BN_bntest_rand(&b,400+i-num1,0,0);
381                         a.neg=rand_neg();
382                         b.neg=rand_neg();
383                         }
384                 BN_sub(&c,&a,&b);
385                 if (bp != NULL)
386                         {
387                         if (!results)
388                                 {
389                                 BN_print(bp,&a);
390                                 BIO_puts(bp," - ");
391                                 BN_print(bp,&b);
392                                 BIO_puts(bp," - ");
393                                 }
394                         BN_print(bp,&c);
395                         BIO_puts(bp,"\n");
396                         }
397                 BN_add(&c,&c,&b);
398                 BN_sub(&c,&c,&a);
399                 if(!BN_is_zero(&c))
400                     {
401                     fprintf(stderr,"Subtract test failed!\n");
402                     return 0;
403                     }
404                 }
405         BN_free(&a);
406         BN_free(&b);
407         BN_free(&c);
408         return(1);
409         }
410
411 int test_div(BIO *bp, BN_CTX *ctx)
412         {
413         BIGNUM a,b,c,d,e;
414         int i;
415
416         BN_init(&a);
417         BN_init(&b);
418         BN_init(&c);
419         BN_init(&d);
420         BN_init(&e);
421
422         for (i=0; i<num0+num1; i++)
423                 {
424                 if (i < num1)
425                         {
426                         BN_bntest_rand(&a,400,0,0);
427                         BN_copy(&b,&a);
428                         BN_lshift(&a,&a,i);
429                         BN_add_word(&a,i);
430                         }
431                 else
432                         BN_bntest_rand(&b,50+3*(i-num1),0,0);
433                 a.neg=rand_neg();
434                 b.neg=rand_neg();
435                 BN_div(&d,&c,&a,&b,ctx);
436                 if (bp != NULL)
437                         {
438                         if (!results)
439                                 {
440                                 BN_print(bp,&a);
441                                 BIO_puts(bp," / ");
442                                 BN_print(bp,&b);
443                                 BIO_puts(bp," - ");
444                                 }
445                         BN_print(bp,&d);
446                         BIO_puts(bp,"\n");
447
448                         if (!results)
449                                 {
450                                 BN_print(bp,&a);
451                                 BIO_puts(bp," % ");
452                                 BN_print(bp,&b);
453                                 BIO_puts(bp," - ");
454                                 }
455                         BN_print(bp,&c);
456                         BIO_puts(bp,"\n");
457                         }
458                 BN_mul(&e,&d,&b,ctx);
459                 BN_add(&d,&e,&c);
460                 BN_sub(&d,&d,&a);
461                 if(!BN_is_zero(&d))
462                     {
463                     fprintf(stderr,"Division test failed!\n");
464                     return 0;
465                     }
466                 }
467         BN_free(&a);
468         BN_free(&b);
469         BN_free(&c);
470         BN_free(&d);
471         BN_free(&e);
472         return(1);
473         }
474
475 int test_div_recp(BIO *bp, BN_CTX *ctx)
476         {
477         BIGNUM a,b,c,d,e;
478         BN_RECP_CTX recp;
479         int i;
480
481         BN_RECP_CTX_init(&recp);
482         BN_init(&a);
483         BN_init(&b);
484         BN_init(&c);
485         BN_init(&d);
486         BN_init(&e);
487
488         for (i=0; i<num0+num1; i++)
489                 {
490                 if (i < num1)
491                         {
492                         BN_bntest_rand(&a,400,0,0);
493                         BN_copy(&b,&a);
494                         BN_lshift(&a,&a,i);
495                         BN_add_word(&a,i);
496                         }
497                 else
498                         BN_bntest_rand(&b,50+3*(i-num1),0,0);
499                 a.neg=rand_neg();
500                 b.neg=rand_neg();
501                 BN_RECP_CTX_set(&recp,&b,ctx);
502                 BN_div_recp(&d,&c,&a,&recp,ctx);
503                 if (bp != NULL)
504                         {
505                         if (!results)
506                                 {
507                                 BN_print(bp,&a);
508                                 BIO_puts(bp," / ");
509                                 BN_print(bp,&b);
510                                 BIO_puts(bp," - ");
511                                 }
512                         BN_print(bp,&d);
513                         BIO_puts(bp,"\n");
514
515                         if (!results)
516                                 {
517                                 BN_print(bp,&a);
518                                 BIO_puts(bp," % ");
519                                 BN_print(bp,&b);
520                                 BIO_puts(bp," - ");
521                                 }
522                         BN_print(bp,&c);
523                         BIO_puts(bp,"\n");
524                         }
525                 BN_mul(&e,&d,&b,ctx);
526                 BN_add(&d,&e,&c);
527                 BN_sub(&d,&d,&a);
528                 if(!BN_is_zero(&d))
529                     {
530                     fprintf(stderr,"Reciprocal division test failed!\n");
531                     fprintf(stderr,"a=");
532                     BN_print_fp(stderr,&a);
533                     fprintf(stderr,"\nb=");
534                     BN_print_fp(stderr,&b);
535                     fprintf(stderr,"\n");
536                     return 0;
537                     }
538                 }
539         BN_free(&a);
540         BN_free(&b);
541         BN_free(&c);
542         BN_free(&d);
543         BN_free(&e);
544         BN_RECP_CTX_free(&recp);
545         return(1);
546         }
547
548 int test_mul(BIO *bp)
549         {
550         BIGNUM a,b,c,d,e;
551         int i;
552         BN_CTX *ctx;
553
554         ctx = BN_CTX_new();
555         if (ctx == NULL) EXIT(1);
556         
557         BN_init(&a);
558         BN_init(&b);
559         BN_init(&c);
560         BN_init(&d);
561         BN_init(&e);
562
563         for (i=0; i<num0+num1; i++)
564                 {
565                 if (i <= num1)
566                         {
567                         BN_bntest_rand(&a,100,0,0);
568                         BN_bntest_rand(&b,100,0,0);
569                         }
570                 else
571                         BN_bntest_rand(&b,i-num1,0,0);
572                 a.neg=rand_neg();
573                 b.neg=rand_neg();
574                 BN_mul(&c,&a,&b,ctx);
575                 if (bp != NULL)
576                         {
577                         if (!results)
578                                 {
579                                 BN_print(bp,&a);
580                                 BIO_puts(bp," * ");
581                                 BN_print(bp,&b);
582                                 BIO_puts(bp," - ");
583                                 }
584                         BN_print(bp,&c);
585                         BIO_puts(bp,"\n");
586                         }
587                 BN_div(&d,&e,&c,&a,ctx);
588                 BN_sub(&d,&d,&b);
589                 if(!BN_is_zero(&d) || !BN_is_zero(&e))
590                     {
591                     fprintf(stderr,"Multiplication test failed!\n");
592                     return 0;
593                     }
594                 }
595         BN_free(&a);
596         BN_free(&b);
597         BN_free(&c);
598         BN_free(&d);
599         BN_free(&e);
600         BN_CTX_free(ctx);
601         return(1);
602         }
603
604 int test_sqr(BIO *bp, BN_CTX *ctx)
605         {
606         BIGNUM a,c,d,e;
607         int i;
608
609         BN_init(&a);
610         BN_init(&c);
611         BN_init(&d);
612         BN_init(&e);
613
614         for (i=0; i<num0; i++)
615                 {
616                 BN_bntest_rand(&a,40+i*10,0,0);
617                 a.neg=rand_neg();
618                 BN_sqr(&c,&a,ctx);
619                 if (bp != NULL)
620                         {
621                         if (!results)
622                                 {
623                                 BN_print(bp,&a);
624                                 BIO_puts(bp," * ");
625                                 BN_print(bp,&a);
626                                 BIO_puts(bp," - ");
627                                 }
628                         BN_print(bp,&c);
629                         BIO_puts(bp,"\n");
630                         }
631                 BN_div(&d,&e,&c,&a,ctx);
632                 BN_sub(&d,&d,&a);
633                 if(!BN_is_zero(&d) || !BN_is_zero(&e))
634                     {
635                     fprintf(stderr,"Square test failed!\n");
636                     return 0;
637                     }
638                 }
639         BN_free(&a);
640         BN_free(&c);
641         BN_free(&d);
642         BN_free(&e);
643         return(1);
644         }
645
646 int test_mont(BIO *bp, BN_CTX *ctx)
647         {
648         BIGNUM a,b,c,d,A,B;
649         BIGNUM n;
650         int i;
651         BN_MONT_CTX *mont;
652
653         BN_init(&a);
654         BN_init(&b);
655         BN_init(&c);
656         BN_init(&d);
657         BN_init(&A);
658         BN_init(&B);
659         BN_init(&n);
660
661         mont=BN_MONT_CTX_new();
662
663         BN_bntest_rand(&a,100,0,0); /**/
664         BN_bntest_rand(&b,100,0,0); /**/
665         for (i=0; i<num2; i++)
666                 {
667                 int bits = (200*(i+1))/num2;
668
669                 if (bits == 0)
670                         continue;
671                 BN_bntest_rand(&n,bits,0,1);
672                 BN_MONT_CTX_set(mont,&n,ctx);
673
674                 BN_nnmod(&a,&a,&n,ctx);
675                 BN_nnmod(&b,&b,&n,ctx);
676
677                 BN_to_montgomery(&A,&a,mont,ctx);
678                 BN_to_montgomery(&B,&b,mont,ctx);
679
680                 BN_mod_mul_montgomery(&c,&A,&B,mont,ctx);/**/
681                 BN_from_montgomery(&A,&c,mont,ctx);/**/
682                 if (bp != NULL)
683                         {
684                         if (!results)
685                                 {
686 #ifdef undef
687 fprintf(stderr,"%d * %d %% %d\n",
688 BN_num_bits(&a),
689 BN_num_bits(&b),
690 BN_num_bits(mont->N));
691 #endif
692                                 BN_print(bp,&a);
693                                 BIO_puts(bp," * ");
694                                 BN_print(bp,&b);
695                                 BIO_puts(bp," % ");
696                                 BN_print(bp,&(mont->N));
697                                 BIO_puts(bp," - ");
698                                 }
699                         BN_print(bp,&A);
700                         BIO_puts(bp,"\n");
701                         }
702                 BN_mod_mul(&d,&a,&b,&n,ctx);
703                 BN_sub(&d,&d,&A);
704                 if(!BN_is_zero(&d))
705                     {
706                     fprintf(stderr,"Montgomery multiplication test failed!\n");
707                     return 0;
708                     }
709                 }
710         BN_MONT_CTX_free(mont);
711         BN_free(&a);
712         BN_free(&b);
713         BN_free(&c);
714         BN_free(&d);
715         BN_free(&A);
716         BN_free(&B);
717         BN_free(&n);
718         return(1);
719         }
720
721 int test_mod(BIO *bp, BN_CTX *ctx)
722         {
723         BIGNUM *a,*b,*c,*d,*e;
724         int i;
725
726         a=BN_new();
727         b=BN_new();
728         c=BN_new();
729         d=BN_new();
730         e=BN_new();
731
732         BN_bntest_rand(a,1024,0,0); /**/
733         for (i=0; i<num0; i++)
734                 {
735                 BN_bntest_rand(b,450+i*10,0,0); /**/
736                 a->neg=rand_neg();
737                 b->neg=rand_neg();
738                 BN_mod(c,a,b,ctx);/**/
739                 if (bp != NULL)
740                         {
741                         if (!results)
742                                 {
743                                 BN_print(bp,a);
744                                 BIO_puts(bp," % ");
745                                 BN_print(bp,b);
746                                 BIO_puts(bp," - ");
747                                 }
748                         BN_print(bp,c);
749                         BIO_puts(bp,"\n");
750                         }
751                 BN_div(d,e,a,b,ctx);
752                 BN_sub(e,e,c);
753                 if(!BN_is_zero(e))
754                     {
755                     fprintf(stderr,"Modulo test failed!\n");
756                     return 0;
757                     }
758                 }
759         BN_free(a);
760         BN_free(b);
761         BN_free(c);
762         BN_free(d);
763         BN_free(e);
764         return(1);
765         }
766
767 int test_mod_mul(BIO *bp, BN_CTX *ctx)
768         {
769         BIGNUM *a,*b,*c,*d,*e;
770         int i,j;
771
772         a=BN_new();
773         b=BN_new();
774         c=BN_new();
775         d=BN_new();
776         e=BN_new();
777
778         for (j=0; j<3; j++) {
779         BN_bntest_rand(c,1024,0,0); /**/
780         for (i=0; i<num0; i++)
781                 {
782                 BN_bntest_rand(a,475+i*10,0,0); /**/
783                 BN_bntest_rand(b,425+i*11,0,0); /**/
784                 a->neg=rand_neg();
785                 b->neg=rand_neg();
786                 if (!BN_mod_mul(e,a,b,c,ctx))
787                         {
788                         unsigned long l;
789
790                         while ((l=ERR_get_error()))
791                                 fprintf(stderr,"ERROR:%s\n",
792                                         ERR_error_string(l,NULL));
793                         EXIT(1);
794                         }
795                 if (bp != NULL)
796                         {
797                         if (!results)
798                                 {
799                                 BN_print(bp,a);
800                                 BIO_puts(bp," * ");
801                                 BN_print(bp,b);
802                                 BIO_puts(bp," % ");
803                                 BN_print(bp,c);
804                                 if ((a->neg ^ b->neg) && !BN_is_zero(e))
805                                         {
806                                         /* If  (a*b) % c  is negative,  c  must be added
807                                          * in order to obtain the normalized remainder
808                                          * (new with OpenSSL 0.9.7, previous versions of
809                                          * BN_mod_mul could generate negative results)
810                                          */
811                                         BIO_puts(bp," + ");
812                                         BN_print(bp,c);
813                                         }
814                                 BIO_puts(bp," - ");
815                                 }
816                         BN_print(bp,e);
817                         BIO_puts(bp,"\n");
818                         }
819                 BN_mul(d,a,b,ctx);
820                 BN_sub(d,d,e);
821                 BN_div(a,b,d,c,ctx);
822                 if(!BN_is_zero(b))
823                     {
824                     fprintf(stderr,"Modulo multiply test failed!\n");
825                     ERR_print_errors_fp(stderr);
826                     return 0;
827                     }
828                 }
829         }
830         BN_free(a);
831         BN_free(b);
832         BN_free(c);
833         BN_free(d);
834         BN_free(e);
835         return(1);
836         }
837
838 int test_mod_exp(BIO *bp, BN_CTX *ctx)
839         {
840         BIGNUM *a,*b,*c,*d,*e;
841         int i;
842
843         a=BN_new();
844         b=BN_new();
845         c=BN_new();
846         d=BN_new();
847         e=BN_new();
848
849         BN_bntest_rand(c,30,0,1); /* must be odd for montgomery */
850         for (i=0; i<num2; i++)
851                 {
852                 BN_bntest_rand(a,20+i*5,0,0); /**/
853                 BN_bntest_rand(b,2+i,0,0); /**/
854
855                 if (!BN_mod_exp(d,a,b,c,ctx))
856                         return(00);
857
858                 if (bp != NULL)
859                         {
860                         if (!results)
861                                 {
862                                 BN_print(bp,a);
863                                 BIO_puts(bp," ^ ");
864                                 BN_print(bp,b);
865                                 BIO_puts(bp," % ");
866                                 BN_print(bp,c);
867                                 BIO_puts(bp," - ");
868                                 }
869                         BN_print(bp,d);
870                         BIO_puts(bp,"\n");
871                         }
872                 BN_exp(e,a,b,ctx);
873                 BN_sub(e,e,d);
874                 BN_div(a,b,e,c,ctx);
875                 if(!BN_is_zero(b))
876                     {
877                     fprintf(stderr,"Modulo exponentiation test failed!\n");
878                     return 0;
879                     }
880                 }
881         BN_free(a);
882         BN_free(b);
883         BN_free(c);
884         BN_free(d);
885         BN_free(e);
886         return(1);
887         }
888
889 int test_exp(BIO *bp, BN_CTX *ctx)
890         {
891         BIGNUM *a,*b,*d,*e,*one;
892         int i;
893
894         a=BN_new();
895         b=BN_new();
896         d=BN_new();
897         e=BN_new();
898         one=BN_new();
899         BN_one(one);
900
901         for (i=0; i<num2; i++)
902                 {
903                 BN_bntest_rand(a,20+i*5,0,0); /**/
904                 BN_bntest_rand(b,2+i,0,0); /**/
905
906                 if (!BN_exp(d,a,b,ctx))
907                         return(00);
908
909                 if (bp != NULL)
910                         {
911                         if (!results)
912                                 {
913                                 BN_print(bp,a);
914                                 BIO_puts(bp," ^ ");
915                                 BN_print(bp,b);
916                                 BIO_puts(bp," - ");
917                                 }
918                         BN_print(bp,d);
919                         BIO_puts(bp,"\n");
920                         }
921                 BN_one(e);
922                 for( ; !BN_is_zero(b) ; BN_sub(b,b,one))
923                     BN_mul(e,e,a,ctx);
924                 BN_sub(e,e,d);
925                 if(!BN_is_zero(e))
926                     {
927                     fprintf(stderr,"Exponentiation test failed!\n");
928                     return 0;
929                     }
930                 }
931         BN_free(a);
932         BN_free(b);
933         BN_free(d);
934         BN_free(e);
935         BN_free(one);
936         return(1);
937         }
938
939 int test_gf2m_add(BIO *bp)
940         {
941         BIGNUM a,b,c;
942         int i, ret = 0;
943
944         BN_init(&a);
945         BN_init(&b);
946         BN_init(&c);
947
948         for (i=0; i<num0; i++)
949                 {
950                 BN_rand(&a,512,0,0);
951                 BN_copy(&b, BN_value_one());
952                 a.neg=rand_neg();
953                 b.neg=rand_neg();
954                 BN_GF2m_add(&c,&a,&b);
955 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
956                 if (bp != NULL)
957                         {
958                         if (!results)
959                                 {
960                                 BN_print(bp,&a);
961                                 BIO_puts(bp," ^ ");
962                                 BN_print(bp,&b);
963                                 BIO_puts(bp," = ");
964                                 }
965                         BN_print(bp,&c);
966                         BIO_puts(bp,"\n");
967                         }
968 #endif
969                 /* Test that two added values have the correct parity. */
970                 if((BN_is_odd(&a) && BN_is_odd(&c)) || (!BN_is_odd(&a) && !BN_is_odd(&c)))
971                         {
972                     fprintf(stderr,"GF(2^m) addition test (a) failed!\n");
973                         goto err;
974                         }
975                 BN_GF2m_add(&c,&c,&c);
976                 /* Test that c + c = 0. */
977                 if(!BN_is_zero(&c))
978                     {
979                     fprintf(stderr,"GF(2^m) addition test (b) failed!\n");
980                         goto err;
981                     }
982                 }
983         ret = 1;
984   err:
985         BN_free(&a);
986         BN_free(&b);
987         BN_free(&c);
988         return ret;
989         }
990
991 int test_gf2m_mod(BIO *bp)
992         {
993         BIGNUM *a,*b[2],*c,*d,*e;
994         int i, j, ret = 0;
995         unsigned int p0[] = {163,7,6,3,0};
996         unsigned int p1[] = {193,15,0};
997
998         a=BN_new();
999         b[0]=BN_new();
1000         b[1]=BN_new();
1001         c=BN_new();
1002         d=BN_new();
1003         e=BN_new();
1004
1005         BN_GF2m_arr2poly(p0, b[0]);
1006         BN_GF2m_arr2poly(p1, b[1]);
1007
1008         for (i=0; i<num0; i++)
1009                 {
1010                 BN_bntest_rand(a, 1024, 0, 0);
1011                 for (j=0; j < 2; j++)
1012                         {
1013                         BN_GF2m_mod(c, a, b[j]);
1014 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
1015                         if (bp != NULL)
1016                                 {
1017                                 if (!results)
1018                                         {
1019                                         BN_print(bp,a);
1020                                         BIO_puts(bp," % ");
1021                                         BN_print(bp,b[j]);
1022                                         BIO_puts(bp," - ");
1023                                         BN_print(bp,c);
1024                                         BIO_puts(bp,"\n");
1025                                         }
1026                                 }
1027 #endif
1028                         BN_GF2m_add(d, a, c);
1029                         BN_GF2m_mod(e, d, b[j]);
1030                         /* Test that a + (a mod p) mod p == 0. */
1031                         if(!BN_is_zero(e))
1032                                 {
1033                                 fprintf(stderr,"GF(2^m) modulo test failed!\n");
1034                                 goto err;
1035                                 }
1036                         }
1037                 }
1038         ret = 1;
1039   err:
1040         BN_free(a);
1041         BN_free(b[0]);
1042         BN_free(b[1]);
1043         BN_free(c);
1044         BN_free(d);
1045         BN_free(e);
1046         return ret;
1047         }
1048
1049 int test_gf2m_mod_mul(BIO *bp,BN_CTX *ctx)
1050         {
1051         BIGNUM *a,*b[2],*c,*d,*e,*f,*g,*h;
1052         int i, j, ret = 0;
1053         unsigned int p0[] = {163,7,6,3,0};
1054         unsigned int p1[] = {193,15,0};
1055
1056         a=BN_new();
1057         b[0]=BN_new();
1058         b[1]=BN_new();
1059         c=BN_new();
1060         d=BN_new();
1061         e=BN_new();
1062         f=BN_new();
1063         g=BN_new();
1064         h=BN_new();
1065
1066         BN_GF2m_arr2poly(p0, b[0]);
1067         BN_GF2m_arr2poly(p1, b[1]);
1068
1069         for (i=0; i<num0; i++)
1070                 {
1071                 BN_bntest_rand(a, 1024, 0, 0);
1072                 BN_bntest_rand(c, 1024, 0, 0);
1073                 BN_bntest_rand(d, 1024, 0, 0);
1074                 for (j=0; j < 2; j++)
1075                         {
1076                         BN_GF2m_mod_mul(e, a, c, b[j], ctx);
1077 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
1078                         if (bp != NULL)
1079                                 {
1080                                 if (!results)
1081                                         {
1082                                         BN_print(bp,a);
1083                                         BIO_puts(bp," * ");
1084                                         BN_print(bp,c);
1085                                         BIO_puts(bp," % ");
1086                                         BN_print(bp,b[j]);
1087                                         BIO_puts(bp," - ");
1088                                         BN_print(bp,e);
1089                                         BIO_puts(bp,"\n");
1090                                         }
1091                                 }
1092 #endif
1093                         BN_GF2m_add(f, a, d);
1094                         BN_GF2m_mod_mul(g, f, c, b[j], ctx);
1095                         BN_GF2m_mod_mul(h, d, c, b[j], ctx);
1096                         BN_GF2m_add(f, e, g);
1097                         BN_GF2m_add(f, f, h);
1098                         /* Test that (a+d)*c = a*c + d*c. */
1099                         if(!BN_is_zero(f))
1100                                 {
1101                                 fprintf(stderr,"GF(2^m) modular multiplication test failed!\n");
1102                                 goto err;
1103                                 }
1104                         }
1105                 }
1106         ret = 1;
1107   err:
1108         BN_free(a);
1109         BN_free(b[0]);
1110         BN_free(b[1]);
1111         BN_free(c);
1112         BN_free(d);
1113         BN_free(e);
1114         BN_free(f);
1115         BN_free(g);
1116         BN_free(h);
1117         return ret;
1118         }
1119
1120 int test_gf2m_mod_sqr(BIO *bp,BN_CTX *ctx)
1121         {
1122         BIGNUM *a,*b[2],*c,*d;
1123         int i, j, ret = 0;
1124         unsigned int p0[] = {163,7,6,3,0};
1125         unsigned int p1[] = {193,15,0};
1126
1127         a=BN_new();
1128         b[0]=BN_new();
1129         b[1]=BN_new();
1130         c=BN_new();
1131         d=BN_new();
1132
1133         BN_GF2m_arr2poly(p0, b[0]);
1134         BN_GF2m_arr2poly(p1, b[1]);
1135
1136         for (i=0; i<num0; i++)
1137                 {
1138                 BN_bntest_rand(a, 1024, 0, 0);
1139                 for (j=0; j < 2; j++)
1140                         {
1141                         BN_GF2m_mod_sqr(c, a, b[j], ctx);
1142                         BN_copy(d, a);
1143                         BN_GF2m_mod_mul(d, a, d, b[j], ctx);
1144 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
1145                         if (bp != NULL)
1146                                 {
1147                                 if (!results)
1148                                         {
1149                                         BN_print(bp,a);
1150                                         BIO_puts(bp," ^ 2 % ");
1151                                         BN_print(bp,b[j]);
1152                                         BIO_puts(bp, " = ");
1153                                         BN_print(bp,c);
1154                                         BIO_puts(bp,"; a * a = ");
1155                                         BN_print(bp,d);
1156                                         BIO_puts(bp,"\n");
1157                                         }
1158                                 }
1159 #endif
1160                         BN_GF2m_add(d, c, d);
1161                         /* Test that a*a = a^2. */
1162                         if(!BN_is_zero(d))
1163                                 {
1164                                 fprintf(stderr,"GF(2^m) modular squaring test failed!\n");
1165                                 goto err;
1166                                 }
1167                         }
1168                 }
1169         ret = 1;
1170   err:
1171         BN_free(a);
1172         BN_free(b[0]);
1173         BN_free(b[1]);
1174         BN_free(c);
1175         BN_free(d);
1176         return ret;
1177         }
1178
1179 int test_gf2m_mod_inv(BIO *bp,BN_CTX *ctx)
1180         {
1181         BIGNUM *a,*b[2],*c,*d;
1182         int i, j, ret = 0;
1183         unsigned int p0[] = {163,7,6,3,0};
1184         unsigned int p1[] = {193,15,0};
1185
1186         a=BN_new();
1187         b[0]=BN_new();
1188         b[1]=BN_new();
1189         c=BN_new();
1190         d=BN_new();
1191
1192         BN_GF2m_arr2poly(p0, b[0]);
1193         BN_GF2m_arr2poly(p1, b[1]);
1194
1195         for (i=0; i<num0; i++)
1196                 {
1197                 BN_bntest_rand(a, 512, 0, 0); 
1198                 for (j=0; j < 2; j++)
1199                         {
1200                         BN_GF2m_mod_inv(c, a, b[j], ctx);
1201                         BN_GF2m_mod_mul(d, a, c, b[j], ctx);
1202 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
1203                         if (bp != NULL)
1204                                 {
1205                                 if (!results)
1206                                         {
1207                                         BN_print(bp,a);
1208                                         BIO_puts(bp, " * ");
1209                                         BN_print(bp,c);
1210                                         BIO_puts(bp," - 1 % ");
1211                                         BN_print(bp,b[j]);
1212                                         BIO_puts(bp,"\n");
1213                                         }
1214                                 }
1215 #endif
1216                         /* Test that ((1/a)*a) = 1. */
1217                         if(!BN_is_one(d))
1218                                 {
1219                                 fprintf(stderr,"GF(2^m) modular inversion test failed!\n");
1220                                 goto err;
1221                                 }
1222                         }
1223                 }
1224         ret = 1;
1225   err:
1226         BN_free(a);
1227         BN_free(b[0]);
1228         BN_free(b[1]);
1229         BN_free(c);
1230         BN_free(d);
1231         return ret;
1232         }
1233
1234 int test_gf2m_mod_div(BIO *bp,BN_CTX *ctx)
1235         {
1236         BIGNUM *a,*b[2],*c,*d,*e,*f;
1237         int i, j, ret = 0;
1238         unsigned int p0[] = {163,7,6,3,0};
1239         unsigned int p1[] = {193,15,0};
1240
1241         a=BN_new();
1242         b[0]=BN_new();
1243         b[1]=BN_new();
1244         c=BN_new();
1245         d=BN_new();
1246         e=BN_new();
1247         f=BN_new();
1248
1249         BN_GF2m_arr2poly(p0, b[0]);
1250         BN_GF2m_arr2poly(p1, b[1]);
1251
1252         for (i=0; i<num0; i++)
1253                 {
1254                 BN_bntest_rand(a, 512, 0, 0); 
1255                 BN_bntest_rand(c, 512, 0, 0);
1256                 for (j=0; j < 2; j++)
1257                         {
1258                         BN_GF2m_mod_div(d, a, c, b[j], ctx);
1259                         BN_GF2m_mod_mul(e, d, c, b[j], ctx);
1260                         BN_GF2m_mod_div(f, a, e, b[j], ctx);
1261 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
1262                         if (bp != NULL)
1263                                 {
1264                                 if (!results)
1265                                         {
1266                                         BN_print(bp,a);
1267                                         BIO_puts(bp, " = ");
1268                                         BN_print(bp,c);
1269                                         BIO_puts(bp," * ");
1270                                         BN_print(bp,d);
1271                                         BIO_puts(bp, " % ");
1272                                         BN_print(bp,b[j]);
1273                                         BIO_puts(bp,"\n");
1274                                         }
1275                                 }
1276 #endif
1277                         /* Test that ((a/c)*c)/a = 1. */
1278                         if(!BN_is_one(f))
1279                                 {
1280                                 fprintf(stderr,"GF(2^m) modular division test failed!\n");
1281                                 goto err;
1282                                 }
1283                         }
1284                 }
1285         ret = 1;
1286   err:
1287         BN_free(a);
1288         BN_free(b[0]);
1289         BN_free(b[1]);
1290         BN_free(c);
1291         BN_free(d);
1292         BN_free(e);
1293         BN_free(f);
1294         return ret;
1295         }
1296
1297 int test_gf2m_mod_exp(BIO *bp,BN_CTX *ctx)
1298         {
1299         BIGNUM *a,*b[2],*c,*d,*e,*f;
1300         int i, j, ret = 0;
1301         unsigned int p0[] = {163,7,6,3,0};
1302         unsigned int p1[] = {193,15,0};
1303
1304         a=BN_new();
1305         b[0]=BN_new();
1306         b[1]=BN_new();
1307         c=BN_new();
1308         d=BN_new();
1309         e=BN_new();
1310         f=BN_new();
1311
1312         BN_GF2m_arr2poly(p0, b[0]);
1313         BN_GF2m_arr2poly(p1, b[1]);
1314
1315         for (i=0; i<num0; i++)
1316                 {
1317                 BN_bntest_rand(a, 512, 0, 0);
1318                 BN_bntest_rand(c, 512, 0, 0);
1319                 BN_bntest_rand(d, 512, 0, 0);
1320                 for (j=0; j < 2; j++)
1321                         {
1322                         BN_GF2m_mod_exp(e, a, c, b[j], ctx);
1323                         BN_GF2m_mod_exp(f, a, d, b[j], ctx);
1324                         BN_GF2m_mod_mul(e, e, f, b[j], ctx);
1325                         BN_add(f, c, d);
1326                         BN_GF2m_mod_exp(f, a, f, b[j], ctx);
1327 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
1328                         if (bp != NULL)
1329                                 {
1330                                 if (!results)
1331                                         {
1332                                         BN_print(bp,a);
1333                                         BIO_puts(bp, " ^ (");
1334                                         BN_print(bp,c);
1335                                         BIO_puts(bp," + ");
1336                                         BN_print(bp,d);
1337                                         BIO_puts(bp, ") = ");
1338                                         BN_print(bp,e);
1339                                         BIO_puts(bp, "; - ");
1340                                         BN_print(bp,f);
1341                                         BIO_puts(bp, " % ");
1342                                         BN_print(bp,b[j]);
1343                                         BIO_puts(bp,"\n");
1344                                         }
1345                                 }
1346 #endif
1347                         BN_GF2m_add(f, e, f);
1348                         /* Test that a^(c+d)=a^c*a^d. */
1349                         if(!BN_is_zero(f))
1350                                 {
1351                                 fprintf(stderr,"GF(2^m) modular exponentiation test failed!\n");
1352                                 goto err;
1353                                 }
1354                         }
1355                 }
1356         ret = 1;
1357   err:
1358         BN_free(a);
1359         BN_free(b[0]);
1360         BN_free(b[1]);
1361         BN_free(c);
1362         BN_free(d);
1363         BN_free(e);
1364         BN_free(f);
1365         return ret;
1366         }
1367
1368 int test_gf2m_mod_sqrt(BIO *bp,BN_CTX *ctx)
1369         {
1370         BIGNUM *a,*b[2],*c,*d,*e,*f;
1371         int i, j, ret = 0;
1372         unsigned int p0[] = {163,7,6,3,0};
1373         unsigned int p1[] = {193,15,0};
1374
1375         a=BN_new();
1376         b[0]=BN_new();
1377         b[1]=BN_new();
1378         c=BN_new();
1379         d=BN_new();
1380         e=BN_new();
1381         f=BN_new();
1382
1383         BN_GF2m_arr2poly(p0, b[0]);
1384         BN_GF2m_arr2poly(p1, b[1]);
1385
1386         for (i=0; i<num0; i++)
1387                 {
1388                 BN_bntest_rand(a, 512, 0, 0);
1389                 for (j=0; j < 2; j++)
1390                         {
1391                         BN_GF2m_mod(c, a, b[j]);
1392                         BN_GF2m_mod_sqrt(d, a, b[j], ctx);
1393                         BN_GF2m_mod_sqr(e, d, b[j], ctx);
1394 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
1395                         if (bp != NULL)
1396                                 {
1397                                 if (!results)
1398                                         {
1399                                         BN_print(bp,d);
1400                                         BIO_puts(bp, " ^ 2 - ");
1401                                         BN_print(bp,a);
1402                                         BIO_puts(bp,"\n");
1403                                         }
1404                                 }
1405 #endif
1406                         BN_GF2m_add(f, c, e);
1407                         /* Test that d^2 = a, where d = sqrt(a). */
1408                         if(!BN_is_zero(f))
1409                                 {
1410                                 fprintf(stderr,"GF(2^m) modular square root test failed!\n");
1411                                 goto err;
1412                                 }
1413                         }
1414                 }
1415         ret = 1;
1416   err:
1417         BN_free(a);
1418         BN_free(b[0]);
1419         BN_free(b[1]);
1420         BN_free(c);
1421         BN_free(d);
1422         BN_free(e);
1423         BN_free(f);
1424         return ret;
1425         }
1426
1427 int test_gf2m_mod_solve_quad(BIO *bp,BN_CTX *ctx)
1428         {
1429         BIGNUM *a,*b[2],*c,*d,*e;
1430         int i, j, s = 0, t, ret = 0;
1431         unsigned int p0[] = {163,7,6,3,0};
1432         unsigned int p1[] = {193,15,0};
1433
1434         a=BN_new();
1435         b[0]=BN_new();
1436         b[1]=BN_new();
1437         c=BN_new();
1438         d=BN_new();
1439         e=BN_new();
1440
1441         BN_GF2m_arr2poly(p0, b[0]);
1442         BN_GF2m_arr2poly(p1, b[1]);
1443
1444         for (i=0; i<num0; i++)
1445                 {
1446                 BN_bntest_rand(a, 512, 0, 0);
1447                 for (j=0; j < 2; j++)
1448                         {
1449                         t = BN_GF2m_mod_solve_quad(c, a, b[j], ctx);
1450                         if (t)
1451                                 {
1452                                 s++;
1453                                 BN_GF2m_mod_sqr(d, c, b[j], ctx);
1454                                 BN_GF2m_add(d, c, d);
1455                                 BN_GF2m_mod(e, a, b[j]);
1456 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
1457                                 if (bp != NULL)
1458                                         {
1459                                         if (!results)
1460                                                 {
1461                                                 BN_print(bp,c);
1462                                                 BIO_puts(bp, " is root of z^2 + z = ");
1463                                                 BN_print(bp,a);
1464                                                 BIO_puts(bp, " % ");
1465                                                 BN_print(bp,b[j]);
1466                                                 BIO_puts(bp, "\n");
1467                                                 }
1468                                         }
1469 #endif
1470                                 BN_GF2m_add(e, e, d);
1471                                 /* Test that solution of quadratic c satisfies c^2 + c = a. */
1472                                 if(!BN_is_zero(e))
1473                                         {
1474                                         fprintf(stderr,"GF(2^m) modular solve quadratic test failed!\n");
1475                                         goto err;
1476                                         }
1477
1478                                 }
1479                         else 
1480                                 {
1481 #if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
1482                                 if (bp != NULL)
1483                                         {
1484                                         if (!results)
1485                                                 {
1486                                                 BIO_puts(bp, "There are no roots of z^2 + z = ");
1487                                                 BN_print(bp,a);
1488                                                 BIO_puts(bp, " % ");
1489                                                 BN_print(bp,b[j]);
1490                                                 BIO_puts(bp, "\n");
1491                                                 }
1492                                         }
1493 #endif
1494                                 }
1495                         }
1496                 }
1497         if (s == 0)
1498                 {       
1499                 fprintf(stderr,"All %i tests of GF(2^m) modular solve quadratic resulted in no roots;\n", num0);
1500                 fprintf(stderr,"this is very unlikely and probably indicates an error.\n");
1501                 goto err;
1502                 }
1503         ret = 1;
1504   err:
1505         BN_free(a);
1506         BN_free(b[0]);
1507         BN_free(b[1]);
1508         BN_free(c);
1509         BN_free(d);
1510         BN_free(e);
1511         return ret;
1512         }
1513
1514 static void genprime_cb(int p, int n, void *arg)
1515         {
1516         char c='*';
1517
1518         if (p == 0) c='.';
1519         if (p == 1) c='+';
1520         if (p == 2) c='*';
1521         if (p == 3) c='\n';
1522         putc(c, stderr);
1523         fflush(stderr);
1524         (void)n;
1525         (void)arg;
1526         }
1527
1528 int test_kron(BIO *bp, BN_CTX *ctx)
1529         {
1530         BIGNUM *a,*b,*r,*t;
1531         int i;
1532         int legendre, kronecker;
1533         int ret = 0;
1534
1535         a = BN_new();
1536         b = BN_new();
1537         r = BN_new();
1538         t = BN_new();
1539         if (a == NULL || b == NULL || r == NULL || t == NULL) goto err;
1540         
1541         /* We test BN_kronecker(a, b, ctx) just for  b  odd (Jacobi symbol).
1542          * In this case we know that if  b  is prime, then BN_kronecker(a, b, ctx)
1543          * is congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol).
1544          * So we generate a random prime  b  and compare these values
1545          * for a number of random  a's.  (That is, we run the Solovay-Strassen
1546          * primality test to confirm that  b  is prime, except that we
1547          * don't want to test whether  b  is prime but whether BN_kronecker
1548          * works.) */
1549
1550         if (!BN_generate_prime(b, 512, 0, NULL, NULL, genprime_cb, NULL)) goto err;
1551         b->neg = rand_neg();
1552         putc('\n', stderr);
1553
1554         for (i = 0; i < num0; i++)
1555                 {
1556                 if (!BN_bntest_rand(a, 512, 0, 0)) goto err;
1557                 a->neg = rand_neg();
1558
1559                 /* t := (|b|-1)/2  (note that b is odd) */
1560                 if (!BN_copy(t, b)) goto err;
1561                 t->neg = 0;
1562                 if (!BN_sub_word(t, 1)) goto err;
1563                 if (!BN_rshift1(t, t)) goto err;
1564                 /* r := a^t mod b */
1565                 b->neg=0;
1566                 
1567                 if (!BN_mod_exp_recp(r, a, t, b, ctx)) goto err;
1568                 b->neg=1;
1569
1570                 if (BN_is_word(r, 1))
1571                         legendre = 1;
1572                 else if (BN_is_zero(r))
1573                         legendre = 0;
1574                 else
1575                         {
1576                         if (!BN_add_word(r, 1)) goto err;
1577                         if (0 != BN_ucmp(r, b))
1578                                 {
1579                                 fprintf(stderr, "Legendre symbol computation failed\n");
1580                                 goto err;
1581                                 }
1582                         legendre = -1;
1583                         }
1584                 
1585                 kronecker = BN_kronecker(a, b, ctx);
1586                 if (kronecker < -1) goto err;
1587                 /* we actually need BN_kronecker(a, |b|) */
1588                 if (a->neg && b->neg)
1589                         kronecker = -kronecker;
1590                 
1591                 if (legendre != kronecker)
1592                         {
1593                         fprintf(stderr, "legendre != kronecker; a = ");
1594                         BN_print_fp(stderr, a);
1595                         fprintf(stderr, ", b = ");
1596                         BN_print_fp(stderr, b);
1597                         fprintf(stderr, "\n");
1598                         goto err;
1599                         }
1600
1601                 putc('.', stderr);
1602                 fflush(stderr);
1603                 }
1604
1605         putc('\n', stderr);
1606         fflush(stderr);
1607         ret = 1;
1608  err:
1609         if (a != NULL) BN_free(a);
1610         if (b != NULL) BN_free(b);
1611         if (r != NULL) BN_free(r);
1612         if (t != NULL) BN_free(t);
1613         return ret;
1614         }
1615
1616 int test_sqrt(BIO *bp, BN_CTX *ctx)
1617         {
1618         BIGNUM *a,*p,*r;
1619         int i, j;
1620         int ret = 0;
1621
1622         a = BN_new();
1623         p = BN_new();
1624         r = BN_new();
1625         if (a == NULL || p == NULL || r == NULL) goto err;
1626         
1627         for (i = 0; i < 16; i++)
1628                 {
1629                 if (i < 8)
1630                         {
1631                         unsigned primes[8] = { 2, 3, 5, 7, 11, 13, 17, 19 };
1632                         
1633                         if (!BN_set_word(p, primes[i])) goto err;
1634                         }
1635                 else
1636                         {
1637                         if (!BN_set_word(a, 32)) goto err;
1638                         if (!BN_set_word(r, 2*i + 1)) goto err;
1639                 
1640                         if (!BN_generate_prime(p, 256, 0, a, r, genprime_cb, NULL)) goto err;
1641                         putc('\n', stderr);
1642                         }
1643                 p->neg = rand_neg();
1644
1645                 for (j = 0; j < num2; j++)
1646                         {
1647                         /* construct 'a' such that it is a square modulo p,
1648                          * but in general not a proper square and not reduced modulo p */
1649                         if (!BN_bntest_rand(r, 256, 0, 3)) goto err;
1650                         if (!BN_nnmod(r, r, p, ctx)) goto err;
1651                         if (!BN_mod_sqr(r, r, p, ctx)) goto err;
1652                         if (!BN_bntest_rand(a, 256, 0, 3)) goto err;
1653                         if (!BN_nnmod(a, a, p, ctx)) goto err;
1654                         if (!BN_mod_sqr(a, a, p, ctx)) goto err;
1655                         if (!BN_mul(a, a, r, ctx)) goto err;
1656                         if (rand_neg())
1657                                 if (!BN_sub(a, a, p)) goto err;
1658
1659                         if (!BN_mod_sqrt(r, a, p, ctx)) goto err;
1660                         if (!BN_mod_sqr(r, r, p, ctx)) goto err;
1661
1662                         if (!BN_nnmod(a, a, p, ctx)) goto err;
1663
1664                         if (BN_cmp(a, r) != 0)
1665                                 {
1666                                 fprintf(stderr, "BN_mod_sqrt failed: a = ");
1667                                 BN_print_fp(stderr, a);
1668                                 fprintf(stderr, ", r = ");
1669                                 BN_print_fp(stderr, r);
1670                                 fprintf(stderr, ", p = ");
1671                                 BN_print_fp(stderr, p);
1672                                 fprintf(stderr, "\n");
1673                                 goto err;
1674                                 }
1675
1676                         putc('.', stderr);
1677                         fflush(stderr);
1678                         }
1679                 
1680                 putc('\n', stderr);
1681                 fflush(stderr);
1682                 }
1683         ret = 1;
1684  err:
1685         if (a != NULL) BN_free(a);
1686         if (p != NULL) BN_free(p);
1687         if (r != NULL) BN_free(r);
1688         return ret;
1689         }
1690
1691 int test_lshift(BIO *bp,BN_CTX *ctx,BIGNUM *a_)
1692         {
1693         BIGNUM *a,*b,*c,*d;
1694         int i;
1695
1696         b=BN_new();
1697         c=BN_new();
1698         d=BN_new();
1699         BN_one(c);
1700
1701         if(a_)
1702             a=a_;
1703         else
1704             {
1705             a=BN_new();
1706             BN_bntest_rand(a,200,0,0); /**/
1707             a->neg=rand_neg();
1708             }
1709         for (i=0; i<num0; i++)
1710                 {
1711                 BN_lshift(b,a,i+1);
1712                 BN_add(c,c,c);
1713                 if (bp != NULL)
1714                         {
1715                         if (!results)
1716                                 {
1717                                 BN_print(bp,a);
1718                                 BIO_puts(bp," * ");
1719                                 BN_print(bp,c);
1720                                 BIO_puts(bp," - ");
1721                                 }
1722                         BN_print(bp,b);
1723                         BIO_puts(bp,"\n");
1724                         }
1725                 BN_mul(d,a,c,ctx);
1726                 BN_sub(d,d,b);
1727                 if(!BN_is_zero(d))
1728                     {
1729                     fprintf(stderr,"Left shift test failed!\n");
1730                     fprintf(stderr,"a=");
1731                     BN_print_fp(stderr,a);
1732                     fprintf(stderr,"\nb=");
1733                     BN_print_fp(stderr,b);
1734                     fprintf(stderr,"\nc=");
1735                     BN_print_fp(stderr,c);
1736                     fprintf(stderr,"\nd=");
1737                     BN_print_fp(stderr,d);
1738                     fprintf(stderr,"\n");
1739                     return 0;
1740                     }
1741                 }
1742         BN_free(a);
1743         BN_free(b);
1744         BN_free(c);
1745         BN_free(d);
1746         return(1);
1747         }
1748
1749 int test_lshift1(BIO *bp)
1750         {
1751         BIGNUM *a,*b,*c;
1752         int i;
1753
1754         a=BN_new();
1755         b=BN_new();
1756         c=BN_new();
1757
1758         BN_bntest_rand(a,200,0,0); /**/
1759         a->neg=rand_neg();
1760         for (i=0; i<num0; i++)
1761                 {
1762                 BN_lshift1(b,a);
1763                 if (bp != NULL)
1764                         {
1765                         if (!results)
1766                                 {
1767                                 BN_print(bp,a);
1768                                 BIO_puts(bp," * 2");
1769                                 BIO_puts(bp," - ");
1770                                 }
1771                         BN_print(bp,b);
1772                         BIO_puts(bp,"\n");
1773                         }
1774                 BN_add(c,a,a);
1775                 BN_sub(a,b,c);
1776                 if(!BN_is_zero(a))
1777                     {
1778                     fprintf(stderr,"Left shift one test failed!\n");
1779                     return 0;
1780                     }
1781                 
1782                 BN_copy(a,b);
1783                 }
1784         BN_free(a);
1785         BN_free(b);
1786         BN_free(c);
1787         return(1);
1788         }
1789
1790 int test_rshift(BIO *bp,BN_CTX *ctx)
1791         {
1792         BIGNUM *a,*b,*c,*d,*e;
1793         int i;
1794
1795         a=BN_new();
1796         b=BN_new();
1797         c=BN_new();
1798         d=BN_new();
1799         e=BN_new();
1800         BN_one(c);
1801
1802         BN_bntest_rand(a,200,0,0); /**/
1803         a->neg=rand_neg();
1804         for (i=0; i<num0; i++)
1805                 {
1806                 BN_rshift(b,a,i+1);
1807                 BN_add(c,c,c);
1808                 if (bp != NULL)
1809                         {
1810                         if (!results)
1811                                 {
1812                                 BN_print(bp,a);
1813                                 BIO_puts(bp," / ");
1814                                 BN_print(bp,c);
1815                                 BIO_puts(bp," - ");
1816                                 }
1817                         BN_print(bp,b);
1818                         BIO_puts(bp,"\n");
1819                         }
1820                 BN_div(d,e,a,c,ctx);
1821                 BN_sub(d,d,b);
1822                 if(!BN_is_zero(d))
1823                     {
1824                     fprintf(stderr,"Right shift test failed!\n");
1825                     return 0;
1826                     }
1827                 }
1828         BN_free(a);
1829         BN_free(b);
1830         BN_free(c);
1831         BN_free(d);
1832         BN_free(e);
1833         return(1);
1834         }
1835
1836 int test_rshift1(BIO *bp)
1837         {
1838         BIGNUM *a,*b,*c;
1839         int i;
1840
1841         a=BN_new();
1842         b=BN_new();
1843         c=BN_new();
1844
1845         BN_bntest_rand(a,200,0,0); /**/
1846         a->neg=rand_neg();
1847         for (i=0; i<num0; i++)
1848                 {
1849                 BN_rshift1(b,a);
1850                 if (bp != NULL)
1851                         {
1852                         if (!results)
1853                                 {
1854                                 BN_print(bp,a);
1855                                 BIO_puts(bp," / 2");
1856                                 BIO_puts(bp," - ");
1857                                 }
1858                         BN_print(bp,b);
1859                         BIO_puts(bp,"\n");
1860                         }
1861                 BN_sub(c,a,b);
1862                 BN_sub(c,c,b);
1863                 if(!BN_is_zero(c) && !BN_abs_is_word(c, 1))
1864                     {
1865                     fprintf(stderr,"Right shift one test failed!\n");
1866                     return 0;
1867                     }
1868                 BN_copy(a,b);
1869                 }
1870         BN_free(a);
1871         BN_free(b);
1872         BN_free(c);
1873         return(1);
1874         }
1875
1876 int rand_neg(void)
1877         {
1878         static unsigned int neg=0;
1879         static int sign[8]={0,0,0,1,1,0,1,1};
1880
1881         return(sign[(neg++)%8]);
1882         }