X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=testbn.c;fp=testbn.c;h=55471bd24c0ac163a0b13c16402c1c5328a9103a;hb=daeeca55a4ef109539dc3e67b758299cc03d35ea;hp=0000000000000000000000000000000000000000;hpb=84cd309295c12e7a8a3a7bc37280f8d7859b4a8b;p=PuTTY.git diff --git a/testbn.c b/testbn.c new file mode 100644 index 00000000..55471bd2 --- /dev/null +++ b/testbn.c @@ -0,0 +1,265 @@ +/* + * testbn.c: standalone test program for the bignum code. + */ + +/* + * Accepts input on standard input, in the form generated by + * testdata/bignum.py. + */ + +#include +#include +#include + +#include "ssh.h" + +void modalfatalbox(const char *p, ...) +{ + va_list ap; + fprintf(stderr, "FATAL ERROR: "); + va_start(ap, p); + vfprintf(stderr, p, ap); + va_end(ap); + fputc('\n', stderr); + exit(1); +} + +int random_byte(void) +{ + modalfatalbox("random_byte called in testbn"); + return 0; +} + +#define fromxdigit(c) ( (c)>'9' ? ((c)&0xDF) - 'A' + 10 : (c) - '0' ) + +int main(int argc, char **argv) +{ + char *buf; + int line = 0; + int passes = 0, fails = 0; + + while ((buf = fgetline(stdin)) != NULL) { + int maxlen = strlen(buf); + unsigned char *data = snewn(maxlen, unsigned char); + unsigned char *ptrs[5], *q; + int ptrnum; + char *bufp = buf; + + line++; + + q = data; + ptrnum = 0; + + while (*bufp && !isspace((unsigned char)*bufp)) + bufp++; + if (bufp) + *bufp++ = '\0'; + + while (*bufp) { + char *start, *end; + int i; + + while (*bufp && !isxdigit((unsigned char)*bufp)) + bufp++; + start = bufp; + + if (!*bufp) + break; + + while (*bufp && isxdigit((unsigned char)*bufp)) + bufp++; + end = bufp; + + if (ptrnum >= lenof(ptrs)) + break; + ptrs[ptrnum++] = q; + + for (i = -((end - start) & 1); i < end-start; i += 2) { + unsigned char val = (i < 0 ? 0 : fromxdigit(start[i])); + val = val * 16 + fromxdigit(start[i+1]); + *q++ = val; + } + + ptrs[ptrnum] = q; + } + + if (!strcmp(buf, "mul")) { + Bignum a, b, c, p; + + if (ptrnum != 3) { + printf("%d: mul with %d parameters, expected 3\n", line, ptrnum); + exit(1); + } + a = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); + b = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); + c = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); + p = bigmul(a, b); + + if (bignum_cmp(c, p) == 0) { + passes++; + } else { + char *as = bignum_decimal(a); + char *bs = bignum_decimal(b); + char *cs = bignum_decimal(c); + char *ps = bignum_decimal(p); + + printf("%d: fail: %s * %s gave %s expected %s\n", + line, as, bs, ps, cs); + fails++; + + sfree(as); + sfree(bs); + sfree(cs); + sfree(ps); + } + freebn(a); + freebn(b); + freebn(c); + freebn(p); + } else if (!strcmp(buf, "modmul")) { + Bignum a, b, m, c, p; + + if (ptrnum != 4) { + printf("%d: modmul with %d parameters, expected 4\n", + line, ptrnum); + exit(1); + } + a = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); + b = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); + m = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); + c = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]); + p = modmul(a, b, m); + + if (bignum_cmp(c, p) == 0) { + passes++; + } else { + char *as = bignum_decimal(a); + char *bs = bignum_decimal(b); + char *ms = bignum_decimal(m); + char *cs = bignum_decimal(c); + char *ps = bignum_decimal(p); + + printf("%d: fail: %s * %s mod %s gave %s expected %s\n", + line, as, bs, ms, ps, cs); + fails++; + + sfree(as); + sfree(bs); + sfree(ms); + sfree(cs); + sfree(ps); + } + freebn(a); + freebn(b); + freebn(m); + freebn(c); + freebn(p); + } else if (!strcmp(buf, "pow")) { + Bignum base, expt, modulus, expected, answer; + + if (ptrnum != 4) { + printf("%d: pow with %d parameters, expected 4\n", line, ptrnum); + exit(1); + } + + base = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); + expt = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); + modulus = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); + expected = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]); + answer = modpow(base, expt, modulus); + + if (bignum_cmp(expected, answer) == 0) { + passes++; + } else { + char *as = bignum_decimal(base); + char *bs = bignum_decimal(expt); + char *cs = bignum_decimal(modulus); + char *ds = bignum_decimal(answer); + char *ps = bignum_decimal(expected); + + printf("%d: fail: %s ^ %s mod %s gave %s expected %s\n", + line, as, bs, cs, ds, ps); + fails++; + + sfree(as); + sfree(bs); + sfree(cs); + sfree(ds); + sfree(ps); + } + freebn(base); + freebn(expt); + freebn(modulus); + freebn(expected); + freebn(answer); + } else if (!strcmp(buf, "divmod")) { + Bignum n, d, expect_q, expect_r, answer_q, answer_r; + int fail; + + if (ptrnum != 4) { + printf("%d: divmod with %d parameters, expected 4\n", line, ptrnum); + exit(1); + } + + n = bignum_from_bytes(ptrs[0], ptrs[1]-ptrs[0]); + d = bignum_from_bytes(ptrs[1], ptrs[2]-ptrs[1]); + expect_q = bignum_from_bytes(ptrs[2], ptrs[3]-ptrs[2]); + expect_r = bignum_from_bytes(ptrs[3], ptrs[4]-ptrs[3]); + answer_q = bigdiv(n, d); + answer_r = bigmod(n, d); + + fail = FALSE; + if (bignum_cmp(expect_q, answer_q) != 0) { + char *as = bignum_decimal(n); + char *bs = bignum_decimal(d); + char *cs = bignum_decimal(answer_q); + char *ds = bignum_decimal(expect_q); + + printf("%d: fail: %s / %s gave %s expected %s\n", + line, as, bs, cs, ds); + fail = TRUE; + + sfree(as); + sfree(bs); + sfree(cs); + sfree(ds); + } + if (bignum_cmp(expect_r, answer_r) != 0) { + char *as = bignum_decimal(n); + char *bs = bignum_decimal(d); + char *cs = bignum_decimal(answer_r); + char *ds = bignum_decimal(expect_r); + + printf("%d: fail: %s mod %s gave %s expected %s\n", + line, as, bs, cs, ds); + fail = TRUE; + + sfree(as); + sfree(bs); + sfree(cs); + sfree(ds); + } + + freebn(n); + freebn(d); + freebn(expect_q); + freebn(expect_r); + freebn(answer_q); + freebn(answer_r); + + if (fail) + fails++; + else + passes++; + } else { + printf("%d: unrecognised test keyword: '%s'\n", line, buf); + exit(1); + } + + sfree(buf); + sfree(data); + } + + printf("passed %d failed %d total %d\n", passes, fails, passes+fails); + return fails != 0; +}