2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * openssl.c OpenSSL support functions
22 * Author: Landon Fuller <landonf@opendarwin.org>
24 * This file was contributed to the Bacula project by Landon Fuller.
26 * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
27 * no-charge, royalty-free, irrevocable copyright license to reproduce,
28 * prepare derivative works of, publicly display, publicly perform,
29 * sublicense, and distribute the original work contributed by Landon Fuller
30 * to the Bacula project in source or object form.
32 * If you wish to license these contributions under an alternate open source
33 * license please contact Landon Fuller <landonf@opendarwin.org>.
42 /* Are we initialized? */
43 static int crypto_initialized = false;
45 * ***FIXME*** this is a sort of dummy to avoid having to
46 * change all the existing code to pass either a jcr or
47 * a NULL. Passing a NULL causes the messages to be
48 * printed by the daemon -- not very good :-(
50 void openssl_post_errors(int code, const char *errstring)
52 openssl_post_errors(NULL, code, errstring);
56 * Post all per-thread openssl errors
58 void openssl_post_errors(JCR *jcr, int code, const char *errstring)
63 /* Pop errors off of the per-thread queue */
64 while((sslerr = ERR_get_error()) != 0) {
65 /* Acquire the human readable string */
66 ERR_error_string_n(sslerr, buf, sizeof(buf));
67 Dmsg3(50, "jcr=%p %s: ERR=%s\n", jcr, errstring, buf);
68 Qmsg2(jcr, M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
72 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
73 /* Array of mutexes for use with OpenSSL static locking */
74 static pthread_mutex_t *mutexes;
76 /* OpenSSL dynamic locking structure */
77 struct CRYPTO_dynlock_value {
78 pthread_mutex_t mutex;
82 * Return an OpenSSL thread ID
86 static unsigned long get_openssl_thread_id(void)
89 * Comparison without use of pthread_equal() is mandated by the OpenSSL API
91 * Note: this creates problems with the new Win32 pthreads
92 * emulation code, which defines pthread_t as a structure.
94 return ((unsigned long)pthread_self());
98 * Allocate a dynamic OpenSSL mutex
100 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
102 struct CRYPTO_dynlock_value *dynlock;
105 dynlock = (struct CRYPTO_dynlock_value *)malloc(sizeof(struct CRYPTO_dynlock_value));
107 if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
109 Jmsg1(NULL, M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
115 static void openssl_update_dynamic_mutex(int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
117 if (mode & CRYPTO_LOCK) {
124 static void openssl_destroy_dynamic_mutex(struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
128 if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
130 Jmsg1(NULL, M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), be.bstrerror(stat));
137 * (Un)Lock a static OpenSSL mutex
139 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
141 if (mode & CRYPTO_LOCK) {
149 * Initialize OpenSSL thread support
150 * Returns: 0 on success
153 static int openssl_init_threads (void)
158 /* Set thread ID callback */
159 CRYPTO_set_id_callback(get_openssl_thread_id);
161 /* Initialize static locking */
162 numlocks = CRYPTO_num_locks();
163 mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
164 for (i = 0; i < numlocks; i++) {
165 if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
167 Jmsg1(NULL, M_FATAL, 0, _("Unable to init mutex: ERR=%s\n"), be.bstrerror(stat));
172 /* Set static locking callback */
173 CRYPTO_set_locking_callback(openssl_update_static_mutex);
175 /* Initialize dyanmic locking */
176 CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
177 CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
178 CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
184 * Clean up OpenSSL threading support
186 static void openssl_cleanup_threads(void)
191 /* Unset thread ID callback */
192 CRYPTO_set_id_callback(NULL);
194 /* Deallocate static lock mutexes */
195 numlocks = CRYPTO_num_locks();
196 for (i = 0; i < numlocks; i++) {
197 if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
199 /* We don't halt execution, reporting the error should be sufficient */
200 Jmsg1(NULL, M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"),
205 /* Unset static locking callback */
206 CRYPTO_set_locking_callback(NULL);
208 /* Free static lock array */
211 /* Unset dynamic locking callbacks */
212 CRYPTO_set_dynlock_create_callback(NULL);
213 CRYPTO_set_dynlock_lock_callback(NULL);
214 CRYPTO_set_dynlock_destroy_callback(NULL);
221 * Returns: 1 on success
224 static int openssl_seed_prng (void)
226 const char *names[] = { "/dev/urandom", "/dev/random", NULL };
231 // Read saved entropy?
233 for (i = 0; names[i]; i++) {
234 if (RAND_load_file(names[i], 1024) != -1) {
245 * Save OpenSSL Entropy
246 * Returns: 1 on success
249 static int openssl_save_prng (void)
252 // Implement PRNG state save
257 * Perform global initialization of OpenSSL
258 * This function is not thread safe.
259 * Returns: 0 on success
262 int init_crypto (void)
266 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
267 if ((stat = openssl_init_threads()) != 0) {
269 Jmsg1(NULL, M_ABORT, 0,
270 _("Unable to init OpenSSL threading: ERR=%s\n"), be.bstrerror(stat));
273 /* Load libssl and libcrypto human-readable error strings */
274 SSL_load_error_strings();
276 /* Initialize OpenSSL SSL library */
279 /* Register OpenSSL ciphers and digests */
280 OpenSSL_add_all_algorithms();
283 if (!openssl_seed_prng()) {
284 Jmsg0(NULL, M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n"));
287 crypto_initialized = true;
293 * Perform global cleanup of OpenSSL
294 * All cryptographic operations must be completed before calling this function.
295 * This function is not thread safe.
296 * Returns: 0 on success
299 int cleanup_crypto (void)
302 * Ensure that we've actually been initialized; Doing this here decreases the
303 * complexity of client's termination/cleanup code.
305 if (!crypto_initialized) {
309 if (!openssl_save_prng()) {
310 Jmsg0(NULL, M_ERROR, 0, _("Failed to save OpenSSL PRNG\n"));
313 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
314 openssl_cleanup_threads();
316 /* Free libssl and libcrypto error strings */
319 /* Free all ciphers and digests */
322 /* Free memory used by PRNG */
326 crypto_initialized = false;
334 int init_crypto (void) { return 0; }
335 int cleanup_crypto (void) { return 0; }
337 #endif /* HAVE_OPENSSL */