Coverage Report

Created: 2024-02-25 06:25

/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
}