/src/tor/src/feature/keymgt/loadkey.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* Copyright (c) 2001 Matej Pfajfar.  | 
2  |  |  * Copyright (c) 2001-2004, Roger Dingledine.  | 
3  |  |  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.  | 
4  |  |  * Copyright (c) 2007-2021, The Tor Project, Inc. */  | 
5  |  | /* See LICENSE for licensing information */  | 
6  |  |  | 
7  |  | /**  | 
8  |  |  * \file loadkey.c  | 
9  |  |  * \brief Read keys from disk, creating as needed  | 
10  |  |  *  | 
11  |  |  * This code is shared by relays and onion services, which both need  | 
12  |  |  * this functionality.  | 
13  |  |  **/  | 
14  |  |  | 
15  |  | #include "core/or/or.h"  | 
16  |  | #include "app/config/config.h"  | 
17  |  | #include "app/main/main.h"  | 
18  |  | #include "feature/keymgt/loadkey.h"  | 
19  |  | #include "feature/nodelist/torcert.h"  | 
20  |  |  | 
21  |  | #include "lib/crypt_ops/crypto_pwbox.h"  | 
22  |  | #include "lib/crypt_ops/crypto_util.h"  | 
23  |  | #include "lib/term/getpass.h"  | 
24  |  | #include "lib/crypt_ops/crypto_format.h"  | 
25  |  |  | 
26  | 0  | #define ENC_KEY_HEADER "Boxed Ed25519 key"  | 
27  | 0  | #define ENC_KEY_TAG "master"  | 
28  |  |  | 
29  |  | #ifdef HAVE_UNISTD_H  | 
30  |  | #include <unistd.h>  | 
31  |  | #endif  | 
32  |  |  | 
33  |  | /** Try to read an RSA key from <b>fname</b>.  If <b>fname</b> doesn't exist  | 
34  |  |  * and <b>generate</b> is true, create a new RSA key and save it in  | 
35  |  |  * <b>fname</b>.  Return the read/created key, or NULL on error.  Log all  | 
36  |  |  * errors at level <b>severity</b>. If <b>created_out</b> is non-NULL and a  | 
37  |  |  * new key was created, set *<b>created_out</b> to true.  | 
38  |  |  */  | 
39  |  | crypto_pk_t *  | 
40  |  | init_key_from_file(const char *fname, int generate, int severity,  | 
41  |  |                    bool *created_out)  | 
42  | 0  | { | 
43  | 0  |   crypto_pk_t *prkey = NULL;  | 
44  |  | 
  | 
45  | 0  |   if (created_out) { | 
46  | 0  |     *created_out = false;  | 
47  | 0  |   }  | 
48  |  | 
  | 
49  | 0  |   if (!(prkey = crypto_pk_new())) { | 
50  | 0  |     tor_log(severity, LD_GENERAL,"Error constructing key");  | 
51  | 0  |     goto error;  | 
52  | 0  |   }  | 
53  |  |  | 
54  | 0  |   switch (file_status(fname)) { | 
55  | 0  |     case FN_DIR:  | 
56  | 0  |     case FN_ERROR:  | 
57  | 0  |       tor_log(severity, LD_FS,"Can't read key from \"%s\"", fname);  | 
58  | 0  |       goto error;  | 
59  |  |     /* treat empty key files as if the file doesn't exist, and,  | 
60  |  |      * if generate is set, replace the empty file in  | 
61  |  |      * crypto_pk_write_private_key_to_filename() */  | 
62  | 0  |     case FN_NOENT:  | 
63  | 0  |     case FN_EMPTY:  | 
64  | 0  |       if (generate) { | 
65  | 0  |         if (!have_lockfile()) { | 
66  | 0  |           if (try_locking(get_options(), 0)<0) { | 
67  |  |             /* Make sure that --list-fingerprint only creates new keys  | 
68  |  |              * if there is no possibility for a deadlock. */  | 
69  | 0  |             tor_log(severity, LD_FS, "Another Tor process has locked \"%s\". "  | 
70  | 0  |                     "Not writing any new keys.", fname);  | 
71  |  |             /*XXXX The 'other process' might make a key in a second or two;  | 
72  |  |              * maybe we should wait for it. */  | 
73  | 0  |             goto error;  | 
74  | 0  |           }  | 
75  | 0  |         }  | 
76  | 0  |         log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",  | 
77  | 0  |                  fname);  | 
78  | 0  |         if (crypto_pk_generate_key(prkey)) { | 
79  | 0  |           tor_log(severity, LD_GENERAL,"Error generating onion key");  | 
80  | 0  |           goto error;  | 
81  | 0  |         }  | 
82  | 0  |         if (! crypto_pk_is_valid_private_key(prkey)) { | 
83  | 0  |           tor_log(severity, LD_GENERAL,"Generated key seems invalid");  | 
84  | 0  |           goto error;  | 
85  | 0  |         }  | 
86  | 0  |         log_info(LD_GENERAL, "Generated key seems valid");  | 
87  | 0  |         if (created_out) { | 
88  | 0  |           *created_out = true;  | 
89  | 0  |         }  | 
90  | 0  |         if (crypto_pk_write_private_key_to_filename(prkey, fname)) { | 
91  | 0  |           tor_log(severity, LD_FS,  | 
92  | 0  |               "Couldn't write generated key to \"%s\".", fname);  | 
93  | 0  |           goto error;  | 
94  | 0  |         }  | 
95  | 0  |       } else { | 
96  | 0  |         tor_log(severity, LD_GENERAL, "No key found in \"%s\"", fname);  | 
97  | 0  |         goto error;  | 
98  | 0  |       }  | 
99  | 0  |       return prkey;  | 
100  | 0  |     case FN_FILE:  | 
101  | 0  |       if (crypto_pk_read_private_key_from_filename(prkey, fname)) { | 
102  | 0  |         tor_log(severity, LD_GENERAL,"Error loading private key.");  | 
103  | 0  |         goto error;  | 
104  | 0  |       }  | 
105  | 0  |       return prkey;  | 
106  | 0  |     default:  | 
107  | 0  |       tor_assert(0);  | 
108  | 0  |   }  | 
109  |  |  | 
110  | 0  |  error:  | 
111  | 0  |   if (prkey)  | 
112  | 0  |     crypto_pk_free(prkey);  | 
113  | 0  |   return NULL;  | 
114  | 0  | }  | 
115  |  |  | 
116  |  | /* DOCDOC */  | 
117  |  | static ssize_t  | 
118  |  | do_getpass(const char *prompt, char *buf, size_t buflen,  | 
119  |  |            int twice, const or_options_t *options)  | 
120  | 0  | { | 
121  | 0  |   if (options->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) { | 
122  | 0  |     tor_assert(buflen);  | 
123  | 0  |     buf[0] = 0;  | 
124  | 0  |     return 0;  | 
125  | 0  |   }  | 
126  |  |  | 
127  | 0  |   char *prompt2 = NULL;  | 
128  | 0  |   char *buf2 = NULL;  | 
129  | 0  |   int fd = -1;  | 
130  | 0  |   ssize_t length = -1;  | 
131  |  | 
  | 
132  | 0  |   if (options->use_keygen_passphrase_fd) { | 
133  | 0  |     twice = 0;  | 
134  | 0  |     fd = options->keygen_passphrase_fd;  | 
135  | 0  |     length = read_all_from_fd(fd, buf, buflen-1);  | 
136  | 0  |     if (length >= 0)  | 
137  | 0  |       buf[length] = 0;  | 
138  | 0  |     goto done_reading;  | 
139  | 0  |   }  | 
140  |  |  | 
141  | 0  |   if (twice) { | 
142  | 0  |     const char msg[] = "One more time:";  | 
143  | 0  |     size_t p2len = strlen(prompt) + 1;  | 
144  | 0  |     if (p2len < sizeof(msg))  | 
145  | 0  |       p2len = sizeof(msg);  | 
146  | 0  |     prompt2 = tor_malloc(p2len);  | 
147  | 0  |     memset(prompt2, ' ', p2len);  | 
148  | 0  |     memcpy(prompt2 + p2len - sizeof(msg), msg, sizeof(msg));  | 
149  |  | 
  | 
150  | 0  |     buf2 = tor_malloc_zero(buflen);  | 
151  | 0  |   }  | 
152  |  | 
  | 
153  | 0  |   while (1) { | 
154  | 0  |     length = tor_getpass(prompt, buf, buflen);  | 
155  | 0  |     if (length < 0)  | 
156  | 0  |       goto done_reading;  | 
157  |  |  | 
158  | 0  |     if (! twice)  | 
159  | 0  |       break;  | 
160  |  |  | 
161  | 0  |     ssize_t length2 = tor_getpass(prompt2, buf2, buflen);  | 
162  |  | 
  | 
163  | 0  |     if (length != length2 || tor_memneq(buf, buf2, length)) { | 
164  | 0  |       fprintf(stderr, "That didn't match.\n");  | 
165  | 0  |     } else { | 
166  | 0  |       break;  | 
167  | 0  |     }  | 
168  | 0  |   }  | 
169  |  |  | 
170  | 0  |  done_reading:  | 
171  | 0  |   if (twice) { | 
172  | 0  |     tor_free(prompt2);  | 
173  | 0  |     memwipe(buf2, 0, buflen);  | 
174  | 0  |     tor_free(buf2);  | 
175  | 0  |   }  | 
176  |  | 
  | 
177  | 0  |   if (options->keygen_force_passphrase == FORCE_PASSPHRASE_ON && length == 0)  | 
178  | 0  |     return -1;  | 
179  |  |  | 
180  | 0  |   return length;  | 
181  | 0  | }  | 
182  |  |  | 
183  |  | /* DOCDOC */  | 
184  |  | int  | 
185  |  | read_encrypted_secret_key(ed25519_secret_key_t *out,  | 
186  |  |                           const char *fname)  | 
187  | 0  | { | 
188  | 0  |   int r = -1;  | 
189  | 0  |   uint8_t *secret = NULL;  | 
190  | 0  |   size_t secret_len = 0;  | 
191  | 0  |   char pwbuf[256];  | 
192  | 0  |   uint8_t encrypted_key[256];  | 
193  | 0  |   char *tag = NULL;  | 
194  | 0  |   int saved_errno = 0;  | 
195  |  | 
  | 
196  | 0  |   ssize_t encrypted_len = crypto_read_tagged_contents_from_file(fname,  | 
197  | 0  |                                           ENC_KEY_HEADER,  | 
198  | 0  |                                           &tag,  | 
199  | 0  |                                           encrypted_key,  | 
200  | 0  |                                           sizeof(encrypted_key));  | 
201  | 0  |   if (encrypted_len < 0) { | 
202  | 0  |     saved_errno = errno;  | 
203  | 0  |     log_info(LD_OR, "%s is missing", fname);  | 
204  | 0  |     r = 0;  | 
205  | 0  |     goto done;  | 
206  | 0  |   }  | 
207  | 0  |   if (strcmp(tag, ENC_KEY_TAG)) { | 
208  | 0  |     saved_errno = EINVAL;  | 
209  | 0  |     goto done;  | 
210  | 0  |   }  | 
211  |  |  | 
212  | 0  |   while (1) { | 
213  | 0  |     ssize_t pwlen =  | 
214  | 0  |       do_getpass("Enter passphrase for master key:", pwbuf, sizeof(pwbuf), 0, | 
215  | 0  |                  get_options());  | 
216  | 0  |     if (pwlen < 0) { | 
217  | 0  |       saved_errno = EINVAL;  | 
218  | 0  |       goto done;  | 
219  | 0  |     }  | 
220  | 0  |     const int r_unbox = crypto_unpwbox(&secret, &secret_len,  | 
221  | 0  |                                        encrypted_key, encrypted_len,  | 
222  | 0  |                                        pwbuf, pwlen);  | 
223  | 0  |     if (r_unbox == UNPWBOX_CORRUPTED) { | 
224  | 0  |       log_err(LD_OR, "%s is corrupted.", fname);  | 
225  | 0  |       saved_errno = EINVAL;  | 
226  | 0  |       goto done;  | 
227  | 0  |     } else if (r_unbox == UNPWBOX_OKAY) { | 
228  | 0  |       break;  | 
229  | 0  |     }  | 
230  |  |  | 
231  |  |     /* Otherwise, passphrase is bad, so try again till user does ctrl-c or gets  | 
232  |  |      * it right. */  | 
233  | 0  |   }  | 
234  |  |  | 
235  | 0  |   if (secret_len != ED25519_SECKEY_LEN) { | 
236  | 0  |     log_err(LD_OR, "%s is corrupted.", fname);  | 
237  | 0  |     saved_errno = EINVAL;  | 
238  | 0  |     goto done;  | 
239  | 0  |   }  | 
240  | 0  |   memcpy(out->seckey, secret, ED25519_SECKEY_LEN);  | 
241  | 0  |   r = 1;  | 
242  |  | 
  | 
243  | 0  |  done:  | 
244  | 0  |   memwipe(encrypted_key, 0, sizeof(encrypted_key));  | 
245  | 0  |   memwipe(pwbuf, 0, sizeof(pwbuf));  | 
246  | 0  |   tor_free(tag);  | 
247  | 0  |   if (secret) { | 
248  | 0  |     memwipe(secret, 0, secret_len);  | 
249  | 0  |     tor_free(secret);  | 
250  | 0  |   }  | 
251  | 0  |   if (saved_errno)  | 
252  | 0  |     errno = saved_errno;  | 
253  | 0  |   return r;  | 
254  | 0  | }  | 
255  |  |  | 
256  |  | /* DOCDOC */  | 
257  |  | int  | 
258  |  | write_encrypted_secret_key(const ed25519_secret_key_t *key,  | 
259  |  |                            const char *fname)  | 
260  | 0  | { | 
261  | 0  |   int r = -1;  | 
262  | 0  |   char pwbuf0[256];  | 
263  | 0  |   uint8_t *encrypted_key = NULL;  | 
264  | 0  |   size_t encrypted_len = 0;  | 
265  |  | 
  | 
266  | 0  |   if (do_getpass("Enter new passphrase:", pwbuf0, sizeof(pwbuf0), 1, | 
267  | 0  |                  get_options()) < 0) { | 
268  | 0  |     log_warn(LD_OR, "NO/failed passphrase");  | 
269  | 0  |     return -1;  | 
270  | 0  |   }  | 
271  |  |  | 
272  | 0  |   if (strlen(pwbuf0) == 0) { | 
273  | 0  |     if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_ON)  | 
274  | 0  |       return -1;  | 
275  | 0  |     else  | 
276  | 0  |       return 0;  | 
277  | 0  |   }  | 
278  |  |  | 
279  | 0  |   if (crypto_pwbox(&encrypted_key, &encrypted_len,  | 
280  | 0  |                    key->seckey, sizeof(key->seckey),  | 
281  | 0  |                    pwbuf0, strlen(pwbuf0),  0) < 0) { | 
282  | 0  |     log_warn(LD_OR, "crypto_pwbox failed!?");  | 
283  | 0  |     goto done;  | 
284  | 0  |   }  | 
285  | 0  |   if (crypto_write_tagged_contents_to_file(fname,  | 
286  | 0  |                                            ENC_KEY_HEADER,  | 
287  | 0  |                                            ENC_KEY_TAG,  | 
288  | 0  |                                            encrypted_key, encrypted_len) < 0)  | 
289  | 0  |     goto done;  | 
290  | 0  |   r = 1;  | 
291  | 0  |  done:  | 
292  | 0  |   if (encrypted_key) { | 
293  | 0  |     memwipe(encrypted_key, 0, encrypted_len);  | 
294  | 0  |     tor_free(encrypted_key);  | 
295  | 0  |   }  | 
296  | 0  |   memwipe(pwbuf0, 0, sizeof(pwbuf0));  | 
297  | 0  |   return r;  | 
298  | 0  | }  | 
299  |  |  | 
300  |  | /* DOCDOC */  | 
301  |  | static int  | 
302  |  | write_secret_key(const ed25519_secret_key_t *key, int encrypted,  | 
303  |  |                  const char *fname,  | 
304  |  |                  const char *fname_tag,  | 
305  |  |                  const char *encrypted_fname)  | 
306  | 0  | { | 
307  | 0  |   if (encrypted) { | 
308  | 0  |     int r = write_encrypted_secret_key(key, encrypted_fname);  | 
309  | 0  |     if (r == 1) { | 
310  |  |       /* Success! */  | 
311  |  |  | 
312  |  |       /* Try to unlink the unencrypted key, if any existed before */  | 
313  | 0  |       if (strcmp(fname, encrypted_fname))  | 
314  | 0  |         unlink(fname);  | 
315  | 0  |       return r;  | 
316  | 0  |     } else if (r != 0) { | 
317  |  |       /* Unrecoverable failure! */  | 
318  | 0  |       return r;  | 
319  | 0  |     }  | 
320  |  |  | 
321  | 0  |     fprintf(stderr, "Not encrypting the secret key.\n");  | 
322  | 0  |   }  | 
323  | 0  |   return ed25519_seckey_write_to_file(key, fname, fname_tag);  | 
324  | 0  | }  | 
325  |  |  | 
326  |  | /**  | 
327  |  |  * Read an ed25519 key and associated certificates from files beginning with  | 
328  |  |  * <b>fname</b>, with certificate type <b>cert_type</b>.  On failure, return  | 
329  |  |  * NULL; on success return the keypair.  | 
330  |  |  *  | 
331  |  |  * The <b>options</b> is used to look at the change_key_passphrase value when  | 
332  |  |  * writing to disk a secret key. It is safe to be NULL even in that case.  | 
333  |  |  *  | 
334  |  |  * If INIT_ED_KEY_CREATE is set in <b>flags</b>, then create the key (and  | 
335  |  |  * certificate if requested) if it doesn't exist, and save it to disk.  | 
336  |  |  *  | 
337  |  |  * If INIT_ED_KEY_NEEDCERT is set in <b>flags</b>, load/create a certificate  | 
338  |  |  * too and store it in *<b>cert_out</b>.  Fail if the cert can't be  | 
339  |  |  * found/created.  To create a certificate, <b>signing_key</b> must be set to  | 
340  |  |  * the key that should sign it; <b>now</b> to the current time, and  | 
341  |  |  * <b>lifetime</b> to the lifetime of the key.  | 
342  |  |  *  | 
343  |  |  * If INIT_ED_KEY_REPLACE is set in <b>flags</b>, then create and save new key  | 
344  |  |  * whether we can read the old one or not.  | 
345  |  |  *  | 
346  |  |  * If INIT_ED_KEY_EXTRA_STRONG is set in <b>flags</b>, set the extra_strong  | 
347  |  |  * flag when creating the secret key.  | 
348  |  |  *  | 
349  |  |  * If INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT is set in <b>flags</b>, and  | 
350  |  |  * we create a new certificate, create it with the signing key embedded.  | 
351  |  |  *  | 
352  |  |  * If INIT_ED_KEY_SPLIT is set in <b>flags</b>, and we create a new key,  | 
353  |  |  * store the public key in a separate file from the secret key.  | 
354  |  |  *  | 
355  |  |  * If INIT_ED_KEY_MISSING_SECRET_OK is set in <b>flags</b>, and we find a  | 
356  |  |  * public key file but no secret key file, return successfully anyway.  | 
357  |  |  *  | 
358  |  |  * If INIT_ED_KEY_OMIT_SECRET is set in <b>flags</b>, do not try to load a  | 
359  |  |  * secret key unless no public key is found.  Do not return a secret key. (but  | 
360  |  |  * create and save one if needed).  | 
361  |  |  *  | 
362  |  |  * If INIT_ED_KEY_TRY_ENCRYPTED is set, we look for an encrypted secret key  | 
363  |  |  * and consider encrypting any new secret key.  | 
364  |  |  *  | 
365  |  |  * If INIT_ED_KEY_NO_REPAIR is set, and there is any issue loading the keys  | 
366  |  |  * from disk _other than their absence_ (full or partial), we do not try to  | 
367  |  |  * replace them.  | 
368  |  |  *  | 
369  |  |  * If INIT_ED_KEY_SUGGEST_KEYGEN is set, have log messages about failures  | 
370  |  |  * refer to the --keygen option.  | 
371  |  |  *  | 
372  |  |  * If INIT_ED_KEY_EXPLICIT_FNAME is set, use the provided file name for the  | 
373  |  |  * secret key file, encrypted or not.  | 
374  |  |  *  | 
375  |  |  * If INIT_ED_KEY_OFFLINE_SECRET is set, we won't try to load the master  | 
376  |  |  * secret key and we log a message at <b>severity</b> that we've done so.  | 
377  |  |  */  | 
378  |  | ed25519_keypair_t *  | 
379  |  | ed_key_init_from_file(const char *fname, uint32_t flags,  | 
380  |  |                       int severity,  | 
381  |  |                       const ed25519_keypair_t *signing_key,  | 
382  |  |                       time_t now,  | 
383  |  |                       time_t lifetime,  | 
384  |  |                       uint8_t cert_type,  | 
385  |  |                       struct tor_cert_st **cert_out,  | 
386  |  |                       const or_options_t *options)  | 
387  | 0  | { | 
388  | 0  |   char *secret_fname = NULL;  | 
389  | 0  |   char *encrypted_secret_fname = NULL;  | 
390  | 0  |   char *public_fname = NULL;  | 
391  | 0  |   char *cert_fname = NULL;  | 
392  | 0  |   const char *loaded_secret_fname = NULL;  | 
393  | 0  |   int created_pk = 0, created_sk = 0, created_cert = 0;  | 
394  | 0  |   const int try_to_load = ! (flags & INIT_ED_KEY_REPLACE);  | 
395  | 0  |   const int encrypt_key = !! (flags & INIT_ED_KEY_TRY_ENCRYPTED);  | 
396  | 0  |   const int norepair = !! (flags & INIT_ED_KEY_NO_REPAIR);  | 
397  | 0  |   const int split = !! (flags & INIT_ED_KEY_SPLIT);  | 
398  | 0  |   const int omit_secret = !! (flags & INIT_ED_KEY_OMIT_SECRET);  | 
399  | 0  |   const int offline_secret = !! (flags & INIT_ED_KEY_OFFLINE_SECRET);  | 
400  | 0  |   const int explicit_fname = !! (flags & INIT_ED_KEY_EXPLICIT_FNAME);  | 
401  |  |  | 
402  |  |   /* we don't support setting both of these flags at once. */  | 
403  | 0  |   tor_assert((flags & (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT)) !=  | 
404  | 0  |                       (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT));  | 
405  |  |  | 
406  | 0  |   char tag[8];  | 
407  | 0  |   tor_snprintf(tag, sizeof(tag), "type%d", (int)cert_type);  | 
408  |  | 
  | 
409  | 0  |   tor_cert_t *cert = NULL;  | 
410  | 0  |   char *got_tag = NULL;  | 
411  | 0  |   ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));  | 
412  |  | 
  | 
413  | 0  |   if (explicit_fname) { | 
414  | 0  |     secret_fname = tor_strdup(fname);  | 
415  | 0  |     encrypted_secret_fname = tor_strdup(fname);  | 
416  | 0  |   } else { | 
417  | 0  |     tor_asprintf(&secret_fname, "%s_secret_key", fname);  | 
418  | 0  |     tor_asprintf(&encrypted_secret_fname, "%s_secret_key_encrypted", fname);  | 
419  | 0  |   }  | 
420  | 0  |   tor_asprintf(&public_fname, "%s_public_key", fname);  | 
421  | 0  |   tor_asprintf(&cert_fname, "%s_cert", fname);  | 
422  |  |  | 
423  |  |   /* Try to read the secret key. */  | 
424  | 0  |   int have_secret = 0;  | 
425  | 0  |   int load_secret = try_to_load &&  | 
426  | 0  |     !offline_secret &&  | 
427  | 0  |     (!omit_secret || file_status(public_fname)==FN_NOENT);  | 
428  | 0  |   if (load_secret) { | 
429  | 0  |     int rv = ed25519_seckey_read_from_file(&keypair->seckey,  | 
430  | 0  |                                            &got_tag, secret_fname);  | 
431  | 0  |     if (rv == 0) { | 
432  | 0  |       have_secret = 1;  | 
433  | 0  |       loaded_secret_fname = secret_fname;  | 
434  | 0  |       tor_assert(got_tag);  | 
435  | 0  |     } else { | 
436  | 0  |       if (errno != ENOENT && norepair) { | 
437  | 0  |         tor_log(severity, LD_OR, "Unable to read %s: %s", secret_fname,  | 
438  | 0  |                 strerror(errno));  | 
439  | 0  |         goto err;  | 
440  | 0  |       }  | 
441  | 0  |     }  | 
442  | 0  |   }  | 
443  |  |  | 
444  |  |   /* Should we try for an encrypted key? */  | 
445  | 0  |   int have_encrypted_secret_file = 0;  | 
446  | 0  |   if (!have_secret && try_to_load && encrypt_key) { | 
447  | 0  |     int r = read_encrypted_secret_key(&keypair->seckey,  | 
448  | 0  |                                       encrypted_secret_fname);  | 
449  | 0  |     if (r > 0) { | 
450  | 0  |       have_secret = 1;  | 
451  | 0  |       have_encrypted_secret_file = 1;  | 
452  | 0  |       tor_free(got_tag); /* convince coverity we aren't leaking */  | 
453  | 0  |       got_tag = tor_strdup(tag);  | 
454  | 0  |       loaded_secret_fname = encrypted_secret_fname;  | 
455  | 0  |     } else if (errno != ENOENT && norepair) { | 
456  | 0  |       tor_log(severity, LD_OR, "Unable to read %s: %s",  | 
457  | 0  |               encrypted_secret_fname, strerror(errno));  | 
458  | 0  |       goto err;  | 
459  | 0  |     }  | 
460  | 0  |   } else { | 
461  | 0  |     if (try_to_load) { | 
462  |  |       /* Check if it's there anyway, so we don't replace it. */  | 
463  | 0  |       if (file_status(encrypted_secret_fname) != FN_NOENT)  | 
464  | 0  |         have_encrypted_secret_file = 1;  | 
465  | 0  |     }  | 
466  | 0  |   }  | 
467  |  |  | 
468  | 0  |   if (have_secret) { | 
469  | 0  |     if (strcmp(got_tag, tag)) { | 
470  | 0  |       tor_log(severity, LD_OR, "%s has wrong tag", loaded_secret_fname);  | 
471  | 0  |       goto err;  | 
472  | 0  |     }  | 
473  |  |     /* Derive the public key */  | 
474  | 0  |     if (ed25519_public_key_generate(&keypair->pubkey, &keypair->seckey)<0) { | 
475  | 0  |       tor_log(severity, LD_OR, "%s can't produce a public key",  | 
476  | 0  |               loaded_secret_fname);  | 
477  | 0  |       goto err;  | 
478  | 0  |     }  | 
479  | 0  |   }  | 
480  |  |  | 
481  |  |   /* If we do split keys here, try to read the pubkey. */  | 
482  | 0  |   int found_public = 0;  | 
483  | 0  |   if (try_to_load && (!have_secret || split)) { | 
484  | 0  |     ed25519_public_key_t pubkey_tmp;  | 
485  | 0  |     tor_free(got_tag);  | 
486  | 0  |     found_public = ed25519_pubkey_read_from_file(&pubkey_tmp,  | 
487  | 0  |                                                  &got_tag, public_fname) == 0;  | 
488  | 0  |     if (!found_public && errno != ENOENT && norepair) { | 
489  | 0  |       tor_log(severity, LD_OR, "Unable to read %s: %s", public_fname,  | 
490  | 0  |               strerror(errno));  | 
491  | 0  |       goto err;  | 
492  | 0  |     }  | 
493  | 0  |     if (found_public && strcmp(got_tag, tag)) { | 
494  | 0  |       tor_log(severity, LD_OR, "%s has wrong tag", public_fname);  | 
495  | 0  |       goto err;  | 
496  | 0  |     }  | 
497  | 0  |     if (found_public) { | 
498  | 0  |       if (have_secret) { | 
499  |  |         /* If we have a secret key and we're reloading the public key,  | 
500  |  |          * the key must match! */  | 
501  | 0  |         if (! ed25519_pubkey_eq(&keypair->pubkey, &pubkey_tmp)) { | 
502  | 0  |           tor_log(severity, LD_OR, "%s does not match %s!  If you are trying "  | 
503  | 0  |                   "to restore from backup, make sure you didn't mix up the "  | 
504  | 0  |                   "key files. If you are absolutely sure that %s is the right "  | 
505  | 0  |                   "key for this relay, delete %s or move it out of the way.",  | 
506  | 0  |                   public_fname, loaded_secret_fname,  | 
507  | 0  |                   loaded_secret_fname, public_fname);  | 
508  | 0  |           goto err;  | 
509  | 0  |         }  | 
510  | 0  |       } else { | 
511  |  |         /* We only have the public key; better use that. */  | 
512  | 0  |         tor_assert(split);  | 
513  | 0  |         memcpy(&keypair->pubkey, &pubkey_tmp, sizeof(pubkey_tmp));  | 
514  | 0  |       }  | 
515  | 0  |     } else { | 
516  |  |       /* We have no public key file, but we do have a secret key, make the  | 
517  |  |        * public key file! */  | 
518  | 0  |       if (have_secret) { | 
519  | 0  |         if (ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag)  | 
520  | 0  |             < 0) { | 
521  | 0  |           tor_log(severity, LD_OR, "Couldn't repair %s", public_fname);  | 
522  | 0  |           goto err;  | 
523  | 0  |         } else { | 
524  | 0  |           tor_log(LOG_NOTICE, LD_OR,  | 
525  | 0  |                   "Found secret key but not %s. Regenerating.",  | 
526  | 0  |                   public_fname);  | 
527  | 0  |         }  | 
528  | 0  |       }  | 
529  | 0  |     }  | 
530  | 0  |   }  | 
531  |  |  | 
532  |  |   /* If the secret key is absent and it's not allowed to be, fail. */  | 
533  | 0  |   if (!have_secret && found_public &&  | 
534  | 0  |       !(flags & INIT_ED_KEY_MISSING_SECRET_OK)) { | 
535  | 0  |     if (have_encrypted_secret_file) { | 
536  | 0  |       tor_log(severity, LD_OR, "We needed to load a secret key from %s, "  | 
537  | 0  |               "but it was encrypted. Try 'tor --keygen' instead, so you "  | 
538  | 0  |               "can enter the passphrase.",  | 
539  | 0  |               secret_fname);  | 
540  | 0  |     } else if (offline_secret) { | 
541  | 0  |       tor_log(severity, LD_OR, "We wanted to load a secret key from %s, "  | 
542  | 0  |               "but you're keeping it offline. (OfflineMasterKey is set.)",  | 
543  | 0  |               secret_fname);  | 
544  | 0  |     } else { | 
545  | 0  |       tor_log(severity, LD_OR, "We needed to load a secret key from %s, "  | 
546  | 0  |               "but couldn't find it. %s", secret_fname,  | 
547  | 0  |               (flags & INIT_ED_KEY_SUGGEST_KEYGEN) ?  | 
548  | 0  |               "If you're keeping your master secret key offline, you will "  | 
549  | 0  |               "need to run 'tor --keygen' to generate new signing keys." :  | 
550  | 0  |               "Did you forget to copy it over when you copied the rest of the "  | 
551  | 0  |               "signing key material?");  | 
552  | 0  |     }  | 
553  | 0  |     goto err;  | 
554  | 0  |   }  | 
555  |  |  | 
556  |  |   /* If it's absent, and we're not supposed to make a new keypair, fail. */  | 
557  | 0  |   if (!have_secret && !found_public && !(flags & INIT_ED_KEY_CREATE)) { | 
558  | 0  |     if (split) { | 
559  | 0  |       tor_log(severity, LD_OR, "No key found in %s or %s.",  | 
560  | 0  |               secret_fname, public_fname);  | 
561  | 0  |     } else { | 
562  | 0  |       tor_log(severity, LD_OR, "No key found in %s.", secret_fname);  | 
563  | 0  |     }  | 
564  | 0  |     goto err;  | 
565  | 0  |   }  | 
566  |  |  | 
567  |  |   /* If the secret key is absent, but the encrypted key would be present,  | 
568  |  |    * that's an error */  | 
569  | 0  |   if (!have_secret && !found_public && have_encrypted_secret_file) { | 
570  | 0  |     tor_assert(!encrypt_key);  | 
571  | 0  |     tor_log(severity, LD_OR, "Found an encrypted secret key, "  | 
572  | 0  |             "but not public key file %s!", public_fname);  | 
573  | 0  |     goto err;  | 
574  | 0  |   }  | 
575  |  |  | 
576  |  |   /* if it's absent, make a new keypair... */  | 
577  | 0  |   if (!have_secret && !found_public) { | 
578  | 0  |     tor_free(keypair);  | 
579  | 0  |     keypair = ed_key_new(signing_key, flags, now, lifetime,  | 
580  | 0  |                          cert_type, &cert);  | 
581  | 0  |     if (!keypair) { | 
582  | 0  |       tor_log(severity, LD_OR, "Couldn't create keypair");  | 
583  | 0  |       goto err;  | 
584  | 0  |     }  | 
585  | 0  |     created_pk = created_sk = created_cert = 1;  | 
586  | 0  |   }  | 
587  |  |  | 
588  |  |   /* Write it to disk if we're supposed to do with a new passphrase, or if  | 
589  |  |    * we just created it. */  | 
590  | 0  |   if (created_sk || (have_secret && options != NULL &&  | 
591  | 0  |                      options->change_key_passphrase)) { | 
592  | 0  |     if (write_secret_key(&keypair->seckey,  | 
593  | 0  |                          encrypt_key,  | 
594  | 0  |                          secret_fname, tag, encrypted_secret_fname) < 0  | 
595  | 0  |         ||  | 
596  | 0  |         (split &&  | 
597  | 0  |          ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag) < 0)  | 
598  | 0  |         ||  | 
599  | 0  |         (cert &&  | 
600  | 0  |          crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",  | 
601  | 0  |                                  tag, cert->encoded, cert->encoded_len) < 0)) { | 
602  | 0  |       tor_log(severity, LD_OR, "Couldn't write keys or cert to file.");  | 
603  | 0  |       goto err;  | 
604  | 0  |     }  | 
605  | 0  |     goto done;  | 
606  | 0  |   }  | 
607  |  |  | 
608  |  |   /* If we're not supposed to get a cert, we're done. */  | 
609  | 0  |   if (! (flags & INIT_ED_KEY_NEEDCERT))  | 
610  | 0  |     goto done;  | 
611  |  |  | 
612  |  |   /* Read a cert. */  | 
613  | 0  |   tor_free(got_tag);  | 
614  | 0  |   uint8_t certbuf[256];  | 
615  | 0  |   ssize_t cert_body_len = crypto_read_tagged_contents_from_file(  | 
616  | 0  |                  cert_fname, "ed25519v1-cert",  | 
617  | 0  |                  &got_tag, certbuf, sizeof(certbuf));  | 
618  | 0  |   if (cert_body_len >= 0 && !strcmp(got_tag, tag))  | 
619  | 0  |     cert = tor_cert_parse(certbuf, cert_body_len);  | 
620  |  |  | 
621  |  |   /* If we got it, check it to the extent we can. */  | 
622  | 0  |   int bad_cert = 0;  | 
623  |  | 
  | 
624  | 0  |   if (! cert) { | 
625  | 0  |     tor_log(severity, LD_OR, "Cert was unparseable");  | 
626  | 0  |     bad_cert = 1;  | 
627  | 0  |   } else if (!tor_memeq(cert->signed_key.pubkey, keypair->pubkey.pubkey,  | 
628  | 0  |                         ED25519_PUBKEY_LEN)) { | 
629  | 0  |     tor_log(severity, LD_OR, "Cert was for wrong key");  | 
630  | 0  |     bad_cert = 1;  | 
631  | 0  |   } else if (signing_key &&  | 
632  | 0  |              tor_cert_checksig(cert, &signing_key->pubkey, now) < 0) { | 
633  | 0  |     tor_log(severity, LD_OR, "Can't check certificate: %s",  | 
634  | 0  |             tor_cert_describe_signature_status(cert));  | 
635  | 0  |     bad_cert = 1;  | 
636  | 0  |   } else if (cert->cert_expired) { | 
637  | 0  |     tor_log(severity, LD_OR, "Certificate is expired");  | 
638  | 0  |     bad_cert = 1;  | 
639  | 0  |   } else if (signing_key && cert->signing_key_included &&  | 
640  | 0  |              ! ed25519_pubkey_eq(&signing_key->pubkey, &cert->signing_key)) { | 
641  | 0  |     tor_log(severity, LD_OR, "Certificate signed by unexpected key!");  | 
642  | 0  |     bad_cert = 1;  | 
643  | 0  |   }  | 
644  |  | 
  | 
645  | 0  |   if (bad_cert) { | 
646  | 0  |     tor_cert_free(cert);  | 
647  | 0  |     cert = NULL;  | 
648  | 0  |   }  | 
649  |  |  | 
650  |  |   /* If we got a cert, we're done. */  | 
651  | 0  |   if (cert)  | 
652  | 0  |     goto done;  | 
653  |  |  | 
654  |  |   /* If we didn't get a cert, and we're not supposed to make one, fail. */  | 
655  | 0  |   if (!signing_key || !(flags & INIT_ED_KEY_CREATE)) { | 
656  | 0  |     tor_log(severity, LD_OR, "Without signing key, can't create certificate");  | 
657  | 0  |     goto err;  | 
658  | 0  |   }  | 
659  |  |  | 
660  |  |   /* We have keys but not a certificate, so make one. */  | 
661  | 0  |   uint32_t cert_flags = 0;  | 
662  | 0  |   if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)  | 
663  | 0  |     cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;  | 
664  | 0  |   cert = tor_cert_create_ed25519(signing_key, cert_type,  | 
665  | 0  |                          &keypair->pubkey,  | 
666  | 0  |                          now, lifetime,  | 
667  | 0  |                          cert_flags);  | 
668  |  | 
  | 
669  | 0  |   if (! cert) { | 
670  | 0  |     tor_log(severity, LD_OR, "Couldn't create certificate");  | 
671  | 0  |     goto err;  | 
672  | 0  |   }  | 
673  |  |  | 
674  |  |   /* Write it to disk. */  | 
675  | 0  |   created_cert = 1;  | 
676  | 0  |   if (crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",  | 
677  | 0  |                              tag, cert->encoded, cert->encoded_len) < 0) { | 
678  | 0  |     tor_log(severity, LD_OR, "Couldn't write cert to disk.");  | 
679  | 0  |     goto err;  | 
680  | 0  |   }  | 
681  |  |  | 
682  | 0  |  done:  | 
683  | 0  |   if (cert_out)  | 
684  | 0  |     *cert_out = cert;  | 
685  | 0  |   else  | 
686  | 0  |     tor_cert_free(cert);  | 
687  |  | 
  | 
688  | 0  |   goto cleanup;  | 
689  |  |  | 
690  | 0  |  err:  | 
691  | 0  |   if (keypair)  | 
692  | 0  |     memwipe(keypair, 0, sizeof(*keypair));  | 
693  | 0  |   tor_free(keypair);  | 
694  | 0  |   tor_cert_free(cert);  | 
695  | 0  |   if (cert_out)  | 
696  | 0  |     *cert_out = NULL;  | 
697  | 0  |   if (created_sk)  | 
698  | 0  |     unlink(secret_fname);  | 
699  | 0  |   if (created_pk)  | 
700  | 0  |     unlink(public_fname);  | 
701  | 0  |   if (created_cert)  | 
702  | 0  |     unlink(cert_fname);  | 
703  |  | 
  | 
704  | 0  |  cleanup:  | 
705  | 0  |   tor_free(encrypted_secret_fname);  | 
706  | 0  |   tor_free(secret_fname);  | 
707  | 0  |   tor_free(public_fname);  | 
708  | 0  |   tor_free(cert_fname);  | 
709  | 0  |   tor_free(got_tag);  | 
710  |  | 
  | 
711  | 0  |   return keypair;  | 
712  | 0  | }  | 
713  |  |  | 
714  |  | /**  | 
715  |  |  * Create a new signing key and (optionally) certificate; do not read or write  | 
716  |  |  * from disk.  See ed_key_init_from_file() for more information.  | 
717  |  |  */  | 
718  |  | ed25519_keypair_t *  | 
719  |  | ed_key_new(const ed25519_keypair_t *signing_key,  | 
720  |  |            uint32_t flags,  | 
721  |  |            time_t now,  | 
722  |  |            time_t lifetime,  | 
723  |  |            uint8_t cert_type,  | 
724  |  |            struct tor_cert_st **cert_out)  | 
725  | 0  | { | 
726  | 0  |   if (cert_out)  | 
727  | 0  |     *cert_out = NULL;  | 
728  |  | 
  | 
729  | 0  |   const int extra_strong = !! (flags & INIT_ED_KEY_EXTRA_STRONG);  | 
730  | 0  |   ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));  | 
731  | 0  |   if (ed25519_keypair_generate(keypair, extra_strong) < 0)  | 
732  | 0  |     goto err;  | 
733  |  |  | 
734  | 0  |   if (! (flags & INIT_ED_KEY_NEEDCERT))  | 
735  | 0  |     return keypair;  | 
736  |  |  | 
737  | 0  |   tor_assert(signing_key);  | 
738  | 0  |   tor_assert(cert_out);  | 
739  | 0  |   uint32_t cert_flags = 0;  | 
740  | 0  |   if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)  | 
741  | 0  |     cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;  | 
742  | 0  |   tor_cert_t *cert = tor_cert_create_ed25519(signing_key, cert_type,  | 
743  | 0  |                                      &keypair->pubkey,  | 
744  | 0  |                                      now, lifetime,  | 
745  | 0  |                                      cert_flags);  | 
746  | 0  |   if (! cert)  | 
747  | 0  |     goto err;  | 
748  |  |  | 
749  | 0  |   *cert_out = cert;  | 
750  | 0  |   return keypair;  | 
751  |  |  | 
752  | 0  |  err:  | 
753  | 0  |   tor_free(keypair);  | 
754  | 0  |   return NULL;  | 
755  | 0  | }  |