tor  0.4.2.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-2019, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
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(redundant-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(redundant-decls)
40 
41 #include <string.h>
42 
43 #ifndef NEW_THREAD_API
44 
45 static tor_mutex_t **openssl_mutexes_ = NULL;
47 static int n_openssl_mutexes_ = 0;
48 #endif /* !defined(NEW_THREAD_API) */
49 
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 
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 OPENSSL_THREADS
125 #error OpenSSL has been built without thread support. Tor requires an \
126  OpenSSL library with thread support enabled.
127 #endif
128 
129 #ifndef NEW_THREAD_API
130 
131 STATIC void
132 openssl_locking_cb_(int mode, int n, const char *file, int line)
133 {
134  (void)file;
135  (void)line;
136  if (!openssl_mutexes_)
137  /* This is not a really good fix for the
138  * "release-freed-lock-from-separate-thread-on-shutdown" problem, but
139  * it can't hurt. */
140  return;
141  if (mode & CRYPTO_LOCK)
143  else
145 }
146 
147 STATIC void
148 tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
149 {
150  CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id());
151 }
152 #endif /* !defined(NEW_THREAD_API) */
153 
156 static int
158 {
159 #ifndef NEW_THREAD_API
160  int i;
161  int n = CRYPTO_num_locks();
162  n_openssl_mutexes_ = n;
163  openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *));
164  for (i=0; i < n; ++i)
166  CRYPTO_set_locking_callback(openssl_locking_cb_);
167  CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id);
168 #endif /* !defined(NEW_THREAD_API) */
169  return 0;
170 }
171 
173 static void
175 {
176  tor_free(crypto_openssl_version_str);
177  tor_free(crypto_openssl_header_version_str);
178 
179 #ifndef NEW_THREAD_API
180  if (n_openssl_mutexes_) {
181  int n = n_openssl_mutexes_;
183  int i;
184  openssl_mutexes_ = NULL;
185  n_openssl_mutexes_ = 0;
186  for (i=0;i<n;++i) {
187  tor_mutex_free(ms[i]);
188  }
189  tor_free(ms);
190  }
191 #endif /* !defined(NEW_THREAD_API) */
192 }
193 
195 void
197 {
198 #ifdef OPENSSL_1_1_API
199  OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
200  OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
201  OPENSSL_INIT_ADD_ALL_CIPHERS |
202  OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
203 #else /* !(defined(OPENSSL_1_1_API)) */
204  ERR_load_crypto_strings();
205  OpenSSL_add_all_algorithms();
206 #endif /* defined(OPENSSL_1_1_API) */
207 
209 
210  unsigned long version_num = OpenSSL_version_num();
211  const char *version_str = OpenSSL_version(OPENSSL_VERSION);
212  if (version_num == OPENSSL_VERSION_NUMBER &&
213  !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
214  log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
215  "(%lx: %s).", version_num, version_str);
216  } else if ((version_num & 0xffff0000) ==
217  (OPENSSL_VERSION_NUMBER & 0xffff0000)) {
218  log_notice(LD_CRYPTO,
219  "We compiled with OpenSSL %lx: %s and we "
220  "are running with OpenSSL %lx: %s. "
221  "These two versions should be binary compatible.",
222  (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
223  version_num, version_str);
224  } else {
225  log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
226  "version we're running with. If you get weird crashes, that "
227  "might be why. (Compiled with %lx: %s; running with %lx: %s).",
228  (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
229  version_num, version_str);
230  }
231 
233 }
234 
235 #ifndef DISABLE_ENGINES
236 
238 static ENGINE *
239 try_load_engine(const char *path, const char *engine)
240 {
241  ENGINE *e = ENGINE_by_id("dynamic");
242  if (e) {
243  if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
244  !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
245  !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
246  !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
247  ENGINE_free(e);
248  e = NULL;
249  }
250  }
251  return e;
252 }
253 #endif /* !defined(DISABLE_ENGINES) */
254 
255 #ifndef DISABLE_ENGINES
256 
257 static void
258 log_engine(const char *fn, ENGINE *e)
259 {
260  if (e) {
261  const char *name, *id;
262  name = ENGINE_get_name(e);
263  id = ENGINE_get_id(e);
264  log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
265  fn, name?name:"?", id?id:"?");
266  } else {
267  log_info(LD_CRYPTO, "Using default implementation for %s", fn);
268  }
269 }
270 #endif /* !defined(DISABLE_ENGINES) */
271 
273 static void
274 crypto_openssl_init_engines(const char *accelName,
275  const char *accelDir)
276 {
277 #ifdef DISABLE_ENGINES
278  (void)accelName;
279  (void)accelDir;
280  log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
281 #else
282  ENGINE *e = NULL;
283 
284  log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
285  ENGINE_load_builtin_engines();
286  ENGINE_register_all_complete();
287 
288  if (accelName) {
289  if (accelDir) {
290  log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
291  " via path \"%s\".", accelName, accelDir);
292  e = try_load_engine(accelName, accelDir);
293  } else {
294  log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
295  " acceleration support.", accelName);
296  e = ENGINE_by_id(accelName);
297  }
298  if (!e) {
299  log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
300  accelName);
301  } else {
302  log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
303  accelName);
304  }
305  }
306  if (e) {
307  log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
308  " setting default ciphers.");
309  ENGINE_set_default(e, ENGINE_METHOD_ALL);
310  }
311  /* Log, if available, the intersection of the set of algorithms
312  used by Tor and the set of algorithms available in the engine */
313  log_engine("RSA", ENGINE_get_default_RSA());
314  log_engine("DH", ENGINE_get_default_DH());
315 #ifdef OPENSSL_1_1_API
316  log_engine("EC", ENGINE_get_default_EC());
317 #else
318  log_engine("ECDH", ENGINE_get_default_ECDH());
319  log_engine("ECDSA", ENGINE_get_default_ECDSA());
320 #endif /* defined(OPENSSL_1_1_API) */
321  log_engine("RAND", ENGINE_get_default_RAND());
322  log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
323  log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
324  log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
325  log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
326  log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
327 #ifdef NID_aes_128_ctr
328  log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
329 #endif
330 #ifdef NID_aes_128_gcm
331  log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
332 #endif
333  log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
334 #ifdef NID_aes_256_gcm
335  log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
336 #endif
337 
338 #endif /* defined(DISABLE_ENGINES) */
339 }
340 
342 int
343 crypto_openssl_late_init(int useAccel, const char *accelName,
344  const char *accelDir)
345 {
346  if (useAccel > 0) {
347  crypto_openssl_init_engines(accelName, accelDir);
348  } else {
349  log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
350  }
351 
352  if (crypto_force_rand_ssleay()) {
353  if (crypto_seed_rng() < 0)
354  return -1;
355  }
356 
357  evaluate_evp_for_aes(-1);
358  evaluate_ctr_for_aes();
359 
360  return 0;
361 }
362 
364 void
366 {
367 #ifndef NEW_THREAD_API
368  ERR_remove_thread_state(NULL);
369 #endif
370 }
371 
373 void
375 {
376  #ifndef OPENSSL_1_1_API
377  EVP_cleanup();
378 #endif
379 #ifndef NEW_THREAD_API
380  ERR_remove_thread_state(NULL);
381 #endif
382 #ifndef OPENSSL_1_1_API
383  ERR_free_strings();
384 #endif
385 
386 #ifndef DISABLE_ENGINES
387 #ifndef OPENSSL_1_1_API
388  ENGINE_cleanup();
389 #endif
390 #endif
391 
392  CONF_modules_unload(1);
393 #ifndef OPENSSL_1_1_API
394  CRYPTO_cleanup_all_ex_data();
395 #endif
396 
398 }
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:633
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.
static ENGINE * try_load_engine(const char *path, const char *engine)
Header for threads.c.
static tor_mutex_t ** openssl_mutexes_
static int setup_openssl_threading(void)
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:62
unsigned long tor_get_thread_id(void)
static int n_openssl_mutexes_
Macros to manage assertions, fatal and non-fatal.
static void crypto_openssl_init_engines(const char *accelName, const char *accelDir)