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 */
8 * \file crypto_openssl_mgt.c
10 * \brief Block of functions related to operations from OpenSSL.
13 #include "lib/crypt_ops/compat_openssl.h"
14 #include "lib/crypt_ops/crypto_openssl_mgt.h"
15 #include "lib/crypt_ops/crypto_rand.h"
16 #include "lib/crypt_ops/aes.h"
17 #include "lib/string/util_string.h"
18 #include "lib/lock/compat_mutex.h"
19 #include "lib/log/log.h"
20 #include "lib/log/util_bug.h"
21 #include "lib/testsupport/testsupport.h"
22 #include "lib/thread/threads.h"
24 DISABLE_GCC_WARNING("-Wredundant-decls")
26 #include <openssl/err.h>
27 #include <openssl/rsa.h>
28 #include <openssl/pem.h>
29 #include <openssl/evp.h>
30 #include <openssl/engine.h>
31 #include <openssl/rand.h>
32 #include <openssl/bn.h>
33 #include <openssl/dh.h>
34 #include <openssl/conf.h>
35 #include <openssl/hmac.h>
36 #include <openssl/crypto.h>
37 #include <openssl/ssl.h>
39 ENABLE_GCC_WARNING("-Wredundant-decls")
43 #ifndef NEW_THREAD_API
44 /** A number of preallocated mutexes for use by OpenSSL. */
45 static tor_mutex_t
**openssl_mutexes_
= NULL
;
46 /** How many mutexes have we allocated for use by OpenSSL? */
47 static int n_openssl_mutexes_
= 0;
48 #endif /* !defined(NEW_THREAD_API) */
50 /** Declare STATIC functions */
51 STATIC
char * parse_openssl_version_str(const char *raw_version
);
52 #ifndef NEW_THREAD_API
53 STATIC
void openssl_locking_cb_(int mode
, int n
, const char *file
, int line
);
54 STATIC
void tor_set_openssl_thread_id(CRYPTO_THREADID
*threadid
);
57 /** Log all pending crypto errors at level <b>severity</b>. Use
58 * <b>doing</b> to describe our current activities.
61 crypto_openssl_log_errors(int severity
, const char *doing
)
64 const char *msg
, *lib
, *func
;
65 while ((err
= ERR_get_error()) != 0) {
66 msg
= (const char*)ERR_reason_error_string(err
);
67 lib
= (const char*)ERR_lib_error_string(err
);
68 func
= (const char*)ERR_func_error_string(err
);
69 if (!msg
) msg
= "(null)";
70 if (!lib
) lib
= "(null)";
71 if (!func
) func
= "(null)";
72 if (BUG(!doing
)) doing
= "(null)";
73 tor_log(severity
, LD_CRYPTO
, "crypto error while %s: %s (in %s:%s)",
74 doing
, msg
, lib
, func
);
78 /* Returns a trimmed and human-readable version of an openssl version string
79 * <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10
80 * May 2012' and this will parse them into a form similar to '1.0.0b' */
82 parse_openssl_version_str(const char *raw_version
)
84 const char *end_of_version
= NULL
;
85 /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's
87 if (!strcmpstart(raw_version
, "OpenSSL ")) {
88 raw_version
+= strlen("OpenSSL ");
89 end_of_version
= strchr(raw_version
, ' ');
93 return tor_strndup(raw_version
,
94 end_of_version
-raw_version
);
96 return tor_strdup(raw_version
);
99 static char *crypto_openssl_version_str
= NULL
;
100 /* Return a human-readable version of the run-time openssl version number. */
102 crypto_openssl_get_version_str(void)
104 #ifdef OPENSSL_VERSION
105 const int query
= OPENSSL_VERSION
;
107 /* This old name was changed around OpenSSL 1.1.0 */
108 const int query
= SSLEAY_VERSION
;
109 #endif /* defined(OPENSSL_VERSION) */
111 if (crypto_openssl_version_str
== NULL
) {
112 const char *raw_version
= OpenSSL_version(query
);
113 crypto_openssl_version_str
= parse_openssl_version_str(raw_version
);
115 return crypto_openssl_version_str
;
118 #undef QUERY_OPENSSL_VERSION
120 static char *crypto_openssl_header_version_str
= NULL
;
121 /* Return a human-readable version of the compile-time openssl version
124 crypto_openssl_get_header_version_str(void)
126 if (crypto_openssl_header_version_str
== NULL
) {
127 crypto_openssl_header_version_str
=
128 parse_openssl_version_str(OPENSSL_VERSION_TEXT
);
130 return crypto_openssl_header_version_str
;
134 #ifndef OPENSSL_THREADS
135 #error "OpenSSL has been built without thread support. Tor requires an \
136 OpenSSL library with thread support enabled."
138 #endif /* !defined(COCCI) */
140 #ifndef NEW_THREAD_API
141 /** Helper: OpenSSL uses this callback to manipulate mutexes. */
143 openssl_locking_cb_(int mode
, int n
, const char *file
, int line
)
147 if (!openssl_mutexes_
)
148 /* This is not a really good fix for the
149 * "release-freed-lock-from-separate-thread-on-shutdown" problem, but
152 if (mode
& CRYPTO_LOCK
)
153 tor_mutex_acquire(openssl_mutexes_
[n
]);
155 tor_mutex_release(openssl_mutexes_
[n
]);
159 tor_set_openssl_thread_id(CRYPTO_THREADID
*threadid
)
161 CRYPTO_THREADID_set_numeric(threadid
, tor_get_thread_id());
163 #endif /* !defined(NEW_THREAD_API) */
165 /** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
166 * multithreaded. Returns 0. */
168 setup_openssl_threading(void)
170 #ifndef NEW_THREAD_API
172 int n
= CRYPTO_num_locks();
173 n_openssl_mutexes_
= n
;
174 openssl_mutexes_
= tor_calloc(n
, sizeof(tor_mutex_t
*));
175 for (i
=0; i
< n
; ++i
)
176 openssl_mutexes_
[i
] = tor_mutex_new();
177 CRYPTO_set_locking_callback(openssl_locking_cb_
);
178 CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id
);
179 #endif /* !defined(NEW_THREAD_API) */
183 /** free OpenSSL variables */
185 crypto_openssl_free_all(void)
187 tor_free(crypto_openssl_version_str
);
188 tor_free(crypto_openssl_header_version_str
);
190 /* Destroying a locked mutex is undefined behaviour. This mutex may be
191 * locked, because multiple threads can access it. But we need to destroy
192 * it, otherwise re-initialisation will trigger undefined behaviour.
193 * See #31735 for details. */
194 #ifndef NEW_THREAD_API
195 if (n_openssl_mutexes_
) {
196 int n
= n_openssl_mutexes_
;
197 tor_mutex_t
**ms
= openssl_mutexes_
;
199 openssl_mutexes_
= NULL
;
200 n_openssl_mutexes_
= 0;
202 tor_mutex_free(ms
[i
]);
206 #endif /* !defined(NEW_THREAD_API) */
209 /** Perform early (pre-configuration) initialization tasks for OpenSSL. */
211 crypto_openssl_early_init(void)
213 #ifdef OPENSSL_1_1_API
214 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
215 OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
216 OPENSSL_INIT_ADD_ALL_CIPHERS
|
217 OPENSSL_INIT_ADD_ALL_DIGESTS
, NULL
);
218 #else /* !defined(OPENSSL_1_1_API) */
219 ERR_load_crypto_strings();
220 OpenSSL_add_all_algorithms();
221 #endif /* defined(OPENSSL_1_1_API) */
223 setup_openssl_threading();
225 unsigned long version_num
= tor_OpenSSL_version_num();
226 const char *version_str
= crypto_openssl_get_version_str();
227 if (version_num
== OPENSSL_VERSION_NUMBER
&&
228 !strcmp(version_str
, OPENSSL_VERSION_TEXT
)) {
229 log_info(LD_CRYPTO
, "OpenSSL version matches version from headers "
230 "(%lx: %s).", version_num
, version_str
);
231 } else if ((version_num
& 0xffff0000) ==
232 (OPENSSL_VERSION_NUMBER
& 0xffff0000)) {
233 log_notice(LD_CRYPTO
,
234 "We compiled with OpenSSL %lx: %s and we "
235 "are running with OpenSSL %lx: %s. "
236 "These two versions should be binary compatible.",
237 (unsigned long)OPENSSL_VERSION_NUMBER
, OPENSSL_VERSION_TEXT
,
238 version_num
, version_str
);
240 log_warn(LD_CRYPTO
, "OpenSSL version from headers does not match the "
241 "version we're running with. If you get weird crashes, that "
242 "might be why. (Compiled with %lx: %s; running with %lx: %s).",
243 (unsigned long)OPENSSL_VERSION_NUMBER
, OPENSSL_VERSION_TEXT
,
244 version_num
, version_str
);
247 crypto_force_rand_ssleay();
250 #ifndef DISABLE_ENGINES
251 /** Try to load an engine in a shared library via fully qualified path.
254 try_load_engine(const char *path
, const char *engine
)
256 ENGINE
*e
= ENGINE_by_id("dynamic");
258 if (!ENGINE_ctrl_cmd_string(e
, "ID", engine
, 0) ||
259 !ENGINE_ctrl_cmd_string(e
, "DIR_LOAD", "2", 0) ||
260 !ENGINE_ctrl_cmd_string(e
, "DIR_ADD", path
, 0) ||
261 !ENGINE_ctrl_cmd_string(e
, "LOAD", NULL
, 0)) {
268 #endif /* !defined(DISABLE_ENGINES) */
270 #ifndef DISABLE_ENGINES
271 /** Log any OpenSSL engines we're using at NOTICE. */
273 log_engine(const char *fn
, ENGINE
*e
)
276 const char *name
, *id
;
277 name
= ENGINE_get_name(e
);
278 id
= ENGINE_get_id(e
);
279 log_notice(LD_CRYPTO
, "Default OpenSSL engine for %s is %s [%s]",
280 fn
, name
?name
:"?", id
?id
:"?");
282 log_info(LD_CRYPTO
, "Using default implementation for %s", fn
);
285 #endif /* !defined(DISABLE_ENGINES) */
287 /** Initialize engines for openssl (if enabled). Load all the built-in
288 * engines, along with the one called <b>accelName</b> (which may be NULL).
289 * If <b>accelName</b> is prefixed with "!", then it is required: return -1
290 * if it can't be loaded. Otherwise return 0.
292 * If <b>accelDir</b> is not NULL, it is the path from which the engine should
295 crypto_openssl_init_engines(const char *accelName
,
296 const char *accelDir
)
298 #ifdef DISABLE_ENGINES
301 log_warn(LD_CRYPTO
, "No OpenSSL hardware acceleration support enabled.");
302 if (accelName
&& accelName
[0] == '!') {
303 log_warn(LD_CRYPTO
, "Unable to load required dynamic OpenSSL engine "
304 "\"%s\".", accelName
+1);
308 #else /* !defined(DISABLE_ENGINES) */
311 log_info(LD_CRYPTO
, "Initializing OpenSSL engine support.");
312 ENGINE_load_builtin_engines();
313 ENGINE_register_all_complete();
316 const bool required
= accelName
[0] == '!';
320 log_info(LD_CRYPTO
, "Trying to load dynamic OpenSSL engine \"%s\""
321 " via path \"%s\".", accelName
, accelDir
);
322 e
= try_load_engine(accelName
, accelDir
);
324 log_info(LD_CRYPTO
, "Initializing dynamic OpenSSL engine \"%s\""
325 " acceleration support.", accelName
);
326 e
= ENGINE_by_id(accelName
);
329 log_warn(LD_CRYPTO
, "Unable to load %sdynamic OpenSSL engine \"%s\".",
330 required
?"required ":"",
335 log_info(LD_CRYPTO
, "Loaded dynamic OpenSSL engine \"%s\".",
340 log_info(LD_CRYPTO
, "Loaded OpenSSL hardware acceleration engine,"
341 " setting default ciphers.");
342 ENGINE_set_default(e
, ENGINE_METHOD_ALL
);
344 /* Log, if available, the intersection of the set of algorithms
345 used by Tor and the set of algorithms available in the engine */
346 log_engine("RSA", ENGINE_get_default_RSA());
347 log_engine("DH", ENGINE_get_default_DH());
348 #ifdef OPENSSL_1_1_API
349 log_engine("EC", ENGINE_get_default_EC());
351 log_engine("ECDH", ENGINE_get_default_ECDH());
352 log_engine("ECDSA", ENGINE_get_default_ECDSA());
353 #endif /* defined(OPENSSL_1_1_API) */
354 log_engine("RAND", ENGINE_get_default_RAND());
355 log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
356 log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1
));
357 log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc
));
358 log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb
));
359 log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc
));
360 #ifdef NID_aes_128_ctr
361 log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr
));
363 #ifdef NID_aes_128_gcm
364 log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm
));
366 log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc
));
367 #ifdef NID_aes_256_gcm
368 log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm
));
372 #endif /* defined(DISABLE_ENGINES) */
375 /** Perform late (post-init) initialization tasks for OpenSSL */
377 crypto_openssl_late_init(int useAccel
, const char *accelName
,
378 const char *accelDir
)
381 if (crypto_openssl_init_engines(accelName
, accelDir
) < 0)
384 log_info(LD_CRYPTO
, "NOT using OpenSSL engine support.");
387 if (crypto_force_rand_ssleay()) {
388 if (crypto_seed_rng() < 0)
392 evaluate_evp_for_aes(-1);
393 evaluate_ctr_for_aes();
398 /** Free crypto resources held by this thread. */
400 crypto_openssl_thread_cleanup(void)
402 #ifndef NEW_THREAD_API
403 ERR_remove_thread_state(NULL
);
407 /** Clean up global resources held by openssl. */
409 crypto_openssl_global_cleanup(void)
411 #ifndef OPENSSL_1_1_API
414 #ifndef NEW_THREAD_API
415 ERR_remove_thread_state(NULL
);
417 #ifndef OPENSSL_1_1_API
421 #ifndef DISABLE_ENGINES
422 #ifndef OPENSSL_1_1_API
427 CONF_modules_unload(1);
428 #ifndef OPENSSL_1_1_API
429 CRYPTO_cleanup_all_ex_data();
432 crypto_openssl_free_all();