tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

tortls.c (11603B)


      1 /* Copyright (c) 2003, Roger Dingledine.
      2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      4 /* See LICENSE for licensing information */
      5 
      6 /**
      7 * @file tortls.c
      8 * @brief Shared functionality for our TLS backends.
      9 **/
     10 
     11 #define TORTLS_PRIVATE
     12 #define TOR_X509_PRIVATE
     13 #include "lib/tls/x509.h"
     14 #include "lib/tls/x509_internal.h"
     15 #include "lib/tls/tortls_sys.h"
     16 #include "lib/tls/tortls.h"
     17 #include "lib/tls/tortls_st.h"
     18 #include "lib/tls/tortls_internal.h"
     19 #include "lib/log/util_bug.h"
     20 #include "lib/intmath/cmp.h"
     21 #include "lib/crypt_ops/crypto_rsa.h"
     22 #include "lib/crypt_ops/crypto_rand.h"
     23 #include "lib/net/socket.h"
     24 #include "lib/subsys/subsys.h"
     25 
     26 #ifdef _WIN32
     27  #include <winsock2.h>
     28  #include <ws2tcpip.h>
     29 #endif
     30 
     31 #include <time.h>
     32 
     33 /** Global TLS contexts. We keep them here because nobody else needs
     34 * to touch them.
     35 *
     36 * @{ */
     37 STATIC tor_tls_context_t *server_tls_context = NULL;
     38 STATIC tor_tls_context_t *client_tls_context = NULL;
     39 /**@}*/
     40 
     41 /**
     42 * Return the appropriate TLS context.
     43 */
     44 tor_tls_context_t *
     45 tor_tls_context_get(int is_server)
     46 {
     47  return is_server ? server_tls_context : client_tls_context;
     48 }
     49 
     50 /** Convert an errno (or a WSAerrno on windows) into a TOR_TLS_* error
     51 * code. */
     52 int
     53 tor_errno_to_tls_error(int e)
     54 {
     55  switch (e) {
     56    case SOCK_ERRNO(ECONNRESET): // most common
     57      return TOR_TLS_ERROR_CONNRESET;
     58    case SOCK_ERRNO(ETIMEDOUT):
     59      return TOR_TLS_ERROR_TIMEOUT;
     60    case SOCK_ERRNO(EHOSTUNREACH):
     61    case SOCK_ERRNO(ENETUNREACH):
     62      return TOR_TLS_ERROR_NO_ROUTE;
     63    case SOCK_ERRNO(ECONNREFUSED):
     64      return TOR_TLS_ERROR_CONNREFUSED; // least common
     65    default:
     66      return TOR_TLS_ERROR_MISC;
     67  }
     68 }
     69 
     70 /** Set *<b>link_cert_out</b> and *<b>id_cert_out</b> to the link certificate
     71 * and ID certificate that we're currently using for our V3 in-protocol
     72 * handshake's certificate chain.  If <b>server</b> is true, provide the certs
     73 * that we use in server mode (auth, ID); otherwise, provide the certs that we
     74 * use in client mode. (link, ID) */
     75 int
     76 tor_tls_get_my_certs(int server,
     77                     const tor_x509_cert_t **link_cert_out,
     78                     const tor_x509_cert_t **id_cert_out)
     79 {
     80  tor_tls_context_t *ctx = tor_tls_context_get(server);
     81  int rv = -1;
     82  const tor_x509_cert_t *link_cert = NULL;
     83  const tor_x509_cert_t *id_cert = NULL;
     84  if (ctx) {
     85    rv = 0;
     86    link_cert = server ? ctx->my_link_cert : ctx->my_auth_cert;
     87    id_cert = ctx->my_id_cert;
     88  }
     89  if (link_cert_out)
     90    *link_cert_out = link_cert;
     91  if (id_cert_out)
     92    *id_cert_out = id_cert;
     93  return rv;
     94 }
     95 
     96 /** Increase the reference count of <b>ctx</b>. */
     97 void
     98 tor_tls_context_incref(tor_tls_context_t *ctx)
     99 {
    100  ++ctx->refcnt;
    101 }
    102 
    103 /** Remove a reference to <b>ctx</b>, and free it if it has no more
    104 * references. */
    105 void
    106 tor_tls_context_decref(tor_tls_context_t *ctx)
    107 {
    108  tor_assert(ctx);
    109  if (--ctx->refcnt == 0) {
    110    tor_tls_context_impl_free(ctx->ctx);
    111    tor_x509_cert_free(ctx->my_link_cert);
    112    tor_x509_cert_free(ctx->my_id_cert);
    113    tor_x509_cert_free(ctx->my_auth_cert);
    114    crypto_pk_free(ctx->link_key);
    115    crypto_pk_free(ctx->auth_key);
    116    /* LCOV_EXCL_BR_START since ctx will never be NULL here */
    117    tor_free(ctx);
    118    /* LCOV_EXCL_BR_STOP */
    119  }
    120 }
    121 
    122 /** Free all global TLS structures. */
    123 void
    124 tor_tls_free_all(void)
    125 {
    126  check_no_tls_errors();
    127 
    128  if (server_tls_context) {
    129    tor_tls_context_t *ctx = server_tls_context;
    130    server_tls_context = NULL;
    131    tor_tls_context_decref(ctx);
    132  }
    133  if (client_tls_context) {
    134    tor_tls_context_t *ctx = client_tls_context;
    135    client_tls_context = NULL;
    136    tor_tls_context_decref(ctx);
    137  }
    138 }
    139 
    140 /** Given a TOR_TLS_* error code, return a string equivalent. */
    141 const char *
    142 tor_tls_err_to_string(int err)
    143 {
    144  if (err >= 0)
    145    return "[Not an error.]";
    146  switch (err) {
    147    case TOR_TLS_ERROR_MISC: return "misc error";
    148    case TOR_TLS_ERROR_IO: return "unexpected close";
    149    case TOR_TLS_ERROR_CONNREFUSED: return "connection refused";
    150    case TOR_TLS_ERROR_CONNRESET: return "connection reset";
    151    case TOR_TLS_ERROR_NO_ROUTE: return "host unreachable";
    152    case TOR_TLS_ERROR_TIMEOUT: return "connection timed out";
    153    case TOR_TLS_CLOSE: return "closed";
    154    case TOR_TLS_WANTREAD: return "want to read";
    155    case TOR_TLS_WANTWRITE: return "want to write";
    156    default: return "(unknown error code)";
    157  }
    158 }
    159 
    160 /** Create new global client and server TLS contexts.
    161 *
    162 * If <b>server_identity</b> is NULL, this will not generate a server
    163 * TLS context. If TOR_TLS_CTX_IS_PUBLIC_SERVER is set in <b>flags</b>, use
    164 * the same TLS context for incoming and outgoing connections, and
    165 * ignore <b>client_identity</b>.
    166 */
    167 int
    168 tor_tls_context_init(unsigned flags,
    169                     crypto_pk_t *client_identity,
    170                     crypto_pk_t *server_identity,
    171                     unsigned int key_lifetime)
    172 {
    173  int rv1 = 0;
    174  int rv2 = 0;
    175  const int is_public_server = flags & TOR_TLS_CTX_IS_PUBLIC_SERVER;
    176  check_no_tls_errors();
    177 
    178  if (is_public_server) {
    179    tor_tls_context_t *new_ctx;
    180    tor_tls_context_t *old_ctx;
    181 
    182    tor_assert(server_identity != NULL);
    183 
    184    rv1 = tor_tls_context_init_one(&server_tls_context,
    185                                   server_identity,
    186                                   key_lifetime, flags, 0);
    187 
    188    if (rv1 >= 0) {
    189      new_ctx = server_tls_context;
    190      tor_tls_context_incref(new_ctx);
    191      old_ctx = client_tls_context;
    192      client_tls_context = new_ctx;
    193 
    194      if (old_ctx != NULL) {
    195        tor_tls_context_decref(old_ctx);
    196      }
    197    } else {
    198      tls_log_errors(NULL, LOG_WARN, LD_CRYPTO,
    199                     "constructing a TLS context");
    200    }
    201  } else {
    202    if (server_identity != NULL) {
    203      rv1 = tor_tls_context_init_one(&server_tls_context,
    204                                     server_identity,
    205                                     key_lifetime,
    206                                     flags,
    207                                     0);
    208      if (rv1 < 0)
    209        tls_log_errors(NULL, LOG_WARN, LD_CRYPTO,
    210                       "constructing a server TLS context");
    211    } else {
    212      tor_tls_context_t *old_ctx = server_tls_context;
    213      server_tls_context = NULL;
    214 
    215      if (old_ctx != NULL) {
    216        tor_tls_context_decref(old_ctx);
    217      }
    218    }
    219 
    220    rv2 = tor_tls_context_init_one(&client_tls_context,
    221                                   client_identity,
    222                                   key_lifetime,
    223                                   flags,
    224                                   1);
    225    if (rv2 < 0)
    226        tls_log_errors(NULL, LOG_WARN, LD_CRYPTO,
    227                       "constructing a client TLS context");
    228  }
    229 
    230  return MIN(rv1, rv2);
    231 }
    232 
    233 /** Create a new global TLS context.
    234 *
    235 * You can call this function multiple times.  Each time you call it,
    236 * it generates new certificates; all new connections will use
    237 * the new SSL context.
    238 */
    239 int
    240 tor_tls_context_init_one(tor_tls_context_t **ppcontext,
    241                         crypto_pk_t *identity,
    242                         unsigned int key_lifetime,
    243                         unsigned int flags,
    244                         int is_client)
    245 {
    246  tor_tls_context_t *new_ctx = tor_tls_context_new(identity,
    247                                                   key_lifetime,
    248                                                   flags,
    249                                                   is_client);
    250  tor_tls_context_t *old_ctx = *ppcontext;
    251 
    252  if (new_ctx != NULL) {
    253    *ppcontext = new_ctx;
    254 
    255    /* Free the old context if one existed. */
    256    if (old_ctx != NULL) {
    257      /* This is safe even if there are open connections: we reference-
    258       * count tor_tls_context_t objects. */
    259      tor_tls_context_decref(old_ctx);
    260    }
    261  }
    262 
    263  return ((new_ctx != NULL) ? 0 : -1);
    264 }
    265 
    266 /** Size of the RSA key to use for our TLS link keys */
    267 #define RSA_LINK_KEY_BITS 2048
    268 
    269 /** How long do identity certificates live? (sec) */
    270 #define IDENTITY_CERT_LIFETIME  (365*24*60*60)
    271 
    272 /**
    273 * Initialize the certificates and keys for a TLS context <b>result</b>
    274 *
    275 * Other arguments as for tor_tls_context_new().
    276 */
    277 int
    278 tor_tls_context_init_certificates(tor_tls_context_t *result,
    279                                  crypto_pk_t *identity,
    280                                  unsigned key_lifetime,
    281                                  unsigned flags)
    282 {
    283  (void)flags;
    284  int rv = -1;
    285  char *nickname = NULL, *nn2 = NULL;
    286  crypto_pk_t *rsa = NULL, *rsa_auth = NULL;
    287  tor_x509_cert_impl_t *cert = NULL, *idcert = NULL, *authcert = NULL;
    288 
    289  nickname = crypto_random_hostname(8, 20, "www.", ".net");
    290 
    291 #ifdef DISABLE_V3_LINKPROTO_SERVERSIDE
    292  nn2 = crypto_random_hostname(8, 20, "www.", ".net");
    293 #else
    294  nn2 = crypto_random_hostname(8, 20, "www.", ".com");
    295 #endif
    296 
    297  /* Generate short-term RSA key for use with TLS. */
    298  if (!(rsa = crypto_pk_new()))
    299    goto error;
    300  if (crypto_pk_generate_key_with_bits(rsa, RSA_LINK_KEY_BITS)<0)
    301    goto error;
    302 
    303  /* Generate short-term RSA key for use in the in-protocol ("v3")
    304   * authentication handshake. */
    305  if (!(rsa_auth = crypto_pk_new()))
    306    goto error;
    307  if (crypto_pk_generate_key(rsa_auth)<0)
    308    goto error;
    309 
    310  /* Create a link certificate signed by identity key. */
    311  cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
    312                                    key_lifetime);
    313  /* Create self-signed certificate for identity key. */
    314  idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
    315                                      IDENTITY_CERT_LIFETIME);
    316  /* Create an authentication certificate signed by identity key. */
    317  authcert = tor_tls_create_certificate(rsa_auth, identity, nickname, nn2,
    318                                        key_lifetime);
    319  if (!cert || !idcert || !authcert) {
    320    log_warn(LD_CRYPTO, "Error creating certificate");
    321    goto error;
    322  }
    323 
    324  result->my_link_cert = tor_x509_cert_new(cert);
    325  cert = NULL;
    326  result->my_id_cert = tor_x509_cert_new(idcert);
    327  idcert = NULL;
    328  result->my_auth_cert = tor_x509_cert_new(authcert);
    329  authcert = NULL;
    330  if (!result->my_link_cert || !result->my_id_cert || !result->my_auth_cert)
    331    goto error;
    332  result->link_key = rsa;
    333  rsa = NULL;
    334  result->auth_key = rsa_auth;
    335  rsa_auth = NULL;
    336 
    337  rv = 0;
    338 error:
    339 
    340  tor_free(nickname);
    341  tor_free(nn2);
    342 
    343  tor_x509_cert_impl_free(cert);
    344  tor_x509_cert_impl_free(idcert);
    345  tor_x509_cert_impl_free(authcert);
    346  crypto_pk_free(rsa);
    347  crypto_pk_free(rsa_auth);
    348 
    349  return rv;
    350 }
    351 /** Make future log messages about <b>tls</b> display the address
    352 * <b>address</b>.
    353 */
    354 void
    355 tor_tls_set_logged_address(tor_tls_t *tls, const char *address)
    356 {
    357  tor_assert(tls);
    358  tor_free(tls->address);
    359  tls->address = tor_strdup(address);
    360 }
    361 
    362 /** Return whether this tls initiated the connect (client) or
    363 * received it (server). */
    364 int
    365 tor_tls_is_server(tor_tls_t *tls)
    366 {
    367  tor_assert(tls);
    368  return tls->isServer;
    369 }
    370 
    371 /** Release resources associated with a TLS object.  Does not close the
    372 * underlying file descriptor.
    373 */
    374 void
    375 tor_tls_free_(tor_tls_t *tls)
    376 {
    377  if (!tls)
    378    return;
    379  tor_assert(tls->ssl);
    380  {
    381    size_t r,w;
    382    tor_tls_get_n_raw_bytes(tls,&r,&w); /* ensure written_by_tls is updated */
    383  }
    384  tor_tls_impl_free(tls->ssl);
    385  tls->ssl = NULL;
    386 #ifdef ENABLE_OPENSSL
    387  tls->negotiated_callback = NULL;
    388 #endif
    389  if (tls->context)
    390    tor_tls_context_decref(tls->context);
    391  tor_free(tls->address);
    392  tls->magic = 0x99999999;
    393  tor_free(tls);
    394 }
    395 
    396 static void
    397 subsys_tortls_shutdown(void)
    398 {
    399  tor_tls_free_all();
    400 }
    401 
    402 const subsys_fns_t sys_tortls = {
    403  .name = "tortls",
    404  SUBSYS_DECLARE_LOCATION(),
    405  .level = -50,
    406  .shutdown = subsys_tortls_shutdown
    407 };