openwrt_helloworld/shadowsocksr-libev/src/server/auth.c
2022-04-17 03:50:24 +08:00

994 lines
34 KiB
C

#include "auth.h"
static int auth_simple_pack_unit_size = 2000;
typedef int (*hmac_with_key_func)(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len);
typedef int (*hash_func)(char *auth, char *msg, int msg_len);
typedef struct auth_simple_global_data {
uint8_t local_client_id[8];
uint32_t connection_id;
}auth_simple_global_data;
typedef struct auth_simple_local_data {
int has_sent_header;
char * recv_buffer;
int recv_buffer_size;
uint32_t recv_id;
uint32_t pack_id;
char * salt;
uint8_t * user_key;
char uid[4];
int user_key_len;
hmac_with_key_func hmac;
hash_func hash;
int hash_len;
}auth_simple_local_data;
void auth_simple_local_data_init(auth_simple_local_data* local) {
local->has_sent_header = 0;
local->recv_buffer = (char*)malloc(16384);
local->recv_buffer_size = 0;
local->recv_id = 1;
local->pack_id = 1;
local->salt = "";
local->user_key = 0;
local->user_key_len = 0;
local->hmac = 0;
local->hash = 0;
local->hash_len = 0;
local->salt = "";
}
void * auth_simple_init_data() {
auth_simple_global_data *global = (auth_simple_global_data*)malloc(sizeof(auth_simple_global_data));
rand_bytes(global->local_client_id, 8);
rand_bytes((uint8_t*)&global->connection_id, 4);
global->connection_id &= 0xFFFFFF;
return global;
}
obfs * auth_simple_new_obfs() {
obfs * self = new_obfs();
self->l_data = malloc(sizeof(auth_simple_local_data));
auth_simple_local_data_init((auth_simple_local_data*)self->l_data);
return self;
}
obfs * auth_aes128_md5_new_obfs() {
obfs * self = new_obfs();
self->l_data = malloc(sizeof(auth_simple_local_data));
auth_simple_local_data_init((auth_simple_local_data*)self->l_data);
((auth_simple_local_data*)self->l_data)->hmac = ss_md5_hmac_with_key;
((auth_simple_local_data*)self->l_data)->hash = ss_md5_hash_func;
((auth_simple_local_data*)self->l_data)->hash_len = 16;
((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_md5";
return self;
}
obfs * auth_aes128_sha1_new_obfs() {
obfs * self = new_obfs();
self->l_data = malloc(sizeof(auth_simple_local_data));
auth_simple_local_data_init((auth_simple_local_data*)self->l_data);
((auth_simple_local_data*)self->l_data)->hmac = ss_sha1_hmac_with_key;
((auth_simple_local_data*)self->l_data)->hash = ss_sha1_hash_func;
((auth_simple_local_data*)self->l_data)->hash_len = 20;
((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_sha1";
return self;
}
void auth_simple_dispose(obfs *self) {
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
if (local->recv_buffer != NULL) {
free(local->recv_buffer);
local->recv_buffer = NULL;
}
if (local->user_key != NULL) {
free(local->user_key);
local->user_key = NULL;
}
free(local);
self->l_data = NULL;
dispose_obfs(self);
}
int auth_simple_pack_data(char *data, int datalength, char *outdata) {
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
int out_size = rand_len + datalength + 6;
outdata[0] = out_size >> 8;
outdata[1] = out_size;
outdata[2] = rand_len;
memmove(outdata + rand_len + 2, data, datalength);
fillcrc32((unsigned char *)outdata, out_size);
return out_size;
}
void memintcopy_lt(void *mem, uint32_t val) {
((uint8_t *)mem)[0] = val;
((uint8_t *)mem)[1] = val >> 8;
((uint8_t *)mem)[2] = val >> 16;
((uint8_t *)mem)[3] = val >> 24;
}
int auth_simple_pack_auth_data(auth_simple_global_data *global, char *data, int datalength, char *outdata) {
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
int out_size = rand_len + datalength + 6 + 12;
outdata[0] = out_size >> 8;
outdata[1] = out_size;
outdata[2] = rand_len;
++global->connection_id;
if (global->connection_id > 0xFF000000) {
rand_bytes(global->local_client_id, 8);
rand_bytes((uint8_t*)&global->connection_id, 4);
global->connection_id &= 0xFFFFFF;
}
time_t t = time(NULL);
memintcopy_lt(outdata + rand_len + 2, t);
memmove(outdata + rand_len + 2 + 4, global->local_client_id, 4);
memintcopy_lt(outdata + rand_len + 2 + 8, global->connection_id);
memmove(outdata + rand_len + 2 + 12, data, datalength);
fillcrc32((unsigned char *)outdata, out_size);
return out_size;
}
int auth_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
char * out_buffer = (char*)malloc(datalength * 2 + 64);
char * buffer = out_buffer;
char * data = plaindata;
int len = datalength;
int pack_len;
if (len > 0 && local->has_sent_header == 0) {
int head_size = get_head_size(plaindata, datalength, 30);
if (head_size > datalength)
head_size = datalength;
pack_len = auth_simple_pack_auth_data((auth_simple_global_data *)self->server.g_data, data, head_size, buffer);
buffer += pack_len;
data += head_size;
len -= head_size;
local->has_sent_header = 1;
}
while ( len > auth_simple_pack_unit_size ) {
pack_len = auth_simple_pack_data(data, auth_simple_pack_unit_size, buffer);
buffer += pack_len;
data += auth_simple_pack_unit_size;
len -= auth_simple_pack_unit_size;
}
if (len > 0) {
pack_len = auth_simple_pack_data(data, len, buffer);
buffer += pack_len;
}
len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
free(out_buffer);
return len;
}
int auth_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
if (local->recv_buffer_size + datalength > 16384)
return -1;
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
local->recv_buffer_size += datalength;
char * out_buffer = (char*)malloc(local->recv_buffer_size);
char * buffer = out_buffer;
while (local->recv_buffer_size > 2) {
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
if (length >= 8192 || length < 7) {
free(out_buffer);
local->recv_buffer_size = 0;
return -1;
}
if (length > local->recv_buffer_size)
break;
int crc = crc32((unsigned char*)recv_buffer, length);
if (crc != -1) {
free(out_buffer);
local->recv_buffer_size = 0;
return -1;
}
int data_size = length - recv_buffer[2] - 6;
memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size);
buffer += data_size;
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
}
int len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
free(out_buffer);
return len;
}
int auth_sha1_pack_data(char *data, int datalength, char *outdata) {
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
int out_size = rand_len + datalength + 6;
outdata[0] = out_size >> 8;
outdata[1] = out_size;
outdata[2] = rand_len;
memmove(outdata + rand_len + 2, data, datalength);
filladler32((unsigned char *)outdata, out_size);
return out_size;
}
int auth_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) {
unsigned char rand_len = (xorshift128plus() & 0x7F) + 1;
int data_offset = rand_len + 4 + 2;
int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN;
fillcrc32to((unsigned char *)server->key, server->key_len, (unsigned char *)outdata);
outdata[4] = out_size >> 8;
outdata[5] = out_size;
outdata[6] = rand_len;
++global->connection_id;
if (global->connection_id > 0xFF000000) {
rand_bytes(global->local_client_id, 8);
rand_bytes((uint8_t*)&global->connection_id, 4);
global->connection_id &= 0xFFFFFF;
}
time_t t = time(NULL);
memintcopy_lt(outdata + data_offset, t);
memmove(outdata + data_offset + 4, global->local_client_id, 4);
memintcopy_lt(outdata + data_offset + 8, global->connection_id);
memmove(outdata + data_offset + 12, data, datalength);
char hash[ONETIMEAUTH_BYTES * 2];
ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv);
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
return out_size;
}
int auth_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
char * out_buffer = (char*)malloc(datalength * 2 + 256);
char * buffer = out_buffer;
char * data = plaindata;
int len = datalength;
int pack_len;
if (len > 0 && local->has_sent_header == 0) {
int head_size = get_head_size(plaindata, datalength, 30);
if (head_size > datalength)
head_size = datalength;
pack_len = auth_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer);
buffer += pack_len;
data += head_size;
len -= head_size;
local->has_sent_header = 1;
}
while ( len > auth_simple_pack_unit_size ) {
pack_len = auth_sha1_pack_data(data, auth_simple_pack_unit_size, buffer);
buffer += pack_len;
data += auth_simple_pack_unit_size;
len -= auth_simple_pack_unit_size;
}
if (len > 0) {
pack_len = auth_sha1_pack_data(data, len, buffer);
buffer += pack_len;
}
len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
free(out_buffer);
return len;
}
int auth_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
if (local->recv_buffer_size + datalength > 16384)
return -1;
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
local->recv_buffer_size += datalength;
char * out_buffer = (char*)malloc(local->recv_buffer_size);
char * buffer = out_buffer;
while (local->recv_buffer_size > 2) {
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
if (length >= 8192 || length < 7) {
free(out_buffer);
local->recv_buffer_size = 0;
return -1;
}
if (length > local->recv_buffer_size)
break;
if (checkadler32((unsigned char*)recv_buffer, length) == 0) {
free(out_buffer);
local->recv_buffer_size = 0;
return -1;
}
int pos = recv_buffer[2] + 2;
int data_size = length - pos - 4;
memmove(buffer, recv_buffer + pos, data_size);
buffer += data_size;
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
}
int len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
free(out_buffer);
return len;
}
int auth_sha1_v2_pack_data(char *data, int datalength, char *outdata) {
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
int out_size = rand_len + datalength + 6;
outdata[0] = out_size >> 8;
outdata[1] = out_size;
if (rand_len < 128)
{
outdata[2] = rand_len;
}
else
{
outdata[2] = 0xFF;
outdata[3] = rand_len >> 8;
outdata[4] = rand_len;
}
memmove(outdata + rand_len + 2, data, datalength);
filladler32((unsigned char *)outdata, out_size);
return out_size;
}
int auth_sha1_v2_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) {
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
int data_offset = rand_len + 4 + 2;
int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN;
const char* salt = "auth_sha1_v2";
int salt_len = strlen(salt);
unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len);
memcpy(crc_salt, salt, salt_len);
memcpy(crc_salt + salt_len, server->key, server->key_len);
fillcrc32to(crc_salt, salt_len + server->key_len, (unsigned char *)outdata);
free(crc_salt);
outdata[4] = out_size >> 8;
outdata[5] = out_size;
if (rand_len < 128)
{
outdata[6] = rand_len;
}
else
{
outdata[6] = 0xFF;
outdata[7] = rand_len >> 8;
outdata[8] = rand_len;
}
++global->connection_id;
if (global->connection_id > 0xFF000000) {
rand_bytes(global->local_client_id, 8);
rand_bytes((uint8_t*)&global->connection_id, 4);
global->connection_id &= 0xFFFFFF;
}
memmove(outdata + data_offset, global->local_client_id, 8);
memintcopy_lt(outdata + data_offset + 8, global->connection_id);
memmove(outdata + data_offset + 12, data, datalength);
char hash[ONETIMEAUTH_BYTES * 2];
ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv);
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
return out_size;
}
int auth_sha1_v2_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
char * out_buffer = (char*)malloc(datalength * 2 + 4096);
char * buffer = out_buffer;
char * data = plaindata;
int len = datalength;
int pack_len;
if (len > 0 && local->has_sent_header == 0) {
int head_size = get_head_size(plaindata, datalength, 30);
if (head_size > datalength)
head_size = datalength;
pack_len = auth_sha1_v2_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer);
buffer += pack_len;
data += head_size;
len -= head_size;
local->has_sent_header = 1;
}
while ( len > auth_simple_pack_unit_size ) {
pack_len = auth_sha1_v2_pack_data(data, auth_simple_pack_unit_size, buffer);
buffer += pack_len;
data += auth_simple_pack_unit_size;
len -= auth_simple_pack_unit_size;
}
if (len > 0) {
pack_len = auth_sha1_v2_pack_data(data, len, buffer);
buffer += pack_len;
}
len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
free(out_buffer);
return len;
}
int auth_sha1_v2_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
if (local->recv_buffer_size + datalength > 16384)
return -1;
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
local->recv_buffer_size += datalength;
char * out_buffer = (char*)malloc(local->recv_buffer_size);
char * buffer = out_buffer;
char error = 0;
while (local->recv_buffer_size > 2) {
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
if (length >= 8192 || length < 7) {
local->recv_buffer_size = 0;
error = 1;
break;
}
if (length > local->recv_buffer_size)
break;
if (checkadler32((unsigned char*)recv_buffer, length) == 0) {
local->recv_buffer_size = 0;
error = 1;
break;
}
int pos = recv_buffer[2];
if (pos < 255)
{
pos += 2;
}
else
{
pos = ((recv_buffer[3] << 8) | recv_buffer[4]) + 2;
}
int data_size = length - pos - 4;
memmove(buffer, recv_buffer + pos, data_size);
buffer += data_size;
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
}
int len;
if (error == 0) {
len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
} else {
len = -1;
}
free(out_buffer);
return len;
}
int auth_sha1_v4_pack_data(char *data, int datalength, char *outdata) {
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
int out_size = rand_len + datalength + 8;
outdata[0] = out_size >> 8;
outdata[1] = out_size;
uint32_t crc_val = crc32((unsigned char*)outdata, 2);
outdata[2] = crc_val;
outdata[3] = crc_val >> 8;
if (rand_len < 128)
{
outdata[4] = rand_len;
}
else
{
outdata[4] = 0xFF;
outdata[5] = rand_len >> 8;
outdata[6] = rand_len;
}
memmove(outdata + rand_len + 4, data, datalength);
filladler32((unsigned char *)outdata, out_size);
return out_size;
}
int auth_sha1_v4_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) {
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
int data_offset = rand_len + 4 + 2;
int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN;
const char* salt = "auth_sha1_v4";
int salt_len = strlen(salt);
unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len + 2);
crc_salt[0] = outdata[0] = out_size >> 8;
crc_salt[1] = outdata[1] = out_size;
memcpy(crc_salt + 2, salt, salt_len);
memcpy(crc_salt + salt_len + 2, server->key, server->key_len);
fillcrc32to(crc_salt, salt_len + server->key_len + 2, (unsigned char *)outdata + 2);
free(crc_salt);
if (rand_len < 128)
{
outdata[6] = rand_len;
}
else
{
outdata[6] = 0xFF;
outdata[7] = rand_len >> 8;
outdata[8] = rand_len;
}
++global->connection_id;
if (global->connection_id > 0xFF000000) {
rand_bytes(global->local_client_id, 8);
rand_bytes((uint8_t*)&global->connection_id, 4);
global->connection_id &= 0xFFFFFF;
}
time_t t = time(NULL);
memintcopy_lt(outdata + data_offset, t);
memmove(outdata + data_offset + 4, global->local_client_id, 4);
memintcopy_lt(outdata + data_offset + 8, global->connection_id);
memmove(outdata + data_offset + 12, data, datalength);
char hash[ONETIMEAUTH_BYTES * 2];
ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv);
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
return out_size;
}
int auth_sha1_v4_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
char * out_buffer = (char*)malloc(datalength * 2 + 4096);
char * buffer = out_buffer;
char * data = plaindata;
int len = datalength;
int pack_len;
if (len > 0 && local->has_sent_header == 0) {
int head_size = get_head_size(plaindata, datalength, 30);
if (head_size > datalength)
head_size = datalength;
pack_len = auth_sha1_v4_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer);
buffer += pack_len;
data += head_size;
len -= head_size;
local->has_sent_header = 1;
}
while ( len > auth_simple_pack_unit_size ) {
pack_len = auth_sha1_v4_pack_data(data, auth_simple_pack_unit_size, buffer);
buffer += pack_len;
data += auth_simple_pack_unit_size;
len -= auth_simple_pack_unit_size;
}
if (len > 0) {
pack_len = auth_sha1_v4_pack_data(data, len, buffer);
buffer += pack_len;
}
len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
free(out_buffer);
return len;
}
int auth_sha1_v4_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
if (local->recv_buffer_size + datalength > 16384)
return -1;
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
local->recv_buffer_size += datalength;
char * out_buffer = (char*)malloc(local->recv_buffer_size);
char * buffer = out_buffer;
char error = 0;
while (local->recv_buffer_size > 4) {
uint32_t crc_val = crc32((unsigned char*)recv_buffer, 2);
if ((((uint32_t)recv_buffer[3] << 8) | recv_buffer[2]) != (crc_val & 0xffff)) {
local->recv_buffer_size = 0;
error = 1;
break;
}
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
if (length >= 8192 || length < 7) {
local->recv_buffer_size = 0;
error = 1;
break;
}
if (length > local->recv_buffer_size)
break;
if (checkadler32((unsigned char*)recv_buffer, length) == 0) {
local->recv_buffer_size = 0;
error = 1;
break;
}
int pos = recv_buffer[4];
if (pos < 255)
{
pos += 4;
}
else
{
pos = (((int)recv_buffer[5] << 8) | recv_buffer[6]) + 4;
}
int data_size = length - pos - 4;
memmove(buffer, recv_buffer + pos, data_size);
buffer += data_size;
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
}
int len;
if (error == 0) {
len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
} else {
len = -1;
}
free(out_buffer);
return len;
}
int auth_aes128_sha1_pack_data(char *data, int datalength, char *outdata, auth_simple_local_data *local, server_info *server) {
unsigned int rand_len = (datalength > 1200 ? 0 : local->pack_id > 4 ? (xorshift128plus() & 0x20) : datalength > 900 ? (xorshift128plus() & 0x80) : (xorshift128plus() & 0x200)) + 1;
int out_size = rand_len + datalength + 8;
memcpy(outdata + rand_len + 4, data, datalength);
outdata[0] = out_size;
outdata[1] = out_size >> 8;
uint8_t key_len = local->user_key_len + 4;
uint8_t *key = (uint8_t*)malloc(key_len);
memcpy(key, local->user_key, local->user_key_len);
memintcopy_lt(key + key_len - 4, local->pack_id);
{
uint8_t rnd_data[rand_len];
rand_bytes(rnd_data, rand_len);
memcpy(outdata + 4, rnd_data, rand_len);
}
{
char hash[20];
local->hmac(hash, outdata, 2, key, key_len);
memcpy(outdata + 2, hash, 2);
}
if (rand_len < 128)
{
outdata[4] = rand_len;
}
else
{
outdata[4] = 0xFF;
outdata[5] = rand_len;
outdata[6] = rand_len >> 8;
}
++local->pack_id;
{
char hash[20];
local->hmac(hash, outdata, out_size - 4, key, key_len);
memcpy(outdata + out_size - 4, hash, 4);
}
free(key);
return out_size;
}
int auth_aes128_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, auth_simple_local_data *local, char *data, int datalength, char *outdata) {
unsigned int rand_len = (datalength > 400 ? (xorshift128plus() & 0x200) : (xorshift128plus() & 0x400));
int data_offset = rand_len + 16 + 4 + 4 + 7;
int out_size = data_offset + datalength + 4;
char encrypt[24];
char encrypt_data[16];
uint8_t *key = (uint8_t*)malloc(server->iv_len + server->key_len);
uint8_t key_len = server->iv_len + server->key_len;
memcpy(key, server->iv, server->iv_len);
memcpy(key + server->iv_len, server->key, server->key_len);
{
uint8_t rnd_data[rand_len];
rand_bytes(rnd_data, rand_len);
memcpy(outdata + data_offset - rand_len, rnd_data, rand_len);
}
++global->connection_id;
if (global->connection_id > 0xFF000000) {
rand_bytes(global->local_client_id, 8);
rand_bytes((uint8_t*)&global->connection_id, 4);
global->connection_id &= 0xFFFFFF;
}
time_t t = time(NULL);
memintcopy_lt(encrypt, t);
memcpy(encrypt + 4, global->local_client_id, 4);
memintcopy_lt(encrypt + 8, global->connection_id);
encrypt[12] = out_size;
encrypt[13] = out_size >> 8;
encrypt[14] = rand_len;
encrypt[15] = rand_len >> 8;
{
if (local->user_key == NULL) {
if(server->param != NULL && server->param[0] != 0) {
char *param = server->param;
char *delim = strchr(param, ':');
if(delim != NULL) {
char uid_str[16] = {};
strncpy(uid_str, param, delim - param);
char key_str[128];
strcpy(key_str, delim + 1);
long uid_long = strtol(uid_str, NULL, 10);
memintcopy_lt(local->uid, uid_long);
char hash[21] = {0};
local->hash(hash, key_str, strlen(key_str));
local->user_key_len = local->hash_len;
local->user_key = (uint8_t*)malloc(local->user_key_len);
memcpy(local->user_key, hash, local->hash_len);
}
}
if (local->user_key == NULL) {
rand_bytes((uint8_t *)local->uid, 4);
local->user_key_len = server->key_len;
local->user_key = (uint8_t*)malloc(local->user_key_len);
memcpy(local->user_key, server->key, local->user_key_len);
}
}
char encrypt_key_base64[256] = {0};
unsigned char encrypt_key[local->user_key_len];
memcpy(encrypt_key, local->user_key, local->user_key_len);
base64_encode(encrypt_key, local->user_key_len, encrypt_key_base64);
int base64_len;
base64_len = (local->user_key_len + 2) / 3 * 4;
memcpy(encrypt_key_base64 + base64_len, local->salt, strlen(local->salt));
char enc_key[16];
int enc_key_len = base64_len + strlen(local->salt);
bytes_to_key_with_size(encrypt_key_base64, enc_key_len, (uint8_t*)enc_key, 16);
ss_aes_128_cbc(encrypt, encrypt_data, enc_key);
memcpy(encrypt + 4, encrypt_data, 16);
memcpy(encrypt, local->uid, 4);
}
{
char hash[20];
local->hmac(hash, encrypt, 20, key, key_len);
memcpy(encrypt + 20, hash, 4);
}
{
uint8_t rnd[1];
rand_bytes(rnd, 1);
memcpy(outdata, rnd, 1);
char hash[20];
local->hmac(hash, (char *)rnd, 1, key, key_len);
memcpy(outdata + 1, hash, 6);
}
memcpy(outdata + 7, encrypt, 24);
memcpy(outdata + data_offset, data, datalength);
{
char hash[20];
local->hmac(hash, outdata, out_size - 4, local->user_key, local->user_key_len);
memmove(outdata + out_size - 4, hash, 4);
}
free(key);
return out_size;
}
int auth_aes128_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
char * out_buffer = (char*)malloc(datalength * 2 + 4096);
char * buffer = out_buffer;
char * data = plaindata;
int len = datalength;
int pack_len;
if (len > 0 && local->has_sent_header == 0) {
int head_size = 1200;
if (head_size > datalength)
head_size = datalength;
pack_len = auth_aes128_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, local, data, head_size, buffer);
buffer += pack_len;
data += head_size;
len -= head_size;
local->has_sent_header = 1;
}
while ( len > auth_simple_pack_unit_size ) {
pack_len = auth_aes128_sha1_pack_data(data, auth_simple_pack_unit_size, buffer, local, &self->server);
buffer += pack_len;
data += auth_simple_pack_unit_size;
len -= auth_simple_pack_unit_size;
}
if (len > 0) {
pack_len = auth_aes128_sha1_pack_data(data, len, buffer, local, &self->server);
buffer += pack_len;
}
len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
free(out_buffer);
return len;
}
int auth_aes128_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
//server_info *server = (server_info*)&self->server;
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
if (local->recv_buffer_size + datalength > 16384)
return -1;
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
local->recv_buffer_size += datalength;
int key_len = local->user_key_len + 4;
uint8_t *key = (uint8_t*)malloc(key_len);
memcpy(key, local->user_key, local->user_key_len);
char * out_buffer = (char*)malloc(local->recv_buffer_size);
char * buffer = out_buffer;
char error = 0;
while (local->recv_buffer_size > 4) {
memintcopy_lt(key + key_len - 4, local->recv_id);
{
char hash[20];
local->hmac(hash, (char*)recv_buffer, 2, key, key_len);
if (memcmp(hash, recv_buffer + 2, 2)) {
local->recv_buffer_size = 0;
error = 1;
break;
}
}
int length = ((int)recv_buffer[1] << 8) + recv_buffer[0];
if (length >= 8192 || length < 8) {
local->recv_buffer_size = 0;
error = 1;
break;
}
if (length > local->recv_buffer_size)
break;
{
char hash[20];
local->hmac(hash, (char *)recv_buffer, length - 4, key, key_len);
if (memcmp(hash, recv_buffer + length - 4, 4))
{
local->recv_buffer_size = 0;
error = 1;
break;
}
}
++local->recv_id;
int pos = recv_buffer[4];
if (pos < 255)
{
pos += 4;
}
else
{
pos = (((int)recv_buffer[6] << 8) | recv_buffer[5]) + 4;
}
int data_size = length - pos - 4;
memmove(buffer, recv_buffer + pos, data_size);
buffer += data_size;
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
}
int len;
if (error == 0) {
len = buffer - out_buffer;
if (*capacity < len) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, len);
} else {
len = -1;
}
free(out_buffer);
free(key);
return len;
}
int auth_aes128_sha1_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
char * out_buffer = (char*)malloc(datalength + 8);
if (local->user_key == NULL) {
if(self->server.param != NULL && self->server.param[0] != 0) {
char *param = self->server.param;
char *delim = strchr(param, ':');
if(delim != NULL) {
char uid_str[16] = {};
strncpy(uid_str, param, delim - param);
char key_str[128];
strcpy(key_str, delim + 1);
long uid_long = strtol(uid_str, NULL, 10);
memintcopy_lt(local->uid, uid_long);
char hash[21] = {0};
local->hash(hash, key_str, strlen(key_str));
local->user_key_len = local->hash_len;
local->user_key = (uint8_t*)malloc(local->user_key_len);
memcpy(local->user_key, hash, local->hash_len);
}
}
if (local->user_key == NULL) {
rand_bytes((uint8_t *)local->uid, 4);
local->user_key_len = self->server.key_len;
local->user_key = (uint8_t*)malloc(local->user_key_len);
memcpy(local->user_key, self->server.key, local->user_key_len);
}
}
int outlength = datalength + 8;
memmove(out_buffer, plaindata, datalength);
memmove(out_buffer + datalength, local->uid, 4);
{
char hash[20];
local->hmac(hash, out_buffer, outlength - 4, local->user_key, local->user_key_len);
memmove(out_buffer + outlength - 4, hash, 4);
}
if (*capacity < outlength) {
*pplaindata = (char*)realloc(*pplaindata, *capacity = outlength * 2);
plaindata = *pplaindata;
}
memmove(plaindata, out_buffer, outlength);
free(out_buffer);
return outlength;
}
int auth_aes128_sha1_client_udp_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
if (datalength <= 4)
return 0;
char *plaindata = *pplaindata;
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
char hash[20];
local->hmac(hash, plaindata, datalength - 4, self->server.key, self->server.key_len);
if (memcmp(hash, plaindata + datalength - 4, 4))
{
return 0;
}
return datalength - 4;
}