tortls.c 4.49 KB
Newer Older
1
2
/* Copyright (c) 2003, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
Nick Mathewson's avatar
Nick Mathewson committed
3
 * Copyright (c) 2007-2018, The Tor Project, Inc. */
4
5
/* See LICENSE for licensing information */

6
#define TORTLS_PRIVATE
7
#include "lib/tls/x509.h"
8
#include "lib/tls/tortls.h"
9
#include "lib/tls/tortls_st.h"
10
#include "lib/tls/tortls_internal.h"
11
12
#include "lib/log/util_bug.h"
#include "lib/intmath/cmp.h"
Ola Bini's avatar
Ola Bini committed
13

14
/** Global TLS contexts. We keep them here because nobody else needs
Nick Mathewson's avatar
Nick Mathewson committed
15
16
17
 * to touch them.
 *
 * @{ */
Ola Bini's avatar
Ola Bini committed
18
19
STATIC tor_tls_context_t *server_tls_context = NULL;
STATIC tor_tls_context_t *client_tls_context = NULL;
Nick Mathewson's avatar
Nick Mathewson committed
20
/**@}*/
21

22
23
24
25
26
/**
 * Return the appropriate TLS context.
 */
tor_tls_context_t *
tor_tls_context_get(int is_server)
27
{
28
  return is_server ? server_tls_context : client_tls_context;
29
30
}

31
/** Increase the reference count of <b>ctx</b>. */
32
void
33
tor_tls_context_incref(tor_tls_context_t *ctx)
34
{
35
  ++ctx->refcnt;
36
37
}

38
/** Free all global TLS structures. */
39
void
40
tor_tls_free_all(void)
Nick Mathewson's avatar
Nick Mathewson committed
41
{
42
  check_no_tls_errors();
43

44
45
46
47
  if (server_tls_context) {
    tor_tls_context_t *ctx = server_tls_context;
    server_tls_context = NULL;
    tor_tls_context_decref(ctx);
Nick Mathewson's avatar
Nick Mathewson committed
48
  }
49
50
51
52
  if (client_tls_context) {
    tor_tls_context_t *ctx = client_tls_context;
    client_tls_context = NULL;
    tor_tls_context_decref(ctx);
53
54
55
  }
}

56
/** Given a TOR_TLS_* error code, return a string equivalent. */
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
const char *
tor_tls_err_to_string(int err)
{
  if (err >= 0)
    return "[Not an error.]";
  switch (err) {
    case TOR_TLS_ERROR_MISC: return "misc error";
    case TOR_TLS_ERROR_IO: return "unexpected close";
    case TOR_TLS_ERROR_CONNREFUSED: return "connection refused";
    case TOR_TLS_ERROR_CONNRESET: return "connection reset";
    case TOR_TLS_ERROR_NO_ROUTE: return "host unreachable";
    case TOR_TLS_ERROR_TIMEOUT: return "connection timed out";
    case TOR_TLS_CLOSE: return "closed";
    case TOR_TLS_WANTREAD: return "want to read";
    case TOR_TLS_WANTWRITE: return "want to write";
    default: return "(unknown error code)";
  }
}

76
77
78
/** Create new global client and server TLS contexts.
 *
 * If <b>server_identity</b> is NULL, this will not generate a server
79
 * TLS context. If TOR_TLS_CTX_IS_PUBLIC_SERVER is set in <b>flags</b>, use
80
 * the same TLS context for incoming and outgoing connections, and
81
82
83
 * ignore <b>client_identity</b>. If one of TOR_TLS_CTX_USE_ECDHE_P{224,256}
 * is set in <b>flags</b>, use that ECDHE group if possible; otherwise use
 * the default ECDHE group. */
84
int
85
tor_tls_context_init(unsigned flags,
86
87
                     crypto_pk_t *client_identity,
                     crypto_pk_t *server_identity,
88
89
90
91
                     unsigned int key_lifetime)
{
  int rv1 = 0;
  int rv2 = 0;
92
  const int is_public_server = flags & TOR_TLS_CTX_IS_PUBLIC_SERVER;
93
  check_no_tls_errors();
94
95
96
97
98
99
100
101
102

  if (is_public_server) {
    tor_tls_context_t *new_ctx;
    tor_tls_context_t *old_ctx;

    tor_assert(server_identity != NULL);

    rv1 = tor_tls_context_init_one(&server_tls_context,
                                   server_identity,
103
                                   key_lifetime, flags, 0);
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

    if (rv1 >= 0) {
      new_ctx = server_tls_context;
      tor_tls_context_incref(new_ctx);
      old_ctx = client_tls_context;
      client_tls_context = new_ctx;

      if (old_ctx != NULL) {
        tor_tls_context_decref(old_ctx);
      }
    }
  } else {
    if (server_identity != NULL) {
      rv1 = tor_tls_context_init_one(&server_tls_context,
                                     server_identity,
119
                                     key_lifetime,
120
                                     flags,
121
                                     0);
122
123
124
125
126
127
128
129
130
131
132
    } else {
      tor_tls_context_t *old_ctx = server_tls_context;
      server_tls_context = NULL;

      if (old_ctx != NULL) {
        tor_tls_context_decref(old_ctx);
      }
    }

    rv2 = tor_tls_context_init_one(&client_tls_context,
                                   client_identity,
133
                                   key_lifetime,
134
                                   flags,
135
                                   1);
136
137
  }

138
  tls_log_errors(NULL, LOG_WARN, LD_CRYPTO, "constructing a TLS context");
139
140
141
  return MIN(rv1, rv2);
}

142
143
144
145
146
147
148
149
150
151
152
/** Make future log messages about <b>tls</b> display the address
 * <b>address</b>.
 */
void
tor_tls_set_logged_address(tor_tls_t *tls, const char *address)
{
  tor_assert(tls);
  tor_free(tls->address);
  tls->address = tor_strdup(address);
}

153
154
155
/** Return whether this tls initiated the connect (client) or
 * received it (server). */
int
156
tor_tls_is_server(tor_tls_t *tls)
157
158
159
160
{
  tor_assert(tls);
  return tls->isServer;
}