chiark / gitweb /
Change ERR response to FAIL for consistency with other programs.
[tripe] / keymgmt.c
1 /* -*-c-*-
2  *
3  * $Id: keymgmt.c,v 1.1 2001/02/03 20:26:37 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.1  2001/02/03 20:26:37  mdw
33  * Initial checkin.
34  *
35  */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include "tripe.h"
40
41 /*----- Global variables --------------------------------------------------*/
42
43 mpmont mg;
44 dh_priv kpriv;
45
46 /*----- Static variables --------------------------------------------------*/
47
48 static key_file *kf_pub;
49 static const char *kr_priv, *kr_pub, *tag_priv;
50 static fwatch w_priv, w_pub;
51
52 /*----- Main code ---------------------------------------------------------*/
53
54 /* --- @keymoan@ --- *
55  *
56  * Arguments:   @@const char *file@ = name of the file
57  *              @int line@ = line number in file
58  *              @const char *msg@ = error message
59  *              @void *p@ = argument pointer
60  *
61  * Returns:     ---
62  *
63  * Use:         Reports an error message about loading a key file.
64  */
65
66 static void keymoan(const char *file, int line, const char *msg, void *p)
67 {
68   a_warn("%s:%i: error: %s", file, line, msg);
69 }
70
71 /* --- @loadpriv@ --- *
72  *
73  * Arguments:   @dstr *d@ = string to write errors in
74  *              @dh_priv *dh@ = where to store the key
75  *
76  * Returns:     Zero if OK, nonzero on error.
77  *
78  * Use:         Loads the private key from its keyfile.
79  */
80
81 static int loadpriv(dstr *d, dh_priv *dh)
82 {
83   key_file kf;
84   key_packstruct kps[DH_PRIVFETCHSZ];
85   key_packdef *kp;
86   dh_priv mydh;
87   int rc = 0;
88   int e;
89
90   if (key_open(&kf, kr_priv, KOPEN_READ, keymoan, 0)) {
91     dstr_putf(d, "error reading private keyring `%s': %s",
92               kr_priv, strerror(errno));
93     rc = -1;
94   } else {
95     T( trace(T_KEYMGMT, "keymgmt: loaded private keyring `%s'", kr_priv); )
96     kp = key_fetchinit(dh_privfetch, kps, &mydh);
97     if ((e = key_fetchbyname(kp, &kf, tag_priv)) != 0) {
98       dstr_putf(d, "error loading private key `%s': %s",
99                 tag_priv, key_strerror(e));
100       rc = -1;
101     } else {
102       dh->dp.p = MP_COPY(mydh.dp.p);
103       dh->dp.q = MP_COPY(mydh.dp.q);
104       dh->dp.g = MP_COPY(mydh.dp.g);
105       dh->x = MP_COPY(mydh.x);
106       dh->y = MP_COPY(mydh.y);      
107       IF_TRACING(T_KEYMGMT, {
108         trace(T_KEYMGMT, "keymgmt: extracted private key `%s'", tag_priv);
109         IF_TRACING(T_CRYPTO, {
110           trace(T_CRYPTO, "crypto: p = %s", mpstr(kpriv.dp.p));
111           trace(T_CRYPTO, "crypto: q = %s", mpstr(kpriv.dp.q));
112           trace(T_CRYPTO, "crypto: g = %s", mpstr(kpriv.dp.g));
113           trace(T_CRYPTO, "crypto: x = %s", mpstr(kpriv.x));
114           trace(T_CRYPTO, "crypto: g^x = %s", mpstr(kpriv.y));
115         })
116       })
117     }
118     key_fetchdone(kp);
119     key_close(&kf);
120   }
121   return (rc);
122 }
123
124 /* --- @loadpub@ --- *
125  *
126  * Arguments:   @dstr *d@ = string to write errors to
127  *
128  * Returns:     Zero if OK, nonzero on error.
129  *
130  * Use:         Reloads the public keyring.
131  */
132
133 static int loadpub(dstr *d)
134 {
135   key_file *kf = CREATE(key_file);
136
137   if (key_open(kf, kr_pub, KOPEN_READ, keymoan, 0)) {
138     dstr_putf(d, "error reading public keyring `%s': %s",
139               kr_pub, strerror(errno));
140     DESTROY(kf);
141     return (-1);
142   }
143   kf_pub = kf;
144   T( trace(T_KEYMGMT, "keymgmt: loaded public keyring `%s'", kr_pub); )
145   return (0);
146 }
147
148 /* --- @km_interval@ --- *
149  *
150  * Arguments:   ---
151  *
152  * Returns:     Zero if OK, nonzero to force reloading of keys.
153  *
154  * Use:         Called on the interval timer to perform various useful jobs.
155  */
156
157 int km_interval(void)
158 {
159   dstr d = DSTR_INIT;
160   dh_priv dh;
161   key_file *kf;
162   int reload = 0;
163
164   /* --- Check the private key first --- */
165
166   if (fwatch_update(&w_priv, kr_priv)) {
167     T( trace(T_KEYMGMT, "keymgmt: private keyring updated: reloading..."); )
168     DRESET(&d);
169     if (loadpriv(&d, &dh))
170       a_warn("%s -- ignoring changes", d.buf);
171     else {
172       reload = 1;
173       mpmont_destroy(&mg);
174       dh_privfree(&kpriv);
175       kpriv = dh;
176       mpmont_create(&mg, kpriv.dp.p);
177     }
178   }
179
180   /* --- Now check the public keys --- */
181
182   if (fwatch_update(&w_pub, kr_pub)) {
183     T( trace(T_KEYMGMT, "keymgmt: public keyring updated: reloading..."); )
184     kf = kf_pub;
185     DRESET(&d);
186     if (loadpub(&d))
187       a_warn("%s -- ignoring changes", d.buf);
188     else {
189       reload = 1;
190       key_close(kf);
191       DESTROY(kf);
192     }
193   }
194
195   /* --- Done --- */
196
197   return (reload);
198 }
199
200 /* --- @km_init@ --- *
201  *
202  * Arguments:   @const char *priv@ = private keyring file
203  *              @const char *pub@ = public keyring file
204  *              @const char *tag@ = tag to load
205  *
206  * Returns:     ---
207  *
208  * Use:         Initializes, and loads the private key.
209  */
210
211 void km_init(const char *priv, const char *pub, const char *tag)
212 {
213   dstr d = DSTR_INIT;
214
215   kr_priv = priv;
216   kr_pub = pub;
217   tag_priv = tag;
218   fwatch_init(&w_priv, kr_priv);
219   fwatch_init(&w_pub, kr_pub);
220
221   DRESET(&d);
222   if (loadpriv(&d, &kpriv))
223     die(EXIT_FAILURE, "%s", d.buf);
224   mpmont_create(&mg, kpriv.dp.p);
225   if (loadpub(&d))
226     die(EXIT_FAILURE, "%s", d.buf);
227 }
228
229 /* --- @km_getpubkey@ --- *
230  *
231  * Arguments:   @const char *tag@ = public key tag to load
232  *              @dh_pub *kpub@ = where to put the public key
233  *
234  * Returns:     Zero if OK, nonzero if it failed.
235  *
236  * Use:         Fetches a public key from the keyring.
237  */
238
239 int km_getpubkey(const char *tag, dh_pub *kpub)
240 {
241   key_packstruct kps[DH_PUBFETCHSZ];
242   key_packdef *kp;
243   dh_pub dp;
244   int e;
245
246   kp = key_fetchinit(dh_pubfetch, kps, &dp);
247   e = key_fetchbyname(kp, kf_pub, tag);
248   key_fetchdone(kp);
249   if (e) {
250     a_warn("error loading public key `%s': %s", tag, key_strerror(e));
251     return (-1);
252   }
253   IF_TRACING(T_KEYMGMT, {
254     trace(T_KEYMGMT, "keymgmt: extracted public key `%s'", tag);
255     IF_TRACING(T_CRYPTO, {
256       trace(T_CRYPTO, "crypto: p = %s", mpstr(dp.dp.p));
257       trace(T_CRYPTO, "crypto: q = %s", mpstr(dp.dp.q));
258       trace(T_CRYPTO, "crypto: g = %s", mpstr(dp.dp.g));
259       trace(T_CRYPTO, "crypto: g^x = %s", mpstr(dp.y));
260     })
261   })
262   if (!mp_eq(dp.dp.p, kpriv.dp.p) ||
263       !mp_eq(dp.dp.q, kpriv.dp.q) ||
264       !mp_eq(dp.dp.g, kpriv.dp.g)) {
265     a_warn("public key `%s' has different group from private key", tag);
266     return (-1);
267   }
268   kpub->dp.p = MP_COPY(dp.dp.p);
269   kpub->dp.q = MP_COPY(dp.dp.q);
270   kpub->dp.g = MP_COPY(dp.dp.g);
271   kpub->y = MP_COPY(dp.y);
272   return (0);
273 }
274
275 /*----- That's all, folks -------------------------------------------------*/