Tor  0.4.3.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  if (crypto_openssl_version_str == NULL) {
105  const char *raw_version = OpenSSL_version(OPENSSL_VERSION);
106  crypto_openssl_version_str = parse_openssl_version_str(raw_version);
107  }
108  return crypto_openssl_version_str;
109 }
110 
111 static char *crypto_openssl_header_version_str = NULL;
112 /* Return a human-readable version of the compile-time openssl version
113 * number. */
114 const char *
115 crypto_openssl_get_header_version_str(void)
116 {
117  if (crypto_openssl_header_version_str == NULL) {
118  crypto_openssl_header_version_str =
119  parse_openssl_version_str(OPENSSL_VERSION_TEXT);
120  }
121  return crypto_openssl_header_version_str;
122 }
123 
124 #ifndef COCCI
125 #ifndef OPENSSL_THREADS
126 #error "OpenSSL has been built without thread support. Tor requires an \
127  OpenSSL library with thread support enabled."
128 #endif
129 #endif /* !defined(COCCI) */
130 
131 #ifndef NEW_THREAD_API
132 /** Helper: OpenSSL uses this callback to manipulate mutexes. */
133 STATIC void
134 openssl_locking_cb_(int mode, int n, const char *file, int line)
135 {
136  (void)file;
137  (void)line;
138  if (!openssl_mutexes_)
139  /* This is not a really good fix for the
140  * "release-freed-lock-from-separate-thread-on-shutdown" problem, but
141  * it can't hurt. */
142  return;
143  if (mode & CRYPTO_LOCK)
145  else
147 }
148 
149 STATIC void
150 tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
151 {
152  CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id());
153 }
154 #endif /* !defined(NEW_THREAD_API) */
155 
156 /** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
157  * multithreaded. Returns 0. */
158 static int
160 {
161 #ifndef NEW_THREAD_API
162  int i;
163  int n = CRYPTO_num_locks();
164  n_openssl_mutexes_ = n;
165  openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *));
166  for (i=0; i < n; ++i)
168  CRYPTO_set_locking_callback(openssl_locking_cb_);
169  CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id);
170 #endif /* !defined(NEW_THREAD_API) */
171  return 0;
172 }
173 
174 /** free OpenSSL variables */
175 static void
177 {
178  tor_free(crypto_openssl_version_str);
179  tor_free(crypto_openssl_header_version_str);
180 
181  /* Destroying a locked mutex is undefined behaviour. This mutex may be
182  * locked, because multiple threads can access it. But we need to destroy
183  * it, otherwise re-initialisation will trigger undefined behaviour.
184  * See #31735 for details. */
185 #ifndef NEW_THREAD_API
186  if (n_openssl_mutexes_) {
187  int n = n_openssl_mutexes_;
189  int i;
190  openssl_mutexes_ = NULL;
191  n_openssl_mutexes_ = 0;
192  for (i=0;i<n;++i) {
193  tor_mutex_free(ms[i]);
194  }
195  tor_free(ms);
196  }
197 #endif /* !defined(NEW_THREAD_API) */
198 }
199 
200 /** Perform early (pre-configuration) initialization tasks for OpenSSL. */
201 void
203 {
204 #ifdef OPENSSL_1_1_API
205  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
206  OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
207  OPENSSL_INIT_ADD_ALL_CIPHERS |
208  OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
209 #else /* !defined(OPENSSL_1_1_API) */
210  ERR_load_crypto_strings();
211  OpenSSL_add_all_algorithms();
212 #endif /* defined(OPENSSL_1_1_API) */
213 
215 
216  unsigned long version_num = OpenSSL_version_num();
217  const char *version_str = OpenSSL_version(OPENSSL_VERSION);
218  if (version_num == OPENSSL_VERSION_NUMBER &&
219  !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
220  log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
221  "(%lx: %s).", version_num, version_str);
222  } else if ((version_num & 0xffff0000) ==
223  (OPENSSL_VERSION_NUMBER & 0xffff0000)) {
224  log_notice(LD_CRYPTO,
225  "We compiled with OpenSSL %lx: %s and we "
226  "are running with OpenSSL %lx: %s. "
227  "These two versions should be binary compatible.",
228  (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
229  version_num, version_str);
230  } else {
231  log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
232  "version we're running with. If you get weird crashes, that "
233  "might be why. (Compiled with %lx: %s; running with %lx: %s).",
234  (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
235  version_num, version_str);
236  }
237 
239 }
240 
241 #ifndef DISABLE_ENGINES
242 /** Try to load an engine in a shared library via fully qualified path.
243  */
244 static ENGINE *
245 try_load_engine(const char *path, const char *engine)
246 {
247  ENGINE *e = ENGINE_by_id("dynamic");
248  if (e) {
249  if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
250  !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
251  !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
252  !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
253  ENGINE_free(e);
254  e = NULL;
255  }
256  }
257  return e;
258 }
259 #endif /* !defined(DISABLE_ENGINES) */
260 
261 #ifndef DISABLE_ENGINES
262 /** Log any OpenSSL engines we're using at NOTICE. */
263 static void
264 log_engine(const char *fn, ENGINE *e)
265 {
266  if (e) {
267  const char *name, *id;
268  name = ENGINE_get_name(e);
269  id = ENGINE_get_id(e);
270  log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
271  fn, name?name:"?", id?id:"?");
272  } else {
273  log_info(LD_CRYPTO, "Using default implementation for %s", fn);
274  }
275 }
276 #endif /* !defined(DISABLE_ENGINES) */
277 
278 /** Initialize engines for openssl (if enabled). Load all the built-in
279  * engines, along with the one called <b>accelName</b> (which may be NULL).
280  * If <b>accelName</b> is prefixed with "!", then it is required: return -1
281  * if it can't be loaded. Otherwise return 0.
282  *
283  * If <b>accelDir</b> is not NULL, it is the path from which the engine should
284  * be loaded. */
285 static int
286 crypto_openssl_init_engines(const char *accelName,
287  const char *accelDir)
288 {
289 #ifdef DISABLE_ENGINES
290  (void)accelName;
291  (void)accelDir;
292  log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
293  if (accelName && accelName[0] == '!') {
294  log_warn(LD_CRYPTO, "Unable to load required dynamic OpenSSL engine "
295  "\"%s\".", accelName+1);
296  return -1;
297  }
298  return 0;
299 #else /* !defined(DISABLE_ENGINES) */
300  ENGINE *e = NULL;
301 
302  log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
303  ENGINE_load_builtin_engines();
304  ENGINE_register_all_complete();
305 
306  if (accelName) {
307  const bool required = accelName[0] == '!';
308  if (required)
309  ++accelName;
310  if (accelDir) {
311  log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
312  " via path \"%s\".", accelName, accelDir);
313  e = try_load_engine(accelName, accelDir);
314  } else {
315  log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
316  " acceleration support.", accelName);
317  e = ENGINE_by_id(accelName);
318  }
319  if (!e) {
320  log_warn(LD_CRYPTO, "Unable to load %sdynamic OpenSSL engine \"%s\".",
321  required?"required ":"",
322  accelName);
323  if (required)
324  return -1;
325  } else {
326  log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
327  accelName);
328  }
329  }
330  if (e) {
331  log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
332  " setting default ciphers.");
333  ENGINE_set_default(e, ENGINE_METHOD_ALL);
334  }
335  /* Log, if available, the intersection of the set of algorithms
336  used by Tor and the set of algorithms available in the engine */
337  log_engine("RSA", ENGINE_get_default_RSA());
338  log_engine("DH", ENGINE_get_default_DH());
339 #ifdef OPENSSL_1_1_API
340  log_engine("EC", ENGINE_get_default_EC());
341 #else
342  log_engine("ECDH", ENGINE_get_default_ECDH());
343  log_engine("ECDSA", ENGINE_get_default_ECDSA());
344 #endif /* defined(OPENSSL_1_1_API) */
345  log_engine("RAND", ENGINE_get_default_RAND());
346  log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
347  log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
348  log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
349  log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
350  log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
351 #ifdef NID_aes_128_ctr
352  log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
353 #endif
354 #ifdef NID_aes_128_gcm
355  log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
356 #endif
357  log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
358 #ifdef NID_aes_256_gcm
359  log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
360 #endif
361  return 0;
362 
363 #endif /* defined(DISABLE_ENGINES) */
364 }
365 
366 /** Perform late (post-init) initialization tasks for OpenSSL */
367 int
368 crypto_openssl_late_init(int useAccel, const char *accelName,
369  const char *accelDir)
370 {
371  if (useAccel > 0) {
372  if (crypto_openssl_init_engines(accelName, accelDir) < 0)
373  return -1;
374  } else {
375  log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
376  }
377 
378  if (crypto_force_rand_ssleay()) {
379  if (crypto_seed_rng() < 0)
380  return -1;
381  }
382 
383  evaluate_evp_for_aes(-1);
384  evaluate_ctr_for_aes();
385 
386  return 0;
387 }
388 
389 /** Free crypto resources held by this thread. */
390 void
392 {
393 #ifndef NEW_THREAD_API
394  ERR_remove_thread_state(NULL);
395 #endif
396 }
397 
398 /** Clean up global resources held by openssl. */
399 void
401 {
402 #ifndef OPENSSL_1_1_API
403  EVP_cleanup();
404 #endif
405 #ifndef NEW_THREAD_API
406  ERR_remove_thread_state(NULL);
407 #endif
408 #ifndef OPENSSL_1_1_API
409  ERR_free_strings();
410 #endif
411 
412 #ifndef DISABLE_ENGINES
413 #ifndef OPENSSL_1_1_API
414  ENGINE_cleanup();
415 #endif
416 #endif
417 
418  CONF_modules_unload(1);
419 #ifndef OPENSSL_1_1_API
420  CRYPTO_cleanup_all_ex_data();
421 #endif
422 
424 }
void tor_mutex_release(tor_mutex_t *m)
Common functions for using (pseudo-)random number generators.
int crypto_force_rand_ssleay(void)
Definition: crypto_rand.c:618
void crypto_openssl_early_init(void)
Headers for crypto_openssl_mgt.c.
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
Definition: log.c:628
void crypto_openssl_global_cleanup(void)
void crypto_openssl_thread_cleanup(void)
void crypto_openssl_log_errors(int severity, const char *doing)
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:206
#define tor_free(p)
Definition: malloc.h:52
Header for util_string.c.
const char * name
Definition: config.c:2441
static ENGINE * try_load_engine(const char *path, const char *engine)
#define STATIC
Definition: testsupport.h:32
Header for threads.c.
static tor_mutex_t ** openssl_mutexes_
static int setup_openssl_threading(void)
#define tor_mutex_free(m)
Definition: compat_mutex.h:66
Headers for aes.c.
STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line)
int crypto_openssl_late_init(int useAccel, const char *accelName, const char *accelDir)
STATIC char * parse_openssl_version_str(const char *raw_version)
Header for compat_mutex.c.
static void crypto_openssl_free_all(void)
Macros to implement mocking and selective exposure for the test code.
void tor_mutex_acquire(tor_mutex_t *m)
tor_mutex_t * tor_mutex_new(void)
Definition: compat_mutex.c:17
static void log_engine(const char *fn, ENGINE *e)
int crypto_seed_rng(void)
Definition: crypto_rand.c:452
Headers for log.c.
#define LD_CRYPTO
Definition: log.h:64
static int crypto_openssl_init_engines(const char *accelName, const char *accelDir)
unsigned long tor_get_thread_id(void)
static int n_openssl_mutexes_
Macros to manage assertions, fatal and non-fatal.