Browse Source

Merge pull request #22 from linusyang/polarssl

[Crypto] Add Initial PolarSSL Support
pull/24/head
Max Lv 11 years ago
parent
commit
8ee40a0deb
18 changed files with 723 additions and 148 deletions
  1. 4
      Makefile.in
  2. 30
      README.md
  3. 1
      aclocal.m4
  4. 6
      config.h.in
  5. 144
      configure
  6. 28
      configure.ac
  7. 4
      libasyncns/Makefile.in
  8. 4
      libev/Makefile.in
  9. 45
      m4/polarssl.m4
  10. 30
      openwrt/Makefile
  11. 4
      src/Makefile.in
  12. 528
      src/encrypt.c
  13. 25
      src/encrypt.h
  14. 4
      src/local.c
  15. 4
      src/redir.c
  16. 4
      src/server.c
  17. 4
      src/udprelay.c
  18. 2
      src/utils.c

4
Makefile.in

@ -43,8 +43,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
$(top_srcdir)/m4/inet_ntop.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/libev/libev.m4 \
$(top_srcdir)/configure.ac
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/polarssl.m4 \
$(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \

30
README.md

@ -55,7 +55,7 @@ Features
Shadowsocks-libev is writen in pure C and only depends on
[libev](http://software.schmorp.de/pkg/libev.html) and
[openssl](http://www.openssl.org/).
[openssl](http://www.openssl.org/) or [polarssl](https://polarssl.org/).
In normal usage, the memory consumption is about 600KB and the CPU utilization is
no more than 5% on a low-end router (Buffalo WHR-G300N V2 with a 400MHz MIPS CPU,
@ -64,6 +64,10 @@ no more than 5% on a low-end router (Buffalo WHR-G300N V2 with a 400MHz MIPS CPU
Installation
------------
__Note__: Default crypto library is OpenSSL. To build against PolarSSL,
specify `--with-crypto-library=polarssl` and `--with-polarssl=/path/to/polarssl`
when running `./configure`.
### Linux
For Unix-like systems, especially Debian-based systems,
@ -129,9 +133,11 @@ make V=99 package/shadowsocks-libev/openwrt/compile
For Windows, use either MinGW (msys) or Cygwin to build.
At the moment, only `ss-local` is supported to build against MinGW (msys).
If you are using MinGW (msys), please download OpenSSL source tarball
If you are using MinGW (msys), please download OpenSSL or PolarSSL source tarball
to the home directory of msys, and build it like this (may take a few minutes):
* OpenSSL
```bash
tar zxf openssl-1.0.1e.tar.gz
cd openssl-1.0.1e
@ -139,14 +145,32 @@ cd openssl-1.0.1e
make && make install
```
* PolarSSL
```bash
tar zxf polarssl-1.3.2-gpl.tgz
cd polarssl-1.3.2
make lib WINDOWS=1
make install DESTDIR="$HOME/prebuilt"
```
Then, build the binary using the commands below, and all `.exe` files
will be built at `$HOME/ss/bin`:
* OpenSSL
```bash
./configure --prefix="$HOME/ss" --with-openssl="$HOME/prebuilt"
make && make install
```
* PolarSSL
```bash
./configure --prefix="$HOME/ss" --with-crypto-library=polarssl --with-polarssl=$HOME/prebuilt
make && make install
```
Usage
-----
@ -156,7 +180,7 @@ usage:
ss-[local|redir|server]
-s <server_host> host name or ip address of your remote server
-p <server_port> port number of your remote server
-l <local_port>> port number of your local server
-l <local_port> port number of your local server
-k <password> password of your remote server
[-m <encrypt_method>] encrypt method, supporting table, rc4,

1
aclocal.m4

@ -1073,3 +1073,4 @@ m4_include([m4/ltsugar.m4])
m4_include([m4/ltversion.m4])
m4_include([m4/lt~obsolete.m4])
m4_include([m4/openssl.m4])
m4_include([m4/polarssl.m4])

6
config.h.in

@ -273,6 +273,12 @@
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Use OpenSSL library */
#undef USE_CRYPTO_OPENSSL
/* Use PolarSSL library */
#undef USE_CRYPTO_POLARSSL
/* Version number of package */
#undef VERSION

144
configure

@ -738,6 +738,7 @@ ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_dependency_tracking
with_crypto_library
enable_shared
enable_static
with_pic
@ -748,6 +749,9 @@ enable_libtool_lock
with_openssl
with_openssl_include
with_openssl_lib
with_polarssl
with_polarssl_include
with_polarssl_lib
enable_assert
enable_largefile
'
@ -1393,6 +1397,9 @@ Optional Features:
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-crypto-library=library
build with the given crypto library,
TYPE=openssl|polarssl [default=openssl]
--with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use
both]
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
@ -1403,6 +1410,11 @@ Optional Packages:
OpenSSL headers directory (without trailing
/openssl)
--with-openssl-lib=DIR OpenSSL library directory
--with-polarssl=DIR PolarSSL base directory, or:
--with-polarssl-include=DIR
PolarSSL headers directory (without trailing
/polarssl)
--with-polarssl-lib=DIR PolarSSL library directory
Some influential environment variables:
CC C compiler command
@ -4005,6 +4017,21 @@ unknown)
esac
# Check whether --with-crypto-library was given.
if test "${with_crypto_library+set}" = set; then :
withval=$with_crypto_library;
case "${withval}" in
openssl|polarssl) ;;
*) as_fn_error $? "bad value ${withval} for --with-crypto-library" "$LINENO" 5 ;;
esac
else
with_crypto_library="openssl"
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@ -12713,12 +12740,14 @@ fi
case $host in
*-mingw*)
LIBS="$LIBS -lgdi32 -lws2_32"
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32"
;;
*)
;;
esac
case "${with_crypto_library}" in
openssl)
@ -12836,6 +12865,119 @@ fi
$as_echo "#define USE_CRYPTO_OPENSSL 1" >>confdefs.h
;;
polarssl)
# Check whether --with-polarssl was given.
if test "${with_polarssl+set}" = set; then :
withval=$with_polarssl; polarssl="$withval"
CFLAGS="$CFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"
fi
# Check whether --with-polarssl-include was given.
if test "${with_polarssl_include+set}" = set; then :
withval=$with_polarssl_include; polarssl_include="$withval"
CFLAGS="$CFLAGS -I$withval"
fi
# Check whether --with-polarssl-lib was given.
if test "${with_polarssl_lib+set}" = set; then :
withval=$with_polarssl_lib; polarssl_lib="$withval"
LDFLAGS="$LDFLAGS -L$withval"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cipher_init_ctx in -lpolarssl" >&5
$as_echo_n "checking for cipher_init_ctx in -lpolarssl... " >&6; }
if ${ac_cv_lib_polarssl_cipher_init_ctx+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpolarssl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char cipher_init_ctx ();
int
main ()
{
return cipher_init_ctx ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_polarssl_cipher_init_ctx=yes
else
ac_cv_lib_polarssl_cipher_init_ctx=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_polarssl_cipher_init_ctx" >&5
$as_echo "$ac_cv_lib_polarssl_cipher_init_ctx" >&6; }
if test "x$ac_cv_lib_polarssl_cipher_init_ctx" = xyes; then :
LIBS="-lpolarssl $LIBS"
else
as_fn_error $? "PolarSSL libraries not found." "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking polarssl version" >&5
$as_echo_n "checking polarssl version... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <polarssl/version.h>
int
main ()
{
#if POLARSSL_VERSION_NUMBER < 0x01020500
#error invalid version
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
$as_echo "ok" >&6; }
else
as_fn_error $? "PolarSSL 1.2.5 or newer required" "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
$as_echo "#define USE_CRYPTO_POLARSSL 1" >>confdefs.h
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
$as_echo_n "checking for C/C++ restrict keyword... " >&6; }
if ${ac_cv_c_restrict+:} false; then :

28
configure.ac

@ -9,6 +9,19 @@ AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
dnl Checks for crypto library
AC_ARG_WITH(
[crypto-library],
[AS_HELP_STRING([--with-crypto-library=library], [build with the given crypto library, TYPE=openssl|polarssl @<:@default=openssl@:>@])],
[
case "${withval}" in
openssl|polarssl) ;;
*) AC_MSG_ERROR([bad value ${withval} for --with-crypto-library]) ;;
esac
],
[with_crypto_library="openssl"]
)
dnl Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
@ -24,14 +37,23 @@ m4_include([libev/libev.m4])
dnl Add library for mingw
case $host in
*-mingw*)
LIBS="$LIBS -lgdi32 -lws2_32"
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32"
;;
*)
;;
esac
dnl Checks for openssl
ss_OPENSSL
dnl Checks for crypto library
case "${with_crypto_library}" in
openssl)
ss_OPENSSL
AC_DEFINE([USE_CRYPTO_OPENSSL], [1], [Use OpenSSL library])
;;
polarssl)
ss_POLARSSL
AC_DEFINE([USE_CRYPTO_POLARSSL], [1], [Use PolarSSL library])
;;
esac
dnl Checks for inet_ntop
ss_FUNC_INET_NTOP

4
libasyncns/Makefile.in

@ -59,8 +59,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
$(top_srcdir)/m4/inet_ntop.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/libev/libev.m4 \
$(top_srcdir)/configure.ac
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/polarssl.m4 \
$(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d

4
libev/Makefile.in

@ -43,8 +43,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
$(top_srcdir)/m4/inet_ntop.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/libev/libev.m4 \
$(top_srcdir)/configure.ac
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/polarssl.m4 \
$(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d

45
m4/polarssl.m4

@ -0,0 +1,45 @@
dnl Check to find the PolarSSL headers/libraries
AC_DEFUN([ss_POLARSSL],
[
AC_ARG_WITH(polarssl,
AS_HELP_STRING([--with-polarssl=DIR], [PolarSSL base directory, or:]),
[polarssl="$withval"
CFLAGS="$CFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"]
)
AC_ARG_WITH(polarssl-include,
AS_HELP_STRING([--with-polarssl-include=DIR], [PolarSSL headers directory (without trailing /polarssl)]),
[polarssl_include="$withval"
CFLAGS="$CFLAGS -I$withval"]
)
AC_ARG_WITH(polarssl-lib,
AS_HELP_STRING([--with-polarssl-lib=DIR], [PolarSSL library directory]),
[polarssl_lib="$withval"
LDFLAGS="$LDFLAGS -L$withval"]
)
AC_CHECK_LIB(polarssl, cipher_init_ctx,
[LIBS="-lpolarssl $LIBS"],
[AC_MSG_ERROR([PolarSSL libraries not found.])]
)
AC_MSG_CHECKING([polarssl version])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[
#include <polarssl/version.h>
]],
[[
#if POLARSSL_VERSION_NUMBER < 0x01020500
#error invalid version
#endif
]]
)],
[AC_MSG_RESULT([ok])],
[AC_MSG_ERROR([PolarSSL 1.2.5 or newer required])]
)
])

30
openwrt/Makefile

@ -7,7 +7,7 @@ PKG_RELEASE=$(PKG_SOURCE_VERSION)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/madeye/shadowsocks-libev.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=eb9d31869e1d7590cd8c2fb1e7d226ac6cf32fad
PKG_SOURCE_VERSION:=71c30b31f34f181c02410612e51e1c03ee4f311f
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MAINTAINER:=Max Lv <max.c.lv@gmail.com>
@ -18,21 +18,41 @@ PKG_BUILD_PARALLEL:=1
include $(INCLUDE_DIR)/package.mk
define Package/shadowsocks-libev
define Package/shadowsocks-libev/Default
SECTION:=net
CATEGORY:=Network
DEPENDS:=+libopenssl
TITLE:=Lightweight Secured Socks5 Proxy
URL:=https://github.com/madeye/shadowsocks-libev
endef
define Package/shadowsocks-libev
$(call Package/shadowsocks-libev/Default)
TITLE+= (OpenSSL)
VARIANT:=openssl
DEPENDS:=+libopenssl
endef
define Package/shadowsocks-libev-polarssl
$(call Package/shadowsocks-libev/Default)
TITLE+= (PolarSSL)
VARIANT:=polarssl
DEPENDS:=+libpolarssl
endef
define Package/shadowsocks-libev/description
Shadowsocks-libev is a lightweight secured scoks5 proxy for embedded devices and low end boxes.
endef
Package/shadowsocks-libev-polarssl/description=$(Package/shadowsocks-libev/description)
define Package/shadowsocks-libev/conffiles
/etc/config/shadowsocks.json
endef
ifeq ($(BUILD_VARIANT),polarssl)
CONFIGURE_ARGS += --with-crypto-library=polarssl
endif
define Package/shadowsocks-libev/install
$(INSTALL_DIR) $(1)/usr/bin $(1)/etc/init.d $(1)/etc/config
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-local $(1)/usr/bin/ss-local
@ -41,5 +61,7 @@ define Package/shadowsocks-libev/install
$(INSTALL_CONF) ./files/shadowsocks.json $(1)/etc/config/shadowsocks.json
endef
$(eval $(call BuildPackage,shadowsocks-libev))
Package/shadowsocks-libev-polarssl/install=$(Package/shadowsocks-libev/install)
$(eval $(call BuildPackage,shadowsocks-libev))
$(eval $(call BuildPackage,shadowsocks-libev-polarssl))

4
src/Makefile.in

@ -45,8 +45,8 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
$(top_srcdir)/m4/inet_ntop.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/libev/libev.m4 \
$(top_srcdir)/configure.ac
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/polarssl.m4 \
$(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d

528
src/encrypt.c

@ -3,9 +3,30 @@
#endif
#include <stdint.h>
#if defined(USE_CRYPTO_OPENSSL)
#include <openssl/md5.h>
#include <openssl/rand.h>
#elif defined(USE_CRYPTO_POLARSSL)
#include <polarssl/md5.h>
#include <polarssl/entropy.h>
#include <polarssl/ctr_drbg.h>
#include <polarssl/version.h>
#define CIPHER_UNSUPPORTED "unsupported"
#endif
#include <time.h>
#ifdef _WIN32
#include <windows.h>
#include <wincrypt.h>
#else
#include <stdio.h>
#endif
#include "encrypt.h"
#include "utils.h"
@ -13,12 +34,12 @@
static uint8_t *enc_table;
static uint8_t *dec_table;
static uint8_t enc_key[EVP_MAX_KEY_LENGTH];
static uint8_t enc_key[MAX_KEY_LENGTH];
static int enc_key_len;
static int enc_iv_len;
#ifdef DEBUG
static dump(char *tag, char *text)
static void dump(char *tag, char *text)
{
int i, len;
len = strlen(text);
@ -49,6 +70,26 @@ static const char* supported_ciphers[CIPHER_NUM] =
"seed-cfb"
};
#ifdef USE_CRYPTO_POLARSSL
static const char* supported_ciphers_polarssl[CIPHER_NUM] =
{
"table",
"ARC4-128",
"AES-128-CFB128",
"AES-192-CFB128",
"AES-256-CFB128",
"BLOWFISH-CFB64",
"CAMELLIA-128-CFB128",
"CAMELLIA-192-CFB128",
"CAMELLIA-256-CFB128",
CIPHER_UNSUPPORTED,
CIPHER_UNSUPPORTED,
CIPHER_UNSUPPORTED,
CIPHER_UNSUPPORTED,
CIPHER_UNSUPPORTED
};
#endif
static int random_compare(const void *_x, const void *_y, uint32_t i, uint64_t a)
{
uint8_t x = *((uint8_t *) _x);
@ -135,6 +176,20 @@ int enc_get_iv_len()
return enc_iv_len;
}
unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md)
{
#if defined(USE_CRYPTO_OPENSSL)
return MD5(d, n, md);
#elif defined(USE_CRYPTO_POLARSSL)
static unsigned char m[16];
if (md == NULL) {
md = m;
}
md5(d, n, md);
return md;
#endif
}
void enc_table_init(const char *pass)
{
uint32_t i;
@ -145,7 +200,7 @@ void enc_table_init(const char *pass)
enc_table = malloc(256);
dec_table = malloc(256);
digest = MD5((const uint8_t *)pass, strlen(pass), NULL);
digest = enc_md5((const uint8_t *)pass, strlen(pass), NULL);
for (i = 0; i < 8; i++)
{
@ -168,57 +223,339 @@ void enc_table_init(const char *pass)
}
}
char* ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method)
int cipher_iv_size(const cipher_kt_t *cipher)
{
if (method > TABLE)
{
const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]);
if (cipher == NULL)
{
LOGE("Cipher %s not found in OpenSSL library", supported_ciphers[method]);
FATAL("Cannot initialize cipher");
#if defined(USE_CRYPTO_OPENSSL)
return EVP_CIPHER_iv_length (cipher);
#elif defined(USE_CRYPTO_POLARSSL)
if (cipher == NULL) {
return 0;
}
return cipher->iv_size;
#endif
}
int cipher_key_size (const cipher_kt_t *cipher)
{
#if defined(USE_CRYPTO_OPENSSL)
return EVP_CIPHER_key_length(cipher);
#elif defined(USE_CRYPTO_POLARSSL)
if (cipher == NULL) {
return 0;
}
/* Override PolarSSL 32 bit default key size with sane 128 bit default */
if (POLARSSL_CIPHER_ID_BLOWFISH == cipher->base->cipher) {
return 128 / 8;
}
return cipher->key_length / 8;
#endif
}
int bytes_to_key(const cipher_kt_t *cipher, const digest_type_t *md, const uint8_t *pass, uint8_t *key, uint8_t *iv)
{
size_t datal;
datal = strlen((const char *) pass);
#if defined(USE_CRYPTO_OPENSSL)
return EVP_BytesToKey(cipher, md, NULL, pass, datal, 1, key, iv);
#elif defined(USE_CRYPTO_POLARSSL)
md_context_t c;
unsigned char md_buf[MAX_MD_SIZE];
int niv;
int nkey;
int addmd;
unsigned int mds;
unsigned int i;
int rv;
nkey = cipher_key_size(cipher);
niv = cipher_iv_size(cipher);
rv = nkey;
if (pass == NULL) {
return nkey;
}
memset(&c, 0, sizeof(md_context_t));
if (md_init_ctx(&c, md)) {
return 0;
}
addmd = 0;
mds = md_get_size(md);
for (;;) {
int error;
do {
error = 1;
if (md_starts(&c)) {
break;
}
if (addmd) {
if (md_update(&c, &(md_buf[0]), mds)) {
break;
}
} else {
addmd = 1;
}
if (md_update(&c, pass, datal))
break;
if (md_finish(&c, &(md_buf[0])))
break;
error = 0;
} while (0);
if (error) {
md_free_ctx(&c);
memset(md_buf, 0, MAX_MD_SIZE);
return 0;
}
EVP_CIPHER_CTX evp;
EVP_CIPHER_CTX_init(&evp);
if (!EVP_CipherInit_ex(&evp, cipher, NULL, NULL, NULL, 1))
{
LOGE("Cannot initialize cipher %s", supported_ciphers[method]);
exit(EXIT_FAILURE);
i=0;
if (nkey) {
for (;;) {
if (nkey == 0) break;
if (i == mds) break;
if (key != NULL)
*(key++)=md_buf[i];
nkey--;
i++;
}
}
if (!EVP_CIPHER_CTX_set_key_length(&evp, enc_key_len))
{
EVP_CIPHER_CTX_cleanup(&evp);
LOGE("Invalid key length: %d", enc_key_len);
exit(EXIT_FAILURE);
if (niv && (i != mds)) {
for (;;) {
if (niv == 0) break;
if (i == mds) break;
if (iv != NULL)
*(iv++)=md_buf[i];
niv--;
i++;
}
}
if (method > RC4)
{
EVP_CIPHER_CTX_set_padding(&evp, 1);
if ((nkey == 0) && (niv == 0)) break;
}
md_free_ctx(&c);
memset(md_buf, 0, MAX_MD_SIZE);
return rv;
#endif
}
int rand_bytes(uint8_t *output, int len)
{
#if defined(USE_CRYPTO_OPENSSL)
return RAND_bytes(output, len);
#elif defined(USE_CRYPTO_POLARSSL)
static entropy_context ec = {0};
static ctr_drbg_context cd_ctx = {0};
static unsigned char rand_initialised = 0;
const size_t blen = min(len, CTR_DRBG_MAX_REQUEST);
if (!rand_initialised) {
#ifdef _WIN32
HCRYPTPROV hProvider;
union {
unsigned __int64 seed;
BYTE buffer[8];
} rand_buffer;
hProvider = 0;
if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, \
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
CryptGenRandom(hProvider, 8, rand_buffer.buffer);
CryptReleaseContext(hProvider, 0);
} else {
rand_buffer.seed = (unsigned __int64) clock();
}
#else
FILE *urand;
union {
uint64_t seed;
uint8_t buffer[8];
} rand_buffer;
urand = fopen("/dev/urandom", "r");
if (urand) {
fread(&rand_buffer.seed, sizeof(rand_buffer.seed), 1, urand);
fclose(urand);
} else {
rand_buffer.seed = (uint64_t) clock();
}
#endif
entropy_init(&ec);
if (ctr_drbg_init(&cd_ctx, entropy_func, &ec, (const unsigned char *) rand_buffer.buffer, 8) != 0) {
#if POLARSSL_VERSION_NUMBER >= 0x01030000
entropy_free(&ec);
#endif
FATAL("Failed to initialize random generator");
}
rand_initialised = 1;
}
#ifdef DEBUG
int orig_len = len;
uint8_t *orig_output = output;
#endif
while (len > 0) {
if (ctr_drbg_random(&cd_ctx, output, blen) != 0) {
return 0;
}
output += blen;
len -= blen;
}
return 1;
#endif
}
const cipher_kt_t *get_cipher_type(int method)
{
if (method <= TABLE || method >= CIPHER_NUM) {
LOGE("get_cipher_type(): Illegal method");
return NULL;
}
const char *ciphername = supported_ciphers[method];
#if defined(USE_CRYPTO_OPENSSL)
return EVP_get_cipherbyname(ciphername);
#elif defined(USE_CRYPTO_POLARSSL)
const char *polarname = supported_ciphers_polarssl[method];
if (strcmp(polarname, CIPHER_UNSUPPORTED) == 0) {
LOGE("Cipher %s currently is not supported by PolarSSL library", ciphername);
FATAL("Unsupported cipher in PolarSSL");
}
return cipher_info_from_string(polarname);
#endif
}
const digest_type_t *get_digest_type(const char *digest)
{
if (digest == NULL) {
LOGE("get_digest_type(): Digest name is null");
return NULL;
}
#if defined(USE_CRYPTO_OPENSSL)
return EVP_get_digestbyname(digest);
#elif defined(USE_CRYPTO_POLARSSL)
return md_info_from_string(digest);
#endif
}
void cipher_context_init(cipher_ctx_t *evp, int method, int enc)
{
if (method <= TABLE || method >= CIPHER_NUM) {
LOGE("cipher_context_init(): Illegal method");
return;
}
const char *ciphername = supported_ciphers[method];
const cipher_kt_t *cipher = get_cipher_type(method);
#if defined(USE_CRYPTO_OPENSSL)
if (cipher == NULL) {
LOGE("Cipher %s not found in OpenSSL library", ciphername);
FATAL("Cannot initialize cipher");
}
EVP_CIPHER_CTX_init(evp);
if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc)) {
LOGE("Cannot initialize cipher %s", ciphername);
exit(EXIT_FAILURE);
}
if (!EVP_CIPHER_CTX_set_key_length(evp, enc_key_len)) {
EVP_CIPHER_CTX_cleanup(evp);
LOGE("Invalid key length: %d", enc_key_len);
exit(EXIT_FAILURE);
}
if (method > RC4) {
EVP_CIPHER_CTX_set_padding(evp, 1);
}
#elif defined(USE_CRYPTO_POLARSSL)
if (cipher == NULL) {
LOGE("Cipher %s not found in PolarSSL library", ciphername);
FATAL("Cannot initialize PolarSSL cipher");
}
if (cipher_init_ctx(evp, cipher) != 0) {
FATAL("Cannot initialize PolarSSL cipher context");
}
#endif
}
void cipher_context_set_iv(cipher_ctx_t *evp, uint8_t *iv, size_t iv_len, int enc)
{
if (evp == NULL || iv == NULL) {
LOGE("cipher_context_set_keyiv(): Cipher context or IV is null");
return;
}
if (enc) {
rand_bytes(iv, iv_len);
}
#if defined(USE_CRYPTO_OPENSSL)
if (!EVP_CipherInit_ex(evp, NULL, NULL, enc_key, iv, enc)) {
EVP_CIPHER_CTX_cleanup(evp);
FATAL("Cannot set key and IV");
}
#elif defined(USE_CRYPTO_POLARSSL)
if (cipher_setkey(evp, enc_key, enc_key_len * 8, enc) != 0) {
cipher_free_ctx(evp);
FATAL("Cannot set PolarSSL cipher key");
}
#if POLARSSL_VERSION_NUMBER >= 0x01030000
if (cipher_set_iv(evp, iv, iv_len) != 0) {
cipher_free_ctx(evp);
FATAL("Cannot set PolarSSL cipher IV");
}
if(cipher_reset(evp) != 0) {
cipher_free_ctx(evp);
FATAL("Cannot finalize PolarSSL cipher context");
}
#else
if(cipher_reset(evp, iv) != 0) {
cipher_free_ctx(evp);
FATAL("Cannot set PolarSSL cipher IV");
}
#endif
#endif
#ifdef DEBUG
dump("IV", iv);
#endif
}
void cipher_context_release(cipher_ctx_t *evp) {
#if defined(USE_CRYPTO_OPENSSL)
EVP_CIPHER_CTX_cleanup(evp);
#elif defined(USE_CRYPTO_POLARSSL)
cipher_free_ctx(evp);
#endif
}
int cipher_context_update(cipher_ctx_t *evp, uint8_t *output, int *olen, \
const uint8_t *input, int ilen) {
#if defined(USE_CRYPTO_OPENSSL)
return EVP_CipherUpdate(evp, (uint8_t *) output, (size_t *) olen, \
(const uint8_t *) input, (size_t) ilen);
#elif defined(USE_CRYPTO_POLARSSL)
return !cipher_update(evp, (const uint8_t *) input, (size_t) ilen, \
(uint8_t *) output, (size_t *) olen);
#endif
}
char* ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method)
{
if (method > TABLE)
{
cipher_ctx_t evp;
cipher_context_init(&evp, method, 1);
int c_len = *len + BLOCK_SIZE;
int iv_len = 0;
int err = 0;
char *ciphertext = malloc(max(iv_len + c_len, buf_size));
uint8_t iv[EVP_MAX_IV_LENGTH];
uint8_t iv[MAX_IV_LENGTH];
iv_len = enc_iv_len;
RAND_bytes(iv, iv_len);
EVP_CipherInit_ex(&evp, NULL, NULL, enc_key, iv, 1);
cipher_context_set_iv(&evp, iv, iv_len, 1);
memcpy(ciphertext, iv, iv_len);
#ifdef DEBUG
dump("IV", iv);
#endif
err = EVP_EncryptUpdate(&evp, (uint8_t*)(ciphertext+iv_len),
&c_len, (const uint8_t *)plaintext, *len);
err = cipher_context_update(&evp, (uint8_t*)(ciphertext+iv_len),
&c_len, (const uint8_t *)plaintext, *len);
if (!err)
{
free(ciphertext);
free(plaintext);
EVP_CIPHER_CTX_cleanup(&evp);
cipher_context_release(&evp);
return NULL;
}
@ -229,7 +566,7 @@ char* ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method)
*len = iv_len + c_len;
free(plaintext);
EVP_CIPHER_CTX_cleanup(&evp);
cipher_context_release(&evp);
return ciphertext;
@ -257,19 +594,15 @@ char* ss_encrypt(int buf_size, char *plaintext, ssize_t *len, struct enc_ctx *ct
if (!ctx->init)
{
uint8_t iv[EVP_MAX_IV_LENGTH];
uint8_t iv[MAX_IV_LENGTH];
iv_len = enc_iv_len;
RAND_bytes(iv, iv_len);
EVP_CipherInit_ex(&ctx->evp, NULL, NULL, enc_key, iv, 1);
cipher_context_set_iv(&ctx->evp, iv, iv_len, 1);
memcpy(ciphertext, iv, iv_len);
ctx->init = 1;
#ifdef DEBUG
dump("IV", iv);
#endif
}
err = EVP_EncryptUpdate(&ctx->evp, (uint8_t*)(ciphertext+iv_len),
&c_len, (const uint8_t *)plaintext, *len);
err = cipher_context_update(&ctx->evp, (uint8_t*)(ciphertext+iv_len),
&c_len, (const uint8_t *)plaintext, *len);
if (!err)
{
free(ciphertext);
@ -302,51 +635,26 @@ char* ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method)
{
if (method > TABLE)
{
const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]);
if (cipher == NULL)
{
LOGE("Cipher %s not found in OpenSSL library", supported_ciphers[method]);
FATAL("Cannot initialize cipher");
}
EVP_CIPHER_CTX evp;
EVP_CIPHER_CTX_init(&evp);
if (!EVP_CipherInit_ex(&evp, cipher, NULL, NULL, NULL, 0))
{
LOGE("Cannot initialize cipher %s", supported_ciphers[method]);
exit(EXIT_FAILURE);
}
if (!EVP_CIPHER_CTX_set_key_length(&evp, enc_key_len))
{
EVP_CIPHER_CTX_cleanup(&evp);
LOGE("Invalid key length: %d", enc_key_len);
exit(EXIT_FAILURE);
}
if (method > RC4)
{
EVP_CIPHER_CTX_set_padding(&evp, 1);
}
cipher_ctx_t evp;
cipher_context_init(&evp, method, 0);
int p_len = *len + BLOCK_SIZE;
int iv_len = 0;
int err = 0;
char *plaintext = malloc(max(p_len, buf_size));
uint8_t iv[EVP_MAX_IV_LENGTH];
uint8_t iv[MAX_IV_LENGTH];
iv_len = enc_iv_len;
memcpy(iv, ciphertext, iv_len);
EVP_CipherInit_ex(&evp, NULL, NULL, enc_key, iv, 0);
cipher_context_set_iv(&evp, iv, iv_len, 0);
#ifdef DEBUG
dump("IV", iv);
#endif
err = EVP_DecryptUpdate(&evp, (uint8_t*)plaintext, &p_len,
(const uint8_t*)(ciphertext + iv_len), *len - iv_len);
err = cipher_context_update(&evp, (uint8_t*)plaintext, &p_len,
(const uint8_t*)(ciphertext + iv_len), *len - iv_len);
if (!err)
{
free(ciphertext);
free(plaintext);
EVP_CIPHER_CTX_cleanup(&evp);
cipher_context_release(&evp);
return NULL;
}
@ -357,7 +665,7 @@ char* ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method)
*len = p_len;
free(ciphertext);
EVP_CIPHER_CTX_cleanup(&evp);
cipher_context_release(&evp);
return plaintext;
}
else
@ -383,18 +691,15 @@ char* ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *c
if (!ctx->init)
{
uint8_t iv[EVP_MAX_IV_LENGTH];
uint8_t iv[MAX_IV_LENGTH];
iv_len = enc_iv_len;
memcpy(iv, ciphertext, iv_len);
EVP_CipherInit_ex(&ctx->evp, NULL, NULL, enc_key, iv, 0);
cipher_context_set_iv(&ctx->evp, iv, iv_len, 0);
ctx->init = 1;
#ifdef DEBUG
dump("IV", iv);
#endif
}
err = EVP_DecryptUpdate(&ctx->evp, (uint8_t*)plaintext, &p_len,
(const uint8_t*)(ciphertext + iv_len), *len - iv_len);
err = cipher_context_update(&ctx->evp, (uint8_t*)plaintext, &p_len,
(const uint8_t*)(ciphertext + iv_len), *len - iv_len);
if (!err)
{
@ -426,50 +731,37 @@ char* ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *c
void enc_ctx_init(int method, struct enc_ctx *ctx, int enc)
{
const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]);
if (cipher == NULL)
{
LOGE("Cipher %s not found in OpenSSL library", supported_ciphers[method]);
FATAL("Cannot initialize cipher");
}
memset(ctx, 0, sizeof(struct enc_ctx));
EVP_CIPHER_CTX *evp = &ctx->evp;
EVP_CIPHER_CTX_init(evp);
if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc))
{
LOGE("Cannot initialize cipher %s", supported_ciphers[method]);
exit(EXIT_FAILURE);
}
if (!EVP_CIPHER_CTX_set_key_length(evp, enc_key_len))
{
EVP_CIPHER_CTX_cleanup(evp);
LOGE("Invalid key length: %d", enc_key_len);
exit(EXIT_FAILURE);
}
if (method > RC4)
{
EVP_CIPHER_CTX_set_padding(evp, 1);
}
cipher_context_init(&ctx->evp, method, enc);
}
void enc_key_init(int method, const char *pass)
{
if (method <= TABLE || method >= CIPHER_NUM) {
LOGE("enc_key_init(): Illegal method");
return;
}
#if defined(USE_CRYPTO_OPENSSL)
OpenSSL_add_all_algorithms();
#endif
uint8_t iv[EVP_MAX_IV_LENGTH];
const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]);
if (cipher == NULL)
{
LOGE("Cipher %s not found in OpenSSL library", supported_ciphers[method]);
uint8_t iv[MAX_IV_LENGTH];
const cipher_kt_t *cipher = get_cipher_type(method);
if (cipher == NULL) {
LOGE("Cipher %s not found in crypto library", supported_ciphers[method]);
FATAL("Cannot initialize cipher");
return;
}
const digest_type_t *md = get_digest_type("MD5");
if (md == NULL) {
FATAL("MD5 Digest not found in crypto library");
}
enc_key_len = EVP_BytesToKey(cipher, EVP_md5(), NULL, (uint8_t *)pass,
strlen(pass), 1, enc_key, iv);
enc_iv_len = EVP_CIPHER_iv_length(cipher);
enc_key_len = bytes_to_key(cipher, md, (const uint8_t *) pass, enc_key, iv);
if (enc_key_len == 0) {
FATAL("Cannot generate key and IV");
}
enc_iv_len = cipher_iv_size(cipher);
}
int enc_init(const char *pass, const char *method)

25
src/encrypt.h

@ -21,7 +21,28 @@
#include <stdlib.h>
#include <stdio.h>
#if defined(USE_CRYPTO_OPENSSL)
#include <openssl/evp.h>
typedef EVP_CIPHER cipher_kt_t;
typedef EVP_CIPHER_CTX cipher_ctx_t;
typedef EVP_MD digest_type_t;
#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH
#define MAX_IV_LENGTH EVP_MAX_IV_LENGTH
#define MAX_MD_SIZE EVP_MAX_MD_SIZE
#elif defined(USE_CRYPTO_POLARSSL)
#include <polarssl/cipher.h>
#include <polarssl/md.h>
typedef cipher_info_t cipher_kt_t;
typedef cipher_context_t cipher_ctx_t;
typedef md_info_t digest_type_t;
#define MAX_KEY_LENGTH 64
#define MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH
#define MAX_MD_SIZE POLARSSL_MD_MAX_SIZE
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
@ -54,7 +75,7 @@
struct enc_ctx
{
uint8_t init;
EVP_CIPHER_CTX evp;
cipher_ctx_t evp;
};
char* ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method);
@ -64,5 +85,7 @@ char* ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *c
void enc_ctx_init(int method, struct enc_ctx *ctx, int enc);
int enc_init(const char *pass, const char *method);
int enc_get_iv_len(void);
void cipher_context_release(cipher_ctx_t *evp);
unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md);
#endif // _ENCRYPT_H

4
src/local.c

@ -700,12 +700,12 @@ static void free_server(struct server *server)
}
if (server->e_ctx != NULL)
{
EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp);
cipher_context_release(&server->e_ctx->evp);
free(server->e_ctx);
}
if (server->d_ctx != NULL)
{
EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp);
cipher_context_release(&server->d_ctx->evp);
free(server->d_ctx);
}
if (server->buf)

4
src/redir.c

@ -557,12 +557,12 @@ void free_server(struct server *server)
}
if (server->e_ctx != NULL)
{
EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp);
cipher_context_release(&server->e_ctx->evp);
free(server->e_ctx);
}
if (server->d_ctx != NULL)
{
EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp);
cipher_context_release(&server->d_ctx->evp);
free(server->d_ctx);
}
if (server->buf != NULL)

4
src/server.c

@ -830,12 +830,12 @@ void free_server(struct server *server)
}
if (server->e_ctx != NULL)
{
EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp);
cipher_context_release(&server->e_ctx->evp);
free(server->e_ctx);
}
if (server->d_ctx != NULL)
{
EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp);
cipher_context_release(&server->d_ctx->evp);
free(server->d_ctx);
}
if (server->buf != NULL)

4
src/udprelay.c

@ -31,8 +31,6 @@
#include "win32.h"
#endif
#include <openssl/md5.h>
#include "utils.h"
#include "udprelay.h"
#include "cache.h"
@ -89,7 +87,7 @@ static char *hash_key(const char *header, const int header_len, const struct soc
memcpy(key, addr, sizeof(struct sockaddr));
memcpy(key + sizeof(struct sockaddr), header, header_len);
return (char*) MD5((const uint8_t *)key, sizeof(struct sockaddr) + header_len, NULL);
return (char*) enc_md5((const uint8_t *)key, sizeof(struct sockaddr) + header_len, NULL);
}
static int parse_udprealy_header(const char* buf, const int buf_len, char *host, char *port)

2
src/utils.c

@ -83,7 +83,7 @@ void usage()
printf(" ss-[local|redir|server]\n");
printf(" -s <server_host> host name or ip address of your remote server\n");
printf(" -p <server_port> port number of your remote server\n");
printf(" -l <local_port>> port number of your local server\n");
printf(" -l <local_port> port number of your local server\n");
printf(" -k <password> password of your remote server\n");
printf("\n");
printf(" [-m <encrypt_method>] encrypt method, supporting table, rc4,\n");

Loading…
Cancel
Save