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 -------------------------------------------------*/