mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-28 11:43:50 +00:00
Fix #928
This commit is contained in:
+114
-225
@@ -433,33 +433,33 @@ enc_table_init(const char *pass)
|
||||
}
|
||||
|
||||
int
|
||||
cipher_iv_size(const cipher_kt_t *cipher)
|
||||
cipher_iv_size(const cipher_t *cipher)
|
||||
{
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
return EVP_CIPHER_iv_length(cipher);
|
||||
return cipher->iv_len;
|
||||
#elif defined(USE_CRYPTO_POLARSSL) || defined(USE_CRYPTO_MBEDTLS)
|
||||
if (cipher == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return cipher->iv_size;
|
||||
return cipher->info->iv_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
cipher_key_size(const cipher_kt_t *cipher)
|
||||
cipher_key_size(const cipher_t *cipher)
|
||||
{
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
return EVP_CIPHER_key_length(cipher);
|
||||
return cipher->key_len;
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
if (cipher == NULL) {
|
||||
return 0;
|
||||
}
|
||||
/* Override PolarSSL 32 bit default key size with sane 128 bit default */
|
||||
if (cipher->base != NULL && POLARSSL_CIPHER_ID_BLOWFISH ==
|
||||
cipher->base->cipher) {
|
||||
if (cipher->info->base != NULL && POLARSSL_CIPHER_ID_BLOWFISH ==
|
||||
cipher->info->base->cipher) {
|
||||
return 128 / 8;
|
||||
}
|
||||
return cipher->key_length / 8;
|
||||
return cipher->info->key_length / 8;
|
||||
#elif defined(USE_CRYPTO_MBEDTLS)
|
||||
/*
|
||||
* Semi-API changes (technically public, morally private)
|
||||
@@ -473,224 +473,107 @@ cipher_key_size(const cipher_kt_t *cipher)
|
||||
return 0;
|
||||
}
|
||||
/* From Version 1.2.7 released 2013-04-13 Default Blowfish keysize is now 128-bits */
|
||||
return cipher->key_bitlen / 8;
|
||||
return cipher->info->key_bitlen / 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)
|
||||
bytes_to_key(const cipher_t *cipher, const digest_type_t *md,
|
||||
const uint8_t *pass, uint8_t *key)
|
||||
{
|
||||
size_t datal;
|
||||
datal = strlen((const char *)pass);
|
||||
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
return EVP_BytesToKey(cipher, md, NULL, pass, datal, 1, key, iv);
|
||||
|
||||
MD5_CTX c;
|
||||
unsigned char md_buf[MAX_MD_SIZE];
|
||||
int nkey;
|
||||
int addmd;
|
||||
unsigned int i, j, mds;
|
||||
|
||||
mds = 16;
|
||||
nkey = cipher_key_size(cipher);
|
||||
if (pass == NULL) return nkey;
|
||||
memset(&c, 0, sizeof(MD5_CTX));
|
||||
|
||||
for (j = 0, addmd = 0; j < nkey; addmd++) {
|
||||
MD5_Init(&c);
|
||||
if (addmd) {
|
||||
MD5_Update(&c, md_buf, mds);
|
||||
}
|
||||
MD5_Update(&c, pass, datal);
|
||||
MD5_Final(md_buf, &c);
|
||||
|
||||
for (i = 0; i < mds; i++, j++) {
|
||||
if (j >= nkey) break;
|
||||
key[j] = md_buf[i];
|
||||
}
|
||||
}
|
||||
return nkey;
|
||||
|
||||
#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;
|
||||
unsigned int i, j, mds;
|
||||
|
||||
nkey = cipher_key_size(cipher);
|
||||
niv = cipher_iv_size(cipher);
|
||||
rv = nkey;
|
||||
if (pass == NULL) {
|
||||
return nkey;
|
||||
}
|
||||
|
||||
mds = md_get_size(md);
|
||||
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;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if (nkey) {
|
||||
for (;;) {
|
||||
if (nkey == 0) {
|
||||
break;
|
||||
}
|
||||
if (i == mds) {
|
||||
break;
|
||||
}
|
||||
if (key != NULL) {
|
||||
*(key++) = md_buf[i];
|
||||
}
|
||||
nkey--;
|
||||
i++;
|
||||
}
|
||||
if (pass == NULL) return nkey;
|
||||
if (md_init_ctx(&c, md)) return 0;
|
||||
|
||||
for (j = 0, addmd = 0; j < nkey; addmd++) {
|
||||
md_starts(&c);
|
||||
if (addmd) {
|
||||
md_update(&c, md_buf, mds);
|
||||
}
|
||||
if (niv && (i != mds)) {
|
||||
for (;;) {
|
||||
if (niv == 0) {
|
||||
break;
|
||||
}
|
||||
if (i == mds) {
|
||||
break;
|
||||
}
|
||||
if (iv != NULL) {
|
||||
*(iv++) = md_buf[i];
|
||||
}
|
||||
niv--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if ((nkey == 0) && (niv == 0)) {
|
||||
break;
|
||||
md_update(&c, pass, datal);
|
||||
md_finish(&c, md_buf);
|
||||
|
||||
for (i = 0; i < mds; i++, j++) {
|
||||
if (j >= nkey) break;
|
||||
key[j] = md_buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
md_free_ctx(&c);
|
||||
memset(md_buf, 0, MAX_MD_SIZE);
|
||||
return rv;
|
||||
return nkey;
|
||||
|
||||
#elif defined(USE_CRYPTO_MBEDTLS)
|
||||
/*
|
||||
*
|
||||
* Generic message digest context.
|
||||
*
|
||||
* typedef struct {
|
||||
* Information about the associated message digest
|
||||
* const mbedtls_md_info_t *md_info;
|
||||
*
|
||||
* Digest-specific context
|
||||
* void *md_ctx;
|
||||
*
|
||||
* HMAC part of the context
|
||||
* void *hmac_ctx;
|
||||
* } mbedtls_md_context_t; // mbedtls 2.0.0
|
||||
*
|
||||
* typedef struct {
|
||||
* Information about the associated message digest
|
||||
* const md_info_t *md_info;
|
||||
*
|
||||
* Digest-specific context
|
||||
* void *md_ctx;
|
||||
* } md_context_t; //polarssl 1.3
|
||||
*
|
||||
*/
|
||||
// NOTE: different struct body, initialize new param hmac 0 to disable HMAC
|
||||
|
||||
mbedtls_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;
|
||||
unsigned int i, j, mds;
|
||||
|
||||
nkey = cipher_key_size(cipher);
|
||||
niv = cipher_iv_size(cipher);
|
||||
rv = nkey;
|
||||
if (pass == NULL) {
|
||||
return nkey;
|
||||
}
|
||||
|
||||
mds = mbedtls_md_get_size(md);
|
||||
memset(&c, 0, sizeof(mbedtls_md_context_t));
|
||||
// XXX: md_init_ctx superseded by mbedtls_md_setup() in 2.0.0
|
||||
// new param hmac 0 to save some memory if HMAC will not be used,
|
||||
// non-zero is HMAC is going to be used with this context.
|
||||
if (mbedtls_md_setup(&c, md, 1)) {
|
||||
return 0;
|
||||
}
|
||||
addmd = 0;
|
||||
mds = mbedtls_md_get_size(md);
|
||||
for (;;) {
|
||||
int error;
|
||||
do {
|
||||
error = 1;
|
||||
if (mbedtls_md_starts(&c)) {
|
||||
break;
|
||||
}
|
||||
if (addmd) {
|
||||
if (mbedtls_md_update(&c, &(md_buf[0]), mds)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
addmd = 1;
|
||||
}
|
||||
if (mbedtls_md_update(&c, pass, datal)) {
|
||||
break;
|
||||
}
|
||||
if (mbedtls_md_finish(&c, &(md_buf[0]))) {
|
||||
break;
|
||||
}
|
||||
error = 0;
|
||||
} while (0);
|
||||
if (error) {
|
||||
mbedtls_md_free(&c); // md_free_ctx deprecated, Use mbedtls_md_free() instead
|
||||
memset(md_buf, 0, MAX_MD_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if (nkey) {
|
||||
for (;;) {
|
||||
if (nkey == 0) {
|
||||
break;
|
||||
}
|
||||
if (i == mds) {
|
||||
break;
|
||||
}
|
||||
if (key != NULL) {
|
||||
*(key++) = md_buf[i];
|
||||
}
|
||||
nkey--;
|
||||
i++;
|
||||
}
|
||||
if (pass == NULL) return nkey;
|
||||
if (mbedtls_md_setup(&c, md, 1)) return 0;
|
||||
|
||||
for (j = 0, addmd = 0; j < nkey; addmd++) {
|
||||
mbedtls_md_starts(&c);
|
||||
if (addmd) {
|
||||
mbedtls_md_update(&c, md_buf, mds);
|
||||
}
|
||||
if (niv && (i != mds)) {
|
||||
for (;;) {
|
||||
if (niv == 0) {
|
||||
break;
|
||||
}
|
||||
if (i == mds) {
|
||||
break;
|
||||
}
|
||||
if (iv != NULL) {
|
||||
*(iv++) = md_buf[i];
|
||||
}
|
||||
niv--;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if ((nkey == 0) && (niv == 0)) {
|
||||
break;
|
||||
mbedtls_md_update(&c, pass, datal);
|
||||
mbedtls_md_finish(&c, &(md_buf[0]));
|
||||
|
||||
for (i = 0; i < mds; i++, j++) {
|
||||
if (j >= nkey) break;
|
||||
key[j] = md_buf[i];
|
||||
}
|
||||
}
|
||||
mbedtls_md_free(&c); // NOTE: md_free_ctx deprecated, Use mbedtls_md_free() instead
|
||||
memset(md_buf, 0, MAX_MD_SIZE);
|
||||
return rv;
|
||||
|
||||
mbedtls_md_free(&c);
|
||||
return nkey;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -794,14 +677,17 @@ cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
|
||||
}
|
||||
#endif
|
||||
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
|
||||
const cipher_kt_t *cipher = get_cipher_type(method);
|
||||
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
ctx->evp = EVP_CIPHER_CTX_new();
|
||||
cipher_evp_t *evp = ctx->evp;
|
||||
|
||||
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);
|
||||
@@ -815,6 +701,9 @@ cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
|
||||
EVP_CIPHER_CTX_set_padding(evp, 1);
|
||||
}
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
ctx->evp = (cipher_evp_t *)ss_malloc(sizeof(cipher_evp_t));
|
||||
cipher_evp_t *evp = ctx->evp;
|
||||
|
||||
if (cipher == NULL) {
|
||||
LOGE("Cipher %s not found in PolarSSL library", ciphername);
|
||||
FATAL("Cannot initialize PolarSSL cipher");
|
||||
@@ -823,10 +712,9 @@ cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
|
||||
FATAL("Cannot initialize PolarSSL cipher context");
|
||||
}
|
||||
#elif defined(USE_CRYPTO_MBEDTLS)
|
||||
// XXX: mbedtls_cipher_setup future change
|
||||
// NOTE: Currently also clears structure. In future versions you will be required to call
|
||||
// mbedtls_cipher_init() on the structure first.
|
||||
// void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx );
|
||||
ctx->evp = (cipher_evp_t *)ss_malloc(sizeof(cipher_evp_t));
|
||||
cipher_evp_t *evp = ctx->evp;
|
||||
|
||||
if (cipher == NULL) {
|
||||
LOGE("Cipher %s not found in mbed TLS library", ciphername);
|
||||
FATAL("Cannot initialize mbed TLS cipher");
|
||||
@@ -900,7 +788,7 @@ cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len,
|
||||
}
|
||||
#endif
|
||||
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
cipher_evp_t *evp = ctx->evp;
|
||||
if (evp == NULL) {
|
||||
LOGE("cipher_context_set_iv(): Cipher context is null");
|
||||
return;
|
||||
@@ -970,15 +858,16 @@ cipher_context_release(cipher_ctx_t *ctx)
|
||||
}
|
||||
#endif
|
||||
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
EVP_CIPHER_CTX_cleanup(evp);
|
||||
EVP_CIPHER_CTX_free(ctx->evp);
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
// NOTE: cipher_free_ctx deprecated in PolarSSL 1.3.11
|
||||
cipher_free_ctx(evp);
|
||||
cipher_free_ctx(ctx->evp);
|
||||
ss_free(ctx->evp);
|
||||
#elif defined(USE_CRYPTO_MBEDTLS)
|
||||
// NOTE: cipher_free_ctx deprecated
|
||||
mbedtls_cipher_free(evp);
|
||||
mbedtls_cipher_free(ctx->evp);
|
||||
ss_free(ctx->evp);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -995,7 +884,7 @@ cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, size_t *olen,
|
||||
return (ret == kCCSuccess) ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
cipher_evp_t *evp = ctx->evp;
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
int err = 0, tlen = *olen;
|
||||
err = EVP_CipherUpdate(evp, (uint8_t *)output, &tlen,
|
||||
@@ -1381,12 +1270,11 @@ enc_key_init(int method, const char *pass)
|
||||
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#else
|
||||
cipher_kt_t cipher_info;
|
||||
#endif
|
||||
|
||||
uint8_t iv[MAX_IV_LENGTH];
|
||||
|
||||
cipher_kt_t *cipher;
|
||||
cipher_kt_t cipher_info;
|
||||
cipher_t cipher;
|
||||
|
||||
// Initialize sodium for random generator
|
||||
if (sodium_init() == -1) {
|
||||
@@ -1394,35 +1282,35 @@ enc_key_init(int method, const char *pass)
|
||||
}
|
||||
|
||||
if (method == SALSA20 || method == CHACHA20 || method == CHACHA20IETF) {
|
||||
// Fake cipher
|
||||
cipher = (cipher_kt_t *)&cipher_info;
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
cipher->key_len = supported_ciphers_key_size[method];
|
||||
cipher->iv_len = supported_ciphers_iv_size[method];
|
||||
cipher.key_len = supported_ciphers_key_size[method];
|
||||
cipher.iv_len = supported_ciphers_iv_size[method];
|
||||
#endif
|
||||
#if defined(USE_CRYPTO_POLARSSL)
|
||||
cipher->base = NULL;
|
||||
cipher->key_length = supported_ciphers_key_size[method] * 8;
|
||||
cipher->iv_size = supported_ciphers_iv_size[method];
|
||||
cipher.info = &cipher_info;
|
||||
cipher.info->base = NULL;
|
||||
cipher.info->key_length = supported_ciphers_key_size[method] * 8;
|
||||
cipher.info->iv_size = supported_ciphers_iv_size[method];
|
||||
#endif
|
||||
#if defined(USE_CRYPTO_MBEDTLS)
|
||||
// XXX: key_length changed to key_bitlen in mbed TLS 2.0.0
|
||||
cipher->base = NULL;
|
||||
cipher->key_bitlen = supported_ciphers_key_size[method] * 8;
|
||||
cipher->iv_size = supported_ciphers_iv_size[method];
|
||||
cipher.info = &cipher_info;
|
||||
cipher.info->base = NULL;
|
||||
cipher.info->key_bitlen = supported_ciphers_key_size[method] * 8;
|
||||
cipher.info->iv_size = supported_ciphers_iv_size[method];
|
||||
#endif
|
||||
} else {
|
||||
cipher = (cipher_kt_t *)get_cipher_type(method);
|
||||
cipher.info = (cipher_kt_t *)get_cipher_type(method);
|
||||
}
|
||||
|
||||
if (cipher == NULL) {
|
||||
if (cipher.info == NULL) {
|
||||
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 = (cipher_kt_t *)&cipher_info;
|
||||
cipher.info = (cipher_kt_t *)&cipher_info;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -1432,7 +1320,7 @@ enc_key_init(int method, const char *pass)
|
||||
cipher_info.base = NULL;
|
||||
cipher_info.key_bitlen = supported_ciphers_key_size[method] * 8;
|
||||
cipher_info.iv_size = supported_ciphers_iv_size[method];
|
||||
cipher = (cipher_kt_t *)&cipher_info;
|
||||
cipher.info = (cipher_kt_t *)&cipher_info;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -1447,14 +1335,15 @@ enc_key_init(int method, const char *pass)
|
||||
FATAL("MD5 Digest not found in crypto library");
|
||||
}
|
||||
|
||||
enc_key_len = bytes_to_key(cipher, md, (const uint8_t *)pass, enc_key, iv);
|
||||
enc_key_len = bytes_to_key(&cipher, md, (const uint8_t *)pass, enc_key);
|
||||
|
||||
if (enc_key_len == 0) {
|
||||
FATAL("Cannot generate key and IV");
|
||||
}
|
||||
if (method == RC4_MD5) {
|
||||
enc_iv_len = 16;
|
||||
} else {
|
||||
enc_iv_len = cipher_iv_size(cipher);
|
||||
enc_iv_len = cipher_iv_size(&cipher);
|
||||
}
|
||||
enc_method = method;
|
||||
}
|
||||
|
||||
+7
-1
@@ -105,13 +105,19 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
cipher_evp_t evp;
|
||||
cipher_evp_t *evp;
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t cc;
|
||||
#endif
|
||||
uint8_t iv[MAX_IV_LENGTH];
|
||||
} cipher_ctx_t;
|
||||
|
||||
typedef struct {
|
||||
cipher_kt_t *info;
|
||||
size_t iv_len;
|
||||
size_t key_len;
|
||||
} cipher_t;
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif HAVE_INTTYPES_H
|
||||
|
||||
Reference in New Issue
Block a user