mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-20 05:45:27 -05:00

This makes it easier to compile in multiple debugging modes, or on Windows, without having to constantly paste annoying test-compile commands out of comments in sshbn.c. The new binary is compiled into the build directory, but not shipped by 'make install', just like fuzzterm. Unlike fuzzterm, though, testbn is also compiled on Windows, for which we didn't already have a mechanism for building unshipped binaries; I've done the very simplest thing for the moment, of providing a target in Makefile.vc to delete them. In order to comply with the PuTTY makefile system's constraint of never compiling the same object multiple times with different ifdefs, I've also moved testbn's main() out into its own source file.
266 lines
7.6 KiB
C
266 lines
7.6 KiB
C
/*
|
|
* testbn.c: standalone test program for the bignum code.
|
|
*/
|
|
|
|
/*
|
|
* Accepts input on standard input, in the form generated by
|
|
* testdata/bignum.py.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
#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;
|
|
}
|