chiark / gitweb /
73656ec130e653378173fa53e7229e31b2728c3d
[tripe] / server / test.c
1 /* -*-c-*-
2  *
3  * Various unit-level tests
4  *
5  * (c) 2017 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Trivial IP Encryption (TrIPE).
11  *
12  * TrIPE is free software: you can redistribute it and/or modify it under
13  * the terms of the GNU General Public License as published by the Free
14  * Software Foundation; either version 3 of the License, or (at your
15  * option) any later version.
16  *
17  * TrIPE is distributed in the hope that it will be useful, but WITHOUT
18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20  * for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with TrIPE.  If not, see <https://www.gnu.org/licenses/>.
24  */
25
26 /*----- Header files ------------------------------------------------------*/
27
28 #include "tripe.h"
29
30 /*----- Data structures ---------------------------------------------------*/
31
32 /*----- Global variables --------------------------------------------------*/
33
34 sel_state sel;
35
36 /*----- Static variables --------------------------------------------------*/
37
38 static char **args;
39
40 /*----- Main code ---------------------------------------------------------*/
41
42 static void usage(FILE *fp)
43 {
44   pquis(fp,
45 "Usage: $ [-k FILE] [-t KEYTAG] [-T TRACE-OPTS] COMMAND [ARGS...]\n");
46 }
47
48 static void version(FILE *fp)
49   { pquis(fp, "$, TrIPE version " VERSION "\n"); }
50
51 static void help(FILE *fp)
52 {
53   version(fp); fputc('\n', fp);
54   usage(fp); fputc('\n', fp);
55   fputs("\
56 Options in full:\n\
57 \n\
58 -h, --help              Show this help text.\n\
59 -v, --version           Show version number.\n\
60 -u, --usage             Show brief usage message.\n\
61 \n\
62 -k, --keyring=FILE      Get keys from FILE.\n\
63 -t, --tag=KEYTAG        Use KEYTAG as master private key.\n\
64 -T, --trace=TRACE-OPTS  Turn on tracing options.\n\
65 \n\
66 Commands:\n\
67 \n\
68 ies-encrypt TY MESSAGE\n\
69 ies-decrypt TY CIPHERTEXT\n\
70 ", fp);
71 }
72
73 static uint32 parseu32(const char *p)
74 {
75   int e = errno;
76   unsigned long i;
77   char *q;
78
79   errno = 0;
80   i = strtoul(p, &q, 0);
81   while (*q && isspace((unsigned char)*q)) q++;
82   if (errno || *q || i > 0xffffffffu) die(2, "bad 32-bit integer `%s'", p);
83   errno = e;
84   return (i);
85 }
86
87 static const char *getarg(void)
88   { if (!*args) die(2, "missing argument"); else return (*args++); }
89
90 static void lastarg(void)
91   { if (*args) die(2, "unexpected argument `%s'", *args); }
92
93 int main(int argc, char *argv[])
94 {
95   const char *kr = "keyring";
96   const char *tag = "tripe";
97   const char *arg;
98   codec *b64;
99   int i, err;
100   uint32 ty;
101   buf b, bb;
102   dstr d = DSTR_INIT;
103   unsigned f = 0;
104 #define f_bogus 1u
105
106   ego(argv[0]);
107   for (;;) {
108     static const struct option opts[] = {
109       { "help",         0,              0,      'h' },
110       { "version",      0,              0,      'v' },
111       { "usage",        0,              0,      'u' },
112       { "keyring",      OPTF_ARGREQ,    0,      'k' },
113       { "tag",          OPTF_ARGREQ,    0,      't' },
114       { "trace",        OPTF_ARGREQ,    0,      'T' },
115       { 0,              0,              0,      0 }
116     };
117
118     i = mdwopt(argc, argv, "hvuk:t:T:", opts, 0, 0, 0); if (i < 0) break;
119     switch (i) {
120       case 'h': help(stdout); exit(0);
121       case 'v': version(stdout); exit(0);
122       case 'u': usage(stdout); exit(0);
123       case 'k': kr = optarg; break;
124       case 't': tag = optarg; break;
125       case 'T':
126         tr_flags = traceopt(tr_opts, optarg, tr_flags, 0);
127         break;
128       default: f |= f_bogus; break;
129     }
130   }
131   if (f&f_bogus) { usage(stderr); exit(2); }
132   args = argv + optind;
133
134   km_init(kr, kr, tag);
135   if (!master) die(3, "failed to load the master key");
136   trace_on(stderr, tr_flags);
137
138   arg = getarg();
139   if (strcmp(arg, "ies-encrypt") == 0) {
140     arg = getarg(); ty = parseu32(arg);
141     arg = getarg(); buf_init(&b, (/*unconst*/ octet *)arg, strlen(arg));
142     buf_init(&bb, buf_t, sizeof(buf_t));
143     lastarg();
144     if ((err = ies_encrypt(master, ty, &b, &bb)) != 0)
145       die(3, "ies_encrypt failed: err = %d", err);
146     b64 = base64_class.encoder(0, "\n", 72);
147     if ((err = b64->ops->code(b64, BBASE(&bb), BLEN(&bb), &d)) != 0 ||
148         (err = b64->ops->code(b64, 0, 0, &d)) != 0)
149       die(3, "base64 encoding failed: %s", codec_strerror(err));
150     b64->ops->destroy(b64);
151     DPUTC(&d, '\n');
152     fwrite(d.buf, 1, d.len, stdout);
153     dstr_destroy(&d);
154   } else if (strcmp(arg, "ies-decrypt") == 0) {
155     arg = getarg(); ty = parseu32(arg);
156     arg = getarg();
157     b64 = base64_class.decoder(CDCF_IGNSPC | CDCF_IGNNEWL);
158     if ((err = b64->ops->code(b64, arg, strlen(arg), &d)) != 0 ||
159         (err = b64->ops->code(b64, 0, 0, &d)) != 0)
160       die(3, "base64 decoding failed: %s", codec_strerror(err));
161     b64->ops->destroy(b64);
162     lastarg();
163     buf_init(&b, d.buf, d.len); buf_init(&bb, buf_t, sizeof(buf_t));
164     if ((err = ies_decrypt(master, ty, &b, &bb)) != 0)
165       die(3, "ies_decrypt failed: err = %d", err);
166     fwrite(BBASE(&bb), 1, BLEN(&bb), stdout);
167     dstr_destroy(&d);
168   } else
169     die(2, "unknown command `%s'", arg);
170
171   return (0);
172 }
173
174 /*----- That's all, folks -------------------------------------------------*/