mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-25 10:13:44 +00:00
darwin: initial support for CommonCrypto API
This commit is contained in:
@@ -18,12 +18,18 @@
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#undef HAVE_ARPA_INET_H
|
||||
|
||||
/* Define to 1 if you have the `CCCryptorCreateWithMode' function. */
|
||||
#undef HAVE_CCCRYPTORCREATEWITHMODE
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define to 1 to use the syscall interface for clock_gettime */
|
||||
#undef HAVE_CLOCK_SYSCALL
|
||||
|
||||
/* Define to 1 if you have the <CommonCrypto/CommonCrypto.h> header file. */
|
||||
#undef HAVE_COMMONCRYPTO_COMMONCRYPTO_H
|
||||
|
||||
/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_INET_NTOP
|
||||
@@ -276,6 +282,9 @@
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
|
||||
/* Use Apple CommonCrypto library */
|
||||
#undef USE_CRYPTO_APPLECC
|
||||
|
||||
/* Use OpenSSL library */
|
||||
#undef USE_CRYPTO_OPENSSL
|
||||
|
||||
|
||||
@@ -752,6 +752,7 @@ with_openssl_lib
|
||||
with_polarssl
|
||||
with_polarssl_include
|
||||
with_polarssl_lib
|
||||
enable_applecc
|
||||
enable_assert
|
||||
enable_largefile
|
||||
'
|
||||
@@ -1391,6 +1392,7 @@ Optional Features:
|
||||
--enable-fast-install[=PKGS]
|
||||
optimize for fast installation [default=yes]
|
||||
--disable-libtool-lock avoid locking (might break parallel builds)
|
||||
--enable-applecc enable Apple CommonCrypto API support
|
||||
--disable-assert turn off assertions
|
||||
--disable-largefile omit support for large files
|
||||
|
||||
@@ -12978,6 +12980,46 @@ $as_echo "#define USE_CRYPTO_POLARSSL 1" >>confdefs.h
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check whether --enable-applecc was given.
|
||||
if test "${enable_applecc+set}" = set; then :
|
||||
enableval=$enable_applecc;
|
||||
for ac_header in CommonCrypto/CommonCrypto.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "CommonCrypto/CommonCrypto.h" "ac_cv_header_CommonCrypto_CommonCrypto_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_CommonCrypto_CommonCrypto_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_COMMONCRYPTO_COMMONCRYPTO_H 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
as_fn_error $? "CommonCrypto header files not found." "$LINENO" 5; break
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
for ac_func in CCCryptorCreateWithMode
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "CCCryptorCreateWithMode" "ac_cv_func_CCCryptorCreateWithMode"
|
||||
if test "x$ac_cv_func_CCCryptorCreateWithMode" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_CCCRYPTORCREATEWITHMODE 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
as_fn_error $? "CommonCrypto API needs OS X (>= 10.7) and iOS (>= 5.0)." "$LINENO" 5; break
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
$as_echo "#define USE_CRYPTO_APPLECC 1" >>confdefs.h
|
||||
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
{ $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 :
|
||||
|
||||
@@ -55,6 +55,21 @@ case "${with_crypto_library}" in
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl Checks for Apple CommonCrypto API
|
||||
AC_ARG_ENABLE(applecc,
|
||||
AS_HELP_STRING([--enable-applecc], [enable Apple CommonCrypto API support]),
|
||||
[
|
||||
AC_CHECK_HEADERS(CommonCrypto/CommonCrypto.h,
|
||||
[],
|
||||
[AC_MSG_ERROR([CommonCrypto header files not found.]); break]
|
||||
)
|
||||
AC_CHECK_FUNCS([CCCryptorCreateWithMode], ,
|
||||
[AC_MSG_ERROR([CommonCrypto API needs OS X (>= 10.7) and iOS (>= 5.0).]); break]
|
||||
)
|
||||
AC_DEFINE([USE_CRYPTO_APPLECC], [1], [Use Apple CommonCrypto library])
|
||||
]
|
||||
)
|
||||
|
||||
dnl Checks for inet_ntop
|
||||
ss_FUNC_INET_NTOP
|
||||
|
||||
|
||||
+135
-20
@@ -17,8 +17,6 @@
|
||||
#include <polarssl/version.h>
|
||||
#define CIPHER_UNSUPPORTED "unsupported"
|
||||
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
@@ -27,6 +25,8 @@
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "encrypt.h"
|
||||
#include "utils.h"
|
||||
|
||||
@@ -89,6 +89,34 @@ static const char* supported_ciphers_polarssl[CIPHER_NUM] =
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
static const CCAlgorithm supported_ciphers_applecc[CIPHER_NUM] =
|
||||
{
|
||||
kCCAlgorithmInvalid,
|
||||
kCCAlgorithmRC4,
|
||||
kCCAlgorithmAES,
|
||||
kCCAlgorithmAES,
|
||||
kCCAlgorithmAES,
|
||||
kCCAlgorithmBlowfish,
|
||||
kCCAlgorithmInvalid,
|
||||
kCCAlgorithmInvalid,
|
||||
kCCAlgorithmInvalid,
|
||||
kCCAlgorithmCAST,
|
||||
kCCAlgorithmDES,
|
||||
kCCAlgorithmInvalid,
|
||||
kCCAlgorithmRC2,
|
||||
kCCAlgorithmInvalid
|
||||
};
|
||||
|
||||
static const int supported_ciphers_iv_size[CIPHER_NUM] = {
|
||||
0, 0, 16, 16, 16, 8, 16, 16, 16, 8, 8, 8, 8, 16
|
||||
};
|
||||
|
||||
static const int supported_ciphers_key_size[CIPHER_NUM] = {
|
||||
0, 16, 16, 24, 32, 16, 16, 24, 32, 16, 8, 16, 16, 16
|
||||
};
|
||||
#endif
|
||||
|
||||
static int random_compare(const void *_x, const void *_y, uint32_t i, uint64_t a)
|
||||
{
|
||||
uint8_t x = *((uint8_t *) _x);
|
||||
@@ -243,7 +271,7 @@ int cipher_key_size (const cipher_kt_t *cipher)
|
||||
return 0;
|
||||
}
|
||||
/* Override PolarSSL 32 bit default key size with sane 128 bit default */
|
||||
if (POLARSSL_CIPHER_ID_BLOWFISH == cipher->base->cipher) {
|
||||
if (cipher->base != NULL && POLARSSL_CIPHER_ID_BLOWFISH == cipher->base->cipher) {
|
||||
return 128 / 8;
|
||||
}
|
||||
return cipher->key_length / 8;
|
||||
@@ -384,10 +412,6 @@ int rand_bytes(uint8_t *output, int len)
|
||||
}
|
||||
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;
|
||||
@@ -413,7 +437,7 @@ const cipher_kt_t *get_cipher_type(int method)
|
||||
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 NULL;
|
||||
}
|
||||
return cipher_info_from_string(polarname);
|
||||
#endif
|
||||
@@ -433,7 +457,7 @@ const digest_type_t *get_digest_type(const char *digest)
|
||||
#endif
|
||||
}
|
||||
|
||||
void cipher_context_init(cipher_ctx_t *evp, int method, int enc)
|
||||
void cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
|
||||
{
|
||||
if (method <= TABLE || method >= CIPHER_NUM) {
|
||||
LOGE("cipher_context_init(): Illegal method");
|
||||
@@ -441,6 +465,26 @@ void cipher_context_init(cipher_ctx_t *evp, int method, int enc)
|
||||
}
|
||||
|
||||
const char *ciphername = supported_ciphers[method];
|
||||
#if defined(USE_CRYPTO_APPLECC)
|
||||
cipher_cc_t *cc = &ctx->cc;
|
||||
cc->cryptor = NULL;
|
||||
cc->cipher = supported_ciphers_applecc[method];
|
||||
if (cc->cipher == kCCAlgorithmInvalid) {
|
||||
cc->valid = kCCContextInvalid;
|
||||
} else {
|
||||
cc->valid = kCCContextValid;
|
||||
if (cc->cipher == kCCAlgorithmRC4) {
|
||||
cc->mode = kCCModeRC4;
|
||||
cc->padding = ccNoPadding;
|
||||
} else {
|
||||
cc->mode = kCCModeCFB;
|
||||
cc->padding = ccPKCS7Padding;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
const cipher_kt_t *cipher = get_cipher_type(method);
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
if (cipher == NULL) {
|
||||
@@ -471,8 +515,42 @@ void cipher_context_init(cipher_ctx_t *evp, int method, int enc)
|
||||
#endif
|
||||
}
|
||||
|
||||
void cipher_context_set_iv(cipher_ctx_t *evp, uint8_t *iv, size_t iv_len, int enc)
|
||||
void cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len, int enc)
|
||||
{
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t *cc = &ctx->cc;
|
||||
if (cc->valid == kCCContextValid) {
|
||||
memcpy(cc->iv, iv, iv_len);
|
||||
memcpy(cc->key, enc_key, enc_key_len);
|
||||
cc->iv_len = iv_len;
|
||||
cc->key_len = enc_key_len;
|
||||
cc->encrypt = enc ? kCCEncrypt : kCCDecrypt;
|
||||
if (cc->cryptor != NULL) {
|
||||
CCCryptorRelease(cc->cryptor);
|
||||
cc->cryptor = NULL;
|
||||
}
|
||||
|
||||
CCCryptorStatus ret;
|
||||
ret = CCCryptorCreateWithMode(
|
||||
cc->encrypt,
|
||||
cc->mode,
|
||||
cc->cipher,
|
||||
cc->padding,
|
||||
cc->iv, cc->key, cc->key_len,
|
||||
NULL, 0, 0, 0,
|
||||
&cc->cryptor);
|
||||
if (ret != kCCSuccess) {
|
||||
if (cc->cryptor != NULL) {
|
||||
CCCryptorRelease(cc->cryptor);
|
||||
cc->cryptor = NULL;
|
||||
}
|
||||
FATAL("Cannot set CommonCrypto key and IV");
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
if (evp == NULL || iv == NULL) {
|
||||
LOGE("cipher_context_set_keyiv(): Cipher context or IV is null");
|
||||
return;
|
||||
@@ -506,12 +584,25 @@ void cipher_context_set_iv(cipher_ctx_t *evp, uint8_t *iv, size_t iv_len, int en
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
dump("IV", iv, iv_len);
|
||||
dump("IV", (char *) iv, iv_len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cipher_context_release(cipher_ctx_t *evp) {
|
||||
void cipher_context_release(cipher_ctx_t *ctx) {
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t *cc = &ctx->cc;
|
||||
if (cc->cryptor != NULL) {
|
||||
CCCryptorRelease(cc->cryptor);
|
||||
cc->cryptor = NULL;
|
||||
}
|
||||
if (cc->valid == kCCContextValid) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
EVP_CIPHER_CTX_cleanup(evp);
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
@@ -519,14 +610,23 @@ void cipher_context_release(cipher_ctx_t *evp) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int cipher_context_update(cipher_ctx_t *evp, uint8_t *output, int *olen,
|
||||
const uint8_t *input, int ilen) {
|
||||
static int cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, int *olen,
|
||||
const uint8_t *input, int ilen) {
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t *cc = &ctx->cc;
|
||||
if (cc->valid == kCCContextValid) {
|
||||
CCCryptorStatus ret;
|
||||
ret = CCCryptorUpdate(cc->cryptor, input, ilen, output, ilen + BLOCK_SIZE, (size_t *) olen);
|
||||
return (ret == kCCSuccess) ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
return EVP_CipherUpdate(evp, (uint8_t *) output, olen,
|
||||
(const uint8_t *) input, (size_t) ilen);
|
||||
return EVP_CipherUpdate(evp, (uint8_t *) output, 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);
|
||||
return !cipher_update(evp, (const uint8_t *) input, (size_t) ilen,
|
||||
(uint8_t *) output, (size_t *) olen);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -743,11 +843,26 @@ void enc_key_init(int method, const char *pass)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#endif
|
||||
|
||||
#if defined(USE_CRYPTO_POLARSSL) && defined(USE_CRYPTO_APPLECC)
|
||||
cipher_kt_t cipher_info;
|
||||
#endif
|
||||
|
||||
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");
|
||||
do {
|
||||
#if defined(USE_CRYPTO_POLARSSL) && defined(USE_CRYPTO_APPLECC)
|
||||
if (supported_ciphers_applecc[method] != kCCAlgorithmInvalid) {
|
||||
cipher_info.base = NULL;
|
||||
cipher_info.key_length = supported_ciphers_key_size[method] * 8;
|
||||
cipher_info.iv_size = supported_ciphers_iv_size[method];
|
||||
cipher = (const cipher_kt_t *) &cipher_info;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
LOGE("Cipher %s not found in crypto library", supported_ciphers[method]);
|
||||
FATAL("Cannot initialize cipher");
|
||||
} while (0);
|
||||
}
|
||||
const digest_type_t *md = get_digest_type("MD5");
|
||||
if (md == NULL) {
|
||||
|
||||
+32
-2
@@ -25,7 +25,7 @@
|
||||
|
||||
#include <openssl/evp.h>
|
||||
typedef EVP_CIPHER cipher_kt_t;
|
||||
typedef EVP_CIPHER_CTX cipher_ctx_t;
|
||||
typedef EVP_CIPHER_CTX cipher_evp_t;
|
||||
typedef EVP_MD digest_type_t;
|
||||
#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH
|
||||
#define MAX_IV_LENGTH EVP_MAX_IV_LENGTH
|
||||
@@ -36,7 +36,7 @@ typedef EVP_MD digest_type_t;
|
||||
#include <polarssl/cipher.h>
|
||||
#include <polarssl/md.h>
|
||||
typedef cipher_info_t cipher_kt_t;
|
||||
typedef cipher_context_t cipher_ctx_t;
|
||||
typedef cipher_context_t cipher_evp_t;
|
||||
typedef md_info_t digest_type_t;
|
||||
#define MAX_KEY_LENGTH 64
|
||||
#define MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH
|
||||
@@ -44,6 +44,36 @@ typedef md_info_t digest_type_t;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
|
||||
#include <CommonCrypto/CommonCrypto.h>
|
||||
|
||||
#define kCCAlgorithmInvalid UINT32_MAX
|
||||
#define kCCContextValid 0
|
||||
#define kCCContextInvalid -1
|
||||
|
||||
typedef struct {
|
||||
CCCryptorRef cryptor;
|
||||
int valid;
|
||||
CCOperation encrypt;
|
||||
CCAlgorithm cipher;
|
||||
CCMode mode;
|
||||
CCPadding padding;
|
||||
uint8_t iv[MAX_IV_LENGTH];
|
||||
uint8_t key[MAX_KEY_LENGTH];
|
||||
size_t iv_len;
|
||||
size_t key_len;
|
||||
} cipher_cc_t;
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
cipher_evp_t evp;
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t cc;
|
||||
#endif
|
||||
} cipher_ctx_t;
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif HAVE_INTTYPES_H
|
||||
|
||||
Reference in New Issue
Block a user