2 * openssl.c OpenSSL support functions
4 * Author: Landon Fuller <landonf@opendarwin.org>
8 * This file was contributed to the Bacula project by Landon Fuller.
10 * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
11 * no-charge, royalty-free, irrevocable copyright license to reproduce,
12 * prepare derivative works of, publicly display, publicly perform,
13 * sublicense, and distribute the original work contributed by Landon Fuller
14 * to the Bacula project in source or object form.
16 * If you wish to license these contributions under an alternate open source
17 * license please contact Landon Fuller <landonf@opendarwin.org>.
20 Bacula® - The Network Backup Solution
22 Copyright (C) 2005-2006 Free Software Foundation Europe e.V.
24 The main author of Bacula is Kern Sibbald, with contributions from
25 many others, a complete list can be found in the file AUTHORS.
26 This program is Free Software; you can redistribute it and/or
27 modify it under the terms of version two of the GNU General Public
28 License as published by the Free Software Foundation plus additions
29 that are listed in the file LICENSE.
31 This program is distributed in the hope that it will be useful, but
32 WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 General Public License for more details.
36 You should have received a copy of the GNU General Public License
37 along with this program; if not, write to the Free Software
38 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
41 Bacula® is a registered trademark of John Walker.
42 The licensor of Bacula is the Free Software Foundation Europe
43 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
44 Switzerland, email:ftf@fsfeurope.org.
53 /* Array of mutexes for use with OpenSSL static locking */
54 static pthread_mutex_t *mutexes;
56 /* OpenSSL dynamic locking structure */
57 struct CRYPTO_dynlock_value {
58 pthread_mutex_t mutex;
63 * Post all per-thread openssl errors
65 void openssl_post_errors(int code, const char *errstring)
70 /* Pop errors off of the per-thread queue */
71 while((sslerr = ERR_get_error()) != 0) {
72 /* Acquire the human readable string */
73 ERR_error_string_n(sslerr, (char *) &buf, sizeof(buf));
74 Emsg2(M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
79 * Return an OpenSSL thread ID
83 static unsigned long get_openssl_thread_id (void)
85 /* Comparison without use of pthread_equal() is mandated by the OpenSSL API */
86 return ((unsigned long) pthread_self());
90 * Allocate a dynamic OpenSSL mutex
92 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
94 struct CRYPTO_dynlock_value *dynlock;
97 dynlock = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value));
99 if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
100 Emsg1(M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
106 static void openssl_update_dynamic_mutex (int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
108 if (mode & CRYPTO_LOCK) {
115 static void openssl_destroy_dynamic_mutex (struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
119 if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
120 Emsg1(M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
127 * (Un)Lock a static OpenSSL mutex
129 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
131 if (mode & CRYPTO_LOCK) {
139 * Initialize OpenSSL thread support
140 * Returns: 0 on success
143 int openssl_init_threads (void)
149 /* Set thread ID callback */
150 CRYPTO_set_id_callback(get_openssl_thread_id);
152 /* Initialize static locking */
153 numlocks = CRYPTO_num_locks();
154 mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
155 for (i = 0; i < numlocks; i++) {
156 if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
157 Emsg1(M_ERROR, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
162 /* Set static locking callback */
163 CRYPTO_set_locking_callback(openssl_update_static_mutex);
165 /* Initialize dyanmic locking */
166 CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
167 CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
168 CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
174 * Clean up OpenSSL threading support
176 void openssl_cleanup_threads (void)
181 /* Unset thread ID callback */
182 CRYPTO_set_id_callback(NULL);
184 /* Deallocate static lock mutexes */
185 numlocks = CRYPTO_num_locks();
186 for (i = 0; i < numlocks; i++) {
187 if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
188 /* We don't halt execution, reporting the error should be sufficient */
189 Emsg1(M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
193 /* Unset static locking callback */
194 CRYPTO_set_locking_callback(NULL);
196 /* Free static lock array */
199 /* Unset dynamic locking callbacks */
200 CRYPTO_set_dynlock_create_callback(NULL);
201 CRYPTO_set_dynlock_lock_callback(NULL);
202 CRYPTO_set_dynlock_destroy_callback(NULL);
208 * Returns: 1 on success
211 int openssl_seed_prng (void)
213 const char *names[] = { "/dev/urandom", "/dev/random", NULL };
218 // Read saved entropy?
220 for (i = 0; names[i]; i++) {
221 if (RAND_load_file(names[i], 1024) != -1) {
232 * Save OpenSSL Entropy
233 * Returns: 1 on success
236 int openssl_save_prng (void)
239 // Implement PRNG state save
243 #endif /* HAVE_OPENSSL */