diff --git a/build-aux/knet_valgrind_memcheck.supp b/build-aux/knet_valgrind_memcheck.supp index 3ad72ff8..efd5eba7 100644 --- a/build-aux/knet_valgrind_memcheck.supp +++ b/build-aux/knet_valgrind_memcheck.supp @@ -1,527 +1,461 @@ -{ - Internal NSPR/NSS leaks (libknet direct) - Memcheck:Leak - match-leak-kinds: definite - fun:calloc - obj:* - obj:* - obj:* - obj:* - obj:* - fun:init_nss_db - fun:nsscrypto_load_lib - fun:crypto_init - fun:knet_handle_crypto - fun:test - fun:main -} -{ - Internal NSPR/NSS leaks (libknet direct) - Memcheck:Leak - match-leak-kinds: definite - fun:malloc - obj:* - obj:* - obj:* - obj:* - obj:* - fun:init_nss_db - fun:nsscrypto_load_lib - fun:crypto_init - fun:knet_handle_crypto - fun:test - fun:main -} -{ - Internal NSPR/NSS leaks (internal crypto test) - Memcheck:Leak - match-leak-kinds: definite - fun:calloc - obj:* - obj:* - obj:* - obj:* - obj:* - fun:init_nss_db - fun:nsscrypto_load_lib - fun:crypto_init - fun:test - fun:main -} -{ - Internal NSPR/NSS leaks (internal crypto test) - Memcheck:Leak - match-leak-kinds: definite - fun:malloc - obj:* - obj:* - obj:* - obj:* - obj:* - fun:init_nss_db - fun:nsscrypto_load_lib - fun:crypto_init - fun:test - fun:main -} { lzma internal stuff Memcheck:Cond fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_stream_header_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_crc32 fun:lzma_stream_header_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_crc32 fun:lzma_stream_header_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:is_overlap fun:memcpy@@GLIBC_2.14 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff Memcheck:Cond fun:memcpy@@GLIBC_2.14 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff Memcheck:Value8 fun:memcpy@@GLIBC_2.14 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff Memcheck:Value8 fun:lzma_vli_encode fun:lzma_filter_flags_encode fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_filter_flags_encode fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:memset fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:memset fun:lzma_block_header_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_block_unpadded_size fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_index_append fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_vli_size fun:lzma_index_append fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_vli_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_vli_encode obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_crc32 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_crc32 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_index_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_stream_footer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Value8 fun:lzma_crc32 fun:lzma_stream_footer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond fun:lzma_crc32 fun:lzma_stream_footer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread fun:clone } { lzma internal stuff Memcheck:Cond obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 obj:/usr/lib64/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } { lzma internal stuff (Debian Unstable) Memcheck:Cond obj:/lib/x86_64-linux-gnu/liblzma.so.5.2.2 obj:/lib/x86_64-linux-gnu/liblzma.so.5.2.2 obj:/lib/x86_64-linux-gnu/liblzma.so.5.2.2 obj:/lib/x86_64-linux-gnu/liblzma.so.5.2.2 fun:lzma_block_buffer_encode fun:lzma_stream_buffer_encode fun:lzma_easy_buffer_encode fun:lzma_compress fun:_parse_recv_from_sock fun:_handle_send_to_links fun:_handle_send_to_links_thread fun:start_thread } diff --git a/libknet/compress.c b/libknet/compress.c index 71852dfc..4e125735 100644 --- a/libknet/compress.c +++ b/libknet/compress.c @@ -1,456 +1,442 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include "internals.h" #include "compress.h" #include "logging.h" #include "threads_common.h" #ifdef BUILDCOMPZLIB #include "compress_zlib.h" #endif #ifdef BUILDCOMPLZ4 #include "compress_lz4.h" #endif #ifdef BUILDCOMPLZO2 #include "compress_lzo2.h" #endif #ifdef BUILDCOMPLZMA #include "compress_lzma.h" #endif #ifdef BUILDCOMPBZIP2 #include "compress_bzip2.h" #endif /* * internal module switch data */ /* * DO NOT CHANGE MODEL_ID HERE OR ONWIRE COMPATIBILITY * WILL BREAK! * * always add before the last NULL/NULL/NULL. */ -#define empty_module 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL }, +#define empty_module 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL }, compress_model_t compress_modules_cmds[] = { { "none", 0, empty_module { "zlib", 1, #ifdef BUILDCOMPZLIB - 1, zlib_load_lib, zlib_unload_lib, 0, 0, NULL, NULL, NULL, zlib_val_level, zlib_compress, zlib_decompress }, + 1, zlib_load_lib, 0, NULL, NULL, NULL, zlib_val_level, zlib_compress, zlib_decompress }, #else empty_module #endif { "lz4", 2, #ifdef BUILDCOMPLZ4 - 1, lz4_load_lib, lz4_unload_lib, 0, 0, NULL, NULL, NULL, lz4_val_level, lz4_compress, lz4_decompress }, + 1, lz4_load_lib, 0, NULL, NULL, NULL, lz4_val_level, lz4_compress, lz4_decompress }, #else empty_module #endif { "lz4hc", 3, #ifdef BUILDCOMPLZ4 - 1, lz4_load_lib, lz4_unload_lib, 0, 0, NULL, NULL, NULL, lz4hc_val_level, lz4hc_compress, lz4_decompress }, + 1, lz4_load_lib, 0, NULL, NULL, NULL, lz4hc_val_level, lz4hc_compress, lz4_decompress }, #else empty_module #endif { "lzo2", 4, #ifdef BUILDCOMPLZO2 - 1, lzo2_load_lib, lzo2_unload_lib, 0, 0, lzo2_is_init, lzo2_init, lzo2_fini, lzo2_val_level, lzo2_compress, lzo2_decompress }, + 1, lzo2_load_lib, 0, lzo2_is_init, lzo2_init, lzo2_fini, lzo2_val_level, lzo2_compress, lzo2_decompress }, #else empty_module #endif { "lzma", 5, #ifdef BUILDCOMPLZMA - 1, lzma_load_lib, lzma_unload_lib, 0, 0, NULL, NULL, NULL, lzma_val_level, lzma_compress, lzma_decompress }, + 1, lzma_load_lib, 0, NULL, NULL, NULL, lzma_val_level, lzma_compress, lzma_decompress }, #else empty_module #endif { "bzip2", 6, #ifdef BUILDCOMPBZIP2 - 1, bzip2_load_lib, bzip2_unload_lib, 0, 0, NULL, NULL, NULL, bzip2_val_level, bzip2_compress, bzip2_decompress }, + 1, bzip2_load_lib, 0, NULL, NULL, NULL, bzip2_val_level, bzip2_compress, bzip2_decompress }, #else empty_module #endif { NULL, 255, empty_module }; static int max_model = 0; static struct timespec last_load_failure; static int compress_get_model(const char *model) { int idx = 0; while (compress_modules_cmds[idx].model_name != NULL) { if (!strcmp(compress_modules_cmds[idx].model_name, model)) { return compress_modules_cmds[idx].model_id; } idx++; } return -1; } static int compress_get_max_model(void) { int idx = 0; while (compress_modules_cmds[idx].model_name != NULL) { idx++; } return idx - 1; } static int compress_is_valid_model(int compress_model) { int idx = 0; while (compress_modules_cmds[idx].model_name != NULL) { if ((compress_model == compress_modules_cmds[idx].model_id) && (compress_modules_cmds[idx].built_in == 1)) { return 0; } idx++; } return -1; } static int val_level( knet_handle_t knet_h, int compress_model, int compress_level) { return compress_modules_cmds[compress_model].val_level(knet_h, compress_level); } /* * compress_check_lib_is_init needs to be invoked in a locked context! */ static int compress_check_lib_is_init(knet_handle_t knet_h, int cmp_model) { /* - * if the module is already loaded and init for this handle, - * we will return and keep the lock to avoid any race condition - * on other threads potentially unloading or reloading. - * * lack of a .is_init function means that the module does not require * init per handle so we use a fake reference in the compress_int_data * to identify that we already increased the libref for this handle */ if (compress_modules_cmds[cmp_model].loaded == 1) { if (compress_modules_cmds[cmp_model].is_init == NULL) { if (knet_h->compress_int_data[cmp_model] != NULL) { return 1; } } else { if (compress_modules_cmds[cmp_model].is_init(knet_h, cmp_model) == 1) { return 1; } } } return 0; } /* * compress_load_lib should _always_ be invoked in write lock context */ static int compress_load_lib(knet_handle_t knet_h, int cmp_model, int rate_limit) { struct timespec clock_now; unsigned long long timediff; /* * checking again for paranoia and because * compress_check_lib_is_init is usually invoked in read context * and we need to switch from read to write locking in between. * another thread might have init the library in the meantime */ if (compress_check_lib_is_init(knet_h, cmp_model)) { return 0; } /* * due to the fact that decompress can load libraries * on demand, depending on the compress model selected * on other nodes, it is possible for an attacker * to send crafted packets to attempt to load libraries * at random in a DoS fashion. * If there is an error loading a library, then we want * to rate_limit a retry to reload the library every X * seconds to avoid a lock DoS that could greatly slow * down libknet. */ if (rate_limit) { if ((last_load_failure.tv_sec != 0) || (last_load_failure.tv_nsec != 0)) { clock_gettime(CLOCK_MONOTONIC, &clock_now); timespec_diff(last_load_failure, clock_now, &timediff); if (timediff < 10000000000) { errno = EAGAIN; return -1; } } } if (compress_modules_cmds[cmp_model].loaded == 0) { if (compress_modules_cmds[cmp_model].load_lib(knet_h) < 0) { clock_gettime(CLOCK_MONOTONIC, &last_load_failure); return -1; } compress_modules_cmds[cmp_model].loaded = 1; } if (compress_modules_cmds[cmp_model].init != NULL) { if (compress_modules_cmds[cmp_model].init(knet_h, cmp_model) < 0) { return -1; } } else { knet_h->compress_int_data[cmp_model] = (void *)&"1"; } - compress_modules_cmds[cmp_model].libref++; - return 0; } int compress_init( knet_handle_t knet_h) { max_model = compress_get_max_model(); if (max_model > KNET_MAX_COMPRESS_METHODS) { log_err(knet_h, KNET_SUB_COMPRESS, "Too many compress methods defined in compress.c."); errno = EINVAL; return -1; } memset(&last_load_failure, 0, sizeof(struct timespec)); return 0; } int compress_cfg( knet_handle_t knet_h, struct knet_handle_compress_cfg *knet_handle_compress_cfg) { int savederrno = 0, err = 0; int cmp_model; cmp_model = compress_get_model(knet_handle_compress_cfg->compress_model); if (cmp_model < 0) { log_err(knet_h, KNET_SUB_COMPRESS, "compress model %s not supported", knet_handle_compress_cfg->compress_model); errno = EINVAL; return -1; } log_debug(knet_h, KNET_SUB_COMPRESS, "Initizializing compress module [%s/%d/%u]", knet_handle_compress_cfg->compress_model, knet_handle_compress_cfg->compress_level, knet_handle_compress_cfg->compress_threshold); if (cmp_model > 0) { if (compress_modules_cmds[cmp_model].built_in == 0) { log_err(knet_h, KNET_SUB_COMPRESS, "compress model %s support has not been built in. Please contact your vendor or fix the build", knet_handle_compress_cfg->compress_model); errno = EINVAL; return -1; } if (knet_handle_compress_cfg->compress_threshold > KNET_MAX_PACKET_SIZE) { log_err(knet_h, KNET_SUB_COMPRESS, "compress threshold cannot be higher than KNET_MAX_PACKET_SIZE (%d).", KNET_MAX_PACKET_SIZE); errno = EINVAL; return -1; } if (knet_handle_compress_cfg->compress_threshold == 0) { knet_h->compress_threshold = KNET_COMPRESS_THRESHOLD; log_debug(knet_h, KNET_SUB_COMPRESS, "resetting compression threshold to default (%d)", KNET_COMPRESS_THRESHOLD); } else { knet_h->compress_threshold = knet_handle_compress_cfg->compress_threshold; } savederrno = pthread_rwlock_rdlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get read lock: %s", strerror(savederrno)); errno = savederrno; return -1; } if (!compress_check_lib_is_init(knet_h, cmp_model)) { /* * need to switch to write lock, load the lib, and return with a write lock * this is not racy because compress_load_lib is written idempotent. */ pthread_rwlock_unlock(&shlib_rwlock); savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s", strerror(savederrno)); errno = savederrno; return -1; } if (compress_load_lib(knet_h, cmp_model, 0) < 0) { savederrno = errno; log_err(knet_h, KNET_SUB_COMPRESS, "Unable to load library: %s", strerror(savederrno)); err = -1; goto out_unlock; } } if (val_level(knet_h, cmp_model, knet_handle_compress_cfg->compress_level) < 0) { log_err(knet_h, KNET_SUB_COMPRESS, "compress level %d not supported for model %s", knet_handle_compress_cfg->compress_level, knet_handle_compress_cfg->compress_model); savederrno = EINVAL; err = -1; goto out_unlock; } out_unlock: pthread_rwlock_unlock(&shlib_rwlock); } if (!err) { knet_h->compress_model = cmp_model; knet_h->compress_level = knet_handle_compress_cfg->compress_level; } else { knet_h->compress_model = 0; } errno = savederrno; return err; } void compress_fini( knet_handle_t knet_h, int all) { int savederrno = 0; int idx = 0; savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s", strerror(savederrno)); return; } while (compress_modules_cmds[idx].model_name != NULL) { if ((compress_modules_cmds[idx].built_in == 1) && (compress_modules_cmds[idx].loaded == 1) && (compress_modules_cmds[idx].model_id > 0) && (knet_h->compress_int_data[idx] != NULL) && (idx < KNET_MAX_COMPRESS_METHODS)) { if ((all) || (compress_modules_cmds[idx].model_id == knet_h->compress_model)) { if (compress_modules_cmds[idx].fini != NULL) { compress_modules_cmds[idx].fini(knet_h, idx); } else { knet_h->compress_int_data[idx] = NULL; } - compress_modules_cmds[idx].libref--; - - if ((compress_modules_cmds[idx].libref == 0) && - (compress_modules_cmds[idx].loaded == 1)) { - log_debug(knet_h, KNET_SUB_COMPRESS, "Unloading %s library", compress_modules_cmds[idx].model_name); - compress_modules_cmds[idx].unload_lib(knet_h); - compress_modules_cmds[idx].loaded = 0; - } } } idx++; } pthread_rwlock_unlock(&shlib_rwlock); return; } /* * compress does not require compress_check_lib_is_init * because it's protected by compress_cfg */ int compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { return compress_modules_cmds[knet_h->compress_model].compress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); } int decompress( knet_handle_t knet_h, int compress_model, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int savederrno = 0, err = 0; if (compress_model > max_model) { log_err(knet_h, KNET_SUB_COMPRESS, "Received packet with unknown compress model %d", compress_model); errno = EINVAL; return -1; } if (compress_is_valid_model(compress_model) < 0) { log_err(knet_h, KNET_SUB_COMPRESS, "Received packet compressed with %s but support is not built in this version of libknet. Please contact your distribution vendor or fix the build.", compress_modules_cmds[compress_model].model_name); errno = EINVAL; return -1; } savederrno = pthread_rwlock_rdlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get read lock: %s", strerror(savederrno)); errno = savederrno; return -1; } if (!compress_check_lib_is_init(knet_h, compress_model)) { /* * need to switch to write lock, load the lib, and return with a write lock * this is not racy because compress_load_lib is written idempotent. */ pthread_rwlock_unlock(&shlib_rwlock); savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s", strerror(savederrno)); errno = savederrno; return -1; } if (compress_load_lib(knet_h, compress_model, 1) < 0) { savederrno = errno; err = -1; log_err(knet_h, KNET_SUB_COMPRESS, "Unable to load library: %s", strerror(savederrno)); goto out_unlock; } } err = compress_modules_cmds[compress_model].decompress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); savederrno = errno; out_unlock: pthread_rwlock_unlock(&shlib_rwlock); errno = savederrno; return err; } diff --git a/libknet/compress.h b/libknet/compress.h index 9ba85c99..16ea1f19 100644 --- a/libknet/compress.h +++ b/libknet/compress.h @@ -1,128 +1,118 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_COMPRESS_H__ #define __KNET_COMPRESS_H__ #include "internals.h" typedef struct { const char *model_name; uint8_t model_id; /* sequencial unique identifier */ uint8_t built_in; /* set at configure/build time to 1 if available */ /* - * shared lib load/unload functions + * shared lib load functions * * both are called in shlib_rwlock write context and should * update the loaded status below. */ int (*load_lib) (knet_handle_t knet_h); - /* - * unload_lib will call dlclose only after all handles using - * the given shared lib have finished using it. - */ - void (*unload_lib) (knet_handle_t knet_h); - /* * library is loaded */ uint8_t loaded; - /* - * number of users for this library - */ - uint8_t libref; /* * runtime bits */ /* * some libs need special init and handling of buffers etc. * is_init is called in shlib_rwlock read only context to see if * the module has been initialized within this knet_handle. * Providing is_init is optional. A module that does not export * an is_init and if the associated shared library is already loaded * is treated as "does not require init". */ int (*is_init) (knet_handle_t knet_h, int method_idx); /* * init is called when the library requires special init handling, * such as memory allocation and such. * init is invoked in shlib_rwlock write only context when * the module exports this function. * It is optional to provide an init function if the module * does not require any init. */ int (*init) (knet_handle_t knet_h, int method_idx); /* * fini is invoked only on knet_handle_free in a write only context. * It is optional to provide this function if the module * does not require any finalization */ void (*fini) (knet_handle_t knet_h, int method_idx); /* * runtime config validation and compress/decompress */ /* * required functions * * val_level is called upon compress configuration changes * to make sure that the requested compress_level is valid * within the context of a given module. */ int (*val_level)(knet_handle_t knet_h, int compress_level); /* * hopefully those 2 don't require any explanation.... */ int (*compress) (knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int (*decompress)(knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); } compress_model_t; int compress_cfg( knet_handle_t knet_h, struct knet_handle_compress_cfg *knet_handle_compress_cfg); int compress_init( knet_handle_t knet_h); void compress_fini( knet_handle_t knet_h, int all); int compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int decompress( knet_handle_t knet_h, int compress_model, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); #endif diff --git a/libknet/compress_bzip2.c b/libknet/compress_bzip2.c index c62f127c..16ca30c3 100644 --- a/libknet/compress_bzip2.c +++ b/libknet/compress_bzip2.c @@ -1,203 +1,190 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #ifdef BUILDCOMPBZIP2 #include #include "internals.h" #include "compress_bzip2.h" #include "logging.h" #include "common.h" #define LIBBZ2_1 "libbz2.so.1" /* * global vars for dlopen */ static void *bzip2_lib; /* * symbols remapping */ int (*_int_BZ2_bzBuffToBuffCompress)(char* dest, unsigned int* destLen, char* source, unsigned int sourceLen, int blockSize100k, int verbosity, int workFactor); int (*_int_BZ2_bzBuffToBuffDecompress)(char* dest, unsigned int* destLen, char* source, unsigned int sourceLen, int samll, int verbosity); static int bzip2_remap_symbols(knet_handle_t knet_h) { int err = 0; char *error = NULL; _int_BZ2_bzBuffToBuffCompress = dlsym(bzip2_lib, "BZ2_bzBuffToBuffCompress"); if (!_int_BZ2_bzBuffToBuffCompress) { error = dlerror(); log_err(knet_h, KNET_SUB_BZIP2COMP, "unable to map BZ2_bzBuffToBuffCompress: %s", error); err = -1; goto out; } _int_BZ2_bzBuffToBuffDecompress = dlsym(bzip2_lib, "BZ2_bzBuffToBuffDecompress"); if (!_int_BZ2_bzBuffToBuffDecompress) { error = dlerror(); log_err(knet_h, KNET_SUB_BZIP2COMP, "unable to map BZ2_bzBuffToBuffDecompress: %s", error); err = -1; goto out; } out: if (err) { errno = EINVAL; } return err; } int bzip2_load_lib( knet_handle_t knet_h) { int err = 0, savederrno = 0; if (!bzip2_lib) { bzip2_lib = open_lib(knet_h, LIBBZ2_1, 0); if (!bzip2_lib) { savederrno = errno; err = -1; goto out; } + } - if (bzip2_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - dlclose(bzip2_lib); - bzip2_lib = NULL; - goto out; - } + if (bzip2_remap_symbols(knet_h) < 0) { + savederrno = errno; + err = -1; } out: errno = savederrno; return err; } -void bzip2_unload_lib( - knet_handle_t knet_h) -{ - if (bzip2_lib) { - dlclose(bzip2_lib); - bzip2_lib = NULL; - } - return; -} - int bzip2_val_level( knet_handle_t knet_h, int compress_level) { if ((compress_level < 1) || (compress_level > 9)) { log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 unsupported compression level %d (accepted values from 1 to 9)", compress_level); errno = EINVAL; return -1; } return 0; } int bzip2_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int err = 0; int savederrno = 0; unsigned int destLen = KNET_DATABUFSIZE_COMPRESS; err = (*_int_BZ2_bzBuffToBuffCompress)((char *)buf_out, &destLen, (char *)buf_in, buf_in_len, knet_h->compress_level, 0, 0); switch(err) { case BZ_OK: *buf_out_len = destLen; break; case BZ_MEM_ERROR: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 compress has not enough memory"); savederrno = ENOMEM; err = -1; break; case BZ_OUTBUFF_FULL: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 unable to compress source in destination buffer"); savederrno = E2BIG; err = -1; break; default: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 compress unknown error %d", err); savederrno = EINVAL; err = -1; break; } errno = savederrno; return err; } int bzip2_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int err = 0; int savederrno = 0; unsigned int destLen = KNET_DATABUFSIZE_COMPRESS; err = (*_int_BZ2_bzBuffToBuffDecompress)((char *)buf_out, &destLen, (char *)buf_in, buf_in_len, 0, 0); switch(err) { case BZ_OK: *buf_out_len = destLen; break; case BZ_MEM_ERROR: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 decompress has not enough memory"); savederrno = ENOMEM; err = -1; break; case BZ_OUTBUFF_FULL: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 unable to decompress source in destination buffer"); savederrno = E2BIG; err = -1; break; case BZ_DATA_ERROR: case BZ_DATA_ERROR_MAGIC: case BZ_UNEXPECTED_EOF: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 decompress detected input data corruption"); savederrno = EINVAL; err = -1; break; default: log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 decompress unknown error %d", err); savederrno = EINVAL; err = -1; break; } errno = savederrno; return err; } #endif diff --git a/libknet/compress_bzip2.h b/libknet/compress_bzip2.h index 92e468e8..8c98e934 100644 --- a/libknet/compress_bzip2.h +++ b/libknet/compress_bzip2.h @@ -1,38 +1,35 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_COMPRESS_BZIP2_H__ #define __KNET_COMPRESS_BZIP2_H__ #include "internals.h" int bzip2_load_lib( knet_handle_t knet_h); -void bzip2_unload_lib( - knet_handle_t knet_h); - int bzip2_val_level( knet_handle_t knet_h, int compress_level); int bzip2_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int bzip2_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); #endif diff --git a/libknet/compress_lz4.c b/libknet/compress_lz4.c index f5c38705..3e285fe2 100644 --- a/libknet/compress_lz4.c +++ b/libknet/compress_lz4.c @@ -1,256 +1,243 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #ifdef BUILDCOMPLZ4 #include #include "internals.h" #include "compress_lz4.h" #include "logging.h" #include "common.h" #define LIBLZ4_1 "liblz4.so.1" /* * global vars for dlopen */ static void *lz4_lib; /* * symbols remapping */ int (*_int_LZ4_compress_HC)(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel); int (*_int_LZ4_compress_fast)(const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration); int (*_int_LZ4_decompress_safe)(const char* source, char* dest, int compressedSize, int maxDecompressedSize); static int lz4_remap_symbols(knet_handle_t knet_h) { int err = 0; char *error = NULL; _int_LZ4_compress_HC = dlsym(lz4_lib, "LZ4_compress_HC"); if (!_int_LZ4_compress_HC) { error = dlerror(); log_err(knet_h, KNET_SUB_LZ4COMP, "unable to map LZ4_compress_HC: %s", error); err = -1; goto out; } _int_LZ4_compress_fast = dlsym(lz4_lib, "LZ4_compress_fast"); if (!_int_LZ4_compress_fast) { error = dlerror(); log_err(knet_h, KNET_SUB_LZ4COMP, "unable to map LZ4_compress_fast: %s", error); err = -1; goto out; } _int_LZ4_decompress_safe = dlsym(lz4_lib, "LZ4_decompress_safe"); if (!_int_LZ4_decompress_safe) { error = dlerror(); log_err(knet_h, KNET_SUB_LZ4COMP, "unable to map LZ4_decompress_safe: %s", error); err = -1; goto out; } out: if (err) { _int_LZ4_compress_HC = NULL; _int_LZ4_compress_fast = NULL; _int_LZ4_decompress_safe = NULL; errno = EINVAL; } return err; } int lz4_load_lib( knet_handle_t knet_h) { int err = 0, savederrno = 0; if (!lz4_lib) { lz4_lib = open_lib(knet_h, LIBLZ4_1, 0); if (!lz4_lib) { savederrno = EAGAIN; err = -1; goto out; } + } - if (lz4_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - dlclose(lz4_lib); - lz4_lib = NULL; - goto out; - } + if (lz4_remap_symbols(knet_h) < 0) { + savederrno = errno; + err = -1; } out: errno = savederrno; return err; } -void lz4_unload_lib( - knet_handle_t knet_h) -{ - if (lz4_lib) { - dlclose(lz4_lib); - lz4_lib = NULL; - } - return; -} - int lz4_val_level( knet_handle_t knet_h, int compress_level) { if (compress_level <= 0) { log_info(knet_h, KNET_SUB_LZ4COMP, "lz4 acceleration level 0 (or negatives) are automatically remapped to 1 by %s", LIBLZ4_1); } return 0; } int lz4_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int lzerr = 0, err = 0; int savederrno = 0; lzerr = (*_int_LZ4_compress_fast)((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE_COMPRESS, knet_h->compress_level); /* * data compressed */ if (lzerr > 0) { *buf_out_len = lzerr; } /* * unable to compress */ if (lzerr == 0) { *buf_out_len = buf_in_len; } /* * lz4 internal error */ if (lzerr < 0) { log_err(knet_h, KNET_SUB_LZ4COMP, "lz4 compression error: %d", lzerr); savederrno = EINVAL; err = -1; } errno = savederrno; return err; } #ifdef LZ4HC_CLEVEL_MAX #define KNET_LZ4HC_MAX LZ4HC_CLEVEL_MAX #endif #ifdef LZ4HC_MAX_CLEVEL #define KNET_LZ4HC_MAX LZ4HC_MAX_CLEVEL #endif #ifndef KNET_LZ4HC_MAX #define KNET_LZ4HC_MAX 0 #error Please check lz4hc.h for missing LZ4HC_CLEVEL_MAX or LZ4HC_MAX_CLEVEL variants #endif int lz4hc_val_level( knet_handle_t knet_h, int compress_level) { if (compress_level < 1) { log_err(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc supports only 1+ values for compression level"); errno = EINVAL; return -1; } if (compress_level < 4) { log_info(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc recommends 4+ compression level for better results"); } if (compress_level > KNET_LZ4HC_MAX) { log_warn(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc installed on this system supports up to compression level %d. Higher values behaves as %d", KNET_LZ4HC_MAX, KNET_LZ4HC_MAX); } return 0; } int lz4hc_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int lzerr = 0, err = 0; int savederrno = 0; lzerr = (*_int_LZ4_compress_HC)((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE_COMPRESS, knet_h->compress_level); /* * data compressed */ if (lzerr > 0) { *buf_out_len = lzerr; } /* * unable to compress */ if (lzerr <= 0) { log_err(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc compression error: %d", lzerr); savederrno = EINVAL; err = -1; } errno = savederrno; return err; } int lz4_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int lzerr = 0, err = 0; int savederrno = 0; lzerr = (*_int_LZ4_decompress_safe)((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE); if (lzerr < 0) { log_err(knet_h, KNET_SUB_LZ4COMP, "lz4 decompression error: %d", lzerr); savederrno = EINVAL; err = -1; } if (lzerr > 0) { *buf_out_len = lzerr; } errno = savederrno; return err; } #endif diff --git a/libknet/compress_lz4.h b/libknet/compress_lz4.h index 298c9cec..6c1b5017 100644 --- a/libknet/compress_lz4.h +++ b/libknet/compress_lz4.h @@ -1,49 +1,46 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_COMPRESS_LZ4_H__ #define __KNET_COMPRESS_LZ4_H__ #include "internals.h" int lz4_load_lib( knet_handle_t knet_h); -void lz4_unload_lib( - knet_handle_t knet_h); - int lz4_val_level( knet_handle_t knet_h, int compress_level); int lz4_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int lz4hc_val_level( knet_handle_t knet_h, int compress_level); int lz4hc_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int lz4_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); #endif diff --git a/libknet/compress_lzma.c b/libknet/compress_lzma.c index 92ffed17..c3df36b4 100644 --- a/libknet/compress_lzma.c +++ b/libknet/compress_lzma.c @@ -1,218 +1,205 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #ifdef BUILDCOMPLZMA #include #include "internals.h" #include "compress_lzma.h" #include "logging.h" #include "common.h" #define LIBLZMA_5 "liblzma.so.5" /* * global vars for dlopen */ static void *lzma_lib; /* * symbols remapping */ int (*_int_lzma_easy_buffer_encode)( uint32_t preset, lzma_check check, const lzma_allocator *allocator, const uint8_t *in, size_t in_size, uint8_t *out, size_t *out_pos, size_t out_size); int (*_int_lzma_stream_buffer_decode)( uint64_t *memlimit, uint32_t flags, const lzma_allocator *allocator, const uint8_t *in, size_t *in_pos, size_t in_size, uint8_t *out, size_t *out_pos, size_t out_size); static int lzma_remap_symbols(knet_handle_t knet_h) { int err = 0; char *error = NULL; _int_lzma_easy_buffer_encode = dlsym(lzma_lib, "lzma_easy_buffer_encode"); if (!_int_lzma_easy_buffer_encode) { error = dlerror(); log_err(knet_h, KNET_SUB_LZMACOMP, "unable to map lzma_easy_buffer_encode: %s", error); err = -1; goto out; } _int_lzma_stream_buffer_decode = dlsym(lzma_lib, "lzma_stream_buffer_decode"); if (!_int_lzma_stream_buffer_decode) { error = dlerror(); log_err(knet_h, KNET_SUB_LZMACOMP, "unable to map lzma_stream_buffer_decode: %s", error); err = -1; goto out; } out: if (err) { errno = EINVAL; } return err; } int lzma_load_lib( knet_handle_t knet_h) { int err = 0, savederrno = 0; if (!lzma_lib) { lzma_lib = open_lib(knet_h, LIBLZMA_5, 0); if (!lzma_lib) { savederrno = EAGAIN; err = -1; goto out; } + } - if (lzma_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - dlclose(lzma_lib); - lzma_lib = NULL; - goto out; - } + if (lzma_remap_symbols(knet_h) < 0) { + savederrno = errno; + err = -1; } out: errno = savederrno; return err; } -void lzma_unload_lib( - knet_handle_t knet_h) -{ - if (lzma_lib) { - dlclose(lzma_lib); - lzma_lib = NULL; - } - return; -} - int lzma_val_level( knet_handle_t knet_h, int compress_level) { if ((compress_level < 0) || (compress_level > 9)) { log_err(knet_h, KNET_SUB_LZMACOMP, "lzma unsupported compression preset %d (accepted values from 0 to 9)", compress_level); errno = EINVAL; return -1; } return 0; } int lzma_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int err = 0; int savederrno = 0; size_t out_pos = 0; lzma_ret ret = 0; ret = (*_int_lzma_easy_buffer_encode)(knet_h->compress_level, LZMA_CHECK_NONE, NULL, (const uint8_t *)buf_in, buf_in_len, (uint8_t *)buf_out, &out_pos, KNET_DATABUFSIZE_COMPRESS); switch(ret) { case LZMA_OK: *buf_out_len = out_pos; break; case LZMA_MEM_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress memory allocation failed"); savederrno = ENOMEM; err = -1; break; case LZMA_MEMLIMIT_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress requires higher memory boundaries (see lzma_memlimit_set)"); savederrno = ENOMEM; err = -1; break; case LZMA_PROG_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress has been called with incorrect options"); savederrno = EINVAL; err = -1; break; default: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress unknown error %u", ret); savederrno = EINVAL; err = -1; break; } errno = savederrno; return err; } int lzma_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int err = 0; int savederrno = 0; uint64_t memlimit = UINT64_MAX; /* disable lzma internal memlimit check */ size_t out_pos = 0, in_pos = 0; lzma_ret ret = 0; ret = (*_int_lzma_stream_buffer_decode)(&memlimit, 0, NULL, (const uint8_t *)buf_in, &in_pos, buf_in_len, (uint8_t *)buf_out, &out_pos, KNET_DATABUFSIZE_COMPRESS); switch(ret) { case LZMA_OK: *buf_out_len = out_pos; break; case LZMA_MEM_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress memory allocation failed"); savederrno = ENOMEM; err = -1; break; case LZMA_MEMLIMIT_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress requires higher memory boundaries (see lzma_memlimit_set)"); savederrno = ENOMEM; err = -1; break; case LZMA_DATA_ERROR: case LZMA_FORMAT_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress invalid data received"); savederrno = EINVAL; err = -1; break; case LZMA_PROG_ERROR: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress has been called with incorrect options"); savederrno = EINVAL; err = -1; break; default: log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress unknown error %u", ret); savederrno = EINVAL; err = -1; break; } errno = savederrno; return err; } #endif diff --git a/libknet/compress_lzma.h b/libknet/compress_lzma.h index 5f70621b..a7bb4fc9 100644 --- a/libknet/compress_lzma.h +++ b/libknet/compress_lzma.h @@ -1,38 +1,35 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_COMPRESS_LZMA_H__ #define __KNET_COMPRESS_LZMA_H__ #include "internals.h" int lzma_load_lib( knet_handle_t knet_h); -void lzma_unload_lib( - knet_handle_t knet_h); - int lzma_val_level( knet_handle_t knet_h, int compress_level); int lzma_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int lzma_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); #endif diff --git a/libknet/compress_lzo2.c b/libknet/compress_lzo2.c index bd00ffc0..1df53aad 100644 --- a/libknet/compress_lzo2.c +++ b/libknet/compress_lzo2.c @@ -1,292 +1,278 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #ifdef BUILDCOMPLZO2 #include #include "internals.h" #include "compress_lzo2.h" #include "logging.h" #include "common.h" #define LIBLZO2_2 "liblzo2.so.2" /* * global vars for dlopen */ static void *lzo2_lib; /* * symbols remapping */ int (*_int_lzo1x_decompress)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem /* NOT USED */ ); int (*_int_lzo1x_1_compress)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem); int (*_int_lzo1x_1_11_compress)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem); int (*_int_lzo1x_1_12_compress)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem); int (*_int_lzo1x_1_15_compress)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem); int (*_int_lzo1x_999_compress)(const lzo_bytep src, lzo_uint src_len, lzo_bytep dst, lzo_uintp dst_len, lzo_voidp wrkmem); static int lzo2_remap_symbols(knet_handle_t knet_h) { int err = 0; char *error = NULL; _int_lzo1x_decompress = dlsym(lzo2_lib, "lzo1x_decompress"); if (!_int_lzo1x_decompress) { error = dlerror(); log_err(knet_h, KNET_SUB_LZO2COMP, "unable to map lzo1x_decompress: %s", error); err = -1; goto out; } _int_lzo1x_1_compress = dlsym(lzo2_lib, "lzo1x_1_compress"); if (!_int_lzo1x_1_compress) { error = dlerror(); log_err(knet_h, KNET_SUB_LZO2COMP, "unable to map lzo1x_1_compress: %s", error); err = -1; goto out; } _int_lzo1x_1_11_compress = dlsym(lzo2_lib, "lzo1x_1_11_compress"); if (!_int_lzo1x_1_11_compress) { error = dlerror(); log_err(knet_h, KNET_SUB_LZO2COMP, "unable to map lzo1x_1_11_compress: %s", error); err = -1; goto out; } _int_lzo1x_1_12_compress = dlsym(lzo2_lib, "lzo1x_1_12_compress"); if (!_int_lzo1x_1_12_compress) { error = dlerror(); log_err(knet_h, KNET_SUB_LZO2COMP, "unable to map lzo1x_1_12_compress: %s", error); err = -1; goto out; } _int_lzo1x_1_15_compress = dlsym(lzo2_lib, "lzo1x_1_15_compress"); if (!_int_lzo1x_1_15_compress) { error = dlerror(); log_err(knet_h, KNET_SUB_LZO2COMP, "unable to map lzo1x_1_15_compress: %s", error); err = -1; goto out; } _int_lzo1x_999_compress = dlsym(lzo2_lib, "lzo1x_999_compress"); if (!_int_lzo1x_999_compress) { error = dlerror(); log_err(knet_h, KNET_SUB_LZO2COMP, "unable to map lzo1x_999_compress: %s", error); err = -1; goto out; } out: if (err) { _int_lzo1x_decompress = NULL; _int_lzo1x_1_compress = NULL; _int_lzo1x_1_11_compress = NULL; _int_lzo1x_1_12_compress = NULL; _int_lzo1x_1_15_compress = NULL; _int_lzo1x_999_compress = NULL; errno = EINVAL; } return err; } int lzo2_load_lib( knet_handle_t knet_h) { int err = 0, savederrno = 0; if (!lzo2_lib) { lzo2_lib = open_lib(knet_h, LIBLZO2_2, 0); if (!lzo2_lib) { savederrno = EAGAIN; err = -1; goto out; } - - if (lzo2_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - dlclose(lzo2_lib); - lzo2_lib = NULL; - goto out; - } } + if (lzo2_remap_symbols(knet_h) < 0) { + savederrno = errno; + err = -1; + } out: errno = savederrno; return err; } -void lzo2_unload_lib( - knet_handle_t knet_h) -{ - if (lzo2_lib) { - dlclose(lzo2_lib); - lzo2_lib = NULL; - } - return; -} - int lzo2_is_init( knet_handle_t knet_h, int method_idx) { if (knet_h->compress_int_data[method_idx]) { return 1; } return 0; } int lzo2_init( knet_handle_t knet_h, int method_idx) { /* * LZO1X_999_MEM_COMPRESS is the highest amount of memory lzo2 can use */ if (!knet_h->compress_int_data[method_idx]) { knet_h->compress_int_data[method_idx] = malloc(LZO1X_999_MEM_COMPRESS); if (!knet_h->compress_int_data[method_idx]) { log_err(knet_h, KNET_SUB_LZO2COMP, "lzo2 unable to allocate work memory"); errno = ENOMEM; return -1; } memset(knet_h->compress_int_data[method_idx], 0, LZO1X_999_MEM_COMPRESS); } return 0; } void lzo2_fini( knet_handle_t knet_h, int method_idx) { if (knet_h->compress_int_data[method_idx]) { free(knet_h->compress_int_data[method_idx]); knet_h->compress_int_data[method_idx] = NULL; } return; } int lzo2_val_level( knet_handle_t knet_h, int compress_level) { switch(compress_level) { case 1: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_compress internal compress method"); break; case 11: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_11_compress internal compress method"); break; case 12: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_12_compress internal compress method"); break; case 15: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_15_compress internal compress method"); break; case 999: log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_999_compress internal compress method"); break; default: log_warn(knet_h, KNET_SUB_LZO2COMP, "Unknown lzo2 internal compress method. lzo1x_1_compress will be used as default fallback"); break; } return 0; } int lzo2_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int savederrno = 0, lzerr = 0, err = 0; lzo_uint cmp_len; switch(knet_h->compress_level) { case 1: lzerr = (*_int_lzo1x_1_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; case 11: lzerr = (*_int_lzo1x_1_11_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; case 12: lzerr = (*_int_lzo1x_1_12_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; case 15: lzerr = (*_int_lzo1x_1_15_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; case 999: lzerr = (*_int_lzo1x_999_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; default: lzerr = (*_int_lzo1x_1_compress)(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]); break; } if (lzerr != LZO_E_OK) { log_err(knet_h, KNET_SUB_LZO2COMP, "lzo2 internal compression error"); savederrno = EAGAIN; err = -1; } else { *buf_out_len = cmp_len; } errno = savederrno; return err; } int lzo2_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int lzerr = 0, err = 0; int savederrno = 0; lzo_uint decmp_len; lzerr = (*_int_lzo1x_decompress)(buf_in, buf_in_len, buf_out, &decmp_len, NULL); if (lzerr != LZO_E_OK) { log_err(knet_h, KNET_SUB_LZO2COMP, "lzo2 internal decompression error"); savederrno = EAGAIN; err = -1; } else { *buf_out_len = decmp_len; } errno = savederrno; return err; } #endif diff --git a/libknet/compress_lzo2.h b/libknet/compress_lzo2.h index 0a8b0630..2080a274 100644 --- a/libknet/compress_lzo2.h +++ b/libknet/compress_lzo2.h @@ -1,50 +1,47 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_COMPRESS_LZO2_H__ #define __KNET_COMPRESS_LZO2_H__ #include "internals.h" int lzo2_load_lib( knet_handle_t knet_h); -void lzo2_unload_lib( - knet_handle_t knet_h); - int lzo2_is_init( knet_handle_t knet_h, int method_idx); int lzo2_init( knet_handle_t knet_h, int method_idx); void lzo2_fini( knet_handle_t knet_h, int method_idx); int lzo2_val_level( knet_handle_t knet_h, int compress_level); int lzo2_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int lzo2_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); #endif diff --git a/libknet/compress_zlib.c b/libknet/compress_zlib.c index 1d5472aa..813d3f7a 100644 --- a/libknet/compress_zlib.c +++ b/libknet/compress_zlib.c @@ -1,214 +1,201 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #ifdef BUILDCOMPZLIB #include #include "internals.h" #include "compress_zlib.h" #include "logging.h" #include "common.h" #define LIBZ_1 "libz.so.1" /* * global vars for dlopen */ static void *zlib_lib; /* * symbols remapping */ int (*_int_uncompress)(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); int (*_int_compress2)(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); static int zlib_remap_symbols(knet_handle_t knet_h) { int err = 0; char *error = NULL; _int_uncompress = dlsym(zlib_lib, "uncompress"); if (!_int_uncompress) { error = dlerror(); log_err(knet_h, KNET_SUB_ZLIBCOMP, "unable to map uncompress: %s", error); err = -1; goto out; } _int_compress2 = dlsym(zlib_lib, "compress2"); if (!_int_compress2) { error = dlerror(); log_err(knet_h, KNET_SUB_ZLIBCOMP, "unable to map compress2: %s", error); err = -1; goto out; } out: if (err) { _int_uncompress = NULL; _int_compress2 = NULL; errno = EINVAL; } return err; } int zlib_load_lib( knet_handle_t knet_h) { int err = 0, savederrno = 0; if (!zlib_lib) { zlib_lib = open_lib(knet_h, LIBZ_1, 0); if (!zlib_lib) { savederrno = EAGAIN; err = -1; goto out; } + } - if (zlib_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - dlclose(zlib_lib); - zlib_lib = NULL; - goto out; - } + if (zlib_remap_symbols(knet_h) < 0) { + savederrno = errno; + err = -1; } out: errno = savederrno; return err; } -void zlib_unload_lib( - knet_handle_t knet_h) -{ - if (zlib_lib) { - dlclose(zlib_lib); - zlib_lib = NULL; - } - return; -} - int zlib_val_level( knet_handle_t knet_h, int compress_level) { if (compress_level < 0) { log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib does not support negative compression level %d", compress_level); return -1; } if (compress_level > 9) { log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib does not support compression level higher than 9"); return -1; } if (compress_level == 0) { log_warn(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress level 0 does NOT perform any compression"); } return 0; } int zlib_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int zerr = 0, err = 0; int savederrno = 0; uLongf destLen = *buf_out_len; zerr = (*_int_compress2)(buf_out, &destLen, buf_in, buf_in_len, knet_h->compress_level); *buf_out_len = destLen; switch(zerr) { case Z_OK: err = 0; savederrno = 0; break; case Z_MEM_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress mem error"); err = -1; savederrno = ENOMEM; break; case Z_BUF_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress buf error"); err = -1; savederrno = ENOBUFS; break; case Z_STREAM_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress stream error"); err = -1; savederrno = EINVAL; break; default: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib unknown compress error: %d", zerr); break; } errno = savederrno; return err; } int zlib_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { int zerr = 0, err = 0; int savederrno = 0; uLongf destLen = *buf_out_len; zerr = (*_int_uncompress)(buf_out, &destLen, buf_in, buf_in_len); *buf_out_len = destLen; switch(zerr) { case Z_OK: err = 0; savederrno = 0; break; case Z_MEM_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib decompress mem error"); err = -1; savederrno = ENOMEM; break; case Z_BUF_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib decompress buf error"); err = -1; savederrno = ENOBUFS; break; case Z_DATA_ERROR: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib decompress data error"); err = -1; savederrno = EINVAL; break; default: log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib unknown decompress error: %d", zerr); break; } errno = savederrno; return err; } #endif diff --git a/libknet/compress_zlib.h b/libknet/compress_zlib.h index b185a6ff..edd2620a 100644 --- a/libknet/compress_zlib.h +++ b/libknet/compress_zlib.h @@ -1,38 +1,35 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_COMPRESS_ZLIB_H__ #define __KNET_COMPRESS_ZLIB_H__ #include "internals.h" int zlib_load_lib( knet_handle_t knet_h); -void zlib_unload_lib( - knet_handle_t knet_h); - int zlib_val_level( knet_handle_t knet_h, int compress_level); int zlib_compress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int zlib_decompress( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); #endif diff --git a/libknet/crypto.c b/libknet/crypto.c index b0f9bdbc..ad379d0e 100644 --- a/libknet/crypto.c +++ b/libknet/crypto.c @@ -1,196 +1,184 @@ /* * Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include "crypto.h" #include "crypto_nss.h" #include "crypto_openssl.h" #include "internals.h" #include "logging.h" /* * internal module switch data */ -#define empty_module NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }, +#define empty_module NULL, 0, NULL, NULL, NULL, NULL, NULL }, crypto_model_t crypto_modules_cmds[] = { { "nss", #ifdef BUILDCRYPTONSS - 1, nsscrypto_load_lib, nsscrypto_unload_lib, 0, 0, nsscrypto_init, nsscrypto_fini, nsscrypto_encrypt_and_sign, nsscrypto_encrypt_and_signv, nsscrypto_authenticate_and_decrypt }, + 1, nsscrypto_load_lib, 0, nsscrypto_init, nsscrypto_fini, nsscrypto_encrypt_and_sign, nsscrypto_encrypt_and_signv, nsscrypto_authenticate_and_decrypt }, #else 0,empty_module #endif { "openssl", #ifdef BUILDCRYPTOOPENSSL - 1, opensslcrypto_load_lib, opensslcrypto_unload_lib, 0, 0, opensslcrypto_init, opensslcrypto_fini, opensslcrypto_encrypt_and_sign, opensslcrypto_encrypt_and_signv, opensslcrypto_authenticate_and_decrypt }, + 1, opensslcrypto_load_lib, 0, opensslcrypto_init, opensslcrypto_fini, opensslcrypto_encrypt_and_sign, opensslcrypto_encrypt_and_signv, opensslcrypto_authenticate_and_decrypt }, #else 0,empty_module #endif { NULL, 0, empty_module }; static int crypto_get_model(const char *model) { int idx = 0; while (crypto_modules_cmds[idx].model_name != NULL) { if (!strcmp(crypto_modules_cmds[idx].model_name, model)) return idx; idx++; } return -1; } /* * exported API */ int crypto_encrypt_and_sign ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { return crypto_modules_cmds[knet_h->crypto_instance->model].crypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); } int crypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len) { return crypto_modules_cmds[knet_h->crypto_instance->model].cryptv(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len); } int crypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { return crypto_modules_cmds[knet_h->crypto_instance->model].decrypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len); } int crypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg) { int savederrno = 0; int model = 0; model = crypto_get_model(knet_handle_crypto_cfg->crypto_model); if (model < 0) { log_err(knet_h, KNET_SUB_CRYPTO, "model %s not supported", knet_handle_crypto_cfg->crypto_model); return -1; } if (crypto_modules_cmds[model].built_in == 0) { log_err(knet_h, KNET_SUB_CRYPTO, "this version of libknet was built without %s support. Please contact your vendor or fix the build.", knet_handle_crypto_cfg->crypto_model); return -1; } savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_CRYPTO, "Unable to get write lock: %s", strerror(savederrno)); return -1; } - if (crypto_modules_cmds[model].load_lib(knet_h) < 0) { - log_err(knet_h, KNET_SUB_CRYPTO, "Unable to load %s lib", crypto_modules_cmds[model].model_name); - goto out_err; + if (!crypto_modules_cmds[model].loaded) { + if (crypto_modules_cmds[model].load_lib(knet_h) < 0) { + log_err(knet_h, KNET_SUB_CRYPTO, "Unable to load %s lib", crypto_modules_cmds[model].model_name); + goto out_err; + } + crypto_modules_cmds[model].loaded = 1; } - crypto_modules_cmds[model].loaded = 1; log_debug(knet_h, KNET_SUB_CRYPTO, "Initizializing crypto module [%s/%s/%s]", knet_handle_crypto_cfg->crypto_model, knet_handle_crypto_cfg->crypto_cipher_type, knet_handle_crypto_cfg->crypto_hash_type); knet_h->crypto_instance = malloc(sizeof(struct crypto_instance)); if (!knet_h->crypto_instance) { log_err(knet_h, KNET_SUB_CRYPTO, "Unable to allocate memory for crypto instance"); pthread_rwlock_unlock(&shlib_rwlock); goto out_err; } /* * if crypto_modules_cmds.init fails, it is expected that * it will clean everything by itself. * crypto_modules_cmds.fini is not invoked on error. */ knet_h->crypto_instance->model = model; if (crypto_modules_cmds[knet_h->crypto_instance->model].init(knet_h, knet_handle_crypto_cfg)) goto out_err; log_debug(knet_h, KNET_SUB_CRYPTO, "security network overhead: %u", knet_h->sec_header_size); - crypto_modules_cmds[model].libref++; pthread_rwlock_unlock(&shlib_rwlock); return 0; out_err: if (knet_h->crypto_instance) { free(knet_h->crypto_instance); knet_h->crypto_instance = NULL; } - if ((crypto_modules_cmds[model].libref == 0) && - (crypto_modules_cmds[model].loaded == 1)) { - log_debug(knet_h, KNET_SUB_CRYPTO, "Unloading %s library", crypto_modules_cmds[model].model_name); - crypto_modules_cmds[model].unload_lib(knet_h); - crypto_modules_cmds[model].loaded = 0; - } + pthread_rwlock_unlock(&shlib_rwlock); return -1; } void crypto_fini( knet_handle_t knet_h) { int savederrno = 0; int model = 0; savederrno = pthread_rwlock_wrlock(&shlib_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_CRYPTO, "Unable to get write lock: %s", strerror(savederrno)); return; } if (knet_h->crypto_instance) { model = knet_h->crypto_instance->model; if (crypto_modules_cmds[model].fini != NULL) { crypto_modules_cmds[model].fini(knet_h); } free(knet_h->crypto_instance); knet_h->crypto_instance = NULL; - crypto_modules_cmds[model].libref--; - - if ((crypto_modules_cmds[model].libref == 0) && - (crypto_modules_cmds[model].loaded == 1)) { - log_debug(knet_h, KNET_SUB_CRYPTO, "Unloading %s library", crypto_modules_cmds[model].model_name); - crypto_modules_cmds[model].unload_lib(knet_h); - crypto_modules_cmds[model].loaded = 0; - } } pthread_rwlock_unlock(&shlib_rwlock); return; } diff --git a/libknet/crypto.h b/libknet/crypto.h index 6661aa94..bdf7193f 100644 --- a/libknet/crypto.h +++ b/libknet/crypto.h @@ -1,79 +1,77 @@ /* * Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_CRYPTO_H__ #define __KNET_CRYPTO_H__ #include "internals.h" struct crypto_instance { int model; void *model_instance; }; typedef struct { const char *model_name; uint8_t built_in; /* * see compress.h for explanation of the various lib related functions */ int (*load_lib) (knet_handle_t knet_h); - void (*unload_lib) (knet_handle_t knet_h); uint8_t loaded; - uint8_t libref; int (*init) (knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); void (*fini) (knet_handle_t knet_h); int (*crypt) (knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int (*cryptv) (knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len); int (*decrypt) (knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); } crypto_model_t; int crypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int crypto_encrypt_and_sign ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int crypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len); int crypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); void crypto_fini( knet_handle_t knet_h); #endif diff --git a/libknet/crypto_nss.c b/libknet/crypto_nss.c index d66e0079..c6eaa86e 100644 --- a/libknet/crypto_nss.c +++ b/libknet/crypto_nss.c @@ -1,1148 +1,1147 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include +#include #ifdef BUILDCRYPTONSS #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "crypto.h" #include "crypto_nss.h" #include "logging.h" #define LIBNSS3 "libnss3.so" /* * global vars for dlopen */ static void *nss_lib; /* * symbols remapping */ /* * nss3 */ CK_MECHANISM_TYPE (*_int_PK11_GetBestWrapMechanism)(PK11SlotInfo *slot); PK11SlotInfo *(*_int_PK11_GetBestSlot)(CK_MECHANISM_TYPE type, void *wincx); int (*_int_PK11_GetBestKeyLength)(PK11SlotInfo *slot, CK_MECHANISM_TYPE type); SECStatus (*_int_PK11_DigestFinal)(PK11Context *context, unsigned char *data, unsigned int *outLen, unsigned int length); void (*_int_SECITEM_FreeItem)(SECItem *zap, PRBool freeit); SECStatus (*_int_NSS_NoDB_Init)(const char *configdir); SECStatus (*_int_NSS_Shutdown)(void); SECStatus (*_int_PK11_DigestBegin)(PK11Context *cx); SECStatus (*_int_PK11_DigestOp)(PK11Context *context, const unsigned char *in, unsigned len); void (*_int_PK11_DestroyContext)(PK11Context *context, PRBool freeit); SECStatus (*_int_PK11_Finalize)(PK11Context *context); SECStatus (*_int_PK11_CipherOp)(PK11Context *context, unsigned char *out, int *outlen, int maxout, const unsigned char *in, int inlen); PK11SymKey *(*_int_PK11_UnwrapSymKey)(PK11SymKey *key, CK_MECHANISM_TYPE wraptype, SECItem *param, SECItem *wrapppedKey, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize); void (*_int_PK11_FreeSymKey)(PK11SymKey *key); PK11Context *(*_int_PK11_CreateContextBySymKey)(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey, SECItem *param); SECStatus (*_int_PK11_GenerateRandom)(unsigned char *data, int len); SECItem *(*_int_PK11_ParamFromIV)(CK_MECHANISM_TYPE type, SECItem *iv); void (*_int_PK11_FreeSlot)(PK11SlotInfo *slot); int (*_int_PK11_GetBlockSize)(CK_MECHANISM_TYPE type, SECItem *params); PK11SymKey *(*_int_PK11_KeyGen)(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, int keySize, void *wincx); /* * nspr4 */ PRStatus (*_int_PR_Cleanup)(void); const char * (*_int_PR_ErrorToString)(PRErrorCode code, PRLanguageCode language); PRErrorCode (*_int_PR_GetError)(void); PRBool (*_int_PR_Initialized)(void); /* * plds4 */ void (*_int_PL_ArenaFinish)(void); static void clean_nss_syms(void) { _int_PK11_GetBestWrapMechanism = NULL; _int_PK11_GetBestSlot = NULL; _int_PK11_GetBestKeyLength = NULL; _int_PK11_DigestFinal = NULL; _int_SECITEM_FreeItem = NULL; _int_NSS_NoDB_Init = NULL; _int_NSS_Shutdown = NULL; _int_PK11_DigestBegin = NULL; _int_PK11_DigestOp = NULL; _int_PK11_DestroyContext = NULL; _int_PK11_Finalize = NULL; _int_PK11_CipherOp = NULL; _int_PK11_UnwrapSymKey = NULL; _int_PK11_FreeSymKey = NULL; _int_PK11_CreateContextBySymKey = NULL; _int_PK11_GenerateRandom = NULL; _int_PK11_ParamFromIV = NULL; _int_PK11_FreeSlot = NULL; _int_PK11_GetBlockSize = NULL; _int_PK11_KeyGen = NULL; _int_PR_Cleanup = NULL; _int_PR_ErrorToString = NULL; _int_PR_Initialized = NULL; _int_PR_GetError = NULL; _int_PL_ArenaFinish = NULL; return; } static int nsscrypto_remap_symbols(knet_handle_t knet_h) { int err = 0; char *error = NULL; /* * nss3 */ _int_PK11_GetBestWrapMechanism = dlsym(nss_lib, "PK11_GetBestWrapMechanism"); if (!_int_PK11_GetBestWrapMechanism) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GetBestWrapMechanism: %s", error); err = -1; goto out; } _int_PK11_GetBestSlot = dlsym(nss_lib, "PK11_GetBestSlot"); if (!_int_PK11_GetBestSlot) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GetBestSlot: %s", error); err = -1; goto out; } _int_PK11_GetBestKeyLength = dlsym(nss_lib, "PK11_GetBestKeyLength"); if (!_int_PK11_GetBestKeyLength) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GetBestKeyLength: %s", error); err = -1; goto out; } _int_PK11_DigestFinal = dlsym(nss_lib, "PK11_DigestFinal"); if (!_int_PK11_DigestFinal) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_DigestFinal: %s", error); err = -1; goto out; } _int_SECITEM_FreeItem = dlsym(nss_lib, "SECITEM_FreeItem"); if (!_int_SECITEM_FreeItem) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map SECITEM_FreeItem: %s", error); err = -1; goto out; } _int_NSS_NoDB_Init = dlsym(nss_lib, "NSS_NoDB_Init"); if (!_int_NSS_NoDB_Init) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map NSS_NoDB_Init: %s", error); err = -1; goto out; } _int_NSS_Shutdown = dlsym(nss_lib, "NSS_Shutdown"); if (!_int_NSS_Shutdown) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map NSS_Shutdown: %s", error); err = -1; goto out; } _int_PK11_DigestBegin = dlsym(nss_lib, "PK11_DigestBegin"); if (!_int_PK11_DigestBegin) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_DigestBegin: %s", error); err = -1; goto out; } _int_PK11_DigestOp = dlsym(nss_lib, "PK11_DigestOp"); if (!_int_PK11_DigestOp) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_DigestOp: %s", error); err = -1; goto out; } _int_PK11_DestroyContext = dlsym(nss_lib, "PK11_DestroyContext"); if (!_int_PK11_DestroyContext) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_DestroyContext: %s", error); err = -1; goto out; } _int_PK11_Finalize = dlsym(nss_lib, "PK11_Finalize"); if (!_int_PK11_Finalize) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_Finalize: %s", error); err = -1; goto out; } _int_PK11_CipherOp = dlsym(nss_lib, "PK11_CipherOp"); if (!_int_PK11_CipherOp) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_CipherOp: %s", error); err = -1; goto out; } _int_PK11_UnwrapSymKey = dlsym(nss_lib, "PK11_UnwrapSymKey"); if (!_int_PK11_UnwrapSymKey) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_UnwrapSymKey: %s", error); err = -1; goto out; } _int_PK11_FreeSymKey = dlsym(nss_lib, "PK11_FreeSymKey"); if (!_int_PK11_FreeSymKey) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_FreeSymKey: %s", error); err = -1; goto out; } _int_PK11_CreateContextBySymKey = dlsym(nss_lib, "PK11_CreateContextBySymKey"); if (!_int_PK11_CreateContextBySymKey) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_CreateContextBySymKey: %s", error); err = -1; goto out; } _int_PK11_GenerateRandom = dlsym(nss_lib, "PK11_GenerateRandom"); if (!_int_PK11_GenerateRandom) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GenerateRandom: %s", error); err = -1; goto out; } _int_PK11_ParamFromIV = dlsym(nss_lib, "PK11_ParamFromIV"); if (!_int_PK11_ParamFromIV) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_ParamFromIV: %s", error); err = -1; goto out; } _int_PK11_FreeSlot = dlsym(nss_lib, "PK11_FreeSlot"); if (!_int_PK11_FreeSlot) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_FreeSlot: %s", error); err = -1; goto out; } _int_PK11_GetBlockSize = dlsym(nss_lib, "PK11_GetBlockSize"); if (!_int_PK11_GetBlockSize) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_GetBlockSize: %s", error); err = -1; goto out; } _int_PK11_KeyGen = dlsym(nss_lib, "PK11_KeyGen"); if (!_int_PK11_KeyGen) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PK11_KeyGen: %s", error); err = -1; goto out; } /* * nspr4 */ _int_PR_Cleanup = dlsym(nss_lib, "PR_Cleanup"); if (!_int_PR_Cleanup) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PR_Cleanup: %s", error); err = -1; goto out; } _int_PR_ErrorToString = dlsym(nss_lib, "PR_ErrorToString"); if (!_int_PR_ErrorToString) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PR_ErrorToString: %s", error); err = -1; goto out; } _int_PR_Initialized = dlsym(nss_lib, "PR_Initialized"); if (!_int_PR_Initialized) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map Initialized: %s", error); err = -1; goto out; } _int_PR_GetError = dlsym(nss_lib, "PR_GetError"); if (!_int_PR_GetError) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PR_GetError: %s", error); err = -1; goto out; } /* * plds4 */ _int_PL_ArenaFinish = dlsym(nss_lib, "PL_ArenaFinish"); if (!_int_PL_ArenaFinish) { error = dlerror(); log_err(knet_h, KNET_SUB_NSSCRYPTO, "unable to map PL_ArenaFinish: %s", error); err = -1; goto out; } out: if (err) { clean_nss_syms(); } return err; } -static int init_nss_db(knet_handle_t knet_h) -{ - if ((*_int_NSS_NoDB_Init)(".") != SECSuccess) { - log_err(knet_h, KNET_SUB_NSSCRYPTO, "NSS DB initialization failed (err %d): %s", - (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); - return -1; - } +static int nss_db_is_init = 0; +static int at_exit_registered = 0; - return 0; -} - -void nsscrypto_unload_lib( - knet_handle_t knet_h) +static void nss_atexit_handler(void) { - log_warn(knet_h, KNET_SUB_NSSCRYPTO, "%s runtime unload can cause minor (< 2kb) memory leaks! Please reload your application at a convenient time (and no, we cannot detect if you are shutting down the app or closing one handle, so you will get this message regardless).", LIBNSS3); - if (nss_lib) { + if (nss_db_is_init) { if (_int_NSS_Shutdown) { (*_int_NSS_Shutdown)(); } if ((_int_PR_Initialized) && ((*_int_PR_Initialized)())) { if (_int_PL_ArenaFinish) { (*_int_PL_ArenaFinish)(); } if (_int_PR_Cleanup) { (*_int_PR_Cleanup)(); } } - dlclose(nss_lib); - nss_lib = NULL; - clean_nss_syms(); } return; } int nsscrypto_load_lib( knet_handle_t knet_h) { int err = 0, savederrno = 0; if (!nss_lib) { nss_lib = open_lib(knet_h, LIBNSS3, 0); if (!nss_lib) { savederrno = errno; err = -1; goto out; } + } - if (nsscrypto_remap_symbols(knet_h) < 0) { - savederrno = errno; + if (nsscrypto_remap_symbols(knet_h) < 0) { + savederrno = errno; + err = -1; + goto out; + } + + if (!at_exit_registered) { + if (atexit(nss_atexit_handler)) { + log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to register NSS atexit handler"); + savederrno = EAGAIN; err = -1; goto out; } + at_exit_registered = 1; + } - if (init_nss_db(knet_h) < 0) { + if ((nss_lib) && (_int_NSS_NoDB_Init) && (!nss_db_is_init)) { + if ((*_int_NSS_NoDB_Init)(".") != SECSuccess) { + log_err(knet_h, KNET_SUB_NSSCRYPTO, "NSS DB initialization failed (err %d): %s", + (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); savederrno = EAGAIN; err = -1; goto out; } + nss_db_is_init = 1; } - out: - if (err) { - nsscrypto_unload_lib(knet_h); - } errno = savederrno; return err; } /* * crypto definitions and conversion tables */ #define SALT_SIZE 16 /* * This are defined in new NSS. For older one, we will define our own */ #ifndef AES_256_KEY_LENGTH #define AES_256_KEY_LENGTH 32 #endif #ifndef AES_192_KEY_LENGTH #define AES_192_KEY_LENGTH 24 #endif #ifndef AES_128_KEY_LENGTH #define AES_128_KEY_LENGTH 16 #endif enum nsscrypto_crypt_t { CRYPTO_CIPHER_TYPE_NONE = 0, CRYPTO_CIPHER_TYPE_AES256 = 1, CRYPTO_CIPHER_TYPE_AES192 = 2, CRYPTO_CIPHER_TYPE_AES128 = 3, CRYPTO_CIPHER_TYPE_3DES = 4 }; CK_MECHANISM_TYPE cipher_to_nss[] = { 0, /* CRYPTO_CIPHER_TYPE_NONE */ CKM_AES_CBC_PAD, /* CRYPTO_CIPHER_TYPE_AES256 */ CKM_AES_CBC_PAD, /* CRYPTO_CIPHER_TYPE_AES192 */ CKM_AES_CBC_PAD, /* CRYPTO_CIPHER_TYPE_AES128 */ CKM_DES3_CBC_PAD /* CRYPTO_CIPHER_TYPE_3DES */ }; size_t nsscipher_key_len[] = { 0, /* CRYPTO_CIPHER_TYPE_NONE */ AES_256_KEY_LENGTH, /* CRYPTO_CIPHER_TYPE_AES256 */ AES_192_KEY_LENGTH, /* CRYPTO_CIPHER_TYPE_AES192 */ AES_128_KEY_LENGTH, /* CRYPTO_CIPHER_TYPE_AES128 */ 24 /* CRYPTO_CIPHER_TYPE_3DES */ }; size_t nsscypher_block_len[] = { 0, /* CRYPTO_CIPHER_TYPE_NONE */ AES_BLOCK_SIZE, /* CRYPTO_CIPHER_TYPE_AES256 */ AES_BLOCK_SIZE, /* CRYPTO_CIPHER_TYPE_AES192 */ AES_BLOCK_SIZE, /* CRYPTO_CIPHER_TYPE_AES128 */ 0 /* CRYPTO_CIPHER_TYPE_3DES */ }; /* * hash definitions and conversion tables */ enum nsscrypto_hash_t { CRYPTO_HASH_TYPE_NONE = 0, CRYPTO_HASH_TYPE_MD5 = 1, CRYPTO_HASH_TYPE_SHA1 = 2, CRYPTO_HASH_TYPE_SHA256 = 3, CRYPTO_HASH_TYPE_SHA384 = 4, CRYPTO_HASH_TYPE_SHA512 = 5 }; CK_MECHANISM_TYPE hash_to_nss[] = { 0, /* CRYPTO_HASH_TYPE_NONE */ CKM_MD5_HMAC, /* CRYPTO_HASH_TYPE_MD5 */ CKM_SHA_1_HMAC, /* CRYPTO_HASH_TYPE_SHA1 */ CKM_SHA256_HMAC, /* CRYPTO_HASH_TYPE_SHA256 */ CKM_SHA384_HMAC, /* CRYPTO_HASH_TYPE_SHA384 */ CKM_SHA512_HMAC /* CRYPTO_HASH_TYPE_SHA512 */ }; size_t nsshash_len[] = { 0, /* CRYPTO_HASH_TYPE_NONE */ MD5_LENGTH, /* CRYPTO_HASH_TYPE_MD5 */ SHA1_LENGTH, /* CRYPTO_HASH_TYPE_SHA1 */ SHA256_LENGTH, /* CRYPTO_HASH_TYPE_SHA256 */ SHA384_LENGTH, /* CRYPTO_HASH_TYPE_SHA384 */ SHA512_LENGTH /* CRYPTO_HASH_TYPE_SHA512 */ }; enum sym_key_type { SYM_KEY_TYPE_CRYPT, SYM_KEY_TYPE_HASH }; struct nsscrypto_instance { PK11SymKey *nss_sym_key; PK11SymKey *nss_sym_key_sign; unsigned char *private_key; unsigned int private_key_len; int crypto_cipher_type; int crypto_hash_type; }; /* * crypt/decrypt functions */ static int nssstring_to_crypto_cipher_type(const char* crypto_cipher_type) { if (strcmp(crypto_cipher_type, "none") == 0) { return CRYPTO_CIPHER_TYPE_NONE; } else if (strcmp(crypto_cipher_type, "aes256") == 0) { return CRYPTO_CIPHER_TYPE_AES256; } else if (strcmp(crypto_cipher_type, "aes192") == 0) { return CRYPTO_CIPHER_TYPE_AES192; } else if (strcmp(crypto_cipher_type, "aes128") == 0) { return CRYPTO_CIPHER_TYPE_AES128; } else if (strcmp(crypto_cipher_type, "3des") == 0) { return CRYPTO_CIPHER_TYPE_3DES; } return -1; } static PK11SymKey *nssimport_symmetric_key(knet_handle_t knet_h, enum sym_key_type key_type) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; SECItem key_item; PK11SlotInfo *slot; PK11SymKey *res_key; CK_MECHANISM_TYPE cipher; CK_ATTRIBUTE_TYPE operation; CK_MECHANISM_TYPE wrap_mechanism; int wrap_key_len; PK11SymKey *wrap_key; PK11Context *wrap_key_crypt_context; SECItem tmp_sec_item; SECItem wrapped_key; int wrapped_key_len; unsigned char wrapped_key_data[KNET_MAX_KEY_LEN]; memset(&key_item, 0, sizeof(key_item)); slot = NULL; wrap_key = NULL; res_key = NULL; wrap_key_crypt_context = NULL; key_item.type = siBuffer; key_item.data = instance->private_key; switch (key_type) { case SYM_KEY_TYPE_CRYPT: key_item.len = nsscipher_key_len[instance->crypto_cipher_type]; cipher = cipher_to_nss[instance->crypto_cipher_type]; operation = CKA_ENCRYPT|CKA_DECRYPT; break; case SYM_KEY_TYPE_HASH: key_item.len = instance->private_key_len; cipher = hash_to_nss[instance->crypto_hash_type]; operation = CKA_SIGN; break; default: log_err(knet_h, KNET_SUB_NSSCRYPTO, "Import symmetric key failed. Unknown keyimport request"); goto exit_res_key; break; } slot = (*_int_PK11_GetBestSlot)(cipher, NULL); if (slot == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to find security slot (%d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } /* * Without FIPS it would be possible to just use * res_key = PK11_ImportSymKey(slot, cipher, PK11_OriginUnwrap, operation, &key_item, NULL); * with FIPS NSS Level 2 certification has to be "workarounded" (so it becomes Level 1) by using * following method: * 1. Generate wrap key * 2. Encrypt authkey with wrap key * 3. Unwrap encrypted authkey using wrap key */ /* * Generate wrapping key */ wrap_mechanism = (*_int_PK11_GetBestWrapMechanism)(slot); wrap_key_len = (*_int_PK11_GetBestKeyLength)(slot, wrap_mechanism); wrap_key = (*_int_PK11_KeyGen)(slot, wrap_mechanism, NULL, wrap_key_len, NULL); if (wrap_key == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to generate wrapping key (%d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } /* * Encrypt authkey with wrapping key */ /* * Initialization of IV is not needed because PK11_GetBestWrapMechanism should return ECB mode */ memset(&tmp_sec_item, 0, sizeof(tmp_sec_item)); wrap_key_crypt_context = (*_int_PK11_CreateContextBySymKey)(wrap_mechanism, CKA_ENCRYPT, wrap_key, &tmp_sec_item); if (wrap_key_crypt_context == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to create encrypt context (%d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } wrapped_key_len = (int)sizeof(wrapped_key_data); if ((*_int_PK11_CipherOp)(wrap_key_crypt_context, wrapped_key_data, &wrapped_key_len, sizeof(wrapped_key_data), key_item.data, key_item.len) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to encrypt authkey (%d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } if ((*_int_PK11_Finalize)(wrap_key_crypt_context) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to finalize encryption of authkey (%d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto exit_res_key; } /* * Finally unwrap sym key */ memset(&tmp_sec_item, 0, sizeof(tmp_sec_item)); wrapped_key.data = wrapped_key_data; wrapped_key.len = wrapped_key_len; res_key = (*_int_PK11_UnwrapSymKey)(wrap_key, wrap_mechanism, &tmp_sec_item, &wrapped_key, cipher, operation, key_item.len); if (res_key == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to import key into NSS (%d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); if ((*_int_PR_GetError)() == SEC_ERROR_BAD_DATA) { /* * Maximum key length for FIPS enabled softtoken is limited to * MAX_KEY_LEN (pkcs11i.h - 256) and checked in NSC_UnwrapKey. Returned * error is CKR_TEMPLATE_INCONSISTENT which is mapped to SEC_ERROR_BAD_DATA. */ log_err(knet_h, KNET_SUB_NSSCRYPTO, "Secret key is probably too long. " "Try reduce it to 256 bytes"); } goto exit_res_key; } exit_res_key: if (wrap_key_crypt_context != NULL) { (*_int_PK11_DestroyContext)(wrap_key_crypt_context, PR_TRUE); } if (wrap_key != NULL) { (*_int_PK11_FreeSymKey)(wrap_key); } if (slot != NULL) { (*_int_PK11_FreeSlot)(slot); } return (res_key); } static int init_nss_crypto(knet_handle_t knet_h) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; if (!cipher_to_nss[instance->crypto_cipher_type]) { return 0; } instance->nss_sym_key = nssimport_symmetric_key(knet_h, SYM_KEY_TYPE_CRYPT); if (instance->nss_sym_key == NULL) { return -1; } return 0; } static int encrypt_nss( knet_handle_t knet_h, const struct iovec *iov, int iovcnt, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; PK11Context* crypt_context = NULL; SECItem crypt_param; SECItem *nss_sec_param = NULL; int tmp_outlen = 0, tmp1_outlen = 0; unsigned int tmp2_outlen = 0; unsigned char *salt = buf_out; unsigned char *data = buf_out + SALT_SIZE; int err = -1; int i; if ((*_int_PK11_GenerateRandom)(salt, SALT_SIZE) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to generate a random number (err %d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } crypt_param.type = siBuffer; crypt_param.data = salt; crypt_param.len = SALT_SIZE; nss_sec_param = (*_int_PK11_ParamFromIV)(cipher_to_nss[instance->crypto_cipher_type], &crypt_param); if (nss_sec_param == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to set up PKCS11 param (err %d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } /* * Create cipher context for encryption */ crypt_context = (*_int_PK11_CreateContextBySymKey)(cipher_to_nss[instance->crypto_cipher_type], CKA_ENCRYPT, instance->nss_sym_key, nss_sec_param); if (!crypt_context) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d): %s", (int)cipher_to_nss[instance->crypto_cipher_type], (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } for (i=0; icrypto_cipher_type], (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } tmp1_outlen = tmp1_outlen + tmp_outlen; } if ((*_int_PK11_DigestFinal)(crypt_context, data + tmp1_outlen, &tmp2_outlen, KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal failed (encrypt) crypt_type=%d (err %d): %s", (int)cipher_to_nss[instance->crypto_cipher_type], (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } *buf_out_len = tmp1_outlen + tmp2_outlen + SALT_SIZE; err = 0; out: if (crypt_context) { (*_int_PK11_DestroyContext)(crypt_context, PR_TRUE); } if (nss_sec_param) { (*_int_SECITEM_FreeItem)(nss_sec_param, PR_TRUE); } return err; } static int decrypt_nss ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; PK11Context* decrypt_context = NULL; SECItem decrypt_param; int tmp1_outlen = 0; unsigned int tmp2_outlen = 0; unsigned char *salt = (unsigned char *)buf_in; unsigned char *data = salt + SALT_SIZE; int datalen = buf_in_len - SALT_SIZE; int err = -1; /* Create cipher context for decryption */ decrypt_param.type = siBuffer; decrypt_param.data = salt; decrypt_param.len = SALT_SIZE; decrypt_context = (*_int_PK11_CreateContextBySymKey)(cipher_to_nss[instance->crypto_cipher_type], CKA_DECRYPT, instance->nss_sym_key, &decrypt_param); if (!decrypt_context) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext (decrypt) failed (err %d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } if ((*_int_PK11_CipherOp)(decrypt_context, buf_out, &tmp1_outlen, KNET_DATABUFSIZE_CRYPT, data, datalen) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp (decrypt) failed (err %d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } if ((*_int_PK11_DigestFinal)(decrypt_context, buf_out + tmp1_outlen, &tmp2_outlen, KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal (decrypt) failed (err %d): %s", (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } *buf_out_len = tmp1_outlen + tmp2_outlen; err = 0; out: if (decrypt_context) { (*_int_PK11_DestroyContext)(decrypt_context, PR_TRUE); } return err; } /* * hash/hmac/digest functions */ static int nssstring_to_crypto_hash_type(const char* crypto_hash_type) { if (strcmp(crypto_hash_type, "none") == 0) { return CRYPTO_HASH_TYPE_NONE; } else if (strcmp(crypto_hash_type, "md5") == 0) { return CRYPTO_HASH_TYPE_MD5; } else if (strcmp(crypto_hash_type, "sha1") == 0) { return CRYPTO_HASH_TYPE_SHA1; } else if (strcmp(crypto_hash_type, "sha256") == 0) { return CRYPTO_HASH_TYPE_SHA256; } else if (strcmp(crypto_hash_type, "sha384") == 0) { return CRYPTO_HASH_TYPE_SHA384; } else if (strcmp(crypto_hash_type, "sha512") == 0) { return CRYPTO_HASH_TYPE_SHA512; } return -1; } static int init_nss_hash(knet_handle_t knet_h) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; if (!hash_to_nss[instance->crypto_hash_type]) { return 0; } instance->nss_sym_key_sign = nssimport_symmetric_key(knet_h, SYM_KEY_TYPE_HASH); if (instance->nss_sym_key_sign == NULL) { return -1; } return 0; } static int calculate_nss_hash( knet_handle_t knet_h, const unsigned char *buf, const size_t buf_len, unsigned char *hash) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; PK11Context* hash_context = NULL; SECItem hash_param; unsigned int hash_tmp_outlen = 0; int err = -1; /* Now do the digest */ hash_param.type = siBuffer; hash_param.data = 0; hash_param.len = 0; hash_context = (*_int_PK11_CreateContextBySymKey)(hash_to_nss[instance->crypto_hash_type], CKA_SIGN, instance->nss_sym_key_sign, &hash_param); if (!hash_context) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (hash) hash_type=%d (err %d): %s", (int)hash_to_nss[instance->crypto_hash_type], (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } if ((*_int_PK11_DigestBegin)(hash_context) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestBegin failed (hash) hash_type=%d (err %d): %s", (int)hash_to_nss[instance->crypto_hash_type], (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } if ((*_int_PK11_DigestOp)(hash_context, buf, buf_len) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestOp failed (hash) hash_type=%d (err %d): %s", (int)hash_to_nss[instance->crypto_hash_type], (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } if ((*_int_PK11_DigestFinal)(hash_context, hash, &hash_tmp_outlen, nsshash_len[instance->crypto_hash_type]) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinale failed (hash) hash_type=%d (err %d): %s", (int)hash_to_nss[instance->crypto_hash_type], (*_int_PR_GetError)(), (*_int_PR_ErrorToString)((*_int_PR_GetError)(), PR_LANGUAGE_I_DEFAULT)); goto out; } err = 0; out: if (hash_context) { (*_int_PK11_DestroyContext)(hash_context, PR_TRUE); } return err; } /* * global/glue nss functions */ static int init_nss(knet_handle_t knet_h) { if (init_nss_crypto(knet_h) < 0) { return -1; } if (init_nss_hash(knet_h) < 0) { return -1; } return 0; } /* * exported API */ int nsscrypto_encrypt_and_sign ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { struct iovec iov_in; memset(&iov_in, 0, sizeof(iov_in)); iov_in.iov_base = (unsigned char *)buf_in; iov_in.iov_len = buf_in_len; return nsscrypto_encrypt_and_signv(knet_h, &iov_in, 1, buf_out, buf_out_len); } int nsscrypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; int i; if (cipher_to_nss[instance->crypto_cipher_type]) { if (encrypt_nss(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len) < 0) { return -1; } } else { *buf_out_len = 0; for (i=0; icrypto_hash_type]) { if (calculate_nss_hash(knet_h, buf_out, *buf_out_len, buf_out + *buf_out_len) < 0) { return -1; } *buf_out_len = *buf_out_len + nsshash_len[instance->crypto_hash_type]; } return 0; } int nsscrypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; ssize_t temp_len = buf_in_len; if (hash_to_nss[instance->crypto_hash_type]) { unsigned char tmp_hash[nsshash_len[instance->crypto_hash_type]]; ssize_t temp_buf_len = buf_in_len - nsshash_len[instance->crypto_hash_type]; if ((temp_buf_len < 0) || (temp_buf_len > KNET_MAX_PACKET_SIZE)) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Incorrect packet size."); return -1; } if (calculate_nss_hash(knet_h, buf_in, temp_buf_len, tmp_hash) < 0) { return -1; } if (memcmp(tmp_hash, buf_in + temp_buf_len, nsshash_len[instance->crypto_hash_type]) != 0) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Digest does not match"); return -1; } temp_len = temp_len - nsshash_len[instance->crypto_hash_type]; *buf_out_len = temp_len; } if (cipher_to_nss[instance->crypto_cipher_type]) { if (decrypt_nss(knet_h, buf_in, temp_len, buf_out, buf_out_len) < 0) { return -1; } } else { memmove(buf_out, buf_in, temp_len); *buf_out_len = temp_len; } return 0; } int nsscrypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg) { struct nsscrypto_instance *nsscrypto_instance = NULL; log_debug(knet_h, KNET_SUB_NSSCRYPTO, "Initizializing nss crypto module [%s/%s]", knet_handle_crypto_cfg->crypto_cipher_type, knet_handle_crypto_cfg->crypto_hash_type); knet_h->crypto_instance->model_instance = malloc(sizeof(struct nsscrypto_instance)); if (!knet_h->crypto_instance->model_instance) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to allocate memory for nss model instance"); return -1; } nsscrypto_instance = knet_h->crypto_instance->model_instance; memset(nsscrypto_instance, 0, sizeof(struct nsscrypto_instance)); nsscrypto_instance->crypto_cipher_type = nssstring_to_crypto_cipher_type(knet_handle_crypto_cfg->crypto_cipher_type); if (nsscrypto_instance->crypto_cipher_type < 0) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "unknown crypto cipher type requested"); goto out_err; } nsscrypto_instance->crypto_hash_type = nssstring_to_crypto_hash_type(knet_handle_crypto_cfg->crypto_hash_type); if (nsscrypto_instance->crypto_hash_type < 0) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "unknown crypto hash type requested"); goto out_err; } if ((nsscrypto_instance->crypto_cipher_type > 0) && (nsscrypto_instance->crypto_hash_type == 0)) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "crypto communication requires hash specified"); goto out_err; } nsscrypto_instance->private_key = knet_handle_crypto_cfg->private_key; nsscrypto_instance->private_key_len = knet_handle_crypto_cfg->private_key_len; if (init_nss(knet_h) < 0) { goto out_err; } knet_h->sec_header_size = 0; if (nsscrypto_instance->crypto_hash_type > 0) { knet_h->sec_header_size += nsshash_len[nsscrypto_instance->crypto_hash_type]; knet_h->sec_hash_size = nsshash_len[nsscrypto_instance->crypto_hash_type]; } if (nsscrypto_instance->crypto_cipher_type > 0) { int block_size; if (nsscypher_block_len[nsscrypto_instance->crypto_cipher_type]) { block_size = nsscypher_block_len[nsscrypto_instance->crypto_cipher_type]; } else { block_size = (*_int_PK11_GetBlockSize)(nsscrypto_instance->crypto_cipher_type, NULL); if (block_size < 0) { goto out_err; } } knet_h->sec_header_size += (block_size * 2); knet_h->sec_header_size += SALT_SIZE; knet_h->sec_salt_size = SALT_SIZE; knet_h->sec_block_size = block_size; } return 0; out_err: nsscrypto_fini(knet_h); return -1; } void nsscrypto_fini( knet_handle_t knet_h) { struct nsscrypto_instance *nsscrypto_instance = knet_h->crypto_instance->model_instance; if (nsscrypto_instance) { if (nsscrypto_instance->nss_sym_key) { (*_int_PK11_FreeSymKey)(nsscrypto_instance->nss_sym_key); nsscrypto_instance->nss_sym_key = NULL; } if (nsscrypto_instance->nss_sym_key_sign) { (*_int_PK11_FreeSymKey)(nsscrypto_instance->nss_sym_key_sign); nsscrypto_instance->nss_sym_key_sign = NULL; } free(nsscrypto_instance); knet_h->crypto_instance->model_instance = NULL; knet_h->sec_header_size = 0; } return; } #endif diff --git a/libknet/crypto_nss.h b/libknet/crypto_nss.h index 578675a9..060022c4 100644 --- a/libknet/crypto_nss.h +++ b/libknet/crypto_nss.h @@ -1,50 +1,47 @@ /* * Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_NSSCRYPTO_H__ #define __KNET_NSSCRYPTO_H__ #include "internals.h" struct nsscrypto_instance; int nsscrypto_load_lib( knet_handle_t knet_h); -void nsscrypto_unload_lib( - knet_handle_t knet_h); - int nsscrypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); void nsscrypto_fini( knet_handle_t knet_h); int nsscrypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int nsscrypto_encrypt_and_sign ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int nsscrypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len); #endif diff --git a/libknet/crypto_openssl.c b/libknet/crypto_openssl.c index 98c52523..7707a592 100644 --- a/libknet/crypto_openssl.c +++ b/libknet/crypto_openssl.c @@ -1,892 +1,843 @@ /* * Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #ifdef BUILDCRYPTOOPENSSL #include #include #include #include #include #include "common.h" #include "crypto.h" #include "crypto_openssl.h" #include "logging.h" /* * 1.0.2 requires at least 120 bytes * 1.1.0 requires at least 256 bytes */ #define SSLERR_BUF_SIZE 512 /* * make this more generic. * Fedora packages it one way, Debian another * and it changes by version */ #define LIBOPENSSL "libcrypto.so" /* * global vars for dlopen */ static void *openssl_lib; /* * symbols remapping */ #ifdef BUILDCRYPTOOPENSSL10 void (*_int_OPENSSL_add_all_algorithms_noconf)(void); #endif #ifdef BUILDCRYPTOOPENSSL11 int (*_int_OPENSSL_init_crypto)(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); #endif #ifdef BUILDCRYPTOOPENSSL10 void (*_int_ERR_load_crypto_strings)(void); #endif unsigned long (*_int_ERR_get_error)(void); void (*_int_ERR_error_string_n)(unsigned long e, char *buf, size_t len); -#ifdef BUILDCRYPTOOPENSSL10 -void (*_int_ERR_free_strings)(void); -#endif void (*_int_RAND_seed)(const void *buf, int num); int (*_int_RAND_bytes)(unsigned char *buf, int num); const EVP_MD *(*_int_EVP_get_digestbyname)(const char *name); int (*_int_EVP_MD_size)(const EVP_MD *md); unsigned char *(*_int_HMAC)(const EVP_MD *evp_md, const void *key, int key_len, const unsigned char *d, size_t n, unsigned char *md, unsigned int *md_len); const EVP_CIPHER *(*_int_EVP_get_cipherbyname)(const char *name); int (*_int_EVP_CIPHER_block_size)(const EVP_CIPHER *cipher); #ifdef BUILDCRYPTOOPENSSL10 void (*_int_EVP_CIPHER_CTX_init)(EVP_CIPHER_CTX *a); int (*_int_EVP_CIPHER_CTX_cleanup)(EVP_CIPHER_CTX *a); #endif #ifdef BUILDCRYPTOOPENSSL11 EVP_CIPHER_CTX *(*_int_EVP_CIPHER_CTX_new)(void); void (*_int_EVP_CIPHER_CTX_free)(EVP_CIPHER_CTX *c); #endif int (*_int_EVP_EncryptInit_ex)(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv); int (*_int_EVP_EncryptUpdate)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl); int (*_int_EVP_EncryptFinal_ex)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); int (*_int_EVP_DecryptInit_ex)(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv); int (*_int_EVP_DecryptUpdate)(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl); int (*_int_EVP_DecryptFinal_ex)(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); -#ifdef BUILDCRYPTOOPENSSL10 -void (*_int_EVP_cleanup)(void); -#endif static void clean_openssl_syms(void) { #ifdef BUILDCRYPTOOPENSSL10 _int_OPENSSL_add_all_algorithms_noconf = NULL; #endif #ifdef BUILDCRYPTOOPENSSL11 _int_OPENSSL_init_crypto = NULL; #endif #ifdef BUILDCRYPTOOPENSSL10 _int_ERR_load_crypto_strings = NULL; #endif _int_ERR_get_error = NULL; _int_ERR_error_string_n = NULL; -#ifdef BUILDCRYPTOOPENSSL10 - _int_ERR_free_strings = NULL; -#endif + _int_RAND_seed = NULL; _int_RAND_bytes = NULL; _int_EVP_get_digestbyname = NULL; _int_EVP_MD_size = NULL; _int_HMAC = NULL; _int_EVP_get_cipherbyname = NULL; _int_EVP_CIPHER_block_size = NULL; #ifdef BUILDCRYPTOOPENSSL10 _int_EVP_CIPHER_CTX_init = NULL; _int_EVP_CIPHER_CTX_cleanup = NULL; #endif #ifdef BUILDCRYPTOOPENSSL11 _int_EVP_CIPHER_CTX_new = NULL; _int_EVP_CIPHER_CTX_free = NULL; #endif _int_EVP_EncryptInit_ex = NULL; _int_EVP_EncryptUpdate = NULL; _int_EVP_EncryptFinal_ex = NULL; _int_EVP_DecryptInit_ex = NULL; _int_EVP_DecryptUpdate = NULL; _int_EVP_DecryptFinal_ex = NULL; -#ifdef BUILDCRYPTOOPENSSL10 - _int_EVP_cleanup = NULL; -#endif return; } static int opensslcrypto_remap_symbols(knet_handle_t knet_h) { int err = 0; char *error = NULL; #ifdef BUILDCRYPTOOPENSSL10 _int_OPENSSL_add_all_algorithms_noconf = dlsym(openssl_lib, "OPENSSL_add_all_algorithms_noconf"); if (!_int_OPENSSL_add_all_algorithms_noconf) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map OPENSSL_add_all_algorithms_noconf: %s", error); err = -1; goto out; } #endif #ifdef BUILDCRYPTOOPENSSL11 _int_OPENSSL_init_crypto = dlsym(openssl_lib, "OPENSSL_init_crypto"); if (!_int_OPENSSL_init_crypto) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map OPENSSL_init_crypto: %s", error); err = -1; goto out; } #endif #ifdef BUILDCRYPTOOPENSSL10 _int_ERR_load_crypto_strings = dlsym(openssl_lib, "ERR_load_crypto_strings"); if (!_int_ERR_load_crypto_strings) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map ERR_load_crypto_strings: %s", error); err = -1; goto out; } #endif _int_ERR_get_error = dlsym(openssl_lib, "ERR_get_error"); if (!_int_ERR_get_error) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map ERR_get_error: %s", error); err = -1; goto out; } _int_ERR_error_string_n = dlsym(openssl_lib, "ERR_error_string_n"); if (!_int_ERR_error_string_n) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map ERR_error_string_n: %s", error); err = -1; goto out; } -#ifdef BUILDCRYPTOOPENSSL10 - _int_ERR_free_strings = dlsym(openssl_lib, "ERR_free_strings"); - if (!_int_ERR_free_strings) { - error = dlerror(); - log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map ERR_free_strings: %s", error); - err = -1; - goto out; - } -#endif - _int_RAND_seed = dlsym(openssl_lib, "RAND_seed"); if (!_int_RAND_seed) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map RAND_seed: %s", error); err = -1; goto out; } _int_RAND_bytes = dlsym(openssl_lib, "RAND_bytes"); if (!_int_RAND_bytes) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map RAND_bytes: %s", error); err = -1; goto out; } _int_EVP_get_digestbyname = dlsym(openssl_lib, "EVP_get_digestbyname"); if (!_int_EVP_get_digestbyname) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_get_digestbyname: %s", error); err = -1; goto out; } _int_EVP_MD_size = dlsym(openssl_lib, "EVP_MD_size"); if (!_int_EVP_MD_size) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_MD_size: %s", error); err = -1; goto out; } _int_HMAC = dlsym(openssl_lib, "HMAC"); if (!_int_HMAC) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map HMAC: %s", error); err = -1; goto out; } _int_EVP_get_cipherbyname = dlsym(openssl_lib, "EVP_get_cipherbyname"); if (!_int_EVP_get_cipherbyname) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_get_cipherbyname: %s", error); err = -1; goto out; } _int_EVP_CIPHER_block_size = dlsym(openssl_lib, "EVP_CIPHER_block_size"); if (!_int_EVP_CIPHER_block_size) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_CIPHER_block_size: %s", error); err = -1; goto out; } #ifdef BUILDCRYPTOOPENSSL10 _int_EVP_CIPHER_CTX_init = dlsym(openssl_lib, "EVP_CIPHER_CTX_init"); if (!_int_EVP_CIPHER_CTX_init) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_CIPHER_CTX_init: %s", error); err = -1; goto out; } _int_EVP_CIPHER_CTX_cleanup = dlsym(openssl_lib, "EVP_CIPHER_CTX_cleanup"); if (!_int_EVP_CIPHER_CTX_cleanup) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_CIPHER_CTX_cleanup: %s", error); err = -1; goto out; } #endif #ifdef BUILDCRYPTOOPENSSL11 _int_EVP_CIPHER_CTX_new = dlsym(openssl_lib, "EVP_CIPHER_CTX_new"); if (!_int_EVP_CIPHER_CTX_new) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_CIPHER_CTX_new: %s", error); err = -1; goto out; } _int_EVP_CIPHER_CTX_free = dlsym(openssl_lib, "EVP_CIPHER_CTX_free"); if (!_int_EVP_CIPHER_CTX_free) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_CIPHER_CTX_free: %s", error); err = -1; goto out; } #endif _int_EVP_EncryptInit_ex = dlsym(openssl_lib, "EVP_EncryptInit_ex"); if (!_int_EVP_EncryptInit_ex) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_EncryptInit_ex: %s", error); err = -1; goto out; } _int_EVP_EncryptUpdate = dlsym(openssl_lib, "EVP_EncryptUpdate"); if (!_int_EVP_EncryptUpdate) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_EncryptUpdate: %s", error); err = -1; goto out; } _int_EVP_EncryptFinal_ex = dlsym(openssl_lib, "EVP_EncryptFinal_ex"); if (!_int_EVP_EncryptFinal_ex) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_EncryptFinal_ex: %s", error); err = -1; goto out; } _int_EVP_DecryptInit_ex = dlsym(openssl_lib, "EVP_DecryptInit_ex"); if (!_int_EVP_DecryptInit_ex) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_DecryptInit_ex: %s", error); err = -1; goto out; } _int_EVP_DecryptUpdate = dlsym(openssl_lib, "EVP_DecryptUpdate"); if (!_int_EVP_DecryptUpdate) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_DecryptUpdate: %s", error); err = -1; goto out; } _int_EVP_DecryptFinal_ex = dlsym(openssl_lib, "EVP_DecryptFinal_ex"); if (!_int_EVP_DecryptFinal_ex) { error = dlerror(); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_DecryptFinal_ex: %s", error); err = -1; goto out; } -#ifdef BUILDCRYPTOOPENSSL10 - _int_EVP_cleanup = dlsym(openssl_lib, "EVP_cleanup"); - if (!_int_EVP_cleanup) { - error = dlerror(); - log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unable to map EVP_cleanup: %s", error); - err = -1; - goto out; - } -#endif - out: if (err) { clean_openssl_syms(); } return err; } -void opensslcrypto_unload_lib( - knet_handle_t knet_h) -{ - if (openssl_lib) { -#ifdef BUILDCRYPTOOPENSSL10 - if (_int_EVP_cleanup) { - (*_int_EVP_cleanup)(); - } - if (_int_ERR_free_strings) { - (*_int_ERR_free_strings)(); - } -#endif - dlclose(openssl_lib); - openssl_lib = NULL; - clean_openssl_syms(); - } - - return; -} +static int openssl_is_init = 0; int opensslcrypto_load_lib( knet_handle_t knet_h) { int err = 0, savederrno = 0; if (!openssl_lib) { openssl_lib = open_lib(knet_h, LIBOPENSSL, 0); if (!openssl_lib) { savederrno = errno; err = -1; goto out; } + } - if (opensslcrypto_remap_symbols(knet_h) < 0) { - savederrno = errno; - err = -1; - goto out; - } + if (opensslcrypto_remap_symbols(knet_h) < 0) { + savederrno = errno; + err = -1; + goto out; + } + if (!openssl_is_init) { #ifdef BUILDCRYPTOOPENSSL10 (*_int_ERR_load_crypto_strings)(); (*_int_OPENSSL_add_all_algorithms_noconf)(); #endif #ifdef BUILDCRYPTOOPENSSL11 if (!(*_int_OPENSSL_init_crypto)(OPENSSL_INIT_ADD_ALL_CIPHERS \ | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to init openssl"); err = -1; savederrno = EAGAIN; goto out; } #endif + openssl_is_init = 1; } out: - if (err) { - opensslcrypto_unload_lib(knet_h); - } errno = savederrno; return err; } /* * crypto definitions and conversion tables */ #define SALT_SIZE 16 struct opensslcrypto_instance { void *private_key; int private_key_len; const EVP_CIPHER *crypto_cipher_type; const EVP_MD *crypto_hash_type; }; /* * crypt/decrypt functions openssl1.0 */ #ifdef BUILDCRYPTOOPENSSL10 static int encrypt_openssl( knet_handle_t knet_h, const struct iovec *iov, int iovcnt, unsigned char *buf_out, ssize_t *buf_out_len) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; EVP_CIPHER_CTX ctx; int tmplen = 0, offset = 0; unsigned char *salt = buf_out; unsigned char *data = buf_out + SALT_SIZE; int err = 0; int i; char sslerr[SSLERR_BUF_SIZE]; (*_int_EVP_CIPHER_CTX_init)(&ctx); /* * contribute to PRNG for each packet we send/receive */ (*_int_RAND_seed)((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len); if (!(*_int_RAND_bytes)(salt, SALT_SIZE)) { (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to get random salt data: %s", sslerr); err = -1; goto out; } /* * add warning re keylength */ (*_int_EVP_EncryptInit_ex)(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); for (i=0; icrypto_instance->model_instance; EVP_CIPHER_CTX ctx; int tmplen1 = 0, tmplen2 = 0; unsigned char *salt = (unsigned char *)buf_in; unsigned char *data = salt + SALT_SIZE; int datalen = buf_in_len - SALT_SIZE; int err = 0; char sslerr[SSLERR_BUF_SIZE]; (*_int_EVP_CIPHER_CTX_init)(&ctx); /* * contribute to PRNG for each packet we send/receive */ (*_int_RAND_seed)(buf_in, buf_in_len); /* * add warning re keylength */ (*_int_EVP_DecryptInit_ex)(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); if (!(*_int_EVP_DecryptUpdate)(&ctx, buf_out, &tmplen1, data, datalen)) { (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to decrypt: %s", sslerr); err = -1; goto out; } if (!(*_int_EVP_DecryptFinal_ex)(&ctx, buf_out + tmplen1, &tmplen2)) { (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize decrypt: %s", sslerr); err = -1; goto out; } *buf_out_len = tmplen1 + tmplen2; out: (*_int_EVP_CIPHER_CTX_cleanup)(&ctx); return err; } #endif #ifdef BUILDCRYPTOOPENSSL11 static int encrypt_openssl( knet_handle_t knet_h, const struct iovec *iov, int iovcnt, unsigned char *buf_out, ssize_t *buf_out_len) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; EVP_CIPHER_CTX *ctx; int tmplen = 0, offset = 0; unsigned char *salt = buf_out; unsigned char *data = buf_out + SALT_SIZE; int err = 0; int i; char sslerr[SSLERR_BUF_SIZE]; ctx = (*_int_EVP_CIPHER_CTX_new)(); /* * contribute to PRNG for each packet we send/receive */ (*_int_RAND_seed)((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len); if (!(*_int_RAND_bytes)(salt, SALT_SIZE)) { (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to get random salt data: %s", sslerr); err = -1; goto out; } /* * add warning re keylength */ (*_int_EVP_EncryptInit_ex)(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); for (i=0; icrypto_instance->model_instance; EVP_CIPHER_CTX *ctx; int tmplen1 = 0, tmplen2 = 0; unsigned char *salt = (unsigned char *)buf_in; unsigned char *data = salt + SALT_SIZE; int datalen = buf_in_len - SALT_SIZE; int err = 0; char sslerr[SSLERR_BUF_SIZE]; ctx = (*_int_EVP_CIPHER_CTX_new)(); /* * contribute to PRNG for each packet we send/receive */ (*_int_RAND_seed)(buf_in, buf_in_len); /* * add warning re keylength */ (*_int_EVP_DecryptInit_ex)(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt); if (!(*_int_EVP_DecryptUpdate)(ctx, buf_out, &tmplen1, data, datalen)) { (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to decrypt: %s", sslerr); err = -1; goto out; } if (!(*_int_EVP_DecryptFinal_ex)(ctx, buf_out + tmplen1, &tmplen2)) { (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize decrypt: %s", sslerr); err = -1; goto out; } *buf_out_len = tmplen1 + tmplen2; out: (*_int_EVP_CIPHER_CTX_free)(ctx); return err; } #endif /* * hash/hmac/digest functions */ static int calculate_openssl_hash( knet_handle_t knet_h, const unsigned char *buf, const size_t buf_len, unsigned char *hash) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; unsigned int hash_len = 0; unsigned char *hash_out = NULL; char sslerr[SSLERR_BUF_SIZE]; hash_out = (*_int_HMAC)(instance->crypto_hash_type, instance->private_key, instance->private_key_len, buf, buf_len, hash, &hash_len); if ((!hash_out) || (hash_len != knet_h->sec_hash_size)) { (*_int_ERR_error_string_n)((*_int_ERR_get_error)(), sslerr, sizeof(sslerr)); log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to calculate hash: %s", sslerr); return -1; } return 0; } /* * exported API */ int opensslcrypto_encrypt_and_sign ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { struct iovec iov_in; memset(&iov_in, 0, sizeof(iov_in)); iov_in.iov_base = (unsigned char *)buf_in; iov_in.iov_len = buf_in_len; return opensslcrypto_encrypt_and_signv(knet_h, &iov_in, 1, buf_out, buf_out_len); } int opensslcrypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; int i; if (instance->crypto_cipher_type) { if (encrypt_openssl(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len) < 0) { return -1; } } else { *buf_out_len = 0; for (i=0; icrypto_hash_type) { if (calculate_openssl_hash(knet_h, buf_out, *buf_out_len, buf_out + *buf_out_len) < 0) { return -1; } *buf_out_len = *buf_out_len + knet_h->sec_hash_size; } return 0; } int opensslcrypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len) { struct opensslcrypto_instance *instance = knet_h->crypto_instance->model_instance; ssize_t temp_len = buf_in_len; if (instance->crypto_hash_type) { unsigned char tmp_hash[knet_h->sec_hash_size]; ssize_t temp_buf_len = buf_in_len - knet_h->sec_hash_size; if ((temp_buf_len < 0) || (temp_buf_len > KNET_MAX_PACKET_SIZE)) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Incorrect packet size."); return -1; } if (calculate_openssl_hash(knet_h, buf_in, temp_buf_len, tmp_hash) < 0) { return -1; } if (memcmp(tmp_hash, buf_in + temp_buf_len, knet_h->sec_hash_size) != 0) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Digest does not match"); return -1; } temp_len = temp_len - knet_h->sec_hash_size; *buf_out_len = temp_len; } if (instance->crypto_cipher_type) { if (decrypt_openssl(knet_h, buf_in, temp_len, buf_out, buf_out_len) < 0) { return -1; } } else { memmove(buf_out, buf_in, temp_len); *buf_out_len = temp_len; } return 0; } int opensslcrypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg) { struct opensslcrypto_instance *opensslcrypto_instance = NULL; log_debug(knet_h, KNET_SUB_OPENSSLCRYPTO, "Initizializing openssl crypto module [%s/%s]", knet_handle_crypto_cfg->crypto_cipher_type, knet_handle_crypto_cfg->crypto_hash_type); knet_h->crypto_instance->model_instance = malloc(sizeof(struct opensslcrypto_instance)); if (!knet_h->crypto_instance->model_instance) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to allocate memory for openssl model instance"); return -1; } opensslcrypto_instance = knet_h->crypto_instance->model_instance; memset(opensslcrypto_instance, 0, sizeof(struct opensslcrypto_instance)); if (strcmp(knet_handle_crypto_cfg->crypto_cipher_type, "none") == 0) { opensslcrypto_instance->crypto_cipher_type = NULL; } else { opensslcrypto_instance->crypto_cipher_type = (*_int_EVP_get_cipherbyname)(knet_handle_crypto_cfg->crypto_cipher_type); if (!opensslcrypto_instance->crypto_cipher_type) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unknown crypto cipher type requested"); goto out_err; } } if (strcmp(knet_handle_crypto_cfg->crypto_hash_type, "none") == 0) { opensslcrypto_instance->crypto_hash_type = NULL; } else { opensslcrypto_instance->crypto_hash_type = (*_int_EVP_get_digestbyname)(knet_handle_crypto_cfg->crypto_hash_type); if (!opensslcrypto_instance->crypto_hash_type) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "unknown crypto hash type requested"); goto out_err; } } if ((opensslcrypto_instance->crypto_cipher_type) && (!opensslcrypto_instance->crypto_hash_type)) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "crypto communication requires hash specified"); goto out_err; } opensslcrypto_instance->private_key = malloc(knet_handle_crypto_cfg->private_key_len); if (!opensslcrypto_instance->private_key) { log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to allocate memory for openssl private key"); goto out_err; } memmove(opensslcrypto_instance->private_key, knet_handle_crypto_cfg->private_key, knet_handle_crypto_cfg->private_key_len); opensslcrypto_instance->private_key_len = knet_handle_crypto_cfg->private_key_len; knet_h->sec_header_size = 0; if (opensslcrypto_instance->crypto_hash_type) { knet_h->sec_hash_size = (*_int_EVP_MD_size)(opensslcrypto_instance->crypto_hash_type); knet_h->sec_header_size += knet_h->sec_hash_size; } if (opensslcrypto_instance->crypto_cipher_type) { int block_size; block_size = (*_int_EVP_CIPHER_block_size)(opensslcrypto_instance->crypto_cipher_type); if (block_size < 0) { goto out_err; } knet_h->sec_header_size += (block_size * 2); knet_h->sec_header_size += SALT_SIZE; knet_h->sec_salt_size = SALT_SIZE; knet_h->sec_block_size = block_size; } return 0; out_err: opensslcrypto_fini(knet_h); return -1; } void opensslcrypto_fini( knet_handle_t knet_h) { struct opensslcrypto_instance *opensslcrypto_instance = knet_h->crypto_instance->model_instance; if (opensslcrypto_instance) { if (opensslcrypto_instance->private_key) { free(opensslcrypto_instance->private_key); opensslcrypto_instance->private_key = NULL; } free(opensslcrypto_instance); knet_h->crypto_instance->model_instance = NULL; knet_h->sec_header_size = 0; } return; } #endif diff --git a/libknet/crypto_openssl.h b/libknet/crypto_openssl.h index e598d2fe..f314b9d8 100644 --- a/libknet/crypto_openssl.h +++ b/libknet/crypto_openssl.h @@ -1,50 +1,47 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Author: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_OPENSSLCRYPTO_H__ #define __KNET_OPENSSLCRYPTO_H__ #include "internals.h" struct opensslcrypto_instance; int opensslcrypto_load_lib( knet_handle_t knet_h); -void opensslcrypto_unload_lib( - knet_handle_t knet_h); - int opensslcrypto_init( knet_handle_t knet_h, struct knet_handle_crypto_cfg *knet_handle_crypto_cfg); void opensslcrypto_fini( knet_handle_t knet_h); int opensslcrypto_authenticate_and_decrypt ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int opensslcrypto_encrypt_and_sign ( knet_handle_t knet_h, const unsigned char *buf_in, const ssize_t buf_in_len, unsigned char *buf_out, ssize_t *buf_out_len); int opensslcrypto_encrypt_and_signv ( knet_handle_t knet_h, const struct iovec *iov_in, int iovcnt_in, unsigned char *buf_out, ssize_t *buf_out_len); #endif diff --git a/libknet/internals.h b/libknet/internals.h index 22e6b8bd..b49bbfce 100644 --- a/libknet/internals.h +++ b/libknet/internals.h @@ -1,488 +1,488 @@ /* * Copyright (C) 2010-2015 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * Federico Simoncelli * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #ifndef __KNET_INTERNALS_H__ #define __KNET_INTERNALS_H__ /* * NOTE: you shouldn't need to include this header normally */ #include #include "libknet.h" #include "onwire.h" #include "compat.h" #define KNET_DATABUFSIZE KNET_MAX_PACKET_SIZE + KNET_HEADER_ALL_SIZE #define KNET_DATABUFSIZE_CRYPT_PAD 1024 #define KNET_DATABUFSIZE_CRYPT KNET_DATABUFSIZE + KNET_DATABUFSIZE_CRYPT_PAD #define KNET_DATABUFSIZE_COMPRESS_PAD 1024 #define KNET_DATABUFSIZE_COMPRESS KNET_DATABUFSIZE + KNET_DATABUFSIZE_COMPRESS_PAD #define KNET_RING_RCVBUFF 8388608 #define PCKT_FRAG_MAX UINT8_MAX #define PCKT_RX_BUFS 512 #define KNET_EPOLL_MAX_EVENTS KNET_DATAFD_MAX typedef void *knet_transport_link_t; /* per link transport handle */ typedef void *knet_transport_t; /* per knet_h transport handle */ struct knet_transport_ops; /* Forward because of circular dependancy */ struct knet_mmsghdr { struct msghdr msg_hdr; /* Message header */ unsigned int msg_len; /* Number of bytes transmitted */ }; struct knet_link { /* required */ struct sockaddr_storage src_addr; struct sockaddr_storage dst_addr; /* configurable */ unsigned int dynamic; /* see KNET_LINK_DYN_ define above */ uint8_t priority; /* higher priority == preferred for A/P */ unsigned long long ping_interval; /* interval */ unsigned long long pong_timeout; /* timeout */ unsigned int latency_fix; /* precision */ uint8_t pong_count; /* how many ping/pong to send/receive before link is up */ uint64_t flags; /* status */ struct knet_link_status status; /* internals */ uint8_t link_id; uint8_t transport_type; /* #defined constant from API */ knet_transport_link_t transport_link; /* link_info_t from transport */ int outsock; unsigned int configured:1; /* set to 1 if src/dst have been configured transport initialized on this link*/ unsigned int transport_connected:1; /* set to 1 if lower level transport is connected */ unsigned int latency_exp; uint8_t received_pong; struct timespec ping_last; /* used by PMTUD thread as temp per-link variables and should always contain the onwire_len value! */ uint32_t proto_overhead; struct timespec pmtud_last; uint32_t last_ping_size; uint32_t last_good_mtu; uint32_t last_bad_mtu; uint32_t last_sent_mtu; uint32_t last_recv_mtu; uint8_t has_valid_mtu; }; #define KNET_CBUFFER_SIZE 4096 struct knet_host_defrag_buf { char buf[KNET_DATABUFSIZE]; uint8_t in_use; /* 0 buffer is free, 1 is in use */ seq_num_t pckt_seq; /* identify the pckt we are receiving */ uint8_t frag_recv; /* how many frags did we receive */ uint8_t frag_map[PCKT_FRAG_MAX];/* bitmap of what we received? */ uint8_t last_first; /* special case if we receive the last fragment first */ uint16_t frag_size; /* normal frag size (not the last one) */ uint16_t last_frag_size; /* the last fragment might not be aligned with MTU size */ struct timespec last_update; /* keep time of the last pckt */ }; struct knet_host { /* required */ knet_node_id_t host_id; /* configurable */ uint8_t link_handler_policy; char name[KNET_MAX_HOST_LEN]; /* status */ struct knet_host_status status; /* internals */ char circular_buffer[KNET_CBUFFER_SIZE]; seq_num_t rx_seq_num; seq_num_t untimed_rx_seq_num; seq_num_t timed_rx_seq_num; uint8_t got_data; /* defrag/reassembly buffers */ struct knet_host_defrag_buf defrag_buf[KNET_MAX_LINK]; char circular_buffer_defrag[KNET_CBUFFER_SIZE]; /* link stuff */ struct knet_link link[KNET_MAX_LINK]; uint8_t active_link_entries; uint8_t active_links[KNET_MAX_LINK]; struct knet_host *next; }; struct knet_sock { int sockfd[2]; /* sockfd[0] will always be application facing * and sockfd[1] internal if sockpair has been created by knet */ int is_socket; /* check if it's a socket for recvmmsg usage */ int is_created; /* knet created this socket and has to clean up on exit/del */ int in_use; /* set to 1 if it's use, 0 if free */ int has_error; /* set to 1 if there were errors reading from the sock * and socket has been removed from epoll */ }; struct knet_fd_trackers { uint8_t transport; /* transport type (UDP/SCTP...) */ uint8_t data_type; /* internal use for transport to define what data are associated * to this fd */ void *data; /* pointer to the data */ }; #define KNET_MAX_FDS KNET_MAX_HOST * KNET_MAX_LINK * 4 #define KNET_MAX_COMPRESS_METHODS UINT8_MAX struct knet_handle { knet_node_id_t host_id; unsigned int enabled:1; struct knet_sock sockfd[KNET_DATAFD_MAX]; int logfd; uint8_t log_levels[KNET_MAX_SUBSYSTEMS]; int hostsockfd[2]; int dstsockfd[2]; int send_to_links_epollfd; int recv_from_links_epollfd; int dst_link_handler_epollfd; unsigned int pmtud_interval; unsigned int data_mtu; /* contains the max data size that we can send onwire * without frags */ struct knet_host *host_head; struct knet_host *host_index[KNET_MAX_HOST]; knet_transport_t transports[KNET_MAX_TRANSPORTS+1]; struct knet_transport_ops *transport_ops[KNET_MAX_TRANSPORTS+1]; struct knet_fd_trackers knet_transport_fd_tracker[KNET_MAX_FDS]; /* track status for each fd handled by transports */ struct knet_handle_stats stats; uint32_t reconnect_int; knet_node_id_t host_ids[KNET_MAX_HOST]; size_t host_ids_entries; struct knet_header *recv_from_sock_buf; struct knet_header *send_to_links_buf[PCKT_FRAG_MAX]; struct knet_header *recv_from_links_buf[PCKT_RX_BUFS]; struct knet_header *pingbuf; struct knet_header *pmtudbuf; pthread_t send_to_links_thread; pthread_t recv_from_links_thread; pthread_t heartbt_thread; pthread_t dst_link_handler_thread; pthread_t pmtud_link_handler_thread; int lock_init_done; pthread_rwlock_t global_rwlock; /* global config lock */ pthread_mutex_t pmtud_mutex; /* pmtud mutex to handle conditional send/recv + timeout */ pthread_cond_t pmtud_cond; /* conditional for above */ pthread_mutex_t tx_mutex; /* used to protect knet_send_sync and TX thread */ pthread_mutex_t hb_mutex; /* used to protect heartbeat thread and seq_num broadcasting */ struct crypto_instance *crypto_instance; uint16_t sec_header_size; uint16_t sec_block_size; uint16_t sec_hash_size; uint16_t sec_salt_size; unsigned char *send_to_links_buf_crypt[PCKT_FRAG_MAX]; unsigned char *recv_from_links_buf_crypt; unsigned char *recv_from_links_buf_decrypt; unsigned char *pingbuf_crypt; unsigned char *pmtudbuf_crypt; int compress_model; int compress_level; uint32_t compress_threshold; void *compress_int_data[KNET_MAX_COMPRESS_METHODS]; /* for compress method private data */ unsigned char *recv_from_links_buf_decompress; unsigned char *send_to_links_buf_compress; seq_num_t tx_seq_num; pthread_mutex_t tx_seq_num_mutex; uint8_t has_loop_link; uint8_t loop_link; void *dst_host_filter_fn_private_data; int (*dst_host_filter_fn) ( void *private_data, const unsigned char *outdata, ssize_t outdata_len, uint8_t tx_rx, knet_node_id_t this_host_id, knet_node_id_t src_node_id, int8_t *channel, knet_node_id_t *dst_host_ids, size_t *dst_host_ids_entries); void *pmtud_notify_fn_private_data; void (*pmtud_notify_fn) ( void *private_data, unsigned int data_mtu); void *host_status_change_notify_fn_private_data; void (*host_status_change_notify_fn) ( void *private_data, knet_node_id_t host_id, uint8_t reachable, uint8_t remote, uint8_t external); void *sock_notify_fn_private_data; void (*sock_notify_fn) ( void *private_data, int datafd, int8_t channel, uint8_t tx_rx, int error, int errorno); int fini_in_progress; }; -extern pthread_rwlock_t shlib_rwlock; /* global shared lib load/unload lock */ +extern pthread_rwlock_t shlib_rwlock; /* global shared lib load lock */ /* * NOTE: every single operation must be implementend * for every protocol. */ typedef struct knet_transport_ops { /* * transport generic information */ const char *transport_name; const uint8_t transport_id; uint32_t transport_mtu_overhead; /* * transport init must allocate the new transport * and perform all internal initializations * (threads, lists, etc). */ int (*transport_init)(knet_handle_t knet_h); /* * transport free must releases _all_ resources * allocated by tranport_init */ int (*transport_free)(knet_handle_t knet_h); /* * link operations should take care of all the * sockets and epoll management for a given link/transport set * transport_link_disable should return err = -1 and errno = EBUSY * if listener is still in use, and any other errno in case * the link cannot be disabled. * * set_config/clear_config are invoked in global write lock context */ int (*transport_link_set_config)(knet_handle_t knet_h, struct knet_link *link); int (*transport_link_clear_config)(knet_handle_t knet_h, struct knet_link *link); /* * transport callback for incoming dynamic connections * this is called in global read lock context */ int (*transport_link_dyn_connect)(knet_handle_t knet_h, int sockfd, struct knet_link *link); /* * per transport error handling of recvmmsg * (see _handle_recv_from_links comments for details) */ /* * transport_rx_sock_error is invoked when recvmmsg returns <= 0 * * transport_rx_sock_error is invoked with both global_rdlock */ int (*transport_rx_sock_error)(knet_handle_t knet_h, int sockfd, int recv_err, int recv_errno); /* * transport_tx_sock_error is invoked with global_rwlock and * it's invoked when sendto or sendmmsg returns =< 0 * * it should return: * -1 on internal error * 0 ignore error and continue * 1 retry * any sleep or wait action should happen inside the transport code */ int (*transport_tx_sock_error)(knet_handle_t knet_h, int sockfd, int recv_err, int recv_errno); /* * this function is called on _every_ received packet * to verify if the packet is data or internal protocol error handling * * it should return: * -1 on error * 0 packet is not data and we should continue the packet process loop * 1 packet is not data and we should STOP the packet process loop * 2 packet is data and should be parsed as such * * transport_rx_is_data is invoked with both global_rwlock * and fd_tracker read lock (from RX thread) */ int (*transport_rx_is_data)(knet_handle_t knet_h, int sockfd, struct knet_mmsghdr *msg); } knet_transport_ops_t; socklen_t sockaddr_len(const struct sockaddr_storage *ss); /** * This is a kernel style list implementation. * * @author Steven Dake */ struct knet_list_head { struct knet_list_head *next; struct knet_list_head *prev; }; /** * @def KNET_LIST_DECLARE() * Declare and initialize a list head. */ #define KNET_LIST_DECLARE(name) \ struct knet_list_head name = { &(name), &(name) } #define KNET_INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) /** * Initialize the list entry. * * Points next and prev pointers to head. * @param head pointer to the list head */ static inline void knet_list_init(struct knet_list_head *head) { head->next = head; head->prev = head; } /** * Add this element to the list. * * @param element the new element to insert. * @param head pointer to the list head */ static inline void knet_list_add(struct knet_list_head *element, struct knet_list_head *head) { head->next->prev = element; element->next = head->next; element->prev = head; head->next = element; } /** * Add to the list (but at the end of the list). * * @param element pointer to the element to add * @param head pointer to the list head * @see knet_list_add() */ static inline void knet_list_add_tail(struct knet_list_head *element, struct knet_list_head *head) { head->prev->next = element; element->next = head; element->prev = head->prev; head->prev = element; } /** * Delete an entry from the list. * * @param _remove the list item to remove */ static inline void knet_list_del(struct knet_list_head *_remove) { _remove->next->prev = _remove->prev; _remove->prev->next = _remove->next; } /** * Replace old entry by new one * @param old: the element to be replaced * @param new: the new element to insert */ static inline void knet_list_replace(struct knet_list_head *old, struct knet_list_head *new) { new->next = old->next; new->next->prev = new; new->prev = old->prev; new->prev->next = new; } /** * Tests whether list is the last entry in list head * @param list: the entry to test * @param head: the head of the list * @return boolean true/false */ static inline int knet_list_is_last(const struct knet_list_head *list, const struct knet_list_head *head) { return list->next == head; } /** * A quick test to see if the list is empty (pointing to it's self). * @param head pointer to the list head * @return boolean true/false */ static inline int32_t knet_list_empty(const struct knet_list_head *head) { return head->next == head; } /** * Get the struct for this entry * @param ptr: the &struct list_head pointer. * @param type: the type of the struct this is embedded in. * @param member: the name of the list_struct within the struct. */ #define knet_list_entry(ptr,type,member)\ ((type *)((char *)(ptr)-(char*)(&((type *)0)->member))) /** * Get the first element from a list * @param ptr: the &struct list_head pointer. * @param type: the type of the struct this is embedded in. * @param member: the name of the list_struct within the struct. */ #define knet_list_first_entry(ptr, type, member) \ knet_list_entry((ptr)->next, type, member) /** * Iterate over a list * @param pos: the &struct list_head to use as a loop counter. * @param head: the head for your list. */ #define knet_list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) /** * Iterate over a list backwards * @param pos: the &struct list_head to use as a loop counter. * @param head: the head for your list. */ #define knet_list_for_each_reverse(pos, head) \ for (pos = (head)->prev; pos != (head); pos = pos->prev) /** * Iterate over a list safe against removal of list entry * @param pos: the &struct list_head to use as a loop counter. * @param n: another &struct list_head to use as temporary storage * @param head: the head for your list. */ #define knet_list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) /** * Iterate over list of given type * @param pos: the type * to use as a loop counter. * @param head: the head for your list. * @param member: the name of the list_struct within the struct. */ #define knet_list_for_each_entry(pos, head, member) \ for (pos = knet_list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = knet_list_entry(pos->member.next, typeof(*pos), member)) #endif diff --git a/libknet/tests/Makefile.am b/libknet/tests/Makefile.am index 9621b68c..a1249ac4 100644 --- a/libknet/tests/Makefile.am +++ b/libknet/tests/Makefile.am @@ -1,96 +1,92 @@ # # Copyright (C) 2016 Red Hat, Inc. All rights reserved. # # Authors: Fabio M. Di Nitto # # This software licensed under GPL-2.0+, LGPL-2.0+ # MAINTAINERCLEANFILES = Makefile.in include $(top_srcdir)/build-aux/check.mk include $(top_srcdir)/libknet/tests/api-check.mk EXTRA_DIST = \ api-test-coverage \ api-check.mk AM_CPPFLAGS = -I$(top_srcdir)/libknet # override global LIBS that pulls in lots of craft we don't need here LIBS = $(top_builddir)/libknet/libknet.la \ $(dl_LIBS) $(pthread_LIBS) noinst_HEADERS = \ test-common.h # the order of those tests is NOT random. # some functions can only be tested properly after some dependents # API have been validated upfront. check_PROGRAMS = \ $(api_checks) \ $(int_checks) \ $(fun_checks) int_checks = \ - int_lib_load_unload \ int_crypto_test \ int_timediff_test fun_checks = benchmarks = \ crypto_bench_test \ knet_bench_test noinst_PROGRAMS = \ api_knet_handle_new_limit_test \ pckt_test \ $(benchmarks) \ $(check_PROGRAMS) noinst_SCRIPTS = \ api-test-coverage TESTS = $(check_PROGRAMS) check-local: check-api-test-coverage check-api-test-coverage: chmod u+x $(top_srcdir)/libknet/tests/api-test-coverage $(top_srcdir)/libknet/tests/api-test-coverage $(top_srcdir) $(top_builddir) pckt_test_SOURCES = pckt_test.c -int_lib_load_unload_SOURCES = int_lib_load_unload.c \ - test-common.c - int_crypto_test_SOURCES = int_crypto.c \ ../common.c \ ../crypto.c \ ../crypto_nss.c \ ../crypto_openssl.c \ ../logging.c \ test-common.c int_crypto_test_CFLAGS = $(nss_CFLAGS) int_timediff_test_SOURCES = int_timediff.c crypto_bench_test_SOURCES = crypto_bench.c \ ../common.c \ ../crypto.c \ ../crypto_nss.c \ ../crypto_openssl.c \ ../logging.c \ test-common.c crypto_bench_test_CFLAGS = $(nss_CFLAGS) knet_bench_test_SOURCES = knet_bench.c \ test-common.c \ ../common.c \ ../logging.c \ ../compat.c \ ../transport_common.c diff --git a/libknet/tests/int_lib_load_unload.c b/libknet/tests/int_lib_load_unload.c deleted file mode 100644 index f74a8262..00000000 --- a/libknet/tests/int_lib_load_unload.c +++ /dev/null @@ -1,1059 +0,0 @@ -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libknet.h" -#include "test-common.h" - -char *orig[256]; -int orig_idx = 0; - -char *cur[256]; -int cur_idx = 0; - -int use_cur = 0; - -static int dump_all = 0; - -static int callback(struct dl_phdr_info *info, size_t size, void *data) -{ - if (strlen(info->dlpi_name) > 0) { - if (dump_all) { - printf("lib: %s\n", info->dlpi_name); - } - if (use_cur) { - cur[cur_idx] = strdup(info->dlpi_name); - cur_idx++; - } else { - orig[orig_idx] = strdup(info->dlpi_name); - orig_idx++; - } - } - - return 0; -} - -static void free_loop(void) -{ - int i; - - if (use_cur) { - for (i = 0; i < cur_idx; i++) { - free(cur[i]); - cur[i] = NULL; - } - cur_idx = 0; - } else { - for (i = 0; i < orig_idx; i++) { - free(orig[i]); - orig[i] = NULL; - } - orig_idx = 0; - } -} - -#if defined(BUILDCRYPTONSS) || defined(BUILDCOMPZLIB) -static int find_lib(const char *libname) -{ - int i; - - for (i = 0; i < cur_idx; i++) { - if (strstr(cur[i], libname) != NULL) { - return 1; - } - } - return 0; -} -#endif - -static void test(void) -{ - int logfds[2]; - knet_handle_t knet_h1, knet_h2; -#if defined(BUILDCRYPTONSS) || defined(BUILDCOMPZLIB) - struct knet_handle_crypto_cfg knet_handle_crypto_cfg; -#endif -#ifdef BUILDCOMPZLIB - struct knet_handle_compress_cfg knet_handle_compress_cfg; -#endif - int do_close = 0; - - use_cur = 0; - dl_iterate_phdr(callback, NULL); - use_cur = 1; - - setup_logpipes(logfds); - - knet_h1 = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG); - if (!knet_h1) { - printf("knet_handle_new failed: %s\n", strerror(errno)); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - -#ifdef BUILDCRYPTONSS - printf("Testing loading nss crypto library\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libnss")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing unloading nss crypto library\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libnss")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); -#else - printf("WARNING: nss support not builtin the library. Unable to test/verify internal crypto load/unload code\n"); -#endif - -#ifdef BUILDCRYPTOOPENSSL - printf("Testing loading openssl crypto library\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "openssl", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libcrypto")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing unloading openssl crypto library\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libcrypto")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); -#else - printf("WARNING: openssl support not builtin the library. Unable to test/verify internal crypto load/unload code\n"); -#endif - -#ifdef BUILDCOMPZLIB - printf("Testing loading compress library\n"); - - memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); - strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1); - knet_handle_compress_cfg.compress_level = 1; - knet_handle_compress_cfg.compress_threshold = 64; - - if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libz")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing unloading compress library\n"); - - memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); - strncpy(knet_handle_compress_cfg.compress_model, "none", sizeof(knet_handle_compress_cfg.compress_model) - 1); - knet_handle_compress_cfg.compress_level = 1; - knet_handle_compress_cfg.compress_threshold = 64; - - if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libz")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); -#else - printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress load/unload code\n"); -#endif - - knet_h2 = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG); - if (!knet_h2) { - printf("knet_handle_new failed: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - -#ifdef BUILDCRYPTONSS - printf("Testing multiple handles loading nss crypto library\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - if (knet_handle_crypto(knet_h2, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libnss")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing multiple handles unloading crypto library\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libnss")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - if (knet_handle_crypto(knet_h2, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libnss")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); -#else - printf("WARNING: nss support not builtin the library. Unable to test/verify internal crypto load/unload code\n"); -#endif - -#ifdef BUILDCRYPTOOPENSSL - printf("Testing multiple handles loading openssl crypto library\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "openssl", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - if (knet_handle_crypto(knet_h2, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libcrypto")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing multiple handles unloading crypto library\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libcrypto")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - if (knet_handle_crypto(knet_h2, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libcrypto")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); -#else - printf("WARNING: openssl support not builtin the library. Unable to test/verify internal crypto load/unload code\n"); -#endif - -#ifdef BUILDCOMPZLIB - printf("Testing multiple handles loading compress library\n"); - - memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); - strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1); - knet_handle_compress_cfg.compress_level = 1; - knet_handle_compress_cfg.compress_threshold = 64; - - if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libz")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing multiple handles unloading compress library\n"); - - memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); - strncpy(knet_handle_compress_cfg.compress_model, "none", sizeof(knet_handle_compress_cfg.compress_model) - 1); - knet_handle_compress_cfg.compress_level = 1; - knet_handle_compress_cfg.compress_threshold = 64; - - if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libz")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libz")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); -#else - printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress load/unload code\n"); -#endif - -#ifdef BUILDCRYPTONSS -#ifdef BUILDCRYPTOOPENSSL - printf("Testing multiple handles loading different crypto libraries\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "openssl", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h2, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libnss")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - if (!find_lib("libcrypto")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing multiple handles unloading crypto library\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libnss")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - if (knet_handle_crypto(knet_h2, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libcrypto")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - -#else - printf("WARNING: openssl support not builtin the library. Unable to test/verify internal compress load/unload code\n"); -#endif -#else - printf("WARNING: nss support not builtin the library. Unable to test/verify internal compress load/unload code\n"); -#endif - -#ifdef BUILDCRYPTONSS -#ifdef BUILDCRYPTOOPENSSL - printf("Testing multiple handles loading different crypto libraries (part 2)\n"); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h1, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg)); - strncpy(knet_handle_crypto_cfg.crypto_model, "openssl", sizeof(knet_handle_crypto_cfg.crypto_model) - 1); - strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1); - strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1); - knet_handle_crypto_cfg.private_key_len = 2000; - - if (knet_handle_crypto(knet_h2, &knet_handle_crypto_cfg)) { - printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libnss")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - if (!find_lib("libcrypto")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing multiple handles unloading crypto library by closing handles\n"); - - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libnss")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libcrypto")) { - printf("library doesn't appear to be unloaded\n"); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); -#else - printf("WARNING: openssl support not builtin the library. Unable to test/verify internal compress load/unload code\n"); - do_close = 1; -#endif -#else - printf("WARNING: nss support not builtin the library. Unable to test/verify internal compress load/unload code\n"); - do_close = 1; -#endif - - knet_h1 = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG); - if (!knet_h1) { - printf("knet_handle_new failed: %s\n", strerror(errno)); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - knet_h2 = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG); - if (!knet_h2) { - printf("knet_handle_new failed: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - -#ifdef BUILDCOMPZLIB -#ifdef BUILDCOMPBZIP2 - printf("Testing multiple handles loading different compress libraries\n"); - - memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); - strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1); - knet_handle_compress_cfg.compress_level = 1; - knet_handle_compress_cfg.compress_threshold = 64; - - if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); - strncpy(knet_handle_compress_cfg.compress_model, "bzip2", sizeof(knet_handle_compress_cfg.compress_model) - 1); - knet_handle_compress_cfg.compress_level = 1; - knet_handle_compress_cfg.compress_threshold = 64; - - if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libz")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - if (!find_lib("libbz2")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing multiple handles unloading compress library\n"); - - memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); - strncpy(knet_handle_compress_cfg.compress_model, "none", sizeof(knet_handle_compress_cfg.compress_model) - 1); - knet_handle_compress_cfg.compress_level = 1; - knet_handle_compress_cfg.compress_threshold = 64; - - if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libz")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libbz2")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); -#else - printf("WARNING: bzip2 support not builtin the library. Unable to test/verify internal compress load/unload code\n"); -#endif -#else - printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress load/unload code\n"); -#endif - -#ifdef BUILDCOMPZLIB -#ifdef BUILDCOMPBZIP2 - printf("Testing multiple handles loading different compress libraries (part 2)\n"); - - memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); - strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1); - knet_handle_compress_cfg.compress_level = 1; - knet_handle_compress_cfg.compress_threshold = 64; - - if (knet_handle_compress(knet_h1, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg)); - strncpy(knet_handle_compress_cfg.compress_model, "bzip2", sizeof(knet_handle_compress_cfg.compress_model) - 1); - knet_handle_compress_cfg.compress_level = 1; - knet_handle_compress_cfg.compress_threshold = 64; - - if (knet_handle_compress(knet_h2, &knet_handle_compress_cfg) != 0) { - printf("knet_handle_compress failed with correct config: %s\n", strerror(errno)); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (!find_lib("libz")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - if (!find_lib("libbz2")) { - printf("library doesn't appear to be loaded\n"); - knet_handle_free(knet_h1); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - printf("Testing multiple handles unloading compress library by closing handles\n"); - - knet_handle_free(knet_h1); - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libz")) { - printf("library doesn't appear to be unloaded\n"); - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); - - knet_handle_free(knet_h2); - flush_logs(logfds[0], stdout); - - dl_iterate_phdr(callback, NULL); - - if (find_lib("libbz2")) { - printf("library doesn't appear to be unloaded\n"); - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - exit(FAIL); - } - - free_loop(); -#else - printf("WARNING: bzip2 support not builtin the library. Unable to test/verify internal compress load/unload code\n"); - do_close = 1; -#endif -#else - printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress load/unload code\n"); - do_close = 1; -#endif - - if (do_close) { - knet_handle_free(knet_h2); - knet_handle_free(knet_h1); - } - flush_logs(logfds[0], stdout); - close_logpipes(logfds); - use_cur = 0; - free_loop(); -} - -int main(int argc, char *argv[]) -{ - need_root(); - - test(); - - return PASS; -}