From 2f175d70284b0cebb163a945f00fc008eb493bf7 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Thu, 23 May 2013 13:54:39 +0800 Subject: [PATCH] WIP: almost there --- src/encrypt.c | 110 +++++++++++++++++++++++++++++++++----------------- src/encrypt.h | 12 ++++-- src/local.c | 8 ++-- src/redir.c | 8 ++-- src/server.c | 14 +++---- 5 files changed, 93 insertions(+), 59 deletions(-) diff --git a/src/encrypt.c b/src/encrypt.c index 81d71941..f3741824 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -10,11 +10,23 @@ #define OFFSET_ROL(p, o) ((uint64_t)(*(p + o)) << (8 * o)) -static char *enc_table; -static char *dec_table; -static char *pass; +static uint8_t *enc_table; +static uint8_t *dec_table; +static char *enc_pass; + +#ifdef DEBUG +static dump(char *tag, char *text) { + int i, len; + len = strlen(text); + printf("%s: ", tag); + for (i = 0; i < len; i++) { + printf("0x%02x ", (uint8_t)text[i]); + } + printf("\n"); +} +#endif -static char* supported_ciphers[8] = { +static const char* supported_ciphers[8] = { "table", "rc4", "aes-128-cfb", @@ -106,7 +118,7 @@ void enc_table_init(const char *pass) { enc_table = malloc(256); dec_table = malloc(256); - digest = MD5((const uint8_t *)key, strlen((const uint8_t *)key), NULL); + digest = MD5((const uint8_t *)pass, strlen(pass), NULL); for (i = 0; i < 8; i++) { key += OFFSET_ROL(digest, i); @@ -125,22 +137,32 @@ void enc_table_init(const char *pass) { } } -char* encrypt(char *plaintext, int *len, struct enc_ctx *ctx) { +char* encrypt(char *plaintext, ssize_t *len, struct enc_ctx *ctx) { if (ctx != NULL) { int c_len = *len + BLOCK_SIZE; - uint8_t *ciphertext; + char *ciphertext; int iv_len = 0; if (ctx->method > RC4) { - iv_len += strlen(ctx->iv); - ciphertext = malloc(iv_len + c_len); - strcpy(ciphertext, ctx->iv); + iv_len += strlen((const char *)ctx->iv); + ciphertext = malloc(max(iv_len + c_len, BUF_SIZE)); + memcpy(ciphertext, ctx->iv, iv_len); ctx->method = NONE; +#ifdef DEBUG + dump("IV", ctx->iv); +#endif } else { - ciphertext = malloc(c_len); + ciphertext = malloc(max(c_len, BUF_SIZE)); } - EVP_EncryptUpdate(ctx->evp, ciphertext + iv_len, &c_len, plaintext, *len); + EVP_EncryptUpdate(&ctx->evp, (uint8_t*)(ciphertext+iv_len), + &c_len, (const uint8_t *)plaintext, *len); + +#ifdef DEBUG + dump("PLAIN", plaintext); + dump("CIPHER", ciphertext); +#endif + *len = iv_len + c_len; free(plaintext); return ciphertext; @@ -154,20 +176,30 @@ char* encrypt(char *plaintext, int *len, struct enc_ctx *ctx) { } } -char* decrypt(char *ciphertext, int *len, struct enc_ctx *ctx) { +char* decrypt(char *ciphertext, ssize_t *len, struct enc_ctx *ctx) { if (ctx != NULL) { int p_len = *len + BLOCK_SIZE; - uint8_t *plaintext = malloc(p_len); + char *plaintext = malloc(max(p_len, BUF_SIZE)); int iv_len = 0; if (ctx->method > RC4) { - iv_len = strlen(ctx->iv); + iv_len = strlen((const char *)ctx->iv); memcpy(ctx->iv, ciphertext, iv_len); + EVP_CipherInit_ex(&ctx->evp, NULL, NULL, ctx->key, ctx->iv, 0); ctx->method = NONE; +#ifdef DEBUG + dump("IV", ctx->iv); +#endif } - EVP_DecryptUpdate(ctx->evp, plaintext, &p_len, - (uint8_t*)(ciphertext + iv_len), *len - iv_len); + EVP_DecryptUpdate(&ctx->evp, (uint8_t*)plaintext, &p_len, + (const uint8_t*)(ciphertext + iv_len), *len - iv_len); + +#ifdef DEBUG + dump("PLAIN", plaintext); + dump("CIPHER", ciphertext); +#endif + *len = p_len; free(ciphertext); return plaintext; @@ -182,38 +214,42 @@ char* decrypt(char *ciphertext, int *len, struct enc_ctx *ctx) { } void enc_ctx_init(int method, struct enc_ctx *ctx, int enc) { - uint8_t key[EVP_MAX_KEY_LENGTH] = {0}; - uint8_t iv[EVP_MAX_IV_LENGTH] = {0}; - int key_len, i; - - EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]); - key_len = EVP_BytesToKey(cipher, EVP_md5(), NULL, (uint8_t *)pass, - strlen(pass), 1, key, iv); - - EVP_CIPHER_CTX_init(ctx->evp); - EVP_CipherInit_ex(ctx->evp, cipher, NULL, NULL, NULL, enc); - if (!EVP_CIPHER_CTX_set_key_length(ctx->evp, key_len)) { - EVP_CIPHER_CTX_cleanup(ctx->evp); + uint8_t *key = ctx->key; + uint8_t *iv = ctx->iv; + int key_len, iv_len, i; + + memset(ctx, 0, sizeof(struct enc_ctx)); + + EVP_CIPHER_CTX *evp = &ctx->evp; + OpenSSL_add_all_algorithms(); + const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]); + + key_len = EVP_BytesToKey(cipher, EVP_md5(), NULL, (uint8_t *)enc_pass, + strlen(enc_pass), 1, key, iv); + + EVP_CIPHER_CTX_init(evp); + EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc); + if (!EVP_CIPHER_CTX_set_key_length(evp, key_len)) { + EVP_CIPHER_CTX_cleanup(evp); LOGE("Invalid key length: %d", key_len); exit(EXIT_FAILURE); } - EVP_CIPHER_CTX_set_padding(ctx->evp, 1); + EVP_CIPHER_CTX_set_padding(evp, 1); if (enc) { - EVP_CipherInit_ex(ctx->evp, NULL, NULL, key, iv, enc); + for (i = 0; i < strlen((const char*)iv); i++) { + iv[i] = rand() % 256; + } + EVP_CipherInit_ex(evp, NULL, NULL, key, iv, enc); } - memset(ctx->iv, 0, strlen(iv)); - for (i = 0; i < strlen(iv); i++) { - ctx->iv[i] = rand() % 256; - } ctx->method = method; } int enc_init(const char *pass, const char *method) { - pass = pass; + enc_pass = strdup(pass); if (method == NULL || strcmp(method, "table") == 0) { - enc_table_init(pass); + enc_table_init(enc_pass); return TABLE; } else if (strcmp(method, "aes-128-cfb") == 0) { return AES_128_CFB; diff --git a/src/encrypt.h b/src/encrypt.h index c6c06422..27ada5ec 100644 --- a/src/encrypt.h +++ b/src/encrypt.h @@ -16,7 +16,7 @@ #include #endif -#define BUF_SIZE 4096 +#define BUF_SIZE 512 #define BLOCK_SIZE 32 #define NONE -1 @@ -29,14 +29,18 @@ #define CAST5_CFB 6 #define DES_CFB 7 +#define min(a,b) (((a)<(b))?(a):(b)) +#define max(a,b) (((a)>(b))?(a):(b)) + struct enc_ctx { int method; + uint8_t key[EVP_MAX_KEY_LENGTH]; uint8_t iv[EVP_MAX_IV_LENGTH]; - EVP_CIPHER_CTX *evp; + EVP_CIPHER_CTX evp; }; -char* encrypt(char *plaintext, int *len, struct enc_ctx *ctx); -char* decrypt(char *ciphertext, int *len, struct enc_ctx *ctx); +char* encrypt(char *plaintext, ssize_t *len, struct enc_ctx *ctx); +char* decrypt(char *ciphertext, ssize_t *len, struct enc_ctx *ctx); void enc_ctx_init(int method, struct enc_ctx *ctx, int enc); int enc_init(const char *pass, const char *method); diff --git a/src/local.c b/src/local.c index d2e48ee6..767f3e50 100644 --- a/src/local.c +++ b/src/local.c @@ -36,8 +36,6 @@ #define EWOULDBLOCK EAGAIN #endif -#define min(a,b) (((a)<(b))?(a):(b)) - int setnonblocking(int fd) { int flags; if (-1 ==(flags = fcntl(fd, F_GETFL, 0))) @@ -189,7 +187,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { } char *addr_to_send = malloc(BUF_SIZE); - uint8_t addr_len = 0; + ssize_t addr_len = 0; addr_to_send[addr_len++] = request->atyp; // get remote addr and port @@ -519,11 +517,11 @@ void free_server(struct server *server) { server->remote->server = NULL; } if (server->e_ctx != NULL) { - EVP_CIPHER_CTX_cleanup(server->e_ctx->evp); + EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp); free(server->e_ctx); } if (server->d_ctx != NULL) { - EVP_CIPHER_CTX_cleanup(server->d_ctx->evp); + EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); free(server->d_ctx); } free(server->buf); diff --git a/src/redir.c b/src/redir.c index beb0aeed..9677f2ea 100644 --- a/src/redir.c +++ b/src/redir.c @@ -31,8 +31,6 @@ #define EWOULDBLOCK EAGAIN #endif -#define min(a,b) (((a)<(b))?(a):(b)) - int getdestaddr(int fd, struct sockaddr_in *destaddr) { socklen_t socklen = sizeof(*destaddr); int error; @@ -296,7 +294,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { // send destaddr char *addr_to_send = malloc(BUF_SIZE); - uint8_t addr_len = 0; + ssize_t addr_len = 0; addr_to_send[addr_len++] = 1; // handle IP V4 only @@ -442,11 +440,11 @@ void free_server(struct server *server) { server->remote->server = NULL; } if (server->e_ctx != NULL) { - EVP_CIPHER_CTX_cleanup(server->e_ctx->evp); + EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp); free(server->e_ctx); } if (server->d_ctx != NULL) { - EVP_CIPHER_CTX_cleanup(server->d_ctx->evp); + EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); free(server->d_ctx); } free(server->buf); diff --git a/src/server.c b/src/server.c index 27ef5d16..059a704b 100644 --- a/src/server.c +++ b/src/server.c @@ -35,8 +35,6 @@ #define EWOULDBLOCK EAGAIN #endif -#define min(a,b) (((a)<(b))?(a):(b)) - static int verbose = 0; static int remote_conn = 0; static int server_conn = 0; @@ -142,16 +140,16 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { struct server *server = server_recv_ctx->server; struct remote *remote = NULL; - char *buf = server->buf; + char **buf = &server->buf; ev_timer_again(EV_A_ &server->recv_ctx->watcher); if (server->stage != 0) { remote = server->remote; - buf = remote->buf; + buf = &remote->buf; } - ssize_t r = recv(server->fd, buf, BUF_SIZE, 0); + ssize_t r = recv(server->fd, *buf, BUF_SIZE, 0); if (r == 0) { // connection closed @@ -174,7 +172,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { } } - buf = decrypt(buf, &r, server->d_ctx); + *buf = decrypt(*buf, &r, server->d_ctx); // handshake and transmit data if (server->stage == 5) { @@ -678,11 +676,11 @@ void free_server(struct server *server) { server->remote->server = NULL; } if (server->e_ctx != NULL) { - EVP_CIPHER_CTX_cleanup(server->e_ctx->evp); + EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp); free(server->e_ctx); } if (server->d_ctx != NULL) { - EVP_CIPHER_CTX_cleanup(server->d_ctx->evp); + EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); free(server->d_ctx); } free(server->buf);