Tor  0.4.6.0-alpha-dev
crypto_openssl_mgt.c
Go to the documentation of this file.
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-2020, 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"
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"
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 crypto_openssl_log_errors(int severity, const char *doing)
62 {
63  unsigned long err;
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);
75  }
76 }
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 parse_openssl_version_str(const char *raw_version)
83 {
84  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  if (!strcmpstart(raw_version, "OpenSSL ")) {
88  raw_version += strlen("OpenSSL ");
89  end_of_version = strchr(raw_version, ' ');
90  }
91 
92  if (end_of_version)
93  return tor_strndup(raw_version,
94  end_of_version-raw_version);
95  else
96  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 crypto_openssl_get_version_str(void)
103 {
104 #ifdef OPENSSL_VERSION
105  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
110 
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);
114  }
115  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 crypto_openssl_get_header_version_str(void)
125 {
126  if (crypto_openssl_header_version_str == NULL) {
127  crypto_openssl_header_version_str =
128  parse_openssl_version_str(OPENSSL_VERSION_TEXT);
129  }
130  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)
154  else
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
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)
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
186 {
187  tor_free(crypto_openssl_version_str);
188  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_;
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 }
208 
209 /** Perform early (pre-configuration) initialization tasks for OpenSSL. */
210 void
212 {
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) */
222 
224 
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);
239  } else {
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);
245  }
246 
248 }
249 
250 #ifndef DISABLE_ENGINES
251 /** Try to load an engine in a shared library via fully qualified path.
252  */
253 static ENGINE *
254 try_load_engine(const char *path, const char *engine)
255 {
256  ENGINE *e = ENGINE_by_id("dynamic");
257  if (e) {
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)) {
262  ENGINE_free(e);
263  e = NULL;
264  }
265  }
266  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 log_engine(const char *fn, ENGINE *e)
274 {
275  if (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:"?");
281  } else {
282  log_info(LD_CRYPTO, "Using default implementation for %s", fn);
283  }
284 }
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 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  ENGINE *e = NULL;
310 
311  log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
312  ENGINE_load_builtin_engines();
313  ENGINE_register_all_complete();
314 
315  if (accelName) {
316  const bool required = accelName[0] == '!';
317  if (required)
318  ++accelName;
319  if (accelDir) {
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);
323  } else {
324  log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
325  " acceleration support.", accelName);
326  e = ENGINE_by_id(accelName);
327  }
328  if (!e) {
329  log_warn(LD_CRYPTO, "Unable to load %sdynamic OpenSSL engine \"%s\".",
330  required?"required ":"",
331  accelName);
332  if (required)
333  return -1;
334  } else {
335  log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
336  accelName);
337  }
338  }
339  if (e) {
340  log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
341  " setting default ciphers.");
342  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  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());
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  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));
362 #endif
363 #ifdef NID_aes_128_gcm
364  log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
365 #endif
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));
369 #endif
370  return 0;
371 
372 #endif /* defined(DISABLE_ENGINES) */
373 }
374 
375 /** Perform late (post-init) initialization tasks for OpenSSL */
376 int
377 crypto_openssl_late_init(int useAccel, const char *accelName,
378  const char *accelDir)
379 {
380  if (useAccel > 0) {
381  if (crypto_openssl_init_engines(accelName, accelDir) < 0)
382  return -1;
383  } else {
384  log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
385  }
386 
387  if (crypto_force_rand_ssleay()) {
388  if (crypto_seed_rng() < 0)
389  return -1;
390  }
391 
392  evaluate_evp_for_aes(-1);
393  evaluate_ctr_for_aes();
394 
395  return 0;
396 }
397 
398 /** Free crypto resources held by this thread. */
399 void
401 {
402 #ifndef NEW_THREAD_API
403  ERR_remove_thread_state(NULL);
404 #endif
405 }
406 
407 /** Clean up global resources held by openssl. */
408 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  CONF_modules_unload(1);
428 #ifndef OPENSSL_1_1_API
429  CRYPTO_cleanup_all_ex_data();
430 #endif
431 
433 }
crypto_openssl_early_init
void crypto_openssl_early_init(void)
Definition: crypto_openssl_mgt.c:211
tor_free
#define tor_free(p)
Definition: malloc.h:52
name
const char * name
Definition: config.c:2463
crypto_seed_rng
int crypto_seed_rng(void)
Definition: crypto_rand.c:452
crypto_openssl_init_engines
static int crypto_openssl_init_engines(const char *accelName, const char *accelDir)
Definition: crypto_openssl_mgt.c:295
threads.h
Header for threads.c.
openssl_mutexes_
static tor_mutex_t ** openssl_mutexes_
Definition: crypto_openssl_mgt.c:45
util_bug.h
Macros to manage assertions, fatal and non-fatal.
setup_openssl_threading
static int setup_openssl_threading(void)
Definition: crypto_openssl_mgt.c:168
crypto_openssl_mgt.h
Headers for crypto_openssl_mgt.c.
crypto_openssl_global_cleanup
void crypto_openssl_global_cleanup(void)
Definition: crypto_openssl_mgt.c:409
crypto_openssl_thread_cleanup
void crypto_openssl_thread_cleanup(void)
Definition: crypto_openssl_mgt.c:400
openssl_locking_cb_
STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line)
Definition: crypto_openssl_mgt.c:143
tor_mutex_t
Definition: compat_mutex.h:40
crypto_openssl_log_errors
void crypto_openssl_log_errors(int severity, const char *doing)
Definition: crypto_openssl_mgt.c:61
aes.h
Headers for aes.c.
strcmpstart
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:215
try_load_engine
static ENGINE * try_load_engine(const char *path, const char *engine)
Definition: crypto_openssl_mgt.c:254
crypto_rand.h
Common functions for using (pseudo-)random number generators.
tor_mutex_new
tor_mutex_t * tor_mutex_new(void)
Definition: compat_mutex.c:17
crypto_openssl_free_all
static void crypto_openssl_free_all(void)
Definition: crypto_openssl_mgt.c:185
LD_CRYPTO
#define LD_CRYPTO
Definition: log.h:64
compat_mutex.h
Header for compat_mutex.c.
tor_mutex_free
#define tor_mutex_free(m)
Definition: compat_mutex.h:66
log.h
Headers for log.c.
log_engine
static void log_engine(const char *fn, ENGINE *e)
Definition: crypto_openssl_mgt.c:273
crypto_openssl_late_init
int crypto_openssl_late_init(int useAccel, const char *accelName, const char *accelDir)
Definition: crypto_openssl_mgt.c:377
testsupport.h
Macros to implement mocking and selective exposure for the test code.
n_openssl_mutexes_
static int n_openssl_mutexes_
Definition: crypto_openssl_mgt.c:47
parse_openssl_version_str
STATIC char * parse_openssl_version_str(const char *raw_version)
Definition: crypto_openssl_mgt.c:82
tor_mutex_acquire
void tor_mutex_acquire(tor_mutex_t *m)
Definition: compat_mutex_pthreads.c:71
tor_log
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
Definition: log.c:590
STATIC
#define STATIC
Definition: testsupport.h:32
util_string.h
Header for util_string.c.
tor_get_thread_id
unsigned long tor_get_thread_id(void)
Definition: compat_pthreads.c:100
crypto_force_rand_ssleay
int crypto_force_rand_ssleay(void)
Definition: crypto_rand.c:618
tor_mutex_release
void tor_mutex_release(tor_mutex_t *m)
Definition: compat_mutex_pthreads.c:84