--- /dev/null
+/* -*-c-*-
+ *
+ * $Id: key-pass.c,v 1.1 1999/12/22 15:47:48 mdw Exp $
+ *
+ * Encrypting keys with passphrases
+ *
+ * (c) 1999 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------*
+ *
+ * $Log: key-pass.c,v $
+ * Revision 1.1 1999/12/22 15:47:48 mdw
+ * Major key-management revision.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+
+#include "key.h"
+#include "paranoia.h"
+#include "passphrase.h"
+#include "rand.h"
+
+#include "blowfish-cbc.h"
+#include "rmd160.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @key_plock@ --- *
+ *
+ * Arguments: @const char *tag@ = tag to use for passphrase
+ * @key_data *k@ = source key data block
+ * @key_data *kt@ = target key data block
+ *
+ * Returns: Zero if successful, nonzero if there was a problem.
+ *
+ * Use: Locks a key by encrypting it with a passphrase.
+ */
+
+int key_plock(const char *tag, key_data *k, key_data *kt)
+{
+ dstr d = DSTR_INIT;
+ octet hash[RMD160_HASHSZ];
+ char buf[256];
+
+ /* --- Sanity check --- */
+
+ assert(((void)"Key data is already encrypted",
+ (k->e & KF_ENCMASK) != KENC_ENCRYPT));
+
+ /* --- Read the passphrase --- */
+
+ if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf)))
+ return (-1);
+
+ /* --- Extract the key data --- *
+ *
+ * On the front, put four random bytes to act as a passphrase salt (which
+ * remain in the clear), and four zero bytes to be able to spot duff
+ * passphrases when unlocking.
+ */
+
+ DENSURE(&d, 8);
+ rand_getgood(RAND_GLOBAL, d.buf, 4);
+ memset(d.buf + 4, 0, 4);
+ d.len += 8;
+ key_encode(k, &d, 0);
+ if (k == kt)
+ key_destroy(k);
+
+ /* --- Hash the passphrase into a key --- */
+
+ {
+ rmd160_ctx h;
+ rmd160_init(&h);
+ rmd160_hash(&h, d.buf, 4);
+ rmd160_hash(&h, buf, strlen(buf));
+ rmd160_done(&h, hash);
+ BURN(h);
+ BURN(buf);
+ }
+
+ /* --- Encrypt the key data --- */
+
+ {
+ blowfish_cbcctx c;
+ blowfish_cbcinit(&c, hash, sizeof(hash), 0);
+ blowfish_cbcencrypt(&c, d.buf + 4, d.buf + 4, d.len - 4);
+ BURN(hash);
+ BURN(c);
+ }
+
+ /* --- Put the key data back in the key --- */
+
+ key_encrypted(kt, d.buf, d.len);
+ dstr_destroy(&d);
+ return (0);
+}
+
+/* --- @key_punlock@ --- *
+ *
+ * Arguments: @const char *tag@ = tag to use for passphrase
+ * @key_data *k@ = source key data block
+ * @key_data *kt@ = target key data block
+ *
+ * Returns: Zero if it worked, nonzero if it didn't.
+ *
+ * Use: Unlocks a passphrase-locked key.
+ */
+
+int key_punlock(const char *tag, key_data *k, key_data *kt)
+{
+ octet hash[RMD160_HASHSZ];
+ char buf[256];
+ octet *p;
+ size_t sz;
+
+ /* --- Sanity check --- */
+
+ assert(((void)"Key data isn't encrypted",
+ (k->e & KF_ENCMASK) == KENC_ENCRYPT));
+
+ /* --- Fetch the passphrase --- */
+
+ if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf)))
+ goto fail_0;
+
+ /* --- Allocate a destination buffer --- *
+ *
+ * Minimum size for a key is four bytes salt, four bytes zeroes, two bytes
+ * type, and two bytes length, making a total of twelve.
+ */
+
+ if (k->u.k.sz < 12)
+ goto fail_0;
+ sz = k->u.k.sz - 4;
+ p = xmalloc(k->u.k.sz);
+
+ /* --- Hash the passphrase --- */
+
+ {
+ rmd160_ctx h;
+ rmd160_init(&h);
+ rmd160_hash(&h, k->u.k.k, 4);
+ rmd160_hash(&h, buf, strlen(buf));
+ rmd160_done(&h, hash);
+ BURN(h);
+ BURN(buf);
+ }
+
+ /* --- Decrypt the key data --- */
+
+ {
+ blowfish_cbcctx c;
+ blowfish_cbcinit(&c, hash, sizeof(hash), 0);
+ blowfish_cbcdecrypt(&c, k->u.k.k + 4, p, sz);
+ BURN(hash);
+ BURN(c);
+ if (LOAD32(p) != 0) {
+ passphrase_cancel(tag);
+ goto fail_1;
+ }
+ }
+
+ /* --- Decode the key data into the destination buffer --- */
+
+ if (k == kt) {
+ key_destroy(k);
+ passphrase_cancel(tag);
+ }
+ if (key_decode(p + 4, sz - 4, kt))
+ goto fail_1;
+
+ /* --- Done --- */
+
+ free(p);
+ return (0);
+
+ /* --- Tidy up if things went wrong --- */
+
+fail_1:
+ free(p);
+fail_0:
+ return (-1);
+}
+
+/*----- That's all, folks -------------------------------------------------*/