X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/blobdiff_plain/e04c2d50fd96f3f31bc96851c55c6efecc10469c..494a7ac04de2a38bf6aade234602f831be314c55:/server/keyset.c diff --git a/server/keyset.c b/server/keyset.c index 0a4952a8..66a59618 100644 --- a/server/keyset.c +++ b/server/keyset.c @@ -1,7 +1,5 @@ /* -*-c-*- * - * $Id$ - * * Handling of symmetric keysets * * (c) 2001 Straylight/Edgeware @@ -30,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) @@ -84,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. @@ -153,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); @@ -170,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 @@ -198,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; @@ -216,7 +201,7 @@ static int dodecrypt(keyset *ks, unsigned ty, buf *b, buf *bb, uint32 *seq) GH_HASH(h, t, sizeof(t)); GH_HASH(h, pseq, SEQSZ + ivsz + sz); mac = GH_DONE(h, 0); - eq = !memcmp(mac, pmac, tagsz); + eq = ct_memeq(mac, pmac, tagsz); IF_TRACING(T_KEYSET, { trace_block(T_CRYPTO, "crypto: computed MAC", mac, tagsz); }) @@ -226,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); } } @@ -303,6 +288,7 @@ keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p) keyset *ks = CREATE(keyset); time_t now = time(0); const octet *pp = k; + const algswitch *algs = &p->kx.kpriv->algs; T( static unsigned seq = 0; ) T( trace(T_KEYSET, "keyset: adding new keyset %u", seq); ) @@ -318,21 +304,21 @@ keyset *ks_gen(const void *k, size_t x, size_t y, size_t z, peer *p) #define HASH_in MINE; YOURS; OURS #define HASH_out YOURS; MINE; OURS -#define INIT_c(k) GC_INIT(algs.c, (k), algs.cksz) -#define INIT_m(k) GM_KEY(algs.m, (k), algs.mksz) +#define INIT_c(k) GC_INIT(algs->c, (k), algs->cksz) +#define INIT_m(k) GM_KEY(algs->m, (k), algs->mksz) #define STR_c "encryption" #define STR_m "integrity" #define STR_in "incoming" #define STR_out "outgoing" #define SETKEY(a, dir) do { \ - h = GH_INIT(algs.h); \ + h = GH_INIT(algs->h); \ HASH_STRING(h, "tripe-" STR_##a); \ HASH_##dir; \ hh = GH_DONE(h, 0); \ IF_TRACING(T_KEYSET, { \ trace_block(T_CRYPTO, "crypto: " STR_##dir " key " STR_##a, \ - hh, algs.a##ksz); \ + hh, algs->a##ksz); \ }) \ ks->a##dir = INIT_##a(hh); \ GH_DESTROY(h); \ @@ -357,25 +343,17 @@ 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; ks->p = p; ks->f = KSF_LISTEN; - ks->tagsz = algs.tagsz; + ks->tagsz = algs->tagsz; 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 @@ -401,9 +379,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 +396,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 +408,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 +421,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 +515,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 +532,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 +549,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 +561,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 -------------------------------------------------*/