From a0d773ca892c4f4db16fe81c9871797dacedaa08 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Sat, 13 Dec 2014 09:42:59 +0800 Subject: [PATCH] refine the sodium support --- src/encrypt.c | 174 ++++++++++++++++++++++++++++++++++++++++---------- src/encrypt.h | 15 ++++- 2 files changed, 151 insertions(+), 38 deletions(-) diff --git a/src/encrypt.c b/src/encrypt.c index 8055a344..477a4feb 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -20,12 +20,12 @@ * . */ +#include + #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include - #if defined(USE_CRYPTO_OPENSSL) #include @@ -49,6 +49,10 @@ #endif +#ifdef HAVE_SODIUM_H +#include +#endif + #include "encrypt.h" #include "utils.h" @@ -57,7 +61,6 @@ static uint8_t *enc_table; static uint8_t *dec_table; static uint8_t enc_key[MAX_KEY_LENGTH]; -static uint8_t enc_iv[MAX_IV_LENGTH]; static int enc_key_len; static int enc_iv_len; static int enc_method; @@ -90,9 +93,11 @@ static const char * supported_ciphers[CIPHER_NUM] = "des-cfb", "idea-cfb", "rc2-cfb", - "seed-cfb", - "salsa20", - "chacha20" + "seed-cfb" +#ifdef HAVE_SODIUM_H + ,"salsa20" + ,"chacha20" +#endif }; #ifdef USE_CRYPTO_POLARSSL @@ -112,9 +117,11 @@ static const char * supported_ciphers_polarssl[CIPHER_NUM] = CIPHER_UNSUPPORTED, CIPHER_UNSUPPORTED, CIPHER_UNSUPPORTED, - CIPHER_UNSUPPORTED, - "salsa20", - "chacha20" + CIPHER_UNSUPPORTED +#ifdef HAVE_SODIUM_H + ,"salsa20" + ,"chacha20" +#endif }; #endif @@ -142,15 +149,38 @@ static const CCAlgorithm supported_ciphers_applecc[CIPHER_NUM] = #endif +#if defined(HAVE_SODIUM_H) || (defined(USE_CRYPTO_POLARSSL) && defined(USE_CRYPTO_APPLECC)) static const int supported_ciphers_iv_size[CIPHER_NUM] = { - 0, 0, 16, 16, 16, 16, 8, 16, 16, 16, 8, 8, 8, 8, 16, 8, 8 + 0, 0, 16, 16, 16, 16, 8, 16, 16, 16, 8, 8, 8, 8, 16 +#ifdef HAVE_SODIUM_H + , 8, 8 +#endif }; static const int supported_ciphers_key_size[CIPHER_NUM] = { - 0, 16, 16, 16, 24, 32, 16, 16, 24, 32, 16, 8, 16, 16, 16, 32, 32 + 0, 16, 16, 16, 24, 32, 16, 16, 24, 32, 16, 8, 16, 16, 16 +#ifdef HAVE_SODIUM_H + , 32, 32 +#endif }; +#endif + +#ifdef HAVE_SODIUM_H +static int crypto_stream_xor_ic(uint8_t *c, const uint8_t *m, uint64_t mlen, + const uint8_t *n, uint64_t ic, const uint8_t *k, int method) +{ + switch (method) { + case SALSA20: + crypto_stream_salsa20_xor_ic(c, m, mlen, n, ic, k); + break; + case CHACHA20: + crypto_stream_chacha20_xor_ic(c, m, mlen, n, ic, k); + break; + } +} +#endif static int random_compare(const void *_x, const void *_y, uint32_t i, uint64_t a) @@ -477,6 +507,12 @@ const cipher_kt_t *get_cipher_type(int method) method = RC4; } +#ifdef HAVE_SODIUM_H + if (method >= SALSA20) { + return NULL; + } +#endif + const char *ciphername = supported_ciphers[method]; #if defined(USE_CRYPTO_OPENSSL) return EVP_get_cipherbyname(ciphername); @@ -512,10 +548,12 @@ void cipher_context_init(cipher_ctx_t *ctx, int method, int enc) return; } +#ifdef HAVE_SODIUM_H if (method >= SALSA20) { enc_iv_len = supported_ciphers_iv_size[method]; return; } +#endif const char *ciphername = supported_ciphers[method]; #if defined(USE_CRYPTO_APPLECC) @@ -582,9 +620,12 @@ void cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len, rand_bytes(iv, iv_len); } +#ifdef HAVE_SODIUM_H if (enc_method >= SALSA20) { + memcpy(ctx->iv, iv, iv_len); return; } +#endif if (enc_method == RC4_MD5) { unsigned char key_iv[32]; @@ -715,7 +756,7 @@ char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method) cipher_ctx_t evp; cipher_context_init(&evp, method, 1); - int c_len = *len; + int p_len = *len, c_len = *len; int iv_len = enc_iv_len; int err = 0; char *ciphertext = malloc(max(iv_len + c_len, buf_size)); @@ -724,8 +765,18 @@ char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method) cipher_context_set_iv(&evp, iv, iv_len, 1); memcpy(ciphertext, iv, iv_len); - err = cipher_context_update(&evp, (uint8_t *)(ciphertext + iv_len), - &c_len, (const uint8_t *)plaintext, *len); +#ifdef HAVE_SODIUM_H + if (method >= SALSA20) { + err = crypto_stream_xor_ic((uint8_t *)(ciphertext + iv_len), + (const uint8_t *)plaintext, (uint64_t)p_len, (const uint8_t *)iv, + 0, enc_key, method); + } else { +#endif + err = cipher_context_update(&evp, (uint8_t *)(ciphertext + iv_len), + &c_len, (const uint8_t *)plaintext, p_len); +#ifdef HAVE_SODIUM_H + } +#endif if (!err) { free(ciphertext); @@ -760,7 +811,7 @@ char * ss_encrypt(int buf_size, char *plaintext, ssize_t *len, { if (ctx != NULL) { int iv_len = 0; - int c_len = *len; + int p_len = *len, c_len = *len; if (!ctx->init) { iv_len = enc_iv_len; } @@ -772,36 +823,46 @@ char * ss_encrypt(int buf_size, char *plaintext, ssize_t *len, uint8_t iv[MAX_IV_LENGTH]; cipher_context_set_iv(&ctx->evp, iv, iv_len, 1); memcpy(ciphertext, iv, iv_len); - memcpy(enc_iv, iv, iv_len); +#ifdef HAVE_SODIUM_H ctx->counter = 0; +#endif ctx->init = 1; } +#ifdef HAVE_SODIUM_H if (enc_method >= SALSA20) { int padding = ctx->counter % SODIUM_BLOCK_SIZE; if (buf_len < iv_len + padding + c_len) { - buf_len= max(iv_len + padding + c_len, buf_size); + buf_len= max(iv_len + (padding + c_len) * 2, buf_size); ciphertext = realloc(buf_len); } if (padding) { - memset(ciphertext + iv_len, 0, padding); + plaintext = realloc(p_len + padding); + memmove(plaintext + padding, plaintext, p_len); + memset(plaintext, 0, padding); + } + err = crypto_stream_xor_ic((uint8_t *)(ciphertext + iv_len), + (const uint8_t *)plaintext, (uint64_t)p_len, (const uint8_t *)ctx->evp->iv, + ctx->counter / SODIUM_BLOCK_SIZE, enc_key, method); + ctx->counter += p_len; + if (padding) { + memmove(ciphertext + iv_len, ciphertext + iv_len + padding, c_len); } - crypto_stream_salsa20_xor_ic((uint8_t *)(ciphertext + iv_len), (const uint8_t *)plaintext, - c_len, (const uint8_t *)enc_iv, ctx->counter, enc_key); - ctx->counter += *len; - memmove(ciphertext + iv_len, ciphertext + iv_len + padding, c_len); } else { +#endif int err = cipher_context_update(&ctx->evp, (uint8_t *)(ciphertext + iv_len), - &c_len, (const uint8_t *)plaintext, *len); + &c_len, (const uint8_t *)plaintext, p_len); if (!err) { free(ciphertext); free(plaintext); return NULL; } +#ifdef HAVE_SODIUM_H } +#endif #ifdef DEBUG - dump("PLAIN", plaintext, *len); + dump("PLAIN", plaintext, p_len); dump("CIPHER", ciphertext + iv_len, c_len); #endif @@ -824,7 +885,7 @@ char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method) cipher_ctx_t evp; cipher_context_init(&evp, method, 0); - int p_len = *len; + int c_len = *len, p_len = *len; int iv_len = enc_iv_len; int err = 0; char *plaintext = malloc(max(p_len, buf_size)); @@ -833,9 +894,20 @@ char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method) memcpy(iv, ciphertext, iv_len); cipher_context_set_iv(&evp, iv, iv_len, 0); - err = cipher_context_update(&evp, (uint8_t *)plaintext, &p_len, - (const uint8_t *)(ciphertext + iv_len), - *len - iv_len); +#ifdef HAVE_SODIUM_H + if (method >= SALSA20) { + err = crypto_stream_xor_ic((uint8_t *)plaintext, + (const uint8_t *)(ciphertext + iv_len), (uint64_t)(c_len - iv_len), + (const uint8_t *)iv, 0, enc_key, method); + } else { +#endif + err = cipher_context_update(&evp, (uint8_t *)plaintext, &p_len, + (const uint8_t *)(ciphertext + iv_len), + c_len - iv_len); +#ifdef HAVE_SODIUM_H + } +#endif + if (!err) { free(ciphertext); free(plaintext); @@ -845,7 +917,7 @@ char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method) #ifdef DEBUG dump("PLAIN", plaintext, p_len); - dump("CIPHER", ciphertext + iv_len, *len - iv_len); + dump("CIPHER", ciphertext + iv_len, c_len - iv_len); #endif *len = p_len; @@ -866,22 +938,50 @@ char * ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, struct enc_ctx *ctx) { if (ctx != NULL) { - int p_len = *len; + int c_len = *len, p_len = *len; int iv_len = 0; int err = 0; - char *plaintext = malloc(max(p_len, buf_size)); + int buf_len = max(p_len, buf_size); + char *plaintext = malloc(buf_len); if (!ctx->init) { uint8_t iv[MAX_IV_LENGTH]; iv_len = enc_iv_len; + p_len -= iv_len; memcpy(iv, ciphertext, iv_len); cipher_context_set_iv(&ctx->evp, iv, iv_len, 0); +#ifdef HAVE_SODIUM_H + ctx->counter = 0; +#endif ctx->init = 1; } - err = cipher_context_update(&ctx->evp, (uint8_t *)plaintext, &p_len, - (const uint8_t *)(ciphertext + iv_len), - *len - iv_len); +#ifdef HAVE_SODIUM_H + if (enc_method >= SALSA20) { + int padding = ctx->counter % SODIUM_BLOCK_SIZE; + if (buf_len < p_len + padding) { + buf_len= max((p_len + padding) * 2, buf_size); + plaintext = realloc(buf_len); + } + if (padding) { + ciphertext = realloc(max(c_len + padding, buf_size)); + memset(ciphertext + iv_len, 0, padding); + } + err = crypto_stream_xor_ic((uint8_t *)plaintext, + (const uint8_t *)(ciphertext + iv_len), (uint64_t)(c_len - iv_len), + (const uint8_t *)ctx->evp->iv, ctx->counter / SODIUM_BLOCK_SIZE, enc_key, method); + ctx->counter += c_len - iv_len; + if (padding) { + memmove(plaintext, plaintext + padding, p_len); + } + } else { +#endif + err = cipher_context_update(&ctx->evp, (uint8_t *)plaintext, &p_len, + (const uint8_t *)(ciphertext + iv_len), + c_len - iv_len); +#ifdef HAVE_SODIUM_H + } +#endif if (!err) { free(ciphertext); @@ -891,7 +991,7 @@ char * ss_decrypt(int buf_size, char *ciphertext, ssize_t *len, #ifdef DEBUG dump("PLAIN", plaintext, p_len); - dump("CIPHER", ciphertext + iv_len, *len - iv_len); + dump("CIPHER", ciphertext + iv_len, c_len - iv_len); #endif *len = p_len; @@ -932,6 +1032,7 @@ void enc_key_init(int method, const char *pass) cipher_kt_t *cipher; +#ifdef HAVE_SODIUM_H if (method == SALSA20 || method == CHACHA20) { if (sodium_init() == -1) { FATAL("Failed to initialize sodium"); @@ -948,8 +1049,11 @@ void enc_key_init(int method, const char *pass) cipher->iv_size = supported_ciphers_iv_size[method]; #endif } else { +#endif cipher = (cipher_kt_t *) get_cipher_type(method); +#ifdef HAVE_SODIUM_H } +#endif if (cipher == NULL) { do { diff --git a/src/encrypt.h b/src/encrypt.h index b444259a..fc707272 100644 --- a/src/encrypt.h +++ b/src/encrypt.h @@ -23,8 +23,6 @@ #ifndef _ENCRYPT_H #define _ENCRYPT_H -#include "config.h" - #ifndef __MINGW32__ #include #else @@ -94,6 +92,9 @@ typedef struct { #ifdef USE_CRYPTO_APPLECC cipher_cc_t cc; #endif +#if HAVE_SODIUM_H + uint8_t iv[MAX_IV_LENGTH]; +#endif } cipher_ctx_t; #ifdef HAVE_STDINT_H @@ -102,9 +103,13 @@ typedef struct { #include #endif +#if HAVE_SODIUM_H #define SODIUM_BLOCK_SIZE 64 - #define CIPHER_NUM 17 +#else +#define CIPHER_NUM 15 +#endif + #define NONE -1 #define TABLE 0 #define RC4 1 @@ -121,15 +126,19 @@ typedef struct { #define IDEA_CFB 12 #define RC2_CFB 13 #define SEED_CFB 14 +#ifdef HAVE_SODIUM_H #define SALSA20 15 #define CHACHA20 16 +#endif #define min(a, b) (((a) < (b)) ? (a) : (b)) #define max(a, b) (((a) > (b)) ? (a) : (b)) struct enc_ctx { uint8_t init; +#if HAVE_SODIUM_H uint64_t counter; +#endif cipher_ctx_t evp; };