crypto_openssl.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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-2017, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * \file crypto_openssl.c
  8. *
  9. * \brief Block of functions related to operations from OpenSSL.
  10. **/
  11. #include "crypto_openssl.h"
  12. #ifndef NEW_THREAD_API
  13. /** A number of preallocated mutexes for use by OpenSSL. */
  14. tor_mutex_t **openssl_mutexes_ = NULL;
  15. /** How many mutexes have we allocated for use by OpenSSL? */
  16. int n_openssl_mutexes_ = 0;
  17. #endif /* !defined(NEW_THREAD_API) */
  18. /* Returns a trimmed and human-readable version of an openssl version string
  19. * <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10
  20. * May 2012' and this will parse them into a form similar to '1.0.0b' */
  21. char *
  22. parse_openssl_version_str(const char *raw_version)
  23. {
  24. const char *end_of_version = NULL;
  25. /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's
  26. trim that down. */
  27. if (!strcmpstart(raw_version, "OpenSSL ")) {
  28. raw_version += strlen("OpenSSL ");
  29. end_of_version = strchr(raw_version, ' ');
  30. }
  31. if (end_of_version)
  32. return tor_strndup(raw_version,
  33. end_of_version-raw_version);
  34. else
  35. return tor_strdup(raw_version);
  36. }
  37. char *crypto_openssl_version_str = NULL;
  38. /* Return a human-readable version of the run-time openssl version number. */
  39. const char *
  40. crypto_openssl_get_version_str(void)
  41. {
  42. if (crypto_openssl_version_str == NULL) {
  43. const char *raw_version = OpenSSL_version(OPENSSL_VERSION);
  44. crypto_openssl_version_str = parse_openssl_version_str(raw_version);
  45. }
  46. return crypto_openssl_version_str;
  47. }
  48. char *crypto_openssl_header_version_str = NULL;
  49. /* Return a human-readable version of the compile-time openssl version
  50. * number. */
  51. const char *
  52. crypto_openssl_get_header_version_str(void)
  53. {
  54. if (crypto_openssl_header_version_str == NULL) {
  55. crypto_openssl_header_version_str =
  56. parse_openssl_version_str(OPENSSL_VERSION_TEXT);
  57. }
  58. return crypto_openssl_header_version_str;
  59. }
  60. #ifndef OPENSSL_THREADS
  61. #error OpenSSL has been built without thread support. Tor requires an \
  62. OpenSSL library with thread support enabled.
  63. #endif
  64. #ifndef NEW_THREAD_API
  65. /** Helper: OpenSSL uses this callback to manipulate mutexes. */
  66. void
  67. openssl_locking_cb_(int mode, int n, const char *file, int line)
  68. {
  69. (void)file;
  70. (void)line;
  71. if (!openssl_mutexes_)
  72. /* This is not a really good fix for the
  73. * "release-freed-lock-from-separate-thread-on-shutdown" problem, but
  74. * it can't hurt. */
  75. return;
  76. if (mode & CRYPTO_LOCK)
  77. tor_mutex_acquire(openssl_mutexes_[n]);
  78. else
  79. tor_mutex_release(openssl_mutexes_[n]);
  80. }
  81. void
  82. tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
  83. {
  84. CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id());
  85. }
  86. #endif /* !defined(NEW_THREAD_API) */
  87. /** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
  88. * multithreaded. Returns 0. */
  89. int
  90. setup_openssl_threading(void)
  91. {
  92. #ifndef NEW_THREAD_API
  93. int i;
  94. int n = CRYPTO_num_locks();
  95. n_openssl_mutexes_ = n;
  96. openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *));
  97. for (i=0; i < n; ++i)
  98. openssl_mutexes_[i] = tor_mutex_new();
  99. CRYPTO_set_locking_callback(openssl_locking_cb_);
  100. CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id);
  101. #endif /* !defined(NEW_THREAD_API) */
  102. return 0;
  103. }