Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/configure.ac b/configure.ac
index 13b02c3e..d68eef1c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,502 +1,494 @@
#
# Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved.
#
# Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
# Federico Simoncelli <fsimon@kronosnet.org>
#
# This software licensed under GPL-2.0+, LGPL-2.0+
#
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
#
AC_PREREQ([2.63])
AC_INIT([kronosnet],
m4_esyscmd([build-aux/git-version-gen .tarball-version]),
[devel@lists.kronosnet.org])
AC_USE_SYSTEM_EXTENSIONS
AM_INIT_AUTOMAKE([1.13 dist-bzip2 dist-xz color-tests -Wno-portability subdir-objects])
LT_PREREQ([2.2.6])
LT_INIT
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([kronosnetd/main.c])
AC_CONFIG_HEADERS([config.h])
AC_CANONICAL_HOST
AC_PROG_LIBTOOL
AC_LANG([C])
systemddir=${prefix}/lib/systemd/system
if test "$prefix" = "NONE"; then
prefix="/usr"
if test "$localstatedir" = "\${prefix}/var"; then
localstatedir="/var"
fi
if test "$sysconfdir" = "\${prefix}/etc"; then
sysconfdir="/etc"
fi
if test "$systemddir" = "NONE/lib/systemd/system"; then
systemddir=/lib/systemd/system
fi
if test "$libdir" = "\${exec_prefix}/lib"; then
if test -e /usr/lib64; then
libdir="/usr/lib64"
else
libdir="/usr/lib"
fi
fi
fi
AC_PROG_AWK
AC_PROG_GREP
AC_PROG_SED
AC_PROG_CPP
AC_PROG_CC
AC_PROG_CC_C99
if test "x$ac_cv_prog_cc_c99" = "xno"; then
AC_MSG_ERROR(["C99 support is required"])
fi
AC_PROG_LN_S
AC_PROG_INSTALL
AC_PROG_MAKE_SET
PKG_PROG_PKG_CONFIG
AC_CHECK_PROGS([DOXYGEN], [doxygen])
AC_CHECK_PROGS([DOXY2MAN], [doxy2man])
manpageupdates=1
if test "x$DOXYGEN" = "x" || test "x$DOXY2MAN" = "x"; then
manpageupdates=0;
fi
AM_CONDITIONAL([MANPAGEUPDATES], [test $manpageupdates -gt 0])
AC_CHECK_PROGS([VALGRIND_EXEC], [valgrind])
AM_CONDITIONAL([HAS_VALGRIND], [test x$VALGRIND_EXEC != "x"])
AC_ARG_ENABLE([libknet-sctp],
[ --disable-libknet-sctp : disable libknet SCTP support ],,
[ enable_libknet_sctp="yes" ])
AM_CONDITIONAL([BUILDSCTP], [test x$enable_libknet_sctp = xyes])
AC_ARG_ENABLE([crypto-all],
[ --disable-crypto-all : disable libknet all crypto modules support ],,
[ enable_crypto_all="yes" ])
AC_ARG_ENABLE([crypto-nss],
[ --disable-crypto-nss : disable libknet nss support ],,
[ enable_crypto_nss="$enable_crypto_all" ])
AM_CONDITIONAL([BUILDCRYPTONSS], [test x$enable_crypto_nss = xyes])
AC_ARG_ENABLE([crypto-openssl],
[ --disable-crypto-openssl : disable libknet openssl support ],,
[ enable_crypto_openssl="$enable_crypto_all" ])
AM_CONDITIONAL([BUILDCRYPTOOPENSSL], [test x$enable_crypto_openssl = xyes])
AC_ARG_ENABLE([compress-all],
[ --disable-compress-all : disable libknet all compress modules support ],,
[ enable_compress_all="yes" ])
AC_ARG_ENABLE([compress-zlib],
[ --disable-compress-zlib : disable libknet zlib support ],,
[ enable_compress_zlib="$enable_compress_all" ])
AM_CONDITIONAL([BUILDCOMPZLIB], [test x$enable_compress_zlib = xyes])
AC_ARG_ENABLE([compress-lz4],
[ --disable-compress-lz4 : disable libknet lz4 support ],,
[ enable_compress_lz4="$enable_compress_all" ])
AM_CONDITIONAL([BUILDCOMPLZ4], [test x$enable_compress_lz4 = xyes])
AC_ARG_ENABLE([compress-lzo2],
[ --disable-compress-lzo2 : disable libknet lzo2 support ],,
[ enable_compress_lzo2="$enable_compress_all" ])
AM_CONDITIONAL([BUILDCOMPLZO2], [test x$enable_compress_lzo2 = xyes])
AC_ARG_ENABLE([compress-lzma],
[ --disable-compress-lzma : disable libknet lzma support ],,
[ enable_compress_lzma="$enable_compress_all" ])
AM_CONDITIONAL([BUILDCOMPLZMA], [test x$enable_compress_lzma = xyes])
AC_ARG_ENABLE([compress-bzip2],
[ --disable-compress-bzip2 : disable libknet bzip2 support ],,
[ enable_compress_bzip2="$enable_compress_all" ])
AM_CONDITIONAL([BUILDCOMPBZIP2], [test x$enable_compress_bzip2 = xyes])
AC_ARG_ENABLE([poc],
[ --enable-poc : enable building poc code ],,
[ enable_poc="no" ])
AM_CONDITIONAL([BUILD_POC], [test x$enable_poc = xyes])
AC_ARG_ENABLE([kronosnetd],
[ --enable-kronosnetd : Kronosnetd support ],,
[ enable_kronosnetd="no" ])
AM_CONDITIONAL([BUILD_KRONOSNETD], [test x$enable_kronosnetd = xyes])
AC_ARG_ENABLE([runautogen],
[ --enable-runautogen : run autogen.sh ],,
[ enable_runautogen="no" ])
AM_CONDITIONAL([BUILD_RUNAUTOGEN], [test x$enable_runautogen = xyes])
AC_ARG_ENABLE([libtap],
[ --enable-libtap : libtap support ],,
[ enable_libtap="no" ])
if test "x$enable_kronosnetd" = xyes; then
enable_libtap=yes
fi
AM_CONDITIONAL([BUILD_LIBTAP], [test x$enable_libtap = xyes])
## local helper functions
# this function checks if CC support options passed as
# args. Global CFLAGS are ignored during this test.
cc_supports_flag() {
saveCPPFLAGS="$CPPFLAGS"
CPPFLAGS="$@"
if echo $CC | grep -q clang; then
CPPFLAGS="-Werror $CPPFLAGS"
fi
AC_MSG_CHECKING([whether $CC supports "$@"])
AC_PREPROC_IFELSE([AC_LANG_PROGRAM([])],
[RC=0; AC_MSG_RESULT([yes])],
[RC=1; AC_MSG_RESULT([no])])
CPPFLAGS="$saveCPPFLAGS"
return $RC
}
# Checks for C features
AC_C_INLINE
# Checks for libraries.
AX_PTHREAD(,[AC_MSG_ERROR([POSIX threads support is required])])
AC_CHECK_LIB([m], [ceil], [AC_SUBST([m_LIBS], [-lm])], [AC_MSG_ERROR([kronosnet requires m library])])
saved_LIBS="$LIBS"
LIBS=
AC_SEARCH_LIBS([clock_gettime], [rt], , [AC_MSG_ERROR([clock_gettime not found])])
AC_SUBST([rt_LIBS], [$LIBS])
LIBS=
AC_SEARCH_LIBS([dlopen], [dl dld], , [AC_MSG_ERROR([dlopen not found])])
AC_SUBST([dl_LIBS], [$LIBS])
LIBS="$saved_LIBS"
# OS detection
AC_MSG_CHECKING([for os in ${host_os}])
case "$host_os" in
*linux*)
AC_DEFINE_UNQUOTED([KNET_LINUX], [1], [Compiling for Linux platform])
AC_MSG_RESULT([Linux])
;;
*bsd*)
AC_DEFINE_UNQUOTED([KNET_BSD], [1], [Compiling for BSD platform])
AC_MSG_RESULT([BSD])
if test "x$enable_libtap" = xyes; then
AC_MSG_ERROR([libtap is not currently supported on BSD platforms])
fi
;;
*)
AC_MSG_ERROR([Unsupported OS? hmmmm])
;;
esac
-# crypto libraries checks
-if test "x$enable_crypto_nss" = xyes; then
- PKG_CHECK_MODULES([nss],[nss])
- AC_DEFINE_UNQUOTED([BUILDCRYPTONSS], [1], [Enable nss crypto])
+AC_DEFUN([KNET_COMP_DEFINES],[
+if test "x$enable_$2_$1" = xyes; then
+ $3
+ AC_DEFINE([BUILD_]m4_toupper([$2_$1]), [1], $1 $2 [enabled])
fi
+AC_DEFINE_UNQUOTED([WITH_]m4_toupper([$2_$1]), [`test "x$enable_$2_$1" != xyes; echo $?`], $1 $2 [built in])
+])
-if test "x$enable_crypto_openssl" = xyes; then
+# crypto libraries checks
+KNET_COMP_DEFINES([nss],[crypto],[PKG_CHECK_MODULES([nss], [nss])])
+KNET_COMP_DEFINES([openssl],[crypto],[
PKG_CHECK_MODULES([openssl],[libcrypto < 1.1],
[AC_DEFINE_UNQUOTED([BUILDCRYPTOOPENSSL10], [1], [openssl 1.0 crypto])],
[PKG_CHECK_MODULES([openssl],[libcrypto >= 1.1],
[AC_DEFINE_UNQUOTED([BUILDCRYPTOOPENSSL11], [1], [openssl 1.1 crypto])])])
- AC_DEFINE_UNQUOTED([BUILDCRYPTOOPENSSL], [1], [Enable openssl crypto])
-fi
+])
# compress libraries checks
-if test "x$enable_compress_zlib" = xyes; then
- PKG_CHECK_MODULES([zlib], [zlib])
- AC_DEFINE_UNQUOTED([BUILDCOMPZLIB], [1], [Enable zlib compression])
-fi
-if test "x$enable_compress_lz4" = xyes; then
- PKG_CHECK_MODULES([liblz4], [liblz4])
- AC_DEFINE_UNQUOTED([BUILDCOMPLZ4], [1], [Enable lz4 compress])
-fi
-if test "x$enable_compress_lzo2" = xyes; then
+KNET_COMP_DEFINES([zlib],[compress],[PKG_CHECK_MODULES([zlib], [zlib])])
+KNET_COMP_DEFINES([lz4],[compress],[PKG_CHECK_MODULES([liblz4], [liblz4])])
+KNET_COMP_DEFINES([lzo2],[compress],[
PKG_CHECK_MODULES([lzo2], [lzo2],,
[AC_CHECK_HEADERS([lzo/lzo1x.h],
[AC_CHECK_LIB([lzo2], [lzo1x_decompress_safe],
[AC_SUBST([lzo2_LIBS], [-llzo2])])],
[AC_MSG_ERROR(["missing required lzo/lzo1x.h header"])])])
- AC_DEFINE_UNQUOTED([BUILDCOMPLZO2], [1], [Enable lzo2 compress])
-fi
-if test "x$enable_compress_lzma" = xyes; then
- PKG_CHECK_MODULES([liblzma], [liblzma])
- AC_DEFINE_UNQUOTED([BUILDCOMPLZMA], [1], [Enable lzma compress])
-fi
-if test "x$enable_compress_bzip2" = xyes; then
+])
+KNET_COMP_DEFINES([lzma],[compress],[PKG_CHECK_MODULES([liblzma], [liblzma])])
+KNET_COMP_DEFINES([bzip2],[compress],[
PKG_CHECK_MODULES([bzip2], [bzip2],,
[AC_CHECK_HEADERS([bzlib.h],
[AC_CHECK_LIB([bz2], [BZ2_bzBuffToBuffCompress],
[AC_SUBST([bzip2_LIBS], [-lbz2])])],
[AC_MSG_ERROR(["missing required bzlib.h"])])])
- AC_DEFINE_UNQUOTED([BUILDCOMPBZIP2], [1], [Enable bzip2 compress])
-fi
+])
# Checks for header files.
AC_CHECK_HEADERS([fcntl.h])
AC_CHECK_HEADERS([stdlib.h])
AC_CHECK_HEADERS([string.h])
AC_CHECK_HEADERS([strings.h])
AC_CHECK_HEADERS([sys/ioctl.h])
AC_CHECK_HEADERS([syslog.h])
AC_CHECK_HEADERS([unistd.h])
AC_CHECK_HEADERS([netinet/in.h])
AC_CHECK_HEADERS([sys/socket.h])
AC_CHECK_HEADERS([arpa/inet.h])
AC_CHECK_HEADERS([netdb.h])
AC_CHECK_HEADERS([limits.h])
AC_CHECK_HEADERS([stdint.h])
AC_CHECK_HEADERS([sys/epoll.h])
if test "x$enable_libknet_sctp" = xyes; then
AC_CHECK_HEADERS([netinet/sctp.h],, [AC_MSG_ERROR(["missing required SCTP headers"])])
fi
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
AC_TYPE_SIZE_T
AC_TYPE_PID_T
AC_TYPE_SSIZE_T
AC_TYPE_UINT8_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
AC_TYPE_INT32_T
# Checks for library functions.
AC_FUNC_ALLOCA
AC_FUNC_FORK
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_CHECK_FUNCS([kevent])
# if neither sys/epoll.h nor kevent are present, we should fail.
if test "x$ac_cv_header_sys_epoll_h" = xno && test "x$ac_cv_func_kevent" = xno; then
AC_MSG_ERROR([Both epoll and kevent unavailable on this OS])
fi
if test "x$ac_cv_header_sys_epoll_h" = xyes && test "x$ac_cv_func_kevent" = xyes; then
AC_MSG_ERROR([Both epoll and kevent available on this OS, please contact the maintainers to fix the code])
fi
# checks (for kronosnetd)
if test "x$enable_kronosnetd" = xyes; then
AC_CHECK_HEADERS([security/pam_appl.h],
[AC_CHECK_LIB([pam], [pam_start],
[AC_SUBST([pam_LIBS], [-lpam])],
[AC_MSG_ERROR([Unable to find LinuxPAM devel files])])])
AC_CHECK_HEADERS([security/pam_misc.h],
[AC_CHECK_LIB([pam_misc], [misc_conv],
[AC_SUBST([pam_misc_LIBS], [-lpam_misc])],
[AC_MSG_ERROR([Unable to find LinuxPAM MISC devel files])])])
PKG_CHECK_MODULES([libqb], [libqb])
AC_CHECK_LIB([qb], [qb_log_thread_priority_set],
[have_qb_log_thread_priority_set="yes"],
[have_qb_log_thread_priority_set="no"])
if test "x${have_qb_log_thread_priority_set}" = xyes; then
AC_DEFINE_UNQUOTED([HAVE_QB_LOG_THREAD_PRIORITY_SET], [1], [have qb_log_thread_priority_set])
fi
fi
# local options
AC_ARG_ENABLE([debug],
[ --enable-debug enable debug build. ],
[ default="no" ])
AC_ARG_WITH([initdefaultdir],
[ --with-initdefaultdir : path to /etc/sysconfig/.. or /etc/default dir. ],
[ INITDEFAULTDIR="$withval" ],
[ INITDEFAULTDIR="$sysconfdir/default" ])
AC_ARG_WITH([initddir],
[ --with-initddir=DIR : path to init script directory. ],
[ INITDDIR="$withval" ],
[ INITDDIR="$sysconfdir/init.d" ])
AC_ARG_WITH([systemddir],
[ --with-systemddir=DIR : path to systemd unit files directory. ],
[ SYSTEMDDIR="$withval" ],
[ SYSTEMDDIR="$systemddir" ])
AC_ARG_WITH([syslogfacility],
[ --with-syslogfacility=FACILITY
default syslog facility. ],
[ SYSLOGFACILITY="$withval" ],
[ SYSLOGFACILITY="LOG_DAEMON" ])
AC_ARG_WITH([sysloglevel],
[ --with-sysloglevel=LEVEL
default syslog level. ],
[ SYSLOGLEVEL="$withval" ],
[ SYSLOGLEVEL="LOG_INFO" ])
AC_ARG_WITH([defaultadmgroup],
[ --with-defaultadmgroup=GROUP
define PAM group. Users part of this group will be
allowed to configure kronosnet. Others will only
receive read-only rights. ],
[ DEFAULTADMGROUP="$withval" ],
[ DEFAULTADMGROUP="kronosnetadm" ])
## random vars
LOGDIR=${localstatedir}/log/
RUNDIR=${localstatedir}/run/
DEFAULT_CONFIG_DIR=${sysconfdir}/kronosnet
## do subst
AM_CONDITIONAL([DEBUG], [test "x${enable_debug}" = xyes])
AC_SUBST([DEFAULT_CONFIG_DIR])
AC_SUBST([INITDEFAULTDIR])
AC_SUBST([INITDDIR])
AC_SUBST([SYSTEMDDIR])
AC_SUBST([LOGDIR])
AC_SUBST([DEFAULTADMGROUP])
AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_DIR],
["$(eval echo ${DEFAULT_CONFIG_DIR})"],
[Default config directory])
AC_DEFINE_UNQUOTED([DEFAULT_CONFIG_FILE],
["$(eval echo ${DEFAULT_CONFIG_DIR}/kronosnetd.conf)"],
[Default config file])
AC_DEFINE_UNQUOTED([LOGDIR],
["$(eval echo ${LOGDIR})"],
[Default logging directory])
AC_DEFINE_UNQUOTED([DEFAULT_LOG_FILE],
["$(eval echo ${LOGDIR}/kronosnetd.log)"],
[Default log file])
AC_DEFINE_UNQUOTED([RUNDIR],
["$(eval echo ${RUNDIR})"],
[Default run directory])
AC_DEFINE_UNQUOTED([SYSLOGFACILITY],
[$(eval echo ${SYSLOGFACILITY})],
[Default syslog facility])
AC_DEFINE_UNQUOTED([SYSLOGLEVEL],
[$(eval echo ${SYSLOGLEVEL})],
[Default syslog level])
AC_DEFINE_UNQUOTED([DEFAULTADMGROUP],
["$(eval echo ${DEFAULTADMGROUP})"],
[Default admin group])
## *FLAGS handling
ENV_CFLAGS="$CFLAGS"
ENV_CPPFLAGS="$CPPFLAGS"
ENV_LDFLAGS="$LDFLAGS"
# debug build stuff
if test "x${enable_debug}" = xyes; then
AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code])
OPT_CFLAGS="-O0"
else
OPT_CFLAGS="-O3"
fi
# gdb flags
if test "x${GCC}" = xyes; then
GDB_FLAGS="-ggdb3"
else
GDB_FLAGS="-g"
fi
# extra warnings
EXTRA_WARNINGS=""
WARNLIST="
all
extra
unused
shadow
missing-prototypes
missing-declarations
suggest-attribute=noreturn
suggest-attribute=format
strict-prototypes
declaration-after-statement
pointer-arith
write-strings
cast-align
bad-function-cast
missing-format-attribute
float-equal
format=2
format-signedness
format-security
format-nonliteral
no-long-long
unsigned-char
gnu89-inline
no-strict-aliasing
error
address
cpp
overflow
parentheses
sequence-point
switch
shift-overflow=2
overlength-strings
retundent-decls
init-self
uninitialized
unused-but-set-variable
unused-function
unused-result
unused-value
unused-variable
unknown-pragmas
no-unused-parameter
"
for j in $WARNLIST; do
if cc_supports_flag -W$j; then
EXTRA_WARNINGS="$EXTRA_WARNINGS -W$j";
fi
done
CFLAGS="$ENV_CFLAGS $lt_prog_compiler_pic $OPT_CFLAGS $GDB_FLAGS \
$EXTRA_WARNINGS $WERROR_CFLAGS"
CPPFLAGS="$ENV_CPPFLAGS"
LDFLAGS="$ENV_LDFLAGS $lt_prog_compiler_pic"
AC_CONFIG_FILES([
Makefile
init/Makefile
libtap/Makefile
libtap/libtap.pc
kronosnetd/Makefile
kronosnetd/kronosnetd.logrotate
libknet/Makefile
libknet/libknet.pc
libknet/tests/Makefile
libknet/man/Doxyfile
libknet/man/Makefile
poc-code/Makefile
poc-code/iov-hash/Makefile
poc-code/access-list/Makefile
])
AC_OUTPUT
diff --git a/libknet/common.c b/libknet/common.c
index 2da535d3..9195bfba 100644
--- a/libknet/common.c
+++ b/libknet/common.c
@@ -1,200 +1,155 @@
/*
* Copyright (C) 2010-2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "config.h"
#include <unistd.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <errno.h>
#include <string.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#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)
+static 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;
}
-/* Separate these into compress.c and crypto.c or keep them together? */
-int load_compress_lib(knet_handle_t knet_h, compress_model_t *model)
+void *load_module(knet_handle_t knet_h, const char *type, const char *name)
{
- void *module;
+ void *module, *ops;
log_msg_t **log_msg_sym;
- compress_model_t *module_cmds;
- char soname[MAXPATHLEN];
- const char model_sym[] = "compress_model";
+ char soname[MAXPATHLEN], opsname[MAXPATHLEN];
- if (model->loaded) {
- return 0;
- }
- snprintf (soname, sizeof soname, "compress_%s.so", model->model_name);
- module = open_lib(knet_h, soname, 0);
- if (!module) {
- return -1;
- }
- log_msg_sym = dlsym (module, "log_msg");
- if (!log_msg_sym) {
- log_err (knet_h, KNET_SUB_COMPRESS, "unable to map symbol log_msg in module %s: %s",
- soname, dlerror ());
- errno = EINVAL;
- return -1;
- }
- *log_msg_sym = log_msg;
- module_cmds = dlsym (module, model_sym);
- if (!module_cmds) {
- log_err (knet_h, KNET_SUB_COMPRESS, "unable to map symbol %s in module %s: %s",
- model_sym, soname, dlerror ());
- errno = EINVAL;
- return -1;
- }
- model->is_init = module_cmds->is_init;
- model->init = module_cmds->init;
- model->fini = module_cmds->fini;
- model->val_level = module_cmds->val_level;
- model->compress = module_cmds->compress;
- model->decompress = module_cmds->decompress;
- return 0;
-}
+ snprintf (soname, sizeof soname, "%s_%s.so", type, name);
-int load_crypto_lib(knet_handle_t knet_h, crypto_model_t *model)
-{
- void *module;
- log_msg_t **log_msg_sym;
- crypto_model_t *module_cmds;
- char soname[MAXPATHLEN];
- const char model_sym[] = "crypto_model";
-
- if (model->loaded) {
- return 0;
- }
- snprintf (soname, sizeof soname, "crypto_%s.so", model->model_name);
module = open_lib(knet_h, soname, 0);
if (!module) {
- return -1;
+ return NULL;
}
+
log_msg_sym = dlsym (module, "log_msg");
if (!log_msg_sym) {
- log_err (knet_h, KNET_SUB_COMPRESS, "unable to map symbol log_msg in module %s: %s",
+ log_err (knet_h, KNET_SUB_COMMON, "unable to map symbol 'log_msg' in module %s: %s",
soname, dlerror ());
errno = EINVAL;
- return -1;
+ return NULL;
}
*log_msg_sym = log_msg;
- module_cmds = dlsym (module, model_sym);
- if (!module_cmds) {
- log_err (knet_h, KNET_SUB_CRYPTO, "unable to map symbol %s in module %s: %s",
- model_sym, soname, dlerror ());
+
+ snprintf (opsname, sizeof opsname, "%s_model", type);
+
+ ops = dlsym (module, opsname);
+ if (!ops) {
+ log_err (knet_h, KNET_SUB_COMMON, "unable to map symbol 'model' in module %s: %s",
+ soname, dlerror ());
errno = EINVAL;
- return -1;
+ return NULL;
}
- model->init = module_cmds->init;
- model->fini = module_cmds->fini;
- model->crypt = module_cmds->crypt;
- model->cryptv = module_cmds->cryptv;
- model->decrypt = module_cmds->decrypt;
- return 0;
+
+ return ops;
}
diff --git a/libknet/common.h b/libknet/common.h
index d21a80d9..0d1db235 100644
--- a/libknet/common.h
+++ b/libknet/common.h
@@ -1,23 +1,19 @@
/*
* Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved.
*
* Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
* Federico Simoncelli <fsimon@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "internals.h"
-#include "compress_model.h"
-#include "crypto_model.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);
-int load_compress_lib(knet_handle_t knet_h, compress_model_t *model);
-int load_crypto_lib(knet_handle_t knet_h, crypto_model_t *model);
+void *load_module(knet_handle_t knet_h, const char *type, const char *name);
#endif
diff --git a/libknet/compress.c b/libknet/compress.c
index daf057f3..8da89962 100644
--- a/libknet/compress.c
+++ b/libknet/compress.c
@@ -1,453 +1,422 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <time.h>
#include "internals.h"
#include "compress.h"
#include "compress_model.h"
#include "logging.h"
#include "threads_common.h"
#include "common.h"
/*
* internal module switch data
*/
/*
* DO NOT CHANGE MODEL_ID HERE OR ONWIRE COMPATIBILITY
* WILL BREAK!
*
- * always add before the last NULL/NULL/NULL.
+ * Always add new items before the last NULL.
*/
-#define empty_module 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
-
compress_model_t compress_modules_cmds[] = {
- { "none", 0, empty_module
- { "zlib", 1,
-#ifdef BUILDCOMPZLIB
- 1, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
-#else
-empty_module
-#endif
- { "lz4", 2,
-#ifdef BUILDCOMPLZ4
- 1, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
-#else
-empty_module
-#endif
- { "lz4hc", 3,
-#ifdef BUILDCOMPLZ4
- 1, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
-#else
-empty_module
-#endif
- { "lzo2", 4,
-#ifdef BUILDCOMPLZO2
- 1, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
-#else
-empty_module
-#endif
- { "lzma", 5,
-#ifdef BUILDCOMPLZMA
- 1, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
-#else
-empty_module
-#endif
- { "bzip2", 6,
-#ifdef BUILDCOMPBZIP2
- 1, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
-#else
-empty_module
-#endif
- { NULL, 255, empty_module
+ { "none" , 0, 0, 0, NULL },
+ { "zlib" , 1, WITH_COMPRESS_ZLIB , 0, NULL },
+ { "lz4" , 2, WITH_COMPRESS_LZ4 , 0, NULL },
+ { "lz4hc", 3, WITH_COMPRESS_LZ4 , 0, NULL },
+ { "lzo2" , 4, WITH_COMPRESS_LZO2 , 0, NULL },
+ { "lzma" , 5, WITH_COMPRESS_LZMA , 0, NULL },
+ { "bzip2", 6, WITH_COMPRESS_BZIP2, 0, NULL },
+ { NULL, 255, 0, 0, NULL }
};
static int max_model = 0;
static struct timespec last_load_failure;
static int compress_get_model(const char *model)
{
int idx = 0;
while (compress_modules_cmds[idx].model_name != NULL) {
if (!strcmp(compress_modules_cmds[idx].model_name, model)) {
return compress_modules_cmds[idx].model_id;
}
idx++;
}
return -1;
}
static int compress_get_max_model(void)
{
int idx = 0;
while (compress_modules_cmds[idx].model_name != NULL) {
idx++;
}
return idx - 1;
}
static int compress_is_valid_model(int compress_model)
{
int idx = 0;
while (compress_modules_cmds[idx].model_name != NULL) {
if ((compress_model == compress_modules_cmds[idx].model_id) &&
(compress_modules_cmds[idx].built_in == 1)) {
return 0;
}
idx++;
}
return -1;
}
static int val_level(
knet_handle_t knet_h,
int compress_model,
int compress_level)
{
- return compress_modules_cmds[compress_model].val_level(knet_h, compress_level);
+ return compress_modules_cmds[compress_model].ops->val_level(knet_h, compress_level);
}
/*
* compress_check_lib_is_init needs to be invoked in a locked context!
*/
static int compress_check_lib_is_init(knet_handle_t knet_h, int cmp_model)
{
/*
* lack of a .is_init function means that the module does not require
* init per handle so we use a fake reference in the compress_int_data
* to identify that we already increased the libref for this handle
*/
if (compress_modules_cmds[cmp_model].loaded == 1) {
- if (compress_modules_cmds[cmp_model].is_init == NULL) {
+ if (compress_modules_cmds[cmp_model].ops->is_init == NULL) {
if (knet_h->compress_int_data[cmp_model] != NULL) {
return 1;
}
} else {
- if (compress_modules_cmds[cmp_model].is_init(knet_h, cmp_model) == 1) {
+ if (compress_modules_cmds[cmp_model].ops->is_init(knet_h, cmp_model) == 1) {
return 1;
}
}
}
return 0;
}
/*
* compress_load_lib should _always_ be invoked in write lock context
*/
static int compress_load_lib(knet_handle_t knet_h, int cmp_model, int rate_limit)
{
struct timespec clock_now;
unsigned long long timediff;
/*
* checking again for paranoia and because
* compress_check_lib_is_init is usually invoked in read context
* and we need to switch from read to write locking in between.
* another thread might have init the library in the meantime
*/
if (compress_check_lib_is_init(knet_h, cmp_model)) {
return 0;
}
/*
* due to the fact that decompress can load libraries
* on demand, depending on the compress model selected
* on other nodes, it is possible for an attacker
* to send crafted packets to attempt to load libraries
* at random in a DoS fashion.
* If there is an error loading a library, then we want
* to rate_limit a retry to reload the library every X
* seconds to avoid a lock DoS that could greatly slow
* down libknet.
*/
if (rate_limit) {
if ((last_load_failure.tv_sec != 0) ||
(last_load_failure.tv_nsec != 0)) {
clock_gettime(CLOCK_MONOTONIC, &clock_now);
timespec_diff(last_load_failure, clock_now, &timediff);
if (timediff < 10000000000) {
errno = EAGAIN;
return -1;
}
}
}
if (compress_modules_cmds[cmp_model].loaded == 0) {
- if (load_compress_lib(knet_h, compress_modules_cmds+cmp_model) < 0) {
+ compress_modules_cmds[cmp_model].ops = load_module (knet_h, "compress", compress_modules_cmds[cmp_model].model_name);
+ if (!compress_modules_cmds[cmp_model].ops) {
clock_gettime(CLOCK_MONOTONIC, &last_load_failure);
return -1;
}
compress_modules_cmds[cmp_model].loaded = 1;
}
- if (compress_modules_cmds[cmp_model].init != NULL) {
- if (compress_modules_cmds[cmp_model].init(knet_h, cmp_model) < 0) {
+ if (compress_modules_cmds[cmp_model].ops->init != NULL) {
+ if (compress_modules_cmds[cmp_model].ops->init(knet_h, cmp_model) < 0) {
return -1;
}
} else {
knet_h->compress_int_data[cmp_model] = (void *)&"1";
}
return 0;
}
int compress_init(
knet_handle_t knet_h)
{
max_model = compress_get_max_model();
if (max_model > KNET_MAX_COMPRESS_METHODS) {
log_err(knet_h, KNET_SUB_COMPRESS, "Too many compress methods defined in compress.c.");
errno = EINVAL;
return -1;
}
memset(&last_load_failure, 0, sizeof(struct timespec));
return 0;
}
int compress_cfg(
knet_handle_t knet_h,
struct knet_handle_compress_cfg *knet_handle_compress_cfg)
{
int savederrno = 0, err = 0;
int cmp_model;
cmp_model = compress_get_model(knet_handle_compress_cfg->compress_model);
if (cmp_model < 0) {
log_err(knet_h, KNET_SUB_COMPRESS, "compress model %s not supported", knet_handle_compress_cfg->compress_model);
errno = EINVAL;
return -1;
}
log_debug(knet_h, KNET_SUB_COMPRESS,
"Initizializing compress module [%s/%d/%u]",
knet_handle_compress_cfg->compress_model, knet_handle_compress_cfg->compress_level, knet_handle_compress_cfg->compress_threshold);
if (cmp_model > 0) {
if (compress_modules_cmds[cmp_model].built_in == 0) {
log_err(knet_h, KNET_SUB_COMPRESS, "compress model %s support has not been built in. Please contact your vendor or fix the build", knet_handle_compress_cfg->compress_model);
errno = EINVAL;
return -1;
}
if (knet_handle_compress_cfg->compress_threshold > KNET_MAX_PACKET_SIZE) {
log_err(knet_h, KNET_SUB_COMPRESS, "compress threshold cannot be higher than KNET_MAX_PACKET_SIZE (%d).",
KNET_MAX_PACKET_SIZE);
errno = EINVAL;
return -1;
}
if (knet_handle_compress_cfg->compress_threshold == 0) {
knet_h->compress_threshold = KNET_COMPRESS_THRESHOLD;
log_debug(knet_h, KNET_SUB_COMPRESS, "resetting compression threshold to default (%d)", KNET_COMPRESS_THRESHOLD);
} else {
knet_h->compress_threshold = knet_handle_compress_cfg->compress_threshold;
}
savederrno = pthread_rwlock_rdlock(&shlib_rwlock);
if (savederrno) {
log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get read lock: %s",
strerror(savederrno));
errno = savederrno;
return -1;
}
if (!compress_check_lib_is_init(knet_h, cmp_model)) {
/*
* need to switch to write lock, load the lib, and return with a write lock
* this is not racy because compress_load_lib is written idempotent.
*/
pthread_rwlock_unlock(&shlib_rwlock);
savederrno = pthread_rwlock_wrlock(&shlib_rwlock);
if (savederrno) {
log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s",
strerror(savederrno));
errno = savederrno;
return -1;
}
if (compress_load_lib(knet_h, cmp_model, 0) < 0) {
savederrno = errno;
log_err(knet_h, KNET_SUB_COMPRESS, "Unable to load library: %s",
strerror(savederrno));
err = -1;
goto out_unlock;
}
}
if (val_level(knet_h, cmp_model, knet_handle_compress_cfg->compress_level) < 0) {
log_err(knet_h, KNET_SUB_COMPRESS, "compress level %d not supported for model %s",
knet_handle_compress_cfg->compress_level, knet_handle_compress_cfg->compress_model);
savederrno = EINVAL;
err = -1;
goto out_unlock;
}
out_unlock:
pthread_rwlock_unlock(&shlib_rwlock);
}
if (!err) {
knet_h->compress_model = cmp_model;
knet_h->compress_level = knet_handle_compress_cfg->compress_level;
} else {
knet_h->compress_model = 0;
}
errno = savederrno;
return err;
}
void compress_fini(
knet_handle_t knet_h,
int all)
{
int savederrno = 0;
int idx = 0;
savederrno = pthread_rwlock_wrlock(&shlib_rwlock);
if (savederrno) {
log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s",
strerror(savederrno));
return;
}
while (compress_modules_cmds[idx].model_name != NULL) {
if ((compress_modules_cmds[idx].built_in == 1) &&
(compress_modules_cmds[idx].loaded == 1) &&
(compress_modules_cmds[idx].model_id > 0) &&
(knet_h->compress_int_data[idx] != NULL) &&
(idx < KNET_MAX_COMPRESS_METHODS)) {
if ((all) || (compress_modules_cmds[idx].model_id == knet_h->compress_model)) {
- if (compress_modules_cmds[idx].fini != NULL) {
- compress_modules_cmds[idx].fini(knet_h, idx);
+ if (compress_modules_cmds[idx].ops->fini != NULL) {
+ compress_modules_cmds[idx].ops->fini(knet_h, idx);
} else {
knet_h->compress_int_data[idx] = NULL;
}
}
}
idx++;
}
pthread_rwlock_unlock(&shlib_rwlock);
return;
}
/*
* compress does not require compress_check_lib_is_init
* because it's protected by compress_cfg
*/
int compress(
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
- return compress_modules_cmds[knet_h->compress_model].compress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
+ return compress_modules_cmds[knet_h->compress_model].ops->compress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
}
int decompress(
knet_handle_t knet_h,
int compress_model,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
int savederrno = 0, err = 0;
if (compress_model > max_model) {
log_err(knet_h, KNET_SUB_COMPRESS, "Received packet with unknown compress model %d", compress_model);
errno = EINVAL;
return -1;
}
if (compress_is_valid_model(compress_model) < 0) {
log_err(knet_h, KNET_SUB_COMPRESS, "Received packet compressed with %s but support is not built in this version of libknet. Please contact your distribution vendor or fix the build.", compress_modules_cmds[compress_model].model_name);
errno = EINVAL;
return -1;
}
savederrno = pthread_rwlock_rdlock(&shlib_rwlock);
if (savederrno) {
log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get read lock: %s",
strerror(savederrno));
errno = savederrno;
return -1;
}
if (!compress_check_lib_is_init(knet_h, compress_model)) {
/*
* need to switch to write lock, load the lib, and return with a write lock
* this is not racy because compress_load_lib is written idempotent.
*/
pthread_rwlock_unlock(&shlib_rwlock);
savederrno = pthread_rwlock_wrlock(&shlib_rwlock);
if (savederrno) {
log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s",
strerror(savederrno));
errno = savederrno;
return -1;
}
if (compress_load_lib(knet_h, compress_model, 1) < 0) {
savederrno = errno;
err = -1;
log_err(knet_h, KNET_SUB_COMPRESS, "Unable to load library: %s",
strerror(savederrno));
goto out_unlock;
}
}
- err = compress_modules_cmds[compress_model].decompress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
+ err = compress_modules_cmds[compress_model].ops->decompress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
savederrno = errno;
out_unlock:
pthread_rwlock_unlock(&shlib_rwlock);
errno = savederrno;
return err;
}
int knet_get_compress_list(struct knet_compress_info *compress_list, size_t *compress_list_entries)
{
int err = 0;
int idx = 0;
int outidx = 0;
if (!compress_list_entries) {
errno = EINVAL;
return -1;
}
while (compress_modules_cmds[idx].model_name != NULL) {
if (compress_modules_cmds[idx].built_in) {
if (compress_list) {
compress_list[outidx].name = compress_modules_cmds[idx].model_name;
}
outidx++;
}
idx++;
}
*compress_list_entries = outidx;
return err;
}
diff --git a/libknet/compress_bzip2.c b/libknet/compress_bzip2.c
index 7f03f9e4..e0636fb6 100644
--- a/libknet/compress_bzip2.c
+++ b/libknet/compress_bzip2.c
@@ -1,118 +1,125 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <errno.h>
#include <bzlib.h>
#include "logging.h"
#include "compress_model.h"
static 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;
}
static 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 = 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;
}
static 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 = 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;
}
-compress_model_t compress_model = { "", 0, 0, NULL, 0, NULL, NULL, NULL, bzip2_val_level, bzip2_compress, bzip2_decompress };
+compress_ops_t compress_model = {
+ NULL,
+ NULL,
+ NULL,
+ bzip2_val_level,
+ bzip2_compress,
+ bzip2_decompress
+};
diff --git a/libknet/compress_lz4.c b/libknet/compress_lz4.c
index f9a7a7f6..73393369 100644
--- a/libknet/compress_lz4.c
+++ b/libknet/compress_lz4.c
@@ -1,94 +1,101 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <errno.h>
#include <lz4hc.h>
#include "logging.h"
#include "compress_model.h"
static 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");
}
return 0;
}
static 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 = 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;
}
static 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 = 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;
}
-compress_model_t compress_model = { "", 0, 0, NULL, 0, NULL, NULL, NULL, lz4_val_level, lz4_compress, lz4_decompress };
+compress_ops_t compress_model = {
+ NULL,
+ NULL,
+ NULL,
+ lz4_val_level,
+ lz4_compress,
+ lz4_decompress
+};
diff --git a/libknet/compress_lz4hc.c b/libknet/compress_lz4hc.c
index a418458e..ef487e20 100644
--- a/libknet/compress_lz4hc.c
+++ b/libknet/compress_lz4hc.c
@@ -1,109 +1,116 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <errno.h>
#include <lz4hc.h>
#include "logging.h"
#include "compress_model.h"
#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
static 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;
}
static 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 = 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;
}
/* This is a straight copy from compress_lz4.c */
static 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 = 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;
}
-compress_model_t compress_model = { "", 0, 0, NULL, 0, NULL, NULL, NULL, lz4hc_val_level, lz4hc_compress, lz4_decompress };
+compress_ops_t compress_model = {
+ NULL,
+ NULL,
+ NULL,
+ lz4hc_val_level,
+ lz4hc_compress,
+ lz4_decompress
+};
diff --git a/libknet/compress_lzma.c b/libknet/compress_lzma.c
index 81e135c0..d285d0c6 100644
--- a/libknet/compress_lzma.c
+++ b/libknet/compress_lzma.c
@@ -1,130 +1,137 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <errno.h>
#include <lzma.h>
#include "logging.h"
#include "compress_model.h"
static 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;
}
static 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 = 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;
}
static 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 = 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;
}
-compress_model_t compress_model = { "", 0, 0, NULL, 0, NULL, NULL, NULL, lzma_val_level, lzma_compress, lzma_decompress };
+compress_ops_t compress_model = {
+ NULL,
+ NULL,
+ NULL,
+ lzma_val_level,
+ lzma_compress,
+ lzma_decompress
+};
diff --git a/libknet/compress_lzo2.c b/libknet/compress_lzo2.c
index f2f7ecf4..7175fc27 100644
--- a/libknet/compress_lzo2.c
+++ b/libknet/compress_lzo2.c
@@ -1,157 +1,164 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <lzo/lzo1x.h>
#include "logging.h"
#include "compress_model.h"
static int lzo2_is_init(
knet_handle_t knet_h,
int method_idx)
{
if (knet_h->compress_int_data[method_idx]) {
return 1;
}
return 0;
}
static 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;
}
static 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;
}
static 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;
}
static 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 = 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 = 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 = 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 = 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 = lzo1x_999_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]);
break;
default:
lzerr = 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;
}
static 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 = 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;
}
-compress_model_t compress_model = { "", 0, 0, NULL, 0, lzo2_is_init, lzo2_init, lzo2_fini, lzo2_val_level, lzo2_compress, lzo2_decompress };
+compress_ops_t compress_model = {
+ lzo2_is_init,
+ lzo2_init,
+ lzo2_fini,
+ lzo2_val_level,
+ lzo2_compress,
+ lzo2_decompress
+};
diff --git a/libknet/compress_model.h b/libknet/compress_model.h
index cc8ba8d3..908ca5a3 100644
--- a/libknet/compress_model.h
+++ b/libknet/compress_model.h
@@ -1,92 +1,87 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#ifndef __KNET_COMPRESS_MODEL_H__
#define __KNET_COMPRESS_MODEL_H__
#include "internals.h"
typedef struct {
- const char *model_name;
- uint8_t model_id; /* sequencial unique identifier */
- uint8_t built_in; /* set at configure/build time to 1 if available */
-
- /*
- * shared lib load functions
- *
- * both are called in shlib_rwlock write context and should
- * update the loaded status below.
- */
- int (*load_lib) (knet_handle_t knet_h);
-
- /*
- * library is loaded
- */
- uint8_t loaded;
-
- /*
- * runtime bits
- */
-
/*
* some libs need special init and handling of buffers etc.
* is_init is called in shlib_rwlock read only context to see if
* the module has been initialized within this knet_handle.
* Providing is_init is optional. A module that does not export
* an is_init and if the associated shared library is already loaded
* is treated as "does not require init".
*/
int (*is_init) (knet_handle_t knet_h, int method_idx);
/*
* init is called when the library requires special init handling,
* such as memory allocation and such.
* init is invoked in shlib_rwlock write only context when
* the module exports this function.
* It is optional to provide an init function if the module
* does not require any init.
*/
int (*init) (knet_handle_t knet_h, int method_idx);
/*
* fini is invoked only on knet_handle_free in a write only context.
* It is optional to provide this function if the module
* does not require any finalization
*/
void (*fini) (knet_handle_t knet_h, int method_idx);
/*
* runtime config validation and compress/decompress
*/
/*
* required functions
*
* val_level is called upon compress configuration changes
* to make sure that the requested compress_level is valid
* within the context of a given module.
*/
int (*val_level)(knet_handle_t knet_h,
int compress_level);
/*
* hopefully those 2 don't require any explanation....
*/
int (*compress) (knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len);
int (*decompress)(knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len);
+} compress_ops_t;
+
+typedef struct {
+ const char *model_name;
+ uint8_t model_id; /* sequential unique identifier */
+ uint8_t built_in; /* set at configure/build time to 1 if available */
+
+ /*
+ * library is loaded
+ */
+ uint8_t loaded;
+
+ /*
+ * runtime bits
+ */
+ compress_ops_t *ops;
} compress_model_t;
#endif
diff --git a/libknet/compress_zlib.c b/libknet/compress_zlib.c
index 91a8ccaf..21e508e9 100644
--- a/libknet/compress_zlib.c
+++ b/libknet/compress_zlib.c
@@ -1,128 +1,135 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <errno.h>
#include <zlib.h>
#include "logging.h"
#include "compress_model.h"
static 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;
}
static 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 = 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;
}
static 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 = 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;
}
-compress_model_t compress_model = { "", 0, 0, NULL, 0, NULL, NULL, NULL, zlib_val_level, zlib_compress, zlib_decompress };
+compress_ops_t compress_model = {
+ NULL,
+ NULL,
+ NULL,
+ zlib_val_level,
+ zlib_compress,
+ zlib_decompress
+};
diff --git a/libknet/crypto.c b/libknet/crypto.c
index 23a43fa3..a57bb33f 100644
--- a/libknet/crypto.c
+++ b/libknet/crypto.c
@@ -1,210 +1,199 @@
/*
* Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "config.h"
#include <sys/errno.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include "crypto.h"
#include "crypto_model.h"
#include "internals.h"
#include "logging.h"
#include "common.h"
/*
* internal module switch data
*/
-#define empty_module NULL, 0, NULL, NULL, NULL, NULL, NULL },
-
crypto_model_t crypto_modules_cmds[] = {
- { "nss",
-#ifdef BUILDCRYPTONSS
- 1, NULL, 0, NULL, NULL, NULL, NULL, NULL },
-#else
- 0,empty_module
-#endif
- { "openssl",
-#ifdef BUILDCRYPTOOPENSSL
- 1, NULL, 0, NULL, NULL, NULL, NULL, NULL },
-#else
- 0,empty_module
-#endif
- { NULL, 0, empty_module
+ { "nss", WITH_CRYPTO_NSS, 0, NULL },
+ { "openssl", WITH_CRYPTO_OPENSSL, 0, NULL },
+ { NULL, 0, 0, NULL }
};
static int crypto_get_model(const char *model)
{
int idx = 0;
while (crypto_modules_cmds[idx].model_name != NULL) {
if (!strcmp(crypto_modules_cmds[idx].model_name, model))
return idx;
idx++;
}
return -1;
}
/*
* exported API
*/
int crypto_encrypt_and_sign (
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
- return crypto_modules_cmds[knet_h->crypto_instance->model].crypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
+ return crypto_modules_cmds[knet_h->crypto_instance->model].ops->crypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
}
int crypto_encrypt_and_signv (
knet_handle_t knet_h,
const struct iovec *iov_in,
int iovcnt_in,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
- return crypto_modules_cmds[knet_h->crypto_instance->model].cryptv(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len);
+ return crypto_modules_cmds[knet_h->crypto_instance->model].ops->cryptv(knet_h, iov_in, iovcnt_in, buf_out, buf_out_len);
}
int crypto_authenticate_and_decrypt (
knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len)
{
- return crypto_modules_cmds[knet_h->crypto_instance->model].decrypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
+ return crypto_modules_cmds[knet_h->crypto_instance->model].ops->decrypt(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
}
int crypto_init(
knet_handle_t knet_h,
struct knet_handle_crypto_cfg *knet_handle_crypto_cfg)
{
int savederrno = 0;
int model = 0;
model = crypto_get_model(knet_handle_crypto_cfg->crypto_model);
if (model < 0) {
log_err(knet_h, KNET_SUB_CRYPTO, "model %s not supported", knet_handle_crypto_cfg->crypto_model);
return -1;
}
if (crypto_modules_cmds[model].built_in == 0) {
log_err(knet_h, KNET_SUB_CRYPTO, "this version of libknet was built without %s support. Please contact your vendor or fix the build.", knet_handle_crypto_cfg->crypto_model);
return -1;
}
savederrno = pthread_rwlock_wrlock(&shlib_rwlock);
if (savederrno) {
log_err(knet_h, KNET_SUB_CRYPTO, "Unable to get write lock: %s",
strerror(savederrno));
return -1;
}
if (!crypto_modules_cmds[model].loaded) {
- if (load_crypto_lib(knet_h, crypto_modules_cmds+model) < 0) {
+ crypto_modules_cmds[model].ops = load_module (knet_h, "crypto", crypto_modules_cmds[model].model_name);
+ if (!crypto_modules_cmds[model].ops) {
log_err(knet_h, KNET_SUB_CRYPTO, "Unable to load %s lib", crypto_modules_cmds[model].model_name);
goto out_err;
}
crypto_modules_cmds[model].loaded = 1;
}
log_debug(knet_h, KNET_SUB_CRYPTO,
"Initizializing crypto module [%s/%s/%s]",
knet_handle_crypto_cfg->crypto_model,
knet_handle_crypto_cfg->crypto_cipher_type,
knet_handle_crypto_cfg->crypto_hash_type);
knet_h->crypto_instance = malloc(sizeof(struct crypto_instance));
if (!knet_h->crypto_instance) {
log_err(knet_h, KNET_SUB_CRYPTO, "Unable to allocate memory for crypto instance");
pthread_rwlock_unlock(&shlib_rwlock);
goto out_err;
}
/*
- * if crypto_modules_cmds.init fails, it is expected that
+ * if crypto_modules_cmds.ops->init fails, it is expected that
* it will clean everything by itself.
- * crypto_modules_cmds.fini is not invoked on error.
+ * crypto_modules_cmds.ops->fini is not invoked on error.
*/
knet_h->crypto_instance->model = model;
- if (crypto_modules_cmds[knet_h->crypto_instance->model].init(knet_h, knet_handle_crypto_cfg))
+ if (crypto_modules_cmds[knet_h->crypto_instance->model].ops->init(knet_h, knet_handle_crypto_cfg))
goto out_err;
log_debug(knet_h, KNET_SUB_CRYPTO, "security network overhead: %zu", knet_h->sec_header_size);
pthread_rwlock_unlock(&shlib_rwlock);
return 0;
out_err:
if (knet_h->crypto_instance) {
free(knet_h->crypto_instance);
knet_h->crypto_instance = NULL;
}
pthread_rwlock_unlock(&shlib_rwlock);
return -1;
}
void crypto_fini(
knet_handle_t knet_h)
{
int savederrno = 0;
int model = 0;
savederrno = pthread_rwlock_wrlock(&shlib_rwlock);
if (savederrno) {
log_err(knet_h, KNET_SUB_CRYPTO, "Unable to get write lock: %s",
strerror(savederrno));
return;
}
if (knet_h->crypto_instance) {
model = knet_h->crypto_instance->model;
- if (crypto_modules_cmds[model].fini != NULL) {
- crypto_modules_cmds[model].fini(knet_h);
+ if (crypto_modules_cmds[model].ops->fini != NULL) {
+ crypto_modules_cmds[model].ops->fini(knet_h);
}
free(knet_h->crypto_instance);
knet_h->crypto_instance = NULL;
}
pthread_rwlock_unlock(&shlib_rwlock);
return;
}
int knet_get_crypto_list(struct knet_crypto_info *crypto_list, size_t *crypto_list_entries)
{
int err = 0;
int idx = 0;
int outidx = 0;
if (!crypto_list_entries) {
errno = EINVAL;
return -1;
}
while (crypto_modules_cmds[idx].model_name != NULL) {
if (crypto_modules_cmds[idx].built_in) {
if (crypto_list) {
crypto_list[outidx].name = crypto_modules_cmds[idx].model_name;
}
outidx++;
}
idx++;
}
*crypto_list_entries = outidx;
return err;
}
diff --git a/libknet/crypto_model.h b/libknet/crypto_model.h
index 3833ce1c..ff0be45b 100644
--- a/libknet/crypto_model.h
+++ b/libknet/crypto_model.h
@@ -1,49 +1,50 @@
/*
* Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#ifndef __KNET_CRYPTO_MODEL_H__
#define __KNET_CRYPTO_MODEL_H__
#include "internals.h"
struct crypto_instance {
int model;
void *model_instance;
};
+/*
+ * see compress_model.h for explanation of the various lib related functions
+ */
typedef struct {
- const char *model_name;
- uint8_t built_in;
-
- /*
- * see compress_model.h for explanation of the various lib related functions
- */
- int (*load_lib) (knet_handle_t knet_h);
- uint8_t loaded;
-
int (*init) (knet_handle_t knet_h,
struct knet_handle_crypto_cfg *knet_handle_crypto_cfg);
void (*fini) (knet_handle_t knet_h);
int (*crypt) (knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len);
int (*cryptv) (knet_handle_t knet_h,
const struct iovec *iov_in,
int iovcnt_in,
unsigned char *buf_out,
ssize_t *buf_out_len);
int (*decrypt) (knet_handle_t knet_h,
const unsigned char *buf_in,
const ssize_t buf_in_len,
unsigned char *buf_out,
ssize_t *buf_out_len);
+} crypto_ops_t;
+
+typedef struct {
+ const char *model_name;
+ uint8_t built_in;
+ uint8_t loaded;
+ crypto_ops_t *ops;
} crypto_model_t;
#endif
diff --git a/libknet/crypto_nss.c b/libknet/crypto_nss.c
index ec7a5094..b41b6011 100644
--- a/libknet/crypto_nss.c
+++ b/libknet/crypto_nss.c
@@ -1,803 +1,809 @@
/*
* Copyright (C) 2012-2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <nss.h>
#include <nspr.h>
#include <pk11pub.h>
#include <pkcs11.h>
#include <prerror.h>
#include <blapit.h>
#include <hasht.h>
#include <pthread.h>
#include <secerr.h>
#include <prinit.h>
#include "crypto_model.h"
#include "logging.h"
static int nss_db_is_init = 0;
static void nss_atexit_handler(void)
{
if (nss_db_is_init) {
NSS_Shutdown();
if (PR_Initialized()) {
PL_ArenaFinish();
PR_Cleanup();
}
}
return;
}
/*
* 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 = PK11_GetBestSlot(cipher, NULL);
if (slot == NULL) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to find security slot (%d): %s",
PR_GetError(), PR_ErrorToString(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 = PK11_GetBestWrapMechanism(slot);
wrap_key_len = PK11_GetBestKeyLength(slot, wrap_mechanism);
wrap_key = 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",
PR_GetError(), PR_ErrorToString(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 = 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",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto exit_res_key;
}
wrapped_key_len = (int)sizeof(wrapped_key_data);
if (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",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto exit_res_key;
}
if (PK11_Finalize(wrap_key_crypt_context) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to finalize encryption of authkey (%d): %s",
PR_GetError(), PR_ErrorToString(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 = 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",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
if (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) {
PK11_DestroyContext(wrap_key_crypt_context, PR_TRUE);
}
if (wrap_key != NULL) {
PK11_FreeSymKey(wrap_key);
}
if (slot != NULL) {
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 (PK11_GenerateRandom(salt, SALT_SIZE) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to generate a random number (err %d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
crypt_param.type = siBuffer;
crypt_param.data = salt;
crypt_param.len = SALT_SIZE;
nss_sec_param = 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",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
/*
* Create cipher context for encryption
*/
crypt_context = 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],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
for (i=0; i<iovcnt; i++) {
if (PK11_CipherOp(crypt_context, data,
&tmp_outlen,
KNET_DATABUFSIZE_CRYPT,
(unsigned char *)iov[i].iov_base,
iov[i].iov_len) != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp failed (encrypt) crypt_type=%d (err %d): %s",
(int)cipher_to_nss[instance->crypto_cipher_type],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
tmp1_outlen = tmp1_outlen + tmp_outlen;
}
if (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],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
*buf_out_len = tmp1_outlen + tmp2_outlen + SALT_SIZE;
err = 0;
out:
if (crypt_context) {
PK11_DestroyContext(crypt_context, PR_TRUE);
}
if (nss_sec_param) {
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 = 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",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (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",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (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",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
*buf_out_len = tmp1_outlen + tmp2_outlen;
err = 0;
out:
if (decrypt_context) {
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 = 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],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (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],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (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],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
if (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],
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
goto out;
}
err = 0;
out:
if (hash_context) {
PK11_DestroyContext(hash_context, PR_TRUE);
}
return err;
}
/*
* global/glue nss functions
*/
static int init_nss(knet_handle_t knet_h)
{
static int at_exit_registered = 0;
if (!at_exit_registered) {
if (atexit(nss_atexit_handler)) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to register NSS atexit handler");
errno = EAGAIN;
return -1;
}
at_exit_registered = 1;
}
if (!nss_db_is_init) {
if (NSS_NoDB_Init(".") != SECSuccess) {
log_err(knet_h, KNET_SUB_NSSCRYPTO, "NSS DB initialization failed (err %d): %s",
PR_GetError(), PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT));
errno = EAGAIN;
return -1;
}
nss_db_is_init = 1;
}
if (init_nss_crypto(knet_h) < 0) {
return -1;
}
if (init_nss_hash(knet_h) < 0) {
return -1;
}
return 0;
}
/*
* exported API
*/
static 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; i<iovcnt_in; i++) {
memmove(buf_out + *buf_out_len, iov_in[i].iov_base, iov_in[i].iov_len);
*buf_out_len = *buf_out_len + iov_in[i].iov_len;
}
}
if (hash_to_nss[instance->crypto_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;
}
static 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);
}
static 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;
}
static 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) {
PK11_FreeSymKey(nsscrypto_instance->nss_sym_key);
nsscrypto_instance->nss_sym_key = NULL;
}
if (nsscrypto_instance->nss_sym_key_sign) {
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;
}
static 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 = 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;
}
-crypto_model_t crypto_model = { "", 0, NULL, 0, nsscrypto_init, nsscrypto_fini, nsscrypto_encrypt_and_sign, nsscrypto_encrypt_and_signv, nsscrypto_authenticate_and_decrypt };
+crypto_ops_t crypto_model = {
+ nsscrypto_init,
+ nsscrypto_fini,
+ nsscrypto_encrypt_and_sign,
+ nsscrypto_encrypt_and_signv,
+ nsscrypto_authenticate_and_decrypt
+};
diff --git a/libknet/crypto_openssl.c b/libknet/crypto_openssl.c
index 647f5a57..1fadb715 100644
--- a/libknet/crypto_openssl.c
+++ b/libknet/crypto_openssl.c
@@ -1,517 +1,523 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#define KNET_MODULE
#include "config.h"
#include <string.h>
#include <errno.h>
#include <dlfcn.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include "logging.h"
#include "crypto_model.h"
/*
* 1.0.2 requires at least 120 bytes
* 1.1.0 requires at least 256 bytes
*/
#define SSLERR_BUF_SIZE 512
/*
* 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];
EVP_CIPHER_CTX_init(&ctx);
/*
* contribute to PRNG for each packet we send/receive
*/
RAND_seed((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len);
if (!RAND_bytes(salt, SALT_SIZE)) {
ERR_error_string_n(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
*/
EVP_EncryptInit_ex(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt);
for (i=0; i<iovcnt; i++) {
if (!EVP_EncryptUpdate(&ctx,
data + offset, &tmplen,
(unsigned char *)iov[i].iov_base, iov[i].iov_len)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to encrypt: %s", sslerr);
err = -1;
goto out;
}
offset = offset + tmplen;
}
if (!EVP_EncryptFinal_ex(&ctx, data + offset, &tmplen)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize encrypt: %s", sslerr);
err = -1;
goto out;
}
*buf_out_len = offset + tmplen + SALT_SIZE;
out:
EVP_CIPHER_CTX_cleanup(&ctx);
return err;
}
static int decrypt_openssl (
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;
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];
EVP_CIPHER_CTX_init(&ctx);
/*
* contribute to PRNG for each packet we send/receive
*/
RAND_seed(buf_in, buf_in_len);
/*
* add warning re keylength
*/
EVP_DecryptInit_ex(&ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt);
if (!EVP_DecryptUpdate(&ctx, buf_out, &tmplen1, data, datalen)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to decrypt: %s", sslerr);
err = -1;
goto out;
}
if (!EVP_DecryptFinal_ex(&ctx, buf_out + tmplen1, &tmplen2)) {
ERR_error_string_n(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:
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 = EVP_CIPHER_CTX_new();
/*
* contribute to PRNG for each packet we send/receive
*/
RAND_seed((unsigned char *)iov[iovcnt - 1].iov_base, iov[iovcnt - 1].iov_len);
if (!RAND_bytes(salt, SALT_SIZE)) {
ERR_error_string_n(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
*/
EVP_EncryptInit_ex(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt);
for (i=0; i<iovcnt; i++) {
if (!EVP_EncryptUpdate(ctx,
data + offset, &tmplen,
(unsigned char *)iov[i].iov_base, iov[i].iov_len)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to encrypt: %s", sslerr);
err = -1;
goto out;
}
offset = offset + tmplen;
}
if (!EVP_EncryptFinal_ex(ctx, data + offset, &tmplen)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to finalize encrypt: %s", sslerr);
err = -1;
goto out;
}
*buf_out_len = offset + tmplen + SALT_SIZE;
out:
EVP_CIPHER_CTX_free(ctx);
return err;
}
static int decrypt_openssl (
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;
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 = EVP_CIPHER_CTX_new();
/*
* contribute to PRNG for each packet we send/receive
*/
RAND_seed(buf_in, buf_in_len);
/*
* add warning re keylength
*/
EVP_DecryptInit_ex(ctx, instance->crypto_cipher_type, NULL, instance->private_key, salt);
if (!EVP_DecryptUpdate(ctx, buf_out, &tmplen1, data, datalen)) {
ERR_error_string_n(ERR_get_error(), sslerr, sizeof(sslerr));
log_err(knet_h, KNET_SUB_OPENSSLCRYPTO, "Unable to decrypt: %s", sslerr);
err = -1;
goto out;
}
if (!EVP_DecryptFinal_ex(ctx, buf_out + tmplen1, &tmplen2)) {
ERR_error_string_n(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:
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 = 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)) {
ERR_error_string_n(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
*/
static 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; i<iovcnt_in; i++) {
memmove(buf_out + *buf_out_len, iov_in[i].iov_base, iov_in[i].iov_len);
*buf_out_len = *buf_out_len + iov_in[i].iov_len;
}
}
if (instance->crypto_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;
}
static 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);
}
static 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;
}
static 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;
}
static int opensslcrypto_init(
knet_handle_t knet_h,
struct knet_handle_crypto_cfg *knet_handle_crypto_cfg)
{
static int openssl_is_init = 0;
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);
if (!openssl_is_init) {
#ifdef BUILDCRYPTOOPENSSL10
ERR_load_crypto_strings();
OPENSSL_add_all_algorithms_noconf();
#endif
#ifdef BUILDCRYPTOOPENSSL11
if (!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");
errno = EAGAIN;
return -1;
}
#endif
openssl_is_init = 1;
}
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 = 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 = 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 = 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 = 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;
}
-crypto_model_t crypto_model = { "", 0, NULL, 0, opensslcrypto_init, opensslcrypto_fini, opensslcrypto_encrypt_and_sign, opensslcrypto_encrypt_and_signv, opensslcrypto_authenticate_and_decrypt };
+crypto_ops_t crypto_model = {
+ opensslcrypto_init,
+ opensslcrypto_fini,
+ opensslcrypto_encrypt_and_sign,
+ opensslcrypto_encrypt_and_signv,
+ opensslcrypto_authenticate_and_decrypt
+};
diff --git a/libknet/tests/api_knet_handle_compress.c b/libknet/tests/api_knet_handle_compress.c
index 628f683c..10bb437d 100644
--- a/libknet/tests/api_knet_handle_compress.c
+++ b/libknet/tests/api_knet_handle_compress.c
@@ -1,173 +1,173 @@
/*
* Copyright (C) 2017 Red Hat, Inc. All rights reserved.
*
* Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "libknet.h"
#include "internals.h"
#include "test-common.h"
static void test(void)
{
knet_handle_t knet_h;
int logfds[2];
struct knet_handle_compress_cfg knet_handle_compress_cfg;
memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
printf("Test knet_handle_compress incorrect knet_h\n");
if ((!knet_handle_compress(NULL, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
printf("knet_handle_compress accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
exit(FAIL);
}
setup_logpipes(logfds);
knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
if (!knet_h) {
printf("knet_handle_new failed: %s\n", strerror(errno));
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_compress with invalid cfg\n");
if ((!knet_handle_compress(knet_h, NULL)) || (errno != EINVAL)) {
printf("knet_handle_compress accepted invalid cfg or returned incorrect error: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_compress with un-initialized cfg\n");
memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
printf("knet_handle_compress accepted invalid un-initialized cfg\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_compress with none compress model (disable compress)\n");
memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
strncpy(knet_handle_compress_cfg.compress_model, "none", sizeof(knet_handle_compress_cfg.compress_model) - 1);
if (knet_handle_compress(knet_h, &knet_handle_compress_cfg) != 0) {
printf("knet_handle_compress did not accept none compress mode cfg\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
-#ifdef BUILDCOMPZLIB
+#ifdef BUILD_COMPRESS_ZLIB
printf("Test knet_handle_compress with zlib compress and negative level\n");
memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
knet_handle_compress_cfg.compress_level = -1;
if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
printf("knet_handle_compress accepted invalid (-1) compress level for zlib\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_compress with zlib compress and excessive compress level\n");
memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
knet_handle_compress_cfg.compress_level = 10;
if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
printf("knet_handle_compress accepted invalid (10) compress level for zlib\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_compress with zlib compress and excessive compress threshold\n");
memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
knet_handle_compress_cfg.compress_level = 1;
knet_handle_compress_cfg.compress_threshold = KNET_MAX_PACKET_SIZE +1;
if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
printf("knet_handle_compress accepted invalid compress threshold\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_compress with zlib compress model normal compress level and threshold\n");
memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
knet_handle_compress_cfg.compress_level = 1;
knet_handle_compress_cfg.compress_threshold = 64;
if (knet_handle_compress(knet_h, &knet_handle_compress_cfg) != 0) {
printf("knet_handle_compress did not accept zlib compress mode with compress level 1 cfg\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
#endif
flush_logs(logfds[0], stdout);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
}
int main(int argc, char *argv[])
{
test();
-#ifdef BUILDCOMPZLIB
+#ifdef BUILD_COMPRESS_ZLIB
return PASS;
#else
printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress API calls\n");
return SKIP;
#endif
}
diff --git a/libknet/tests/api_knet_handle_crypto.c b/libknet/tests/api_knet_handle_crypto.c
index 81ceb874..0d18b08c 100644
--- a/libknet/tests/api_knet_handle_crypto.c
+++ b/libknet/tests/api_knet_handle_crypto.c
@@ -1,270 +1,270 @@
/*
* Copyright (C) 2016-2017 Red Hat, Inc. All rights reserved.
*
* Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "libknet.h"
#include "internals.h"
#include "test-common.h"
static void test(void)
{
knet_handle_t knet_h;
int logfds[2];
struct knet_handle_crypto_cfg knet_handle_crypto_cfg;
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
printf("Test knet_handle_crypto incorrect knet_h\n");
if ((!knet_handle_crypto(NULL, &knet_handle_crypto_cfg)) || (errno != EINVAL)) {
printf("knet_handle_crypto accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
exit(FAIL);
}
setup_logpipes(logfds);
knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
if (!knet_h) {
printf("knet_handle_new failed: %s\n", strerror(errno));
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_crypto with invalid cfg\n");
if ((!knet_handle_crypto(knet_h, NULL)) || (errno != EINVAL)) {
printf("knet_handle_crypto accepted invalid cfg or returned incorrect error: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_crypto with un-initialized cfg\n");
if ((!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) || (errno != EINVAL)) {
printf("knet_handle_crypto accepted invalid un-initialized cfg\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_crypto with none crypto model (disable crypto)\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg) != 0) {
printf("knet_handle_crypto did not accept none crypto mode cfg\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_crypto with none crypto cipher and hash (disable crypto)\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg) != 0) {
printf("knet_handle_crypto did not accept none crypto cipher and hash cfg\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_crypto with nss/aes128/sha1 and too short key\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
knet_handle_crypto_cfg.private_key_len = 10;
if ((!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) || (errno != EINVAL)) {
printf("knet_handle_crypto accepted too short private key\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_crypto with nss/aes128/sha1 and too long key\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
knet_handle_crypto_cfg.private_key_len = 10000;
if ((!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) || (errno != EINVAL)) {
printf("knet_handle_crypto accepted too long private key\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
-#ifdef BUILDCRYPTONSS
+#ifdef BUILD_CRYPTO_NSS
printf("Test knet_handle_crypto with nss/aes128/sha1 and normal key\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
knet_handle_crypto_cfg.private_key_len = 2000;
if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) {
printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_crypto (nss specific test) with nss/aes128/none and normal key\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "nss", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
knet_handle_crypto_cfg.private_key_len = 2000;
if (!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) {
printf("knet_handle_crypto (nss) accepted crypto without hashing\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Shutdown crypto\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
knet_handle_crypto_cfg.private_key_len = 2000;
if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg) < 0) {
printf("Unable to shutdown crypto: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
#endif
-#ifdef BUILDCRYPTOOPENSSL
+#ifdef BUILD_CRYPTO_OPENSSL
printf("Test knet_handle_crypto with openssl/aes128/sha1 and normal key\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "openssl", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
knet_handle_crypto_cfg.private_key_len = 2000;
if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) {
printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_handle_crypto (nss specific test) with openssl/aes128/none and normal key\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "openssl", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
knet_handle_crypto_cfg.private_key_len = 2000;
if (!knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) {
printf("knet_handle_crypto (nss) accepted crypto without hashing\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Shutdown crypto\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
knet_handle_crypto_cfg.private_key_len = 2000;
if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg) < 0) {
printf("Unable to shutdown crypto: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
#endif
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
}
int main(int argc, char *argv[])
{
test();
-#if defined(BUILDCRYPTONSS) || defined(BUILDCRYPTOOPENSSL)
+#if defined(BUILD_CRYPTO_NSS) || defined(BUILD_CRYPTO_OPENSSL)
return PASS;
#else
printf("WARNING: nss support not builtin the library. Unable to test/verify internal crypto API calls\n");
return SKIP;
#endif
}
diff --git a/libknet/tests/api_knet_send_compress.c b/libknet/tests/api_knet_send_compress.c
index 1386768f..bb8e1752 100644
--- a/libknet/tests/api_knet_send_compress.c
+++ b/libknet/tests/api_knet_send_compress.c
@@ -1,290 +1,290 @@
/*
* Copyright (C) 2016-2017 Red Hat, Inc. All rights reserved.
*
* Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include "libknet.h"
#include "compress.h"
#include "internals.h"
#include "netutils.h"
#include "test-common.h"
static int private_data;
static void sock_notify(void *pvt_data,
int datafd,
int8_t channel,
uint8_t tx_rx,
int error,
int errorno)
{
return;
}
static void test(const char *model)
{
knet_handle_t knet_h;
int logfds[2];
int datafd = 0;
int8_t channel = 0;
struct knet_handle_stats stats;
char send_buff[KNET_MAX_PACKET_SIZE];
char recv_buff[KNET_MAX_PACKET_SIZE];
ssize_t send_len = 0;
int recv_len = 0;
int savederrno;
struct sockaddr_storage lo;
struct knet_handle_compress_cfg knet_handle_compress_cfg;
if (make_local_sockaddr(&lo, 0) < 0) {
printf("Unable to convert loopback to sockaddr: %s\n", strerror(errno));
exit(FAIL);
}
memset(send_buff, 0, sizeof(send_buff));
setup_logpipes(logfds);
knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
if (!knet_h) {
printf("knet_handle_new failed: %s\n", strerror(errno));
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_send with %s and valid data\n", model);
memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
strncpy(knet_handle_compress_cfg.compress_model, model, sizeof(knet_handle_compress_cfg.compress_model) - 1);
knet_handle_compress_cfg.compress_level = 4;
knet_handle_compress_cfg.compress_threshold = 0;
if (knet_handle_compress(knet_h, &knet_handle_compress_cfg) < 0) {
printf("knet_handle_compress did not accept zlib compress mode with compress level 1 cfg\n");
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
datafd = 0;
channel = -1;
if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_host_add(knet_h, 1) < 0) {
printf("knet_host_add failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_UDP, &lo, &lo, 0) < 0) {
printf("Unable to configure link: %s\n", strerror(errno));
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_link_set_enable(knet_h, 1, 0, 1) < 0) {
printf("knet_link_set_enable failed: %s\n", strerror(errno));
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_handle_setfwd(knet_h, 1) < 0) {
printf("knet_handle_setfwd failed: %s\n", strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (wait_for_host(knet_h, 1, 10, logfds[0], stdout) < 0) {
printf("timeout waiting for host to be reachable");
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
send_len = knet_send(knet_h, send_buff, KNET_MAX_PACKET_SIZE, channel);
if (send_len <= 0) {
printf("knet_send failed: %s\n", strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (send_len != sizeof(send_buff)) {
printf("knet_send sent only %zd bytes: %s\n", send_len, strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
if (wait_for_packet(knet_h, 10, datafd)) {
printf("Error waiting for packet: %s\n", strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
recv_len = knet_recv(knet_h, recv_buff, KNET_MAX_PACKET_SIZE, channel);
savederrno = errno;
if (recv_len != send_len) {
printf("knet_recv received only %d bytes: %s (errno: %d)\n", recv_len, strerror(errno), errno);
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
if ((is_helgrind()) && (recv_len == -1) && (savederrno == EAGAIN)) {
printf("helgrind exception. this is normal due to possible timeouts\n");
exit(PASS);
}
exit(FAIL);
}
if (memcmp(recv_buff, send_buff, KNET_MAX_PACKET_SIZE)) {
printf("recv and send buffers are different!\n");
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
/* A sanity check on the stats */
if (knet_handle_get_stats(knet_h, &stats, sizeof(stats)) < 0) {
printf("knet_handle_get_stats failed: %s\n", strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (strcmp(model, "none") == 0) {
if (stats.tx_compressed_packets != 0 ||
stats.rx_compressed_packets != 0) {
printf("stats look wrong: s/b all 0 for model 'none' tx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp), rx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp)\n",
stats.tx_compressed_packets,
stats.tx_compressed_size_bytes,
stats.tx_compressed_original_bytes,
stats.rx_compressed_packets,
stats.rx_compressed_size_bytes,
stats.rx_compressed_original_bytes);
}
} else {
if (stats.tx_compressed_packets != 1 ||
stats.rx_compressed_packets != 1 ||
stats.tx_compressed_original_bytes < stats.tx_compressed_size_bytes ||
stats.tx_compressed_original_bytes < stats.tx_compressed_size_bytes) {
printf("stats look wrong: tx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp), rx_packets: %" PRIu64 " (%" PRIu64 "/%" PRIu64 " comp/uncomp)\n",
stats.tx_compressed_packets,
stats.tx_compressed_size_bytes,
stats.tx_compressed_original_bytes,
stats.rx_compressed_packets,
stats.rx_compressed_size_bytes,
stats.rx_compressed_original_bytes);
}
}
flush_logs(logfds[0], stdout);
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
}
int main(int argc, char *argv[])
{
test("none");
-#ifdef BUILDCOMPZLIB
+#ifdef BUILD_COMPRESS_ZLIB
test("zlib");
#endif
-#ifdef BUILDCOMPLZ4
+#ifdef BUILD_COMPRESS_LZ4
test("lz4");
test("lz4hc");
#endif
-#ifdef BUILDCOMPLZO2
+#ifdef BUILD_COMPRESS_LZO2
test("lzo2");
#endif
-#ifdef BUILDCOMPLZMA
+#ifdef BUILD_COMPRESS_LZMA
test("lzma");
#endif
-#ifdef BUILDCOMPBZIP2
+#ifdef BUILD_COMPRESS_BZIP2
test("bzip2");
#endif
return PASS;
}
diff --git a/libknet/tests/api_knet_send_crypto.c b/libknet/tests/api_knet_send_crypto.c
index 3061ce67..6b23e47a 100644
--- a/libknet/tests/api_knet_send_crypto.c
+++ b/libknet/tests/api_knet_send_crypto.c
@@ -1,265 +1,265 @@
/*
* Copyright (C) 2016-2017 Red Hat, Inc. All rights reserved.
*
* Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include "libknet.h"
#include "compress.h"
#include "internals.h"
#include "netutils.h"
#include "test-common.h"
static int private_data;
static void sock_notify(void *pvt_data,
int datafd,
int8_t channel,
uint8_t tx_rx,
int error,
int errorno)
{
return;
}
static void test(const char *model)
{
knet_handle_t knet_h;
int logfds[2];
int datafd = 0;
int8_t channel = 0;
struct knet_handle_stats stats;
char send_buff[KNET_MAX_PACKET_SIZE];
char recv_buff[KNET_MAX_PACKET_SIZE];
ssize_t send_len = 0;
int recv_len = 0;
int savederrno;
struct sockaddr_storage lo;
struct knet_handle_crypto_cfg knet_handle_crypto_cfg;
if (make_local_sockaddr(&lo, 0) < 0) {
printf("Unable to convert loopback to sockaddr: %s\n", strerror(errno));
exit(FAIL);
}
memset(send_buff, 0, sizeof(send_buff));
setup_logpipes(logfds);
knet_h = knet_handle_new(1, logfds[1], KNET_LOG_DEBUG);
if (!knet_h) {
printf("knet_handle_new failed: %s\n", strerror(errno));
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
printf("Test knet_send with %s and valid data\n", model);
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, model, sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha1", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
knet_handle_crypto_cfg.private_key_len = 2000;
if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) {
printf("knet_handle_crypto failed with correct config: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
datafd = 0;
channel = -1;
if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_host_add(knet_h, 1) < 0) {
printf("knet_host_add failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_link_set_config(knet_h, 1, 0, KNET_TRANSPORT_UDP, &lo, &lo, 0) < 0) {
printf("Unable to configure link: %s\n", strerror(errno));
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_link_set_enable(knet_h, 1, 0, 1) < 0) {
printf("knet_link_set_enable failed: %s\n", strerror(errno));
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_handle_setfwd(knet_h, 1) < 0) {
printf("knet_handle_setfwd failed: %s\n", strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (wait_for_host(knet_h, 1, 10, logfds[0], stdout) < 0) {
printf("timeout waiting for host to be reachable");
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
send_len = knet_send(knet_h, send_buff, KNET_MAX_PACKET_SIZE, channel);
if (send_len <= 0) {
printf("knet_send failed: %s\n", strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (send_len != sizeof(send_buff)) {
printf("knet_send sent only %zd bytes: %s\n", send_len, strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
if (wait_for_packet(knet_h, 10, datafd)) {
printf("Error waiting for packet: %s\n", strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
recv_len = knet_recv(knet_h, recv_buff, KNET_MAX_PACKET_SIZE, channel);
savederrno = errno;
if (recv_len != send_len) {
printf("knet_recv received only %d bytes: %s (errno: %d)\n", recv_len, strerror(errno), errno);
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
if ((is_helgrind()) && (recv_len == -1) && (savederrno == EAGAIN)) {
printf("helgrind exception. this is normal due to possible timeouts\n");
exit(PASS);
}
exit(FAIL);
}
if (memcmp(recv_buff, send_buff, KNET_MAX_PACKET_SIZE)) {
printf("recv and send buffers are different!\n");
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
/* A sanity check on the stats */
if (knet_handle_get_stats(knet_h, &stats, sizeof(stats)) < 0) {
printf("knet_handle_get_stats failed: %s\n", strerror(errno));
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (stats.tx_crypt_packets >= 1 ||
stats.rx_crypt_packets < 1) {
printf("stats look wrong: tx_packets: %" PRIu64 ", rx_packets: %" PRIu64 "\n",
stats.tx_crypt_packets,
stats.rx_crypt_packets);
}
flush_logs(logfds[0], stdout);
knet_link_set_enable(knet_h, 1, 0, 0);
knet_link_clear_config(knet_h, 1, 0);
knet_host_remove(knet_h, 1);
knet_handle_free(knet_h);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
}
int main(int argc, char *argv[])
{
-#ifdef BUILDCRYPTONSS
+#ifdef BUILD_CRYPTO_NSS
test("nss");
#endif
-#ifdef BUILDCRYPTOOPENSSL
+#ifdef BUILD_CRYPTO_OPENSSL
#ifdef KNET_BSD
if (is_memcheck() || is_helgrind()) {
printf("valgrind-freebsd cannot run this test properly. Skipping\n");
return PASS;
}
#endif
test("openssl");
#endif
return PASS;
}

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jun 25, 2:18 AM (14 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1951865
Default Alt Text
(135 KB)

Event Timeline