X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/6f51228e8b99c2f0cbec5cb9d77925e0031eacd8..d11a0bf77a5230387d222ec727865a898767ff3e:/key-pass.c?ds=sidebyside diff --git a/key-pass.c b/key-pass.c new file mode 100644 index 00000000..024a6142 --- /dev/null +++ b/key-pass.c @@ -0,0 +1,210 @@ +/* -*-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 + +#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 -------------------------------------------------*/