/* -*-c-*-
*
- * $Id: key-pass.c,v 1.3 2004/03/27 00:04:19 mdw Exp $
+ * $Id$
*
* Encrypting keys with passphrases
*
* MA 02111-1307, USA.
*/
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: key-pass.c,v $
- * Revision 1.3 2004/03/27 00:04:19 mdw
- * INCOMPATIBLE CHANGE. Use proper authentication on encrypted keys.
- *
- * Revision 1.2 2000/06/17 11:26:35 mdw
- * `rand_getgood' is deprecated.
- *
- * Revision 1.1 1999/12/22 15:47:48 mdw
- * Major key-management revision.
- *
- */
-
/*----- Header files ------------------------------------------------------*/
#include <mLib/dstr.h>
* has been replaced incompatibly.
*/
-/* --- @key_plock@ --- *
+/* --- @key_lock@ --- *
*
- * Arguments: @const char *tag@ = tag to use for passphrase
+ * Arguments: @key_data *kt@ = destination block
* @key_data *k@ = source key data block
- * @key_data *kt@ = target key data block
+ * @const void *e@ = secret to encrypt key with
+ * @size_t esz@ = size of the secret
*
- * Returns: Zero if successful, nonzero if there was a problem.
+ * Returns: ---
*
- * Use: Locks a key by encrypting it with a passphrase.
+ * Use: Encrypts a key data block using a secret.
*/
-int key_plock(const char *tag, key_data *k, key_data *kt)
+void key_lock(key_data *kt, key_data *k, const void *e, size_t esz)
{
dstr d = DSTR_INIT;
octet b[RMD160_HASHSZ * 2];
octet *m;
size_t msz;
- char buf[256];
+ rmd160_mgfctx r;
+ blowfish_cbcctx c;
+ rmd160_mackey mk;
+ rmd160_macctx mc;
/* --- Sanity check --- */
m = (octet *)d.buf + RMD160_HASHSZ * 2;
msz = d.len - RMD160_HASHSZ * 2;
- /* --- Read the passphrase --- */
-
- if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf))) {
- dstr_destroy(&d);
- return (-1);
- }
-
/* --- Hash the passphrase to make a key --- */
- {
- rmd160_mgfctx r;
- rmd160_mgfkeybegin(&r);
- rmd160_mgfkeyadd(&r, d.buf, RMD160_HASHSZ);
- rmd160_mgfkeyadd(&r, buf, strlen(buf));
- rmd160_mgfencrypt(&r, 0, b, sizeof(b));
- BURN(r);
- BURN(buf);
- }
+ rmd160_mgfkeybegin(&r);
+ rmd160_mgfkeyadd(&r, d.buf, RMD160_HASHSZ);
+ rmd160_mgfkeyadd(&r, e, esz);
+ rmd160_mgfencrypt(&r, 0, b, sizeof(b));
+ BURN(r);
/* --- Encrypt the plaintext --- */
- {
- blowfish_cbcctx c;
- blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0);
- blowfish_cbcencrypt(&c, m, m, msz);
- BURN(c);
- }
+ blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0);
+ blowfish_cbcencrypt(&c, m, m, msz);
+ BURN(c);
/* --- MAC the ciphertext --- */
- {
- rmd160_mackey mk;
- rmd160_macctx mc;
- rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
- rmd160_macinit(&mc, &mk);
- rmd160_machash(&mc, m, msz);
- rmd160_macdone(&mc, d.buf + RMD160_HASHSZ);
- BURN(mk);
- BURN(mc);
- }
+ rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
+ rmd160_macinit(&mc, &mk);
+ rmd160_machash(&mc, m, msz);
+ rmd160_macdone(&mc, d.buf + RMD160_HASHSZ);
+ BURN(mk);
+ BURN(mc);
/* --- Done --- */
BURN(b);
key_encrypted(kt, d.buf, d.len);
dstr_destroy(&d);
- return (0);
}
-/* --- @key_punlock@ --- *
+/* --- @key_unlock@ --- *
*
- * Arguments: @const char *tag@ = tag to use for passphrase
+ * Arguments: @key_data *kt@ = target block
* @key_data *k@ = source key data block
- * @key_data *kt@ = target key data block
+ * @const void *e@ = secret to decrypt the block with
+ * @size_t esz@ = size of the secret
*
- * Returns: Zero if it worked, nonzero if it didn't.
+ * Returns: Zero for success, or a @KERR_@ error code.
*
- * Use: Unlocks a passphrase-locked key.
+ * Use: Unlocks a key using a secret.
*/
-int key_punlock(const char *tag, key_data *k, key_data *kt)
+int key_unlock(key_data *kt, key_data *k, const void *e, size_t esz)
{
octet b[RMD160_HASHSZ * 2];
- char buf[256];
- octet *p;
+ octet *p = 0;
+ int rc;
+ rmd160_mgfctx r;
+ blowfish_cbcctx c;
+ rmd160_mackey mk;
+ rmd160_macctx mc;
size_t sz;
/* --- Sanity check --- */
assert(((void)"Key data isn't encrypted",
(k->e & KF_ENCMASK) == KENC_ENCRYPT));
- /* --- Allocate a destination buffer --- */
+ /* --- Check the size --- */
if (k->u.k.sz < RMD160_HASHSZ * 2)
- return (-1);;
+ return (KERR_MALFORMED);
sz = k->u.k.sz - RMD160_HASHSZ * 2;
- p = xmalloc(k->u.k.sz);
- /* --- Fetch the passphrase --- */
+ /* --- Hash the passphrase to make a key --- */
- if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf)))
- goto fail;
+ rmd160_mgfkeybegin(&r);
+ rmd160_mgfkeyadd(&r, k->u.k.k, RMD160_HASHSZ);
+ rmd160_mgfkeyadd(&r, e, esz);
+ rmd160_mgfencrypt(&r, 0, b, sizeof(b));
+ BURN(r);
- /* --- Hash the passphrase to make a key --- */
+ /* --- Verify the MAC --- */
- {
- rmd160_mgfctx r;
- rmd160_mgfkeybegin(&r);
- rmd160_mgfkeyadd(&r, k->u.k.k, RMD160_HASHSZ);
- rmd160_mgfkeyadd(&r, buf, strlen(buf));
- rmd160_mgfencrypt(&r, 0, b, sizeof(b));
- BURN(r);
- BURN(buf);
+ rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
+ rmd160_macinit(&mc, &mk);
+ rmd160_machash(&mc, k->u.k.k + RMD160_HASHSZ * 2, sz);
+ rmd160_macdone(&mc, b + RMD160_HASHSZ);
+ if (memcmp(b + RMD160_HASHSZ, k->u.k.k + RMD160_HASHSZ,
+ RMD160_HASHSZ) != 0) {
+ rc = KERR_BADPASS;
+ goto fail;
}
+ BURN(mk);
+ BURN(mc);
- /* --- Decrypt the key data --- */
+ /* --- Allocate a destination buffer --- */
- {
- blowfish_cbcctx c;
- blowfish_cbcinit(&c, b, sizeof(b), 0);
- blowfish_cbcdecrypt(&c, k->u.k.k + RMD160_HASHSZ, p, sz);
- BURN(c);
- }
+ p = xmalloc(sz);
- /* --- Verify the MAC --- */
+ /* --- Decrypt the key data --- */
- {
- rmd160_mackey mk;
- rmd160_macctx mc;
- rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
- rmd160_macinit(&mc, &mk);
- rmd160_machash(&mc, p, sz);
- rmd160_macdone(&mc, b);
- if (memcmp(b, k->u.k.k + RMD160_HASHSZ, RMD160_HASHSZ) != 0) {
- passphrase_cancel(tag);
- goto fail;
- }
- BURN(mk);
- BURN(mc);
- }
+ blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0);
+ blowfish_cbcdecrypt(&c, k->u.k.k + RMD160_HASHSZ * 2, p, sz);
+ BURN(c);
/* --- Decode the key data into the destination buffer --- */
- if (k == kt) {
+ if (k == kt)
key_destroy(k);
- passphrase_cancel(tag);
- }
- if (key_decode(p, sz, kt))
+ if (key_decode(p, sz, kt)) {
+ rc = KERR_MALFORMED;
goto fail;
+ }
/* --- Done --- */
- free(p);
+ xfree(p);
return (0);
/* --- Tidy up if things went wrong --- */
fail:
BURN(b);
- free(p);
- return (-1);
+ xfree(p);
+ return (rc);
+}
+
+/* --- @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, a @KERR@ error code on failure.
+ *
+ * Use: Locks a key by encrypting it with a passphrase.
+ */
+
+int key_plock(const char *tag, key_data *k, key_data *kt)
+{
+ char buf[256];
+
+ if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf)))
+ return (KERR_IO);
+ key_lock(kt, k, buf, strlen(buf));
+ BURN(buf);
+ 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, a @KERR_@ error code on failure.
+ *
+ * Use: Unlocks a passphrase-locked key.
+ */
+
+int key_punlock(const char *tag, key_data *k, key_data *kt)
+{
+ char buf[256];
+ int rc;
+
+ if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf)))
+ return (KERR_IO);
+ rc = key_unlock(kt, k, buf, strlen(buf));
+ BURN(buf);
+ if (rc == KERR_BADPASS || k == kt)
+ passphrase_cancel(tag);
+ return (rc);
}
/*----- That's all, folks -------------------------------------------------*/