Browse Source

Merge pull request #51 from linusyang/applecc

Support for Apple's CommonCrypto API
pull/52/head
Max Lv 10 years ago
parent
commit
e0d8a15971
5 changed files with 233 additions and 22 deletions
  1. 9
      config.h.in
  2. 42
      configure
  3. 15
      configure.ac
  4. 155
      src/encrypt.c
  5. 34
      src/encrypt.h

9
config.h.in

@ -18,12 +18,18 @@
/* Define to 1 if you have the <arpa/inet.h> header file. */ /* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H #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. */ /* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME #undef HAVE_CLOCK_GETTIME
/* Define to 1 to use the syscall interface for clock_gettime */ /* Define to 1 to use the syscall interface for clock_gettime */
#undef HAVE_CLOCK_SYSCALL #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 /* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
don't. */ don't. */
#undef HAVE_DECL_INET_NTOP #undef HAVE_DECL_INET_NTOP
@ -276,6 +282,9 @@
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME #undef TIME_WITH_SYS_TIME
/* Use Apple CommonCrypto library */
#undef USE_CRYPTO_APPLECC
/* Use OpenSSL library */ /* Use OpenSSL library */
#undef USE_CRYPTO_OPENSSL #undef USE_CRYPTO_OPENSSL

42
configure

@ -752,6 +752,7 @@ with_openssl_lib
with_polarssl with_polarssl
with_polarssl_include with_polarssl_include
with_polarssl_lib with_polarssl_lib
enable_applecc
enable_assert enable_assert
enable_largefile enable_largefile
' '
@ -1391,6 +1392,7 @@ Optional Features:
--enable-fast-install[=PKGS] --enable-fast-install[=PKGS]
optimize for fast installation [default=yes] optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds) --disable-libtool-lock avoid locking (might break parallel builds)
--enable-applecc enable Apple CommonCrypto API support
--disable-assert turn off assertions --disable-assert turn off assertions
--disable-largefile omit support for large files --disable-largefile omit support for large files
@ -12978,6 +12980,46 @@ $as_echo "#define USE_CRYPTO_POLARSSL 1" >>confdefs.h
;; ;;
esac 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 "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
$as_echo_n "checking for C/C++ restrict keyword... " >&6; } $as_echo_n "checking for C/C++ restrict keyword... " >&6; }
if ${ac_cv_c_restrict+:} false; then : if ${ac_cv_c_restrict+:} false; then :

15
configure.ac

@ -55,6 +55,21 @@ case "${with_crypto_library}" in
;; ;;
esac 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 dnl Checks for inet_ntop
ss_FUNC_INET_NTOP ss_FUNC_INET_NTOP

155
src/encrypt.c

@ -17,8 +17,6 @@
#include <polarssl/version.h> #include <polarssl/version.h>
#define CIPHER_UNSUPPORTED "unsupported" #define CIPHER_UNSUPPORTED "unsupported"
#endif
#include <time.h> #include <time.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
@ -27,6 +25,8 @@
#include <stdio.h> #include <stdio.h>
#endif #endif
#endif
#include "encrypt.h" #include "encrypt.h"
#include "utils.h" #include "utils.h"
@ -89,6 +89,34 @@ static const char* supported_ciphers_polarssl[CIPHER_NUM] =
}; };
#endif #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) static int random_compare(const void *_x, const void *_y, uint32_t i, uint64_t a)
{ {
uint8_t x = *((uint8_t *) _x); uint8_t x = *((uint8_t *) _x);
@ -243,7 +271,7 @@ int cipher_key_size (const cipher_kt_t *cipher)
return 0; return 0;
} }
/* Override PolarSSL 32 bit default key size with sane 128 bit default */ /* 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 128 / 8;
} }
return cipher->key_length / 8; return cipher->key_length / 8;
@ -384,10 +412,6 @@ int rand_bytes(uint8_t *output, int len)
} }
rand_initialised = 1; rand_initialised = 1;
} }
#ifdef DEBUG
int orig_len = len;
uint8_t *orig_output = output;
#endif
while (len > 0) { while (len > 0) {
if (ctr_drbg_random(&cd_ctx, output, blen) != 0) { if (ctr_drbg_random(&cd_ctx, output, blen) != 0) {
return 0; return 0;
@ -413,7 +437,7 @@ const cipher_kt_t *get_cipher_type(int method)
const char *polarname = supported_ciphers_polarssl[method]; const char *polarname = supported_ciphers_polarssl[method];
if (strcmp(polarname, CIPHER_UNSUPPORTED) == 0) { if (strcmp(polarname, CIPHER_UNSUPPORTED) == 0) {
LOGE("Cipher %s currently is not supported by PolarSSL library", ciphername); LOGE("Cipher %s currently is not supported by PolarSSL library", ciphername);
FATAL("Unsupported cipher in PolarSSL");
return NULL;
} }
return cipher_info_from_string(polarname); return cipher_info_from_string(polarname);
#endif #endif
@ -433,7 +457,7 @@ const digest_type_t *get_digest_type(const char *digest)
#endif #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) { if (method <= TABLE || method >= CIPHER_NUM) {
LOGE("cipher_context_init(): Illegal method"); 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]; 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); const cipher_kt_t *cipher = get_cipher_type(method);
#if defined(USE_CRYPTO_OPENSSL) #if defined(USE_CRYPTO_OPENSSL)
if (cipher == NULL) { if (cipher == NULL) {
@ -471,8 +515,42 @@ void cipher_context_init(cipher_ctx_t *evp, int method, int enc)
#endif #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) { if (evp == NULL || iv == NULL) {
LOGE("cipher_context_set_keyiv(): Cipher context or IV is null"); LOGE("cipher_context_set_keyiv(): Cipher context or IV is null");
return; 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
#endif #endif
#ifdef DEBUG #ifdef DEBUG
dump("IV", iv, iv_len);
dump("IV", (char *) iv, iv_len);
#endif #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) #if defined(USE_CRYPTO_OPENSSL)
EVP_CIPHER_CTX_cleanup(evp); EVP_CIPHER_CTX_cleanup(evp);
#elif defined(USE_CRYPTO_POLARSSL) #elif defined(USE_CRYPTO_POLARSSL)
@ -519,14 +610,23 @@ void cipher_context_release(cipher_ctx_t *evp) {
#endif #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) #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) #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 #endif
} }
@ -743,11 +843,26 @@ void enc_key_init(int method, const char *pass)
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
#endif #endif
#if defined(USE_CRYPTO_POLARSSL) && defined(USE_CRYPTO_APPLECC)
cipher_kt_t cipher_info;
#endif
uint8_t iv[MAX_IV_LENGTH]; uint8_t iv[MAX_IV_LENGTH];
const cipher_kt_t *cipher = get_cipher_type(method); const cipher_kt_t *cipher = get_cipher_type(method);
if (cipher == NULL) { 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"); const digest_type_t *md = get_digest_type("MD5");
if (md == NULL) { if (md == NULL) {

34
src/encrypt.h

@ -25,7 +25,7 @@
#include <openssl/evp.h> #include <openssl/evp.h>
typedef EVP_CIPHER cipher_kt_t; 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; typedef EVP_MD digest_type_t;
#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH #define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH
#define MAX_IV_LENGTH EVP_MAX_IV_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/cipher.h>
#include <polarssl/md.h> #include <polarssl/md.h>
typedef cipher_info_t cipher_kt_t; 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; typedef md_info_t digest_type_t;
#define MAX_KEY_LENGTH 64 #define MAX_KEY_LENGTH 64
#define MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH #define MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH
@ -44,6 +44,36 @@ typedef md_info_t digest_type_t;
#endif #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 #ifdef HAVE_STDINT_H
#include <stdint.h> #include <stdint.h>
#elif HAVE_INTTYPES_H #elif HAVE_INTTYPES_H

Loading…
Cancel
Save