• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57 /* ====================================================================
58  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
59  *
60  * Portions of the attached software ("Contribution") are developed by
61  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
62  *
63  * The Contribution is licensed pursuant to the Eric Young open source
64  * license provided above.
65  *
66  * The binary polynomial arithmetic software is originally written by
67  * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
68  * Laboratories. */
69 
70 /* For BIGNUM format macros. */
71 #if !defined(__STDC_FORMAT_MACROS)
72 #define __STDC_FORMAT_MACROS
73 #endif
74 
75 #include <errno.h>
76 #include <stdio.h>
77 #include <string.h>
78 
79 #include <openssl/bn.h>
80 #include <openssl/crypto.h>
81 #include <openssl/err.h>
82 #include <openssl/mem.h>
83 
84 #include "../crypto/test/scoped_types.h"
85 
86 
87 // This program tests the BIGNUM implementation. It takes an optional -bc
88 // argument to write a transcript compatible with the UNIX bc utility.
89 //
90 // TODO(davidben): Rather than generate random inputs and depend on bc to check
91 // the results, most of these tests should use known answers.
92 
93 static const int num0 = 100; // number of tests
94 static const int num1 = 50;  // additional tests for some functions
95 static const int num2 = 5;   // number of tests for slow functions
96 
97 static bool test_add(FILE *fp);
98 static bool test_sub(FILE *fp);
99 static bool test_lshift1(FILE *fp);
100 static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a);
101 static bool test_rshift1(FILE *fp);
102 static bool test_rshift(FILE *fp, BN_CTX *ctx);
103 static bool test_sqr(FILE *fp, BN_CTX *ctx);
104 static bool test_mul(FILE *fp);
105 static bool test_div(FILE *fp, BN_CTX *ctx);
106 static int rand_neg();
107 
108 static bool test_div_word(FILE *fp);
109 static bool test_mont(FILE *fp, BN_CTX *ctx);
110 static bool test_mod(FILE *fp, BN_CTX *ctx);
111 static bool test_mod_mul(FILE *fp, BN_CTX *ctx);
112 static bool test_mod_exp(FILE *fp, BN_CTX *ctx);
113 static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx);
114 static bool test_exp(FILE *fp, BN_CTX *ctx);
115 static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx);
116 static bool test_exp_mod_zero(void);
117 static bool test_small_prime(FILE *fp, BN_CTX *ctx);
118 static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx);
119 static bool test_sqrt(FILE *fp, BN_CTX *ctx);
120 static bool test_bn2bin_padded(FILE *fp, BN_CTX *ctx);
121 static bool test_dec2bn(FILE *fp, BN_CTX *ctx);
122 static bool test_hex2bn(FILE *fp, BN_CTX *ctx);
123 static bool test_asc2bn(FILE *fp, BN_CTX *ctx);
124 static bool test_rand();
125 
126 static const uint8_t kSample[] =
127     "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
128     "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
129 
130 // A wrapper around puts that takes its arguments in the same order as our *_fp
131 // functions.
puts_fp(FILE * out,const char * m)132 static void puts_fp(FILE *out, const char *m) {
133   if (out != nullptr) {
134     fputs(m, out);
135   }
136 }
137 
flush_fp(FILE * out)138 static void flush_fp(FILE *out) {
139   if (out != nullptr) {
140     fflush(out);
141   }
142 }
143 
message(FILE * out,const char * m)144 static void message(FILE *out, const char *m) {
145   puts_fp(out, "print \"test ");
146   puts_fp(out, m);
147   puts_fp(out, "\\n\"\n");
148 }
149 
main(int argc,char * argv[])150 int main(int argc, char *argv[]) {
151   CRYPTO_library_init();
152 
153   ScopedFILE bc_file;
154   argc--;
155   argv++;
156   while (argc >= 1) {
157     if (strcmp(*argv, "-bc") == 0) {
158       if (argc < 2) {
159         fprintf(stderr, "Missing parameter to -bc\n");
160         return 1;
161       }
162       bc_file.reset(fopen(argv[1], "w+"));
163       if (!bc_file) {
164         fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno));
165       }
166       argc--;
167       argv++;
168     } else {
169       fprintf(stderr, "Unknown option: %s\n", argv[0]);
170       return 1;
171     }
172     argc--;
173     argv++;
174   }
175 
176 
177   ScopedBN_CTX ctx(BN_CTX_new());
178   if (!ctx) {
179     return 1;
180   }
181 
182   puts_fp(bc_file.get(), "/* This script, when run through the UNIX bc utility, "
183                          "should produce a sequence of zeros. */\n");
184   puts_fp(bc_file.get(), "/* tr a-f A-F < bn_test.out | sed s/BAsE/base/ | bc "
185                          "| grep -v 0 */\n");
186   puts_fp(bc_file.get(), "obase=16\nibase=16\n");
187 
188   message(bc_file.get(), "BN_add");
189   if (!test_add(bc_file.get())) {
190     return 1;
191   }
192   flush_fp(bc_file.get());
193 
194   message(bc_file.get(), "BN_sub");
195   if (!test_sub(bc_file.get())) {
196     return 1;
197   }
198   flush_fp(bc_file.get());
199 
200   message(bc_file.get(), "BN_lshift1");
201   if (!test_lshift1(bc_file.get())) {
202     return 1;
203   }
204   flush_fp(bc_file.get());
205 
206   message(bc_file.get(), "BN_lshift (fixed)");
207   ScopedBIGNUM sample(BN_bin2bn(kSample, sizeof(kSample) - 1, NULL));
208   if (!sample) {
209     return 1;
210   }
211   if (!test_lshift(bc_file.get(), ctx.get(), bssl::move(sample))) {
212     return 1;
213   }
214   flush_fp(bc_file.get());
215 
216   message(bc_file.get(), "BN_lshift");
217   if (!test_lshift(bc_file.get(), ctx.get(), nullptr)) {
218     return 1;
219   }
220   flush_fp(bc_file.get());
221 
222   message(bc_file.get(), "BN_rshift1");
223   if (!test_rshift1(bc_file.get())) {
224     return 1;
225   }
226   flush_fp(bc_file.get());
227 
228   message(bc_file.get(), "BN_rshift");
229   if (!test_rshift(bc_file.get(), ctx.get())) {
230     return 1;
231   }
232   flush_fp(bc_file.get());
233 
234   message(bc_file.get(), "BN_sqr");
235   if (!test_sqr(bc_file.get(), ctx.get())) {
236     return 1;
237   }
238   flush_fp(bc_file.get());
239 
240   message(bc_file.get(), "BN_mul");
241   if (!test_mul(bc_file.get())) {
242     return 1;
243   }
244   flush_fp(bc_file.get());
245 
246   message(bc_file.get(), "BN_div");
247   if (!test_div(bc_file.get(), ctx.get())) {
248     return 1;
249   }
250   flush_fp(bc_file.get());
251 
252   message(bc_file.get(), "BN_div_word");
253   if (!test_div_word(bc_file.get())) {
254     return 1;
255   }
256   flush_fp(bc_file.get());
257 
258   message(bc_file.get(), "BN_mod");
259   if (!test_mod(bc_file.get(), ctx.get())) {
260     return 1;
261   }
262   flush_fp(bc_file.get());
263 
264   message(bc_file.get(), "BN_mod_mul");
265   if (!test_mod_mul(bc_file.get(), ctx.get())) {
266     return 1;
267   }
268   flush_fp(bc_file.get());
269 
270   message(bc_file.get(), "BN_mont");
271   if (!test_mont(bc_file.get(), ctx.get())) {
272     return 1;
273   }
274   flush_fp(bc_file.get());
275 
276   message(bc_file.get(), "BN_mod_exp");
277   if (!test_mod_exp(bc_file.get(), ctx.get())) {
278     return 1;
279   }
280   flush_fp(bc_file.get());
281 
282   message(bc_file.get(), "BN_mod_exp_mont_consttime");
283   if (!test_mod_exp_mont_consttime(bc_file.get(), ctx.get()) ||
284       !test_mod_exp_mont5(bc_file.get(), ctx.get())) {
285     return 1;
286   }
287   flush_fp(bc_file.get());
288 
289   message(bc_file.get(), "BN_exp");
290   if (!test_exp(bc_file.get(), ctx.get()) ||
291       !test_exp_mod_zero()) {
292     return 1;
293   }
294   flush_fp(bc_file.get());
295 
296   message(bc_file.get(), "BN_mod_sqrt");
297   if (!test_mod_sqrt(bc_file.get(), ctx.get())) {
298     return 1;
299   }
300   flush_fp(bc_file.get());
301 
302   message(bc_file.get(), "Small prime generation");
303   if (!test_small_prime(bc_file.get(), ctx.get())) {
304     return 1;
305   }
306   flush_fp(bc_file.get());
307 
308   message(bc_file.get(), "BN_sqrt");
309   if (!test_sqrt(bc_file.get(), ctx.get())) {
310     return 1;
311   }
312   flush_fp(bc_file.get());
313 
314   message(bc_file.get(), "BN_bn2bin_padded");
315   if (!test_bn2bin_padded(bc_file.get(), ctx.get())) {
316     return 1;
317   }
318   flush_fp(bc_file.get());
319 
320   message(bc_file.get(), "BN_dec2bn");
321   if (!test_dec2bn(bc_file.get(), ctx.get())) {
322     return 1;
323   }
324   flush_fp(bc_file.get());
325 
326   message(bc_file.get(), "BN_hex2bn");
327   if (!test_hex2bn(bc_file.get(), ctx.get())) {
328     return 1;
329   }
330   flush_fp(bc_file.get());
331 
332   message(bc_file.get(), "BN_asc2bn");
333   if (!test_asc2bn(bc_file.get(), ctx.get())) {
334     return 1;
335   }
336   flush_fp(bc_file.get());
337 
338   message(bc_file.get(), "BN_rand");
339   if (!test_rand()) {
340     return 1;
341   }
342   flush_fp(bc_file.get());
343 
344   printf("PASS\n");
345   return 0;
346 }
347 
test_add(FILE * fp)348 static bool test_add(FILE *fp) {
349   ScopedBIGNUM a(BN_new());
350   ScopedBIGNUM b(BN_new());
351   ScopedBIGNUM c(BN_new());
352   if (!a || !b || !c || !BN_rand(a.get(), 512, 0, 0)) {
353     return false;
354   }
355 
356   for (int i = 0; i < num0; i++) {
357     if (!BN_rand(b.get(), 450 + i, 0, 0)) {
358       return false;
359     }
360     a->neg = rand_neg();
361     b->neg = rand_neg();
362     if (!BN_add(c.get(), a.get(), b.get())) {
363       return false;
364     }
365     if (fp != NULL) {
366       BN_print_fp(fp, a.get());
367       puts_fp(fp, " + ");
368       BN_print_fp(fp, b.get());
369       puts_fp(fp, " - ");
370       BN_print_fp(fp, c.get());
371       puts_fp(fp, "\n");
372     }
373     a->neg = !a->neg;
374     b->neg = !b->neg;
375     if (!BN_add(c.get(), c.get(), b.get()) ||
376         !BN_add(c.get(), c.get(), a.get())) {
377       return false;
378     }
379     if (!BN_is_zero(c.get())) {
380       fprintf(stderr, "Add test failed!\n");
381       return false;
382     }
383   }
384   return true;
385 }
386 
test_sub(FILE * fp)387 static bool test_sub(FILE *fp) {
388   ScopedBIGNUM a(BN_new());
389   ScopedBIGNUM b(BN_new());
390   ScopedBIGNUM c(BN_new());
391   if (!a || !b || !c) {
392     return false;
393   }
394 
395   for (int i = 0; i < num0 + num1; i++) {
396     if (i < num1) {
397       if (!BN_rand(a.get(), 512, 0, 0) ||
398           !BN_copy(b.get(), a.get()) ||
399           !BN_set_bit(a.get(), i) ||
400           !BN_add_word(b.get(), i)) {
401         return false;
402       }
403     } else {
404       if (!BN_rand(b.get(), 400 + i - num1, 0, 0)) {
405         return false;
406       }
407       a->neg = rand_neg();
408       b->neg = rand_neg();
409     }
410     if (!BN_sub(c.get(), a.get(), b.get())) {
411       return false;
412     }
413     if (fp != NULL) {
414       BN_print_fp(fp, a.get());
415       puts_fp(fp, " - ");
416       BN_print_fp(fp, b.get());
417       puts_fp(fp, " - ");
418       BN_print_fp(fp, c.get());
419       puts_fp(fp, "\n");
420     }
421     if (!BN_add(c.get(), c.get(), b.get()) ||
422         !BN_sub(c.get(), c.get(), a.get())) {
423       return false;
424     }
425     if (!BN_is_zero(c.get())) {
426       fprintf(stderr, "Subtract test failed!\n");
427       return false;
428     }
429   }
430   return true;
431 }
432 
test_div(FILE * fp,BN_CTX * ctx)433 static bool test_div(FILE *fp, BN_CTX *ctx) {
434   ScopedBIGNUM a(BN_new());
435   ScopedBIGNUM b(BN_new());
436   ScopedBIGNUM c(BN_new());
437   ScopedBIGNUM d(BN_new());
438   ScopedBIGNUM e(BN_new());
439   if (!a || !b || !c || !d || !e) {
440     return false;
441   }
442 
443   for (int i = 0; i < num0 + num1; i++) {
444     if (i < num1) {
445       if (!BN_rand(a.get(), 400, 0, 0) ||
446           !BN_copy(b.get(), a.get()) ||
447           !BN_lshift(a.get(), a.get(), i) ||
448           !BN_add_word(a.get(), i)) {
449         return false;
450       }
451     } else if (!BN_rand(b.get(), 50 + 3 * (i - num1), 0, 0)) {
452       return false;
453     }
454     a->neg = rand_neg();
455     b->neg = rand_neg();
456     if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
457       return false;
458     }
459     if (fp != NULL) {
460       BN_print_fp(fp, a.get());
461       puts_fp(fp, " / ");
462       BN_print_fp(fp, b.get());
463       puts_fp(fp, " - ");
464       BN_print_fp(fp, d.get());
465       puts_fp(fp, "\n");
466 
467       BN_print_fp(fp, a.get());
468       puts_fp(fp, " % ");
469       BN_print_fp(fp, b.get());
470       puts_fp(fp, " - ");
471       BN_print_fp(fp, c.get());
472       puts_fp(fp, "\n");
473     }
474     if (!BN_mul(e.get(), d.get(), b.get(), ctx) ||
475         !BN_add(d.get(), e.get(), c.get()) ||
476         !BN_sub(d.get(), d.get(), a.get())) {
477       return false;
478     }
479     if (!BN_is_zero(d.get())) {
480       fprintf(stderr, "Division test failed!\n");
481       return false;
482     }
483   }
484 
485   // Test that BN_div never gives negative zero in the quotient.
486   if (!BN_set_word(a.get(), 1) ||
487       !BN_set_word(b.get(), 2)) {
488     return false;
489   }
490   BN_set_negative(a.get(), 1);
491   if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
492     return false;
493   }
494   if (!BN_is_zero(d.get()) || BN_is_negative(d.get())) {
495     fprintf(stderr, "Division test failed!\n");
496     return false;
497   }
498 
499   // Test that BN_div never gives negative zero in the remainder.
500   if (!BN_set_word(b.get(), 1)) {
501     return false;
502   }
503   if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
504     return false;
505   }
506   if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
507     fprintf(stderr, "Division test failed!\n");
508     return false;
509   }
510 
511   return true;
512 }
513 
test_lshift1(FILE * fp)514 static bool test_lshift1(FILE *fp) {
515   ScopedBIGNUM a(BN_new());
516   ScopedBIGNUM b(BN_new());
517   ScopedBIGNUM c(BN_new());
518   if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
519     return false;
520   }
521   a->neg = rand_neg();
522   for (int i = 0; i < num0; i++) {
523     if (!BN_lshift1(b.get(), a.get())) {
524       return false;
525     }
526     if (fp != NULL) {
527       BN_print_fp(fp, a.get());
528       puts_fp(fp, " * 2");
529       puts_fp(fp, " - ");
530       BN_print_fp(fp, b.get());
531       puts_fp(fp, "\n");
532     }
533     if (!BN_add(c.get(), a.get(), a.get()) ||
534         !BN_sub(a.get(), b.get(), c.get())) {
535       return false;
536     }
537     if (!BN_is_zero(a.get())) {
538       fprintf(stderr, "Left shift one test failed!\n");
539       return false;
540     }
541 
542     if (!BN_copy(a.get(), b.get())) {
543       return false;
544     }
545   }
546   return true;
547 }
548 
test_rshift(FILE * fp,BN_CTX * ctx)549 static bool test_rshift(FILE *fp, BN_CTX *ctx) {
550   ScopedBIGNUM a(BN_new());
551   ScopedBIGNUM b(BN_new());
552   ScopedBIGNUM c(BN_new());
553   ScopedBIGNUM d(BN_new());
554   ScopedBIGNUM e(BN_new());
555   if (!a || !b || !c || !d || !e || !BN_one(c.get()) ||
556       !BN_rand(a.get(), 200, 0, 0)) {
557     return false;
558   }
559   a->neg = rand_neg();
560   for (int i = 0; i < num0; i++) {
561     if (!BN_rshift(b.get(), a.get(), i + 1) ||
562         !BN_add(c.get(), c.get(), c.get())) {
563       return false;
564     }
565     if (fp != NULL) {
566       BN_print_fp(fp, a.get());
567       puts_fp(fp, " / ");
568       BN_print_fp(fp, c.get());
569       puts_fp(fp, " - ");
570       BN_print_fp(fp, b.get());
571       puts_fp(fp, "\n");
572     }
573     if (!BN_div(d.get(), e.get(), a.get(), c.get(), ctx) ||
574         !BN_sub(d.get(), d.get(), b.get())) {
575       return false;
576     }
577     if (!BN_is_zero(d.get())) {
578       fprintf(stderr, "Right shift test failed!\n");
579       return false;
580     }
581   }
582   return true;
583 }
584 
test_rshift1(FILE * fp)585 static bool test_rshift1(FILE *fp) {
586   ScopedBIGNUM a(BN_new());
587   ScopedBIGNUM b(BN_new());
588   ScopedBIGNUM c(BN_new());
589   if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
590     return false;
591   }
592   a->neg = rand_neg();
593 
594   for (int i = 0; i < num0; i++) {
595     if (!BN_rshift1(b.get(), a.get())) {
596       return false;
597     }
598     if (fp != NULL) {
599       BN_print_fp(fp, a.get());
600       puts_fp(fp, " / 2");
601       puts_fp(fp, " - ");
602       BN_print_fp(fp, b.get());
603       puts_fp(fp, "\n");
604     }
605     if (!BN_sub(c.get(), a.get(), b.get()) ||
606         !BN_sub(c.get(), c.get(), b.get())) {
607       return false;
608     }
609     if (!BN_is_zero(c.get()) && !BN_abs_is_word(c.get(), 1)) {
610       fprintf(stderr, "Right shift one test failed!\n");
611       return false;
612     }
613     if (!BN_copy(a.get(), b.get())) {
614       return false;
615     }
616   }
617   return true;
618 }
619 
test_lshift(FILE * fp,BN_CTX * ctx,ScopedBIGNUM a)620 static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a) {
621   if (!a) {
622     a.reset(BN_new());
623     if (!a || !BN_rand(a.get(), 200, 0, 0)) {
624       return false;
625     }
626     a->neg = rand_neg();
627   }
628 
629   ScopedBIGNUM b(BN_new());
630   ScopedBIGNUM c(BN_new());
631   ScopedBIGNUM d(BN_new());
632   if (!b || !c || !d || !BN_one(c.get())) {
633     return false;
634   }
635 
636   for (int i = 0; i < num0; i++) {
637     if (!BN_lshift(b.get(), a.get(), i + 1) ||
638         !BN_add(c.get(), c.get(), c.get())) {
639       return false;
640     }
641     if (fp != NULL) {
642       BN_print_fp(fp, a.get());
643       puts_fp(fp, " * ");
644       BN_print_fp(fp, c.get());
645       puts_fp(fp, " - ");
646       BN_print_fp(fp, b.get());
647       puts_fp(fp, "\n");
648     }
649     if (!BN_mul(d.get(), a.get(), c.get(), ctx) ||
650         !BN_sub(d.get(), d.get(), b.get())) {
651       return false;
652     }
653     if (!BN_is_zero(d.get())) {
654       fprintf(stderr, "Left shift test failed!\n");
655       fprintf(stderr, "a=");
656       BN_print_fp(stderr, a.get());
657       fprintf(stderr, "\nb=");
658       BN_print_fp(stderr, b.get());
659       fprintf(stderr, "\nc=");
660       BN_print_fp(stderr, c.get());
661       fprintf(stderr, "\nd=");
662       BN_print_fp(stderr, d.get());
663       fprintf(stderr, "\n");
664       return false;
665     }
666   }
667   return true;
668 }
669 
test_mul(FILE * fp)670 static bool test_mul(FILE *fp) {
671   ScopedBN_CTX ctx(BN_CTX_new());
672   ScopedBIGNUM a(BN_new());
673   ScopedBIGNUM b(BN_new());
674   ScopedBIGNUM c(BN_new());
675   ScopedBIGNUM d(BN_new());
676   ScopedBIGNUM e(BN_new());
677   if (!ctx || !a || !b || !c || !d || !e) {
678     return false;
679   }
680 
681   for (int i = 0; i < num0 + num1; i++) {
682     if (i <= num1) {
683       if (!BN_rand(a.get(), 100, 0, 0) ||
684           !BN_rand(b.get(), 100, 0, 0)) {
685         return false;
686       }
687     } else if (!BN_rand(b.get(), i - num1, 0, 0)) {
688       return false;
689     }
690     a->neg = rand_neg();
691     b->neg = rand_neg();
692     if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) {
693       return false;
694     }
695     if (fp != NULL) {
696       BN_print_fp(fp, a.get());
697       puts_fp(fp, " * ");
698       BN_print_fp(fp, b.get());
699       puts_fp(fp, " - ");
700       BN_print_fp(fp, c.get());
701       puts_fp(fp, "\n");
702     }
703     if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx.get()) ||
704         !BN_sub(d.get(), d.get(), b.get())) {
705       return false;
706     }
707     if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
708       fprintf(stderr, "Multiplication test failed!\n");
709       return false;
710     }
711   }
712 
713   // Test that BN_mul never gives negative zero.
714   if (!BN_set_word(a.get(), 1)) {
715     return false;
716   }
717   BN_set_negative(a.get(), 1);
718   BN_zero(b.get());
719   if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) {
720     return false;
721   }
722   if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
723     fprintf(stderr, "Multiplication test failed!\n");
724     return false;
725   }
726 
727   return true;
728 }
729 
test_sqr(FILE * fp,BN_CTX * ctx)730 static bool test_sqr(FILE *fp, BN_CTX *ctx) {
731   ScopedBIGNUM a(BN_new());
732   ScopedBIGNUM c(BN_new());
733   ScopedBIGNUM d(BN_new());
734   ScopedBIGNUM e(BN_new());
735   if (!a || !c || !d || !e) {
736     return false;
737   }
738 
739   for (int i = 0; i < num0; i++) {
740     if (!BN_rand(a.get(), 40 + i * 10, 0, 0)) {
741       return false;
742     }
743     a->neg = rand_neg();
744     if (!BN_sqr(c.get(), a.get(), ctx)) {
745       return false;
746     }
747     if (fp != NULL) {
748       BN_print_fp(fp, a.get());
749       puts_fp(fp, " * ");
750       BN_print_fp(fp, a.get());
751       puts_fp(fp, " - ");
752       BN_print_fp(fp, c.get());
753       puts_fp(fp, "\n");
754     }
755     if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx) ||
756         !BN_sub(d.get(), d.get(), a.get())) {
757       return false;
758     }
759     if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
760       fprintf(stderr, "Square test failed!\n");
761       return false;
762     }
763   }
764 
765   // Regression test for a BN_sqr overflow bug.
766   BIGNUM *a_raw = a.get();
767   if (!BN_hex2bn(
768           &a_raw,
769           "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000") ||
770       !BN_sqr(c.get(), a.get(), ctx)) {
771     return false;
772   }
773   if (fp != NULL) {
774     BN_print_fp(fp, a.get());
775     puts_fp(fp, " * ");
776     BN_print_fp(fp, a.get());
777     puts_fp(fp, " - ");
778     BN_print_fp(fp, c.get());
779     puts_fp(fp, "\n");
780   }
781   if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
782     return false;
783   }
784   if (BN_cmp(c.get(), d.get())) {
785     fprintf(stderr,
786             "Square test failed: BN_sqr and BN_mul produce "
787             "different results!\n");
788     return false;
789   }
790 
791   // Regression test for a BN_sqr overflow bug.
792   a_raw = a.get();
793   if (!BN_hex2bn(
794           &a_raw,
795           "80000000000000000000000080000001FFFFFFFE000000000000000000000000") ||
796       !BN_sqr(c.get(), a.get(), ctx)) {
797     return false;
798   }
799   if (fp != NULL) {
800     BN_print_fp(fp, a.get());
801     puts_fp(fp, " * ");
802     BN_print_fp(fp, a.get());
803     puts_fp(fp, " - ");
804     BN_print_fp(fp, c.get());
805     puts_fp(fp, "\n");
806   }
807   if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
808     return false;
809   }
810   if (BN_cmp(c.get(), d.get())) {
811     fprintf(stderr,
812             "Square test failed: BN_sqr and BN_mul produce "
813             "different results!\n");
814     return false;
815   }
816 
817   return true;
818 }
819 
820 
rand_neg()821 static int rand_neg() {
822   static unsigned int neg = 0;
823   static const int sign[8] = {0, 0, 0, 1, 1, 0, 1, 1};
824 
825   return sign[(neg++) % 8];
826 }
827 
print_word(FILE * fp,BN_ULONG w)828 static void print_word(FILE *fp, BN_ULONG w) {
829   fprintf(fp, BN_HEX_FMT1, w);
830 }
831 
test_div_word(FILE * fp)832 static bool test_div_word(FILE *fp) {
833   ScopedBIGNUM a(BN_new());
834   ScopedBIGNUM b(BN_new());
835   if (!a || !b) {
836     return false;
837   }
838 
839   for (int i = 0; i < num0; i++) {
840     BN_ULONG s;
841     do {
842       if (!BN_rand(a.get(), 512, -1, 0) ||
843           !BN_rand(b.get(), BN_BITS2, -1, 0)) {
844         return false;
845       }
846       s = b->d[0];
847     } while (!s);
848 
849     if (!BN_copy(b.get(), a.get())) {
850       return false;
851     }
852     BN_ULONG r = BN_div_word(b.get(), s);
853     if (r == (BN_ULONG)-1) {
854       return false;
855     }
856 
857     if (fp != NULL) {
858       BN_print_fp(fp, a.get());
859       puts_fp(fp, " / ");
860       print_word(fp, s);
861       puts_fp(fp, " - ");
862       BN_print_fp(fp, b.get());
863       puts_fp(fp, "\n");
864 
865       BN_print_fp(fp, a.get());
866       puts_fp(fp, " % ");
867       print_word(fp, s);
868       puts_fp(fp, " - ");
869       print_word(fp, r);
870       puts_fp(fp, "\n");
871     }
872     if (!BN_mul_word(b.get(), s) ||
873         !BN_add_word(b.get(), r) ||
874         !BN_sub(b.get(), a.get(), b.get())) {
875       return false;
876     }
877     if (!BN_is_zero(b.get())) {
878       fprintf(stderr, "Division (word) test failed!\n");
879       return false;
880     }
881   }
882   return true;
883 }
884 
test_mont(FILE * fp,BN_CTX * ctx)885 static bool test_mont(FILE *fp, BN_CTX *ctx) {
886   ScopedBIGNUM a(BN_new());
887   ScopedBIGNUM b(BN_new());
888   ScopedBIGNUM c(BN_new());
889   ScopedBIGNUM d(BN_new());
890   ScopedBIGNUM A(BN_new());
891   ScopedBIGNUM B(BN_new());
892   ScopedBIGNUM n(BN_new());
893   ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
894   if (!a || !b || !c || !d || !A || !B || !n || !mont ||
895       !BN_rand(a.get(), 100, 0, 0) ||
896       !BN_rand(b.get(), 100, 0, 0)) {
897     return false;
898   }
899 
900   for (int i = 0; i < num2; i++) {
901     int bits = (200 * (i + 1)) / num2;
902 
903     if (bits == 0) {
904       continue;
905     }
906     if (!BN_rand(n.get(), bits, 0, 1) ||
907         !BN_MONT_CTX_set(mont.get(), n.get(), ctx) ||
908         !BN_nnmod(a.get(), a.get(), n.get(), ctx) ||
909         !BN_nnmod(b.get(), b.get(), n.get(), ctx) ||
910         !BN_to_montgomery(A.get(), a.get(), mont.get(), ctx) ||
911         !BN_to_montgomery(B.get(), b.get(), mont.get(), ctx) ||
912         !BN_mod_mul_montgomery(c.get(), A.get(), B.get(), mont.get(), ctx) ||
913         !BN_from_montgomery(A.get(), c.get(), mont.get(), ctx)) {
914       return false;
915     }
916     if (fp != NULL) {
917       BN_print_fp(fp, a.get());
918       puts_fp(fp, " * ");
919       BN_print_fp(fp, b.get());
920       puts_fp(fp, " % ");
921       BN_print_fp(fp, &mont->N);
922       puts_fp(fp, " - ");
923       BN_print_fp(fp, A.get());
924       puts_fp(fp, "\n");
925     }
926     if (!BN_mod_mul(d.get(), a.get(), b.get(), n.get(), ctx) ||
927         !BN_sub(d.get(), d.get(), A.get())) {
928       return false;
929     }
930     if (!BN_is_zero(d.get())) {
931       fprintf(stderr, "Montgomery multiplication test failed!\n");
932       return false;
933     }
934   }
935   return true;
936 }
937 
test_mod(FILE * fp,BN_CTX * ctx)938 static bool test_mod(FILE *fp, BN_CTX *ctx) {
939   ScopedBIGNUM a(BN_new());
940   ScopedBIGNUM b(BN_new());
941   ScopedBIGNUM c(BN_new());
942   ScopedBIGNUM d(BN_new());
943   ScopedBIGNUM e(BN_new());
944   if (!a || !b || !c || !d || !e ||
945       !BN_rand(a.get(), 1024, 0, 0)) {
946     return false;
947   }
948 
949   for (int i = 0; i < num0; i++) {
950     if (!BN_rand(b.get(), 450 + i * 10, 0, 0)) {
951       return false;
952     }
953     a->neg = rand_neg();
954     b->neg = rand_neg();
955     if (!BN_mod(c.get(), a.get(), b.get(), ctx)) {
956       return false;
957     }
958     if (fp != NULL) {
959       BN_print_fp(fp, a.get());
960       puts_fp(fp, " % ");
961       BN_print_fp(fp, b.get());
962       puts_fp(fp, " - ");
963       BN_print_fp(fp, c.get());
964       puts_fp(fp, "\n");
965     }
966     if (!BN_div(d.get(), e.get(), a.get(), b.get(), ctx) ||
967         !BN_sub(e.get(), e.get(), c.get())) {
968       return false;
969     }
970     if (!BN_is_zero(e.get())) {
971       fprintf(stderr, "Modulo test failed!\n");
972       return false;
973     }
974   }
975   return true;
976 }
977 
test_mod_mul(FILE * fp,BN_CTX * ctx)978 static bool test_mod_mul(FILE *fp, BN_CTX *ctx) {
979   ScopedBIGNUM a(BN_new());
980   ScopedBIGNUM b(BN_new());
981   ScopedBIGNUM c(BN_new());
982   ScopedBIGNUM d(BN_new());
983   ScopedBIGNUM e(BN_new());
984   if (!a || !b || !c || !d || !e) {
985     return false;
986   }
987 
988   for (int j = 0; j < 3; j++) {
989     if (!BN_rand(c.get(), 1024, 0, 0)) {
990       return false;
991     }
992     for (int i = 0; i < num0; i++) {
993       if (!BN_rand(a.get(), 475 + i * 10, 0, 0) ||
994           !BN_rand(b.get(), 425 + i * 11, 0, 0)) {
995         return false;
996       }
997       a->neg = rand_neg();
998       b->neg = rand_neg();
999       if (!BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) {
1000         ERR_print_errors_fp(stderr);
1001         return false;
1002       }
1003       if (fp != NULL) {
1004         BN_print_fp(fp, a.get());
1005         puts_fp(fp, " * ");
1006         BN_print_fp(fp, b.get());
1007         puts_fp(fp, " % ");
1008         BN_print_fp(fp, c.get());
1009         if (a->neg != b->neg && !BN_is_zero(e.get())) {
1010           // If  (a*b) % c  is negative,  c  must be added
1011           // in order to obtain the normalized remainder
1012           // (new with OpenSSL 0.9.7, previous versions of
1013           // BN_mod_mul could generate negative results)
1014           puts_fp(fp, " + ");
1015           BN_print_fp(fp, c.get());
1016         }
1017         puts_fp(fp, " - ");
1018         BN_print_fp(fp, e.get());
1019         puts_fp(fp, "\n");
1020       }
1021       if (!BN_mul(d.get(), a.get(), b.get(), ctx) ||
1022           !BN_sub(d.get(), d.get(), e.get()) ||
1023           !BN_div(a.get(), b.get(), d.get(), c.get(), ctx)) {
1024         return false;
1025       }
1026       if (!BN_is_zero(b.get())) {
1027         fprintf(stderr, "Modulo multiply test failed!\n");
1028         ERR_print_errors_fp(stderr);
1029         return false;
1030       }
1031     }
1032   }
1033   return true;
1034 }
1035 
test_mod_exp(FILE * fp,BN_CTX * ctx)1036 static bool test_mod_exp(FILE *fp, BN_CTX *ctx) {
1037   ScopedBIGNUM a(BN_new());
1038   ScopedBIGNUM b(BN_new());
1039   ScopedBIGNUM c(BN_new());
1040   ScopedBIGNUM d(BN_new());
1041   ScopedBIGNUM e(BN_new());
1042   if (!a || !b || !c || !d || !e ||
1043       !BN_rand(c.get(), 30, 0, 1)) {  // must be odd for montgomery
1044     return false;
1045   }
1046   for (int i = 0; i < num2; i++) {
1047     if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
1048         !BN_rand(b.get(), 2 + i, 0, 0) ||
1049         !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) {
1050       return false;
1051     }
1052 
1053     if (fp != NULL) {
1054       BN_print_fp(fp, a.get());
1055       puts_fp(fp, " ^ ");
1056       BN_print_fp(fp, b.get());
1057       puts_fp(fp, " % ");
1058       BN_print_fp(fp, c.get());
1059       puts_fp(fp, " - ");
1060       BN_print_fp(fp, d.get());
1061       puts_fp(fp, "\n");
1062     }
1063     if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
1064         !BN_sub(e.get(), e.get(), d.get()) ||
1065         !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
1066       return false;
1067     }
1068     if (!BN_is_zero(b.get())) {
1069       fprintf(stderr, "Modulo exponentiation test failed!\n");
1070       return false;
1071     }
1072   }
1073   return true;
1074 }
1075 
test_mod_exp_mont_consttime(FILE * fp,BN_CTX * ctx)1076 static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx) {
1077   ScopedBIGNUM a(BN_new());
1078   ScopedBIGNUM b(BN_new());
1079   ScopedBIGNUM c(BN_new());
1080   ScopedBIGNUM d(BN_new());
1081   ScopedBIGNUM e(BN_new());
1082   if (!a || !b || !c || !d || !e ||
1083       !BN_rand(c.get(), 30, 0, 1)) {  // must be odd for montgomery
1084     return false;
1085   }
1086   for (int i = 0; i < num2; i++) {
1087     if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
1088         !BN_rand(b.get(), 2 + i, 0, 0) ||
1089         !BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
1090                                    NULL)) {
1091       return false;
1092     }
1093 
1094     if (fp != NULL) {
1095       BN_print_fp(fp, a.get());
1096       puts_fp(fp, " ^ ");
1097       BN_print_fp(fp, b.get());
1098       puts_fp(fp, " % ");
1099       BN_print_fp(fp, c.get());
1100       puts_fp(fp, " - ");
1101       BN_print_fp(fp, d.get());
1102       puts_fp(fp, "\n");
1103     }
1104     if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
1105         !BN_sub(e.get(), e.get(), d.get()) ||
1106         !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
1107       return false;
1108     }
1109     if (!BN_is_zero(b.get())) {
1110       fprintf(stderr, "Modulo exponentiation test failed!\n");
1111       return false;
1112     }
1113   }
1114   return true;
1115 }
1116 
1117 // Test constant-time modular exponentiation with 1024-bit inputs,
1118 // which on x86_64 cause a different code branch to be taken.
test_mod_exp_mont5(FILE * fp,BN_CTX * ctx)1119 static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx) {
1120   ScopedBIGNUM a(BN_new());
1121   ScopedBIGNUM p(BN_new());
1122   ScopedBIGNUM m(BN_new());
1123   ScopedBIGNUM d(BN_new());
1124   ScopedBIGNUM e(BN_new());
1125   if (!a || !p || !m || !d || !e ||
1126       !BN_rand(m.get(), 1024, 0, 1) ||  // must be odd for montgomery
1127       !BN_rand(a.get(), 1024, 0, 0)) {
1128     return false;
1129   }
1130   // Zero exponent.
1131   BN_zero(p.get());
1132   if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
1133                                  NULL)) {
1134     return false;
1135   }
1136   if (!BN_is_one(d.get())) {
1137     fprintf(stderr, "Modular exponentiation test failed!\n");
1138     return false;
1139   }
1140   if (!BN_rand(p.get(), 1024, 0, 0)) {
1141     return false;
1142   }
1143   // Zero input.
1144   BN_zero(a.get());
1145   if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
1146                                  NULL)) {
1147     return false;
1148   }
1149   if (!BN_is_zero(d.get())) {
1150     fprintf(stderr, "Modular exponentiation test failed!\n");
1151     return false;
1152   }
1153   // Craft an input whose Montgomery representation is 1, i.e., shorter than the
1154   // modulus m, in order to test the const time precomputation
1155   // scattering/gathering.
1156   ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
1157   if (!mont || !BN_one(a.get()) ||
1158       !BN_MONT_CTX_set(mont.get(), m.get(), ctx) ||
1159       !BN_from_montgomery(e.get(), a.get(), mont.get(), ctx) ||
1160       !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
1161                                  NULL) ||
1162       !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
1163     return false;
1164   }
1165   if (BN_cmp(a.get(), d.get()) != 0) {
1166     fprintf(stderr, "Modular exponentiation test failed!\n");
1167     return false;
1168   }
1169   // Finally, some regular test vectors.
1170   if (!BN_rand(e.get(), 1024, 0, 0) ||
1171       !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
1172                                  NULL) ||
1173       !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
1174     return false;
1175   }
1176   if (BN_cmp(a.get(), d.get()) != 0) {
1177     fprintf(stderr, "Modular exponentiation test failed!\n");
1178     return false;
1179   }
1180 
1181   return true;
1182 }
1183 
test_exp(FILE * fp,BN_CTX * ctx)1184 static bool test_exp(FILE *fp, BN_CTX *ctx) {
1185   ScopedBIGNUM a(BN_new());
1186   ScopedBIGNUM b(BN_new());
1187   ScopedBIGNUM d(BN_new());
1188   ScopedBIGNUM e(BN_new());
1189   if (!a || !b || !d || !e) {
1190     return false;
1191   }
1192 
1193   for (int i = 0; i < num2; i++) {
1194     if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
1195         !BN_rand(b.get(), 2 + i, 0, 0) ||
1196         !BN_exp(d.get(), a.get(), b.get(), ctx)) {
1197       return false;
1198     }
1199 
1200     if (fp != NULL) {
1201       BN_print_fp(fp, a.get());
1202       puts_fp(fp, " ^ ");
1203       BN_print_fp(fp, b.get());
1204       puts_fp(fp, " - ");
1205       BN_print_fp(fp, d.get());
1206       puts_fp(fp, "\n");
1207     }
1208     if (!BN_one(e.get())) {
1209       return false;
1210     }
1211     for (; !BN_is_zero(b.get()); BN_sub(b.get(), b.get(), BN_value_one())) {
1212       if (!BN_mul(e.get(), e.get(), a.get(), ctx)) {
1213         return false;
1214       }
1215     }
1216     if (!BN_sub(e.get(), e.get(), d.get())) {
1217       return false;
1218     }
1219     if (!BN_is_zero(e.get())) {
1220       fprintf(stderr, "Exponentiation test failed!\n");
1221       return false;
1222     }
1223   }
1224   return true;
1225 }
1226 
1227 // test_exp_mod_zero tests that 1**0 mod 1 == 0.
test_exp_mod_zero(void)1228 static bool test_exp_mod_zero(void) {
1229   ScopedBIGNUM zero(BN_new());
1230   if (!zero) {
1231     return false;
1232   }
1233   BN_zero(zero.get());
1234 
1235   ScopedBN_CTX ctx(BN_CTX_new());
1236   ScopedBIGNUM r(BN_new());
1237   if (!ctx || !r ||
1238       !BN_mod_exp(r.get(), BN_value_one(), zero.get(), BN_value_one(), ctx.get())) {
1239     return false;
1240   }
1241 
1242   if (!BN_is_zero(r.get())) {
1243     fprintf(stderr, "1**0 mod 1 = ");
1244     BN_print_fp(stderr, r.get());
1245     fprintf(stderr, ", should be 0\n");
1246     return false;
1247   }
1248 
1249   return true;
1250 }
1251 
test_mod_sqrt(FILE * fp,BN_CTX * ctx)1252 static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx) {
1253   ScopedBIGNUM a(BN_new());
1254   ScopedBIGNUM p(BN_new());
1255   ScopedBIGNUM r(BN_new());
1256   if (!a || !p || !r) {
1257     return false;
1258   }
1259 
1260   for (int i = 0; i < 16; i++) {
1261     if (i < 8) {
1262       const unsigned kPrimes[8] = {2, 3, 5, 7, 11, 13, 17, 19};
1263       if (!BN_set_word(p.get(), kPrimes[i])) {
1264         return false;
1265       }
1266     } else {
1267       if (!BN_set_word(a.get(), 32) ||
1268           !BN_set_word(r.get(), 2 * i + 1) ||
1269           !BN_generate_prime_ex(p.get(), 256, 0, a.get(), r.get(), nullptr)) {
1270         return false;
1271       }
1272     }
1273     p->neg = rand_neg();
1274 
1275     for (int j = 0; j < num2; j++) {
1276       // construct 'a' such that it is a square modulo p, but in general not a
1277       // proper square and not reduced modulo p
1278       if (!BN_rand(r.get(), 256, 0, 3) ||
1279           !BN_nnmod(r.get(), r.get(), p.get(), ctx) ||
1280           !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
1281           !BN_rand(a.get(), 256, 0, 3) ||
1282           !BN_nnmod(a.get(), a.get(), p.get(), ctx) ||
1283           !BN_mod_sqr(a.get(), a.get(), p.get(), ctx) ||
1284           !BN_mul(a.get(), a.get(), r.get(), ctx)) {
1285         return false;
1286       }
1287       if (rand_neg() && !BN_sub(a.get(), a.get(), p.get())) {
1288         return false;
1289       }
1290 
1291       if (!BN_mod_sqrt(r.get(), a.get(), p.get(), ctx) ||
1292           !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
1293           !BN_nnmod(a.get(), a.get(), p.get(), ctx)) {
1294         return false;
1295       }
1296 
1297       if (BN_cmp(a.get(), r.get()) != 0) {
1298         fprintf(stderr, "BN_mod_sqrt failed: a = ");
1299         BN_print_fp(stderr, a.get());
1300         fprintf(stderr, ", r = ");
1301         BN_print_fp(stderr, r.get());
1302         fprintf(stderr, ", p = ");
1303         BN_print_fp(stderr, p.get());
1304         fprintf(stderr, "\n");
1305         return false;
1306       }
1307     }
1308   }
1309   return true;
1310 }
1311 
test_small_prime(FILE * fp,BN_CTX * ctx)1312 static bool test_small_prime(FILE *fp, BN_CTX *ctx) {
1313   static const unsigned kBits = 10;
1314 
1315   ScopedBIGNUM r(BN_new());
1316   if (!r || !BN_generate_prime_ex(r.get(), static_cast<int>(kBits), 0, NULL,
1317                                   NULL, NULL)) {
1318     return false;
1319   }
1320   if (BN_num_bits(r.get()) != kBits) {
1321     fprintf(fp, "Expected %u bit prime, got %u bit number\n", kBits,
1322             BN_num_bits(r.get()));
1323     return false;
1324   }
1325 
1326   return true;
1327 }
1328 
test_sqrt(FILE * fp,BN_CTX * ctx)1329 static bool test_sqrt(FILE *fp, BN_CTX *ctx) {
1330   ScopedBIGNUM n(BN_new());
1331   ScopedBIGNUM nn(BN_new());
1332   ScopedBIGNUM sqrt(BN_new());
1333   if (!n || !nn || !sqrt) {
1334     return false;
1335   }
1336 
1337   // Test some random squares.
1338   for (int i = 0; i < 100; i++) {
1339     if (!BN_rand(n.get(), 1024 /* bit length */,
1340                  -1 /* no modification of top bits */,
1341                  0 /* don't modify bottom bit */) ||
1342         !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
1343         !BN_sqrt(sqrt.get(), nn.get(), ctx)) {
1344       ERR_print_errors_fp(stderr);
1345       return false;
1346     }
1347     if (BN_cmp(n.get(), sqrt.get()) != 0) {
1348       fprintf(stderr, "Bad result from BN_sqrt.\n");
1349       return false;
1350     }
1351   }
1352 
1353   // Test some non-squares.
1354   for (int i = 0; i < 100; i++) {
1355     if (!BN_rand(n.get(), 1024 /* bit length */,
1356                  -1 /* no modification of top bits */,
1357                  0 /* don't modify bottom bit */) ||
1358         !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
1359         !BN_add(nn.get(), nn.get(), BN_value_one())) {
1360       ERR_print_errors_fp(stderr);
1361       return false;
1362     }
1363 
1364     if (BN_sqrt(sqrt.get(), nn.get(), ctx)) {
1365       char *nn_str = BN_bn2dec(nn.get());
1366       fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str);
1367       OPENSSL_free(nn_str);
1368     }
1369   }
1370 
1371   return true;
1372 }
1373 
test_bn2bin_padded(FILE * fp,BN_CTX * ctx)1374 static bool test_bn2bin_padded(FILE *fp, BN_CTX *ctx) {
1375   uint8_t zeros[256], out[256], reference[128];
1376 
1377   memset(zeros, 0, sizeof(zeros));
1378 
1379   // Test edge case at 0.
1380   ScopedBIGNUM n(BN_new());
1381   if (!n || !BN_bn2bin_padded(NULL, 0, n.get())) {
1382     fprintf(stderr,
1383             "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n");
1384     return false;
1385   }
1386   memset(out, -1, sizeof(out));
1387   if (!BN_bn2bin_padded(out, sizeof(out), n.get())) {
1388     fprintf(stderr,
1389             "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n");
1390     return false;
1391   }
1392   if (memcmp(zeros, out, sizeof(out))) {
1393     fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n");
1394     return false;
1395   }
1396 
1397   // Test a random numbers at various byte lengths.
1398   for (size_t bytes = 128 - 7; bytes <= 128; bytes++) {
1399     if (!BN_rand(n.get(), bytes * 8, 0 /* make sure top bit is 1 */,
1400                  0 /* don't modify bottom bit */)) {
1401       ERR_print_errors_fp(stderr);
1402       return false;
1403     }
1404     if (BN_num_bytes(n.get()) != bytes ||
1405         BN_bn2bin(n.get(), reference) != bytes) {
1406       fprintf(stderr, "Bad result from BN_rand; bytes.\n");
1407       return false;
1408     }
1409     // Empty buffer should fail.
1410     if (BN_bn2bin_padded(NULL, 0, n.get())) {
1411       fprintf(stderr,
1412               "BN_bn2bin_padded incorrectly succeeded on empty buffer.\n");
1413       return false;
1414     }
1415     // One byte short should fail.
1416     if (BN_bn2bin_padded(out, bytes - 1, n.get())) {
1417       fprintf(stderr, "BN_bn2bin_padded incorrectly succeeded on short.\n");
1418       return false;
1419     }
1420     // Exactly right size should encode.
1421     if (!BN_bn2bin_padded(out, bytes, n.get()) ||
1422         memcmp(out, reference, bytes) != 0) {
1423       fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
1424       return false;
1425     }
1426     // Pad up one byte extra.
1427     if (!BN_bn2bin_padded(out, bytes + 1, n.get()) ||
1428         memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) {
1429       fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
1430       return false;
1431     }
1432     // Pad up to 256.
1433     if (!BN_bn2bin_padded(out, sizeof(out), n.get()) ||
1434         memcmp(out + sizeof(out) - bytes, reference, bytes) ||
1435         memcmp(out, zeros, sizeof(out) - bytes)) {
1436       fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
1437       return false;
1438     }
1439   }
1440 
1441   return true;
1442 }
1443 
DecimalToBIGNUM(ScopedBIGNUM * out,const char * in)1444 static int DecimalToBIGNUM(ScopedBIGNUM *out, const char *in) {
1445   BIGNUM *raw = NULL;
1446   int ret = BN_dec2bn(&raw, in);
1447   out->reset(raw);
1448   return ret;
1449 }
1450 
test_dec2bn(FILE * fp,BN_CTX * ctx)1451 static bool test_dec2bn(FILE *fp, BN_CTX *ctx) {
1452   ScopedBIGNUM bn;
1453   int ret = DecimalToBIGNUM(&bn, "0");
1454   if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1455     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1456     return false;
1457   }
1458 
1459   ret = DecimalToBIGNUM(&bn, "256");
1460   if (ret != 3 || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) {
1461     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1462     return false;
1463   }
1464 
1465   ret = DecimalToBIGNUM(&bn, "-42");
1466   if (ret != 3 || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) {
1467     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1468     return false;
1469   }
1470 
1471   ret = DecimalToBIGNUM(&bn, "-0");
1472   if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1473     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1474     return false;
1475   }
1476 
1477   ret = DecimalToBIGNUM(&bn, "42trailing garbage is ignored");
1478   if (ret != 2 || !BN_abs_is_word(bn.get(), 42) || BN_is_negative(bn.get())) {
1479     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1480     return false;
1481   }
1482 
1483   return true;
1484 }
1485 
HexToBIGNUM(ScopedBIGNUM * out,const char * in)1486 static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
1487   BIGNUM *raw = NULL;
1488   int ret = BN_hex2bn(&raw, in);
1489   out->reset(raw);
1490   return ret;
1491 }
1492 
test_hex2bn(FILE * fp,BN_CTX * ctx)1493 static bool test_hex2bn(FILE *fp, BN_CTX *ctx) {
1494   ScopedBIGNUM bn;
1495   int ret = HexToBIGNUM(&bn, "0");
1496   if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1497     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1498     return false;
1499   }
1500 
1501   ret = HexToBIGNUM(&bn, "256");
1502   if (ret != 3 || !BN_is_word(bn.get(), 0x256) || BN_is_negative(bn.get())) {
1503     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1504     return false;
1505   }
1506 
1507   ret = HexToBIGNUM(&bn, "-42");
1508   if (ret != 3 || !BN_abs_is_word(bn.get(), 0x42) || !BN_is_negative(bn.get())) {
1509     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1510     return false;
1511   }
1512 
1513   ret = HexToBIGNUM(&bn, "-0");
1514   if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1515     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1516     return false;
1517   }
1518 
1519   ret = HexToBIGNUM(&bn, "abctrailing garbage is ignored");
1520   if (ret != 3 || !BN_is_word(bn.get(), 0xabc) || BN_is_negative(bn.get())) {
1521     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1522     return false;
1523   }
1524 
1525   return true;
1526 }
1527 
ASCIIToBIGNUM(const char * in)1528 static ScopedBIGNUM ASCIIToBIGNUM(const char *in) {
1529   BIGNUM *raw = NULL;
1530   if (!BN_asc2bn(&raw, in)) {
1531     return nullptr;
1532   }
1533   return ScopedBIGNUM(raw);
1534 }
1535 
test_asc2bn(FILE * fp,BN_CTX * ctx)1536 static bool test_asc2bn(FILE *fp, BN_CTX *ctx) {
1537   ScopedBIGNUM bn = ASCIIToBIGNUM("0");
1538   if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1539     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1540     return false;
1541   }
1542 
1543   bn = ASCIIToBIGNUM("256");
1544   if (!bn || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) {
1545     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1546     return false;
1547   }
1548 
1549   bn = ASCIIToBIGNUM("-42");
1550   if (!bn || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) {
1551     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1552     return false;
1553   }
1554 
1555   bn = ASCIIToBIGNUM("0x1234");
1556   if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) {
1557     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1558     return false;
1559   }
1560 
1561   bn = ASCIIToBIGNUM("0X1234");
1562   if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) {
1563     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1564     return false;
1565   }
1566 
1567   bn = ASCIIToBIGNUM("-0xabcd");
1568   if (!bn || !BN_abs_is_word(bn.get(), 0xabcd) || !BN_is_negative(bn.get())) {
1569     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1570     return false;
1571   }
1572 
1573   bn = ASCIIToBIGNUM("-0");
1574   if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1575     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1576     return false;
1577   }
1578 
1579   bn = ASCIIToBIGNUM("123trailing garbage is ignored");
1580   if (!bn || !BN_is_word(bn.get(), 123) || BN_is_negative(bn.get())) {
1581     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1582     return false;
1583   }
1584 
1585   return true;
1586 }
1587 
test_rand()1588 static bool test_rand() {
1589   ScopedBIGNUM bn(BN_new());
1590   if (!bn) {
1591     return false;
1592   }
1593 
1594   // Test BN_rand accounts for degenerate cases with |top| and |bottom|
1595   // parameters.
1596   if (!BN_rand(bn.get(), 0, 0 /* top */, 0 /* bottom */) ||
1597       !BN_is_zero(bn.get())) {
1598     fprintf(stderr, "BN_rand gave a bad result.\n");
1599     return false;
1600   }
1601   if (!BN_rand(bn.get(), 0, 1 /* top */, 1 /* bottom */) ||
1602       !BN_is_zero(bn.get())) {
1603     fprintf(stderr, "BN_rand gave a bad result.\n");
1604     return false;
1605   }
1606 
1607   if (!BN_rand(bn.get(), 1, 0 /* top */, 0 /* bottom */) ||
1608       !BN_is_word(bn.get(), 1)) {
1609     fprintf(stderr, "BN_rand gave a bad result.\n");
1610     return false;
1611   }
1612   if (!BN_rand(bn.get(), 1, 1 /* top */, 0 /* bottom */) ||
1613       !BN_is_word(bn.get(), 1)) {
1614     fprintf(stderr, "BN_rand gave a bad result.\n");
1615     return false;
1616   }
1617   if (!BN_rand(bn.get(), 1, -1 /* top */, 1 /* bottom */) ||
1618       !BN_is_word(bn.get(), 1)) {
1619     fprintf(stderr, "BN_rand gave a bad result.\n");
1620     return false;
1621   }
1622 
1623   if (!BN_rand(bn.get(), 2, 1 /* top */, 0 /* bottom */) ||
1624       !BN_is_word(bn.get(), 3)) {
1625     fprintf(stderr, "BN_rand gave a bad result.\n");
1626     return false;
1627   }
1628 
1629   return true;
1630 }
1631