* @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.
if (osz >= SZ_REGEN && nsz < SZ_REGEN) {
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);
* @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
if (psz < ivsz + SEQSZ + tagsz) {
T( trace(T_KEYSET, "keyset: block too small for keyset %u", ks->seq); )
- return (-1);
+ return (KSERR_DECRYPT);
}
sz = psz - ivsz - SEQSZ - tagsz;
pmac = BCUR(b); pseq = pmac + tagsz; piv = pseq + SEQSZ; ppk = piv + ivsz;
trace(T_KEYSET, "keyset: incorrect MAC: decryption failed");
trace_block(T_CRYPTO, "crypto: expected MAC", pmac, tagsz);
})
- return (-1);
+ return (KSERR_DECRYPT);
}
}
* @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
if (!KEYOK(ks, now)) {
buf_break(bb);
- return (0);
+ return (KSERR_NOKEYS);
}
return (doencrypt(ks, ty, b, 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_DECRYPT@ 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
buf_ensure(bb, BLEN(b)) ||
dodecrypt(ks, ty, b, bb, &seq) ||
seq_check(&ks->iseq, seq, "SYMM"))
- return (-1);
+ return (KSERR_DECRYPT);
return (0);
}
* @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.
*/
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;
* @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.
*/
uint32 seq;
if (buf_ensure(bb, BLEN(b)))
- return (-1);
+ return (KSERR_DECRYPT);
for (ks = *ksroot; ks; ks = ks->next) {
if (!KEYOK(ks, now))
ks->seq); )
ks->f &= ~KSF_LISTEN;
}
- return (seq_check(&ks->iseq, seq, "SYMM"));
+ if (seq_check(&ks->iseq, seq, "SYMM"))
+ return (KSERR_DECRYPT);
+ else
+ return (0);
}
}
T( trace(T_KEYSET, "keyset: no matching keys, or incorrect MAC"); )
- return (-1);
+ return (KSERR_DECRYPT);
}
/*----- That's all, folks -------------------------------------------------*/
p_pingdone(pg, PING_OK);
}
+/* --- @p_encrypt@ --- *
+ *
+ * Arguments: @peer *p@ = peer to encrypt message to
+ * @int ty@ message type to send
+ * @buf *bin, *bout@ = input and output buffers
+ *
+ * Returns: ---
+ *
+ * Use: Convenience function for packet encryption. Forces
+ * renegotiation when necessary. Check for the output buffer
+ * being broken to find out whether the encryption was
+ * successful.
+ */
+
+static int p_encrypt(peer *p, int ty, buf *bin, buf *bout)
+{
+ int err = ksl_encrypt(&p->ks, ty, bin, bout);
+
+ if (err == KSERR_REGEN) {
+ kx_start(&p->kx, 1);
+ err = 0;
+ }
+ if (!BOK(bout))
+ err = -1;
+ return (err);
+}
+
+/* --- @p_decrypt@ --- *
+ *
+ * Arguments: @peer *p@ = peer to decrypt message from
+ * @int ty@ = message type to expect
+ * @buf *bin, *bout@ = input and output buffers
+ *
+ * Returns: Zero on success; nonzero on error.
+ *
+ * Use: Convenience function for packet decryption. Reports errors
+ * and updates statistics appropriately.
+ */
+
+static int p_decrypt(peer *p, int ty, buf *bin, buf *bout)
+{
+ if (ksl_decrypt(&p->ks, ty, bin, bout)) {
+ p->st.n_reject++;
+ a_warn("PEER", "?PEER", p, "decrypt-failed", A_END);
+ return (-1);
+ }
+ if (!BOK(bout))
+ return (-1);
+ return (0);
+}
+
/* --- @p_read@ --- *
*
* Arguments: @int fd@ = file descriptor to read from
return;
}
buf_init(&bb, buf_o, sizeof(buf_o));
- if (ksl_decrypt(&p->ks, MSG_PACKET, &b, &bb)) {
- p->st.n_reject++;
- a_warn("PEER", "?PEER", p, "decrypt-failed", A_END);
+ if (p_decrypt(p, MSG_PACKET, &b, &bb))
return;
- }
if (BOK(&bb)) {
p->st.n_ipin++;
p->st.sz_ipin += BSZ(&b);
break;
case MISC_EPING:
buf_init(&bb, buf_t, sizeof(buf_t));
- if (ksl_decrypt(&p->ks, ch, &b, &bb)) {
- p->st.n_reject++;
- a_warn("PEER", "?PEER", p, "decrypt-failed", A_END);
+ if (p_decrypt(p, ch, &b, &bb))
return;
- }
if (BOK(&bb)) {
buf_flip(&bb);
- if (ksl_encrypt(&p->ks, MSG_MISC | MISC_EPONG, &bb,
- p_txstart(p, MSG_MISC | MISC_EPONG)))
- kx_start(&p->kx, 0);
+ p_encrypt(p, MSG_MISC | MISC_EPONG, &bb,
+ p_txstart(p, MSG_MISC | MISC_EPONG));
p_txend(p);
}
break;
case MISC_EPONG:
buf_init(&bb, buf_t, sizeof(buf_t));
- if (ksl_decrypt(&p->ks, ch, &b, &bb)) {
- p->st.n_reject++;
- a_warn("PEER", "?PEER", p, "decrypt-failed", A_END);
+ if (p_decrypt(p, ch, &b, &bb))
return;
- }
if (BOK(&bb)) {
buf_flip(&bb);
p_ponged(p, MISC_EPONG, &bb);
buf_init(&bb, buf_t, sizeof(buf_t));
p_pingwrite(pg, &bb);
buf_flip(&bb);
- if (ksl_encrypt(&p->ks, MSG_MISC | MISC_EPING, &bb, b))
- kx_start(&p->kx, 0);
+ p_encrypt(p, MSG_MISC | MISC_EPING, &bb, b);
if (!BOK(b))
return (-1);
p_txend(p);
buf *bb = p_txstart(p, MSG_PACKET);
TIMER;
- if (ksl_encrypt(&p->ks, MSG_PACKET, b, bb))
- kx_start(&p->kx, 0);
+ p_encrypt(p, MSG_PACKET, b, bb);
if (BOK(bb) && BLEN(bb)) {
p->st.n_ipout++;
p->st.sz_ipout += BLEN(bb);
#define KSF_LISTEN 1u /* Don't encrypt packets yet */
#define KSF_LINK 2u /* Key is in a linked list */
+#define KSERR_REGEN -1 /* Regenerate keys */
+#define KSERR_NOKEYS -2 /* No keys left */
+#define KSERR_DECRYPT -3 /* Unable to decrypt message */
+
/* --- Key exchange --- *
*
* TrIPE uses the Wrestlers Protocol for its key exchange. The Wrestlers
* @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
* @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_DECRYPT@ 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
* @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.
*/
* @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.
*/