X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/59b2b448afd977128c84bcea6b18adaf37d4be69..1d6d3b01cb40e0cfaeb816c87c513695aea0816a:/key-pass.c diff --git a/key-pass.c b/key-pass.c index 3785765..ab8e003 100644 --- a/key-pass.c +++ b/key-pass.c @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: key-pass.c,v 1.3 2004/03/27 00:04:19 mdw Exp $ + * $Id$ * * Encrypting keys with passphrases * * (c) 1999 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Catacomb. * @@ -15,32 +15,18 @@ * 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.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 @@ -68,27 +54,32 @@ * has been replaced incompatibly. */ -/* --- @key_plock@ --- * +/* --- @key_lock@ --- * * - * Arguments: @const char *tag@ = tag to use for passphrase - * @key_data *k@ = source key data block - * @key_data *kt@ = target key data block + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @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 --- */ + if (k) key_incref(k); else k = *kt; assert(((void)"Key data is already encrypted", (k->e & KF_ENCMASK) != KENC_ENCRYPT)); @@ -98,153 +89,176 @@ int key_plock(const char *tag, key_data *k, key_data *kt) rand_get(RAND_GLOBAL, d.buf, RMD160_HASHSZ); d.len += RMD160_HASHSZ * 2; key_encode(k, &d, 0); - if (k == kt) - key_destroy(k); 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); + *kt = key_newencrypted(0, d.buf, d.len); + key_drop(k); dstr_destroy(&d); - return (0); } -/* --- @key_punlock@ --- * +/* --- @key_unlock@ --- * * - * Arguments: @const char *tag@ = tag to use for passphrase - * @key_data *k@ = source key data block - * @key_data *kt@ = target key data block + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @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; + int drop = 0; + key_data *kd; + rmd160_mgfctx r; + blowfish_cbcctx c; + rmd160_mackey mk; + rmd160_macctx mc; size_t sz; /* --- Sanity check --- */ + if (!k) { k = *kt; drop = 1; } 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) { - key_destroy(k); - passphrase_cancel(tag); - } - if (key_decode(p, sz, kt)) + if ((kd = key_decode(p, sz)) == 0) { + rc = KERR_MALFORMED; goto fail; + } + *kt = kd; /* --- Done --- */ - free(p); + xfree(p); + if (drop) key_drop(k); return (0); /* --- Tidy up if things went wrong --- */ fail: BURN(b); - free(p); - return (-1); + xfree(p); + return (rc); +} + +/* --- @key_plock@ --- * + * + * Arguments: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const char *tag@ = tag to use for passphrase + * + * Returns: Zero if successful, a @KERR@ error code on failure. + * + * Use: Locks a key by encrypting it with a passphrase. + */ + +int key_plock(key_data **kt, key_data *k, const char *tag) +{ + 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: @key_data **kt@ = where to store the destination pointer + * @key_data *k@ = source key data block or null to use @*kt@ + * @const char *tag@ = tag to use for passphrase + * + * Returns: Zero if it worked, a @KERR_@ error code on failure. + * + * Use: Unlocks a passphrase-locked key. + */ + +int key_punlock(key_data **kt, key_data *k, const char *tag) +{ + 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) + passphrase_cancel(tag); + return (rc); } /*----- That's all, folks -------------------------------------------------*/