chiark / gitweb /
3053ca8e2c98840ab86690f8ccdddead50aa0239
[tripe] / server / keyset.c
1 /* -*-c-*-
2  *
3  * Handling of symmetric keysets
4  *
5  * (c) 2001 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 /*----- Handy macros ------------------------------------------------------*/
32
33 #define KEYOK(ks, now) ((ks)->sz_exp > 0 && (ks)->t_exp > now)
34
35 #define SEQSZ 4                         /* Size of sequence number packet */
36
37 /*----- Low-level packet encryption and decryption ------------------------*/
38
39 /* --- Encrypted data format --- *
40  *
41  * Let %$p_i$% be the %$i$%-th plaintext message, with type %$t$%.  We first
42  * compute
43  *
44  *   %$c_i = \mathcal{E}\textrm{-CBC}_{K_{\text{E}}}(p_i)$%
45  *
46  * as the CBC-ciphertext of %$p_i$%, and then
47  *
48  *   %$\sigma_i = \mathcal{T}_{K_{\text{M}}}(t, i, c_i)$%
49  *
50  * as a MAC on the %%\emph{ciphertext}%%.  The message sent is then the pair
51  * %$(\sigma_i, c_i)$%.  This construction is provably secure in the NM-CCA
52  * sense (assuming that the cipher is IND-CPA, and the MAC is SUF-CMA)
53  * [Bellare and Namprempre].
54  *
55  * This also ensures that, assuming the key is good, we have a secure channel
56  * [Krawczyk].  Actually, [Krawczyk] shows that, if the cipher is either a
57  * simple stream cipher or a block cipher in CBC mode, we can use the MAC-
58  * then-encrypt scheme and still have a secure channel.  However, I like the
59  * NM-CCA guarantee from [Bellare and Namprempre].  I'm less worried about
60  * the Horton Principle [Wagner and Schneier].
61  */
62
63 /* --- @doencrypt@ --- *
64  *
65  * Arguments:   @keyset *ks@ = pointer to keyset to use
66  *              @unsigned ty@ = type of message this is
67  *              @buf *b@ = pointer to an input buffer
68  *              @buf *bb@ = pointer to an output buffer
69  *
70  * Returns:     Zero if OK; @KSERR_REGEN@ if it's time to generate new keys.
71  *              Also returns zero if there was insufficient buffer space, but
72  *              the buffer is broken in this case.
73  *
74  * Use:         Encrypts a message with the given key.  We assume that the
75  *              keyset is OK to use.
76  */
77
78 static int doencrypt(keyset *ks, unsigned ty, buf *b, buf *bb)
79 {
80   ghash *h;
81   gcipher *c = ks->cout;
82   const octet *p = BCUR(b);
83   size_t sz = BLEFT(b);
84   octet *qmac, *qseq, *qiv, *qpk;
85   uint32 oseq;
86   size_t ivsz = GC_CLASS(c)->blksz;
87   size_t tagsz = ks->tagsz;
88   size_t osz, nsz;
89   octet t[4];
90   int rc = 0;
91
92   /* --- Allocate the required buffer space --- */
93
94   if (buf_ensure(bb, tagsz + SEQSZ + ivsz + sz))
95     return (0); /* Caution! */
96   qmac = BCUR(bb); qseq = qmac + tagsz; qiv = qseq + SEQSZ; qpk = qiv + ivsz;
97   BSTEP(bb, tagsz + SEQSZ + ivsz + sz);
98   STORE32(t, ty);
99
100   oseq = ks->oseq++; STORE32(qseq, oseq);
101   IF_TRACING(T_KEYSET, {
102     trace(T_KEYSET, "keyset: encrypting packet %lu using keyset %u",
103           (unsigned long)oseq, ks->seq);
104     trace_block(T_CRYPTO, "crypto: plaintext packet", p, sz);
105   })
106
107   /* --- Encrypt the packet --- */
108
109   if (ivsz) {
110     rand_get(RAND_GLOBAL, qiv, ivsz);
111     GC_SETIV(c, qiv);
112     IF_TRACING(T_KEYSET, {
113       trace_block(T_CRYPTO, "crypto: initialization vector", qiv, ivsz);
114     })
115   }
116   GC_ENCRYPT(c, p, qpk, sz);
117   IF_TRACING(T_KEYSET, {
118     trace_block(T_CRYPTO, "crypto: encrypted packet", qpk, sz);
119   })
120
121   /* --- Now compute the MAC --- */
122
123   if (tagsz) {
124     h = GM_INIT(ks->mout);
125     GH_HASH(h, t, sizeof(t));
126     GH_HASH(h, qseq, SEQSZ + ivsz + sz);
127     memcpy(qmac, GH_DONE(h, 0), tagsz);
128     GH_DESTROY(h);
129     IF_TRACING(T_KEYSET, {
130       trace_block(T_CRYPTO, "crypto: computed MAC", qmac, tagsz);
131     })
132   }
133
134   /* --- Deduct the packet size from the key's data life --- */
135
136   osz = ks->sz_exp;
137   if (osz > sz)
138     nsz = osz - sz;
139   else
140     nsz = 0;
141   if (osz >= ks->sz_regen && ks->sz_regen > nsz) {
142     T( trace(T_KEYSET, "keyset: keyset %u data regen limit exceeded -- "
143              "forcing exchange", ks->seq); )
144     rc = KSERR_REGEN;
145   }
146   ks->sz_exp = nsz;
147   return (rc);
148 }
149
150 /* --- @dodecrypt@ --- *
151  *
152  * Arguments:   @keyset *ks@ = pointer to keyset to use
153  *              @unsigned ty@ = expected type code
154  *              @buf *b@ = pointer to an input buffer
155  *              @buf *bb@ = pointer to an output buffer
156  *              @uint32 *seq@ = where to store the sequence number
157  *
158  * Returns:     Zero on success; @KSERR_DECRYPT@ on failure.
159  *
160  * Use:         Attempts to decrypt a message with the given key.  No other
161  *              checking (e.g., sequence number checks) is performed.  We
162  *              assume that the keyset is OK to use, and that there is
163  *              sufficient output buffer space reserved.  If the decryption
164  *              is successful, the buffer pointer is moved past the decrypted
165  *              packet, and the packet's sequence number is stored in @*seq@.
166  */
167
168 static int dodecrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq)
169 {
170   const octet *pmac, *piv, *pseq, *ppk;
171   size_t psz = BLEFT(b);
172   size_t sz;
173   octet *q = BCUR(bb);
174   ghash *h;
175   gcipher *c = ks->cin;
176   size_t ivsz = GC_CLASS(c)->blksz;
177   size_t tagsz = ks->tagsz;
178   octet *mac;
179   int eq;
180   octet t[4];
181
182   /* --- Break up the packet into its components --- */
183
184   if (psz < ivsz + SEQSZ + tagsz) {
185     T( trace(T_KEYSET, "keyset: block too small for keyset %u", ks->seq); )
186     return (KSERR_MALFORMED);
187   }
188   sz = psz - ivsz - SEQSZ - tagsz;
189   pmac = BCUR(b); pseq = pmac + tagsz; piv = pseq + SEQSZ; ppk = piv + ivsz;
190   STORE32(t, ty);
191
192   IF_TRACING(T_KEYSET, {
193     trace(T_KEYSET, "keyset: decrypting using keyset %u", ks->seq);
194     trace_block(T_CRYPTO, "crypto: ciphertext packet", ppk, sz);
195   })
196
197   /* --- Verify the MAC on the packet --- */
198
199   if (tagsz) {
200     h = GM_INIT(ks->min);
201     GH_HASH(h, t, sizeof(t));
202     GH_HASH(h, pseq, SEQSZ + ivsz + sz);
203     mac = GH_DONE(h, 0);
204     eq = !memcmp(mac, pmac, tagsz);
205     IF_TRACING(T_KEYSET, {
206       trace_block(T_CRYPTO, "crypto: computed MAC", mac, tagsz);
207     })
208     GH_DESTROY(h);
209     if (!eq) {
210       IF_TRACING(T_KEYSET, {
211         trace(T_KEYSET, "keyset: incorrect MAC: decryption failed");
212         trace_block(T_CRYPTO, "crypto: expected MAC", pmac, tagsz);
213       })
214       return (KSERR_DECRYPT);
215     }
216   }
217
218   /* --- Decrypt the packet --- */
219
220   if (ivsz) {
221     GC_SETIV(c, piv);
222     IF_TRACING(T_KEYSET, {
223       trace_block(T_CRYPTO, "crypto: initialization vector", piv, ivsz);
224     })
225   }
226   GC_DECRYPT(c, ppk, q, sz);
227   if (seq)
228     *seq = LOAD32(pseq);
229   IF_TRACING(T_KEYSET, {
230     trace(T_KEYSET, "keyset: decrypted OK (sequence = %lu)",
231           (unsigned long)LOAD32(pseq));
232     trace_block(T_CRYPTO, "crypto: decrypted packet", q, sz);
233   })
234   BSTEP(bb, sz);
235   return (0);
236 }
237
238 /*----- Operations on a single keyset -------------------------------------*/
239
240 /* --- @ks_drop@ --- *
241  *
242  * Arguments:   @keyset *ks@ = pointer to a keyset
243  *
244  * Returns:     ---
245  *
246  * Use:         Decrements a keyset's reference counter.  If the counter hits
247  *              zero, the keyset is freed.
248  */
249
250 void ks_drop(keyset *ks)
251 {
252   if (--ks->ref)
253     return;
254   GC_DESTROY(ks->cin);
255   GC_DESTROY(ks->cout);
256   GM_DESTROY(ks->min);
257   GM_DESTROY(ks->mout);
258   DESTROY(ks);
259 }
260
261 /* --- @ks_gen@ --- *
262  *
263  * Arguments:   @const void *k@ = pointer to key material
264  *              @size_t x, y, z@ = offsets into key material (see below)
265  *              @peer *p@ = pointer to peer information
266  *
267  * Returns:     A pointer to the new keyset.
268  *
269  * Use:         Derives a new keyset from the given key material.  The
270  *              offsets @x@, @y@ and @z@ separate the key material into three
271  *              parts.  Between the @k@ and @k + x@ is `my' contribution to
272  *              the key material; between @k + x@ and @k + y@ is `your'
273  *              contribution; and between @k + y@ and @k + z@ is a shared
274  *              value we made together.  These are used to construct two
275  *              pairs of symmetric keys.  Each pair consists of an encryption
276  *              key and a message authentication key.  One pair is used for
277  *              outgoing messages, the other for incoming messages.
278  *
279  *              The new key is marked so that it won't be selected for output
280  *              by @ksl_encrypt@.  You can still encrypt data with it by
281  *              calling @ks_encrypt@ directly.
282  */
283
284 keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p)
285 {
286   ghash *h;
287   const octet *hh;
288   keyset *ks = CREATE(keyset);
289   time_t now = time(0);
290   const octet *pp = k;
291   T( static unsigned seq = 0; )
292
293   T( trace(T_KEYSET, "keyset: adding new keyset %u", seq); )
294
295   /* --- Construct the various keys --- *
296    *
297    * This is done with macros, because it's quite tedious.
298    */
299
300 #define MINE GH_HASH(h, pp, x)
301 #define YOURS GH_HASH(h, pp + x, y - x)
302 #define OURS GH_HASH(h, pp + y, z - y)
303
304 #define HASH_in MINE; YOURS; OURS
305 #define HASH_out YOURS; MINE; OURS
306 #define INIT_c(k) GC_INIT(algs.c, (k), algs.cksz)
307 #define INIT_m(k) GM_KEY(algs.m, (k), algs.mksz)
308 #define STR_c "encryption"
309 #define STR_m "integrity"
310 #define STR_in "incoming"
311 #define STR_out "outgoing"
312
313 #define SETKEY(a, dir) do {                                             \
314   h = GH_INIT(algs.h);                                                  \
315   HASH_STRING(h, "tripe-" STR_##a);                                     \
316   HASH_##dir;                                                           \
317   hh = GH_DONE(h, 0);                                                   \
318   IF_TRACING(T_KEYSET, {                                                \
319     trace_block(T_CRYPTO, "crypto: " STR_##dir " key " STR_##a,         \
320                 hh, algs.a##ksz);                                       \
321   })                                                                    \
322   ks->a##dir = INIT_##a(hh);                                            \
323   GH_DESTROY(h);                                                        \
324 } while (0)
325
326   SETKEY(c, in); SETKEY(c, out);
327   SETKEY(m, in); SETKEY(m, out);
328
329 #undef MINE
330 #undef YOURS
331 #undef OURS
332 #undef STR_c
333 #undef STR_m
334 #undef STR_in
335 #undef STR_out
336 #undef INIT_c
337 #undef INIT_m
338 #undef HASH_in
339 #undef HASH_out
340 #undef SETKEY
341
342   T( ks->seq = seq++; )
343   ks->ref = 1;
344   ks->t_exp = now + T_EXP;
345   ks->sz_exp = algs.expsz;
346   ks->sz_regen = algs.expsz/2;
347   ks->oseq = 0;
348   seq_reset(&ks->iseq);
349   ks->next = 0;
350   ks->p = p;
351   ks->f = KSF_LISTEN;
352   ks->tagsz = algs.tagsz;
353   return (ks);
354 }
355
356 /* --- @ks_tregen@ --- *
357  *
358  * Arguments:   @keyset *ks@ = pointer to a keyset
359  *
360  * Returns:     The time at which moves ought to be made to replace this key.
361  */
362
363 time_t ks_tregen(keyset *ks) { return (ks->t_exp - T_EXP + T_REGEN); }
364
365 /* --- @ks_activate@ --- *
366  *
367  * Arguments:   @keyset *ks@ = pointer to a keyset
368  *
369  * Returns:     ---
370  *
371  * Use:         Activates a keyset, so that it can be used for encrypting
372  *              outgoing messages.
373  */
374
375 void ks_activate(keyset *ks)
376 {
377   if (ks->f & KSF_LISTEN) {
378     T( trace(T_KEYSET, "keyset: activating keyset %u", ks->seq); )
379     ks->f &= ~KSF_LISTEN;
380   }
381 }
382
383 /* --- @ks_encrypt@ --- *
384  *
385  * Arguments:   @keyset *ks@ = pointer to a keyset
386  *              @unsigned ty@ = message type
387  *              @buf *b@ = pointer to input buffer
388  *              @buf *bb@ = pointer to output buffer
389  *
390  * Returns:     Zero if successful; @KSERR_REGEN@ if we should negotiate a
391  *              new key; @KSERR_NOKEYS@ if the key is not usable.  Also
392  *              returns zero if there was insufficient buffer (but the output
393  *              buffer is broken in this case).
394  *
395  * Use:         Encrypts a block of data using the key.  Note that the `key
396  *              ought to be replaced' notification is only ever given once
397  *              for each key.  Also note that this call forces a keyset to be
398  *              used even if it's marked as not for data output.
399  */
400
401 int ks_encrypt(keyset *ks, unsigned ty, buf *b, buf *bb)
402 {
403   time_t now = time(0);
404
405   if (!KEYOK(ks, now)) {
406     buf_break(bb);
407     return (KSERR_NOKEYS);
408   }
409   return (doencrypt(ks, ty, b, bb));
410 }
411
412 /* --- @ks_decrypt@ --- *
413  *
414  * Arguments:   @keyset *ks@ = pointer to a keyset
415  *              @unsigned ty@ = expected type code
416  *              @buf *b@ = pointer to an input buffer
417  *              @buf *bb@ = pointer to an output buffer
418  *
419  * Returns:     Zero on success; @KSERR_...@ on failure.  Also returns
420  *              zero if there was insufficient buffer (but the output buffer
421  *              is broken in this case).
422  *
423  * Use:         Attempts to decrypt a message using a given key.  Note that
424  *              requesting decryption with a key directly won't clear a
425  *              marking that it's not for encryption.
426  */
427
428 int ks_decrypt(keyset *ks, unsigned ty, buf *b, buf *bb)
429 {
430   time_t now = time(0);
431   uint32 seq;
432   int err;
433
434   if (!KEYOK(ks, now)) return (KSERR_DECRYPT);
435   if (buf_ensure(bb, BLEN(b))) return (0);
436   if ((err = dodecrypt(ks, ty, b, bb, &seq)) != 0) return (err);
437   if (seq_check(&ks->iseq, seq, "SYMM")) return (KSERR_SEQ);
438   return (0);
439 }
440
441 /*----- Keyset list handling ----------------------------------------------*/
442
443 /* --- @ksl_free@ --- *
444  *
445  * Arguments:   @keyset **ksroot@ = pointer to keyset list head
446  *
447  * Returns:     ---
448  *
449  * Use:         Frees (releases references to) all of the keys in a keyset.
450  */
451
452 void ksl_free(keyset **ksroot)
453 {
454   keyset *ks, *ksn;
455   for (ks = *ksroot; ks; ks = ksn) {
456     ksn = ks->next;
457     ks->f &= ~KSF_LINK;
458     ks_drop(ks);
459   }
460 }
461
462 /* --- @ksl_link@ --- *
463  *
464  * Arguments:   @keyset **ksroot@ = pointer to keyset list head
465  *              @keyset *ks@ = pointer to a keyset
466  *
467  * Returns:     ---
468  *
469  * Use:         Links a keyset into a list.  A keyset can only be on one list
470  *              at a time.  Bad things happen otherwise.
471  */
472
473 void ksl_link(keyset **ksroot, keyset *ks)
474 {
475   assert(!(ks->f & KSF_LINK));
476   ks->next = *ksroot;
477   *ksroot = ks;
478   ks->f |= KSF_LINK;
479   ks->ref++;
480 }
481
482 /* --- @ksl_prune@ --- *
483  *
484  * Arguments:   @keyset **ksroot@ = pointer to keyset list head
485  *
486  * Returns:     ---
487  *
488  * Use:         Prunes the keyset list by removing keys which mustn't be used
489  *              any more.
490  */
491
492 void ksl_prune(keyset **ksroot)
493 {
494   time_t now = time(0);
495
496   while (*ksroot) {
497     keyset *ks = *ksroot;
498
499     if (ks->t_exp <= now) {
500       T( trace(T_KEYSET, "keyset: expiring keyset %u (time limit reached)",
501                ks->seq); )
502       goto kill;
503     } else if (ks->sz_exp == 0) {
504       T( trace(T_KEYSET, "keyset: expiring keyset %u (data limit reached)",
505                ks->seq); )
506       goto kill;
507     } else {
508       ksroot = &ks->next;
509       continue;
510     }
511
512   kill:
513     *ksroot = ks->next;
514     ks->f &= ~KSF_LINK;
515     ks_drop(ks);
516   }
517 }
518
519 /* --- @ksl_encrypt@ --- *
520  *
521  * Arguments:   @keyset **ksroot@ = pointer to keyset list head
522  *              @unsigned ty@ = message type
523  *              @buf *b@ = pointer to input buffer
524  *              @buf *bb@ = pointer to output buffer
525  *
526  * Returns:     Zero if successful; @KSERR_REGEN@ if it's time to negotiate a
527  *              new key; @KSERR_NOKEYS@ if there are no suitable keys
528  *              available.  Also returns zero if there was insufficient
529  *              buffer space (but the output buffer is broken in this case).
530  *
531  * Use:         Encrypts a packet.
532  */
533
534 int ksl_encrypt(keyset **ksroot, unsigned ty, buf *b, buf *bb)
535 {
536   time_t now = time(0);
537   keyset *ks = *ksroot;
538
539   for (;;) {
540     if (!ks) {
541       T( trace(T_KEYSET, "keyset: no suitable keysets found"); )
542       buf_break(bb);
543       return (KSERR_NOKEYS);
544     }
545     if (KEYOK(ks, now) && !(ks->f & KSF_LISTEN))
546       break;
547     ks = ks->next;
548   }
549
550   return (doencrypt(ks, ty, b, bb));
551 }
552
553 /* --- @ksl_decrypt@ --- *
554  *
555  * Arguments:   @keyset **ksroot@ = pointer to keyset list head
556  *              @unsigned ty@ = expected type code
557  *              @buf *b@ = pointer to input buffer
558  *              @buf *bb@ = pointer to output buffer
559  *
560  * Returns:     Zero on success; @KSERR_DECRYPT@ on failure.  Also returns
561  *              zero if there was insufficient buffer (but the output buffer
562  *              is broken in this case).
563  *
564  * Use:         Decrypts a packet.
565  */
566
567 int ksl_decrypt(keyset **ksroot, unsigned ty, buf *b, buf *bb)
568 {
569   time_t now = time(0);
570   keyset *ks;
571   uint32 seq;
572   int err;
573
574   if (buf_ensure(bb, BLEN(b)))
575     return (0);
576
577   for (ks = *ksroot; ks; ks = ks->next) {
578     if (!KEYOK(ks, now))
579       continue;
580     if ((err = dodecrypt(ks, ty, b, bb, &seq)) == 0) {
581       if (ks->f & KSF_LISTEN) {
582         T( trace(T_KEYSET, "keyset: implicitly activating keyset %u",
583                  ks->seq); )
584         ks->f &= ~KSF_LISTEN;
585       }
586       if (seq_check(&ks->iseq, seq, "SYMM"))
587         return (KSERR_SEQ);
588       else
589         return (0);
590     }
591     if (err != KSERR_DECRYPT) return (err);
592   }
593   T( trace(T_KEYSET, "keyset: no matching keys, or incorrect MAC"); )
594   return (KSERR_DECRYPT);
595 }
596
597 /*----- That's all, folks -------------------------------------------------*/