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 */
8 * @brief Shared functionality for our TLS backends.
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"
33 /** Global TLS contexts. We keep them here because nobody else needs
37 STATIC tor_tls_context_t
*server_tls_context
= NULL
;
38 STATIC tor_tls_context_t
*client_tls_context
= NULL
;
42 * Return the appropriate TLS context.
45 tor_tls_context_get(int is_server
)
47 return is_server
? server_tls_context
: client_tls_context
;
50 /** Convert an errno (or a WSAerrno on windows) into a TOR_TLS_* error
53 tor_errno_to_tls_error(int 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
66 return TOR_TLS_ERROR_MISC
;
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) */
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
)
80 tor_tls_context_t
*ctx
= tor_tls_context_get(server
);
82 const tor_x509_cert_t
*link_cert
= NULL
;
83 const tor_x509_cert_t
*id_cert
= NULL
;
86 link_cert
= server
? ctx
->my_link_cert
: ctx
->my_auth_cert
;
87 id_cert
= ctx
->my_id_cert
;
90 *link_cert_out
= link_cert
;
92 *id_cert_out
= id_cert
;
97 * Return the authentication key that we use to authenticate ourselves as a
98 * client in the V3 in-protocol handshake.
101 tor_tls_get_my_client_auth_key(void)
103 tor_tls_context_t
*context
= tor_tls_context_get(0);
106 return context
->auth_key
;
109 /** Increase the reference count of <b>ctx</b>. */
111 tor_tls_context_incref(tor_tls_context_t
*ctx
)
116 /** Remove a reference to <b>ctx</b>, and free it if it has no more
119 tor_tls_context_decref(tor_tls_context_t
*ctx
)
122 if (--ctx
->refcnt
== 0) {
123 tor_tls_context_impl_free(ctx
->ctx
);
124 tor_x509_cert_free(ctx
->my_link_cert
);
125 tor_x509_cert_free(ctx
->my_id_cert
);
126 tor_x509_cert_free(ctx
->my_auth_cert
);
127 crypto_pk_free(ctx
->link_key
);
128 crypto_pk_free(ctx
->auth_key
);
129 /* LCOV_EXCL_BR_START since ctx will never be NULL here */
131 /* LCOV_EXCL_BR_STOP */
135 /** Free all global TLS structures. */
137 tor_tls_free_all(void)
139 check_no_tls_errors();
141 if (server_tls_context
) {
142 tor_tls_context_t
*ctx
= server_tls_context
;
143 server_tls_context
= NULL
;
144 tor_tls_context_decref(ctx
);
146 if (client_tls_context
) {
147 tor_tls_context_t
*ctx
= client_tls_context
;
148 client_tls_context
= NULL
;
149 tor_tls_context_decref(ctx
);
153 /** Given a TOR_TLS_* error code, return a string equivalent. */
155 tor_tls_err_to_string(int err
)
158 return "[Not an error.]";
160 case TOR_TLS_ERROR_MISC
: return "misc error";
161 case TOR_TLS_ERROR_IO
: return "unexpected close";
162 case TOR_TLS_ERROR_CONNREFUSED
: return "connection refused";
163 case TOR_TLS_ERROR_CONNRESET
: return "connection reset";
164 case TOR_TLS_ERROR_NO_ROUTE
: return "host unreachable";
165 case TOR_TLS_ERROR_TIMEOUT
: return "connection timed out";
166 case TOR_TLS_CLOSE
: return "closed";
167 case TOR_TLS_WANTREAD
: return "want to read";
168 case TOR_TLS_WANTWRITE
: return "want to write";
169 default: return "(unknown error code)";
173 /** Create new global client and server TLS contexts.
175 * If <b>server_identity</b> is NULL, this will not generate a server
176 * TLS context. If TOR_TLS_CTX_IS_PUBLIC_SERVER is set in <b>flags</b>, use
177 * the same TLS context for incoming and outgoing connections, and
178 * ignore <b>client_identity</b>. If one of TOR_TLS_CTX_USE_ECDHE_P{224,256}
179 * is set in <b>flags</b>, use that ECDHE group if possible; otherwise use
180 * the default ECDHE group. */
182 tor_tls_context_init(unsigned flags
,
183 crypto_pk_t
*client_identity
,
184 crypto_pk_t
*server_identity
,
185 unsigned int key_lifetime
)
189 const int is_public_server
= flags
& TOR_TLS_CTX_IS_PUBLIC_SERVER
;
190 check_no_tls_errors();
192 if (is_public_server
) {
193 tor_tls_context_t
*new_ctx
;
194 tor_tls_context_t
*old_ctx
;
196 tor_assert(server_identity
!= NULL
);
198 rv1
= tor_tls_context_init_one(&server_tls_context
,
200 key_lifetime
, flags
, 0);
203 new_ctx
= server_tls_context
;
204 tor_tls_context_incref(new_ctx
);
205 old_ctx
= client_tls_context
;
206 client_tls_context
= new_ctx
;
208 if (old_ctx
!= NULL
) {
209 tor_tls_context_decref(old_ctx
);
212 tls_log_errors(NULL
, LOG_WARN
, LD_CRYPTO
,
213 "constructing a TLS context");
216 if (server_identity
!= NULL
) {
217 rv1
= tor_tls_context_init_one(&server_tls_context
,
223 tls_log_errors(NULL
, LOG_WARN
, LD_CRYPTO
,
224 "constructing a server TLS context");
226 tor_tls_context_t
*old_ctx
= server_tls_context
;
227 server_tls_context
= NULL
;
229 if (old_ctx
!= NULL
) {
230 tor_tls_context_decref(old_ctx
);
234 rv2
= tor_tls_context_init_one(&client_tls_context
,
240 tls_log_errors(NULL
, LOG_WARN
, LD_CRYPTO
,
241 "constructing a client TLS context");
244 return MIN(rv1
, rv2
);
247 /** Create a new global TLS context.
249 * You can call this function multiple times. Each time you call it,
250 * it generates new certificates; all new connections will use
251 * the new SSL context.
254 tor_tls_context_init_one(tor_tls_context_t
**ppcontext
,
255 crypto_pk_t
*identity
,
256 unsigned int key_lifetime
,
260 tor_tls_context_t
*new_ctx
= tor_tls_context_new(identity
,
264 tor_tls_context_t
*old_ctx
= *ppcontext
;
266 if (new_ctx
!= NULL
) {
267 *ppcontext
= new_ctx
;
269 /* Free the old context if one existed. */
270 if (old_ctx
!= NULL
) {
271 /* This is safe even if there are open connections: we reference-
272 * count tor_tls_context_t objects. */
273 tor_tls_context_decref(old_ctx
);
277 return ((new_ctx
!= NULL
) ? 0 : -1);
280 /** Size of the RSA key to use for our TLS link keys */
281 #define RSA_LINK_KEY_BITS 2048
283 /** How long do identity certificates live? (sec) */
284 #define IDENTITY_CERT_LIFETIME (365*24*60*60)
287 * Initialize the certificates and keys for a TLS context <b>result</b>
289 * Other arguments as for tor_tls_context_new().
292 tor_tls_context_init_certificates(tor_tls_context_t
*result
,
293 crypto_pk_t
*identity
,
294 unsigned key_lifetime
,
299 char *nickname
= NULL
, *nn2
= NULL
;
300 crypto_pk_t
*rsa
= NULL
, *rsa_auth
= NULL
;
301 tor_x509_cert_impl_t
*cert
= NULL
, *idcert
= NULL
, *authcert
= NULL
;
303 nickname
= crypto_random_hostname(8, 20, "www.", ".net");
305 #ifdef DISABLE_V3_LINKPROTO_SERVERSIDE
306 nn2
= crypto_random_hostname(8, 20, "www.", ".net");
308 nn2
= crypto_random_hostname(8, 20, "www.", ".com");
311 /* Generate short-term RSA key for use with TLS. */
312 if (!(rsa
= crypto_pk_new()))
314 if (crypto_pk_generate_key_with_bits(rsa
, RSA_LINK_KEY_BITS
)<0)
317 /* Generate short-term RSA key for use in the in-protocol ("v3")
318 * authentication handshake. */
319 if (!(rsa_auth
= crypto_pk_new()))
321 if (crypto_pk_generate_key(rsa_auth
)<0)
324 /* Create a link certificate signed by identity key. */
325 cert
= tor_tls_create_certificate(rsa
, identity
, nickname
, nn2
,
327 /* Create self-signed certificate for identity key. */
328 idcert
= tor_tls_create_certificate(identity
, identity
, nn2
, nn2
,
329 IDENTITY_CERT_LIFETIME
);
330 /* Create an authentication certificate signed by identity key. */
331 authcert
= tor_tls_create_certificate(rsa_auth
, identity
, nickname
, nn2
,
333 if (!cert
|| !idcert
|| !authcert
) {
334 log_warn(LD_CRYPTO
, "Error creating certificate");
338 result
->my_link_cert
= tor_x509_cert_new(cert
);
340 result
->my_id_cert
= tor_x509_cert_new(idcert
);
342 result
->my_auth_cert
= tor_x509_cert_new(authcert
);
344 if (!result
->my_link_cert
|| !result
->my_id_cert
|| !result
->my_auth_cert
)
346 result
->link_key
= rsa
;
348 result
->auth_key
= rsa_auth
;
357 tor_x509_cert_impl_free(cert
);
358 tor_x509_cert_impl_free(idcert
);
359 tor_x509_cert_impl_free(authcert
);
361 crypto_pk_free(rsa_auth
);
365 /** Make future log messages about <b>tls</b> display the address
369 tor_tls_set_logged_address(tor_tls_t
*tls
, const char *address
)
372 tor_free(tls
->address
);
373 tls
->address
= tor_strdup(address
);
376 /** Return whether this tls initiated the connect (client) or
377 * received it (server). */
379 tor_tls_is_server(tor_tls_t
*tls
)
382 return tls
->isServer
;
385 /** Release resources associated with a TLS object. Does not close the
386 * underlying file descriptor.
389 tor_tls_free_(tor_tls_t
*tls
)
393 tor_assert(tls
->ssl
);
396 tor_tls_get_n_raw_bytes(tls
,&r
,&w
); /* ensure written_by_tls is updated */
398 tor_tls_impl_free(tls
->ssl
);
400 #ifdef ENABLE_OPENSSL
401 tls
->negotiated_callback
= NULL
;
404 tor_tls_context_decref(tls
->context
);
405 tor_free(tls
->address
);
406 tls
->magic
= 0x99999999;
410 /** If the provided tls connection is authenticated and has a
411 * certificate chain that is currently valid and signed, then set
412 * *<b>identity_key</b> to the identity certificate's key and return
413 * 0. Else, return -1 and log complaints with log-level <b>severity</b>.
416 tor_tls_verify(int severity
, tor_tls_t
*tls
, crypto_pk_t
**identity
)
418 tor_x509_cert_impl_t
*cert
= NULL
, *id_cert
= NULL
;
419 tor_x509_cert_t
*peer_x509
= NULL
, *id_x509
= NULL
;
421 tor_assert(identity
);
424 try_to_extract_certs_from_tls(severity
, tls
, &cert
, &id_cert
);
428 log_fn(severity
,LD_PROTOCOL
,"No distinct identity certificate found");
431 peer_x509
= tor_x509_cert_new(cert
);
432 id_x509
= tor_x509_cert_new(id_cert
);
433 cert
= id_cert
= NULL
; /* Prevent double-free */
435 if (! tor_tls_cert_is_valid(severity
, peer_x509
, id_x509
, time(NULL
), 0)) {
439 *identity
= tor_tls_cert_get_key(id_x509
);
443 tor_x509_cert_impl_free(cert
);
444 tor_x509_cert_impl_free(id_cert
);
445 tor_x509_cert_free(peer_x509
);
446 tor_x509_cert_free(id_x509
);
452 subsys_tortls_shutdown(void)
457 const subsys_fns_t sys_tortls
= {
459 SUBSYS_DECLARE_LOCATION(),
461 .shutdown
= subsys_tortls_shutdown