mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-11-01 15:33:50 +00:00
WIP: add aes/des and other ciphers
This commit is contained in:
+139
-67
@@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
if (enc_conf.method == TABLE) {
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+19
-22
@@ -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
|
||||
#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 {
|
||||
struct enc_ctx {
|
||||
int method;
|
||||
union {
|
||||
struct {
|
||||
uint8_t *encrypt_table;
|
||||
uint8_t *decrypt_table;
|
||||
uint32_t salt;
|
||||
uint64_t key;
|
||||
} table;
|
||||
uint8_t iv[EVP_MAX_IV_LENGTH];
|
||||
EVP_CIPHER_CTX *evp;
|
||||
};
|
||||
|
||||
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);
|
||||
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
|
||||
|
||||
+24
-13
@@ -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) {
|
||||
|
||||
+5
-4
@@ -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);
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user