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 <utility>
80 
81 #include <openssl/bn.h>
82 #include <openssl/crypto.h>
83 #include <openssl/err.h>
84 #include <openssl/mem.h>
85 
86 #include "../crypto/test/scoped_types.h"
87 #include "../crypto/test/test_util.h"
88 
89 
90 // This program tests the BIGNUM implementation. It takes an optional -bc
91 // argument to write a transcript compatible with the UNIX bc utility.
92 //
93 // TODO(davidben): Rather than generate random inputs and depend on bc to check
94 // the results, most of these tests should use known answers.
95 
96 static const int num0 = 100; // number of tests
97 static const int num1 = 50;  // additional tests for some functions
98 static const int num2 = 5;   // number of tests for slow functions
99 
100 static bool test_add(FILE *fp);
101 static bool test_sub(FILE *fp);
102 static bool test_lshift1(FILE *fp);
103 static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a);
104 static bool test_rshift1(FILE *fp);
105 static bool test_rshift(FILE *fp, BN_CTX *ctx);
106 static bool test_sqr(FILE *fp, BN_CTX *ctx);
107 static bool test_mul(FILE *fp);
108 static bool test_div(FILE *fp, BN_CTX *ctx);
109 static int rand_neg();
110 
111 static bool test_div_word(FILE *fp);
112 static bool test_mont(FILE *fp, BN_CTX *ctx);
113 static bool test_mod(FILE *fp, BN_CTX *ctx);
114 static bool test_mod_mul(FILE *fp, BN_CTX *ctx);
115 static bool test_mod_exp(FILE *fp, BN_CTX *ctx);
116 static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx);
117 static bool test_exp(FILE *fp, BN_CTX *ctx);
118 static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx);
119 static bool test_exp_mod_zero(void);
120 static bool test_small_prime(FILE *fp, BN_CTX *ctx);
121 static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx);
122 static bool test_sqrt(FILE *fp, BN_CTX *ctx);
123 static bool test_bn2bin_padded(BN_CTX *ctx);
124 static bool test_dec2bn(BN_CTX *ctx);
125 static bool test_hex2bn(BN_CTX *ctx);
126 static bool test_asc2bn(BN_CTX *ctx);
127 static bool test_mpi();
128 static bool test_rand();
129 static bool test_asn1();
130 
131 static const uint8_t kSample[] =
132     "\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 // A wrapper around puts that takes its arguments in the same order as our *_fp
136 // functions.
puts_fp(FILE * out,const char * m)137 static void puts_fp(FILE *out, const char *m) {
138   if (out != nullptr) {
139     fputs(m, out);
140   }
141 }
142 
flush_fp(FILE * out)143 static void flush_fp(FILE *out) {
144   if (out != nullptr) {
145     fflush(out);
146   }
147 }
148 
message(FILE * out,const char * m)149 static void message(FILE *out, const char *m) {
150   puts_fp(out, "print \"test ");
151   puts_fp(out, m);
152   puts_fp(out, "\\n\"\n");
153 }
154 
main(int argc,char * argv[])155 int main(int argc, char *argv[]) {
156   CRYPTO_library_init();
157 
158   ScopedFILE bc_file;
159   argc--;
160   argv++;
161   while (argc >= 1) {
162     if (strcmp(*argv, "-bc") == 0) {
163       if (argc < 2) {
164         fprintf(stderr, "Missing parameter to -bc\n");
165         return 1;
166       }
167       bc_file.reset(fopen(argv[1], "w+"));
168       if (!bc_file) {
169         fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno));
170       }
171       argc--;
172       argv++;
173     } else {
174       fprintf(stderr, "Unknown option: %s\n", argv[0]);
175       return 1;
176     }
177     argc--;
178     argv++;
179   }
180 
181 
182   ScopedBN_CTX ctx(BN_CTX_new());
183   if (!ctx) {
184     return 1;
185   }
186 
187   puts_fp(bc_file.get(), "/* This script, when run through the UNIX bc utility, "
188                          "should produce a sequence of zeros. */\n");
189   puts_fp(bc_file.get(), "/* tr a-f A-F < bn_test.out | sed s/BAsE/base/ | bc "
190                          "| grep -v 0 */\n");
191   puts_fp(bc_file.get(), "obase=16\nibase=16\n");
192 
193   message(bc_file.get(), "BN_add");
194   if (!test_add(bc_file.get())) {
195     return 1;
196   }
197   flush_fp(bc_file.get());
198 
199   message(bc_file.get(), "BN_sub");
200   if (!test_sub(bc_file.get())) {
201     return 1;
202   }
203   flush_fp(bc_file.get());
204 
205   message(bc_file.get(), "BN_lshift1");
206   if (!test_lshift1(bc_file.get())) {
207     return 1;
208   }
209   flush_fp(bc_file.get());
210 
211   message(bc_file.get(), "BN_lshift (fixed)");
212   ScopedBIGNUM sample(BN_bin2bn(kSample, sizeof(kSample) - 1, NULL));
213   if (!sample) {
214     return 1;
215   }
216   if (!test_lshift(bc_file.get(), ctx.get(), std::move(sample))) {
217     return 1;
218   }
219   flush_fp(bc_file.get());
220 
221   message(bc_file.get(), "BN_lshift");
222   if (!test_lshift(bc_file.get(), ctx.get(), nullptr)) {
223     return 1;
224   }
225   flush_fp(bc_file.get());
226 
227   message(bc_file.get(), "BN_rshift1");
228   if (!test_rshift1(bc_file.get())) {
229     return 1;
230   }
231   flush_fp(bc_file.get());
232 
233   message(bc_file.get(), "BN_rshift");
234   if (!test_rshift(bc_file.get(), ctx.get())) {
235     return 1;
236   }
237   flush_fp(bc_file.get());
238 
239   message(bc_file.get(), "BN_sqr");
240   if (!test_sqr(bc_file.get(), ctx.get())) {
241     return 1;
242   }
243   flush_fp(bc_file.get());
244 
245   message(bc_file.get(), "BN_mul");
246   if (!test_mul(bc_file.get())) {
247     return 1;
248   }
249   flush_fp(bc_file.get());
250 
251   message(bc_file.get(), "BN_div");
252   if (!test_div(bc_file.get(), ctx.get())) {
253     return 1;
254   }
255   flush_fp(bc_file.get());
256 
257   message(bc_file.get(), "BN_div_word");
258   if (!test_div_word(bc_file.get())) {
259     return 1;
260   }
261   flush_fp(bc_file.get());
262 
263   message(bc_file.get(), "BN_mod");
264   if (!test_mod(bc_file.get(), ctx.get())) {
265     return 1;
266   }
267   flush_fp(bc_file.get());
268 
269   message(bc_file.get(), "BN_mod_mul");
270   if (!test_mod_mul(bc_file.get(), ctx.get())) {
271     return 1;
272   }
273   flush_fp(bc_file.get());
274 
275   message(bc_file.get(), "BN_mont");
276   if (!test_mont(bc_file.get(), ctx.get())) {
277     return 1;
278   }
279   flush_fp(bc_file.get());
280 
281   message(bc_file.get(), "BN_mod_exp");
282   if (!test_mod_exp(bc_file.get(), ctx.get())) {
283     return 1;
284   }
285   flush_fp(bc_file.get());
286 
287   message(bc_file.get(), "BN_mod_exp_mont_consttime");
288   if (!test_mod_exp_mont_consttime(bc_file.get(), ctx.get()) ||
289       !test_mod_exp_mont5(bc_file.get(), ctx.get())) {
290     return 1;
291   }
292   flush_fp(bc_file.get());
293 
294   message(bc_file.get(), "BN_exp");
295   if (!test_exp(bc_file.get(), ctx.get()) ||
296       !test_exp_mod_zero()) {
297     return 1;
298   }
299   flush_fp(bc_file.get());
300 
301   message(bc_file.get(), "BN_mod_sqrt");
302   if (!test_mod_sqrt(bc_file.get(), ctx.get())) {
303     return 1;
304   }
305   flush_fp(bc_file.get());
306 
307   message(bc_file.get(), "Small prime generation");
308   if (!test_small_prime(bc_file.get(), ctx.get())) {
309     return 1;
310   }
311   flush_fp(bc_file.get());
312 
313   message(bc_file.get(), "BN_sqrt");
314   if (!test_sqrt(bc_file.get(), ctx.get())) {
315     return 1;
316   }
317   flush_fp(bc_file.get());
318 
319   if (!test_bn2bin_padded(ctx.get()) ||
320       !test_dec2bn(ctx.get()) ||
321       !test_hex2bn(ctx.get()) ||
322       !test_asc2bn(ctx.get()) ||
323       !test_mpi() ||
324       !test_rand() ||
325       !test_asn1()) {
326     return 1;
327   }
328 
329   printf("PASS\n");
330   return 0;
331 }
332 
HexToBIGNUM(ScopedBIGNUM * out,const char * in)333 static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
334   BIGNUM *raw = NULL;
335   int ret = BN_hex2bn(&raw, in);
336   out->reset(raw);
337   return ret;
338 }
339 
test_add(FILE * fp)340 static bool test_add(FILE *fp) {
341   ScopedBIGNUM a(BN_new());
342   ScopedBIGNUM b(BN_new());
343   ScopedBIGNUM c(BN_new());
344   if (!a || !b || !c || !BN_rand(a.get(), 512, 0, 0)) {
345     return false;
346   }
347 
348   for (int i = 0; i < num0; i++) {
349     if (!BN_rand(b.get(), 450 + i, 0, 0)) {
350       return false;
351     }
352     a->neg = rand_neg();
353     b->neg = rand_neg();
354     if (!BN_add(c.get(), a.get(), b.get())) {
355       return false;
356     }
357     if (fp != NULL) {
358       BN_print_fp(fp, a.get());
359       puts_fp(fp, " + ");
360       BN_print_fp(fp, b.get());
361       puts_fp(fp, " - ");
362       BN_print_fp(fp, c.get());
363       puts_fp(fp, "\n");
364     }
365     a->neg = !a->neg;
366     b->neg = !b->neg;
367     if (!BN_add(c.get(), c.get(), b.get()) ||
368         !BN_add(c.get(), c.get(), a.get())) {
369       return false;
370     }
371     if (!BN_is_zero(c.get())) {
372       fprintf(stderr, "Add test failed!\n");
373       return false;
374     }
375   }
376   return true;
377 }
378 
test_sub(FILE * fp)379 static bool test_sub(FILE *fp) {
380   ScopedBIGNUM a(BN_new());
381   ScopedBIGNUM b(BN_new());
382   ScopedBIGNUM c(BN_new());
383   if (!a || !b || !c) {
384     return false;
385   }
386 
387   for (int i = 0; i < num0 + num1; i++) {
388     if (i < num1) {
389       if (!BN_rand(a.get(), 512, 0, 0) ||
390           !BN_copy(b.get(), a.get()) ||
391           !BN_set_bit(a.get(), i) ||
392           !BN_add_word(b.get(), i)) {
393         return false;
394       }
395     } else {
396       if (!BN_rand(b.get(), 400 + i - num1, 0, 0)) {
397         return false;
398       }
399       a->neg = rand_neg();
400       b->neg = rand_neg();
401     }
402     if (!BN_sub(c.get(), a.get(), b.get())) {
403       return false;
404     }
405     if (fp != NULL) {
406       BN_print_fp(fp, a.get());
407       puts_fp(fp, " - ");
408       BN_print_fp(fp, b.get());
409       puts_fp(fp, " - ");
410       BN_print_fp(fp, c.get());
411       puts_fp(fp, "\n");
412     }
413     if (!BN_add(c.get(), c.get(), b.get()) ||
414         !BN_sub(c.get(), c.get(), a.get())) {
415       return false;
416     }
417     if (!BN_is_zero(c.get())) {
418       fprintf(stderr, "Subtract test failed!\n");
419       return false;
420     }
421   }
422   return true;
423 }
424 
test_div(FILE * fp,BN_CTX * ctx)425 static bool test_div(FILE *fp, BN_CTX *ctx) {
426   ScopedBIGNUM a(BN_new());
427   ScopedBIGNUM b(BN_new());
428   ScopedBIGNUM c(BN_new());
429   ScopedBIGNUM d(BN_new());
430   ScopedBIGNUM e(BN_new());
431   if (!a || !b || !c || !d || !e) {
432     return false;
433   }
434 
435   if (!BN_one(a.get())) {
436     return false;
437   }
438   BN_zero(b.get());
439   if (BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
440     fprintf(stderr, "Division by zero succeeded!\n");
441     return false;
442   }
443   ERR_clear_error();
444 
445   for (int i = 0; i < num0 + num1; i++) {
446     if (i < num1) {
447       if (!BN_rand(a.get(), 400, 0, 0) ||
448           !BN_copy(b.get(), a.get()) ||
449           !BN_lshift(a.get(), a.get(), i) ||
450           !BN_add_word(a.get(), i)) {
451         return false;
452       }
453     } else if (!BN_rand(b.get(), 50 + 3 * (i - num1), 0, 0)) {
454       return false;
455     }
456     a->neg = rand_neg();
457     b->neg = rand_neg();
458     if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
459       return false;
460     }
461     if (fp != NULL) {
462       BN_print_fp(fp, a.get());
463       puts_fp(fp, " / ");
464       BN_print_fp(fp, b.get());
465       puts_fp(fp, " - ");
466       BN_print_fp(fp, d.get());
467       puts_fp(fp, "\n");
468 
469       BN_print_fp(fp, a.get());
470       puts_fp(fp, " % ");
471       BN_print_fp(fp, b.get());
472       puts_fp(fp, " - ");
473       BN_print_fp(fp, c.get());
474       puts_fp(fp, "\n");
475     }
476     if (!BN_mul(e.get(), d.get(), b.get(), ctx) ||
477         !BN_add(d.get(), e.get(), c.get()) ||
478         !BN_sub(d.get(), d.get(), a.get())) {
479       return false;
480     }
481     if (!BN_is_zero(d.get())) {
482       fprintf(stderr, "Division test failed!\n");
483       return false;
484     }
485   }
486 
487   // Test that BN_div never gives negative zero in the quotient.
488   if (!BN_set_word(a.get(), 1) ||
489       !BN_set_word(b.get(), 2)) {
490     return false;
491   }
492   BN_set_negative(a.get(), 1);
493   if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
494     return false;
495   }
496   if (!BN_is_zero(d.get()) || BN_is_negative(d.get())) {
497     fprintf(stderr, "Division test failed!\n");
498     return false;
499   }
500 
501   // Test that BN_div never gives negative zero in the remainder.
502   if (!BN_set_word(b.get(), 1)) {
503     return false;
504   }
505   if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
506     return false;
507   }
508   if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
509     fprintf(stderr, "Division test failed!\n");
510     return false;
511   }
512 
513   return true;
514 }
515 
test_lshift1(FILE * fp)516 static bool test_lshift1(FILE *fp) {
517   ScopedBIGNUM a(BN_new());
518   ScopedBIGNUM b(BN_new());
519   ScopedBIGNUM c(BN_new());
520   if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
521     return false;
522   }
523   a->neg = rand_neg();
524   for (int i = 0; i < num0; i++) {
525     if (!BN_lshift1(b.get(), a.get())) {
526       return false;
527     }
528     if (fp != NULL) {
529       BN_print_fp(fp, a.get());
530       puts_fp(fp, " * 2");
531       puts_fp(fp, " - ");
532       BN_print_fp(fp, b.get());
533       puts_fp(fp, "\n");
534     }
535     if (!BN_add(c.get(), a.get(), a.get()) ||
536         !BN_sub(a.get(), b.get(), c.get())) {
537       return false;
538     }
539     if (!BN_is_zero(a.get())) {
540       fprintf(stderr, "Left shift one test failed!\n");
541       return false;
542     }
543 
544     if (!BN_copy(a.get(), b.get())) {
545       return false;
546     }
547   }
548   return true;
549 }
550 
test_rshift(FILE * fp,BN_CTX * ctx)551 static bool test_rshift(FILE *fp, BN_CTX *ctx) {
552   ScopedBIGNUM a(BN_new());
553   ScopedBIGNUM b(BN_new());
554   ScopedBIGNUM c(BN_new());
555   ScopedBIGNUM d(BN_new());
556   ScopedBIGNUM e(BN_new());
557   if (!a || !b || !c || !d || !e || !BN_one(c.get()) ||
558       !BN_rand(a.get(), 200, 0, 0)) {
559     return false;
560   }
561   a->neg = rand_neg();
562   for (int i = 0; i < num0; i++) {
563     if (!BN_rshift(b.get(), a.get(), i + 1) ||
564         !BN_add(c.get(), c.get(), c.get())) {
565       return false;
566     }
567     if (fp != NULL) {
568       BN_print_fp(fp, a.get());
569       puts_fp(fp, " / ");
570       BN_print_fp(fp, c.get());
571       puts_fp(fp, " - ");
572       BN_print_fp(fp, b.get());
573       puts_fp(fp, "\n");
574     }
575     if (!BN_div(d.get(), e.get(), a.get(), c.get(), ctx) ||
576         !BN_sub(d.get(), d.get(), b.get())) {
577       return false;
578     }
579     if (!BN_is_zero(d.get())) {
580       fprintf(stderr, "Right shift test failed!\n");
581       return false;
582     }
583   }
584   return true;
585 }
586 
test_rshift1(FILE * fp)587 static bool test_rshift1(FILE *fp) {
588   ScopedBIGNUM a(BN_new());
589   ScopedBIGNUM b(BN_new());
590   ScopedBIGNUM c(BN_new());
591   if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
592     return false;
593   }
594   a->neg = rand_neg();
595 
596   for (int i = 0; i < num0; i++) {
597     if (!BN_rshift1(b.get(), a.get())) {
598       return false;
599     }
600     if (fp != NULL) {
601       BN_print_fp(fp, a.get());
602       puts_fp(fp, " / 2");
603       puts_fp(fp, " - ");
604       BN_print_fp(fp, b.get());
605       puts_fp(fp, "\n");
606     }
607     if (!BN_sub(c.get(), a.get(), b.get()) ||
608         !BN_sub(c.get(), c.get(), b.get())) {
609       return false;
610     }
611     if (!BN_is_zero(c.get()) && !BN_abs_is_word(c.get(), 1)) {
612       fprintf(stderr, "Right shift one test failed!\n");
613       return false;
614     }
615     if (!BN_copy(a.get(), b.get())) {
616       return false;
617     }
618   }
619   return true;
620 }
621 
test_lshift(FILE * fp,BN_CTX * ctx,ScopedBIGNUM a)622 static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a) {
623   if (!a) {
624     a.reset(BN_new());
625     if (!a || !BN_rand(a.get(), 200, 0, 0)) {
626       return false;
627     }
628     a->neg = rand_neg();
629   }
630 
631   ScopedBIGNUM b(BN_new());
632   ScopedBIGNUM c(BN_new());
633   ScopedBIGNUM d(BN_new());
634   if (!b || !c || !d || !BN_one(c.get())) {
635     return false;
636   }
637 
638   for (int i = 0; i < num0; i++) {
639     if (!BN_lshift(b.get(), a.get(), i + 1) ||
640         !BN_add(c.get(), c.get(), c.get())) {
641       return false;
642     }
643     if (fp != NULL) {
644       BN_print_fp(fp, a.get());
645       puts_fp(fp, " * ");
646       BN_print_fp(fp, c.get());
647       puts_fp(fp, " - ");
648       BN_print_fp(fp, b.get());
649       puts_fp(fp, "\n");
650     }
651     if (!BN_mul(d.get(), a.get(), c.get(), ctx) ||
652         !BN_sub(d.get(), d.get(), b.get())) {
653       return false;
654     }
655     if (!BN_is_zero(d.get())) {
656       fprintf(stderr, "Left shift test failed!\n");
657       fprintf(stderr, "a=");
658       BN_print_fp(stderr, a.get());
659       fprintf(stderr, "\nb=");
660       BN_print_fp(stderr, b.get());
661       fprintf(stderr, "\nc=");
662       BN_print_fp(stderr, c.get());
663       fprintf(stderr, "\nd=");
664       BN_print_fp(stderr, d.get());
665       fprintf(stderr, "\n");
666       return false;
667     }
668   }
669   return true;
670 }
671 
test_mul(FILE * fp)672 static bool test_mul(FILE *fp) {
673   ScopedBN_CTX ctx(BN_CTX_new());
674   ScopedBIGNUM a(BN_new());
675   ScopedBIGNUM b(BN_new());
676   ScopedBIGNUM c(BN_new());
677   ScopedBIGNUM d(BN_new());
678   ScopedBIGNUM e(BN_new());
679   if (!ctx || !a || !b || !c || !d || !e) {
680     return false;
681   }
682 
683   for (int i = 0; i < num0 + num1; i++) {
684     if (i <= num1) {
685       if (!BN_rand(a.get(), 100, 0, 0) ||
686           !BN_rand(b.get(), 100, 0, 0)) {
687         return false;
688       }
689     } else if (!BN_rand(b.get(), i - num1, 0, 0)) {
690       return false;
691     }
692     a->neg = rand_neg();
693     b->neg = rand_neg();
694     if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) {
695       return false;
696     }
697     if (fp != NULL) {
698       BN_print_fp(fp, a.get());
699       puts_fp(fp, " * ");
700       BN_print_fp(fp, b.get());
701       puts_fp(fp, " - ");
702       BN_print_fp(fp, c.get());
703       puts_fp(fp, "\n");
704     }
705     if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx.get()) ||
706         !BN_sub(d.get(), d.get(), b.get())) {
707       return false;
708     }
709     if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
710       fprintf(stderr, "Multiplication test failed!\n");
711       return false;
712     }
713   }
714 
715   // Test that BN_mul never gives negative zero.
716   if (!BN_set_word(a.get(), 1)) {
717     return false;
718   }
719   BN_set_negative(a.get(), 1);
720   BN_zero(b.get());
721   if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) {
722     return false;
723   }
724   if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
725     fprintf(stderr, "Multiplication test failed!\n");
726     return false;
727   }
728 
729   return true;
730 }
731 
test_sqr(FILE * fp,BN_CTX * ctx)732 static bool test_sqr(FILE *fp, BN_CTX *ctx) {
733   ScopedBIGNUM a(BN_new());
734   ScopedBIGNUM c(BN_new());
735   ScopedBIGNUM d(BN_new());
736   ScopedBIGNUM e(BN_new());
737   if (!a || !c || !d || !e) {
738     return false;
739   }
740 
741   for (int i = 0; i < num0; i++) {
742     if (!BN_rand(a.get(), 40 + i * 10, 0, 0)) {
743       return false;
744     }
745     a->neg = rand_neg();
746     if (!BN_sqr(c.get(), a.get(), ctx)) {
747       return false;
748     }
749     if (fp != NULL) {
750       BN_print_fp(fp, a.get());
751       puts_fp(fp, " * ");
752       BN_print_fp(fp, a.get());
753       puts_fp(fp, " - ");
754       BN_print_fp(fp, c.get());
755       puts_fp(fp, "\n");
756     }
757     if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx) ||
758         !BN_sub(d.get(), d.get(), a.get())) {
759       return false;
760     }
761     if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
762       fprintf(stderr, "Square test failed!\n");
763       return false;
764     }
765   }
766 
767   // Regression test for a BN_sqr overflow bug.
768   BIGNUM *a_raw = a.get();
769   if (!BN_hex2bn(
770           &a_raw,
771           "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000") ||
772       !BN_sqr(c.get(), a.get(), ctx)) {
773     return false;
774   }
775   if (fp != NULL) {
776     BN_print_fp(fp, a.get());
777     puts_fp(fp, " * ");
778     BN_print_fp(fp, a.get());
779     puts_fp(fp, " - ");
780     BN_print_fp(fp, c.get());
781     puts_fp(fp, "\n");
782   }
783   if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
784     return false;
785   }
786   if (BN_cmp(c.get(), d.get())) {
787     fprintf(stderr,
788             "Square test failed: BN_sqr and BN_mul produce "
789             "different results!\n");
790     return false;
791   }
792 
793   // Regression test for a BN_sqr overflow bug.
794   a_raw = a.get();
795   if (!BN_hex2bn(
796           &a_raw,
797           "80000000000000000000000080000001FFFFFFFE000000000000000000000000") ||
798       !BN_sqr(c.get(), a.get(), ctx)) {
799     return false;
800   }
801   if (fp != NULL) {
802     BN_print_fp(fp, a.get());
803     puts_fp(fp, " * ");
804     BN_print_fp(fp, a.get());
805     puts_fp(fp, " - ");
806     BN_print_fp(fp, c.get());
807     puts_fp(fp, "\n");
808   }
809   if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
810     return false;
811   }
812   if (BN_cmp(c.get(), d.get())) {
813     fprintf(stderr,
814             "Square test failed: BN_sqr and BN_mul produce "
815             "different results!\n");
816     return false;
817   }
818 
819   return true;
820 }
821 
822 
rand_neg()823 static int rand_neg() {
824   static unsigned int neg = 0;
825   static const int sign[8] = {0, 0, 0, 1, 1, 0, 1, 1};
826 
827   return sign[(neg++) % 8];
828 }
829 
print_word(FILE * fp,BN_ULONG w)830 static void print_word(FILE *fp, BN_ULONG w) {
831   fprintf(fp, BN_HEX_FMT1, w);
832 }
833 
test_div_word(FILE * fp)834 static bool test_div_word(FILE *fp) {
835   ScopedBIGNUM a(BN_new());
836   ScopedBIGNUM b(BN_new());
837   if (!a || !b) {
838     return false;
839   }
840 
841   for (int i = 0; i < num0; i++) {
842     do {
843       if (!BN_rand(a.get(), 512, -1, 0) ||
844           !BN_rand(b.get(), BN_BITS2, -1, 0)) {
845         return false;
846       }
847     } while (BN_is_zero(b.get()));
848 
849     if (!BN_copy(b.get(), a.get())) {
850       return false;
851     }
852     BN_ULONG s = b->d[0];
853     BN_ULONG r = BN_div_word(b.get(), s);
854     if (r == (BN_ULONG)-1) {
855       return false;
856     }
857 
858     if (fp != NULL) {
859       BN_print_fp(fp, a.get());
860       puts_fp(fp, " / ");
861       print_word(fp, s);
862       puts_fp(fp, " - ");
863       BN_print_fp(fp, b.get());
864       puts_fp(fp, "\n");
865 
866       BN_print_fp(fp, a.get());
867       puts_fp(fp, " % ");
868       print_word(fp, s);
869       puts_fp(fp, " - ");
870       print_word(fp, r);
871       puts_fp(fp, "\n");
872     }
873     if (!BN_mul_word(b.get(), s) ||
874         !BN_add_word(b.get(), r) ||
875         !BN_sub(b.get(), a.get(), b.get())) {
876       return false;
877     }
878     if (!BN_is_zero(b.get())) {
879       fprintf(stderr, "Division (word) test failed!\n");
880       return false;
881     }
882   }
883   return true;
884 }
885 
test_mont(FILE * fp,BN_CTX * ctx)886 static bool test_mont(FILE *fp, BN_CTX *ctx) {
887   ScopedBIGNUM a(BN_new());
888   ScopedBIGNUM b(BN_new());
889   ScopedBIGNUM c(BN_new());
890   ScopedBIGNUM d(BN_new());
891   ScopedBIGNUM A(BN_new());
892   ScopedBIGNUM B(BN_new());
893   ScopedBIGNUM n(BN_new());
894   ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
895   if (!a || !b || !c || !d || !A || !B || !n || !mont) {
896     return false;
897   }
898 
899   BN_zero(n.get());
900   if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) {
901     fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n");
902     return false;
903   }
904   ERR_clear_error();
905 
906   if (!BN_set_word(n.get(), 16)) {
907     return false;
908   }
909   if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) {
910     fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n");
911     return false;
912   }
913   ERR_clear_error();
914 
915   if (!BN_rand(a.get(), 100, 0, 0) ||
916       !BN_rand(b.get(), 100, 0, 0)) {
917     return false;
918   }
919 
920   for (int i = 0; i < num2; i++) {
921     int bits = (200 * (i + 1)) / num2;
922 
923     if (bits == 0) {
924       continue;
925     }
926     if (!BN_rand(n.get(), bits, 0, 1) ||
927         !BN_MONT_CTX_set(mont.get(), n.get(), ctx) ||
928         !BN_nnmod(a.get(), a.get(), n.get(), ctx) ||
929         !BN_nnmod(b.get(), b.get(), n.get(), ctx) ||
930         !BN_to_montgomery(A.get(), a.get(), mont.get(), ctx) ||
931         !BN_to_montgomery(B.get(), b.get(), mont.get(), ctx) ||
932         !BN_mod_mul_montgomery(c.get(), A.get(), B.get(), mont.get(), ctx) ||
933         !BN_from_montgomery(A.get(), c.get(), mont.get(), ctx)) {
934       return false;
935     }
936     if (fp != NULL) {
937       BN_print_fp(fp, a.get());
938       puts_fp(fp, " * ");
939       BN_print_fp(fp, b.get());
940       puts_fp(fp, " % ");
941       BN_print_fp(fp, &mont->N);
942       puts_fp(fp, " - ");
943       BN_print_fp(fp, A.get());
944       puts_fp(fp, "\n");
945     }
946     if (!BN_mod_mul(d.get(), a.get(), b.get(), n.get(), ctx) ||
947         !BN_sub(d.get(), d.get(), A.get())) {
948       return false;
949     }
950     if (!BN_is_zero(d.get())) {
951       fprintf(stderr, "Montgomery multiplication test failed!\n");
952       return false;
953     }
954   }
955 
956   return true;
957 }
958 
test_mod(FILE * fp,BN_CTX * ctx)959 static bool test_mod(FILE *fp, BN_CTX *ctx) {
960   ScopedBIGNUM a(BN_new());
961   ScopedBIGNUM b(BN_new());
962   ScopedBIGNUM c(BN_new());
963   ScopedBIGNUM d(BN_new());
964   ScopedBIGNUM e(BN_new());
965   if (!a || !b || !c || !d || !e ||
966       !BN_rand(a.get(), 1024, 0, 0)) {
967     return false;
968   }
969 
970   for (int i = 0; i < num0; i++) {
971     if (!BN_rand(b.get(), 450 + i * 10, 0, 0)) {
972       return false;
973     }
974     a->neg = rand_neg();
975     b->neg = rand_neg();
976     if (!BN_mod(c.get(), a.get(), b.get(), ctx)) {
977       return false;
978     }
979     if (fp != NULL) {
980       BN_print_fp(fp, a.get());
981       puts_fp(fp, " % ");
982       BN_print_fp(fp, b.get());
983       puts_fp(fp, " - ");
984       BN_print_fp(fp, c.get());
985       puts_fp(fp, "\n");
986     }
987     if (!BN_div(d.get(), e.get(), a.get(), b.get(), ctx) ||
988         !BN_sub(e.get(), e.get(), c.get())) {
989       return false;
990     }
991     if (!BN_is_zero(e.get())) {
992       fprintf(stderr, "Modulo test failed!\n");
993       return false;
994     }
995   }
996   return true;
997 }
998 
test_mod_mul(FILE * fp,BN_CTX * ctx)999 static bool test_mod_mul(FILE *fp, BN_CTX *ctx) {
1000   ScopedBIGNUM a(BN_new());
1001   ScopedBIGNUM b(BN_new());
1002   ScopedBIGNUM c(BN_new());
1003   ScopedBIGNUM d(BN_new());
1004   ScopedBIGNUM e(BN_new());
1005   if (!a || !b || !c || !d || !e) {
1006     return false;
1007   }
1008 
1009   if (!BN_one(a.get()) || !BN_one(b.get())) {
1010     return false;
1011   }
1012   BN_zero(c.get());
1013   if (BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) {
1014     fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n");
1015     return false;
1016   }
1017   ERR_clear_error();
1018 
1019   for (int j = 0; j < 3; j++) {
1020     if (!BN_rand(c.get(), 1024, 0, 0)) {
1021       return false;
1022     }
1023     for (int i = 0; i < num0; i++) {
1024       if (!BN_rand(a.get(), 475 + i * 10, 0, 0) ||
1025           !BN_rand(b.get(), 425 + i * 11, 0, 0)) {
1026         return false;
1027       }
1028       a->neg = rand_neg();
1029       b->neg = rand_neg();
1030       if (!BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) {
1031         ERR_print_errors_fp(stderr);
1032         return false;
1033       }
1034       if (fp != NULL) {
1035         BN_print_fp(fp, a.get());
1036         puts_fp(fp, " * ");
1037         BN_print_fp(fp, b.get());
1038         puts_fp(fp, " % ");
1039         BN_print_fp(fp, c.get());
1040         if (a->neg != b->neg && !BN_is_zero(e.get())) {
1041           // If  (a*b) % c  is negative,  c  must be added
1042           // in order to obtain the normalized remainder
1043           // (new with OpenSSL 0.9.7, previous versions of
1044           // BN_mod_mul could generate negative results)
1045           puts_fp(fp, " + ");
1046           BN_print_fp(fp, c.get());
1047         }
1048         puts_fp(fp, " - ");
1049         BN_print_fp(fp, e.get());
1050         puts_fp(fp, "\n");
1051       }
1052       if (!BN_mul(d.get(), a.get(), b.get(), ctx) ||
1053           !BN_sub(d.get(), d.get(), e.get()) ||
1054           !BN_div(a.get(), b.get(), d.get(), c.get(), ctx)) {
1055         return false;
1056       }
1057       if (!BN_is_zero(b.get())) {
1058         fprintf(stderr, "Modulo multiply test failed!\n");
1059         ERR_print_errors_fp(stderr);
1060         return false;
1061       }
1062     }
1063   }
1064   return true;
1065 }
1066 
test_mod_exp(FILE * fp,BN_CTX * ctx)1067 static bool test_mod_exp(FILE *fp, BN_CTX *ctx) {
1068   ScopedBIGNUM a(BN_new());
1069   ScopedBIGNUM b(BN_new());
1070   ScopedBIGNUM c(BN_new());
1071   ScopedBIGNUM d(BN_new());
1072   ScopedBIGNUM e(BN_new());
1073   if (!a || !b || !c || !d || !e) {
1074     return false;
1075   }
1076 
1077   if (!BN_one(a.get()) || !BN_one(b.get())) {
1078     return false;
1079   }
1080   BN_zero(c.get());
1081   if (BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) {
1082     fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n");
1083     return 0;
1084   }
1085   ERR_clear_error();
1086 
1087   if (!BN_rand(c.get(), 30, 0, 1)) {  // must be odd for montgomery
1088     return false;
1089   }
1090   for (int i = 0; i < num2; i++) {
1091     if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
1092         !BN_rand(b.get(), 2 + i, 0, 0) ||
1093         !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) {
1094       return false;
1095     }
1096 
1097     if (fp != NULL) {
1098       BN_print_fp(fp, a.get());
1099       puts_fp(fp, " ^ ");
1100       BN_print_fp(fp, b.get());
1101       puts_fp(fp, " % ");
1102       BN_print_fp(fp, c.get());
1103       puts_fp(fp, " - ");
1104       BN_print_fp(fp, d.get());
1105       puts_fp(fp, "\n");
1106     }
1107     if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
1108         !BN_sub(e.get(), e.get(), d.get()) ||
1109         !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
1110       return false;
1111     }
1112     if (!BN_is_zero(b.get())) {
1113       fprintf(stderr, "Modulo exponentiation test failed!\n");
1114       return false;
1115     }
1116   }
1117 
1118    // Regression test for carry propagation bug in sqr8x_reduction.
1119   if (!HexToBIGNUM(&a, "050505050505") ||
1120       !HexToBIGNUM(&b, "02") ||
1121       !HexToBIGNUM(
1122           &c,
1123           "4141414141414141414141274141414141414141414141414141414141414141"
1124           "4141414141414141414141414141414141414141414141414141414141414141"
1125           "4141414141414141414141800000000000000000000000000000000000000000"
1126           "0000000000000000000000000000000000000000000000000000000000000000"
1127           "0000000000000000000000000000000000000000000000000000000000000000"
1128           "0000000000000000000000000000000000000000000000000000000001") ||
1129       !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx) ||
1130       !BN_mul(e.get(), a.get(), a.get(), ctx)) {
1131     return false;
1132   }
1133   if (BN_cmp(d.get(), e.get()) != 0) {
1134     fprintf(stderr, "BN_mod_exp and BN_mul produce different results!\n");
1135     return false;
1136   }
1137 
1138   return true;
1139 }
1140 
test_mod_exp_mont_consttime(FILE * fp,BN_CTX * ctx)1141 static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx) {
1142   ScopedBIGNUM a(BN_new());
1143   ScopedBIGNUM b(BN_new());
1144   ScopedBIGNUM c(BN_new());
1145   ScopedBIGNUM d(BN_new());
1146   ScopedBIGNUM e(BN_new());
1147   if (!a || !b || !c || !d || !e) {
1148     return false;
1149   }
1150 
1151   if (!BN_one(a.get()) || !BN_one(b.get())) {
1152     return false;
1153   }
1154   BN_zero(c.get());
1155   if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
1156                                 nullptr)) {
1157     fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus succeeded!\n");
1158     return 0;
1159   }
1160   ERR_clear_error();
1161 
1162   if (!BN_set_word(c.get(), 16)) {
1163     return false;
1164   }
1165   if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
1166                                 nullptr)) {
1167     fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus succeeded!\n");
1168     return 0;
1169   }
1170   ERR_clear_error();
1171 
1172   if (!BN_rand(c.get(), 30, 0, 1)) {  // must be odd for montgomery
1173     return false;
1174   }
1175   for (int i = 0; i < num2; i++) {
1176     if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
1177         !BN_rand(b.get(), 2 + i, 0, 0) ||
1178         !BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
1179                                    NULL)) {
1180       return false;
1181     }
1182 
1183     if (fp != NULL) {
1184       BN_print_fp(fp, a.get());
1185       puts_fp(fp, " ^ ");
1186       BN_print_fp(fp, b.get());
1187       puts_fp(fp, " % ");
1188       BN_print_fp(fp, c.get());
1189       puts_fp(fp, " - ");
1190       BN_print_fp(fp, d.get());
1191       puts_fp(fp, "\n");
1192     }
1193     if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
1194         !BN_sub(e.get(), e.get(), d.get()) ||
1195         !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
1196       return false;
1197     }
1198     if (!BN_is_zero(b.get())) {
1199       fprintf(stderr, "Modulo exponentiation test failed!\n");
1200       return false;
1201     }
1202   }
1203   return true;
1204 }
1205 
1206 // Test constant-time modular exponentiation with 1024-bit inputs,
1207 // which on x86_64 cause a different code branch to be taken.
test_mod_exp_mont5(FILE * fp,BN_CTX * ctx)1208 static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx) {
1209   ScopedBIGNUM a(BN_new());
1210   ScopedBIGNUM p(BN_new());
1211   ScopedBIGNUM m(BN_new());
1212   ScopedBIGNUM d(BN_new());
1213   ScopedBIGNUM e(BN_new());
1214   if (!a || !p || !m || !d || !e ||
1215       !BN_rand(m.get(), 1024, 0, 1) ||  // must be odd for montgomery
1216       !BN_rand(a.get(), 1024, 0, 0)) {
1217     return false;
1218   }
1219   // Zero exponent.
1220   BN_zero(p.get());
1221   if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
1222                                  NULL)) {
1223     return false;
1224   }
1225   if (!BN_is_one(d.get())) {
1226     fprintf(stderr, "Modular exponentiation test failed!\n");
1227     return false;
1228   }
1229   if (!BN_rand(p.get(), 1024, 0, 0)) {
1230     return false;
1231   }
1232   // Zero input.
1233   BN_zero(a.get());
1234   if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
1235                                  NULL)) {
1236     return false;
1237   }
1238   if (!BN_is_zero(d.get())) {
1239     fprintf(stderr, "Modular exponentiation test failed!\n");
1240     return false;
1241   }
1242   // Craft an input whose Montgomery representation is 1, i.e., shorter than the
1243   // modulus m, in order to test the const time precomputation
1244   // scattering/gathering.
1245   ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
1246   if (!mont || !BN_one(a.get()) ||
1247       !BN_MONT_CTX_set(mont.get(), m.get(), ctx) ||
1248       !BN_from_montgomery(e.get(), a.get(), mont.get(), ctx) ||
1249       !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
1250                                  NULL) ||
1251       !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
1252     return false;
1253   }
1254   if (BN_cmp(a.get(), d.get()) != 0) {
1255     fprintf(stderr, "Modular exponentiation test failed!\n");
1256     return false;
1257   }
1258   // Finally, some regular test vectors.
1259   if (!BN_rand(e.get(), 1024, 0, 0) ||
1260       !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
1261                                  NULL) ||
1262       !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
1263     return false;
1264   }
1265   if (BN_cmp(a.get(), d.get()) != 0) {
1266     fprintf(stderr, "Modular exponentiation test failed!\n");
1267     return false;
1268   }
1269 
1270   return true;
1271 }
1272 
test_exp(FILE * fp,BN_CTX * ctx)1273 static bool test_exp(FILE *fp, BN_CTX *ctx) {
1274   ScopedBIGNUM a(BN_new());
1275   ScopedBIGNUM b(BN_new());
1276   ScopedBIGNUM d(BN_new());
1277   ScopedBIGNUM e(BN_new());
1278   if (!a || !b || !d || !e) {
1279     return false;
1280   }
1281 
1282   for (int i = 0; i < num2; i++) {
1283     if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
1284         !BN_rand(b.get(), 2 + i, 0, 0) ||
1285         !BN_exp(d.get(), a.get(), b.get(), ctx)) {
1286       return false;
1287     }
1288 
1289     if (fp != NULL) {
1290       BN_print_fp(fp, a.get());
1291       puts_fp(fp, " ^ ");
1292       BN_print_fp(fp, b.get());
1293       puts_fp(fp, " - ");
1294       BN_print_fp(fp, d.get());
1295       puts_fp(fp, "\n");
1296     }
1297     if (!BN_one(e.get())) {
1298       return false;
1299     }
1300     while (!BN_is_zero(b.get())) {
1301       if (!BN_mul(e.get(), e.get(), a.get(), ctx) ||
1302           !BN_sub(b.get(), b.get(), BN_value_one())) {
1303         return false;
1304       }
1305     }
1306     if (!BN_sub(e.get(), e.get(), d.get())) {
1307       return false;
1308     }
1309     if (!BN_is_zero(e.get())) {
1310       fprintf(stderr, "Exponentiation test failed!\n");
1311       return false;
1312     }
1313   }
1314   return true;
1315 }
1316 
1317 // test_exp_mod_zero tests that 1**0 mod 1 == 0.
test_exp_mod_zero(void)1318 static bool test_exp_mod_zero(void) {
1319   ScopedBIGNUM zero(BN_new()), a(BN_new()), r(BN_new());
1320   if (!zero || !a || !r || !BN_rand(a.get(), 1024, 0, 0)) {
1321     return false;
1322   }
1323   BN_zero(zero.get());
1324 
1325   if (!BN_mod_exp(r.get(), a.get(), zero.get(), BN_value_one(), nullptr) ||
1326       !BN_is_zero(r.get()) ||
1327       !BN_mod_exp_mont(r.get(), a.get(), zero.get(), BN_value_one(), nullptr,
1328                        nullptr) ||
1329       !BN_is_zero(r.get()) ||
1330       !BN_mod_exp_mont_consttime(r.get(), a.get(), zero.get(), BN_value_one(),
1331                                  nullptr, nullptr) ||
1332       !BN_is_zero(r.get()) ||
1333       !BN_mod_exp_mont_word(r.get(), 42, zero.get(), BN_value_one(), nullptr,
1334                             nullptr) ||
1335       !BN_is_zero(r.get())) {
1336     return false;
1337   }
1338 
1339   return true;
1340 }
1341 
test_mod_sqrt(FILE * fp,BN_CTX * ctx)1342 static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx) {
1343   ScopedBIGNUM a(BN_new());
1344   ScopedBIGNUM p(BN_new());
1345   ScopedBIGNUM r(BN_new());
1346   if (!a || !p || !r) {
1347     return false;
1348   }
1349 
1350   for (int i = 0; i < 16; i++) {
1351     if (i < 8) {
1352       const unsigned kPrimes[8] = {2, 3, 5, 7, 11, 13, 17, 19};
1353       if (!BN_set_word(p.get(), kPrimes[i])) {
1354         return false;
1355       }
1356     } else {
1357       if (!BN_set_word(a.get(), 32) ||
1358           !BN_set_word(r.get(), 2 * i + 1) ||
1359           !BN_generate_prime_ex(p.get(), 256, 0, a.get(), r.get(), nullptr)) {
1360         return false;
1361       }
1362     }
1363     p->neg = rand_neg();
1364 
1365     for (int j = 0; j < num2; j++) {
1366       // construct 'a' such that it is a square modulo p, but in general not a
1367       // proper square and not reduced modulo p
1368       if (!BN_rand(r.get(), 256, 0, 3) ||
1369           !BN_nnmod(r.get(), r.get(), p.get(), ctx) ||
1370           !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
1371           !BN_rand(a.get(), 256, 0, 3) ||
1372           !BN_nnmod(a.get(), a.get(), p.get(), ctx) ||
1373           !BN_mod_sqr(a.get(), a.get(), p.get(), ctx) ||
1374           !BN_mul(a.get(), a.get(), r.get(), ctx)) {
1375         return false;
1376       }
1377       if (rand_neg() && !BN_sub(a.get(), a.get(), p.get())) {
1378         return false;
1379       }
1380 
1381       if (!BN_mod_sqrt(r.get(), a.get(), p.get(), ctx) ||
1382           !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
1383           !BN_nnmod(a.get(), a.get(), p.get(), ctx)) {
1384         return false;
1385       }
1386 
1387       if (BN_cmp(a.get(), r.get()) != 0) {
1388         fprintf(stderr, "BN_mod_sqrt failed: a = ");
1389         BN_print_fp(stderr, a.get());
1390         fprintf(stderr, ", r = ");
1391         BN_print_fp(stderr, r.get());
1392         fprintf(stderr, ", p = ");
1393         BN_print_fp(stderr, p.get());
1394         fprintf(stderr, "\n");
1395         return false;
1396       }
1397     }
1398   }
1399   return true;
1400 }
1401 
test_small_prime(FILE * fp,BN_CTX * ctx)1402 static bool test_small_prime(FILE *fp, BN_CTX *ctx) {
1403   static const unsigned kBits = 10;
1404 
1405   ScopedBIGNUM r(BN_new());
1406   if (!r || !BN_generate_prime_ex(r.get(), static_cast<int>(kBits), 0, NULL,
1407                                   NULL, NULL)) {
1408     return false;
1409   }
1410   if (BN_num_bits(r.get()) != kBits) {
1411     fprintf(fp, "Expected %u bit prime, got %u bit number\n", kBits,
1412             BN_num_bits(r.get()));
1413     return false;
1414   }
1415 
1416   return true;
1417 }
1418 
test_sqrt(FILE * fp,BN_CTX * ctx)1419 static bool test_sqrt(FILE *fp, BN_CTX *ctx) {
1420   ScopedBIGNUM n(BN_new());
1421   ScopedBIGNUM nn(BN_new());
1422   ScopedBIGNUM sqrt(BN_new());
1423   if (!n || !nn || !sqrt) {
1424     return false;
1425   }
1426 
1427   // Test some random squares.
1428   for (int i = 0; i < 100; i++) {
1429     if (!BN_rand(n.get(), 1024 /* bit length */,
1430                  -1 /* no modification of top bits */,
1431                  0 /* don't modify bottom bit */) ||
1432         !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
1433         !BN_sqrt(sqrt.get(), nn.get(), ctx)) {
1434       ERR_print_errors_fp(stderr);
1435       return false;
1436     }
1437     if (BN_cmp(n.get(), sqrt.get()) != 0) {
1438       fprintf(stderr, "Bad result from BN_sqrt.\n");
1439       return false;
1440     }
1441   }
1442 
1443   // Test some non-squares.
1444   for (int i = 0; i < 100; i++) {
1445     if (!BN_rand(n.get(), 1024 /* bit length */,
1446                  -1 /* no modification of top bits */,
1447                  0 /* don't modify bottom bit */) ||
1448         !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
1449         !BN_add(nn.get(), nn.get(), BN_value_one())) {
1450       ERR_print_errors_fp(stderr);
1451       return false;
1452     }
1453 
1454     if (BN_sqrt(sqrt.get(), nn.get(), ctx)) {
1455       char *nn_str = BN_bn2dec(nn.get());
1456       fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str);
1457       OPENSSL_free(nn_str);
1458     }
1459   }
1460 
1461   return true;
1462 }
1463 
test_bn2bin_padded(BN_CTX * ctx)1464 static bool test_bn2bin_padded(BN_CTX *ctx) {
1465   uint8_t zeros[256], out[256], reference[128];
1466 
1467   memset(zeros, 0, sizeof(zeros));
1468 
1469   // Test edge case at 0.
1470   ScopedBIGNUM n(BN_new());
1471   if (!n || !BN_bn2bin_padded(NULL, 0, n.get())) {
1472     fprintf(stderr,
1473             "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n");
1474     return false;
1475   }
1476   memset(out, -1, sizeof(out));
1477   if (!BN_bn2bin_padded(out, sizeof(out), n.get())) {
1478     fprintf(stderr,
1479             "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n");
1480     return false;
1481   }
1482   if (memcmp(zeros, out, sizeof(out))) {
1483     fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n");
1484     return false;
1485   }
1486 
1487   // Test a random numbers at various byte lengths.
1488   for (size_t bytes = 128 - 7; bytes <= 128; bytes++) {
1489     if (!BN_rand(n.get(), bytes * 8, 0 /* make sure top bit is 1 */,
1490                  0 /* don't modify bottom bit */)) {
1491       ERR_print_errors_fp(stderr);
1492       return false;
1493     }
1494     if (BN_num_bytes(n.get()) != bytes ||
1495         BN_bn2bin(n.get(), reference) != bytes) {
1496       fprintf(stderr, "Bad result from BN_rand; bytes.\n");
1497       return false;
1498     }
1499     // Empty buffer should fail.
1500     if (BN_bn2bin_padded(NULL, 0, n.get())) {
1501       fprintf(stderr,
1502               "BN_bn2bin_padded incorrectly succeeded on empty buffer.\n");
1503       return false;
1504     }
1505     // One byte short should fail.
1506     if (BN_bn2bin_padded(out, bytes - 1, n.get())) {
1507       fprintf(stderr, "BN_bn2bin_padded incorrectly succeeded on short.\n");
1508       return false;
1509     }
1510     // Exactly right size should encode.
1511     if (!BN_bn2bin_padded(out, bytes, n.get()) ||
1512         memcmp(out, reference, bytes) != 0) {
1513       fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
1514       return false;
1515     }
1516     // Pad up one byte extra.
1517     if (!BN_bn2bin_padded(out, bytes + 1, n.get()) ||
1518         memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) {
1519       fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
1520       return false;
1521     }
1522     // Pad up to 256.
1523     if (!BN_bn2bin_padded(out, sizeof(out), n.get()) ||
1524         memcmp(out + sizeof(out) - bytes, reference, bytes) ||
1525         memcmp(out, zeros, sizeof(out) - bytes)) {
1526       fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
1527       return false;
1528     }
1529   }
1530 
1531   return true;
1532 }
1533 
DecimalToBIGNUM(ScopedBIGNUM * out,const char * in)1534 static int DecimalToBIGNUM(ScopedBIGNUM *out, const char *in) {
1535   BIGNUM *raw = NULL;
1536   int ret = BN_dec2bn(&raw, in);
1537   out->reset(raw);
1538   return ret;
1539 }
1540 
test_dec2bn(BN_CTX * ctx)1541 static bool test_dec2bn(BN_CTX *ctx) {
1542   ScopedBIGNUM bn;
1543   int ret = DecimalToBIGNUM(&bn, "0");
1544   if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1545     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1546     return false;
1547   }
1548 
1549   ret = DecimalToBIGNUM(&bn, "256");
1550   if (ret != 3 || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) {
1551     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1552     return false;
1553   }
1554 
1555   ret = DecimalToBIGNUM(&bn, "-42");
1556   if (ret != 3 || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) {
1557     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1558     return false;
1559   }
1560 
1561   ret = DecimalToBIGNUM(&bn, "-0");
1562   if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1563     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1564     return false;
1565   }
1566 
1567   ret = DecimalToBIGNUM(&bn, "42trailing garbage is ignored");
1568   if (ret != 2 || !BN_abs_is_word(bn.get(), 42) || BN_is_negative(bn.get())) {
1569     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
1570     return false;
1571   }
1572 
1573   return true;
1574 }
1575 
test_hex2bn(BN_CTX * ctx)1576 static bool test_hex2bn(BN_CTX *ctx) {
1577   ScopedBIGNUM bn;
1578   int ret = HexToBIGNUM(&bn, "0");
1579   if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1580     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1581     return false;
1582   }
1583 
1584   ret = HexToBIGNUM(&bn, "256");
1585   if (ret != 3 || !BN_is_word(bn.get(), 0x256) || BN_is_negative(bn.get())) {
1586     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1587     return false;
1588   }
1589 
1590   ret = HexToBIGNUM(&bn, "-42");
1591   if (ret != 3 || !BN_abs_is_word(bn.get(), 0x42) || !BN_is_negative(bn.get())) {
1592     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1593     return false;
1594   }
1595 
1596   ret = HexToBIGNUM(&bn, "-0");
1597   if (ret != 2 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1598     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1599     return false;
1600   }
1601 
1602   ret = HexToBIGNUM(&bn, "abctrailing garbage is ignored");
1603   if (ret != 3 || !BN_is_word(bn.get(), 0xabc) || BN_is_negative(bn.get())) {
1604     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
1605     return false;
1606   }
1607 
1608   return true;
1609 }
1610 
ASCIIToBIGNUM(const char * in)1611 static ScopedBIGNUM ASCIIToBIGNUM(const char *in) {
1612   BIGNUM *raw = NULL;
1613   if (!BN_asc2bn(&raw, in)) {
1614     return nullptr;
1615   }
1616   return ScopedBIGNUM(raw);
1617 }
1618 
test_asc2bn(BN_CTX * ctx)1619 static bool test_asc2bn(BN_CTX *ctx) {
1620   ScopedBIGNUM bn = ASCIIToBIGNUM("0");
1621   if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1622     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1623     return false;
1624   }
1625 
1626   bn = ASCIIToBIGNUM("256");
1627   if (!bn || !BN_is_word(bn.get(), 256) || BN_is_negative(bn.get())) {
1628     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1629     return false;
1630   }
1631 
1632   bn = ASCIIToBIGNUM("-42");
1633   if (!bn || !BN_abs_is_word(bn.get(), 42) || !BN_is_negative(bn.get())) {
1634     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1635     return false;
1636   }
1637 
1638   bn = ASCIIToBIGNUM("0x1234");
1639   if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) {
1640     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1641     return false;
1642   }
1643 
1644   bn = ASCIIToBIGNUM("0X1234");
1645   if (!bn || !BN_is_word(bn.get(), 0x1234) || BN_is_negative(bn.get())) {
1646     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1647     return false;
1648   }
1649 
1650   bn = ASCIIToBIGNUM("-0xabcd");
1651   if (!bn || !BN_abs_is_word(bn.get(), 0xabcd) || !BN_is_negative(bn.get())) {
1652     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1653     return false;
1654   }
1655 
1656   bn = ASCIIToBIGNUM("-0");
1657   if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
1658     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1659     return false;
1660   }
1661 
1662   bn = ASCIIToBIGNUM("123trailing garbage is ignored");
1663   if (!bn || !BN_is_word(bn.get(), 123) || BN_is_negative(bn.get())) {
1664     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
1665     return false;
1666   }
1667 
1668   return true;
1669 }
1670 
1671 struct MPITest {
1672   const char *base10;
1673   const char *mpi;
1674   size_t mpi_len;
1675 };
1676 
1677 static const MPITest kMPITests[] = {
1678   { "0", "\x00\x00\x00\x00", 4 },
1679   { "1", "\x00\x00\x00\x01\x01", 5 },
1680   { "-1", "\x00\x00\x00\x01\x81", 5 },
1681   { "128", "\x00\x00\x00\x02\x00\x80", 6 },
1682   { "256", "\x00\x00\x00\x02\x01\x00", 6 },
1683   { "-256", "\x00\x00\x00\x02\x81\x00", 6 },
1684 };
1685 
test_mpi()1686 static bool test_mpi() {
1687   uint8_t scratch[8];
1688 
1689   for (size_t i = 0; i < sizeof(kMPITests) / sizeof(kMPITests[0]); i++) {
1690     const MPITest &test = kMPITests[i];
1691     ScopedBIGNUM bn(ASCIIToBIGNUM(test.base10));
1692     const size_t mpi_len = BN_bn2mpi(bn.get(), NULL);
1693     if (mpi_len > sizeof(scratch)) {
1694       fprintf(stderr, "MPI test #%u: MPI size is too large to test.\n",
1695               (unsigned)i);
1696       return false;
1697     }
1698 
1699     const size_t mpi_len2 = BN_bn2mpi(bn.get(), scratch);
1700     if (mpi_len != mpi_len2) {
1701       fprintf(stderr, "MPI test #%u: length changes.\n", (unsigned)i);
1702       return false;
1703     }
1704 
1705     if (mpi_len != test.mpi_len ||
1706         memcmp(test.mpi, scratch, mpi_len) != 0) {
1707       fprintf(stderr, "MPI test #%u failed:\n", (unsigned)i);
1708       hexdump(stderr, "Expected: ", test.mpi, test.mpi_len);
1709       hexdump(stderr, "Got:      ", scratch, mpi_len);
1710       return false;
1711     }
1712 
1713     ScopedBIGNUM bn2(BN_mpi2bn(scratch, mpi_len, NULL));
1714     if (bn2.get() == nullptr) {
1715       fprintf(stderr, "MPI test #%u: failed to parse\n", (unsigned)i);
1716       return false;
1717     }
1718 
1719     if (BN_cmp(bn.get(), bn2.get()) != 0) {
1720       fprintf(stderr, "MPI test #%u: wrong result\n", (unsigned)i);
1721       return false;
1722     }
1723   }
1724 
1725   return true;
1726 }
1727 
test_rand()1728 static bool test_rand() {
1729   ScopedBIGNUM bn(BN_new());
1730   if (!bn) {
1731     return false;
1732   }
1733 
1734   // Test BN_rand accounts for degenerate cases with |top| and |bottom|
1735   // parameters.
1736   if (!BN_rand(bn.get(), 0, 0 /* top */, 0 /* bottom */) ||
1737       !BN_is_zero(bn.get())) {
1738     fprintf(stderr, "BN_rand gave a bad result.\n");
1739     return false;
1740   }
1741   if (!BN_rand(bn.get(), 0, 1 /* top */, 1 /* bottom */) ||
1742       !BN_is_zero(bn.get())) {
1743     fprintf(stderr, "BN_rand gave a bad result.\n");
1744     return false;
1745   }
1746 
1747   if (!BN_rand(bn.get(), 1, 0 /* top */, 0 /* bottom */) ||
1748       !BN_is_word(bn.get(), 1)) {
1749     fprintf(stderr, "BN_rand gave a bad result.\n");
1750     return false;
1751   }
1752   if (!BN_rand(bn.get(), 1, 1 /* top */, 0 /* bottom */) ||
1753       !BN_is_word(bn.get(), 1)) {
1754     fprintf(stderr, "BN_rand gave a bad result.\n");
1755     return false;
1756   }
1757   if (!BN_rand(bn.get(), 1, -1 /* top */, 1 /* bottom */) ||
1758       !BN_is_word(bn.get(), 1)) {
1759     fprintf(stderr, "BN_rand gave a bad result.\n");
1760     return false;
1761   }
1762 
1763   if (!BN_rand(bn.get(), 2, 1 /* top */, 0 /* bottom */) ||
1764       !BN_is_word(bn.get(), 3)) {
1765     fprintf(stderr, "BN_rand gave a bad result.\n");
1766     return false;
1767   }
1768 
1769   return true;
1770 }
1771 
1772 struct ASN1Test {
1773   const char *value_ascii;
1774   const char *der;
1775   size_t der_len;
1776 };
1777 
1778 static const ASN1Test kASN1Tests[] = {
1779     {"0", "\x02\x01\x00", 3},
1780     {"1", "\x02\x01\x01", 3},
1781     {"127", "\x02\x01\x7f", 3},
1782     {"128", "\x02\x02\x00\x80", 4},
1783     {"0xdeadbeef", "\x02\x05\x00\xde\xad\xbe\xef", 7},
1784     {"0x0102030405060708",
1785      "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
1786     {"0xffffffffffffffff",
1787       "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
1788 };
1789 
1790 struct ASN1InvalidTest {
1791   const char *der;
1792   size_t der_len;
1793 };
1794 
1795 static const ASN1InvalidTest kASN1InvalidTests[] = {
1796     // Bad tag.
1797     {"\x03\x01\x00", 3},
1798     // Empty contents.
1799     {"\x02\x00", 2},
1800 };
1801 
1802 // kASN1BuggyTests are incorrect encodings and how |BN_cbs2unsigned_buggy|
1803 // should interpret them.
1804 static const ASN1Test kASN1BuggyTests[] = {
1805     // Negative numbers.
1806     {"128", "\x02\x01\x80", 3},
1807     {"255", "\x02\x01\xff", 3},
1808     // Unnecessary leading zeros.
1809     {"1", "\x02\x02\x00\x01", 4},
1810 };
1811 
test_asn1()1812 static bool test_asn1() {
1813   for (const ASN1Test &test : kASN1Tests) {
1814     ScopedBIGNUM bn = ASCIIToBIGNUM(test.value_ascii);
1815     if (!bn) {
1816       return false;
1817     }
1818 
1819     // Test that the input is correctly parsed.
1820     ScopedBIGNUM bn2(BN_new());
1821     if (!bn2) {
1822       return false;
1823     }
1824     CBS cbs;
1825     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
1826     if (!BN_cbs2unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
1827       fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
1828       return false;
1829     }
1830     if (BN_cmp(bn.get(), bn2.get()) != 0) {
1831       fprintf(stderr, "Bad parse.\n");
1832       return false;
1833     }
1834 
1835     // Test the value serializes correctly.
1836     CBB cbb;
1837     uint8_t *der;
1838     size_t der_len;
1839     CBB_zero(&cbb);
1840     if (!CBB_init(&cbb, 0) ||
1841         !BN_bn2cbb(&cbb, bn.get()) ||
1842         !CBB_finish(&cbb, &der, &der_len)) {
1843       CBB_cleanup(&cbb);
1844       return false;
1845     }
1846     ScopedOpenSSLBytes delete_der(der);
1847     if (der_len != test.der_len ||
1848         memcmp(der, reinterpret_cast<const uint8_t*>(test.der), der_len) != 0) {
1849       fprintf(stderr, "Bad serialization.\n");
1850       return false;
1851     }
1852 
1853     // |BN_cbs2unsigned_buggy| parses all valid input.
1854     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
1855     if (!BN_cbs2unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
1856       fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
1857       return false;
1858     }
1859     if (BN_cmp(bn.get(), bn2.get()) != 0) {
1860       fprintf(stderr, "Bad parse.\n");
1861       return false;
1862     }
1863   }
1864 
1865   for (const ASN1InvalidTest &test : kASN1InvalidTests) {
1866     ScopedBIGNUM bn(BN_new());
1867     if (!bn) {
1868       return false;
1869     }
1870     CBS cbs;
1871     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
1872     if (BN_cbs2unsigned(&cbs, bn.get())) {
1873       fprintf(stderr, "Parsed invalid input.\n");
1874       return false;
1875     }
1876     ERR_clear_error();
1877 
1878     // All tests in kASN1InvalidTests are also rejected by
1879     // |BN_cbs2unsigned_buggy|.
1880     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
1881     if (BN_cbs2unsigned_buggy(&cbs, bn.get())) {
1882       fprintf(stderr, "Parsed invalid input.\n");
1883       return false;
1884     }
1885     ERR_clear_error();
1886   }
1887 
1888   for (const ASN1Test &test : kASN1BuggyTests) {
1889     // These broken encodings are rejected by |BN_cbs2unsigned|.
1890     ScopedBIGNUM bn(BN_new());
1891     if (!bn) {
1892       return false;
1893     }
1894 
1895     CBS cbs;
1896     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
1897     if (BN_cbs2unsigned(&cbs, bn.get())) {
1898       fprintf(stderr, "Parsed invalid input.\n");
1899       return false;
1900     }
1901     ERR_clear_error();
1902 
1903     // However |BN_cbs2unsigned_buggy| accepts them.
1904     ScopedBIGNUM bn2 = ASCIIToBIGNUM(test.value_ascii);
1905     if (!bn2) {
1906       return false;
1907     }
1908 
1909     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
1910     if (!BN_cbs2unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) {
1911       fprintf(stderr, "Parsing (invalid) ASN.1 INTEGER failed.\n");
1912       return false;
1913     }
1914 
1915     if (BN_cmp(bn.get(), bn2.get()) != 0) {
1916       fprintf(stderr, "\"Bad\" parse.\n");
1917       return false;
1918     }
1919   }
1920 
1921   // Serializing negative numbers is not supported.
1922   ScopedBIGNUM bn = ASCIIToBIGNUM("-1");
1923   if (!bn) {
1924     return false;
1925   }
1926   CBB cbb;
1927   CBB_zero(&cbb);
1928   if (!CBB_init(&cbb, 0) ||
1929       BN_bn2cbb(&cbb, bn.get())) {
1930     fprintf(stderr, "Serialized negative number.\n");
1931     CBB_cleanup(&cbb);
1932     return false;
1933   }
1934   CBB_cleanup(&cbb);
1935 
1936   return true;
1937 }
1938