testbn.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * testbn.c: standalone test program for the bignum code.
  3. */
  4. /*
  5. * Accepts input on standard input, in the form generated by
  6. * testdata/bignum.py.
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <ctype.h>
  11. #include "ssh.h"
  12. #include "sshbn.h"
  13. void modalfatalbox(const char *p, ...)
  14. {
  15. va_list ap;
  16. fprintf(stderr, "FATAL ERROR: ");
  17. va_start(ap, p);
  18. vfprintf(stderr, p, ap);
  19. va_end(ap);
  20. fputc('\n', stderr);
  21. exit(1);
  22. }
  23. int random_byte(void)
  24. {
  25. modalfatalbox("random_byte called in testbn");
  26. return 0;
  27. }
  28. #define fromxdigit(c) ( (c)>'9' ? ((c)&0xDF) - 'A' + 10 : (c) - '0' )
  29. int main(int argc, char **argv)
  30. {
  31. char *buf;
  32. int line = 0;
  33. int passes = 0, fails = 0;
  34. printf("BIGNUM_INT_BITS = %d\n", (int)BIGNUM_INT_BITS);
  35. while ((buf = fgetline(stdin)) != NULL) {
  36. int maxlen = strlen(buf);
  37. unsigned char *data = snewn(maxlen, unsigned char);
  38. unsigned char *ptrs[5], *q;
  39. int ptrnum;
  40. char *bufp = buf;
  41. line++;
  42. q = data;
  43. ptrnum = 0;
  44. while (*bufp && !isspace((unsigned char)*bufp))
  45. bufp++;
  46. if (bufp)
  47. *bufp++ = '\0';
  48. while (*bufp) {
  49. char *start, *end;
  50. int i;
  51. while (*bufp && !isxdigit((unsigned char)*bufp))
  52. bufp++;
  53. start = bufp;
  54. if (!*bufp)
  55. break;
  56. while (*bufp && isxdigit((unsigned char)*bufp))
  57. bufp++;
  58. end = bufp;
  59. if (ptrnum >= lenof(ptrs))
  60. break;
  61. ptrs[ptrnum++] = q;
  62. for (i = -((end - start) & 1); i < end-start; i += 2) {
  63. unsigned char val = (i < 0 ? 0 : fromxdigit(start[i]));
  64. val = val * 16 + fromxdigit(start[i+1]);
  65. *q++ = val;
  66. }
  67. ptrs[ptrnum] = q;
  68. }
  69. if (!strcmp(buf, "mul")) {
  70. Bignum a, b, c, p;
  71. if (ptrnum != 3) {
  72. printf("%d: mul with %d parameters, expected 3\n", line, ptrnum);
  73. exit(1);
  74. }
  75. a = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]);
  76. b = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]);
  77. c = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]);
  78. p = bigmul(a, b);
  79. if (bignum_cmp(c, p) == 0) {
  80. passes++;
  81. } else {
  82. char *as = bignum_decimal(a);
  83. char *bs = bignum_decimal(b);
  84. char *cs = bignum_decimal(c);
  85. char *ps = bignum_decimal(p);
  86. printf("%d: fail: %s * %s gave %s expected %s\n",
  87. line, as, bs, ps, cs);
  88. fails++;
  89. sfree(as);
  90. sfree(bs);
  91. sfree(cs);
  92. sfree(ps);
  93. }
  94. freebn(a);
  95. freebn(b);
  96. freebn(c);
  97. freebn(p);
  98. } else if (!strcmp(buf, "modmul")) {
  99. Bignum a, b, m, c, p;
  100. if (ptrnum != 4) {
  101. printf("%d: modmul with %d parameters, expected 4\n",
  102. line, ptrnum);
  103. exit(1);
  104. }
  105. a = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]);
  106. b = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]);
  107. m = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]);
  108. c = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]);
  109. p = modmul(a, b, m);
  110. if (bignum_cmp(c, p) == 0) {
  111. passes++;
  112. } else {
  113. char *as = bignum_decimal(a);
  114. char *bs = bignum_decimal(b);
  115. char *ms = bignum_decimal(m);
  116. char *cs = bignum_decimal(c);
  117. char *ps = bignum_decimal(p);
  118. printf("%d: fail: %s * %s mod %s gave %s expected %s\n",
  119. line, as, bs, ms, ps, cs);
  120. fails++;
  121. sfree(as);
  122. sfree(bs);
  123. sfree(ms);
  124. sfree(cs);
  125. sfree(ps);
  126. }
  127. freebn(a);
  128. freebn(b);
  129. freebn(m);
  130. freebn(c);
  131. freebn(p);
  132. } else if (!strcmp(buf, "pow")) {
  133. Bignum base, expt, modulus, expected, answer;
  134. if (ptrnum != 4) {
  135. printf("%d: pow with %d parameters, expected 4\n", line, ptrnum);
  136. exit(1);
  137. }
  138. base = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]);
  139. expt = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]);
  140. modulus = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]);
  141. expected = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]);
  142. answer = modpow(base, expt, modulus);
  143. if (bignum_cmp(expected, answer) == 0) {
  144. passes++;
  145. } else {
  146. char *as = bignum_decimal(base);
  147. char *bs = bignum_decimal(expt);
  148. char *cs = bignum_decimal(modulus);
  149. char *ds = bignum_decimal(answer);
  150. char *ps = bignum_decimal(expected);
  151. printf("%d: fail: %s ^ %s mod %s gave %s expected %s\n",
  152. line, as, bs, cs, ds, ps);
  153. fails++;
  154. sfree(as);
  155. sfree(bs);
  156. sfree(cs);
  157. sfree(ds);
  158. sfree(ps);
  159. }
  160. freebn(base);
  161. freebn(expt);
  162. freebn(modulus);
  163. freebn(expected);
  164. freebn(answer);
  165. } else if (!strcmp(buf, "divmod")) {
  166. Bignum n, d, expect_q, expect_r, answer_q, answer_r;
  167. int fail;
  168. if (ptrnum != 4) {
  169. printf("%d: divmod with %d parameters, expected 4\n", line, ptrnum);
  170. exit(1);
  171. }
  172. n = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]);
  173. d = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]);
  174. expect_q = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]);
  175. expect_r = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]);
  176. answer_q = bigdiv(n, d);
  177. answer_r = bigmod(n, d);
  178. fail = FALSE;
  179. if (bignum_cmp(expect_q, answer_q) != 0) {
  180. char *as = bignum_decimal(n);
  181. char *bs = bignum_decimal(d);
  182. char *cs = bignum_decimal(answer_q);
  183. char *ds = bignum_decimal(expect_q);
  184. printf("%d: fail: %s / %s gave %s expected %s\n",
  185. line, as, bs, cs, ds);
  186. fail = TRUE;
  187. sfree(as);
  188. sfree(bs);
  189. sfree(cs);
  190. sfree(ds);
  191. }
  192. if (bignum_cmp(expect_r, answer_r) != 0) {
  193. char *as = bignum_decimal(n);
  194. char *bs = bignum_decimal(d);
  195. char *cs = bignum_decimal(answer_r);
  196. char *ds = bignum_decimal(expect_r);
  197. printf("%d: fail: %s mod %s gave %s expected %s\n",
  198. line, as, bs, cs, ds);
  199. fail = TRUE;
  200. sfree(as);
  201. sfree(bs);
  202. sfree(cs);
  203. sfree(ds);
  204. }
  205. freebn(n);
  206. freebn(d);
  207. freebn(expect_q);
  208. freebn(expect_r);
  209. freebn(answer_q);
  210. freebn(answer_r);
  211. if (fail)
  212. fails++;
  213. else
  214. passes++;
  215. } else {
  216. printf("%d: unrecognised test keyword: '%s'\n", line, buf);
  217. exit(1);
  218. }
  219. sfree(buf);
  220. sfree(data);
  221. }
  222. printf("passed %d failed %d total %d\n", passes, fails, passes+fails);
  223. return fails != 0;
  224. }