3 * $Id: keyset.c,v 1.1 2001/02/03 20:26:37 mdw Exp $
5 * Handling of symmetric keysets
7 * (c) 2001 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Trivial IP Encryption (TrIPE).
14 * TrIPE is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * TrIPE is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with TrIPE; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /*----- Revision history --------------------------------------------------*
32 * Revision 1.1 2001/02/03 20:26:37 mdw
37 /*----- Header files ------------------------------------------------------*/
41 /*----- Tunable parameters ------------------------------------------------*/
43 #define KEY_EXPTIME MIN(60) /* Expiry time for a key */
44 #define KEY_REGENTIME MIN(45) /* Regeneration time for a key */
45 #define KEY_EXPSZ MEG(512) /* Expiry data size for a key */
46 #define KEY_REGENSZ MEG(256) /* Data size threshold for regen */
48 /*----- Handy macros ------------------------------------------------------*/
50 #define KEYOK(ks, now) ((ks)->sz_exp > 0 && (ks)->t_exp > now)
52 /*----- Main code ---------------------------------------------------------*/
56 * Arguments: @keyset *ks@ = pointer to a keyset
60 * Use: Frees a keyset.
63 static void freeks(keyset *ks)
65 ks->c->ops->destroy(ks->c);
66 ks->m->ops->destroy(ks->m);
70 /* --- @ks_free@ --- *
72 * Arguments: @keyset **ksroot@ = pointer to keyset list head
76 * Use: Frees all of the keys in a keyset.
79 void ks_free(keyset **ksroot)
82 for (ks = *ksroot; ks; ks = ksn) {
88 /* --- @ks_prune@ --- *
90 * Arguments: @keyset **ksroot@ = pointer to keyset list head
94 * Use: Prunes the keyset list by removing keys which mustn't be used
98 void ks_prune(keyset **ksroot)
100 time_t now = time(0);
103 keyset *ks = *ksroot;
104 if (ks->t_exp <= now) {
105 T( trace(T_KEYSET, "keyset: expiring keyset %u (time limit reached)",
109 } else if (ks->sz_exp == 0) {
110 T( trace(T_KEYSET, "keyset: expiring keyset %u (data limit reached)",
119 /* --- @ks_gen@ --- *
121 * Arguments: @keyset **ksroot@ = pointer to keyset list head
122 * @const void *k@ = pointer to key material
123 * @size_t sz@ = size of the key material
125 * Returns: The regeneration time for the new key.
127 * Use: Derives a keyset from the given key material and adds it to
131 time_t ks_gen(keyset **ksroot, const void *k, size_t sz)
134 octet buf[RMD160_HASHSZ];
135 keyset *ks = CREATE(keyset);
136 time_t now = time(0);
137 T( static unsigned seq = 0; )
139 T( trace(T_KEYSET, "keyset: adding new keyset %u", seq); )
141 #define GETHASH(str) do { \
143 rmd160_hash(&r, str, sizeof(str) - 1); \
144 rmd160_hash(&r, k, sz); \
145 rmd160_done(&r, buf); \
146 IF_TRACING(T_KEYSET, { \
147 trace_block(T_CRYPTO, "crypto: key " str, buf, sizeof(buf)); \
151 GETHASH("tripe-encryption "); ks->c = blowfish_cbc.init(buf, sizeof(buf));
152 GETHASH("tripe-integrity "); ks->m = rmd160_hmac.key(buf, sizeof(buf));
156 T( ks->seq = seq++; )
157 ks->t_exp = now + KEY_EXPTIME;
158 ks->sz_exp = KEY_EXPSZ;
162 return (now + KEY_REGENTIME);
165 /* --- @ks_encrypt@ --- *
167 * Arguments: @keyset **ksroot@ = pointer to keyset list head
168 * @buf *b@ = pointer to input buffer
169 * @buf *bb@ = pointer to output buffer
171 * Returns: Nonzero if a new key is needed.
173 * Use: Encrypts a packet.
176 int ks_encrypt(keyset **ksroot, buf *b, buf *bb)
178 time_t now = time(0);
183 const octet *p = BCUR(b);
185 size_t sz = BLEFT(b);
189 /* --- Get the latest valid key --- */
194 T( trace(T_KEYSET, "keyset: no active keys -- forcing exchange"); )
203 /* --- MAC and encrypt the packet --- */
206 ivsz = c->ops->c->blksz;
207 if (buf_ensure(bb, ivsz + sz))
209 h = ks->m->ops->init(ks->m);
210 h->ops->hash(h, p, sz);
212 IF_TRACING(T_KEYSET, {
213 trace(T_KEYSET, "keyset: encrypting using keyset %u", ks->seq);
214 trace_block(T_CRYPTO, "crypto: computed MAC", q, ivsz);
219 if (buf_ensure(bb, sz))
221 c->ops->encrypt(c, p, q + ivsz, sz);
222 IF_TRACING(T_KEYSET, {
223 trace_block(T_CRYPTO, "crypto: encrypted packet", q + ivsz, sz);
225 BSTEP(bb, ivsz + sz);
227 /* --- Deduct the packet size from the key's data life --- */
234 if (osz >= KEY_REGENSZ && nsz < KEY_REGENSZ) {
235 T( trace(T_KEYSET, "keyset: keyset %u data regen limit exceeded -- "
236 "forcing exchange", ks->seq); )
243 /* --- @ks_decrypt@ --- *
245 * Arguments: @keyset **ksroot@ = pointer to keyset list head
246 * @buf *b@ = pointer to input buffer
247 * @buf *bb@ = pointer to output buffer
249 * Returns: Nonzero if the packet couldn't be decrypted.
251 * Use: Decrypts a packet.
254 int ks_decrypt(keyset **ksroot, buf *b, buf *bb)
256 time_t now = time(0);
257 const octet *pp = BCUR(b);
259 size_t sz = BLEFT(b);
263 T( trace(T_KEYSET, "keyset: attempting to decrypt packet"); )
264 if (buf_ensure(bb, sz))
266 for (ks = *ksroot; ks; ks = ks->next) {
269 size_t ivsz = c->ops->c->blksz;
276 T( trace(T_KEYSET, "keyset: block too small for keyset %u", ks->seq); )
280 c->ops->setiv(c, pp);
281 c->ops->decrypt(c, p, q, sz - ivsz);
282 h = ks->m->ops->init(ks->m);
283 h->ops->hash(h, q, sz - ivsz);
284 mac = h->ops->done(h, 0);
285 eq = !memcmp(mac, pp, ivsz);
286 IF_TRACING(T_KEYSET, {
287 trace(T_KEYSET, "keyset: decrypting using keyset %u", ks->seq);
288 trace_block(T_CRYPTO, "crypto: computed MAC", mac, ivsz);
292 BSTEP(bb, sz - ivsz);
293 IF_TRACING(T_KEYSET, {
294 trace(T_KEYSET, "keyset: decrypted OK");
295 trace_block(T_CRYPTO, "crypto: decrypted packet", q, sz - ivsz);
299 IF_TRACING(T_KEYSET, {
300 trace(T_KEYSET, "keyset: decryption failed");
301 trace_block(T_CRYPTO, "crypto: expected MAC", pp, ivsz);
304 T( trace(T_KEYSET, "keyset: no matching keys"); )
308 /*----- That's all, folks -------------------------------------------------*/