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