X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/786989941b7b4504f0234c4a318f929802e981ad..12a26b8b34df23103d4da6d7e40705485266a4d6:/server/keyset.c diff --git a/server/keyset.c b/server/keyset.c index bb2397fc..1f580ff7 100644 --- a/server/keyset.c +++ b/server/keyset.c @@ -1,13 +1,11 @@ /* -*-c-*- - * - * $Id$ * * Handling of symmetric keysets * * (c) 2001 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Trivial IP Encryption (TrIPE). * @@ -15,12 +13,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * TrIPE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with TrIPE; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -32,18 +30,8 @@ /*----- Tunable parameters ------------------------------------------------*/ -/* --- Note on size limits --- * - * - * For a 64-bit block cipher (e.g., Blowfish), the probability of a collision - * occurring after 32 MB is less than %$2^{-21}$%, and the probability of a - * collision occurring after 64 MB is less than %$2^{-19}$%. These could be - * adjusted dependent on the encryption scheme, but it's too much pain. - */ - #define T_EXP MIN(60) /* Expiry time for a key */ #define T_REGEN MIN(45) /* Regeneration time for a key */ -#define SZ_EXP MEG(64) /* Expiry data size for a key */ -#define SZ_REGEN MEG(32) /* Data size threshold for regen */ /*----- Handy macros ------------------------------------------------------*/ @@ -56,7 +44,7 @@ /* --- Encrypted data format --- * * * Let %$p_i$% be the %$i$%-th plaintext message, with type %$t$%. We first - * compute + * compute * * %$c_i = \mathcal{E}\textrm{-CBC}_{K_{\text{E}}}(p_i)$% * @@ -84,7 +72,9 @@ * @buf *b@ = pointer to an input buffer * @buf *bb@ = pointer to an output buffer * - * Returns: Zero if OK, nonzero if a new key is required. + * Returns: Zero if OK; @KSERR_REGEN@ if it's time to generate new keys. + * Also returns zero if there was insufficient buffer space, but + * the buffer is broken in this case. * * Use: Encrypts a message with the given key. We assume that the * keyset is OK to use. @@ -153,13 +143,13 @@ static int doencrypt(keyset *ks, unsigned ty, buf *b, buf *bb) nsz = osz - sz; else nsz = 0; - if (osz >= SZ_REGEN && nsz < SZ_REGEN) { + if (osz >= ks->sz_regen && ks->sz_regen > nsz) { T( trace(T_KEYSET, "keyset: keyset %u data regen limit exceeded -- " "forcing exchange", ks->seq); ) - rc = -1; + rc = KSERR_REGEN; } ks->sz_exp = nsz; - return (rc); + return (rc); } /* --- @dodecrypt@ --- * @@ -170,7 +160,7 @@ static int doencrypt(keyset *ks, unsigned ty, buf *b, buf *bb) * @buf *bb@ = pointer to an output buffer * @uint32 *seq@ = where to store the sequence number * - * Returns: Zero if OK, nonzero if it failed. + * Returns: Zero on success; @KSERR_DECRYPT@ on failure. * * Use: Attempts to decrypt a message with the given key. No other * checking (e.g., sequence number checks) is performed. We @@ -198,7 +188,7 @@ static int dodecrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq) if (psz < ivsz + SEQSZ + tagsz) { T( trace(T_KEYSET, "keyset: block too small for keyset %u", ks->seq); ) - return (-1); + return (KSERR_MALFORMED); } sz = psz - ivsz - SEQSZ - tagsz; pmac = BCUR(b); pseq = pmac + tagsz; piv = pseq + SEQSZ; ppk = piv + ivsz; @@ -226,7 +216,7 @@ static int dodecrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq) trace(T_KEYSET, "keyset: incorrect MAC: decryption failed"); trace_block(T_CRYPTO, "crypto: expected MAC", pmac, tagsz); }) - return (-1); + return (KSERR_DECRYPT); } } @@ -277,7 +267,7 @@ void ks_drop(keyset *ks) * * Arguments: @const void *k@ = pointer to key material * @size_t x, y, z@ = offsets into key material (see below) - * @peer *p@ = pointer to peer information + * @peer *p@ = pointer to peer information * * Returns: A pointer to the new keyset. * @@ -357,7 +347,8 @@ keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p) T( ks->seq = seq++; ) ks->ref = 1; ks->t_exp = now + T_EXP; - ks->sz_exp = SZ_EXP; + ks->sz_exp = algs.expsz; + ks->sz_regen = algs.expsz/2; ks->oseq = 0; seq_reset(&ks->iseq); ks->next = 0; @@ -401,9 +392,10 @@ void ks_activate(keyset *ks) * @buf *b@ = pointer to input buffer * @buf *bb@ = pointer to output buffer * - * Returns: Zero if OK, nonzero if the key needs replacing. If the - * encryption failed, the output buffer is broken and zero is - * returned. + * Returns: Zero if successful; @KSERR_REGEN@ if we should negotiate a + * new key; @KSERR_NOKEYS@ if the key is not usable. Also + * returns zero if there was insufficient buffer (but the output + * buffer is broken in this case). * * Use: Encrypts a block of data using the key. Note that the `key * ought to be replaced' notification is only ever given once @@ -417,7 +409,7 @@ int ks_encrypt(keyset *ks, unsigned ty, buf *b, buf *bb) if (!KEYOK(ks, now)) { buf_break(bb); - return (0); + return (KSERR_NOKEYS); } return (doencrypt(ks, ty, b, bb)); } @@ -429,7 +421,9 @@ int ks_encrypt(keyset *ks, unsigned ty, buf *b, buf *bb) * @buf *b@ = pointer to an input buffer * @buf *bb@ = pointer to an output buffer * - * Returns: Zero on success, or nonzero if there was some problem. + * Returns: Zero on success; @KSERR_...@ on failure. Also returns + * zero if there was insufficient buffer (but the output buffer + * is broken in this case). * * Use: Attempts to decrypt a message using a given key. Note that * requesting decryption with a key directly won't clear a @@ -440,12 +434,12 @@ int ks_decrypt(keyset *ks, unsigned ty, buf *b, buf *bb) { time_t now = time(0); uint32 seq; + int err; - if (!KEYOK(ks, now) || - buf_ensure(bb, BLEN(b)) || - dodecrypt(ks, ty, b, bb, &seq) || - seq_check(&ks->iseq, seq, "SYMM")) - return (-1); + if (!KEYOK(ks, now)) return (KSERR_DECRYPT); + if (buf_ensure(bb, BLEN(b))) return (0); + if ((err = dodecrypt(ks, ty, b, bb, &seq)) != 0) return (err); + if (seq_check(&ks->iseq, seq, "SYMM")) return (KSERR_SEQ); return (0); } @@ -534,7 +528,10 @@ void ksl_prune(keyset **ksroot) * @buf *b@ = pointer to input buffer * @buf *bb@ = pointer to output buffer * - * Returns: Nonzero if a new key is needed. + * Returns: Zero if successful; @KSERR_REGEN@ if it's time to negotiate a + * new key; @KSERR_NOKEYS@ if there are no suitable keys + * available. Also returns zero if there was insufficient + * buffer space (but the output buffer is broken in this case). * * Use: Encrypts a packet. */ @@ -548,7 +545,7 @@ int ksl_encrypt(keyset **ksroot, unsigned ty, buf *b, buf *bb) if (!ks) { T( trace(T_KEYSET, "keyset: no suitable keysets found"); ) buf_break(bb); - return (-1); + return (KSERR_NOKEYS); } if (KEYOK(ks, now) && !(ks->f & KSF_LISTEN)) break; @@ -565,7 +562,9 @@ int ksl_encrypt(keyset **ksroot, unsigned ty, buf *b, buf *bb) * @buf *b@ = pointer to input buffer * @buf *bb@ = pointer to output buffer * - * Returns: Nonzero if the packet couldn't be decrypted. + * Returns: Zero on success; @KSERR_DECRYPT@ on failure. Also returns + * zero if there was insufficient buffer (but the output buffer + * is broken in this case). * * Use: Decrypts a packet. */ @@ -575,24 +574,29 @@ int ksl_decrypt(keyset **ksroot, unsigned ty, buf *b, buf *bb) time_t now = time(0); keyset *ks; uint32 seq; + int err; if (buf_ensure(bb, BLEN(b))) - return (-1); + return (0); for (ks = *ksroot; ks; ks = ks->next) { if (!KEYOK(ks, now)) continue; - if (!dodecrypt(ks, ty, b, bb, &seq)) { + if ((err = dodecrypt(ks, ty, b, bb, &seq)) == 0) { if (ks->f & KSF_LISTEN) { T( trace(T_KEYSET, "keyset: implicitly activating keyset %u", ks->seq); ) ks->f &= ~KSF_LISTEN; } - return (seq_check(&ks->iseq, seq, "SYMM")); + if (seq_check(&ks->iseq, seq, "SYMM")) + return (KSERR_SEQ); + else + return (0); } + if (err != KSERR_DECRYPT) return (err); } T( trace(T_KEYSET, "keyset: no matching keys, or incorrect MAC"); ) - return (-1); + return (KSERR_DECRYPT); } /*----- That's all, folks -------------------------------------------------*/