chiark / gitweb /
slip: Report unexpected kinds of death from userv
[secnet.git] / eax-test.c
1 /*
2  * eax-test.c: test harness for EAX, implementation
3  */
4 /*
5  * This file is Free Software.  It was originally written for secnet.
6  *
7  * You may redistribute it and/or modify it under the terms of the GNU
8  * General Public License as published by the Free Software
9  * Foundation; either version 2, or (at your option) any later
10  * version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 /*
23  * usages:
24  *   ./eax-foo-test <eax-foo-test.vectors
25  *      runs the test vectors, regenerates the file on stdout
26  *   grep -v CIPHER <eax-foo-test.vectors | ./eax-foo-test
27  *      generates output with CIPHER lines reinserted
28  * All errors result in calls to abort().
29  */
30
31 #include "eax-test.h"
32
33 struct valbuf {
34     _Bool got;
35     uint8_t v[1024];
36     size_t len;
37 };
38 #define V(vb) ((vb).v), ((vb).len)
39
40 static struct valbuf msg, key, nonce, header, cipher, ourcipher, returnplain;
41 static size_t tau;
42
43 static void trydecrypt(_Bool expected)
44 {
45     _Bool actual = eax_decrypt(-1, V(nonce), V(header), V(ourcipher), tau,
46                                returnplain.v);
47     assert(actual == expected);
48     if (actual) {
49         returnplain.len = ourcipher.len - tau;
50         assert(returnplain.len == msg.len);
51         assert(!memcmp(returnplain.v, msg.v, msg.len));
52     }
53 }
54
55 static void negtest(struct valbuf *perturb)
56 {
57     unsigned delta = 0x04;
58     size_t i;
59     for (i=0; i<perturb->len; i++) {
60         perturb->v[i] ^= delta;
61         trydecrypt(0);
62         perturb->v[i] ^= delta;
63     }
64 }
65
66 static void something(void)
67 {
68     if (!msg.got) return;
69     assert(key.got);
70     assert(nonce.got);
71     assert(header.got);
72     eaxtest_blockcipher_key_setup(V(key));
73     eax_setup(-1);
74     if (cipher.got) {
75         assert(cipher.len > msg.len);
76         tau = cipher.len - msg.len;
77         assert(tau <= blocksize);
78     } else {
79         assert(msg.len + blocksize < sizeof(ourcipher.v));
80         tau = blocksize;
81     }
82     ourcipher.len = msg.len + tau;
83     eax_encrypt(-1, V(nonce), V(header), V(msg), tau, ourcipher.v);
84     if (cipher.got) {
85         assert(ourcipher.len == cipher.len);
86         assert(!memcmp(ourcipher.v, cipher.v, cipher.len));
87         trydecrypt(1);
88         negtest(&ourcipher);
89         negtest(&header);
90     } else {
91         size_t i;
92         printf("CIPHER: ");
93         for (i=0; i<ourcipher.len; i++)
94             printf("%02X", ourcipher.v[i]);
95         putchar('\n');
96     }
97     msg.got=key.got=nonce.got=header.got=0;
98 }
99
100 static int getputchar(void)
101 {
102     int c = getchar();
103     assert(c != EOF);
104     putchar(c);
105     return c;
106 }
107
108 int main(int argc, const char *const *argv)
109 {
110     struct valbuf *cv;
111
112     assert(argc==1);
113
114     for (;;) {
115         int c = getchar();
116         switch (c) {
117         case 'M':  something();  cv = &msg;     putchar(c);  break;
118         case 'K':                cv = &key;     putchar(c);  break;
119         case 'N':                cv = &nonce;   putchar(c);  break;
120         case 'H':                cv = &header;  putchar(c);  break;
121         case 'C':                cv = &cipher;  putchar(c);  break;
122         case '\n':                              putchar(c);  continue;
123         case EOF:  something();  exit(0);
124         default:   assert(!"unexpected input");
125         }
126         cv->got = 1;
127         cv->len = 0;
128         for (;;) {
129             c = getputchar();
130             if (c == ':') break;
131             assert(isalpha(c));
132         }
133         for (;;) {
134             char hbuf[3], *ep;
135             c = getputchar();
136             if (c == '\n') break;
137             if (isspace(c)) continue;
138             assert(isprint(c));
139             hbuf[0] = c;
140             c = getputchar();
141             assert(isprint(c));
142             hbuf[1] = c;
143             hbuf[2] = 0;
144             assert(cv->len < sizeof(cv->v));
145             cv->v[cv->len++] = strtoul(hbuf,&ep,16);
146             assert(!*ep);
147         }
148     }
149     assert(!ferror(stdin));
150     assert(feof(stdin));
151     assert(!ferror(stdout));
152     assert(!fflush(stdout));
153     return 0;
154 }