chiark / gitweb /
server/tests.at (AWAIT_KXDONE): Ignore the correct server messages.
[tripe] / server / bulkcrypto.c
1 /* -*-c-*-
2  *
3  * Bulk crypto transformations
4  *
5  * (c) 2014 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
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * TrIPE is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with TrIPE; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /*----- Header files ------------------------------------------------------*/
28
29 #include "tripe.h"
30
31 /*----- Utilities ---------------------------------------------------------*/
32
33 #define SEQSZ 4                         /* Size of sequence number packet */
34
35 #define TRACE_IV(qiv, ivsz) do { IF_TRACING(T_KEYSET, {                 \
36   trace_block(T_CRYPTO, "crypto: initialization vector",                \
37               (qiv), (ivsz));                                           \
38 }) } while (0)
39
40 #define TRACE_CT(qpk, sz) do { IF_TRACING(T_KEYSET, {                   \
41   trace_block(T_CRYPTO, "crypto: encrypted packet", (qpk), (sz));       \
42 }) } while (0)
43
44 #define TRACE_MAC(qmac, tagsz) do { IF_TRACING(T_KEYSET, {              \
45   trace_block(T_CRYPTO, "crypto: computed MAC", (qmac), (tagsz));       \
46 }) } while (0)
47
48 #define CHECK_MAC(h, pmac, tagsz) do {                                  \
49   ghash *_h = (h);                                                      \
50   const octet *_pmac = (pmac);                                          \
51   size_t _tagsz = (tagsz);                                              \
52   octet *_mac = GH_DONE(_h, 0);                                         \
53   int _eq = ct_memeq(_mac, _pmac, _tagsz);                              \
54   TRACE_MAC(_mac, _tagsz);                                              \
55   GH_DESTROY(_h);                                                       \
56   if (!_eq) {                                                           \
57     IF_TRACING(T_KEYSET, {                                              \
58       trace(T_KEYSET, "keyset: incorrect MAC: decryption failed");      \
59       trace_block(T_CRYPTO, "crypto: expected MAC", _pmac, _tagsz);     \
60     })                                                                  \
61     return (KSERR_DECRYPT);                                             \
62   }                                                                     \
63 } while (0)
64
65 /*----- The original transform --------------------------------------------*
66  *
67  * We generate a random initialization vector (if the cipher needs one).  We
68  * encrypt the input message with the cipher, and format the type, sequence
69  * number, IV, and ciphertext as follows.
70  *
71  *              +------+ +------+---...---+------...------+
72  *              | type | | seq  |   iv    |   ciphertext  |
73  *              +------+ +------+---...---+------...------+
74  *                 32       32     blksz         sz
75  *
76  * All of this is fed into the MAC to compute a tag.  The type is not
77  * transmitted: the other end knows what type of message it expects, and the
78  * type is only here to prevent us from being confused because some other
79  * kind of ciphertext has been substituted.  The tag is prepended to the
80  * remainder, to yield the finished cryptogram, as follows.
81  *
82  *              +---...---+------+---...---+------...------+
83  *              |   tag   | seq  |   iv    |   ciphertext  |
84  *              +---...---+------+---...---+------...------+
85  *                 tagsz     32     blksz         sz
86  *
87  * Decryption: checks the overall size, verifies the tag, then decrypts the
88  * ciphertext and extracts the sequence number.
89  */
90
91 static int v0_check(const algswitch *a, dstr *e)
92   { return (0); }
93
94 static size_t v0_overhead(const algswitch *a)
95   { return a->tagsz + SEQSZ + a->c->blksz; }
96
97 static int v0_encrypt(keyset *ks, unsigned ty, buf *b, buf *bb)
98 {
99   ghash *h;
100   gcipher *c = ks->out.c;
101   const octet *p = BCUR(b);
102   size_t sz = BLEFT(b);
103   octet *qmac, *qseq, *qiv, *qpk;
104   uint32 oseq;
105   size_t ivsz = GC_CLASS(c)->blksz;
106   size_t tagsz = ks->tagsz;
107   octet t[4];
108
109   /* --- Determine the ciphertext layout --- */
110
111   if (buf_ensure(bb, tagsz + SEQSZ + ivsz + sz)) return (0);
112   qmac = BCUR(bb); qseq = qmac + tagsz; qiv = qseq + SEQSZ; qpk = qiv + ivsz;
113   BSTEP(bb, tagsz + SEQSZ + ivsz + sz);
114
115   /* --- Store the type --- *
116    *
117    * This isn't transmitted, but it's covered by the MAC.
118    */
119
120   STORE32(t, ty);
121
122   /* --- Store the sequence number --- */
123
124   oseq = ks->oseq++;
125   STORE32(qseq, oseq);
126
127   /* --- Establish an initialization vector if necessary --- */
128
129   if (ivsz) {
130     rand_get(RAND_GLOBAL, qiv, ivsz);
131     GC_SETIV(c, qiv);
132     TRACE_IV(qiv, ivsz);
133   }
134
135   /* --- Encrypt the packet --- */
136
137   GC_ENCRYPT(c, p, qpk, sz);
138   TRACE_CT(qpk, sz);
139
140   /* --- Compute a MAC over type, sequence number, IV, and ciphertext --- */
141
142   if (tagsz) {
143     h = GM_INIT(ks->out.m);
144     GH_HASH(h, t, sizeof(t));
145     GH_HASH(h, qseq, SEQSZ + ivsz + sz);
146     memcpy(qmac, GH_DONE(h, 0), tagsz);
147     GH_DESTROY(h);
148     TRACE_MAC(qmac, tagsz);
149   }
150
151   /* --- We're done --- */
152
153   return (0);
154 }
155
156 static int v0_decrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq)
157 {
158   const octet *pmac, *piv, *pseq, *ppk;
159   size_t psz = BLEFT(b);
160   size_t sz;
161   octet *q = BCUR(bb);
162   ghash *h;
163   gcipher *c = ks->in.c;
164   size_t ivsz = GC_CLASS(c)->blksz;
165   size_t tagsz = ks->tagsz;
166   octet t[4];
167
168   /* --- Break up the packet into its components --- */
169
170   if (psz < ivsz + SEQSZ + tagsz) {
171     T( trace(T_KEYSET, "keyset: block too small for keyset %u", ks->seq); )
172     return (KSERR_MALFORMED);
173   }
174   sz = psz - ivsz - SEQSZ - tagsz;
175   pmac = BCUR(b); pseq = pmac + tagsz; piv = pseq + SEQSZ; ppk = piv + ivsz;
176   STORE32(t, ty);
177
178   /* --- Verify the MAC on the packet --- */
179
180   if (tagsz) {
181     h = GM_INIT(ks->in.m);
182     GH_HASH(h, t, sizeof(t));
183     GH_HASH(h, pseq, SEQSZ + ivsz + sz);
184     CHECK_MAC(h, pmac, tagsz);
185   }
186
187   /* --- Decrypt the packet --- */
188
189   if (ivsz) {
190     TRACE_IV(piv, ivsz);
191     GC_SETIV(c, piv);
192   }
193   GC_DECRYPT(c, ppk, q, sz);
194
195   /* --- Finished --- */
196
197   *seq = LOAD32(pseq);
198   BSTEP(bb, sz);
199   return (0);
200 }
201
202 /*----- The implicit-IV transform -----------------------------------------*
203  *
204  * The v0 transform makes everything explicit.  There's an IV because the
205  * cipher needs an IV; there's a sequence number because replay prevention
206  * needs a sequence number.
207  *
208  * This new transform works rather differently.  We make use of a block
209  * cipher to encrypt the sequence number, and use that as the IV.  We
210  * transmit the sequence number in the clear, as before.  This reduces
211  * overhead; and it's not a significant privacy leak because the adversary
212  * can see the order in which the messages are transmitted -- i.e., the
213  * sequence numbers are almost completely predictable anyway.
214  *
215  * So, a MAC is computed over
216  *
217  *              +------+ +------+------...------+
218  *              | type | | seq  |   ciphertext  |
219  *              +------+ +------+------...------+
220  *                 32       32         sz
221  *
222  * and we actually transmit the following as the cryptogram.
223  *
224  *              +---...---+------+------...------+
225  *              |   tag   | seq  |   ciphertext  |
226  *              +---...---+------+------...------+
227  *                 tagsz     32         sz
228  */
229
230 static int iiv_check(const algswitch *a, dstr *e)
231 {
232   if (a->b->blksz < a->c->blksz) {
233     a_format(e, "blkc", "%.*s", strlen(a->b->name) - 4, a->b->name,
234              "blksz-insufficient", A_END);
235     return (-1);
236   }
237   return (0);
238 }
239
240 static size_t iiv_overhead(const algswitch *a)
241   { return a->tagsz + SEQSZ; }
242
243 #define TRACE_PRESEQ(qseq, ivsz) do { IF_TRACING(T_KEYSET, {            \
244   trace_block(T_CRYPTO, "crypto: IV derivation input", (qseq), (ivsz)); \
245 }) } while (0)
246
247 static int iiv_encrypt(keyset *ks, unsigned ty, buf *b, buf *bb)
248 {
249   ghash *h;
250   gcipher *c = ks->out.c, *blkc = ks->out.b;
251   const octet *p = BCUR(b);
252   size_t sz = BLEFT(b);
253   octet *qmac, *qseq, *qpk;
254   uint32 oseq;
255   size_t ivsz = GC_CLASS(c)->blksz, blkcsz = GC_CLASS(blkc)->blksz;
256   size_t tagsz = ks->tagsz;
257   octet t[4];
258
259   /* --- Determine the ciphertext layout --- */
260
261   if (buf_ensure(bb, tagsz + SEQSZ + sz)) return (0);
262   qmac = BCUR(bb); qseq = qmac + tagsz; qpk = qseq + SEQSZ;
263   BSTEP(bb, tagsz + SEQSZ + sz);
264
265   /* --- Store the type --- *
266    *
267    * This isn't transmitted, but it's covered by the MAC.
268    */
269
270   STORE32(t, ty);
271
272   /* --- Store the sequence number --- */
273
274   oseq = ks->oseq++;
275   STORE32(qseq, oseq);
276
277   /* --- Establish an initialization vector if necessary --- */
278
279   if (ivsz) {
280     memset(buf_u, 0, blkcsz - SEQSZ);
281     memcpy(buf_u + blkcsz - SEQSZ, qseq, SEQSZ);
282     TRACE_PRESEQ(buf_u, ivsz);
283     GC_ENCRYPT(blkc, buf_u, buf_u, blkcsz);
284     GC_SETIV(c, buf_u);
285     TRACE_IV(buf_u, ivsz);
286   }
287
288   /* --- Encrypt the packet --- */
289
290   GC_ENCRYPT(c, p, qpk, sz);
291   TRACE_CT(qpk, sz);
292
293   /* --- Compute a MAC over type, sequence number, and ciphertext --- */
294
295   if (tagsz) {
296     h = GM_INIT(ks->out.m);
297     GH_HASH(h, t, sizeof(t));
298     GH_HASH(h, qseq, SEQSZ + sz);
299     memcpy(qmac, GH_DONE(h, 0), tagsz);
300     GH_DESTROY(h);
301     TRACE_MAC(qmac, tagsz);
302   }
303
304   /* --- We're done --- */
305
306   return (0);
307 }
308
309 static int iiv_decrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq)
310 {
311   const octet *pmac, *pseq, *ppk;
312   size_t psz = BLEFT(b);
313   size_t sz;
314   octet *q = BCUR(bb);
315   ghash *h;
316   gcipher *c = ks->in.c, *blkc = ks->in.b;
317   size_t ivsz = GC_CLASS(c)->blksz, blkcsz = GC_CLASS(blkc)->blksz;
318   size_t tagsz = ks->tagsz;
319   octet t[4];
320
321   /* --- Break up the packet into its components --- */
322
323   if (psz < SEQSZ + tagsz) {
324     T( trace(T_KEYSET, "keyset: block too small for keyset %u", ks->seq); )
325     return (KSERR_MALFORMED);
326   }
327   sz = psz - SEQSZ - tagsz;
328   pmac = BCUR(b); pseq = pmac + tagsz; ppk = pseq + SEQSZ;
329   STORE32(t, ty);
330
331   /* --- Verify the MAC on the packet --- */
332
333   if (tagsz) {
334     h = GM_INIT(ks->in.m);
335     GH_HASH(h, t, sizeof(t));
336     GH_HASH(h, pseq, SEQSZ + sz);
337     CHECK_MAC(h, pmac, tagsz);
338   }
339
340   /* --- Decrypt the packet --- */
341
342   if (ivsz) {
343     memset(buf_u, 0, blkcsz - SEQSZ);
344     memcpy(buf_u + blkcsz - SEQSZ, pseq, SEQSZ);
345     TRACE_PRESEQ(buf_u, ivsz);
346     GC_ENCRYPT(blkc, buf_u, buf_u, blkcsz);
347     GC_SETIV(c, buf_u);
348     TRACE_IV(buf_u, ivsz);
349   }
350   GC_DECRYPT(c, ppk, q, sz);
351
352   /* --- Finished --- */
353
354   *seq = LOAD32(pseq);
355   BSTEP(bb, sz);
356   return (0);
357 }
358
359 /*----- Bulk crypto transform table ---------------------------------------*/
360
361 const bulkcrypto bulktab[] = {
362
363 #define BULK(name, pre, prim)                                           \
364   { name, prim, pre##_check, pre##_overhead, pre##_encrypt, pre##_decrypt }
365
366   BULK("v0", v0, BCP_CIPHER | BCP_MAC),
367   BULK("iiv", iiv, BCP_CIPHER | BCP_MAC | BCP_BLKC),
368
369 #undef BULK
370   { 0 }
371 };
372
373 /*----- That's all, folks -------------------------------------------------*/