Browse Source

WIP: almost there

pull/4/head
Max Lv 12 years ago
parent
commit
2f175d7028
5 changed files with 93 additions and 59 deletions
  1. 110
      src/encrypt.c
  2. 12
      src/encrypt.h
  3. 8
      src/local.c
  4. 8
      src/redir.c
  5. 14
      src/server.c

110
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((constn> <span class="n">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 = strdupn><span class="p">(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;

12
src/encrypt.h

@ -16,7 +16,7 @@
#include <inttypes.h>
#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);

8
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);

8
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);

14
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);

Loading…
Cancel
Save