diff --git a/.gitignore b/.gitignore index 759e634c..fde01c66 100644 --- a/.gitignore +++ b/.gitignore @@ -1,53 +1,55 @@ *.o *.a *.la *.lo *.pc *.tar.* *.sha256* stamp-h1 Makefile.in Makefile .deps .libs .version .dirstamp # build-aux/release.mk related litter /.tarball-version /tag-* aclocal.m4 autoconf autoheader autom4te.cache automake compile config.* configure* debian/changelog debian/kronosnetd.postinst debian/patches depcomp install-sh libtoolize ltmain.sh m4 missing libtool autoscan.log init/kronosnetd init/kronosnetd.service kronosnetd/kronosnetd kronosnetd/knet-keygen kronosnetd/kronosnetd.logrotate kronosnet.spec +libknet/compress_canary +libknet/crypto_canary *.swp *_test *_bench test-driver *.trs *.log Doxyfile doxyfile.stamp xml/ diff --git a/libknet/Makefile.am b/libknet/Makefile.am index 18cbb82f..c0bd4cfa 100644 --- a/libknet/Makefile.am +++ b/libknet/Makefile.am @@ -1,122 +1,130 @@ # # Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved. # # Authors: Fabio M. Di Nitto # Federico Simoncelli # # This software licensed under GPL-2.0+, LGPL-2.0+ # MAINTAINERCLEANFILES = Makefile.in include $(top_srcdir)/build-aux/check.mk SYMFILE = libknet_exported_syms EXTRA_DIST = $(SYMFILE) SUBDIRS = . tests man libversion = 1:0:0 # override global LIBS that pulls in lots of craft we don't need here LIBS = sources = \ common.c \ compat.c \ compress.c \ compress_zlib.c \ compress_lz4.c \ compress_lzo2.c \ compress_lzma.c \ compress_bzip2.c \ crypto.c \ crypto_nss.c \ crypto_openssl.c \ handle.c \ host.c \ links.c \ logging.c \ netutils.c \ threads_common.c \ threads_dsthandler.c \ threads_heartbeat.c \ threads_pmtud.c \ threads_rx.c \ threads_tx.c \ transport_udp.c \ transport_sctp.c \ transport_loopback.c \ transport_common.c include_HEADERS = libknet.h pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libknet.pc noinst_HEADERS = \ common.h \ compat.h \ compress.h \ - compress_zlib.h \ + compress_bzip2.h \ + compress_bzip2_remap.h \ compress_lz4.h \ - compress_lzo2.h \ + compress_lz4_remap.h \ compress_lzma.h \ - compress_bzip2.h \ + compress_lzma_remap.h \ + compress_lzo2.h \ + compress_lzo2_remap.h \ + compress_zlib.h \ + compress_zlib_remap.h \ crypto.h \ crypto_nss.h \ + crypto_nss_remap.h \ crypto_openssl.h \ + crypto_openssl_remap.h \ host.h \ internals.h \ links.h \ logging.h \ netutils.h \ onwire.h \ + remap.h \ threads_common.h \ threads_dsthandler.h \ threads_heartbeat.h \ threads_pmtud.h \ threads_rx.h \ threads_tx.h \ transports.h lib_LTLIBRARIES = libknet.la libknet_la_SOURCES = $(sources) libknet_la_CFLAGS = $(nss_CFLAGS) $(openssl_CFLAGS) \ $(zlib_CFLAGS) $(liblz4_CFLAGS) $(lzo2_CFLAGS) $(liblzma_CFLAGS) $(bzip2_CFLAGS) EXTRA_libknet_la_DEPENDENCIES = $(SYMFILE) libknet_la_LDFLAGS = -Wl,--version-script=$(srcdir)/$(SYMFILE) \ --export-dynamic \ -version-number $(libversion) libknet_la_LIBADD = $(dl_LIBS) $(pthread_LIBS) $(rt_LIBS) $(m_LIBS) noinst_PROGRAMS = crypto_canary compress_canary crypto_canary_SOURCES = crypto_canary.c crypto_canary_CFLAGS = $(nss_CFLAGS) $(openssl_CFLAGS) crypto_canary_LDADD = $(nss_LIBS) $(openssl_LIBS) compress_canary_SOURCES = compress_canary.c compress_canary_CFLAGS = $(zlib_CFLAGS) $(liblz4_CFLAGS) $(lzo2_CFLAGS) $(liblzma_CFLAGS) $(bzip2_CFLAGS) compress_canary_LDADD = $(zlib_LIBS) $(liblz4_LIBS) $(lzo2_LIBS) $(liblzma_LIBS) $(bzip2_LIBS) dist_man_MANS = man update-man-pages: doxyfile.stamp doxyfile.stamp: Doxyfile if MANPAGEUPDATES $(DOXYGEN) Doxyfile $(DOXY2MAN) -o $(abs_srcdir)/man -s 3 --short-pkg @PACKAGE_NAME@ --pkg "Kronosnet Programmer's Manual" $(builddir)/xml/libknet_8h.xml else @echo this system does not have doxy2man or doxygen installed. Unable to update man pages automatically. endif touch doxyfile.stamp clean-local: rm -rf doxyfile.stamp xml diff --git a/libknet/common.c b/libknet/common.c index eefa100c..4d104722 100644 --- a/libknet/common.c +++ b/libknet/common.c @@ -1,120 +1,130 @@ /* * 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 #include #include #include #include #include "logging.h" #include "common.h" int _fdset_cloexec(int fd) { int fdflags; fdflags = fcntl(fd, F_GETFD, 0); if (fdflags < 0) return -1; fdflags |= FD_CLOEXEC; if (fcntl(fd, F_SETFD, fdflags) < 0) return -1; return 0; } int _fdset_nonblock(int fd) { int fdflags; fdflags = fcntl(fd, F_GETFL, 0); if (fdflags < 0) return -1; fdflags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, fdflags) < 0) return -1; return 0; } void *open_lib(knet_handle_t knet_h, const char *libname, int extra_flags) { void *ret = NULL; char *error = NULL; char dir[MAXPATHLEN], path[MAXPATHLEN], link[MAXPATHLEN]; struct stat sb; /* * clear any pending error */ dlerror(); ret = dlopen(libname, RTLD_NOW | RTLD_GLOBAL | extra_flags); error = dlerror(); if (error != NULL) { log_err(knet_h, KNET_SUB_COMMON, "unable to dlopen %s: %s", libname, error); errno = EAGAIN; return NULL; } memset(dir, 0, sizeof(dir)); memset(link, 0, sizeof(link)); memset(path, 0, sizeof(path)); if (dlinfo(ret, RTLD_DI_ORIGIN, &dir) < 0) { /* * should we dlclose and return error? */ log_warn(knet_h, KNET_SUB_COMMON, "unable to dlinfo %s: %s", libname, error); } else { snprintf(path, sizeof(path), "%s/%s", dir, libname); log_info(knet_h, KNET_SUB_COMMON, "%s has been loaded from %s", libname, path); /* * try to resolve the library and check if it is a symlink and to where. * we can't prevent symlink attacks but at least we can log where the library * has been loaded from */ if (lstat(path, &sb) < 0) { log_debug(knet_h, KNET_SUB_COMMON, "Unable to stat %s: %s", path, strerror(errno)); goto out; } if (S_ISLNK(sb.st_mode)) { if (readlink(path, link, sizeof(link)) < 0) { log_debug(knet_h, KNET_SUB_COMMON, "Unable to readlink %s: %s", path, strerror(errno)); goto out; } /* * symlink is relative to the directory */ if (link[0] != '/') { snprintf(path, sizeof(path), "%s/%s", dir, link); log_info(knet_h, KNET_SUB_COMMON, "%s/%s is a symlink to %s", dir, libname, path); } else { log_info(knet_h, KNET_SUB_COMMON, "%s/%s is a symlink to %s", dir, libname, link); } } } out: return ret; } + +void *remap_symbol(knet_handle_t knet_h, uint8_t subsystem, + void *lib_handle, const char *symbol_name) +{ + void *symbol = dlsym (lib_handle, symbol_name); + if (!symbol) { + log_err (knet_h, subsystem, "unable to map %s: %s", symbol_name, dlerror ()); + } + return symbol; +} diff --git a/libknet/common.h b/libknet/common.h index 6aebe630..f92f5941 100644 --- a/libknet/common.h +++ b/libknet/common.h @@ -1,19 +1,21 @@ /* * Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * Federico Simoncelli * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "internals.h" #ifndef __KNET_COMMON_H__ #define __KNET_COMMON_H__ int _fdset_cloexec(int fd); int _fdset_nonblock(int fd); void *open_lib(knet_handle_t knet_h, const char *libname, int extra_flags); +void *remap_symbol(knet_handle_t knet_h, uint8_t subsystem, + void *lib_handle, const char *symbol_name); #endif diff --git a/libknet/compress_bzip2.c b/libknet/compress_bzip2.c index f65f7e40..b276530a 100644 --- a/libknet/compress_bzip2.c +++ b/libknet/compress_bzip2.c @@ -1,190 +1,167 @@ /* * Copyright (C) 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); +#include "compress_bzip2_remap.h" 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; - } +#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_BZIP2COMP, bzip2_lib, name) +#include "compress_bzip2_remap.h" + return 0; - _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; + fail: +#define REMAP_FAIL +#include "compress_bzip2_remap.h" + errno = EINVAL; + return -1; } 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; } out: errno = savederrno; return err; } 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_remap.h b/libknet/compress_bzip2_remap.h new file mode 100644 index 00000000..917e7ee1 --- /dev/null +++ b/libknet/compress_bzip2_remap.h @@ -0,0 +1,11 @@ +#include "remap.h" + +REMAP_PROTO(int,BZ2_bzBuffToBuffCompress, + (char* dest, unsigned int* destLen, + char* source, unsigned int sourceLen, + int blockSize100k, int verbosity, + int workFactor)) +REMAP_PROTO(int,BZ2_bzBuffToBuffDecompress, + (char* dest, unsigned int* destLen, + char* source, unsigned int sourceLen, + int samll, int verbosity)) diff --git a/libknet/compress_canary.c b/libknet/compress_canary.c index 9cdf6d53..fe010fa2 100644 --- a/libknet/compress_canary.c +++ b/libknet/compress_canary.c @@ -1,32 +1,36 @@ /* Transform the binary into dependencies like: * dpkg-shlibdeps -pcompress -dSuggests -xlibc6 -elibknet/compress_canary */ #include "config.h" -char BZ2_bzBuffToBuffCompress(void); -char LZ4_compress_HC(void); -char lzma_easy_buffer_encode(void); -char lzo1x_1_compress(void); -char compress2(void); +#define CANARY + +#include "compress_bzip2_remap.h" +#include "compress_lz4_remap.h" +#include "compress_lzma_remap.h" +#include "compress_lzo2_remap.h" +#include "compress_zlib_remap.h" + +#define CANARY_CALL int main (void) { return #ifdef BUILDCOMPBZIP2 - BZ2_bzBuffToBuffCompress() + +#include "compress_bzip2_remap.h" #endif #ifdef BUILDCOMPLZ4 - LZ4_compress_HC() + +#include "compress_lz4_remap.h" #endif #ifdef BUILDCOMPLZMA - lzma_easy_buffer_encode() + +#include "compress_lzma_remap.h" #endif #ifdef BUILDCOMPLZO2 - lzo1x_1_compress() + +#include "compress_lzo2_remap.h" #endif #ifdef BUILDCOMPZLIB - compress2() + +#include "compress_zlib_remap.h" #endif 0; } diff --git a/libknet/compress_lz4.c b/libknet/compress_lz4.c index f9da3553..e491ee12 100644 --- a/libknet/compress_lz4.c +++ b/libknet/compress_lz4.c @@ -1,243 +1,207 @@ /* * Copyright (C) 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); +#include "compress_lz4_remap.h" 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; - } +#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_LZ4COMP, lz4_lib, name) +#include "compress_lz4_remap.h" + return 0; -out: - if (err) { - _int_LZ4_compress_HC = NULL; - _int_LZ4_compress_fast = NULL; - _int_LZ4_decompress_safe = NULL; - errno = EINVAL; - } - return err; + fail: +#define REMAP_FAIL +#include "compress_lz4_remap.h" + errno = EINVAL; + return -1; } 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; } out: errno = savederrno; return err; } 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_remap.h b/libknet/compress_lz4_remap.h new file mode 100644 index 00000000..039cc9ad --- /dev/null +++ b/libknet/compress_lz4_remap.h @@ -0,0 +1,13 @@ +#include "remap.h" + +REMAP_PROTO(int,LZ4_compress_HC, + (const char* src, char* dst, + int srcSize, int dstCapacity, + int compressionLevel)) +REMAP_PROTO(int,LZ4_compress_fast, + (const char* source, char* dest, + int sourceSize, int maxDestSize, + int acceleration)) +REMAP_PROTO(int,LZ4_decompress_safe, + (const char* source, char* dest, + int compressedSize, int maxDecompressedSize)) diff --git a/libknet/compress_lzma.c b/libknet/compress_lzma.c index 79a0acb9..359382ca 100644 --- a/libknet/compress_lzma.c +++ b/libknet/compress_lzma.c @@ -1,205 +1,179 @@ /* * Copyright (C) 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); +#include "compress_lzma_remap.h" 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; - } +#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_LZMACOMP, lzma_lib, name) +#include "compress_lzma_remap.h" + return 0; - _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; + fail: +#define REMAP_FAIL +#include "compress_lzma_remap.h" + errno = EINVAL; + return -1; } 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; } out: errno = savederrno; return err; } 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_remap.h b/libknet/compress_lzma_remap.h new file mode 100644 index 00000000..780ebd53 --- /dev/null +++ b/libknet/compress_lzma_remap.h @@ -0,0 +1,12 @@ +#include "remap.h" + +REMAP_PROTO(LZMA_API(lzma_ret),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)) +REMAP_PROTO(LZMA_API(lzma_ret),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)) diff --git a/libknet/compress_lzo2.c b/libknet/compress_lzo2.c index 792ddd28..37ac8f2c 100644 --- a/libknet/compress_lzo2.c +++ b/libknet/compress_lzo2.c @@ -1,278 +1,204 @@ /* * Copyright (C) 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); +#include "compress_lzo2_remap.h" 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; - } +#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_LZO2COMP, lzo2_lib, name) +#include "compress_lzo2_remap.h" + return 0; -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; + fail: +#define REMAP_FAIL +#include "compress_lzo2_remap.h" + errno = EINVAL; + return -1; } 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; } out: errno = savederrno; return err; } 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_remap.h b/libknet/compress_lzo2_remap.h new file mode 100644 index 00000000..c0c7d2b7 --- /dev/null +++ b/libknet/compress_lzo2_remap.h @@ -0,0 +1,26 @@ +#include "remap.h" + +REMAP_PROTO(int,lzo1x_decompress, + (const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ )) +REMAP_PROTO(int,lzo1x_1_compress, + (const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem)) +REMAP_PROTO(int,lzo1x_1_11_compress, + (const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem)) +REMAP_PROTO(int,lzo1x_1_12_compress, + (const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem)) +REMAP_PROTO(int,lzo1x_1_15_compress, + (const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem)) +REMAP_PROTO(int,lzo1x_999_compress, + (const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem)) diff --git a/libknet/compress_zlib.c b/libknet/compress_zlib.c index 6200b692..08037d24 100644 --- a/libknet/compress_zlib.c +++ b/libknet/compress_zlib.c @@ -1,206 +1,182 @@ /* * Copyright (C) 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" #ifdef KNET_LINUX #define LIBZ_1 "libz.so.1" #endif #ifdef KNET_BSD #define LIBZ_1 "libz.so" #endif /* * 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); +#include "compress_zlib_remap.h" 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; - } +#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_ZLIBCOMP, zlib_lib, name) +#include "compress_zlib_remap.h" + return 0; -out: - if (err) { - _int_uncompress = NULL; - _int_compress2 = NULL; - errno = EINVAL; - } - return err; + fail: +#define REMAP_FAIL +#include "compress_zlib_remap.h" + errno = EINVAL; + return -1; } 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; } out: errno = savederrno; return err; } 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_remap.h b/libknet/compress_zlib_remap.h new file mode 100644 index 00000000..7ff16e67 --- /dev/null +++ b/libknet/compress_zlib_remap.h @@ -0,0 +1,9 @@ +#include "remap.h" + +REMAP_PROTO(int,uncompress, + (Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)) +REMAP_PROTO(int,compress2, + (Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)) diff --git a/libknet/crypto_canary.c b/libknet/crypto_canary.c index c9fcced4..1555694c 100644 --- a/libknet/crypto_canary.c +++ b/libknet/crypto_canary.c @@ -1,20 +1,24 @@ /* Transform the binary into dependencies like: * dpkg-shlibdeps -pcrypto -dRecommends -xlibc6 -elibknet/crypto_canary -O | sed 's/,/ |/g' >>debian/substvars */ #include "config.h" -char NSS_NoDB_Init(void); -char EVP_EncryptInit_ex(void); +#define CANARY + +#include "crypto_nss_remap.h" +#include "crypto_openssl_remap.h" + +#define CANARY_CALL int main (void) { return #ifdef BUILDCRYPTONSS - NSS_NoDB_Init() + +#include "crypto_nss_remap.h" #endif #ifdef BUILDCRYPTOOPENSSL - EVP_EncryptInit_ex() + +#include "crypto_openssl_remap.h" #endif 0; } diff --git a/libknet/crypto_nss.c b/libknet/crypto_nss.c index c6a12e67..4f554ebb 100644 --- a/libknet/crypto_nss.c +++ b/libknet/crypto_nss.c @@ -1,1147 +1,858 @@ /* * Copyright (C) 2012-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; -} +#include "crypto_nss_remap.h" 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; - } - +#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_NSSCRYPTO, nss_lib, name) +#include "crypto_nss_remap.h" + return 0; -out: - if (err) { - clean_nss_syms(); - } - return err; + fail: +#define REMAP_FAIL +#include "crypto_nss_remap.h" + errno = EINVAL; + return -1; } static int nss_db_is_init = 0; static int at_exit_registered = 0; static void nss_atexit_handler(void) { 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)(); } } } 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; 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 ((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: 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_remap.h b/libknet/crypto_nss_remap.h new file mode 100644 index 00000000..572aecda --- /dev/null +++ b/libknet/crypto_nss_remap.h @@ -0,0 +1,54 @@ +#include "remap.h" + +/* + * nss3 + */ +REMAP_PROTO(CK_MECHANISM_TYPE,PK11_GetBestWrapMechanism,(PK11SlotInfo *slot)) +REMAP_PROTO(PK11SlotInfo *,PK11_GetBestSlot, + (CK_MECHANISM_TYPE type, void *wincx)) +REMAP_PROTO(int,PK11_GetBestKeyLength, + (PK11SlotInfo *slot, CK_MECHANISM_TYPE type)) +REMAP_PROTO(SECStatus,PK11_DigestFinal, + (PK11Context *context, unsigned char *data, + unsigned int *outLen, unsigned int length)) +REMAP_PROTO(void,SECITEM_FreeItem,(SECItem *zap, PRBool freeit)) +REMAP_PROTO(SECStatus,NSS_NoDB_Init,(const char *configdir)) +REMAP_PROTO(SECStatus,NSS_Shutdown,(void)) +REMAP_PROTO(SECStatus,PK11_DigestBegin,(PK11Context *cx)) +REMAP_PROTO(SECStatus,PK11_DigestOp, + (PK11Context *context, const unsigned char *in, unsigned len)) +REMAP_PROTO(void,PK11_DestroyContext,(PK11Context *context, PRBool freeit)) +REMAP_PROTO(SECStatus,PK11_Finalize,(PK11Context *context)) +REMAP_PROTO(SECStatus,PK11_CipherOp, + (PK11Context *context, unsigned char *out, int *outlen, + int maxout, const unsigned char *in, int inlen)) +REMAP_PROTO(PK11SymKey *,PK11_UnwrapSymKey, + (PK11SymKey *key, CK_MECHANISM_TYPE wraptype, SECItem *param, + SECItem *wrapppedKey, CK_MECHANISM_TYPE target, + CK_ATTRIBUTE_TYPE operation, int keySize)) +REMAP_PROTO(void,PK11_FreeSymKey,(PK11SymKey *key)) +REMAP_PROTO(PK11Context *,PK11_CreateContextBySymKey, + (CK_MECHANISM_TYPE type, + CK_ATTRIBUTE_TYPE operation, + PK11SymKey *symKey, SECItem *param)) +REMAP_PROTO(SECStatus,PK11_GenerateRandom,(unsigned char *data, int len)) +REMAP_PROTO(SECItem *,PK11_ParamFromIV,(CK_MECHANISM_TYPE type, SECItem *iv)) +REMAP_PROTO(void,PK11_FreeSlot,(PK11SlotInfo *slot)) +REMAP_PROTO(int,PK11_GetBlockSize,(CK_MECHANISM_TYPE type, SECItem *params)) +REMAP_PROTO(PK11SymKey *,PK11_KeyGen, + (PK11SlotInfo *slot, CK_MECHANISM_TYPE type, + SECItem *param, int keySize, void *wincx)) + +/* + * nspr4 + */ +REMAP_PROTO(PRStatus,PR_Cleanup,(void)) +REMAP_PROTO(const char *,PR_ErrorToString, + (PRErrorCode code, PRLanguageCode language)) +REMAP_PROTO(PRErrorCode,PR_GetError,(void)) +REMAP_PROTO(PRBool,PR_Initialized,(void)) + +/* + * plds4 + */ +REMAP_PROTO(void,PL_ArenaFinish,(void)) diff --git a/libknet/crypto_openssl.c b/libknet/crypto_openssl.c index dfc8fdb8..81b4bc6b 100644 --- a/libknet/crypto_openssl.c +++ b/libknet/crypto_openssl.c @@ -1,848 +1,577 @@ /* * Copyright (C) 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 */ #ifdef KNET_LINUX #define LIBOPENSSL "libcrypto.so" #endif #ifdef KNET_BSD #define LIBOPENSSL "libcrypto.so.10" #endif /* * 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); - -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); - - -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; - - _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; - return; -} +#include "crypto_openssl_remap.h" 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; - } - - _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; - } - -out: - if (err) { - clean_openssl_syms(); - } +#define REMAP_WITH(name) remap_symbol (knet_h, KNET_SUB_OPENSSLCRYPTO, openssl_lib, name) +#include "crypto_openssl_remap.h" + return 0; - return err; + fail: +#define REMAP_FAIL +#include "crypto_openssl_remap.h" + errno = EINVAL; + return -1; } 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 (!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: 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_remap.h b/libknet/crypto_openssl_remap.h new file mode 100644 index 00000000..6d2d609e --- /dev/null +++ b/libknet/crypto_openssl_remap.h @@ -0,0 +1,58 @@ +#include "remap.h" + +#ifdef BUILDCRYPTOOPENSSL10 +REMAP_PROTO(void,OPENSSL_add_all_algorithms_noconf,(void)) +#endif +#ifdef BUILDCRYPTOOPENSSL11 +REMAP_PROTO(int,OPENSSL_init_crypto, + (uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)) +#endif + +#ifdef BUILDCRYPTOOPENSSL10 +REMAP_PROTO(void,ERR_load_crypto_strings,(void)) +#endif +REMAP_PROTO(unsigned long,ERR_get_error,(void)) +REMAP_PROTO(void,ERR_error_string_n, + (unsigned long e, char *buf, size_t len)) + +REMAP_PROTO(void,RAND_seed,(const void *buf, int num)) +REMAP_PROTO(int,RAND_bytes,(unsigned char *buf, int num)) + +REMAP_PROTO(const EVP_MD *,EVP_get_digestbyname,(const char *name)) +REMAP_PROTO(int,EVP_MD_size,(const EVP_MD *md)) +REMAP_PROTO(unsigned char *,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)) + +REMAP_PROTO(const EVP_CIPHER *,EVP_get_cipherbyname,(const char *name)) +REMAP_PROTO(int,EVP_CIPHER_block_size,(const EVP_CIPHER *cipher)) + +#ifdef BUILDCRYPTOOPENSSL10 +REMAP_PROTO(void,EVP_CIPHER_CTX_init,(EVP_CIPHER_CTX *a)) +REMAP_PROTO(int,EVP_CIPHER_CTX_cleanup,(EVP_CIPHER_CTX *a)) +#endif +#ifdef BUILDCRYPTOOPENSSL11 +REMAP_PROTO(EVP_CIPHER_CTX *,EVP_CIPHER_CTX_new,(void)) +REMAP_PROTO(void,EVP_CIPHER_CTX_free,(EVP_CIPHER_CTX *c)) +#endif + +REMAP_PROTO(int,EVP_EncryptInit_ex, + (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, + const unsigned char *iv)) +REMAP_PROTO(int,EVP_EncryptUpdate, + (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl)) +REMAP_PROTO(int,EVP_EncryptFinal_ex, + (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)) + +REMAP_PROTO(int,EVP_DecryptInit_ex, + (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, + const unsigned char *iv)) +REMAP_PROTO(int,EVP_DecryptUpdate, + (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl)) +REMAP_PROTO(int,EVP_DecryptFinal_ex, + (EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl)) diff --git a/libknet/remap.h b/libknet/remap.h new file mode 100644 index 00000000..87c1e679 --- /dev/null +++ b/libknet/remap.h @@ -0,0 +1,27 @@ +/* Repeated inclusions define this differently */ +#undef REMAP_PROTO + +#ifdef CANARY + +/* Canary uses fake prototype to make "calls" uniform */ +#ifdef CANARY_CALL +#define REMAP_PROTO(ret,name,args) name() + +#else +#define REMAP_PROTO(ret,name,args) char name(void); +#endif /* CANARY_CALL */ + +#else + +#ifdef REMAP_FAIL +#define REMAP_PROTO(ret,name,args) _int_ ## name = NULL; +#else +#ifdef REMAP_WITH +#define REMAP_PROTO(ret,name,args) if (!(_int_ ## name = REMAP_WITH(#name))) goto fail; +#else +/* Provide the plain prototype as well for validation */ +#define REMAP_PROTO(ret,name,args) ret (*_int_ ## name)args; \ + ret name args; +#endif /* REMAP_WITH */ +#endif /* REMAP_FAIL */ + +#endif /* CANARY */