chiark / gitweb /
Another error fix.
[tripe] / keymgmt.c
1 /* -*-c-*-
2  *
3  * $Id: keymgmt.c,v 1.3 2001/06/22 19:40:36 mdw Exp $
4  *
5  * Key loading and storing
6  *
7  * (c) 2001 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of Trivial IP Encryption (TrIPE).
13  *
14  * TrIPE is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  * 
19  * TrIPE 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 General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with TrIPE; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Revision history --------------------------------------------------* 
30  *
31  * $Log: keymgmt.c,v $
32  * Revision 1.3  2001/06/22 19:40:36  mdw
33  * Support expiry of other peers' public keys.
34  *
35  * Revision 1.2  2001/06/19 22:07:09  mdw
36  * Cosmetic fixes.
37  *
38  * Revision 1.1  2001/02/03 20:26:37  mdw
39  * Initial checkin.
40  *
41  */
42
43 /*----- Header files ------------------------------------------------------*/
44
45 #include "tripe.h"
46
47 /*----- Global variables --------------------------------------------------*/
48
49 mpmont mg;
50 dh_priv kpriv;
51
52 /*----- Static variables --------------------------------------------------*/
53
54 static key_file *kf_pub;
55 static const char *kr_priv, *kr_pub, *tag_priv;
56 static fwatch w_priv, w_pub;
57
58 /*----- Main code ---------------------------------------------------------*/
59
60 /* --- @keymoan@ --- *
61  *
62  * Arguments:   @const char *file@ = name of the file
63  *              @int line@ = line number in file
64  *              @const char *msg@ = error message
65  *              @void *p@ = argument pointer
66  *
67  * Returns:     ---
68  *
69  * Use:         Reports an error message about loading a key file.
70  */
71
72 static void keymoan(const char *file, int line, const char *msg, void *p)
73 {
74   a_warn("%s:%i: error: %s", file, line, msg);
75 }
76
77 /* --- @loadpriv@ --- *
78  *
79  * Arguments:   @dstr *d@ = string to write errors in
80  *              @dh_priv *dh@ = where to store the key
81  *
82  * Returns:     Zero if OK, nonzero on error.
83  *
84  * Use:         Loads the private key from its keyfile.
85  */
86
87 static int loadpriv(dstr *d, dh_priv *dh)
88 {
89   key_file kf;
90   key_packstruct kps[DH_PRIVFETCHSZ];
91   key_packdef *kp;
92   dh_priv mydh;
93   int rc = 0;
94   int e;
95
96   if (key_open(&kf, kr_priv, KOPEN_READ, keymoan, 0)) {
97     dstr_putf(d, "error reading private keyring `%s': %s",
98               kr_priv, strerror(errno));
99     rc = -1;
100   } else {
101     T( trace(T_KEYMGMT, "keymgmt: loaded private keyring `%s'", kr_priv); )
102     kp = key_fetchinit(dh_privfetch, kps, &mydh);
103     if ((e = key_fetchbyname(kp, &kf, tag_priv)) != 0) {
104       dstr_putf(d, "error loading private key `%s': %s",
105                 tag_priv, key_strerror(e));
106       rc = -1;
107     } else {
108       dh->dp.p = MP_COPY(mydh.dp.p);
109       dh->dp.q = MP_COPY(mydh.dp.q);
110       dh->dp.g = MP_COPY(mydh.dp.g);
111       dh->x = MP_COPY(mydh.x);
112       dh->y = MP_COPY(mydh.y);      
113       IF_TRACING(T_KEYMGMT, {
114         trace(T_KEYMGMT, "keymgmt: extracted private key `%s'", tag_priv);
115         IF_TRACING(T_CRYPTO, {
116           trace(T_CRYPTO, "crypto: p = %s", mpstr(kpriv.dp.p));
117           trace(T_CRYPTO, "crypto: q = %s", mpstr(kpriv.dp.q));
118           trace(T_CRYPTO, "crypto: g = %s", mpstr(kpriv.dp.g));
119           trace(T_CRYPTO, "crypto: x = %s", mpstr(kpriv.x));
120           trace(T_CRYPTO, "crypto: g^x = %s", mpstr(kpriv.y));
121         })
122       })
123     }
124     key_fetchdone(kp);
125     key_close(&kf);
126   }
127   return (rc);
128 }
129
130 /* --- @loadpub@ --- *
131  *
132  * Arguments:   @dstr *d@ = string to write errors to
133  *
134  * Returns:     Zero if OK, nonzero on error.
135  *
136  * Use:         Reloads the public keyring.
137  */
138
139 static int loadpub(dstr *d)
140 {
141   key_file *kf = CREATE(key_file);
142
143   if (key_open(kf, kr_pub, KOPEN_READ, keymoan, 0)) {
144     dstr_putf(d, "error reading public keyring `%s': %s",
145               kr_pub, strerror(errno));
146     DESTROY(kf);
147     return (-1);
148   }
149   kf_pub = kf;
150   T( trace(T_KEYMGMT, "keymgmt: loaded public keyring `%s'", kr_pub); )
151   return (0);
152 }
153
154 /* --- @km_interval@ --- *
155  *
156  * Arguments:   ---
157  *
158  * Returns:     Zero if OK, nonzero to force reloading of keys.
159  *
160  * Use:         Called on the interval timer to perform various useful jobs.
161  */
162
163 int km_interval(void)
164 {
165   dstr d = DSTR_INIT;
166   dh_priv dh;
167   key_file *kf;
168   int reload = 0;
169
170   /* --- Check the private key first --- */
171
172   if (fwatch_update(&w_priv, kr_priv)) {
173     T( trace(T_KEYMGMT, "keymgmt: private keyring updated: reloading..."); )
174     DRESET(&d);
175     if (loadpriv(&d, &dh))
176       a_warn("%s -- ignoring changes", d.buf);
177     else {
178       reload = 1;
179       mpmont_destroy(&mg);
180       dh_privfree(&kpriv);
181       kpriv = dh;
182       mpmont_create(&mg, kpriv.dp.p);
183     }
184   }
185
186   /* --- Now check the public keys --- */
187
188   if (fwatch_update(&w_pub, kr_pub)) {
189     T( trace(T_KEYMGMT, "keymgmt: public keyring updated: reloading..."); )
190     kf = kf_pub;
191     DRESET(&d);
192     if (loadpub(&d))
193       a_warn("%s -- ignoring changes", d.buf);
194     else {
195       reload = 1;
196       key_close(kf);
197       DESTROY(kf);
198     }
199   }
200
201   /* --- Done --- */
202
203   return (reload);
204 }
205
206 /* --- @km_init@ --- *
207  *
208  * Arguments:   @const char *priv@ = private keyring file
209  *              @const char *pub@ = public keyring file
210  *              @const char *tag@ = tag to load
211  *
212  * Returns:     ---
213  *
214  * Use:         Initializes, and loads the private key.
215  */
216
217 void km_init(const char *priv, const char *pub, const char *tag)
218 {
219   dstr d = DSTR_INIT;
220
221   kr_priv = priv;
222   kr_pub = pub;
223   tag_priv = tag;
224   fwatch_init(&w_priv, kr_priv);
225   fwatch_init(&w_pub, kr_pub);
226
227   DRESET(&d);
228   if (loadpriv(&d, &kpriv))
229     die(EXIT_FAILURE, "%s", d.buf);
230   mpmont_create(&mg, kpriv.dp.p);
231   if (loadpub(&d))
232     die(EXIT_FAILURE, "%s", d.buf);
233 }
234
235 /* --- @km_getpubkey@ --- *
236  *
237  * Arguments:   @const char *tag@ = public key tag to load
238  *              @dh_pub *kpub@ = where to put the public key
239  *              @time_t *t_exp@ = where to put the expiry time
240  *
241  * Returns:     Zero if OK, nonzero if it failed.
242  *
243  * Use:         Fetches a public key from the keyring.
244  */
245
246 int km_getpubkey(const char *tag, dh_pub *kpub, time_t *t_exp)
247 {
248   key_packstruct kps[DH_PUBFETCHSZ];
249   key_packdef *kp;
250   key *k;
251   dh_pub dp;
252   int e;
253
254   kp = key_fetchinit(dh_pubfetch, kps, &dp);
255   if ((k = key_bytag(kf_pub, tag)) == 0)
256     e = KERR_NOTFOUND;
257   else
258     e = key_fetch(kp, k);
259   key_fetchdone(kp);
260   if (e) {
261     a_warn("error loading public key `%s': %s", tag, key_strerror(e));
262     return (-1);
263   }
264   IF_TRACING(T_KEYMGMT, {
265     trace(T_KEYMGMT, "keymgmt: extracted public key `%s'", tag);
266     IF_TRACING(T_CRYPTO, {
267       trace(T_CRYPTO, "crypto: p = %s", mpstr(dp.dp.p));
268       trace(T_CRYPTO, "crypto: q = %s", mpstr(dp.dp.q));
269       trace(T_CRYPTO, "crypto: g = %s", mpstr(dp.dp.g));
270       trace(T_CRYPTO, "crypto: g^x = %s", mpstr(dp.y));
271     })
272   })
273   if (!mp_eq(dp.dp.p, kpriv.dp.p) ||
274       !mp_eq(dp.dp.q, kpriv.dp.q) ||
275       !mp_eq(dp.dp.g, kpriv.dp.g)) {
276     a_warn("public key `%s' has different group from private key", tag);
277     return (-1);
278   }
279   kpub->dp.p = MP_COPY(dp.dp.p);
280   kpub->dp.q = MP_COPY(dp.dp.q);
281   kpub->dp.g = MP_COPY(dp.dp.g);
282   kpub->y = MP_COPY(dp.y);
283   *t_exp = k->exp;
284   return (0);
285 }
286
287 /*----- That's all, folks -------------------------------------------------*/