LCOV - code coverage report
Current view: top level - feature/keymgt - loadkey.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 273 373 73.2 %
Date: 2021-11-24 03:28:48 Functions: 7 7 100.0 %

          Line data    Source code
       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             : #define ENC_KEY_HEADER "Boxed Ed25519 key"
      27             : #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          43 : init_key_from_file(const char *fname, int generate, int severity,
      41             :                    bool *created_out)
      42             : {
      43          43 :   crypto_pk_t *prkey = NULL;
      44             : 
      45          43 :   if (created_out) {
      46          43 :     *created_out = false;
      47             :   }
      48             : 
      49          43 :   if (!(prkey = crypto_pk_new())) {
      50           0 :     tor_log(severity, LD_GENERAL,"Error constructing key");
      51           0 :     goto error;
      52             :   }
      53             : 
      54          43 :   switch (file_status(fname)) {
      55           0 :     case FN_DIR:
      56             :     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          29 :     case FN_NOENT:
      63             :     case FN_EMPTY:
      64          29 :       if (generate) {
      65          29 :         if (!have_lockfile()) {
      66          17 :           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             :                     "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             :           }
      75             :         }
      76          29 :         log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
      77             :                  fname);
      78          29 :         if (crypto_pk_generate_key(prkey)) {
      79           0 :           tor_log(severity, LD_GENERAL,"Error generating onion key");
      80           0 :           goto error;
      81             :         }
      82          29 :         if (! crypto_pk_is_valid_private_key(prkey)) {
      83           0 :           tor_log(severity, LD_GENERAL,"Generated key seems invalid");
      84           0 :           goto error;
      85             :         }
      86          29 :         log_info(LD_GENERAL, "Generated key seems valid");
      87          29 :         if (created_out) {
      88          29 :           *created_out = true;
      89             :         }
      90          29 :         if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
      91           0 :           tor_log(severity, LD_FS,
      92             :               "Couldn't write generated key to \"%s\".", fname);
      93           0 :           goto error;
      94             :         }
      95             :       } else {
      96           0 :         tor_log(severity, LD_GENERAL, "No key found in \"%s\"", fname);
      97           0 :         goto error;
      98             :       }
      99             :       return prkey;
     100          14 :     case FN_FILE:
     101          14 :       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             :       }
     105             :       return prkey;
     106             :     default:
     107           0 :       tor_assert(0);
     108             :   }
     109             : 
     110           0 :  error:
     111           0 :   if (prkey)
     112           0 :     crypto_pk_free(prkey);
     113             :   return NULL;
     114             : }
     115             : 
     116             : /* DOCDOC */
     117             : static ssize_t
     118           3 : do_getpass(const char *prompt, char *buf, size_t buflen,
     119             :            int twice, const or_options_t *options)
     120             : {
     121           3 :   if (options->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) {
     122           1 :     tor_assert(buflen);
     123           1 :     buf[0] = 0;
     124           1 :     return 0;
     125             :   }
     126             : 
     127           2 :   char *prompt2 = NULL;
     128           2 :   char *buf2 = NULL;
     129           2 :   int fd = -1;
     130           2 :   ssize_t length = -1;
     131             : 
     132           2 :   if (options->use_keygen_passphrase_fd) {
     133           2 :     twice = 0;
     134           2 :     fd = options->keygen_passphrase_fd;
     135           2 :     length = read_all_from_fd(fd, buf, buflen-1);
     136           2 :     if (length >= 0)
     137           2 :       buf[length] = 0;
     138           2 :     goto done_reading;
     139             :   }
     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             :       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             :   }
     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             :       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             :     } else {
     166             :       break;
     167             :     }
     168             :   }
     169             : 
     170           0 :  done_reading:
     171           2 :   if (twice) {
     172           0 :     tor_free(prompt2);
     173           0 :     memwipe(buf2, 0, buflen);
     174           0 :     tor_free(buf2);
     175             :   }
     176             : 
     177           2 :   if (options->keygen_force_passphrase == FORCE_PASSPHRASE_ON && length == 0)
     178           0 :     return -1;
     179             : 
     180             :   return length;
     181             : }
     182             : 
     183             : /* DOCDOC */
     184             : int
     185           3 : read_encrypted_secret_key(ed25519_secret_key_t *out,
     186             :                           const char *fname)
     187             : {
     188           3 :   int r = -1;
     189           3 :   uint8_t *secret = NULL;
     190           3 :   size_t secret_len = 0;
     191           3 :   char pwbuf[256];
     192           3 :   uint8_t encrypted_key[256];
     193           3 :   char *tag = NULL;
     194           3 :   int saved_errno = 0;
     195             : 
     196           3 :   ssize_t encrypted_len = crypto_read_tagged_contents_from_file(fname,
     197             :                                           ENC_KEY_HEADER,
     198             :                                           &tag,
     199             :                                           encrypted_key,
     200             :                                           sizeof(encrypted_key));
     201           3 :   if (encrypted_len < 0) {
     202           2 :     saved_errno = errno;
     203           2 :     log_info(LD_OR, "%s is missing", fname);
     204           2 :     r = 0;
     205           2 :     goto done;
     206             :   }
     207           1 :   if (strcmp(tag, ENC_KEY_TAG)) {
     208           0 :     saved_errno = EINVAL;
     209           0 :     goto done;
     210             :   }
     211             : 
     212           1 :   while (1) {
     213           1 :     ssize_t pwlen =
     214           1 :       do_getpass("Enter passphrase for master key:", pwbuf, sizeof(pwbuf), 0,
     215             :                  get_options());
     216           1 :     if (pwlen < 0) {
     217           0 :       saved_errno = EINVAL;
     218           0 :       goto done;
     219             :     }
     220           1 :     const int r_unbox = crypto_unpwbox(&secret, &secret_len,
     221             :                                        encrypted_key, encrypted_len,
     222             :                                        pwbuf, pwlen);
     223           1 :     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           1 :     } else if (r_unbox == UNPWBOX_OKAY) {
     228             :       break;
     229             :     }
     230             : 
     231             :     /* Otherwise, passphrase is bad, so try again till user does ctrl-c or gets
     232             :      * it right. */
     233             :   }
     234             : 
     235           1 :   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             :   }
     240           1 :   memcpy(out->seckey, secret, ED25519_SECKEY_LEN);
     241           1 :   r = 1;
     242             : 
     243           3 :  done:
     244           3 :   memwipe(encrypted_key, 0, sizeof(encrypted_key));
     245           3 :   memwipe(pwbuf, 0, sizeof(pwbuf));
     246           3 :   tor_free(tag);
     247           3 :   if (secret) {
     248           1 :     memwipe(secret, 0, secret_len);
     249           1 :     tor_free(secret);
     250             :   }
     251           3 :   if (saved_errno)
     252           2 :     errno = saved_errno;
     253           3 :   return r;
     254             : }
     255             : 
     256             : /* DOCDOC */
     257             : int
     258           2 : write_encrypted_secret_key(const ed25519_secret_key_t *key,
     259             :                            const char *fname)
     260             : {
     261           2 :   int r = -1;
     262           2 :   char pwbuf0[256];
     263           2 :   uint8_t *encrypted_key = NULL;
     264           2 :   size_t encrypted_len = 0;
     265             : 
     266           2 :   if (do_getpass("Enter new passphrase:", pwbuf0, sizeof(pwbuf0), 1,
     267             :                  get_options()) < 0) {
     268           0 :     log_warn(LD_OR, "NO/failed passphrase");
     269           0 :     return -1;
     270             :   }
     271             : 
     272           2 :   if (strlen(pwbuf0) == 0) {
     273           1 :     if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_ON)
     274             :       return -1;
     275             :     else
     276           1 :       return 0;
     277             :   }
     278             : 
     279           1 :   if (crypto_pwbox(&encrypted_key, &encrypted_len,
     280           1 :                    key->seckey, sizeof(key->seckey),
     281             :                    pwbuf0, strlen(pwbuf0),  0) < 0) {
     282           0 :     log_warn(LD_OR, "crypto_pwbox failed!?");
     283           0 :     goto done;
     284             :   }
     285           1 :   if (crypto_write_tagged_contents_to_file(fname,
     286             :                                            ENC_KEY_HEADER,
     287             :                                            ENC_KEY_TAG,
     288             :                                            encrypted_key, encrypted_len) < 0)
     289           0 :     goto done;
     290             :   r = 1;
     291           1 :  done:
     292           1 :   if (encrypted_key) {
     293           1 :     memwipe(encrypted_key, 0, encrypted_len);
     294           1 :     tor_free(encrypted_key);
     295             :   }
     296           1 :   memwipe(pwbuf0, 0, sizeof(pwbuf0));
     297           1 :   return r;
     298             : }
     299             : 
     300             : /* DOCDOC */
     301             : static int
     302          30 : 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             : {
     307          30 :   if (encrypted) {
     308           2 :     int r = write_encrypted_secret_key(key, encrypted_fname);
     309           2 :     if (r == 1) {
     310             :       /* Success! */
     311             : 
     312             :       /* Try to unlink the unencrypted key, if any existed before */
     313           1 :       if (strcmp(fname, encrypted_fname))
     314           1 :         unlink(fname);
     315           1 :       return r;
     316           1 :     } else if (r != 0) {
     317             :       /* Unrecoverable failure! */
     318             :       return r;
     319             :     }
     320             : 
     321           1 :     fprintf(stderr, "Not encrypting the secret key.\n");
     322             :   }
     323          29 :   return ed25519_seckey_write_to_file(key, fname, fname_tag);
     324             : }
     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         142 : 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             : {
     388         142 :   char *secret_fname = NULL;
     389         142 :   char *encrypted_secret_fname = NULL;
     390         142 :   char *public_fname = NULL;
     391         142 :   char *cert_fname = NULL;
     392         142 :   const char *loaded_secret_fname = NULL;
     393         142 :   int created_pk = 0, created_sk = 0, created_cert = 0;
     394         142 :   const int try_to_load = ! (flags & INIT_ED_KEY_REPLACE);
     395         142 :   const int encrypt_key = !! (flags & INIT_ED_KEY_TRY_ENCRYPTED);
     396         142 :   const int norepair = !! (flags & INIT_ED_KEY_NO_REPAIR);
     397         142 :   const int split = !! (flags & INIT_ED_KEY_SPLIT);
     398         142 :   const int omit_secret = !! (flags & INIT_ED_KEY_OMIT_SECRET);
     399         142 :   const int offline_secret = !! (flags & INIT_ED_KEY_OFFLINE_SECRET);
     400         142 :   const int explicit_fname = !! (flags & INIT_ED_KEY_EXPLICIT_FNAME);
     401             : 
     402             :   /* we don't support setting both of these flags at once. */
     403         142 :   tor_assert((flags & (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT)) !=
     404             :                       (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT));
     405             : 
     406         142 :   char tag[8];
     407         142 :   tor_snprintf(tag, sizeof(tag), "type%d", (int)cert_type);
     408             : 
     409         142 :   tor_cert_t *cert = NULL;
     410         142 :   char *got_tag = NULL;
     411         142 :   ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));
     412             : 
     413         142 :   if (explicit_fname) {
     414           0 :     secret_fname = tor_strdup(fname);
     415           0 :     encrypted_secret_fname = tor_strdup(fname);
     416             :   } else {
     417         142 :     tor_asprintf(&secret_fname, "%s_secret_key", fname);
     418         142 :     tor_asprintf(&encrypted_secret_fname, "%s_secret_key_encrypted", fname);
     419             :   }
     420         142 :   tor_asprintf(&public_fname, "%s_public_key", fname);
     421         142 :   tor_asprintf(&cert_fname, "%s_cert", fname);
     422             : 
     423             :   /* Try to read the secret key. */
     424         142 :   int have_secret = 0;
     425         388 :   int load_secret = try_to_load &&
     426         142 :     !offline_secret &&
     427          24 :     (!omit_secret || file_status(public_fname)==FN_NOENT);
     428         104 :   if (load_secret) {
     429         104 :     int rv = ed25519_seckey_read_from_file(&keypair->seckey,
     430             :                                            &got_tag, secret_fname);
     431         104 :     if (rv == 0) {
     432          47 :       have_secret = 1;
     433          47 :       loaded_secret_fname = secret_fname;
     434          47 :       tor_assert(got_tag);
     435             :     } else {
     436          57 :       if (errno != ENOENT && norepair) {
     437           0 :         tor_log(severity, LD_OR, "Unable to read %s: %s", secret_fname,
     438             :                 strerror(errno));
     439           0 :         goto err;
     440             :       }
     441             :     }
     442             :   }
     443             : 
     444             :   /* Should we try for an encrypted key? */
     445         142 :   int have_encrypted_secret_file = 0;
     446         142 :   if (!have_secret && try_to_load && encrypt_key) {
     447           3 :     int r = read_encrypted_secret_key(&keypair->seckey,
     448             :                                       encrypted_secret_fname);
     449           3 :     if (r > 0) {
     450           1 :       have_secret = 1;
     451           1 :       have_encrypted_secret_file = 1;
     452           1 :       tor_free(got_tag); /* convince coverity we aren't leaking */
     453           1 :       got_tag = tor_strdup(tag);
     454           1 :       loaded_secret_fname = encrypted_secret_fname;
     455           2 :     } else if (errno != ENOENT && norepair) {
     456           0 :       tor_log(severity, LD_OR, "Unable to read %s: %s",
     457             :               encrypted_secret_fname, strerror(errno));
     458           0 :       goto err;
     459             :     }
     460             :   } else {
     461         139 :     if (try_to_load) {
     462             :       /* Check if it's there anyway, so we don't replace it. */
     463         123 :       if (file_status(encrypted_secret_fname) != FN_NOENT)
     464           3 :         have_encrypted_secret_file = 1;
     465             :     }
     466             :   }
     467             : 
     468         142 :   if (have_secret) {
     469          48 :     if (strcmp(got_tag, tag)) {
     470           1 :       tor_log(severity, LD_OR, "%s has wrong tag", loaded_secret_fname);
     471           1 :       goto err;
     472             :     }
     473             :     /* Derive the public key */
     474          47 :     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             :               loaded_secret_fname);
     477           0 :       goto err;
     478             :     }
     479             :   }
     480             : 
     481             :   /* If we do split keys here, try to read the pubkey. */
     482         141 :   int found_public = 0;
     483         141 :   if (try_to_load && (!have_secret || split)) {
     484          90 :     ed25519_public_key_t pubkey_tmp;
     485          90 :     tor_free(got_tag);
     486          90 :     found_public = ed25519_pubkey_read_from_file(&pubkey_tmp,
     487          90 :                                                  &got_tag, public_fname) == 0;
     488          90 :     if (!found_public && errno != ENOENT && norepair) {
     489           0 :       tor_log(severity, LD_OR, "Unable to read %s: %s", public_fname,
     490             :               strerror(errno));
     491           2 :       goto err;
     492             :     }
     493          90 :     if (found_public && strcmp(got_tag, tag)) {
     494           1 :       tor_log(severity, LD_OR, "%s has wrong tag", public_fname);
     495           1 :       goto err;
     496             :     }
     497          89 :     if (found_public) {
     498          38 :       if (have_secret) {
     499             :         /* If we have a secret key and we're reloading the public key,
     500             :          * the key must match! */
     501          10 :         if (! ed25519_pubkey_eq(&keypair->pubkey, &pubkey_tmp)) {
     502           1 :           tor_log(severity, LD_OR, "%s does not match %s!  If you are trying "
     503             :                   "to restore from backup, make sure you didn't mix up the "
     504             :                   "key files. If you are absolutely sure that %s is the right "
     505             :                   "key for this relay, delete %s or move it out of the way.",
     506             :                   public_fname, loaded_secret_fname,
     507             :                   loaded_secret_fname, public_fname);
     508           1 :           goto err;
     509             :         }
     510             :       } else {
     511             :         /* We only have the public key; better use that. */
     512          28 :         tor_assert(split);
     513          88 :         memcpy(&keypair->pubkey, &pubkey_tmp, sizeof(pubkey_tmp));
     514             :       }
     515             :     } else {
     516             :       /* We have no public key file, but we do have a secret key, make the
     517             :        * public key file! */
     518          51 :       if (have_secret) {
     519           2 :         if (ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag)
     520             :             < 0) {
     521           0 :           tor_log(severity, LD_OR, "Couldn't repair %s", public_fname);
     522           0 :           goto err;
     523             :         } else {
     524           2 :           tor_log(LOG_NOTICE, LD_OR,
     525             :                   "Found secret key but not %s. Regenerating.",
     526             :                   public_fname);
     527             :         }
     528             :       }
     529             :     }
     530             :   }
     531             : 
     532             :   /* If the secret key is absent and it's not allowed to be, fail. */
     533         139 :   if (!have_secret && found_public &&
     534          28 :       !(flags & INIT_ED_KEY_MISSING_SECRET_OK)) {
     535           4 :     if (have_encrypted_secret_file) {
     536           2 :       tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
     537             :               "but it was encrypted. Try 'tor --keygen' instead, so you "
     538             :               "can enter the passphrase.",
     539             :               secret_fname);
     540           2 :     } else if (offline_secret) {
     541           0 :       tor_log(severity, LD_OR, "We wanted to load a secret key from %s, "
     542             :               "but you're keeping it offline. (OfflineMasterKey is set.)",
     543             :               secret_fname);
     544             :     } else {
     545           2 :       tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
     546             :               "but couldn't find it. %s", secret_fname,
     547           2 :               (flags & INIT_ED_KEY_SUGGEST_KEYGEN) ?
     548             :               "If you're keeping your master secret key offline, you will "
     549             :               "need to run 'tor --keygen' to generate new signing keys." :
     550             :               "Did you forget to copy it over when you copied the rest of the "
     551             :               "signing key material?");
     552             :     }
     553           4 :     goto err;
     554             :   }
     555             : 
     556             :   /* If it's absent, and we're not supposed to make a new keypair, fail. */
     557         135 :   if (!have_secret && !found_public && !(flags & INIT_ED_KEY_CREATE)) {
     558          34 :     if (split) {
     559          15 :       tor_log(severity, LD_OR, "No key found in %s or %s.",
     560             :               secret_fname, public_fname);
     561             :     } else {
     562          19 :       tor_log(severity, LD_OR, "No key found in %s.", secret_fname);
     563             :     }
     564          34 :     goto err;
     565             :   }
     566             : 
     567             :   /* If the secret key is absent, but the encrypted key would be present,
     568             :    * that's an error */
     569         101 :   if (!have_secret && !found_public && have_encrypted_secret_file) {
     570           1 :     tor_assert(!encrypt_key);
     571           1 :     tor_log(severity, LD_OR, "Found an encrypted secret key, "
     572             :             "but not public key file %s!", public_fname);
     573           1 :     goto err;
     574             :   }
     575             : 
     576             :   /* if it's absent, make a new keypair... */
     577         100 :   if (!have_secret && !found_public) {
     578          30 :     tor_free(keypair);
     579          30 :     keypair = ed_key_new(signing_key, flags, now, lifetime,
     580             :                          cert_type, &cert);
     581          30 :     if (!keypair) {
     582           0 :       tor_log(severity, LD_OR, "Couldn't create keypair");
     583           0 :       goto err;
     584             :     }
     585             :     created_pk = created_sk = created_cert = 1;
     586             :   }
     587             : 
     588             :   /* Write it to disk if we're supposed to do with a new passphrase, or if
     589             :    * we just created it. */
     590         100 :   if (created_sk || (have_secret && options != NULL &&
     591          36 :                      options->change_key_passphrase)) {
     592          30 :     if (write_secret_key(&keypair->seckey,
     593             :                          encrypt_key,
     594             :                          secret_fname, tag, encrypted_secret_fname) < 0
     595          30 :         ||
     596          12 :         (split &&
     597          12 :          ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag) < 0)
     598          30 :         ||
     599          47 :         (cert &&
     600          17 :          crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",
     601          17 :                                  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             :     }
     605          30 :     goto done;
     606             :   }
     607             : 
     608             :   /* If we're not supposed to get a cert, we're done. */
     609          70 :   if (! (flags & INIT_ED_KEY_NEEDCERT))
     610          37 :     goto done;
     611             : 
     612             :   /* Read a cert. */
     613          33 :   tor_free(got_tag);
     614          33 :   uint8_t certbuf[256];
     615          33 :   ssize_t cert_body_len = crypto_read_tagged_contents_from_file(
     616             :                  cert_fname, "ed25519v1-cert",
     617             :                  &got_tag, certbuf, sizeof(certbuf));
     618          33 :   if (cert_body_len >= 0 && !strcmp(got_tag, tag))
     619          31 :     cert = tor_cert_parse(certbuf, cert_body_len);
     620             : 
     621             :   /* If we got it, check it to the extent we can. */
     622          33 :   int bad_cert = 0;
     623             : 
     624          33 :   if (! cert) {
     625           2 :     tor_log(severity, LD_OR, "Cert was unparseable");
     626           2 :     bad_cert = 1;
     627          31 :   } else if (!tor_memeq(cert->signed_key.pubkey, keypair->pubkey.pubkey,
     628             :                         ED25519_PUBKEY_LEN)) {
     629           1 :     tor_log(severity, LD_OR, "Cert was for wrong key");
     630           1 :     bad_cert = 1;
     631          34 :   } else if (signing_key &&
     632           4 :              tor_cert_checksig(cert, &signing_key->pubkey, now) < 0) {
     633           1 :     tor_log(severity, LD_OR, "Can't check certificate: %s",
     634             :             tor_cert_describe_signature_status(cert));
     635           1 :     bad_cert = 1;
     636          29 :   } else if (cert->cert_expired) {
     637           0 :     tor_log(severity, LD_OR, "Certificate is expired");
     638           0 :     bad_cert = 1;
     639          29 :   } 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             :   }
     644             : 
     645           4 :   if (bad_cert) {
     646           4 :     tor_cert_free(cert);
     647           4 :     cert = NULL;
     648             :   }
     649             : 
     650             :   /* If we got a cert, we're done. */
     651          33 :   if (cert)
     652          29 :     goto done;
     653             : 
     654             :   /* If we didn't get a cert, and we're not supposed to make one, fail. */
     655           4 :   if (!signing_key || !(flags & INIT_ED_KEY_CREATE)) {
     656           4 :     tor_log(severity, LD_OR, "Without signing key, can't create certificate");
     657           4 :     goto err;
     658             :   }
     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             :                          now, lifetime,
     667             :                          cert_flags);
     668             : 
     669           0 :   if (! cert) {
     670           0 :     tor_log(severity, LD_OR, "Couldn't create certificate");
     671           0 :     goto err;
     672             :   }
     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             :   }
     681             : 
     682           0 :  done:
     683          96 :   if (cert_out)
     684          52 :     *cert_out = cert;
     685             :   else
     686          44 :     tor_cert_free(cert);
     687             : 
     688          96 :   goto cleanup;
     689             : 
     690          46 :  err:
     691          46 :   if (keypair)
     692          46 :     memwipe(keypair, 0, sizeof(*keypair));
     693          46 :   tor_free(keypair);
     694          46 :   tor_cert_free(cert);
     695          46 :   if (cert_out)
     696          26 :     *cert_out = NULL;
     697          46 :   if (created_sk)
     698           0 :     unlink(secret_fname);
     699          46 :   if (created_pk)
     700           0 :     unlink(public_fname);
     701          46 :   if (created_cert)
     702           0 :     unlink(cert_fname);
     703             : 
     704          46 :  cleanup:
     705         142 :   tor_free(encrypted_secret_fname);
     706         142 :   tor_free(secret_fname);
     707         142 :   tor_free(public_fname);
     708         142 :   tor_free(cert_fname);
     709         142 :   tor_free(got_tag);
     710             : 
     711         142 :   return keypair;
     712             : }
     713             : 
     714             : /**
     715             :  * Create a new signing key and (optionally) certficiate; do not read or write
     716             :  * from disk.  See ed_key_init_from_file() for more information.
     717             :  */
     718             : ed25519_keypair_t *
     719          67 : 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             : {
     726          67 :   if (cert_out)
     727          67 :     *cert_out = NULL;
     728             : 
     729          67 :   const int extra_strong = !! (flags & INIT_ED_KEY_EXTRA_STRONG);
     730          67 :   ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));
     731          67 :   if (ed25519_keypair_generate(keypair, extra_strong) < 0)
     732           0 :     goto err;
     733             : 
     734          67 :   if (! (flags & INIT_ED_KEY_NEEDCERT))
     735             :     return keypair;
     736             : 
     737          53 :   tor_assert(signing_key);
     738          53 :   tor_assert(cert_out);
     739          53 :   uint32_t cert_flags = 0;
     740          53 :   if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
     741          17 :     cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
     742         106 :   tor_cert_t *cert = tor_cert_create_ed25519(signing_key, cert_type,
     743          53 :                                      &keypair->pubkey,
     744             :                                      now, lifetime,
     745             :                                      cert_flags);
     746          53 :   if (! cert)
     747           0 :     goto err;
     748             : 
     749          53 :   *cert_out = cert;
     750          53 :   return keypair;
     751             : 
     752           0 :  err:
     753           0 :   tor_free(keypair);
     754           0 :   return NULL;
     755             : }

Generated by: LCOV version 1.14