Table for driving key data extraction.
[u/mdw/catacomb] / key-pass.c
1 /* -*-c-*-
2 *
3 * $Id: key-pass.c,v 1.1 1999/12/22 15:47:48 mdw Exp $
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 $
33 * Revision 1.1 1999/12/22 15:47:48 mdw
34 * Major key-management revision.
35 *
36 */
37
38 /*----- Header files ------------------------------------------------------*/
39
40 #include <mLib/dstr.h>
41
42 #include "key.h"
43 #include "paranoia.h"
44 #include "passphrase.h"
45 #include "rand.h"
46
47 #include "blowfish-cbc.h"
48 #include "rmd160.h"
49
50 /*----- Main code ---------------------------------------------------------*/
51
52 /* --- @key_plock@ --- *
53 *
54 * Arguments: @const char *tag@ = tag to use for passphrase
55 * @key_data *k@ = source key data block
56 * @key_data *kt@ = target key data block
57 *
58 * Returns: Zero if successful, nonzero if there was a problem.
59 *
60 * Use: Locks a key by encrypting it with a passphrase.
61 */
62
63 int key_plock(const char *tag, key_data *k, key_data *kt)
64 {
65 dstr d = DSTR_INIT;
66 octet hash[RMD160_HASHSZ];
67 char buf[256];
68
69 /* --- Sanity check --- */
70
71 assert(((void)"Key data is already encrypted",
72 (k->e & KF_ENCMASK) != KENC_ENCRYPT));
73
74 /* --- Read the passphrase --- */
75
76 if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf)))
77 return (-1);
78
79 /* --- Extract the key data --- *
80 *
81 * On the front, put four random bytes to act as a passphrase salt (which
82 * remain in the clear), and four zero bytes to be able to spot duff
83 * passphrases when unlocking.
84 */
85
86 DENSURE(&d, 8);
87 rand_getgood(RAND_GLOBAL, d.buf, 4);
88 memset(d.buf + 4, 0, 4);
89 d.len += 8;
90 key_encode(k, &d, 0);
91 if (k == kt)
92 key_destroy(k);
93
94 /* --- Hash the passphrase into a key --- */
95
96 {
97 rmd160_ctx h;
98 rmd160_init(&h);
99 rmd160_hash(&h, d.buf, 4);
100 rmd160_hash(&h, buf, strlen(buf));
101 rmd160_done(&h, hash);
102 BURN(h);
103 BURN(buf);
104 }
105
106 /* --- Encrypt the key data --- */
107
108 {
109 blowfish_cbcctx c;
110 blowfish_cbcinit(&c, hash, sizeof(hash), 0);
111 blowfish_cbcencrypt(&c, d.buf + 4, d.buf + 4, d.len - 4);
112 BURN(hash);
113 BURN(c);
114 }
115
116 /* --- Put the key data back in the key --- */
117
118 key_encrypted(kt, d.buf, d.len);
119 dstr_destroy(&d);
120 return (0);
121 }
122
123 /* --- @key_punlock@ --- *
124 *
125 * Arguments: @const char *tag@ = tag to use for passphrase
126 * @key_data *k@ = source key data block
127 * @key_data *kt@ = target key data block
128 *
129 * Returns: Zero if it worked, nonzero if it didn't.
130 *
131 * Use: Unlocks a passphrase-locked key.
132 */
133
134 int key_punlock(const char *tag, key_data *k, key_data *kt)
135 {
136 octet hash[RMD160_HASHSZ];
137 char buf[256];
138 octet *p;
139 size_t sz;
140
141 /* --- Sanity check --- */
142
143 assert(((void)"Key data isn't encrypted",
144 (k->e & KF_ENCMASK) == KENC_ENCRYPT));
145
146 /* --- Fetch the passphrase --- */
147
148 if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf)))
149 goto fail_0;
150
151 /* --- Allocate a destination buffer --- *
152 *
153 * Minimum size for a key is four bytes salt, four bytes zeroes, two bytes
154 * type, and two bytes length, making a total of twelve.
155 */
156
157 if (k->u.k.sz < 12)
158 goto fail_0;
159 sz = k->u.k.sz - 4;
160 p = xmalloc(k->u.k.sz);
161
162 /* --- Hash the passphrase --- */
163
164 {
165 rmd160_ctx h;
166 rmd160_init(&h);
167 rmd160_hash(&h, k->u.k.k, 4);
168 rmd160_hash(&h, buf, strlen(buf));
169 rmd160_done(&h, hash);
170 BURN(h);
171 BURN(buf);
172 }
173
174 /* --- Decrypt the key data --- */
175
176 {
177 blowfish_cbcctx c;
178 blowfish_cbcinit(&c, hash, sizeof(hash), 0);
179 blowfish_cbcdecrypt(&c, k->u.k.k + 4, p, sz);
180 BURN(hash);
181 BURN(c);
182 if (LOAD32(p) != 0) {
183 passphrase_cancel(tag);
184 goto fail_1;
185 }
186 }
187
188 /* --- Decode the key data into the destination buffer --- */
189
190 if (k == kt) {
191 key_destroy(k);
192 passphrase_cancel(tag);
193 }
194 if (key_decode(p + 4, sz - 4, kt))
195 goto fail_1;
196
197 /* --- Done --- */
198
199 free(p);
200 return (0);
201
202 /* --- Tidy up if things went wrong --- */
203
204 fail_1:
205 free(p);
206 fail_0:
207 return (-1);
208 }
209
210 /*----- That's all, folks -------------------------------------------------*/