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