Browse Source

Fix #928

pull/936/head
Max Lv 8 years ago
parent
commit
b43a715301
2 changed files with 121 additions and 226 deletions
  1. 339
      src/encrypt.c
  2. 8
      src/encrypt.h

339
src/encrypt.c

@ -433,33 +433,33 @@ enc_table_init(const char *pass)
} }
int int
cipher_iv_size(const cipher_kt_t *cipher)
cipher_iv_size(const cipher_t *cipher)
{ {
#if defined(USE_CRYPTO_OPENSSL) #if defined(USE_CRYPTO_OPENSSL)
return EVP_CIPHER_iv_length(cipher);
return cipher->iv_len;
#elif defined(USE_CRYPTO_POLARSSL) || defined(USE_CRYPTO_MBEDTLS) #elif defined(USE_CRYPTO_POLARSSL) || defined(USE_CRYPTO_MBEDTLS)
if (cipher == NULL) { if (cipher == NULL) {
return 0; return 0;
} }
return cipher->iv_size;
return cipher->info->iv_size;
#endif #endif
} }
int int
cipher_key_size(const cipher_kt_t *cipher)
cipher_key_size(const cipher_t *cipher)
{ {
#if defined(USE_CRYPTO_OPENSSL) #if defined(USE_CRYPTO_OPENSSL)
return EVP_CIPHER_key_length(cipher);
return cipher->key_len;
#elif defined(USE_CRYPTO_POLARSSL) #elif defined(USE_CRYPTO_POLARSSL)
if (cipher == NULL) { if (cipher == NULL) {
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 (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 128 / 8;
} }
return cipher->key_length / 8;
return cipher->info->key_length / 8;
#elif defined(USE_CRYPTO_MBEDTLS) #elif defined(USE_CRYPTO_MBEDTLS)
/* /*
* Semi-API changes (technically public, morally private) * Semi-API changes (technically public, morally private)
@ -473,224 +473,107 @@ cipher_key_size(const cipher_kt_t *cipher)
return 0; return 0;
} }
/* From Version 1.2.7 released 2013-04-13 Default Blowfish keysize is now 128-bits */ /* 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 #endif
} }
int 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; size_t datal;
datal = strlen((const char *)pass); datal = strlen((const char *)pass);
#if defined(USE_CRYPTO_OPENSSL) #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;
MD5_CTX c;
unsigned char md_buf[MAX_MD_SIZE]; unsigned char md_buf[MAX_MD_SIZE];
int niv;
int nkey; int nkey;
int addmd; int addmd;
unsigned int mds;
unsigned int i;
int rv;
unsigned int i, j, mds;
mds = 16;
nkey = cipher_key_size(cipher); nkey = cipher_key_size(cipher);
niv = cipher_iv_size(cipher);
rv = nkey;
if (pass == NULL) {
return nkey;
}
if (pass == NULL) return nkey;
memset(&c, 0, sizeof(MD5_CTX));
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;
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);
i = 0;
if (nkey) {
for (;;) {
if (nkey == 0) {
break;
}
if (i == mds) {
break;
}
if (key != NULL) {
*(key++) = md_buf[i];
}
nkey--;
i++;
}
for (i = 0; i < mds; i++, j++) {
if (j >= nkey) break;
key[j] = md_buf[i];
} }
if (niv && (i != mds)) {
for (;;) {
if (niv == 0) {
break;
}
if (i == mds) {
break;
}
if (iv != NULL) {
*(iv++) = md_buf[i];
}
niv--;
i++;
}
}
return nkey;
#elif defined(USE_CRYPTO_POLARSSL)
md_context_t c;
unsigned char md_buf[MAX_MD_SIZE];
int nkey;
int addmd;
unsigned int i, j, mds;
nkey = cipher_key_size(cipher);
mds = md_get_size(md);
memset(&c, 0, sizeof(md_context_t));
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 ((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); md_free_ctx(&c);
memset(md_buf, 0, MAX_MD_SIZE);
return rv;
return nkey;
#elif defined(USE_CRYPTO_MBEDTLS) #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; mbedtls_md_context_t c;
unsigned char md_buf[MAX_MD_SIZE]; unsigned char md_buf[MAX_MD_SIZE];
int niv;
int nkey; int nkey;
int addmd; int addmd;
unsigned int mds;
unsigned int i;
int rv;
unsigned int i, j, mds;
nkey = cipher_key_size(cipher); 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)); 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 (niv && (i != mds)) {
for (;;) {
if (niv == 0) {
break;
}
if (i == mds) {
break;
}
if (iv != NULL) {
*(iv++) = md_buf[i];
}
niv--;
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 ((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 #endif
} }
@ -794,14 +677,17 @@ cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
} }
#endif #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)
ctx->evp = EVP_CIPHER_CTX_new();
cipher_evp_t *evp = ctx->evp;
if (cipher == NULL) { if (cipher == NULL) {
LOGE("Cipher %s not found in OpenSSL library", ciphername); LOGE("Cipher %s not found in OpenSSL library", ciphername);
FATAL("Cannot initialize cipher"); FATAL("Cannot initialize cipher");
} }
EVP_CIPHER_CTX_init(evp);
if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc)) { if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc)) {
LOGE("Cannot initialize cipher %s", ciphername); LOGE("Cannot initialize cipher %s", ciphername);
exit(EXIT_FAILURE); 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); EVP_CIPHER_CTX_set_padding(evp, 1);
} }
#elif defined(USE_CRYPTO_POLARSSL) #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) { if (cipher == NULL) {
LOGE("Cipher %s not found in PolarSSL library", ciphername); LOGE("Cipher %s not found in PolarSSL library", ciphername);
FATAL("Cannot initialize PolarSSL cipher"); 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"); FATAL("Cannot initialize PolarSSL cipher context");
} }
#elif defined(USE_CRYPTO_MBEDTLS) #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) { if (cipher == NULL) {
LOGE("Cipher %s not found in mbed TLS library", ciphername); LOGE("Cipher %s not found in mbed TLS library", ciphername);
FATAL("Cannot initialize mbed TLS cipher"); 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 #endif
cipher_evp_t *evp = &ctx->evp;
cipher_evp_t *evp = ctx->evp;
if (evp == NULL) { if (evp == NULL) {
LOGE("cipher_context_set_iv(): Cipher context is null"); LOGE("cipher_context_set_iv(): Cipher context is null");
return; return;
@ -970,15 +858,16 @@ cipher_context_release(cipher_ctx_t *ctx)
} }
#endif #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_free(ctx->evp);
#elif defined(USE_CRYPTO_POLARSSL) #elif defined(USE_CRYPTO_POLARSSL)
// NOTE: cipher_free_ctx deprecated in PolarSSL 1.3.11 // 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) #elif defined(USE_CRYPTO_MBEDTLS)
// NOTE: cipher_free_ctx deprecated // NOTE: cipher_free_ctx deprecated
mbedtls_cipher_free(evp);
mbedtls_cipher_free(ctx->evp);
ss_free(ctx->evp);
#endif #endif
} }
@ -995,7 +884,7 @@ cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, size_t *olen,
return (ret == kCCSuccess) ? 1 : 0; return (ret == kCCSuccess) ? 1 : 0;
} }
#endif #endif
cipher_evp_t *evp = &ctx->evp;
cipher_evp_t *evp = ctx->evp;
#if defined(USE_CRYPTO_OPENSSL) #if defined(USE_CRYPTO_OPENSSL)
int err = 0, tlen = *olen; int err = 0, tlen = *olen;
err = EVP_CipherUpdate(evp, (uint8_t *)output, &tlen, 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) #if defined(USE_CRYPTO_OPENSSL)
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
#else
cipher_kt_t cipher_info;
#endif #endif
uint8_t iv[MAX_IV_LENGTH];
cipher_kt_t *cipher;
cipher_kt_t cipher_info;
cipher_t cipher;
// Initialize sodium for random generator // Initialize sodium for random generator
if (sodium_init() == -1) { if (sodium_init() == -1) {
@ -1394,35 +1282,35 @@ enc_key_init(int method, const char *pass)
} }
if (method == SALSA20 || method == CHACHA20 || method == CHACHA20IETF) { if (method == SALSA20 || method == CHACHA20 || method == CHACHA20IETF) {
// Fake cipher
cipher = (cipher_kt_t *)&cipher_info;
#if defined(USE_CRYPTO_OPENSSL) #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 #endif
#if defined(USE_CRYPTO_POLARSSL) #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 #endif
#if defined(USE_CRYPTO_MBEDTLS) #if defined(USE_CRYPTO_MBEDTLS)
// XXX: key_length changed to key_bitlen in mbed TLS 2.0.0 // 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 #endif
} else { } 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 { do {
#if defined(USE_CRYPTO_POLARSSL) && defined(USE_CRYPTO_APPLECC) #if defined(USE_CRYPTO_POLARSSL) && defined(USE_CRYPTO_APPLECC)
if (supported_ciphers_applecc[method] != kCCAlgorithmInvalid) { if (supported_ciphers_applecc[method] != kCCAlgorithmInvalid) {
cipher_info.base = NULL; cipher_info.base = NULL;
cipher_info.key_length = supported_ciphers_key_size[method] * 8; cipher_info.key_length = supported_ciphers_key_size[method] * 8;
cipher_info.iv_size = supported_ciphers_iv_size[method]; cipher_info.iv_size = supported_ciphers_iv_size[method];
cipher = (cipher_kt_t *)&cipher_info;
cipher.info = (cipher_kt_t *)&cipher_info;
break; break;
} }
#endif #endif
@ -1432,7 +1320,7 @@ enc_key_init(int method, const char *pass)
cipher_info.base = NULL; cipher_info.base = NULL;
cipher_info.key_bitlen = supported_ciphers_key_size[method] * 8; cipher_info.key_bitlen = supported_ciphers_key_size[method] * 8;
cipher_info.iv_size = supported_ciphers_iv_size[method]; cipher_info.iv_size = supported_ciphers_iv_size[method];
cipher = (cipher_kt_t *)&cipher_info;
cipher.info = (cipher_kt_t *)&cipher_info;
break; break;
} }
#endif #endif
@ -1447,14 +1335,15 @@ enc_key_init(int method, const char *pass)
FATAL("MD5 Digest not found in crypto library"); 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) { if (enc_key_len == 0) {
FATAL("Cannot generate key and IV"); FATAL("Cannot generate key and IV");
} }
if (method == RC4_MD5) { if (method == RC4_MD5) {
enc_iv_len = 16; enc_iv_len = 16;
} else { } else {
enc_iv_len = cipher_iv_size(cipher);
enc_iv_len = cipher_iv_size(&cipher);
} }
enc_method = method; enc_method = method;
} }

8
src/encrypt.h

@ -105,13 +105,19 @@ typedef struct {
#endif #endif
typedef struct { typedef struct {
cipher_evp_t evp;
cipher_evp_t *evp;
#ifdef USE_CRYPTO_APPLECC #ifdef USE_CRYPTO_APPLECC
cipher_cc_t cc; cipher_cc_t cc;
#endif #endif
uint8_t iv[MAX_IV_LENGTH]; uint8_t iv[MAX_IV_LENGTH];
} cipher_ctx_t; } cipher_ctx_t;
typedef struct {
cipher_kt_t *info;
size_t iv_len;
size_t key_len;
} cipher_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