Major memory management overhaul. Added arena support. Use the secure
[u/mdw/catacomb] / key-pass.c
CommitLineData
d11a0bf7 1/* -*-c-*-
2 *
bbded534 3 * $Id: key-pass.c,v 1.2 2000/06/17 11:26:35 mdw Exp $
d11a0bf7 4 *
5 * Encrypting keys with passphrases
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: key-pass.c,v $
bbded534 33 * Revision 1.2 2000/06/17 11:26:35 mdw
34 * `rand_getgood' is deprecated.
35 *
d11a0bf7 36 * Revision 1.1 1999/12/22 15:47:48 mdw
37 * Major key-management revision.
38 *
39 */
40
41/*----- Header files ------------------------------------------------------*/
42
43#include <mLib/dstr.h>
44
45#include "key.h"
46#include "paranoia.h"
47#include "passphrase.h"
48#include "rand.h"
49
50#include "blowfish-cbc.h"
51#include "rmd160.h"
52
53/*----- Main code ---------------------------------------------------------*/
54
55/* --- @key_plock@ --- *
56 *
57 * Arguments: @const char *tag@ = tag to use for passphrase
58 * @key_data *k@ = source key data block
59 * @key_data *kt@ = target key data block
60 *
61 * Returns: Zero if successful, nonzero if there was a problem.
62 *
63 * Use: Locks a key by encrypting it with a passphrase.
64 */
65
66int key_plock(const char *tag, key_data *k, key_data *kt)
67{
68 dstr d = DSTR_INIT;
69 octet hash[RMD160_HASHSZ];
70 char buf[256];
71
72 /* --- Sanity check --- */
73
74 assert(((void)"Key data is already encrypted",
75 (k->e & KF_ENCMASK) != KENC_ENCRYPT));
76
77 /* --- Read the passphrase --- */
78
79 if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf)))
80 return (-1);
81
82 /* --- Extract the key data --- *
83 *
84 * On the front, put four random bytes to act as a passphrase salt (which
85 * remain in the clear), and four zero bytes to be able to spot duff
86 * passphrases when unlocking.
87 */
88
89 DENSURE(&d, 8);
bbded534 90 rand_get(RAND_GLOBAL, d.buf, 4);
d11a0bf7 91 memset(d.buf + 4, 0, 4);
92 d.len += 8;
93 key_encode(k, &d, 0);
94 if (k == kt)
95 key_destroy(k);
96
97 /* --- Hash the passphrase into a key --- */
98
99 {
100 rmd160_ctx h;
101 rmd160_init(&h);
102 rmd160_hash(&h, d.buf, 4);
103 rmd160_hash(&h, buf, strlen(buf));
104 rmd160_done(&h, hash);
105 BURN(h);
106 BURN(buf);
107 }
108
109 /* --- Encrypt the key data --- */
110
111 {
112 blowfish_cbcctx c;
113 blowfish_cbcinit(&c, hash, sizeof(hash), 0);
114 blowfish_cbcencrypt(&c, d.buf + 4, d.buf + 4, d.len - 4);
115 BURN(hash);
116 BURN(c);
117 }
118
119 /* --- Put the key data back in the key --- */
120
121 key_encrypted(kt, d.buf, d.len);
122 dstr_destroy(&d);
123 return (0);
124}
125
126/* --- @key_punlock@ --- *
127 *
128 * Arguments: @const char *tag@ = tag to use for passphrase
129 * @key_data *k@ = source key data block
130 * @key_data *kt@ = target key data block
131 *
132 * Returns: Zero if it worked, nonzero if it didn't.
133 *
134 * Use: Unlocks a passphrase-locked key.
135 */
136
137int key_punlock(const char *tag, key_data *k, key_data *kt)
138{
139 octet hash[RMD160_HASHSZ];
140 char buf[256];
141 octet *p;
142 size_t sz;
143
144 /* --- Sanity check --- */
145
146 assert(((void)"Key data isn't encrypted",
147 (k->e & KF_ENCMASK) == KENC_ENCRYPT));
148
149 /* --- Fetch the passphrase --- */
150
151 if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf)))
152 goto fail_0;
153
154 /* --- Allocate a destination buffer --- *
155 *
156 * Minimum size for a key is four bytes salt, four bytes zeroes, two bytes
157 * type, and two bytes length, making a total of twelve.
158 */
159
160 if (k->u.k.sz < 12)
161 goto fail_0;
162 sz = k->u.k.sz - 4;
163 p = xmalloc(k->u.k.sz);
164
165 /* --- Hash the passphrase --- */
166
167 {
168 rmd160_ctx h;
169 rmd160_init(&h);
170 rmd160_hash(&h, k->u.k.k, 4);
171 rmd160_hash(&h, buf, strlen(buf));
172 rmd160_done(&h, hash);
173 BURN(h);
174 BURN(buf);
175 }
176
177 /* --- Decrypt the key data --- */
178
179 {
180 blowfish_cbcctx c;
181 blowfish_cbcinit(&c, hash, sizeof(hash), 0);
182 blowfish_cbcdecrypt(&c, k->u.k.k + 4, p, sz);
183 BURN(hash);
184 BURN(c);
185 if (LOAD32(p) != 0) {
186 passphrase_cancel(tag);
187 goto fail_1;
188 }
189 }
190
191 /* --- Decode the key data into the destination buffer --- */
192
193 if (k == kt) {
194 key_destroy(k);
195 passphrase_cancel(tag);
196 }
197 if (key_decode(p + 4, sz - 4, kt))
198 goto fail_1;
199
200 /* --- Done --- */
201
202 free(p);
203 return (0);
204
205 /* --- Tidy up if things went wrong --- */
206
207fail_1:
208 free(p);
209fail_0:
210 return (-1);
211}
212
213/*----- That's all, folks -------------------------------------------------*/