Browse Source

WIP: add aes/des and other ciphers

pull/4/head
Max Lv 11 years ago
parent
commit
2b6e884354
6 changed files with 188 additions and 265 deletions
  1. 204
      src/encrypt.c
  2. 45
      src/encrypt.h
  3. 37
      src/local.c
  4. 9
      src/local.h
  5. 103
      src/rc4.c
  6. 55
      src/rc4.h

204
src/encrypt.c

@ -8,6 +8,19 @@
#define OFFSET_ROL(p, o) ((uint64_t)(*(p + o)) << (8 * o))
static char *enc_table;
static char *dec_table;
static void* supported_ciphers = {
NULL,
EVP_rc4,
EVP_aes_128_cfb,
EVP_aes_192_cfb,
EVP_aes_256_cfb,
EVP_bf_cfb,
EVP_cast5_cvb,
EVP_des_cfb
};
static void md5(const uint8_t *text, uint8_t *digest) {
md5_state_t state;
md5_init(&state);
@ -15,16 +28,14 @@ static void md5(const uint8_t *text, uint8_t *digest) {
md5_finish(&state, digest);
}
static int random_compare(const void *_x, const void *_y) {
uint32_t i = enc_conf.ctx.table.salt;
uint64_t a = enc_conf.ctx.table.key;
static int random_compare(const void *_x, const void *_y, uint32_t i, uint64_t a) {
uint8_t x = *((uint8_t *) _x);
uint8_t y = *((uint8_t*) _y);
return (a % (x + i) - a % (y + i));
}
static void merge(uint8_t *left, int llength, uint8_t *right, int rlength)
{
static void merge(uint8_t *left, int llength, uint8_t *right,
int rlength, uint32_t salt, uint64_t key) {
uint8_t *ltmp = (uint8_t *) malloc(llength * sizeof(uint8_t));
uint8_t *rtmp = (uint8_t *) malloc(rlength * sizeof(uint8_t));
@ -37,7 +48,7 @@ static void merge(uint8_t *left, int llength, uint8_t *right, int rlength)
memcpy(rtmp, right, rlength * sizeof(uint8_t));
while (llength > 0 && rlength > 0) {
if (random_compare(ll, rr) <= 0) {
if (random_compare(ll, rr, salt, key) <= 0) {
*result = *ll;
++ll;
--llength;
@ -68,8 +79,8 @@ static void merge(uint8_t *left, int llength, uint8_t *right, int rlength)
free(rtmp);
}
static void merge_sort(uint8_t array[], int length)
{
static void merge_sort(uint8_t array[], int length,
uint32_t salt, uint64_t key) {
uint8_t middle;
uint8_t *left, *right;
int llength;
@ -84,87 +95,148 @@ static void merge_sort(uint8_t array[], int length)
left = array;
right = array + llength;
merge_sort(left, llength);
merge_sort(right, middle);
merge(left, llength, right, middle);
merge_sort(left, llength, salt, key);
merge_sort(right, middle, salt, key);
merge(left, llength, right, middle, salt, key);
}
void encrypt_ctx(char *buf, int len, struct rc4_state *ctx) {
if (ctx != NULL) {
rc4_crypt(ctx, (uint8_t*) buf, (uint8_t*) buf, len);
} else {
char *end = buf + len;
while (buf < end) {
*buf = (char)enc_conf.ctx.table.encrypt_table[(uint8_t)*buf];
buf++;
}
}
}
void decrypt_ctx(char *buf, int len, struct rc4_state *ctx) {
if (ctx != NULL) {
rc4_crypt(ctx, (uint8_t*) buf, (uint8_t*) buf, len);
} else {
char *end = buf + len;
while (buf < end) {
*buf = (char)enc_conf.ctx.table.decrypt_table[(uint8_t)*buf];
buf++;
}
}
}
void enc_ctx_init(struct rc4_state *ctx, int enc) {
uint8_t *key = enc_conf.ctx.rc4.key;
int key_len = enc_conf.ctx.rc4.key_len;
rc4_init(ctx, key, key_len);
}
static void enc_rc4_init(const char *pass) {
enc_conf.ctx.rc4.key_len = 16;
enc_conf.ctx.rc4.key = malloc(16);
md5((const uint8_t*)pass, enc_conf.ctx.rc4.key);
}
static void enc_table_init(const char *pass) {
uint8_t *enc_table = malloc(256);
uint8_t *dec_table = malloc(256);
uint8_t digest[16];
uint32_t *salt = &enc_conf.ctx.table.salt;
uint64_t *key = &enc_conf.ctx.table.key;
void enc_table_init(const char *pass) {
uint32_t i;
uint32_t salt;
uint64_t key = 0;
uint8_t digest[16];
enc_table = malloc(256);
dec_table = malloc(256);
md5((const uint8_t*)pass, digest);
*key = 0;
for (i = 0; i < 8; i++) {
*key += OFFSET_ROL(digest, i);
key += OFFSET_ROL(digest, i);
}
for(i = 0; i < 256; ++i) {
enc_table[i] = i;
}
for(i = 1; i < 1024; ++i) {
*salt = i;
merge_sort(enc_table, 256);
salt = i;
merge_sort(enc_table, 256, salt, key);
}
for(i = 0; i < 256; ++i) {
// gen decrypt table from encrypt table
dec_table[enc_table[i]] = i;
}
}
enc_conf.ctx.table.encrypt_table = enc_table;
enc_conf.ctx.table.decrypt_table = dec_table;
char* encrypt(char *plaintext, int *len, struct enc_ctx *ctx) {
if (ctx != NULL) {
/* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE
* -1 bytes */
int c_len = *len + AES_BLOCK_SIZE;
uint8_t *ciphertext;
int iv_len = 0;
if (ctx->method > RC4) {
iv_len += strlen(ctx->iv);
ciphertext = malloc(iv_len + c_len);
strcpy(ciphertext, ctx->iv);
ctx->method = NONE;
} else {
ciphertext = malloc(c_len);
}
EVP_EncryptUpdate(ctx->evp, ciphertext + iv_len, &c_len, plaintext, *len);
*len = iv_len + c_len;
free(plaintext);
return ciphertext;
} else {
char *begin = plaintext;
while (plaintext < begin + *len) {
*plaintext = (char)enc_table[(uint8_t)*plaintext];
plaintext++;
}
return begin;
}
}
char* decrypt(char *ciphertext, int *len, struct enc_ctx *ctx) {
if (ctx != NULL) {
/* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE
* -1 bytes */
int p_len = *len + AES_BLOCK_SIZE;
uint8_t *plaintext = malloc(p_len);
int iv_len = 0;
if (ctx->method > RC4) {
iv_len = strlen(ctx->iv);
memcpy(ctx->iv, ciphertext, iv_len);
ctx->method = NONE;
}
EVP_DecryptUpdate(ctx->evp, plaintext, &p_len,
(uint8_t*)(ciphertext + iv_len), *len - iv_len);
*len = p_len;
free(ciphertext);
return plaintext;
} else {
char *begin = ciphertext;
while (ciphertext < begin + *len) {
*ciphertext = (char)dec_table[(uint8_t)*ciphertext];
ciphertext++;
}
return begin;
}
}
void enc_conf_init(const char *pass, const char *method) {
enc_conf.method = TABLE;
if (method != NULL && strcmp(method, "rc4") == 0) {
enc_conf.method = RC4;
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;
EVP_CIPHER *cipher = (*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);
LOGE("Invalid key length: %d", key_len);
exit(EXIT_FAILURE);
}
EVP_CIPHER_CTX_set_padding(ctx->evp, 1);
if (enc) {
int i;
EVP_CipherInit_ex(ctx->evp, NULL, NULL, key, iv, enc);
}
memset(ctx->iv, 0, strlen(iv));
for (i = 0; i < strlen(iv); i++) {
ctx->iv[i] = rand() % 256;
}
if (enc_conf.method == TABLE) {
ctx->method = method;
}
int enc_init(const char *pass, const char *method) {
if (method == NULL || strcmp(method, "table") == 0) {
enc_table_init(pass);
} else if (enc_conf.method == RC4) {
enc_rc4_init(pass);
return TABLE;
} else if (strcmp(method, "aes-128-cfb") == 0) {
return AES_128_CFB;
} else if (strcmp(method, "aes-192-cfb") == 0) {
return AES_192_CFB;
} else if (strcmp(method, "aes-256-cfb") == 0) {
return AES_256_CFB;
} else if (strcmp(method, "bf-cfb") == 0) {
return BF_CFB;
} else if (strcmp(method, "cast5-cfb") == 0) {
return CAST5_CFB;
} else if (strcmp(method, "des-cfb") == 0) {
return DES_CFB;
} else if (strcmp(method, "rc4") == 0) {
return RC4;
}
return TABLE;
}

45
src/encrypt.h

@ -8,6 +8,8 @@
#include <stdlib.h>
#include <stdio.h>
#include <openssl/evp.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#elif HAVE_INTTYPES_H
@ -15,33 +17,28 @@
#endif
#include "md5.h"
#include "rc4.h"
#define BUF_SIZE 4096
#define TABLE 0
#define RC4 1
struct {
#define NONE -1
#define TABLE 0
#define RC4 1
#define AES_128_CFB 2
#define AES_192_CFB 3
#define AES_256_CFB 4
#define BF_CFB 5
#define CAST5_CFB 6
#define DES_CFB 7
struct enc_ctx {
int method;
union {
struct {
uint8_t *encrypt_table;
uint8_t *decrypt_table;
uint32_t salt;
uint64_t key;
} table;
struct {
uint8_t *key;
int key_len;
} rc4;
} ctx;
} enc_conf;
void encrypt_ctx(char *buf, int len, struct rc4_state *ctx);
void decrypt_ctx(char *buf, int len, struct rc4_state *ctx);
void enc_ctx_init(struct rc4_state *ctx, int enc);
void enc_conf_init(const char *pass, const char *method);
uint8_t iv[EVP_MAX_IV_LENGTH];
EVP_CIPHER_CTX *evp;
};
char* encrypt(char *buf, int len, EVP_CIPHER_CTX *ctx);
char* decrypt(char *buf, int len, EVP_CIPHER_CTX *ctx);
void enc_ctx_init(int method, struct enc_ctx *ctx, int enc);
int enc_init(const char *pass, const char *method);
#endif // _ENCRYPT_H

37
src/local.c

@ -140,7 +140,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
// local socks5 server
if (server->stage == 5) {
encrypt_ctx(remote->buf, r, server->e_ctx);
remote->buf = encrypt(remote->buf, r, server->e_ctx);
int s = send(remote->fd, remote->buf, r, 0);
if(s == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
@ -188,7 +188,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
return;
}
char addr_to_send[256];
char *addr_to_send = malloc(256);
uint8_t addr_len = 0;
addr_to_send[addr_len++] = request->atyp;
@ -223,8 +223,10 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
return;
}
encrypt_ctx(addr_to_send, addr_len, server->e_ctx);
addr_to_send = encrypt(addr_to_send, addr_len, server->e_ctx);
int s = send(remote->fd, addr_to_send, addr_len, 0);
free(addr_to_send);
if (s < addr_len) {
LOGE("failed to send remote addr.");
close_and_free_remote(EV_A_ remote);
@ -352,7 +354,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
}
}
decrypt_ctx(server->buf, r, server->d_ctx);
server->buf = decrypt(server->buf, r, server->d_ctx);
int s = send(server->fd, server->buf, r, 0);
if (s == -1) {
@ -445,6 +447,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) {
struct remote* new_remote(int fd, int timeout) {
struct remote *remote;
remote = malloc(sizeof(struct remote));
remote->buf = malloc(256);
remote->recv_ctx = malloc(sizeof(struct remote_ctx));
remote->send_ctx = malloc(sizeof(struct remote_ctx));
remote->fd = fd;
@ -465,6 +468,7 @@ void free_remote(struct remote *remote) {
if (remote->server != NULL) {
remote->server->remote = NULL;
}
free(remote->buf);
free(remote->recv_ctx);
free(remote->send_ctx);
free(remote);
@ -481,9 +485,10 @@ void close_and_free_remote(EV_P_ struct remote *remote) {
}
}
struct server* new_server(int fd) {
struct server* new_server(int fd, int method) {
struct server *server;
server = malloc(sizeof(struct server));
server->buf = malloc(256);
server->recv_ctx = malloc(sizeof(struct server_ctx));
server->send_ctx = malloc(sizeof(struct server_ctx));
server->fd = fd;
@ -494,11 +499,11 @@ struct server* new_server(int fd) {
server->send_ctx->server = server;
server->send_ctx->connected = 0;
server->stage = 0;
if (enc_conf.method == RC4) {
server->e_ctx = malloc(sizeof(struct rc4_state));
server->d_ctx = malloc(sizeof(struct rc4_state));
enc_ctx_init(server->e_ctx, 1);
enc_ctx_init(server->d_ctx, 0);
if (method) {
server->e_ctx = malloc(sizeof(struct enc_ctx));
server->d_ctx = malloc(sizeof(struct enc_ctx));
enc_ctx_init(method, server->e_ctx, 1);
enc_ctx_init(method, server->d_ctx, 0);
} else {
server->e_ctx = NULL;
server->d_ctx = NULL;
@ -513,10 +518,15 @@ void free_server(struct server *server) {
if (server->remote != NULL) {
server->remote->server = NULL;
}
if (enc_conf.method == RC4) {
if (server->e_ctx != NULL) {
EVP_CIPHER_CTX_cleanup(server->e_ctx);
free(server->e_ctx);
}
if (server->d_ctx != NULL) {
EVP_CIPHER_CTX_cleanup(server->d_ctx);
free(server->d_ctx);
}
free(server->buf);
free(server->recv_ctx);
free(server->send_ctx);
free(server);
@ -577,7 +587,7 @@ static void accept_cb (EV_P_ ev_io *w, int revents) {
if (listener->iface) setinterface(sockfd, listener->iface);
#endif
struct server *server = new_server(serverfd);
struct server *server = new_server(serverfd, listener->method);
struct remote *remote = new_remote(sockfd, listener->timeout);
server->remote = remote;
remote->server = server;
@ -676,7 +686,7 @@ int main (int argc, char **argv) {
// Setup keys
LOGD("calculating ciphers...");
enc_conf_init(password, method);
int m = enc_init(password, method);
// Setup socket
int listenfd;
@ -702,6 +712,7 @@ int main (int argc, char **argv) {
listen_ctx.timeout = atoi(timeout);
listen_ctx.fd = listenfd;
listen_ctx.iface = iface;
listen_ctx.method = m;
struct ev_loop *loop = ev_default_loop(0);
if (!loop) {

9
src/local.h

@ -11,6 +11,7 @@ struct listen_ctx {
int remote_num;
char *remote_port;
char *iface;
int method;
int timeout;
int fd;
struct sockaddr sock;
@ -24,12 +25,12 @@ struct server_ctx {
struct server {
int fd;
char buf[BUF_SIZE]; // server send from, remote recv into
char *buf; // server send from, remote recv into
char stage;
int buf_len;
int buf_idx;
struct rc4_state *e_ctx;
struct rc4_state *d_ctx;
struct enc_ctx *e_ctx;
struct enc_ctx *d_ctx;
struct server_ctx *recv_ctx;
struct server_ctx *send_ctx;
struct remote *remote;
@ -61,7 +62,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents);
struct remote* new_remote(int fd, int timeout);
void free_remote(struct remote *remote);
void close_and_free_remote(EV_P_ struct remote *remote);
struct server* new_server(int fd);
struct server* new_server(int fd, int method);
void free_server(struct server *server);
void close_and_free_server(EV_P_ struct server *server);

103
src/rc4.c

@ -1,103 +0,0 @@
/*
* rc4.c
*
* Copyright (c) 1996-2000 Whistle Communications, Inc.
* All rights reserved.
*
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* provided, however, that:
* 1. Any and all reproductions of the source or object code must include the
* copyright notice above and the following disclaimer of warranties; and
* 2. No rights are granted, in any manner or form, to use Whistle
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
*
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/crypto/rc4/rc4.c,v 1.2.2.1 2000/04/18 04:48:31 archie Exp $
*/
#include <stdint.h>
#include "rc4.h"
static inline void
swap_bytes(u_char *a, u_char *b)
{
u_char temp;
temp = *a;
*a = *b;
*b = temp;
}
/*
* Initialize an RC4 state buffer using the supplied key,
* which can have arbitrary length.
*/
void
rc4_init(struct rc4_state *const state, const u_char *key, int keylen)
{
u_char j;
int i;
/* Initialize state with identity permutation */
for (i = 0; i < 256; i++)
state->perm[i] = (u_char)i;
state->index1 = 0;
state->index2 = 0;
/* Randomize the permutation using key data */
for (j = i = 0; i < 256; i++) {
j += state->perm[i] + key[i % keylen];
swap_bytes(&state->perm[i], &state->perm[j]);
}
}
/*
* Encrypt some data using the supplied RC4 state buffer.
* The input and output buffers may be the same buffer.
* Since RC4 is a stream cypher, this function is used
* for both encryption and decryption.
*/
void
rc4_crypt(struct rc4_state *const state,
const u_char *inbuf, u_char *outbuf, int buflen)
{
int i;
u_char j;
for (i = 0; i < buflen; i++) {
/* Update modification indicies */
state->index1++;
state->index2 += state->perm[state->index1];
/* Modify permutation */
swap_bytes(&state->perm[state->index1],
&state->perm[state->index2]);
/* Encrypt/decrypt next byte */
j = state->perm[state->index1] + state->perm[state->index2];
outbuf[i] = inbuf[i] ^ state->perm[j];
}
}

55
src/rc4.h

@ -1,55 +0,0 @@
/*
* rc4.h
*
* Copyright (c) 1996-2000 Whistle Communications, Inc.
* All rights reserved.
*
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* provided, however, that:
* 1. Any and all reproductions of the source or object code must include the
* copyright notice above and the following disclaimer of warranties; and
* 2. No rights are granted, in any manner or form, to use Whistle
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
*
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* $FreeBSD: src/sys/crypto/rc4/rc4.h,v 1.2.2.1 2000/04/18 04:48:32 archie Exp $
*/
#ifndef RC4_H_
#define RC4_H_
typedef uint8_t u_char;
struct rc4_state {
u_char perm[256];
u_char index1;
u_char index2;
};
void rc4_init(struct rc4_state *state, const u_char *key, int keylen);
void rc4_crypt(struct rc4_state *state,
const u_char *inbuf, u_char *outbuf, int buflen);
#endif
Loading…
Cancel
Save