Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

1409 рядки
37 KiB

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