2 * openssl.c OpenSSL support functions
4 * Author: Landon Fuller <landonf@opendarwin.org>
8 * Copyright (C) 2005 Kern Sibbald
10 * This file was contributed to the Bacula project by Landon Fuller.
12 * Landon Fuller has been granted a perpetual, worldwide, non-exclusive,
13 * no-charge, royalty-free, irrevocable copyright license to reproduce,
14 * prepare derivative works of, publicly display, publicly perform,
15 * sublicense, and distribute the original work contributed by Landon Fuller
16 * to the Bacula project in source or object form.
18 * If you wish to license these contributions under an alternate open source
19 * license please contact Landon Fuller <landonf@opendarwin.org>.
22 Copyright (C) 2005-2006 Kern Sibbald
24 This program is free software; you can redistribute it and/or
25 modify it under the terms of the GNU General Public License
26 version 2 as amended with additional clauses defined in the
27 file LICENSE in the main source directory.
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 the file LICENSE for additional details.
42 /* Array of mutexes for use with OpenSSL static locking */
43 static pthread_mutex_t *mutexes;
45 /* OpenSSL dynamic locking structure */
46 struct CRYPTO_dynlock_value {
47 pthread_mutex_t mutex;
52 * Post all per-thread openssl errors
54 void openssl_post_errors(int code, const char *errstring)
59 /* Pop errors off of the per-thread queue */
60 while((sslerr = ERR_get_error()) != 0) {
61 /* Acquire the human readable string */
62 ERR_error_string_n(sslerr, (char *) &buf, sizeof(buf));
63 Emsg2(M_ERROR, 0, "%s: ERR=%s\n", errstring, buf);
68 * Return an OpenSSL thread ID
72 static unsigned long get_openssl_thread_id (void)
74 /* Comparison without use of pthread_equal() is mandated by the OpenSSL API */
75 return ((unsigned long) pthread_self());
79 * Allocate a dynamic OpenSSL mutex
81 static struct CRYPTO_dynlock_value *openssl_create_dynamic_mutex (const char *file, int line)
83 struct CRYPTO_dynlock_value *dynlock;
86 dynlock = (struct CRYPTO_dynlock_value *) malloc(sizeof(struct CRYPTO_dynlock_value));
88 if ((stat = pthread_mutex_init(&dynlock->mutex, NULL)) != 0) {
89 Emsg1(M_ABORT, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
95 static void openssl_update_dynamic_mutex (int mode, struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
97 if (mode & CRYPTO_LOCK) {
104 static void openssl_destroy_dynamic_mutex (struct CRYPTO_dynlock_value *dynlock, const char *file, int line)
108 if ((stat = pthread_mutex_destroy(&dynlock->mutex)) != 0) {
109 Emsg1(M_ABORT, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
116 * (Un)Lock a static OpenSSL mutex
118 static void openssl_update_static_mutex (int mode, int i, const char *file, int line)
120 if (mode & CRYPTO_LOCK) {
128 * Initialize OpenSSL thread support
129 * Returns: 0 on success
132 int openssl_init_threads (void)
138 /* Set thread ID callback */
139 CRYPTO_set_id_callback(get_openssl_thread_id);
141 /* Initialize static locking */
142 numlocks = CRYPTO_num_locks();
143 mutexes = (pthread_mutex_t *) malloc(numlocks * sizeof(pthread_mutex_t));
144 for (i = 0; i < numlocks; i++) {
145 if ((stat = pthread_mutex_init(&mutexes[i], NULL)) != 0) {
146 Emsg1(M_ERROR, 0, _("Unable to init mutex: ERR=%s\n"), strerror(stat));
151 /* Set static locking callback */
152 CRYPTO_set_locking_callback(openssl_update_static_mutex);
154 /* Initialize dyanmic locking */
155 CRYPTO_set_dynlock_create_callback(openssl_create_dynamic_mutex);
156 CRYPTO_set_dynlock_lock_callback(openssl_update_dynamic_mutex);
157 CRYPTO_set_dynlock_destroy_callback(openssl_destroy_dynamic_mutex);
163 * Clean up OpenSSL threading support
165 void openssl_cleanup_threads (void)
170 /* Unset thread ID callback */
171 CRYPTO_set_id_callback(NULL);
173 /* Deallocate static lock mutexes */
174 numlocks = CRYPTO_num_locks();
175 for (i = 0; i < numlocks; i++) {
176 if ((stat = pthread_mutex_destroy(&mutexes[i])) != 0) {
177 /* We don't halt execution, reporting the error should be sufficient */
178 Emsg1(M_ERROR, 0, _("Unable to destroy mutex: ERR=%s\n"), strerror(stat));
182 /* Unset static locking callback */
183 CRYPTO_set_locking_callback(NULL);
185 /* Free static lock array */
188 /* Unset dynamic locking callbacks */
189 CRYPTO_set_dynlock_create_callback(NULL);
190 CRYPTO_set_dynlock_lock_callback(NULL);
191 CRYPTO_set_dynlock_destroy_callback(NULL);
197 * Returns: 1 on success
200 int openssl_seed_prng (void)
202 const char *names[] = { "/dev/urandom", "/dev/random", NULL };
207 // Read saved entropy?
209 for (i = 0; names[i]; i++) {
210 if (RAND_load_file(names[i], 1024) != -1) {
221 * Save OpenSSL Entropy
222 * Returns: 1 on success
225 int openssl_save_prng (void)
228 // Implement PRNG state save
232 #endif /* HAVE_OPENSSL */