X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/53a941d3f97a50964587c6e9533b1e43e74a57a8..62b5e3ecc77424add00ad4e5dc86e7248751cdf6:/server/keyset.c diff --git a/server/keyset.c b/server/keyset.c index fe491280..f21a59a9 100644 --- a/server/keyset.c +++ b/server/keyset.c @@ -28,21 +28,6 @@ #include "tripe.h" -/*----- 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 ------------------------------------------------------*/ #define KEYOK(ks, now) ((ks)->sz_exp > 0 && (ks)->t_exp > now) @@ -82,7 +67,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. @@ -151,10 +138,10 @@ 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); @@ -168,7 +155,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 @@ -196,7 +183,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; @@ -224,7 +211,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); } } @@ -355,7 +342,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; @@ -365,15 +353,6 @@ keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p) return (ks); } -/* --- @ks_tregen@ --- * - * - * Arguments: @keyset *ks@ = pointer to a keyset - * - * Returns: The time at which moves ought to be made to replace this key. - */ - -time_t ks_tregen(keyset *ks) { return (ks->t_exp - T_EXP + T_REGEN); } - /* --- @ks_activate@ --- * * * Arguments: @keyset *ks@ = pointer to a keyset @@ -399,9 +378,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 @@ -415,7 +395,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)); } @@ -427,7 +407,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 @@ -438,12 +420,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); } @@ -532,7 +514,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. */ @@ -546,7 +531,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; @@ -563,7 +548,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. */ @@ -573,24 +560,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 -------------------------------------------------*/