#4400: Add CyaSSL support

This commit is contained in:
Mike Gelfand 2015-01-07 02:04:08 +00:00
parent 295eade2a6
commit c7d2a7f959
11 changed files with 457 additions and 16 deletions

View File

@ -29,6 +29,7 @@ tr_auto_option(USE_SYSTEM_MINIUPNPC "Use system miniupnpc library" AUTO)
tr_auto_option(USE_SYSTEM_NATPMP "Use system natpmp library" AUTO)
tr_auto_option(USE_SYSTEM_UTP "Use system utp library" AUTO)
tr_auto_option(USE_SYSTEM_B64 "Use system b64 library" AUTO)
tr_list_option(WITH_CRYPTO "Use specified crypto library" AUTO openssl cyassl)
tr_auto_option(WITH_INOTIFY "Enable inotify support (on systems that support it)" AUTO)
tr_auto_option(WITH_KQUEUE "Enable kqueue support (on systems that support it)" AUTO)
tr_auto_option(WITH_SYSTEMD "Add support for systemd startup notification (on systems that support it)" AUTO)
@ -94,6 +95,7 @@ endif()
set(CURL_MINIMUM 7.15.4)
set(EVENT2_MINIMUM 2.0.10)
set(OPENSSL_MINIMUM 0.9.4)
set(CYASSL_MINIMUM 3.0)
set(ZLIB_MINIMUM 1.2.3)
set(GTK_MINIMUM 3.4.0)
set(GLIB_MINIMUM 2.32.0)
@ -136,6 +138,35 @@ if(UNIX)
find_package(ICONV REQUIRED)
endif()
if(WITH_CRYPTO STREQUAL "AUTO" OR WITH_CRYPTO STREQUAL "openssl")
tr_get_required_flag(WITH_CRYPTO OPENSSL_IS_REQUIRED)
find_package(OpenSSL ${OPENSSL_MINIMUM} ${OPENSSL_IS_REQUIRED})
tr_fixup_list_option(WITH_CRYPTO "openssl" OPENSSL_FOUND "AUTO" OPENSSL_IS_REQUIRED)
if(WITH_CRYPTO STREQUAL "openssl")
set(CRYPTO_PKG "openssl")
set(CRYPTO_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
set(CRYPTO_LIBRARIES ${OPENSSL_LIBRARIES})
endif()
endif()
if(WITH_CRYPTO STREQUAL "AUTO" OR WITH_CRYPTO STREQUAL "cyassl")
tr_get_required_flag(WITH_CRYPTO CYASSL_IS_REQUIRED)
find_package(CyaSSL ${CYASSL_MINIMUM} ${CYASSL_IS_REQUIRED})
tr_fixup_list_option(WITH_CRYPTO "cyassl" CYASSL_FOUND "AUTO" CYASSL_IS_REQUIRED)
if(WITH_CRYPTO STREQUAL "cyassl")
set(CRYPTO_PKG "cyassl")
set(CRYPTO_INCLUDE_DIRS ${CYASSL_INCLUDE_DIRS})
set(CRYPTO_LIBRARIES ${CYASSL_LIBRARIES})
endif()
endif()
# We should have found the library by now
if(CRYPTO_PKG STREQUAL "")
if(WITH_CRYPTO STREQUAL "AUTO")
message(FATAL_ERROR "Unable to find any supported crypto library.")
else()
message(FATAL_ERROR "Requested crypto library '${WITH_CRYPTO}' is not supported.")
endif()
endif()
if(ENABLE_GTK)
tr_get_required_flag(ENABLE_GTK GTK_IS_REQUIRED)

View File

@ -2,7 +2,6 @@ AM_CPPFLAGS = -I@top_srcdir@
AM_CFLAGS = \
@LIBEVENT_CFLAGS@ \
@OPENSSL_CFLAGS@ \
@LIBCURL_CFLAGS@ \
@ZLIB_CFLAGS@ \
@PTHREAD_CFLAGS@
@ -22,7 +21,7 @@ transmission_cli_LDADD = \
@LIBUTP_LIBS@ \
@LIBEVENT_LIBS@ \
@LIBCURL_LIBS@ \
@OPENSSL_LIBS@ \
@CRYPTO_LIBS@ \
@INTLLIBS@ \
@ZLIB_LIBS@ \
@PTHREAD_LIBS@ \

47
cmake/FindCyaSSL.cmake Normal file
View File

@ -0,0 +1,47 @@
if(CYASSL_PREFER_STATIC_LIB)
set(CYASSL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
if(WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib ${CMAKE_FIND_LIBRARY_SUFFIXES})
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
endif()
endif()
if(UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(_CYASSL QUIET cyassl)
endif()
find_path(CYASSL_INCLUDE_DIR NAMES cyassl/version.h HINTS ${_CYASSL_INCLUDEDIR})
find_library(CYASSL_LIBRARY NAMES cyassl HINTS ${_CYASSL_LIBDIR})
if(CYASSL_INCLUDE_DIR)
if(_CYASSL_VERSION)
set(CYASSL_VERSION ${_CYASSL_VERSION})
else()
file(STRINGS "${CYASSL_INCLUDE_DIR}/cyassl/version.h" CYASSL_VERSION_STR REGEX "^#define[\t ]+LIBCYASSL_VERSION_STRING[\t ]+\"[^\"]+\"")
if(CYASSL_VERSION_STR MATCHES "\"([^\"]+)\"")
set(CYASSL_VERSION_STR "${CMAKE_MATCH_1}")
endif()
endif()
endif()
set(CYASSL_INCLUDE_DIRS ${CYASSL_INCLUDE_DIR})
set(CYASSL_LIBRARIES ${CYASSL_LIBRARY})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CYASSL
REQUIRED_VARS
CYASSL_LIBRARY
CYASSL_INCLUDE_DIR
VERSION_VAR
CYASSL_VERSION
)
mark_as_advanced(CYASSL_INCLUDE_DIR CYASSL_LIBRARY)
if(CYASSL_PREFER_STATIC_LIB)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CYASSL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
unset(CYASSL_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES)
endif()

View File

@ -24,6 +24,37 @@ macro(tr_fixup_auto_option NAME ISFOUND ISREQ)
endif()
endmacro()
function(tr_list_option_changed NAME ACC VAL FIL STK)
get_property(VAR_STRINGS CACHE ${NAME} PROPERTY STRINGS)
string(TOUPPER "${VAL}" VAL_UPCASE)
foreach(X ${VAR_STRINGS})
string(TOUPPER "${X}" X_UPCASE)
if("${VAL_UPCASE}" STREQUAL "${X_UPCASE}")
if(NOT "${VAL}" STREQUAL "${X}")
set_property(CACHE ${NAME} PROPERTY VALUE "${X}")
message(STATUS ">>> (list) ${NAME} -> ${X}")
endif()
return()
endif()
endforeach()
string(REPLACE ";" "', '" VAR_STRINGS "${VAR_STRINGS}")
message(FATAL_ERROR "Option '${NAME}' set to unrecognized value '${VAL}'. Should be one of '${VAR_STRINGS}'.")
endfunction()
macro(tr_list_option NAME DESC VAL)
set(${NAME} "${VAL}" CACHE STRING "${DESC}")
set_property(CACHE ${NAME} PROPERTY STRINGS "${VAL};${ARGN}")
variable_watch(${NAME} tr_list_option_changed)
endmacro()
macro(tr_fixup_list_option NAME FVAL ISFOUND RVAL ISREQ)
if(${ISFOUND})
set_property(CACHE ${NAME} PROPERTY VALUE "${FVAL}")
elseif(NOT (${ISREQ}))
set_property(CACHE ${NAME} PROPERTY VALUE "${RVAL}")
endif()
endmacro()
macro(tr_get_required_flag IVAR OVAR)
set(${OVAR})
if (${IVAR} AND NOT ${IVAR} STREQUAL "AUTO")

View File

@ -37,15 +37,20 @@ AM_CONDITIONAL(TR_UNSTABLE, test "x$supported_build" = "xno")
## MANDATORY for everything
##
##
CURL_MINIMUM=7.15.4
AC_SUBST(CURL_MINIMUM)
LIBEVENT_MINIMUM=2.0.10
AC_SUBST(LIBEVENT_MINIMUM)
OPENSSL_MINIMUM=0.9.4
AC_SUBST(OPENSSL_MINIMUM)
ZLIB_MINIMUM=1.2.3
AC_SUBST(ZLIB_MINIMUM)
# crypto backends
OPENSSL_MINIMUM=0.9.4
AC_SUBST(OPENSSL_MINIMUM)
CYASSL_MINIMUM=3.0
AC_SUBST(CYASSL_MINIMUM)
##
##
## MANDATORY for the GTK+ client
@ -112,11 +117,44 @@ AC_SEARCH_LIBS(cos, [m])
AC_SEARCH_LIBS([socket], [socket net])
AC_SEARCH_LIBS([gethostbyname], [nsl bind])
AC_SEARCH_LIBS([quotacursor_skipidtype], [quota])
PKG_CHECK_MODULES(OPENSSL, [openssl >= $OPENSSL_MINIMUM], , [CHECK_SSL()])
PKG_CHECK_MODULES(LIBCURL, [libcurl >= $CURL_MINIMUM])
PKG_CHECK_MODULES(LIBEVENT, [libevent >= $LIBEVENT_MINIMUM])
PKG_CHECK_MODULES(ZLIB, [zlib >= $ZLIB_MINIMUM])
AC_ARG_WITH([crypto], AS_HELP_STRING([--with-crypto=PKG],
[Use specified crypto library: auto (default), openssl, cyassl]),
[want_crypto=$withval], [want_crypto=auto])
AS_IF([test "x$want_crypto" = "xauto" -o "x$want_crypto" = "xopenssl"], [
PKG_CHECK_MODULES(OPENSSL, [openssl >= $OPENSSL_MINIMUM],
[want_crypto="openssl"; CRYPTO_PKG="openssl"; CRYPTO_CFLAGS="$OPENSSL_CFLAGS"; CRYPTO_LIBS="$OPENSSL_LIBS"],
[AS_IF([test "x$want_crypto" = "xopenssl"],
[AC_MSG_ERROR([OpenSSL support requested, but library not found.])]
)]
)
])
AS_IF([test "x$want_crypto" = "xauto" -o "x$want_crypto" = "xcyassl"], [
PKG_CHECK_MODULES(CYASSL, [cyassl >= $CYASSL_MINIMUM],
[want_crypto="cyassl"; CRYPTO_PKG="cyassl"; CRYPTO_CFLAGS="$CYASSL_CFLAGS"; CRYPTO_LIBS="$CYASSL_LIBS"],
[AS_IF([test "x$want_crypto" = "xcyassl"],
[AC_MSG_ERROR([CyaSSL support requested, but library not found.])]
)]
)
])
# we should have found the library by now
AS_IF([test "x$CRYPTO_PKG" = "x"], [
AS_IF([test "x$want_crypto" = "xauto"],
[AC_MSG_ERROR([Unable to find any supported crypto library.])],
[AC_MSG_ERROR([Requested crypto library "$want_crypto" is not supported.])],
)
])
AC_SUBST(CRYPTO_PKG)
AC_SUBST(CRYPTO_CFLAGS)
AC_SUBST(CRYPTO_LIBS)
AC_SYS_LARGEFILE
AC_CHECK_FUNCS([lseek64])
@ -619,6 +657,7 @@ Configuration:
Build libtransmission: yes
* optimized for low-resource systems: ${enable_lightweight}
* µTP enabled: ${build_utp}
* crypto library: ${CRYPTO_PKG}
Build Command-Line client: ${build_cli}

View File

@ -2,7 +2,6 @@ AM_CPPFLAGS = -I@top_srcdir@ -DEMBEDDED
AM_CFLAGS = \
@LIBEVENT_CFLAGS@ \
@OPENSSL_CFLAGS@ \
@LIBCURL_CFLAGS@ \
@SYSTEMD_DAEMON_CFLAGS@ \
@ZLIB_CFLAGS@ \
@ -28,7 +27,7 @@ LDADD = \
@LIBUTP_LIBS@ \
@LIBEVENT_LIBS@ \
@LIBCURL_LIBS@ \
@OPENSSL_LIBS@ \
@CRYPTO_LIBS@ \
@INTLLIBS@ \
@SYSTEMD_DAEMON_LIBS@ \
@ZLIB_LIBS@ \

View File

@ -21,7 +21,6 @@ AM_CFLAGS = \
@LIBEVENT_CFLAGS@ \
@GTK_CFLAGS@ \
@LIBCURL_CFLAGS@ \
@OPENSSL_CFLAGS@ \
@ZLIB_CFLAGS@ \
@PTHREAD_CFLAGS@
@ -95,7 +94,7 @@ transmission_gtk_LDADD = \
@LIBAPPINDICATOR_LIBS@ \
@LIBEVENT_LIBS@ \
@LIBCURL_LIBS@ \
@OPENSSL_LIBS@ \
@CRYPTO_LIBS@ \
@ZLIB_LIBS@ \
@PTHREAD_LIBS@ \
${LIBM}

View File

@ -16,7 +16,7 @@ set(${PROJECT_NAME}_SOURCES
crypto.c
crypto-utils.c
crypto-utils-fallback.c
crypto-utils-openssl.c
crypto-utils-${CRYPTO_PKG}.c
error.c
fdlimit.c
file.c
@ -167,7 +167,7 @@ include_directories(
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
${ZLIB_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIRS}
${CRYPTO_INCLUDE_DIRS}
${CURL_INCLUDE_DIRS}
${ICONV_INCLUDE_DIRS}
${EVENT2_INCLUDE_DIRS}
@ -200,7 +200,7 @@ endforeach()
target_link_libraries(${TR_NAME}
${CMAKE_THREAD_LIBS_INIT}
${ZLIB_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${CURL_LIBRARIES}
${ICONV_LIBRARIES}
${EVENT2_LIBRARIES}

View File

@ -11,7 +11,7 @@ AM_CFLAGS = \
@LIBNATPMP_CFLAGS@ \
@LIBEVENT_CFLAGS@ \
@LIBCURL_CFLAGS@ \
@OPENSSL_CFLAGS@ \
@CRYPTO_CFLAGS@ \
@PTHREAD_CFLAGS@ \
@ZLIB_CFLAGS@
@ -178,7 +178,7 @@ apps_ldadd = \
@LIBUTP_LIBS@ \
@LIBCURL_LIBS@ \
@LIBEVENT_LIBS@ \
@OPENSSL_LIBS@ \
@CRYPTO_LIBS@ \
@PTHREAD_LIBS@ \
@ZLIB_LIBS@ \
${LIBM}

View File

@ -0,0 +1,297 @@
/*
* This file Copyright (C) Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
* $Id$
*/
#include <assert.h>
#include <cyassl/ctaocrypt/arc4.h>
#include <cyassl/ctaocrypt/dh.h>
#include <cyassl/ctaocrypt/error-crypt.h>
#include <cyassl/ctaocrypt/random.h>
#include <cyassl/ctaocrypt/sha.h>
#include <cyassl/version.h>
#include "transmission.h"
#include "crypto-utils.h"
#include "log.h"
#include "utils.h"
#define TR_CRYPTO_DH_SECRET_FALLBACK
#include "crypto-utils-fallback.c"
struct tr_dh_ctx
{
DhKey dh;
word32 key_length;
uint8_t * private_key;
word32 private_key_length;
};
/***
****
***/
#define MY_NAME "tr_crypto_utils"
static void
log_cyassl_error (int error_code,
const char * file,
int line)
{
if (tr_logLevelIsActive (TR_LOG_ERROR))
{
#if LIBCYASSL_VERSION_HEX >= 0x03000002
const char * error_message = CTaoCryptGetErrorString (error_code);
#else
char error_message[CYASSL_MAX_ERROR_SZ];
CTaoCryptErrorString (error_code, error_message);
#endif
tr_logAddMessage (file, line, TR_LOG_ERROR, MY_NAME, "CyaSSL error: %s", error_message);
}
}
static bool
check_cyassl_result (int result,
const char * file,
int line)
{
const bool ret = result == 0;
if (!ret)
log_cyassl_error (result, file, line);
return ret;
}
#define check_result(result) check_cyassl_result ((result), __FILE__, __LINE__)
/***
****
***/
static RNG *
get_rng (void)
{
static RNG rng;
static bool rng_initialized = false;
if (!rng_initialized)
{
if (!check_result (InitRng (&rng)))
return NULL;
rng_initialized = true;
}
return &rng;
}
/***
****
***/
tr_sha1_ctx_t
tr_sha1_init (void)
{
Sha * handle = tr_new (Sha, 1);
if (check_result (InitSha (handle)))
return handle;
tr_free (handle);
return NULL;
}
bool
tr_sha1_update (tr_sha1_ctx_t handle,
const void * data,
size_t data_length)
{
assert (handle != NULL);
if (data_length == 0)
return true;
assert (data != NULL);
return check_result (ShaUpdate (handle, data, data_length));
}
bool
tr_sha1_final (tr_sha1_ctx_t handle,
uint8_t * hash)
{
bool ret = true;
if (hash != NULL)
{
assert (handle != NULL);
ret = check_result (ShaFinal (handle, hash));
}
tr_free (handle);
return ret;
}
/***
****
***/
tr_rc4_ctx_t
tr_rc4_new (void)
{
return tr_new0 (Arc4, 1);
}
void
tr_rc4_free (tr_rc4_ctx_t handle)
{
tr_free (handle);
}
void
tr_rc4_set_key (tr_rc4_ctx_t handle,
const uint8_t * key,
size_t key_length)
{
assert (handle != NULL);
assert (key != NULL);
Arc4SetKey (handle, key, key_length);
}
void
tr_rc4_process (tr_rc4_ctx_t handle,
const void * input,
void * output,
size_t length)
{
assert (handle != NULL);
if (length == 0)
return;
assert (input != NULL);
assert (output != NULL);
Arc4Process (handle, output, input, length);
}
/***
****
***/
tr_dh_ctx_t
tr_dh_new (const uint8_t * prime_num,
size_t prime_num_length,
const uint8_t * generator_num,
size_t generator_num_length)
{
struct tr_dh_ctx * handle = tr_new0 (struct tr_dh_ctx, 1);
assert (prime_num != NULL);
assert (generator_num != NULL);
InitDhKey (&handle->dh);
if (!check_result (DhSetKey (&handle->dh,
prime_num, prime_num_length,
generator_num, generator_num_length)))
{
tr_free (handle);
return NULL;
}
handle->key_length = prime_num_length;
return handle;
}
void
tr_dh_free (tr_dh_ctx_t raw_handle)
{
struct tr_dh_ctx * handle = raw_handle;
if (handle == NULL)
return;
FreeDhKey (&handle->dh);
tr_free (handle->private_key);
tr_free (handle);
}
bool
tr_dh_make_key (tr_dh_ctx_t raw_handle,
size_t private_key_length UNUSED,
uint8_t * public_key,
size_t * public_key_length)
{
struct tr_dh_ctx * handle = raw_handle;
word32 my_private_key_length, my_public_key_length;
assert (handle != NULL);
assert (public_key != NULL);
if (handle->private_key == NULL)
handle->private_key = tr_malloc (handle->key_length);
if (!check_result (DhGenerateKeyPair (&handle->dh, get_rng (),
handle->private_key, &my_private_key_length,
public_key, &my_public_key_length)))
return false;
tr_dh_align_key (public_key, my_public_key_length, handle->key_length);
handle->private_key_length = my_private_key_length;
if (public_key_length != NULL)
*public_key_length = handle->key_length;
return true;
}
tr_dh_secret_t
tr_dh_agree (tr_dh_ctx_t raw_handle,
const uint8_t * other_public_key,
size_t other_public_key_length)
{
struct tr_dh_ctx * handle = raw_handle;
struct tr_dh_secret * ret;
word32 my_secret_key_length;
assert (handle != NULL);
assert (other_public_key != NULL);
ret = tr_dh_secret_new (handle->key_length);
if (check_result (DhAgree (&handle->dh,
ret->key, &my_secret_key_length,
handle->private_key, handle->private_key_length,
other_public_key, other_public_key_length)))
{
tr_dh_secret_align (ret, my_secret_key_length);
}
else
{
tr_dh_secret_free (ret);
ret = NULL;
}
return ret;
}
/***
****
***/
bool
tr_rand_buffer (void * buffer,
size_t length)
{
assert (buffer != NULL);
return check_result (RNG_GenerateBlock (get_rng (), buffer, length));
}

View File

@ -3,7 +3,6 @@ AM_CPPFLAGS = -I@top_srcdir@
AM_CFLAGS = \
@LIBEVENT_CFLAGS@ \
@LIBCURL_CFLAGS@ \
@OPENSSL_CFLAGS@ \
@ZLIB_CFLAGS@ \
@PTHREAD_CFLAGS@ \
${LIBM}
@ -35,7 +34,7 @@ transmission_create_LDADD = \
@LIBUTP_LIBS@ \
@LIBEVENT_LIBS@ \
@LIBCURL_LIBS@ \
@OPENSSL_LIBS@ \
@CRYPTO_LIBS@ \
@ZLIB_LIBS@ \
@PTHREAD_LIBS@ \
${LIBM}