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