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 crypto_openssl_mgt.c
9 : *
10 : * \brief Block of functions related to operations from OpenSSL.
11 : **/
12 :
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"
23 :
24 : DISABLE_GCC_WARNING("-Wredundant-decls")
25 :
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>
38 :
39 : ENABLE_GCC_WARNING("-Wredundant-decls")
40 :
41 : #include <string.h>
42 :
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) */
49 :
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);
55 : #endif
56 :
57 : /** Log all pending crypto errors at level <b>severity</b>. Use
58 : * <b>doing</b> to describe our current activities.
59 : */
60 : void
61 49 : crypto_openssl_log_errors(int severity, const char *doing)
62 : {
63 49 : unsigned long err;
64 49 : const char *msg, *lib, *func;
65 95 : while ((err = ERR_get_error()) != 0) {
66 46 : msg = (const char*)ERR_reason_error_string(err);
67 46 : lib = (const char*)ERR_lib_error_string(err);
68 46 : func = (const char*)ERR_func_error_string(err);
69 46 : if (!msg) msg = "(null)";
70 46 : if (!lib) lib = "(null)";
71 46 : if (!func) func = "(null)";
72 46 : if (BUG(!doing)) doing = "(null)";
73 46 : tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
74 : doing, msg, lib, func);
75 : }
76 49 : }
77 :
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' */
81 : STATIC char *
82 5562 : parse_openssl_version_str(const char *raw_version)
83 : {
84 5562 : const char *end_of_version = NULL;
85 : /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's
86 : trim that down. */
87 5562 : if (!strcmpstart(raw_version, "OpenSSL ")) {
88 5562 : raw_version += strlen("OpenSSL ");
89 5562 : end_of_version = strchr(raw_version, ' ');
90 : }
91 :
92 5562 : if (end_of_version)
93 5562 : return tor_strndup(raw_version,
94 : end_of_version-raw_version);
95 : else
96 0 : return tor_strdup(raw_version);
97 : }
98 :
99 : static char *crypto_openssl_version_str = NULL;
100 : /* Return a human-readable version of the run-time openssl version number. */
101 : const char *
102 5797 : crypto_openssl_get_version_str(void)
103 : {
104 : #ifdef OPENSSL_VERSION
105 5797 : const int query = OPENSSL_VERSION;
106 : #else
107 : /* This old name was changed around OpenSSL 1.1.0 */
108 : const int query = SSLEAY_VERSION;
109 : #endif /* defined(OPENSSL_VERSION) */
110 :
111 5797 : if (crypto_openssl_version_str == NULL) {
112 5561 : const char *raw_version = OpenSSL_version(query);
113 5561 : crypto_openssl_version_str = parse_openssl_version_str(raw_version);
114 : }
115 5797 : return crypto_openssl_version_str;
116 : }
117 :
118 : #undef QUERY_OPENSSL_VERSION
119 :
120 : static char *crypto_openssl_header_version_str = NULL;
121 : /* Return a human-readable version of the compile-time openssl version
122 : * number. */
123 : const char *
124 1 : crypto_openssl_get_header_version_str(void)
125 : {
126 1 : if (crypto_openssl_header_version_str == NULL) {
127 1 : crypto_openssl_header_version_str =
128 1 : parse_openssl_version_str(OPENSSL_VERSION_TEXT);
129 : }
130 1 : return crypto_openssl_header_version_str;
131 : }
132 :
133 : #ifndef COCCI
134 : #ifndef OPENSSL_THREADS
135 : #error "OpenSSL has been built without thread support. Tor requires an \
136 : OpenSSL library with thread support enabled."
137 : #endif
138 : #endif /* !defined(COCCI) */
139 :
140 : #ifndef NEW_THREAD_API
141 : /** Helper: OpenSSL uses this callback to manipulate mutexes. */
142 : STATIC void
143 : openssl_locking_cb_(int mode, int n, const char *file, int line)
144 : {
145 : (void)file;
146 : (void)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
150 : * it can't hurt. */
151 : return;
152 : if (mode & CRYPTO_LOCK)
153 : tor_mutex_acquire(openssl_mutexes_[n]);
154 : else
155 : tor_mutex_release(openssl_mutexes_[n]);
156 : }
157 :
158 : STATIC void
159 : tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
160 : {
161 : CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id());
162 : }
163 : #endif /* !defined(NEW_THREAD_API) */
164 :
165 : /** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
166 : * multithreaded. Returns 0. */
167 : static int
168 : setup_openssl_threading(void)
169 : {
170 : #ifndef NEW_THREAD_API
171 : int i;
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) */
180 : return 0;
181 : }
182 :
183 : /** free OpenSSL variables */
184 : static void
185 235 : crypto_openssl_free_all(void)
186 : {
187 235 : tor_free(crypto_openssl_version_str);
188 235 : tor_free(crypto_openssl_header_version_str);
189 :
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_;
198 : int i;
199 : openssl_mutexes_ = NULL;
200 : n_openssl_mutexes_ = 0;
201 : for (i=0;i<n;++i) {
202 : tor_mutex_free(ms[i]);
203 : }
204 : tor_free(ms);
205 : }
206 : #endif /* !defined(NEW_THREAD_API) */
207 235 : }
208 :
209 : /** Perform early (pre-configuration) initialization tasks for OpenSSL. */
210 : void
211 5561 : crypto_openssl_early_init(void)
212 : {
213 : #ifdef OPENSSL_1_1_API
214 5561 : 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) */
222 :
223 5561 : setup_openssl_threading();
224 :
225 5561 : unsigned long version_num = tor_OpenSSL_version_num();
226 5561 : const char *version_str = crypto_openssl_get_version_str();
227 5561 : if (version_num == OPENSSL_VERSION_NUMBER &&
228 5561 : !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
229 0 : log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
230 : "(%lx: %s).", version_num, version_str);
231 5561 : } else if ((version_num & 0xffff0000) ==
232 : (OPENSSL_VERSION_NUMBER & 0xffff0000)) {
233 5561 : 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);
239 : } else {
240 0 : 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);
245 : }
246 :
247 5561 : crypto_force_rand_ssleay();
248 5561 : }
249 :
250 : #ifndef DISABLE_ENGINES
251 : /** Try to load an engine in a shared library via fully qualified path.
252 : */
253 : static ENGINE *
254 0 : try_load_engine(const char *path, const char *engine)
255 : {
256 0 : ENGINE *e = ENGINE_by_id("dynamic");
257 0 : if (e) {
258 0 : if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
259 0 : !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
260 0 : !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
261 0 : !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
262 0 : ENGINE_free(e);
263 0 : e = NULL;
264 : }
265 : }
266 0 : return e;
267 : }
268 : #endif /* !defined(DISABLE_ENGINES) */
269 :
270 : #ifndef DISABLE_ENGINES
271 : /** Log any OpenSSL engines we're using at NOTICE. */
272 : static void
273 130 : log_engine(const char *fn, ENGINE *e)
274 : {
275 130 : if (e) {
276 0 : const char *name, *id;
277 0 : name = ENGINE_get_name(e);
278 0 : id = ENGINE_get_id(e);
279 0 : log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
280 : fn, name?name:"?", id?id:"?");
281 : } else {
282 130 : log_info(LD_CRYPTO, "Using default implementation for %s", fn);
283 : }
284 130 : }
285 : #endif /* !defined(DISABLE_ENGINES) */
286 :
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.
291 : *
292 : * If <b>accelDir</b> is not NULL, it is the path from which the engine should
293 : * be loaded. */
294 : static int
295 11 : crypto_openssl_init_engines(const char *accelName,
296 : const char *accelDir)
297 : {
298 : #ifdef DISABLE_ENGINES
299 : (void)accelName;
300 : (void)accelDir;
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);
305 : return -1;
306 : }
307 : return 0;
308 : #else /* !defined(DISABLE_ENGINES) */
309 11 : ENGINE *e = NULL;
310 :
311 11 : log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
312 11 : ENGINE_load_builtin_engines();
313 11 : ENGINE_register_all_complete();
314 :
315 11 : if (accelName) {
316 4 : const bool required = accelName[0] == '!';
317 4 : if (required)
318 1 : ++accelName;
319 4 : if (accelDir) {
320 0 : log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
321 : " via path \"%s\".", accelName, accelDir);
322 0 : e = try_load_engine(accelName, accelDir);
323 : } else {
324 4 : log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
325 : " acceleration support.", accelName);
326 4 : e = ENGINE_by_id(accelName);
327 : }
328 4 : if (!e) {
329 7 : log_warn(LD_CRYPTO, "Unable to load %sdynamic OpenSSL engine \"%s\".",
330 : required?"required ":"",
331 : accelName);
332 4 : if (required)
333 : return -1;
334 : } else {
335 0 : log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
336 : accelName);
337 : }
338 : }
339 3 : if (e) {
340 0 : log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
341 : " setting default ciphers.");
342 0 : ENGINE_set_default(e, ENGINE_METHOD_ALL);
343 : }
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 10 : log_engine("RSA", ENGINE_get_default_RSA());
347 10 : log_engine("DH", ENGINE_get_default_DH());
348 : #ifdef OPENSSL_1_1_API
349 10 : log_engine("EC", ENGINE_get_default_EC());
350 : #else
351 : log_engine("ECDH", ENGINE_get_default_ECDH());
352 : log_engine("ECDSA", ENGINE_get_default_ECDSA());
353 : #endif /* defined(OPENSSL_1_1_API) */
354 10 : log_engine("RAND", ENGINE_get_default_RAND());
355 10 : log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
356 10 : log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
357 10 : log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
358 10 : log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
359 10 : log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
360 : #ifdef NID_aes_128_ctr
361 10 : log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
362 : #endif
363 : #ifdef NID_aes_128_gcm
364 10 : log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
365 : #endif
366 10 : log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
367 : #ifdef NID_aes_256_gcm
368 10 : log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
369 : #endif
370 10 : return 0;
371 :
372 : #endif /* defined(DISABLE_ENGINES) */
373 : }
374 :
375 : /** Perform late (post-init) initialization tasks for OpenSSL */
376 : int
377 5528 : crypto_openssl_late_init(int useAccel, const char *accelName,
378 : const char *accelDir)
379 : {
380 5528 : if (useAccel > 0) {
381 11 : if (crypto_openssl_init_engines(accelName, accelDir) < 0)
382 : return -1;
383 : } else {
384 5517 : log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
385 : }
386 :
387 5527 : if (crypto_force_rand_ssleay()) {
388 0 : if (crypto_seed_rng() < 0)
389 : return -1;
390 : }
391 :
392 5527 : evaluate_evp_for_aes(-1);
393 5527 : evaluate_ctr_for_aes();
394 :
395 5527 : return 0;
396 : }
397 :
398 : /** Free crypto resources held by this thread. */
399 : void
400 0 : crypto_openssl_thread_cleanup(void)
401 : {
402 : #ifndef NEW_THREAD_API
403 : ERR_remove_thread_state(NULL);
404 : #endif
405 0 : }
406 :
407 : /** Clean up global resources held by openssl. */
408 : void
409 235 : crypto_openssl_global_cleanup(void)
410 : {
411 : #ifndef OPENSSL_1_1_API
412 : EVP_cleanup();
413 : #endif
414 : #ifndef NEW_THREAD_API
415 : ERR_remove_thread_state(NULL);
416 : #endif
417 : #ifndef OPENSSL_1_1_API
418 : ERR_free_strings();
419 : #endif
420 :
421 : #ifndef DISABLE_ENGINES
422 : #ifndef OPENSSL_1_1_API
423 : ENGINE_cleanup();
424 : #endif
425 : #endif
426 :
427 235 : CONF_modules_unload(1);
428 : #ifndef OPENSSL_1_1_API
429 : CRYPTO_cleanup_all_ex_data();
430 : #endif
431 :
432 235 : crypto_openssl_free_all();
433 235 : }
|