Commit 82d5badd authored by Jan Včelák's avatar Jan Včelák 🚀

thread-safe crypto: add module with initialization and cleanup

ref #157
parent f8f95eec
......@@ -147,8 +147,9 @@ libknot_la_SOURCES = \
libknot/tsig-op.c \
libknot/binary.h \
libknot/binary.c \
libknot/dnssec/cleanup.h \
libknot/dnssec/config.h \
libknot/dnssec/crypto.c \
libknot/dnssec/crypto.h \
libknot/dnssec/key.c \
libknot/dnssec/key.h \
libknot/dnssec/nsec-bitmap.h \
......
......@@ -27,7 +27,7 @@
#endif /* HAVE_CAP_NG_H */
#include "libknot/common.h"
#include "libknot/dnssec/cleanup.h"
#include "libknot/dnssec/crypto.h"
#include "common/evqueue.h"
#include "knot/knot.h"
#include "knot/server/server.h"
......@@ -100,7 +100,7 @@ void help(void)
int main(int argc, char **argv)
{
atexit(knot_dnssec_cleanup);
atexit(knot_crypto_cleanup);
// Parse command line arguments
int c = 0, li = 0;
......
......@@ -20,7 +20,6 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include <openssl/evp.h>
#include <assert.h>
#include "common/prng.h"
......@@ -35,7 +34,7 @@
#include "libknot/nameserver/name-server.h"
#include "libknot/zone/zonedb.h"
#include "libknot/dname.h"
#include "libknot/dnssec/cleanup.h"
#include "libknot/dnssec/crypto.h"
/*! \brief Event scheduler loop. */
static int evsched_run(dthread_t *thread)
......@@ -77,7 +76,7 @@ static int evsched_run(dthread_t *thread)
/*! \brief Event scheduler thread destructor. */
static int evsched_destruct(dthread_t *thread)
{
knot_dnssec_thread_cleanup();
knot_crypto_cleanup_thread();
return KNOT_EOK;
}
......@@ -353,8 +352,8 @@ server_t *server_create()
return NULL;
}
knot_ns_set_data(server->nameserver, server);
dbg_server("server: initializing OpenSSL\n");
OpenSSL_add_all_digests();
dbg_server("server: initializing crypto backend\n");
knot_crypto_init();
// Create XFR handler
server->xfr = xfr_create(XFR_THREADS_COUNT, server->nameserver);
......
......@@ -40,7 +40,7 @@
#include "knot/server/zones.h"
#include "libknot/nameserver/name-server.h"
#include "libknot/util/wire.h"
#include "libknot/dnssec/cleanup.h"
#include "libknot/dnssec/crypto.h"
/*! \brief TCP worker data. */
typedef struct tcp_worker_t {
......@@ -674,7 +674,7 @@ int tcp_loop_worker(dthread_t *thread)
int tcp_handler_destruct(dthread_t *thread)
{
knot_dnssec_thread_cleanup();
knot_crypto_cleanup_thread();
return KNOT_EOK;
}
......
......@@ -50,7 +50,7 @@
#include "libknot/packet/packet.h"
#include "knot/server/zones.h"
#include "knot/server/notify.h"
#include "libknot/dnssec/cleanup.h"
#include "libknot/dnssec/crypto.h"
/* FD_COPY macro compat. */
#ifndef FD_COPY
......@@ -643,6 +643,6 @@ int udp_master(dthread_t *thread)
int udp_master_destruct(dthread_t *thread)
{
knot_dnssec_thread_cleanup();
knot_crypto_cleanup_thread();
return KNOT_EOK;
}
......@@ -26,7 +26,7 @@
#include "knot/server/zones.h"
#include "knot/zone/zone-load.h"
#include "libknot/dname.h"
#include "libknot/dnssec/cleanup.h"
#include "libknot/dnssec/crypto.h"
#include "libknot/nameserver/name-server.h"
#include "libknot/rdata.h"
#include "libknot/zone/zone.h"
......@@ -695,7 +695,7 @@ static int zone_loader_thread(dthread_t *thread)
static int zone_loader_destruct(dthread_t *thread)
{
knot_dnssec_thread_cleanup();
knot_crypto_cleanup_thread();
return KNOT_EOK;
}
......
/* Copyright (C) 2013 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <pthread.h>
#include "libknot/common.h"
#include "libknot/dnssec/crypto.h"
/*!
* \brief Mutexes to be used by OpenSSL.
*/
static pthread_mutex_t *openssl_mutex = NULL;
static int openssl_mutex_count = 0;
/*!
* \brief Callback for OpenSSL mutex locking and unlocking.
*
* \see CRYPTO_set_locking_callback() in OpenSSL documentation.
*
* \param mode Locking mode.
* \param n Mutex number.
* \param file Source file where locking occurs (for debugging).
* \param line Line number where locking occurs (for debugging).
*/
static void openssl_mutex_cb(int mode, int n, const char *file, int line)
{
UNUSED(file);
UNUSED(line);
assert(openssl_mutex);
assert(n < openssl_mutex_count);
pthread_mutex_t *mutex = &openssl_mutex[n];
if (mode & CRYPTO_LOCK) {
pthread_mutex_lock(mutex);
} else {
pthread_mutex_unlock(mutex);
}
}
/*!
* \brief Initialize mutexes for OpenSSL usage.
*/
static void openssl_mutexes_init(void)
{
assert(openssl_mutex_count == 0);
assert(openssl_mutex == NULL);
openssl_mutex_count = CRYPTO_num_locks();
if (openssl_mutex_count == 0) {
return;
}
openssl_mutex = calloc(openssl_mutex_count, sizeof(pthread_mutex_t));
for (int i = 0; i < openssl_mutex_count; i++) {
pthread_mutex_init(&openssl_mutex[i], NULL);
}
CRYPTO_set_locking_callback(openssl_mutex_cb);
}
/*!
* \brief Destroy mutexes for OpenSSL usage.
*/
static void openssl_mutexes_destroy(void)
{
assert(openssl_mutex);
for (int i = 0; i < openssl_mutex_count; i++) {
pthread_mutex_destroy(&openssl_mutex[i]);
}
free(openssl_mutex);
openssl_mutex_count = 0;
openssl_mutex = NULL;
}
/*!
* \brief Callback for thread identification for purpose of OpenSSL.
*
* \see CRYPTO_THREADID_set_callback() in OpenSSL documentation.
*
* \param openssl_id Thread identifier in OpenSSL.
*/
static void openssl_threadid_cb(CRYPTO_THREADID *openssl_id)
{
pthread_t id = pthread_self();
CRYPTO_THREADID_set_numeric(openssl_id, id);
}
/*- public API --------------------------------------------------------------*/
void knot_crypto_init(void)
{
OpenSSL_add_all_digests();
}
void knot_crypto_cleanup(void)
{
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
knot_crypto_cleanup_thread();
}
void knot_crypto_cleanup_thread(void)
{
ERR_remove_state(0);
}
void knot_crypto_init_threads(void)
{
// locking
if (!openssl_mutex) {
openssl_mutexes_init();
}
// thread identification
CRYPTO_THREADID_set_callback(openssl_threadid_cb);
}
void knot_crypto_cleanup_threads(void)
{
if (openssl_mutex) {
openssl_mutexes_destroy();
}
}
......@@ -14,42 +14,46 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file cleanup.h
* \file crypto.h
*
* \author Jan Vcelak <jan.vcelak@nic.cz>
*
* \brief DNSSEC deinitialization
* \brief Cryptographic backend initialization and clean up.
*
* \addtogroup dnssec
* @{
*/
#ifndef _KNOT_DNSSEC_CLEANUP_H_
#define _KNOT_DNSSEC_CLEANUP_H_
#ifndef _KNOT_DNSSEC_CRYPTO_H_
#define _KNOT_DNSSEC_CRYPTO_H_
#include <openssl/err.h>
#include <openssl/evp.h>
/*!
* \brief Initialize cryptographic backend.
*/
void knot_crypto_init(void);
/*!
* \brief Clean up data allocated by cryptographic backend.
*/
void knot_crypto_cleanup(void);
/*!
* \brief Deinitialize OpenSSL library thread specific data.
* \brief Clean up thread specific data allocated by cryptographic backend.
*/
static inline void knot_dnssec_thread_cleanup(void)
{
ERR_remove_state(0);
}
void knot_crypto_cleanup_thread(void);
/*!
* \brief Deinitialize OpenSSL library.
* \brief Initialize data required for thread-safety of cryptographic backend.
*
* \note Does not include actions performed by knot_crypto_init().
*/
static inline void knot_dnssec_cleanup(void)
{
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
void knot_crypto_init_threads(void);
knot_dnssec_thread_cleanup();
}
/*!
* \brief Clean up allocated data required for thread-safety of crypto backend.
*/
void knot_crypto_cleanup_threads(void);
#endif // _KNOT_DNSSEC_CLEANUP_H_
#endif // _KNOT_DNSSEC_CRYPTO_H_
/*! @} */
......@@ -24,7 +24,7 @@
#include "common/errcode.h"
#include "common/hex.h"
#include "common/strtonum.h"
#include "libknot/dnssec/cleanup.h"
#include "libknot/dnssec/crypto.h"
#include "libknot/dnssec/nsec3.h"
#define PROGRAM_NAME "knsec3hash"
......@@ -115,7 +115,7 @@ int main(int argc, char *argv[])
return 1;
}
atexit(knot_dnssec_cleanup);
atexit(knot_crypto_cleanup);
int exit_code = 1;
knot_nsec3_params_t nsec3_params = { 0 };
......
......@@ -20,11 +20,11 @@
#include "common/errcode.h" // KNOT_EOK
#include "utils/nsupdate/nsupdate_params.h" // params_t
#include "utils/nsupdate/nsupdate_exec.h" // host_exec
#include "libknot/dnssec/cleanup.h" // knot_dnssec_cleanup
#include "libknot/dnssec/crypto.h" // knot_crypto_cleanup
int main(int argc, char *argv[])
{
atexit(knot_dnssec_cleanup);
atexit(knot_crypto_cleanup);
int ret = EXIT_SUCCESS;
......
......@@ -20,8 +20,8 @@
#include <tap/basic.h>
#include "common/errcode.h"
#include "libknot/dnssec/cleanup.h"
#include "libknot/dnssec/config.h"
#include "libknot/dnssec/crypto.h"
#include "libknot/dnssec/sign.h"
#ifdef KNOT_ENABLE_ECDSA
......@@ -141,7 +141,7 @@ int main(int argc, char *argv[])
knot_free_key_params(&kp);
}
knot_dnssec_cleanup();
knot_crypto_cleanup();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment