+ *
+ * Arguments: @keyset *ks@ = pointer to a keyset
+ * @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.
+ *
+ * Use: Encrypts a block of data using the key. Note that the `key
+ * ought to be replaced' notification is only ever given once
+ * for each key. Also note that this call forces a keyset to be
+ * used even if it's marked as not for data output.
+ */
+
+int ks_encrypt(keyset *ks, buf *b, buf *bb)
+{
+ time_t now = time(0);
+
+ if (!KEYOK(ks, now)) {
+ buf_break(bb);
+ return (0);
+ }
+ return (doencrypt(ks, b, bb));
+}
+
+/* --- @ks_decrypt@ --- *
+ *
+ * Arguments: @keyset *ks@ = pointer to a keyset
+ * @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.
+ *
+ * Use: Attempts to decrypt a message using a given key. Note that
+ * requesting decryption with a key directly won't clear a
+ * marking that it's not for encryption.
+ */
+
+int ks_decrypt(keyset *ks, buf *b, buf *bb)
+{
+ time_t now = time(0);
+ uint32 seq;
+
+ if (!KEYOK(ks, now) ||
+ buf_ensure(bb, BLEN(b)) ||
+ dodecrypt(ks, b, bb, &seq) ||
+ dosequence(ks, seq))
+ return (-1);
+ return (0);
+}
+
+/*----- Keyset list handling ----------------------------------------------*/
+
+/* --- @ksl_free@ --- *
+ *
+ * Arguments: @keyset **ksroot@ = pointer to keyset list head
+ *
+ * Returns: ---
+ *
+ * Use: Frees (releases references to) all of the keys in a keyset.
+ */
+
+void ksl_free(keyset **ksroot)
+{
+ keyset *ks, *ksn;
+ for (ks = *ksroot; ks; ks = ksn) {
+ ksn = ks->next;
+ ks->f &= ~KSF_LINK;
+ ks_drop(ks);
+ }
+}
+
+/* --- @ksl_link@ --- *
+ *
+ * Arguments: @keyset **ksroot@ = pointer to keyset list head
+ * @keyset *ks@ = pointer to a keyset
+ *
+ * Returns: ---
+ *
+ * Use: Links a keyset into a list. A keyset can only be on one list
+ * at a time. Bad things happen otherwise.
+ */
+
+void ksl_link(keyset **ksroot, keyset *ks)
+{
+ assert(!(ks->f & KSF_LINK));
+ ks->next = *ksroot;
+ *ksroot = ks;
+ ks->f |= KSF_LINK;
+ ks->ref++;
+}
+
+/* --- @ksl_prune@ --- *
+ *
+ * Arguments: @keyset **ksroot@ = pointer to keyset list head
+ *
+ * Returns: ---
+ *
+ * Use: Prunes the keyset list by removing keys which mustn't be used
+ * any more.
+ */
+
+void ksl_prune(keyset **ksroot)
+{
+ time_t now = time(0);
+
+ while (*ksroot) {
+ keyset *ks = *ksroot;
+
+ if (ks->t_exp <= now) {
+ T( trace(T_KEYSET, "keyset: expiring keyset %u (time limit reached)",
+ ks->seq); )
+ goto kill;
+ } else if (ks->sz_exp == 0) {
+ T( trace(T_KEYSET, "keyset: expiring keyset %u (data limit reached)",
+ ks->seq); )
+ goto kill;
+ } else {
+ ksroot = &ks->next;
+ continue;
+ }
+
+ kill:
+ *ksroot = ks->next;
+ ks->f &= ~KSF_LINK;
+ ks_drop(ks);
+ }
+}
+
+/* --- @ksl_encrypt@ --- *