1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
/* Copyright (c) 2001, Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file crypto_openssl.c
*
* \brief Block of functions related to operations from OpenSSL.
**/
#include "compat_openssl.h"
#include "crypto_openssl_mgt.h"
DISABLE_GCC_WARNING(redundant-decls)
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
#include <openssl/rand.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/conf.h>
#include <openssl/hmac.h>
#include <openssl/crypto.h>
ENABLE_GCC_WARNING(redundant-decls)
#ifndef NEW_THREAD_API
/** A number of preallocated mutexes for use by OpenSSL. */
static tor_mutex_t **openssl_mutexes_ = NULL;
/** How many mutexes have we allocated for use by OpenSSL? */
static int n_openssl_mutexes_ = 0;
#endif /* !defined(NEW_THREAD_API) */
/** Declare STATIC functions */
STATIC char * parse_openssl_version_str(const char *raw_version);
#ifndef NEW_THREAD_API
STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line);
STATIC void tor_set_openssl_thread_id(CRYPTO_THREADID *threadid);
#endif
/* Returns a trimmed and human-readable version of an openssl version string
* <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10
* May 2012' and this will parse them into a form similar to '1.0.0b' */
STATIC char *
parse_openssl_version_str(const char *raw_version)
{
const char *end_of_version = NULL;
/* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's
trim that down. */
if (!strcmpstart(raw_version, "OpenSSL ")) {
raw_version += strlen("OpenSSL ");
end_of_version = strchr(raw_version, ' ');
}
if (end_of_version)
return tor_strndup(raw_version,
end_of_version-raw_version);
else
return tor_strdup(raw_version);
}
static char *crypto_openssl_version_str = NULL;
/* Return a human-readable version of the run-time openssl version number. */
const char *
crypto_openssl_get_version_str(void)
{
if (crypto_openssl_version_str == NULL) {
const char *raw_version = OpenSSL_version(OPENSSL_VERSION);
crypto_openssl_version_str = parse_openssl_version_str(raw_version);
}
return crypto_openssl_version_str;
}
static char *crypto_openssl_header_version_str = NULL;
/* Return a human-readable version of the compile-time openssl version
* number. */
const char *
crypto_openssl_get_header_version_str(void)
{
if (crypto_openssl_header_version_str == NULL) {
crypto_openssl_header_version_str =
parse_openssl_version_str(OPENSSL_VERSION_TEXT);
}
return crypto_openssl_header_version_str;
}
#ifndef OPENSSL_THREADS
#error OpenSSL has been built without thread support. Tor requires an \
OpenSSL library with thread support enabled.
#endif
#ifndef NEW_THREAD_API
/** Helper: OpenSSL uses this callback to manipulate mutexes. */
STATIC void
openssl_locking_cb_(int mode, int n, const char *file, int line)
{
(void)file;
(void)line;
if (!openssl_mutexes_)
/* This is not a really good fix for the
* "release-freed-lock-from-separate-thread-on-shutdown" problem, but
* it can't hurt. */
return;
if (mode & CRYPTO_LOCK)
tor_mutex_acquire(openssl_mutexes_[n]);
else
tor_mutex_release(openssl_mutexes_[n]);
}
STATIC void
tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
{
CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id());
}
#endif /* !defined(NEW_THREAD_API) */
/** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
* multithreaded. Returns 0. */
int
setup_openssl_threading(void)
{
#ifndef NEW_THREAD_API
int i;
int n = CRYPTO_num_locks();
n_openssl_mutexes_ = n;
openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *));
for (i=0; i < n; ++i)
openssl_mutexes_[i] = tor_mutex_new();
CRYPTO_set_locking_callback(openssl_locking_cb_);
CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id);
#endif /* !defined(NEW_THREAD_API) */
return 0;
}
/** free OpenSSL variables */
void
crypto_openssl_free_all(void)
{
tor_free(crypto_openssl_version_str);
tor_free(crypto_openssl_header_version_str);
#ifndef NEW_THREAD_API
if (n_openssl_mutexes_) {
int n = n_openssl_mutexes_;
tor_mutex_t **ms = openssl_mutexes_;
int i;
openssl_mutexes_ = NULL;
n_openssl_mutexes_ = 0;
for (i=0;i<n;++i) {
tor_mutex_free(ms[i]);
}
tor_free(ms);
}
#endif /* !defined(NEW_THREAD_API) */
}
|