blob: caef5722af6ac748d1a6cf771c703bc6435a1d8c [file] [log] [blame]
David Benjamina5974bf2015-03-25 23:49:37 -04001/* 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#include <stdio.h>
71#include <string.h>
72
73#include <openssl/bio.h>
74#include <openssl/bn.h>
75#include <openssl/crypto.h>
76#include <openssl/err.h>
77#include <openssl/mem.h>
78
79#include "../crypto/test/scoped_types.h"
80#include "internal.h"
81
82
83static const int num0 = 100; // number of tests
84static const int num1 = 50; // additional tests for some functions
85static const int num2 = 5; // number of tests for slow functions
86
87static bool test_add(BIO *bp);
88static bool test_sub(BIO *bp);
89static bool test_lshift1(BIO *bp);
90static bool test_lshift(BIO *bp, BN_CTX *ctx, ScopedBIGNUM a);
91static bool test_rshift1(BIO *bp);
92static bool test_rshift(BIO *bp, BN_CTX *ctx);
93static bool test_sqr(BIO *bp, BN_CTX *ctx);
94static bool test_mul(BIO *bp);
95static bool test_div(BIO *bp, BN_CTX *ctx);
96static int rand_neg();
97
98static bool test_div_word(BIO *bp);
99static bool test_mont(BIO *bp, BN_CTX *ctx);
100static bool test_mod(BIO *bp, BN_CTX *ctx);
101static bool test_mod_mul(BIO *bp, BN_CTX *ctx);
102static bool test_mod_exp(BIO *bp, BN_CTX *ctx);
103static bool test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx);
104static bool test_exp(BIO *bp, BN_CTX *ctx);
105static bool test_mod_sqrt(BIO *bp, BN_CTX *ctx);
106static bool test_exp_mod_zero(void);
107static bool test_small_prime(BIO *bp, BN_CTX *ctx);
108static bool test_mod_exp_mont5(BIO *bp, BN_CTX *ctx);
109static bool test_sqrt(BIO *bp, BN_CTX *ctx);
110static bool test_bn2bin_padded(BIO *bp, BN_CTX *ctx);
111
112// g_results can be set to true to cause the result of each computation to be
113// printed.
114static bool g_results = false;
115
116static const uint8_t kSample[] =
117 "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
118 "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
119
120static void message(BIO *out, const char *m) {
121 BIO_puts(out, "print \"test ");
122 BIO_puts(out, m);
123 BIO_puts(out, "\\n\"\n");
124}
125
126int main(int argc, char *argv[]) {
127 char *outfile = NULL;
128
129 CRYPTO_library_init();
130
131 argc--;
132 argv++;
133 while (argc >= 1) {
134 if (strcmp(*argv, "-results") == 0) {
135 g_results = true;
136 } else if (strcmp(*argv, "-out") == 0) {
137 if (--argc < 1) {
138 break;
139 }
140 outfile = *(++argv);
141 }
142 argc--;
143 argv++;
144 }
145
146
147 ScopedBN_CTX ctx(BN_CTX_new());
148 if (!ctx) {
149 return 1;
150 }
151
152 ScopedBIO out(BIO_new(BIO_s_file()));
153 if (!out) {
154 return 1;
155 }
156
157 if (outfile == NULL) {
158 BIO_set_fp(out.get(), stdout, BIO_NOCLOSE);
159 } else {
160 if (!BIO_write_filename(out.get(), outfile)) {
161 perror(outfile);
162 return 1;
163 }
164 }
165
166 if (!g_results) {
167 BIO_puts(out.get(), "obase=16\nibase=16\n");
168 }
169
170 message(out.get(), "BN_add");
171 if (!test_add(out.get())) {
172 return 1;
173 }
174 (void)BIO_flush(out.get());
175
176 message(out.get(), "BN_sub");
177 if (!test_sub(out.get())) {
178 return 1;
179 }
180 (void)BIO_flush(out.get());
181
182 message(out.get(), "BN_lshift1");
183 if (!test_lshift1(out.get())) {
184 return 1;
185 }
186 (void)BIO_flush(out.get());
187
188 message(out.get(), "BN_lshift (fixed)");
189 ScopedBIGNUM sample(BN_bin2bn(kSample, sizeof(kSample) - 1, NULL));
190 if (!sample) {
191 return 1;
192 }
193 if (!test_lshift(out.get(), ctx.get(), bssl::move(sample))) {
194 return 1;
195 }
196 (void)BIO_flush(out.get());
197
198 message(out.get(), "BN_lshift");
199 if (!test_lshift(out.get(), ctx.get(), nullptr)) {
200 return 1;
201 }
202 (void)BIO_flush(out.get());
203
204 message(out.get(), "BN_rshift1");
205 if (!test_rshift1(out.get())) {
206 return 1;
207 }
208 (void)BIO_flush(out.get());
209
210 message(out.get(), "BN_rshift");
211 if (!test_rshift(out.get(), ctx.get())) {
212 return 1;
213 }
214 (void)BIO_flush(out.get());
215
216 message(out.get(), "BN_sqr");
217 if (!test_sqr(out.get(), ctx.get())) {
218 return 1;
219 }
220 (void)BIO_flush(out.get());
221
222 message(out.get(), "BN_mul");
223 if (!test_mul(out.get())) {
224 return 1;
225 }
226 (void)BIO_flush(out.get());
227
228 message(out.get(), "BN_div");
229 if (!test_div(out.get(), ctx.get())) {
230 return 1;
231 }
232 (void)BIO_flush(out.get());
233
234 message(out.get(), "BN_div_word");
235 if (!test_div_word(out.get())) {
236 return 1;
237 }
238 (void)BIO_flush(out.get());
239
240 message(out.get(), "BN_mod");
241 if (!test_mod(out.get(), ctx.get())) {
242 return 1;
243 }
244 (void)BIO_flush(out.get());
245
246 message(out.get(), "BN_mod_mul");
247 if (!test_mod_mul(out.get(), ctx.get())) {
248 return 1;
249 }
250 (void)BIO_flush(out.get());
251
252 message(out.get(), "BN_mont");
253 if (!test_mont(out.get(), ctx.get())) {
254 return 1;
255 }
256 (void)BIO_flush(out.get());
257
258 message(out.get(), "BN_mod_exp");
259 if (!test_mod_exp(out.get(), ctx.get())) {
260 return 1;
261 }
262 (void)BIO_flush(out.get());
263
264 message(out.get(), "BN_mod_exp_mont_consttime");
265 if (!test_mod_exp_mont_consttime(out.get(), ctx.get()) ||
266 !test_mod_exp_mont5(out.get(), ctx.get())) {
267 return 1;
268 }
269 (void)BIO_flush(out.get());
270
271 message(out.get(), "BN_exp");
272 if (!test_exp(out.get(), ctx.get()) ||
273 !test_exp_mod_zero()) {
274 return 1;
275 }
276 (void)BIO_flush(out.get());
277
278 message(out.get(), "BN_mod_sqrt");
279 if (!test_mod_sqrt(out.get(), ctx.get())) {
280 return 1;
281 }
282 (void)BIO_flush(out.get());
283
284 message(out.get(), "Small prime generation");
285 if (!test_small_prime(out.get(), ctx.get())) {
286 return 1;
287 }
288 (void)BIO_flush(out.get());
289
290 message(out.get(), "BN_sqrt");
291 if (!test_sqrt(out.get(), ctx.get())) {
292 return 1;
293 }
294 (void)BIO_flush(out.get());
295
296 message(out.get(), "BN_bn2bin_padded");
297 if (!test_bn2bin_padded(out.get(), ctx.get())) {
298 return 1;
299 }
300 (void)BIO_flush(out.get());
301
302 printf("PASS\n");
303 return 0;
304}
305
306static bool test_add(BIO *bp) {
307 ScopedBIGNUM a(BN_new());
308 ScopedBIGNUM b(BN_new());
309 ScopedBIGNUM c(BN_new());
310 if (!a || !b || !c || !BN_rand(a.get(), 512, 0, 0)) {
311 return false;
312 }
313
314 for (int i = 0; i < num0; i++) {
315 if (!BN_rand(b.get(), 450 + i, 0, 0)) {
316 return false;
317 }
318 a->neg = rand_neg();
319 b->neg = rand_neg();
320 if (!BN_add(c.get(), a.get(), b.get())) {
321 return false;
322 }
323 if (bp != NULL) {
324 if (!g_results) {
325 BN_print(bp, a.get());
326 BIO_puts(bp, " + ");
327 BN_print(bp, b.get());
328 BIO_puts(bp, " - ");
329 }
330 BN_print(bp, c.get());
331 BIO_puts(bp, "\n");
332 }
333 a->neg = !a->neg;
334 b->neg = !b->neg;
335 if (!BN_add(c.get(), c.get(), b.get()) ||
336 !BN_add(c.get(), c.get(), a.get())) {
337 return false;
338 }
339 if (!BN_is_zero(c.get())) {
340 fprintf(stderr, "Add test failed!\n");
341 return false;
342 }
343 }
344 return true;
345}
346
347static bool test_sub(BIO *bp) {
348 ScopedBIGNUM a(BN_new());
349 ScopedBIGNUM b(BN_new());
350 ScopedBIGNUM c(BN_new());
351 if (!a || !b || !c) {
352 return false;
353 }
354
355 for (int i = 0; i < num0 + num1; i++) {
356 if (i < num1) {
357 if (!BN_rand(a.get(), 512, 0, 0) ||
358 !BN_copy(b.get(), a.get()) ||
359 !BN_set_bit(a.get(), i) ||
360 !BN_add_word(b.get(), i)) {
361 return false;
362 }
363 } else {
364 if (!BN_rand(b.get(), 400 + i - num1, 0, 0)) {
365 return false;
366 }
367 a->neg = rand_neg();
368 b->neg = rand_neg();
369 }
370 if (!BN_sub(c.get(), a.get(), b.get())) {
371 return false;
372 }
373 if (bp != NULL) {
374 if (!g_results) {
375 BN_print(bp, a.get());
376 BIO_puts(bp, " - ");
377 BN_print(bp, b.get());
378 BIO_puts(bp, " - ");
379 }
380 BN_print(bp, c.get());
381 BIO_puts(bp, "\n");
382 }
383 if (!BN_add(c.get(), c.get(), b.get()) ||
384 !BN_sub(c.get(), c.get(), a.get())) {
385 return false;
386 }
387 if (!BN_is_zero(c.get())) {
388 fprintf(stderr, "Subtract test failed!\n");
389 return false;
390 }
391 }
392 return true;
393}
394
395static bool test_div(BIO *bp, BN_CTX *ctx) {
396 ScopedBIGNUM a(BN_new());
397 ScopedBIGNUM b(BN_new());
398 ScopedBIGNUM c(BN_new());
399 ScopedBIGNUM d(BN_new());
400 ScopedBIGNUM e(BN_new());
401 if (!a || !b || !c || !d || !e) {
402 return false;
403 }
404
405 for (int i = 0; i < num0 + num1; i++) {
406 if (i < num1) {
407 if (!BN_rand(a.get(), 400, 0, 0) ||
408 !BN_copy(b.get(), a.get()) ||
409 !BN_lshift(a.get(), a.get(), i) ||
410 !BN_add_word(a.get(), i)) {
411 return false;
412 }
413 } else if (!BN_rand(b.get(), 50 + 3 * (i - num1), 0, 0)) {
414 return false;
415 }
416 a->neg = rand_neg();
417 b->neg = rand_neg();
418 if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
419 return false;
420 }
421 if (bp != NULL) {
422 if (!g_results) {
423 BN_print(bp, a.get());
424 BIO_puts(bp, " / ");
425 BN_print(bp, b.get());
426 BIO_puts(bp, " - ");
427 }
428 BN_print(bp, d.get());
429 BIO_puts(bp, "\n");
430
431 if (!g_results) {
432 BN_print(bp, a.get());
433 BIO_puts(bp, " % ");
434 BN_print(bp, b.get());
435 BIO_puts(bp, " - ");
436 }
437 BN_print(bp, c.get());
438 BIO_puts(bp, "\n");
439 }
440 if (!BN_mul(e.get(), d.get(), b.get(), ctx) ||
441 !BN_add(d.get(), e.get(), c.get()) ||
442 !BN_sub(d.get(), d.get(), a.get())) {
443 return false;
444 }
445 if (!BN_is_zero(d.get())) {
446 fprintf(stderr, "Division test failed!\n");
447 return false;
448 }
449 }
450 return true;
451}
452
453static bool test_lshift1(BIO *bp) {
454 ScopedBIGNUM a(BN_new());
455 ScopedBIGNUM b(BN_new());
456 ScopedBIGNUM c(BN_new());
457 if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
458 return false;
459 }
460 a->neg = rand_neg();
461 for (int i = 0; i < num0; i++) {
462 if (!BN_lshift1(b.get(), a.get())) {
463 return false;
464 }
465 if (bp != NULL) {
466 if (!g_results) {
467 BN_print(bp, a.get());
468 BIO_puts(bp, " * 2");
469 BIO_puts(bp, " - ");
470 }
471 BN_print(bp, b.get());
472 BIO_puts(bp, "\n");
473 }
474 if (!BN_add(c.get(), a.get(), a.get()) ||
475 !BN_sub(a.get(), b.get(), c.get())) {
476 return false;
477 }
478 if (!BN_is_zero(a.get())) {
479 fprintf(stderr, "Left shift one test failed!\n");
480 return false;
481 }
482
483 if (!BN_copy(a.get(), b.get())) {
484 return false;
485 }
486 }
487 return true;
488}
489
490static bool test_rshift(BIO *bp, BN_CTX *ctx) {
491 ScopedBIGNUM a(BN_new());
492 ScopedBIGNUM b(BN_new());
493 ScopedBIGNUM c(BN_new());
494 ScopedBIGNUM d(BN_new());
495 ScopedBIGNUM e(BN_new());
496 if (!a || !b || !c || !d || !e || !BN_one(c.get()) ||
497 !BN_rand(a.get(), 200, 0, 0)) {
498 return false;
499 }
500 a->neg = rand_neg();
501 for (int i = 0; i < num0; i++) {
502 if (!BN_rshift(b.get(), a.get(), i + 1) ||
503 !BN_add(c.get(), c.get(), c.get())) {
504 return false;
505 }
506 if (bp != NULL) {
507 if (!g_results) {
508 BN_print(bp, a.get());
509 BIO_puts(bp, " / ");
510 BN_print(bp, c.get());
511 BIO_puts(bp, " - ");
512 }
513 BN_print(bp, b.get());
514 BIO_puts(bp, "\n");
515 }
516 if (!BN_div(d.get(), e.get(), a.get(), c.get(), ctx) ||
517 !BN_sub(d.get(), d.get(), b.get())) {
518 return false;
519 }
520 if (!BN_is_zero(d.get())) {
521 fprintf(stderr, "Right shift test failed!\n");
522 return false;
523 }
524 }
525 return true;
526}
527
528static bool test_rshift1(BIO *bp) {
529 ScopedBIGNUM a(BN_new());
530 ScopedBIGNUM b(BN_new());
531 ScopedBIGNUM c(BN_new());
532 if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
533 return false;
534 }
535 a->neg = rand_neg();
536
537 for (int i = 0; i < num0; i++) {
538 if (!BN_rshift1(b.get(), a.get())) {
539 return false;
540 }
541 if (bp != NULL) {
542 if (!g_results) {
543 BN_print(bp, a.get());
544 BIO_puts(bp, " / 2");
545 BIO_puts(bp, " - ");
546 }
547 BN_print(bp, b.get());
548 BIO_puts(bp, "\n");
549 }
550 if (!BN_sub(c.get(), a.get(), b.get()) ||
551 !BN_sub(c.get(), c.get(), b.get())) {
552 return false;
553 }
554 if (!BN_is_zero(c.get()) && !BN_abs_is_word(c.get(), 1)) {
555 fprintf(stderr, "Right shift one test failed!\n");
556 return false;
557 }
558 if (!BN_copy(a.get(), b.get())) {
559 return false;
560 }
561 }
562 return true;
563}
564
565static bool test_lshift(BIO *bp, BN_CTX *ctx, ScopedBIGNUM a) {
566 if (!a) {
567 a.reset(BN_new());
568 if (!a || !BN_rand(a.get(), 200, 0, 0)) {
569 return false;
570 }
571 a->neg = rand_neg();
572 }
573
574 ScopedBIGNUM b(BN_new());
575 ScopedBIGNUM c(BN_new());
576 ScopedBIGNUM d(BN_new());
577 if (!b || !c || !d || !BN_one(c.get())) {
578 return false;
579 }
580
581 for (int i = 0; i < num0; i++) {
582 if (!BN_lshift(b.get(), a.get(), i + 1) ||
583 !BN_add(c.get(), c.get(), c.get())) {
584 return false;
585 }
586 if (bp != NULL) {
587 if (!g_results) {
588 BN_print(bp, a.get());
589 BIO_puts(bp, " * ");
590 BN_print(bp, c.get());
591 BIO_puts(bp, " - ");
592 }
593 BN_print(bp, b.get());
594 BIO_puts(bp, "\n");
595 }
596 if (!BN_mul(d.get(), a.get(), c.get(), ctx) ||
597 !BN_sub(d.get(), d.get(), b.get())) {
598 return false;
599 }
600 if (!BN_is_zero(d.get())) {
601 fprintf(stderr, "Left shift test failed!\n");
602 fprintf(stderr, "a=");
603 BN_print_fp(stderr, a.get());
604 fprintf(stderr, "\nb=");
605 BN_print_fp(stderr, b.get());
606 fprintf(stderr, "\nc=");
607 BN_print_fp(stderr, c.get());
608 fprintf(stderr, "\nd=");
609 BN_print_fp(stderr, d.get());
610 fprintf(stderr, "\n");
611 return false;
612 }
613 }
614 return true;
615}
616
617static bool test_mul(BIO *bp) {
618 ScopedBN_CTX ctx(BN_CTX_new());
619 ScopedBIGNUM a(BN_new());
620 ScopedBIGNUM b(BN_new());
621 ScopedBIGNUM c(BN_new());
622 ScopedBIGNUM d(BN_new());
623 ScopedBIGNUM e(BN_new());
624 if (!ctx || !a || !b || !c || !d || !e) {
625 return false;
626 }
627
628 for (int i = 0; i < num0 + num1; i++) {
629 if (i <= num1) {
630 if (!BN_rand(a.get(), 100, 0, 0) ||
631 !BN_rand(b.get(), 100, 0, 0)) {
632 return false;
633 }
634 } else if (!BN_rand(b.get(), i - num1, 0, 0)) {
635 return false;
636 }
637 a->neg = rand_neg();
638 b->neg = rand_neg();
639 if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) {
640 return false;
641 }
642 if (bp != NULL) {
643 if (!g_results) {
644 BN_print(bp, a.get());
645 BIO_puts(bp, " * ");
646 BN_print(bp, b.get());
647 BIO_puts(bp, " - ");
648 }
649 BN_print(bp, c.get());
650 BIO_puts(bp, "\n");
651 }
652 if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx.get()) ||
653 !BN_sub(d.get(), d.get(), b.get())) {
654 return false;
655 }
656 if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
657 fprintf(stderr, "Multiplication test failed!\n");
658 return false;
659 }
660 }
661 return true;
662}
663
664static bool test_sqr(BIO *bp, BN_CTX *ctx) {
665 ScopedBIGNUM a(BN_new());
666 ScopedBIGNUM c(BN_new());
667 ScopedBIGNUM d(BN_new());
668 ScopedBIGNUM e(BN_new());
669 if (!a || !c || !d || !e) {
670 return false;
671 }
672
673 for (int i = 0; i < num0; i++) {
674 if (!BN_rand(a.get(), 40 + i * 10, 0, 0)) {
675 return false;
676 }
677 a->neg = rand_neg();
678 if (!BN_sqr(c.get(), a.get(), ctx)) {
679 return false;
680 }
681 if (bp != NULL) {
682 if (!g_results) {
683 BN_print(bp, a.get());
684 BIO_puts(bp, " * ");
685 BN_print(bp, a.get());
686 BIO_puts(bp, " - ");
687 }
688 BN_print(bp, c.get());
689 BIO_puts(bp, "\n");
690 }
691 if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx) ||
692 !BN_sub(d.get(), d.get(), a.get())) {
693 return false;
694 }
695 if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
696 fprintf(stderr, "Square test failed!\n");
697 return false;
698 }
699 }
700
701 // Regression test for a BN_sqr overflow bug.
702 BIGNUM *a_raw = a.get();
703 if (!BN_hex2bn(
704 &a_raw,
705 "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000") ||
706 !BN_sqr(c.get(), a.get(), ctx)) {
707 return false;
708 }
709 if (bp != NULL) {
710 if (!g_results) {
711 BN_print(bp, a.get());
712 BIO_puts(bp, " * ");
713 BN_print(bp, a.get());
714 BIO_puts(bp, " - ");
715 }
716 BN_print(bp, c.get());
717 BIO_puts(bp, "\n");
718 }
719 if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
720 return false;
721 }
722 if (BN_cmp(c.get(), d.get())) {
723 fprintf(stderr,
724 "Square test failed: BN_sqr and BN_mul produce "
725 "different results!\n");
726 return false;
727 }
728
729 // Regression test for a BN_sqr overflow bug.
730 a_raw = a.get();
731 if (!BN_hex2bn(
732 &a_raw,
733 "80000000000000000000000080000001FFFFFFFE000000000000000000000000") ||
734 !BN_sqr(c.get(), a.get(), ctx)) {
735 return false;
736 }
737 if (bp != NULL) {
738 if (!g_results) {
739 BN_print(bp, a.get());
740 BIO_puts(bp, " * ");
741 BN_print(bp, a.get());
742 BIO_puts(bp, " - ");
743 }
744 BN_print(bp, c.get());
745 BIO_puts(bp, "\n");
746 }
747 if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
748 return false;
749 }
750 if (BN_cmp(c.get(), d.get())) {
751 fprintf(stderr,
752 "Square test failed: BN_sqr and BN_mul produce "
753 "different results!\n");
754 return false;
755 }
756
757 return true;
758}
759
760
761static int rand_neg() {
762 static unsigned int neg = 0;
763 static const int sign[8] = {0, 0, 0, 1, 1, 0, 1, 1};
764
765 return sign[(neg++) % 8];
766}
767
768static void print_word(BIO *bp, BN_ULONG w) {
769 BIO_printf(bp, BN_HEX_FMT1, w);
770}
771
772static bool test_div_word(BIO *bp) {
773 ScopedBIGNUM a(BN_new());
774 ScopedBIGNUM b(BN_new());
775 if (!a || !b) {
776 return false;
777 }
778
779 for (int i = 0; i < num0; i++) {
780 BN_ULONG s;
781 do {
782 if (!BN_rand(a.get(), 512, -1, 0) ||
783 !BN_rand(b.get(), BN_BITS2, -1, 0)) {
784 return false;
785 }
786 s = b->d[0];
787 } while (!s);
788
789 if (!BN_copy(b.get(), a.get())) {
790 return false;
791 }
792 BN_ULONG r = BN_div_word(b.get(), s);
793 if (r == (BN_ULONG)-1) {
794 return false;
795 }
796
797 if (bp != NULL) {
798 if (!g_results) {
799 BN_print(bp, a.get());
800 BIO_puts(bp, " / ");
801 print_word(bp, s);
802 BIO_puts(bp, " - ");
803 }
804 BN_print(bp, b.get());
805 BIO_puts(bp, "\n");
806
807 if (!g_results) {
808 BN_print(bp, a.get());
809 BIO_puts(bp, " % ");
810 print_word(bp, s);
811 BIO_puts(bp, " - ");
812 }
813 print_word(bp, r);
814 BIO_puts(bp, "\n");
815 }
816 if (!BN_mul_word(b.get(), s) ||
817 !BN_add_word(b.get(), r) ||
818 !BN_sub(b.get(), a.get(), b.get())) {
819 return false;
820 }
821 if (!BN_is_zero(b.get())) {
822 fprintf(stderr, "Division (word) test failed!\n");
823 return false;
824 }
825 }
826 return true;
827}
828
829static bool test_mont(BIO *bp, BN_CTX *ctx) {
830 ScopedBIGNUM a(BN_new());
831 ScopedBIGNUM b(BN_new());
832 ScopedBIGNUM c(BN_new());
833 ScopedBIGNUM d(BN_new());
834 ScopedBIGNUM A(BN_new());
835 ScopedBIGNUM B(BN_new());
836 ScopedBIGNUM n(BN_new());
837 ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
838 if (!a || !b || !c || !d || !A || !B || !n || !mont ||
839 !BN_rand(a.get(), 100, 0, 0) ||
840 !BN_rand(b.get(), 100, 0, 0)) {
841 return false;
842 }
843
844 for (int i = 0; i < num2; i++) {
845 int bits = (200 * (i + 1)) / num2;
846
847 if (bits == 0) {
848 continue;
849 }
850 if (!BN_rand(n.get(), bits, 0, 1) ||
851 !BN_MONT_CTX_set(mont.get(), n.get(), ctx) ||
852 !BN_nnmod(a.get(), a.get(), n.get(), ctx) ||
853 !BN_nnmod(b.get(), b.get(), n.get(), ctx) ||
854 !BN_to_montgomery(A.get(), a.get(), mont.get(), ctx) ||
855 !BN_to_montgomery(B.get(), b.get(), mont.get(), ctx) ||
856 !BN_mod_mul_montgomery(c.get(), A.get(), B.get(), mont.get(), ctx) ||
857 !BN_from_montgomery(A.get(), c.get(), mont.get(), ctx)) {
858 return false;
859 }
860 if (bp != NULL) {
861 if (!g_results) {
862 BN_print(bp, a.get());
863 BIO_puts(bp, " * ");
864 BN_print(bp, b.get());
865 BIO_puts(bp, " % ");
866 BN_print(bp, &mont->N);
867 BIO_puts(bp, " - ");
868 }
869 BN_print(bp, A.get());
870 BIO_puts(bp, "\n");
871 }
872 if (!BN_mod_mul(d.get(), a.get(), b.get(), n.get(), ctx) ||
873 !BN_sub(d.get(), d.get(), A.get())) {
874 return false;
875 }
876 if (!BN_is_zero(d.get())) {
877 fprintf(stderr, "Montgomery multiplication test failed!\n");
878 return false;
879 }
880 }
881 return true;
882}
883
884static bool test_mod(BIO *bp, BN_CTX *ctx) {
885 ScopedBIGNUM a(BN_new());
886 ScopedBIGNUM b(BN_new());
887 ScopedBIGNUM c(BN_new());
888 ScopedBIGNUM d(BN_new());
889 ScopedBIGNUM e(BN_new());
890 if (!a || !b || !c || !d || !e ||
891 !BN_rand(a.get(), 1024, 0, 0)) {
892 return false;
893 }
894
895 for (int i = 0; i < num0; i++) {
896 if (!BN_rand(b.get(), 450 + i * 10, 0, 0)) {
897 return false;
898 }
899 a->neg = rand_neg();
900 b->neg = rand_neg();
901 if (!BN_mod(c.get(), a.get(), b.get(), ctx)) {
902 return false;
903 }
904 if (bp != NULL) {
905 if (!g_results) {
906 BN_print(bp, a.get());
907 BIO_puts(bp, " % ");
908 BN_print(bp, b.get());
909 BIO_puts(bp, " - ");
910 }
911 BN_print(bp, c.get());
912 BIO_puts(bp, "\n");
913 }
914 if (!BN_div(d.get(), e.get(), a.get(), b.get(), ctx) ||
915 !BN_sub(e.get(), e.get(), c.get())) {
916 return false;
917 }
918 if (!BN_is_zero(e.get())) {
919 fprintf(stderr, "Modulo test failed!\n");
920 return false;
921 }
922 }
923 return true;
924}
925
926static bool test_mod_mul(BIO *bp, BN_CTX *ctx) {
927 ScopedBIGNUM a(BN_new());
928 ScopedBIGNUM b(BN_new());
929 ScopedBIGNUM c(BN_new());
930 ScopedBIGNUM d(BN_new());
931 ScopedBIGNUM e(BN_new());
932 if (!a || !b || !c || !d || !e) {
933 return false;
934 }
935
936 for (int j = 0; j < 3; j++) {
937 if (!BN_rand(c.get(), 1024, 0, 0)) {
938 return false;
939 }
940 for (int i = 0; i < num0; i++) {
941 if (!BN_rand(a.get(), 475 + i * 10, 0, 0) ||
942 !BN_rand(b.get(), 425 + i * 11, 0, 0)) {
943 return false;
944 }
945 a->neg = rand_neg();
946 b->neg = rand_neg();
947 if (!BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) {
Brian Smith83a82982015-04-09 16:21:10 -1000948 ERR_print_errors_fp(stderr);
David Benjamina5974bf2015-03-25 23:49:37 -0400949 return false;
950 }
951 if (bp != NULL) {
952 if (!g_results) {
953 BN_print(bp, a.get());
954 BIO_puts(bp, " * ");
955 BN_print(bp, b.get());
956 BIO_puts(bp, " % ");
957 BN_print(bp, c.get());
958 if (a->neg != b->neg && !BN_is_zero(e.get())) {
959 // If (a*b) % c is negative, c must be added
960 // in order to obtain the normalized remainder
961 // (new with OpenSSL 0.9.7, previous versions of
962 // BN_mod_mul could generate negative results)
963 BIO_puts(bp, " + ");
964 BN_print(bp, c.get());
965 }
966 BIO_puts(bp, " - ");
967 }
968 BN_print(bp, e.get());
969 BIO_puts(bp, "\n");
970 }
971 if (!BN_mul(d.get(), a.get(), b.get(), ctx) ||
972 !BN_sub(d.get(), d.get(), e.get()) ||
973 !BN_div(a.get(), b.get(), d.get(), c.get(), ctx)) {
974 return false;
975 }
976 if (!BN_is_zero(b.get())) {
977 fprintf(stderr, "Modulo multiply test failed!\n");
Brian Smith83a82982015-04-09 16:21:10 -1000978 ERR_print_errors_fp(stderr);
David Benjamina5974bf2015-03-25 23:49:37 -0400979 return false;
980 }
981 }
982 }
983 return true;
984}
985
986static bool test_mod_exp(BIO *bp, BN_CTX *ctx) {
987 ScopedBIGNUM a(BN_new());
988 ScopedBIGNUM b(BN_new());
989 ScopedBIGNUM c(BN_new());
990 ScopedBIGNUM d(BN_new());
991 ScopedBIGNUM e(BN_new());
992 if (!a || !b || !c || !d || !e ||
993 !BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery
994 return false;
995 }
996 for (int i = 0; i < num2; i++) {
997 if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
998 !BN_rand(b.get(), 2 + i, 0, 0) ||
999 !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) {
1000 return false;
1001 }
1002
1003 if (bp != NULL) {
1004 if (!g_results) {
1005 BN_print(bp, a.get());
1006 BIO_puts(bp, " ^ ");
1007 BN_print(bp, b.get());
1008 BIO_puts(bp, " % ");
1009 BN_print(bp, c.get());
1010 BIO_puts(bp, " - ");
1011 }
1012 BN_print(bp, d.get());
1013 BIO_puts(bp, "\n");
1014 }
1015 if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
1016 !BN_sub(e.get(), e.get(), d.get()) ||
1017 !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
1018 return false;
1019 }
1020 if (!BN_is_zero(b.get())) {
1021 fprintf(stderr, "Modulo exponentiation test failed!\n");
1022 return false;
1023 }
1024 }
1025 return true;
1026}
1027
1028static bool test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx) {
1029 ScopedBIGNUM a(BN_new());
1030 ScopedBIGNUM b(BN_new());
1031 ScopedBIGNUM c(BN_new());
1032 ScopedBIGNUM d(BN_new());
1033 ScopedBIGNUM e(BN_new());
1034 if (!a || !b || !c || !d || !e ||
1035 !BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery
1036 return false;
1037 }
1038 for (int i = 0; i < num2; i++) {
1039 if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
1040 !BN_rand(b.get(), 2 + i, 0, 0) ||
1041 !BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
1042 NULL)) {
1043 return false;
1044 }
1045
1046 if (bp != NULL) {
1047 if (!g_results) {
1048 BN_print(bp, a.get());
1049 BIO_puts(bp, " ^ ");
1050 BN_print(bp, b.get());
1051 BIO_puts(bp, " % ");
1052 BN_print(bp, c.get());
1053 BIO_puts(bp, " - ");
1054 }
1055 BN_print(bp, d.get());
1056 BIO_puts(bp, "\n");
1057 }
1058 if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
1059 !BN_sub(e.get(), e.get(), d.get()) ||
1060 !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
1061 return false;
1062 }
1063 if (!BN_is_zero(b.get())) {
1064 fprintf(stderr, "Modulo exponentiation test failed!\n");
1065 return false;
1066 }
1067 }
1068 return true;
1069}
1070
1071// Test constant-time modular exponentiation with 1024-bit inputs,
1072// which on x86_64 cause a different code branch to be taken.
1073static bool test_mod_exp_mont5(BIO *bp, BN_CTX *ctx) {
1074 ScopedBIGNUM a(BN_new());
1075 ScopedBIGNUM p(BN_new());
1076 ScopedBIGNUM m(BN_new());
1077 ScopedBIGNUM d(BN_new());
1078 ScopedBIGNUM e(BN_new());
1079 if (!a || !p || !m || !d || !e ||
1080 !BN_rand(m.get(), 1024, 0, 1) || // must be odd for montgomery
1081 !BN_rand(a.get(), 1024, 0, 0)) {
1082 return false;
1083 }
1084 // Zero exponent.
1085 BN_zero(p.get());
1086 if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
1087 NULL)) {
1088 return false;
1089 }
1090 if (!BN_is_one(d.get())) {
1091 fprintf(stderr, "Modular exponentiation test failed!\n");
1092 return false;
1093 }
1094 if (!BN_rand(p.get(), 1024, 0, 0)) {
1095 return false;
1096 }
1097 // Zero input.
1098 BN_zero(a.get());
1099 if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
1100 NULL)) {
1101 return false;
1102 }
1103 if (!BN_is_zero(d.get())) {
1104 fprintf(stderr, "Modular exponentiation test failed!\n");
1105 return false;
1106 }
1107 // Craft an input whose Montgomery representation is 1, i.e., shorter than the
1108 // modulus m, in order to test the const time precomputation
1109 // scattering/gathering.
1110 ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
1111 if (!mont || !BN_one(a.get()) ||
1112 !BN_MONT_CTX_set(mont.get(), m.get(), ctx) ||
1113 !BN_from_montgomery(e.get(), a.get(), mont.get(), ctx) ||
1114 !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
1115 NULL) ||
1116 !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
1117 return false;
1118 }
1119 if (BN_cmp(a.get(), d.get()) != 0) {
1120 fprintf(stderr, "Modular exponentiation test failed!\n");
1121 return false;
1122 }
1123 // Finally, some regular test vectors.
1124 if (!BN_rand(e.get(), 1024, 0, 0) ||
1125 !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
1126 NULL) ||
1127 !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
1128 return false;
1129 }
1130 if (BN_cmp(a.get(), d.get()) != 0) {
1131 fprintf(stderr, "Modular exponentiation test failed!\n");
1132 return false;
1133 }
1134
1135 return true;
1136}
1137
1138static bool test_exp(BIO *bp, BN_CTX *ctx) {
1139 ScopedBIGNUM a(BN_new());
1140 ScopedBIGNUM b(BN_new());
1141 ScopedBIGNUM d(BN_new());
1142 ScopedBIGNUM e(BN_new());
1143 if (!a || !b || !d || !e) {
1144 return false;
1145 }
1146
1147 for (int i = 0; i < num2; i++) {
1148 if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
1149 !BN_rand(b.get(), 2 + i, 0, 0) ||
1150 !BN_exp(d.get(), a.get(), b.get(), ctx)) {
1151 return false;
1152 }
1153
1154 if (bp != NULL) {
1155 if (!g_results) {
1156 BN_print(bp, a.get());
1157 BIO_puts(bp, " ^ ");
1158 BN_print(bp, b.get());
1159 BIO_puts(bp, " - ");
1160 }
1161 BN_print(bp, d.get());
1162 BIO_puts(bp, "\n");
1163 }
1164 if (!BN_one(e.get())) {
1165 return false;
1166 }
1167 for (; !BN_is_zero(b.get()); BN_sub(b.get(), b.get(), BN_value_one())) {
1168 if (!BN_mul(e.get(), e.get(), a.get(), ctx)) {
1169 return false;
1170 }
1171 }
1172 if (!BN_sub(e.get(), e.get(), d.get())) {
1173 return false;
1174 }
1175 if (!BN_is_zero(e.get())) {
1176 fprintf(stderr, "Exponentiation test failed!\n");
1177 return false;
1178 }
1179 }
1180 return true;
1181}
1182
1183// test_exp_mod_zero tests that 1**0 mod 1 == 0.
1184static bool test_exp_mod_zero(void) {
1185 ScopedBIGNUM zero(BN_new());
1186 if (!zero) {
1187 return false;
1188 }
1189 BN_zero(zero.get());
1190
1191 ScopedBN_CTX ctx(BN_CTX_new());
1192 ScopedBIGNUM r(BN_new());
1193 if (!ctx || !r ||
1194 !BN_mod_exp(r.get(), BN_value_one(), zero.get(), BN_value_one(), ctx.get())) {
1195 return false;
1196 }
1197
1198 if (!BN_is_zero(r.get())) {
1199 printf("1**0 mod 1 = ");
1200 BN_print_fp(stdout, r.get());
1201 printf(", should be 0\n");
1202 return false;
1203 }
1204
1205 return true;
1206}
1207
1208static int genprime_cb(int p, int n, BN_GENCB *arg) {
1209 char c = '*';
1210
1211 if (p == 0) {
1212 c = '.';
1213 } else if (p == 1) {
1214 c = '+';
1215 } else if (p == 2) {
1216 c = '*';
1217 } else if (p == 3) {
1218 c = '\n';
1219 }
1220 putc(c, stdout);
1221 fflush(stdout);
1222 return 1;
1223}
1224
1225static bool test_mod_sqrt(BIO *bp, BN_CTX *ctx) {
1226 ScopedBIGNUM a(BN_new());
1227 ScopedBIGNUM p(BN_new());
1228 ScopedBIGNUM r(BN_new());
1229 if (!a || !p || !r) {
1230 return false;
1231 }
1232
1233 BN_GENCB cb;
1234 BN_GENCB_set(&cb, genprime_cb, NULL);
1235
1236 for (int i = 0; i < 16; i++) {
1237 if (i < 8) {
1238 const unsigned kPrimes[8] = {2, 3, 5, 7, 11, 13, 17, 19};
1239 if (!BN_set_word(p.get(), kPrimes[i])) {
1240 return false;
1241 }
1242 } else {
1243 if (!BN_set_word(a.get(), 32) ||
1244 !BN_set_word(r.get(), 2 * i + 1) ||
1245 !BN_generate_prime_ex(p.get(), 256, 0, a.get(), r.get(), &cb)) {
1246 return false;
1247 }
1248 putc('\n', stdout);
1249 }
1250 p->neg = rand_neg();
1251
1252 for (int j = 0; j < num2; j++) {
1253 // construct 'a' such that it is a square modulo p, but in general not a
1254 // proper square and not reduced modulo p
1255 if (!BN_rand(r.get(), 256, 0, 3) ||
1256 !BN_nnmod(r.get(), r.get(), p.get(), ctx) ||
1257 !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
1258 !BN_rand(a.get(), 256, 0, 3) ||
1259 !BN_nnmod(a.get(), a.get(), p.get(), ctx) ||
1260 !BN_mod_sqr(a.get(), a.get(), p.get(), ctx) ||
1261 !BN_mul(a.get(), a.get(), r.get(), ctx)) {
1262 return false;
1263 }
1264 if (rand_neg() && !BN_sub(a.get(), a.get(), p.get())) {
1265 return false;
1266 }
1267
1268 if (!BN_mod_sqrt(r.get(), a.get(), p.get(), ctx) ||
1269 !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
1270 !BN_nnmod(a.get(), a.get(), p.get(), ctx)) {
1271 return false;
1272 }
1273
1274 if (BN_cmp(a.get(), r.get()) != 0) {
1275 fprintf(stderr, "BN_mod_sqrt failed: a = ");
1276 BN_print_fp(stderr, a.get());
1277 fprintf(stderr, ", r = ");
1278 BN_print_fp(stderr, r.get());
1279 fprintf(stderr, ", p = ");
1280 BN_print_fp(stderr, p.get());
1281 fprintf(stderr, "\n");
1282 return false;
1283 }
1284
1285 putc('.', stdout);
1286 fflush(stdout);
1287 }
1288
1289 putc('\n', stdout);
1290 fflush(stderr);
1291 }
1292 return true;
1293}
1294
1295static bool test_small_prime(BIO *bp, BN_CTX *ctx) {
1296 static const int kBits = 10;
1297
1298 ScopedBIGNUM r(BN_new());
1299 if (!r || !BN_generate_prime_ex(r.get(), kBits, 0, NULL, NULL, NULL)) {
1300 return false;
1301 }
1302 if (BN_num_bits(r.get()) != kBits) {
1303 BIO_printf(bp, "Expected %d bit prime, got %d bit number\n", kBits,
1304 BN_num_bits(r.get()));
1305 return false;
1306 }
1307
1308 return true;
1309}
1310
1311static bool test_sqrt(BIO *bp, BN_CTX *ctx) {
1312 ScopedBIGNUM n(BN_new());
1313 ScopedBIGNUM nn(BN_new());
1314 ScopedBIGNUM sqrt(BN_new());
1315 if (!n || !nn || !sqrt) {
1316 return false;
1317 }
1318
1319 // Test some random squares.
1320 for (int i = 0; i < 100; i++) {
1321 if (!BN_rand(n.get(), 1024 /* bit length */,
1322 -1 /* no modification of top bits */,
1323 0 /* don't modify bottom bit */) ||
1324 !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
1325 !BN_sqrt(sqrt.get(), nn.get(), ctx)) {
Brian Smith83a82982015-04-09 16:21:10 -10001326 ERR_print_errors_fp(stderr);
David Benjamina5974bf2015-03-25 23:49:37 -04001327 return false;
1328 }
1329 if (BN_cmp(n.get(), sqrt.get()) != 0) {
1330 fprintf(stderr, "Bad result from BN_sqrt.\n");
1331 return false;
1332 }
1333 }
1334
1335 // Test some non-squares.
1336 for (int i = 0; i < 100; i++) {
1337 if (!BN_rand(n.get(), 1024 /* bit length */,
1338 -1 /* no modification of top bits */,
1339 0 /* don't modify bottom bit */) ||
1340 !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
1341 !BN_add(nn.get(), nn.get(), BN_value_one())) {
Brian Smith83a82982015-04-09 16:21:10 -10001342 ERR_print_errors_fp(stderr);
David Benjamina5974bf2015-03-25 23:49:37 -04001343 return false;
1344 }
1345
1346 if (BN_sqrt(sqrt.get(), nn.get(), ctx)) {
1347 char *nn_str = BN_bn2dec(nn.get());
1348 fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str);
1349 OPENSSL_free(nn_str);
1350 }
1351 }
1352
1353 return true;
1354}
1355
1356static bool test_bn2bin_padded(BIO *bp, BN_CTX *ctx) {
1357 uint8_t zeros[256], out[256], reference[128];
1358
1359 memset(zeros, 0, sizeof(zeros));
1360
1361 // Test edge case at 0.
1362 ScopedBIGNUM n(BN_new());
1363 if (!n || !BN_bn2bin_padded(NULL, 0, n.get())) {
1364 fprintf(stderr,
1365 "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n");
1366 return false;
1367 }
1368 memset(out, -1, sizeof(out));
1369 if (!BN_bn2bin_padded(out, sizeof(out), n.get())) {
1370 fprintf(stderr,
1371 "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n");
1372 return false;
1373 }
1374 if (memcmp(zeros, out, sizeof(out))) {
1375 fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n");
1376 return false;
1377 }
1378
1379 // Test a random numbers at various byte lengths.
1380 for (size_t bytes = 128 - 7; bytes <= 128; bytes++) {
1381 if (!BN_rand(n.get(), bytes * 8, 0 /* make sure top bit is 1 */,
1382 0 /* don't modify bottom bit */)) {
Brian Smith83a82982015-04-09 16:21:10 -10001383 ERR_print_errors_fp(stderr);
David Benjamina5974bf2015-03-25 23:49:37 -04001384 return false;
1385 }
1386 if (BN_num_bytes(n.get()) != bytes ||
1387 BN_bn2bin(n.get(), reference) != bytes) {
1388 fprintf(stderr, "Bad result from BN_rand; bytes.\n");
1389 return false;
1390 }
1391 // Empty buffer should fail.
1392 if (BN_bn2bin_padded(NULL, 0, n.get())) {
1393 fprintf(stderr,
1394 "BN_bn2bin_padded incorrectly succeeded on empty buffer.\n");
1395 return false;
1396 }
1397 // One byte short should fail.
1398 if (BN_bn2bin_padded(out, bytes - 1, n.get())) {
1399 fprintf(stderr, "BN_bn2bin_padded incorrectly succeeded on short.\n");
1400 return false;
1401 }
1402 // Exactly right size should encode.
1403 if (!BN_bn2bin_padded(out, bytes, n.get()) ||
1404 memcmp(out, reference, bytes) != 0) {
1405 fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
1406 return false;
1407 }
1408 // Pad up one byte extra.
1409 if (!BN_bn2bin_padded(out, bytes + 1, n.get()) ||
1410 memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) {
1411 fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
1412 return false;
1413 }
1414 // Pad up to 256.
1415 if (!BN_bn2bin_padded(out, sizeof(out), n.get()) ||
1416 memcmp(out + sizeof(out) - bytes, reference, bytes) ||
1417 memcmp(out, zeros, sizeof(out) - bytes)) {
1418 fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
1419 return false;
1420 }
1421 }
1422
1423 return true;
1424}