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

610 lines
22 KiB
C

#include "tls1.2_ticket.h"
#include "list.c"
typedef struct tls12_ticket_auth_global_data {
uint8_t local_client_id[32];
List client_data;
time_t startup_time;
}tls12_ticket_auth_global_data;
typedef struct tls12_ticket_auth_local_data {
int handshake_status;
char *send_buffer;
int send_buffer_size;
char *recv_buffer;
int recv_buffer_size;
}tls12_ticket_auth_local_data;
void tls12_ticket_auth_local_data_init(tls12_ticket_auth_local_data* local) {
local->handshake_status = 0;
local->send_buffer = malloc(0);
local->send_buffer_size = 0;
local->recv_buffer = malloc(0);
local->recv_buffer_size = 0;
}
void * tls12_ticket_auth_init_data() {
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)malloc(sizeof(tls12_ticket_auth_global_data));
rand_bytes(global->local_client_id, 32);
global->client_data = list_init(22);
global->startup_time = time(NULL);
return global;
}
obfs * tls12_ticket_auth_new_obfs() {
obfs * self = new_obfs();
self->l_data = malloc(sizeof(tls12_ticket_auth_local_data));
tls12_ticket_auth_local_data_init((tls12_ticket_auth_local_data*)self->l_data);
return self;
}
void tls12_ticket_auth_dispose(obfs *self) {
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
if (local->send_buffer != NULL) {
free(local->send_buffer);
local->send_buffer = NULL;
}
if (local->recv_buffer != NULL) {
free(local->recv_buffer);
local->recv_buffer = NULL;
}
free(local);
dispose_obfs(self);
}
int tls12_ticket_pack_auth_data(tls12_ticket_auth_global_data *global, server_info *server, char *outdata) {
int out_size = 32;
time_t t = time(NULL);
outdata[0] = t >> 24;
outdata[1] = t >> 16;
outdata[2] = t >> 8;
outdata[3] = t;
rand_bytes((uint8_t*)outdata + 4, 18);
uint8_t *key = (uint8_t*)malloc(server->key_len + 32);
char hash[ONETIMEAUTH_BYTES * 2];
memcpy(key, server->key, server->key_len);
memcpy(key + server->key_len, global->local_client_id, 32);
ss_sha1_hmac_with_key(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, key, server->key_len + 32);
free(key);
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
return out_size;
}
void tls12_ticket_auth_pack_data(char *encryptdata, int datalength, int start, int len, char *out_buffer, int outlength) {
out_buffer[outlength] = 0x17;
out_buffer[outlength + 1] = 0x3;
out_buffer[outlength + 2] = 0x3;
out_buffer[outlength + 3] = len >> 8;
out_buffer[outlength + 4] = len;
memcpy(out_buffer + outlength + 5, encryptdata + start, len);
}
int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
char *encryptdata = *pencryptdata;
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
char * out_buffer = NULL;
if (local->handshake_status == 8) {
if (datalength < 1024) {
if (*capacity < datalength + 5) {
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2);
encryptdata = *pencryptdata;
}
memmove(encryptdata + 5, encryptdata, datalength);
encryptdata[0] = 0x17;
encryptdata[1] = 0x3;
encryptdata[2] = 0x3;
encryptdata[3] = datalength >> 8;
encryptdata[4] = datalength;
return datalength + 5;
} else {
out_buffer = (char*)malloc(datalength + 2048);
int start = 0;
int outlength = 0;
int len;
while (datalength - start > 2048) {
len = xorshift128plus() % 4096 + 100;
if (len > datalength - start)
len = datalength - start;
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
outlength += len + 5;
start += len;
}
if (datalength - start > 0) {
len = datalength - start;
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
outlength += len + 5;
}
if (*capacity < outlength) {
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
encryptdata = *pencryptdata;
}
memcpy(encryptdata, out_buffer, outlength);
free(out_buffer);
return outlength;
}
}
local->send_buffer = (char*)realloc(local->send_buffer, local->send_buffer_size + datalength + 5);
memcpy(local->send_buffer + local->send_buffer_size + 5, encryptdata, datalength);
local->send_buffer[local->send_buffer_size] = 0x17;
local->send_buffer[local->send_buffer_size + 1] = 0x3;
local->send_buffer[local->send_buffer_size + 2] = 0x3;
local->send_buffer[local->send_buffer_size + 3] = datalength >> 8;
local->send_buffer[local->send_buffer_size + 4] = datalength;
local->send_buffer_size += datalength + 5;
if (local->handshake_status == 0) {
#define CSTR_DECL(name, len, str) const char* name = str; const int len = sizeof(str) - 1;
CSTR_DECL(tls_data0, tls_data0_len, "\x00\x1c\xc0\x2b\xc0\x2f\xcc\xa9\xcc\xa8\xcc\x14\xcc\x13\xc0\x0a\xc0\x14\xc0\x09\xc0\x13\x00\x9c\x00\x35\x00\x2f\x00\x0a\x01\x00"
);
CSTR_DECL(tls_data1, tls_data1_len, "\xff\x01\x00\x01\x00"
);
CSTR_DECL(tls_data2, tls_data2_len, "\x00\x17\x00\x00\x00\x23\x00\xd0");
CSTR_DECL(tls_data3, tls_data3_len, "\x00\x0d\x00\x16\x00\x14\x06\x01\x06\x03\x05\x01\x05\x03\x04\x01\x04\x03\x03\x01\x03\x03\x02\x01\x02\x03\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x12\x00\x00\x75\x50\x00\x00\x00\x0b\x00\x02\x01\x00\x00\x0a\x00\x06\x00\x04\x00\x17\x00\x18"
//"00150066000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" // padding
);
uint8_t tls_data[2048];
int tls_data_len = 0;
memcpy(tls_data, tls_data1, tls_data1_len);
tls_data_len += tls_data1_len;
char hosts[1024];
char * phost[128];
int host_num = 0;
int pos;
char sni[256] = {0};
if (self->server.param && strlen(self->server.param) == 0)
self->server.param = NULL;
strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts);
phost[host_num++] = hosts;
for (pos = 0; hosts[pos]; ++pos) {
if (hosts[pos] == ',') {
phost[host_num++] = &hosts[pos + 1];
}
}
host_num = xorshift128plus() % host_num;
sprintf(sni, "%s", phost[host_num]);
int sni_len = strlen(sni);
if (sni_len > 0 && sni[sni_len - 1] >= '0' && sni[sni_len - 1] <= '9')
sni_len = 0;
tls_data[tls_data_len] = '\0';
tls_data[tls_data_len + 1] = '\0';
tls_data[tls_data_len + 2] = (sni_len + 5) >> 8;
tls_data[tls_data_len + 3] = (sni_len + 5);
tls_data[tls_data_len + 4] = (sni_len + 3) >> 8;
tls_data[tls_data_len + 5] = (sni_len + 3);
tls_data[tls_data_len + 6] = '\0';
tls_data[tls_data_len + 7] = sni_len >> 8;
tls_data[tls_data_len + 8] = sni_len;
memcpy(tls_data + tls_data_len + 9, sni, sni_len);
tls_data_len += 9 + sni_len;
memcpy(tls_data + tls_data_len, tls_data2, tls_data2_len);
tls_data_len += tls_data2_len;
rand_bytes(tls_data + tls_data_len, 208);
tls_data_len += 208;
memcpy(tls_data + tls_data_len, tls_data3, tls_data3_len);
tls_data_len += tls_data3_len;
datalength = 11 + 32 + 1 + 32 + tls_data0_len + 2 + tls_data_len;
out_buffer = (char*)malloc(datalength);
char *pdata = out_buffer + datalength - tls_data_len;
int len = tls_data_len;
memcpy(pdata, tls_data, tls_data_len);
pdata[-1] = tls_data_len;
pdata[-2] = tls_data_len >> 8;
pdata -= 2; len += 2;
memcpy(pdata - tls_data0_len, tls_data0, tls_data0_len);
pdata -= tls_data0_len; len += tls_data0_len;
memcpy(pdata - 32, global->local_client_id, 32);
pdata -= 32; len += 32;
pdata[-1] = 0x20;
pdata -= 1; len += 1;
tls12_ticket_pack_auth_data(global, &self->server, pdata - 32);
pdata -= 32; len += 32;
pdata[-1] = 0x3;
pdata[-2] = 0x3; // tls version
pdata -= 2; len += 2;
pdata[-1] = len;
pdata[-2] = len >> 8;
pdata[-3] = 0;
pdata[-4] = 1;
pdata -= 4; len += 4;
pdata[-1] = len;
pdata[-2] = len >> 8;
pdata -= 2; len += 2;
pdata[-1] = 0x1;
pdata[-2] = 0x3; // tls version
pdata -= 2; len += 2;
pdata[-1] = 0x16; // tls handshake
pdata -= 1; len += 1;
local->handshake_status = 1;
} else if (datalength == 0) {
datalength = local->send_buffer_size + 43;
out_buffer = (char*)malloc(datalength);
char *pdata = out_buffer;
memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6);
pdata += 6;
memcpy(pdata, "\x16\x03\x03\x00\x20", 5);
pdata += 5;
rand_bytes((uint8_t*)pdata, 22);
pdata += 22;
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
char hash[ONETIMEAUTH_BYTES * 2];
memcpy(key, self->server.key, self->server.key_len);
memcpy(key + self->server.key_len, global->local_client_id, 32);
ss_sha1_hmac_with_key(hash, out_buffer, pdata - out_buffer, key, self->server.key_len + 32);
free(key);
memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN);
pdata += OBFS_HMAC_SHA1_LEN;
memcpy(pdata, local->send_buffer, local->send_buffer_size);
free(local->send_buffer);
local->send_buffer = NULL;
local->handshake_status = 8;
} else {
return 0;
}
if (*capacity < datalength) {
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = datalength * 2);
encryptdata = *pencryptdata;
}
memmove(encryptdata, out_buffer, datalength);
free(out_buffer);
return datalength;
}
int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
char *encryptdata = *pencryptdata;
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
char * out_buffer = NULL;
if (local->handshake_status == 8) {
if (datalength < 1024) {
if (*capacity < datalength + 5) {
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2);
encryptdata = *pencryptdata;
}
memmove(encryptdata + 5, encryptdata, datalength);
encryptdata[0] = 0x17;
encryptdata[1] = 0x3;
encryptdata[2] = 0x3;
encryptdata[3] = datalength >> 8;
encryptdata[4] = datalength;
return datalength + 5;
} else {
out_buffer = (char*)malloc(datalength + 2048);
int start = 0;
int outlength = 0;
int len;
while (datalength - start > 2048) {
len = xorshift128plus() % 4096 + 100;
if (len > datalength - start)
len = datalength - start;
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
outlength += len + 5;
start += len;
}
if (datalength - start > 0) {
len = datalength - start;
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
outlength += len + 5;
}
if (*capacity < outlength) {
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
encryptdata = *pencryptdata;
}
memcpy(encryptdata, out_buffer, outlength);
free(out_buffer);
return outlength;
}
}
local->handshake_status = 3;
out_buffer = (char*)malloc(43 + 86);
int data_len = 0;
char *p_data = out_buffer + 86;
memcpy(p_data - 10, "\xc0\x2f\x00\x00\x05\xff\x01\x00\x01\x00", 10);
p_data -= 10;data_len += 10;
memcpy(p_data - 32, global->local_client_id, 32);
p_data -= 32;data_len += 32;
p_data[-1] = 0x20;
p_data -= 1;data_len += 1;
tls12_ticket_pack_auth_data(global, &self->server, p_data - 32);
p_data -= 32;data_len += 32;
p_data[-1] = 0x3;
p_data[-2] = 0x3; // tls version
p_data -= 2;data_len += 2;
p_data[-1] = data_len;
p_data[-2] = data_len >> 8;
p_data[-3] = 0x00;
p_data[-4] = 0x02;
p_data -= 4; data_len += 4;
p_data[-1] = data_len;
p_data[-2] = data_len >> 8;
p_data[-3] = 0x03;
p_data[-4] = 0x03;
p_data[-5] = 0x16;
p_data -= 5; data_len += 5;
memcpy(out_buffer, p_data, data_len);
char *pdata = out_buffer + 86;
memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6);
pdata += 6;
memcpy(pdata, "\x16\x03\x03\x00\x20", 5);
pdata += 5;
rand_bytes((uint8_t*)pdata, 22);
pdata += 22;
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
char hash[ONETIMEAUTH_BYTES * 2];
memcpy(key, self->server.key, self->server.key_len);
memcpy(key + self->server.key_len, global->local_client_id, 32);
ss_sha1_hmac_with_key(hash, out_buffer, 43 + 86, key, self->server.key_len + 32);
free(key);
memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN);
memmove(encryptdata, out_buffer, 43 + 86);
free(out_buffer);
return 43 + 86;
}
int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
char *encryptdata = *pencryptdata;
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
*needsendback = 0;
if (local->handshake_status == 8) {
local->recv_buffer_size += datalength;
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size);
memcpy(local->recv_buffer + local->recv_buffer_size - datalength, encryptdata, datalength);
datalength = 0;
while (local->recv_buffer_size > 5) {
if (local->recv_buffer[0] != 0x17)
return -1;
int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4];
if (size + 5 > local->recv_buffer_size)
break;
if (*capacity < datalength + size) {
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + size) * 2);
encryptdata = *pencryptdata;
}
memcpy(encryptdata + datalength, local->recv_buffer + 5, size);
datalength += size;
local->recv_buffer_size -= 5 + size;
memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size);
}
return datalength;
}
if (datalength < 11 + 32 + 1 + 32) {
return -1;
}
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
char hash[ONETIMEAUTH_BYTES * 2];
memcpy(key, self->server.key, self->server.key_len);
memcpy(key + self->server.key_len, global->local_client_id, 32);
ss_sha1_hmac_with_key(hash, encryptdata + 11, 22, key, self->server.key_len + 32);
free(key);
if (memcmp(encryptdata + 33, hash, OBFS_HMAC_SHA1_LEN)) {
return -1;
}
*needsendback = 1;
return 0;
}
int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
char *encryptdata = *pencryptdata;
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
*needsendback = 0;
if (local->handshake_status == 8) {
if(datalength != 0)
{
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength);
memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength);
local->recv_buffer_size += datalength;
}
datalength = 0;
while (local->recv_buffer_size > 5) {
if (local->recv_buffer[0] != 0x17 || local->recv_buffer[1] != 0x03 || local->recv_buffer[2] != 0x03)
{
LOGE("server_decode data error, wrong tls version 3");
return -1;
}
int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4];
if (size + 5 > local->recv_buffer_size)
break;
if (*capacity < local->recv_buffer_size + size) {
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (local->recv_buffer_size + size) * 2);
encryptdata = *pencryptdata;
}
memcpy(encryptdata + datalength, local->recv_buffer + 5, size);
datalength += size;
local->recv_buffer_size -= 5 + size;
memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size);
}
return datalength;
}
if (local->handshake_status == 3) {
char *verify = encryptdata;
if(datalength < 43)
{
LOGE("server_decode data error, too short:%d", (int)datalength);
return -1;
}
if(encryptdata[0] != 0x14 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x01 || encryptdata[5] != 0x01)
{
LOGE("server_decode data error, wrong tls version");
return -1;
}
encryptdata += 6;
if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x20)
{
LOGE("server_decode data error, wrong tls version 2");
return -1;
}
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
char hash[ONETIMEAUTH_BYTES * 2];
memcpy(key, self->server.key, self->server.key_len);
memcpy(key + self->server.key_len, global->local_client_id, 32);
ss_sha1_hmac_with_key(hash, verify, 33, key, self->server.key_len + 32);
free(key);
if (memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN) != 0) {
LOGE("server_decode data error, hash Mismatch %d",(int)memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN));
return -1;
}
local->recv_buffer_size = datalength - 43;
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size);
memmove(local->recv_buffer, encryptdata + 37, datalength - 43);
local->handshake_status = 8;
return tls12_ticket_auth_server_decode(self, pencryptdata, 0, capacity, needsendback);
}
local->handshake_status = 2;
if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x01)
{
return -1;
}
encryptdata += 3;
{
int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1];
if(size != datalength - 5)
{
LOGE("tls_auth wrong tls head size");
return -1;
}
}
encryptdata += 2;
if(encryptdata[0] != 0x01 || encryptdata[1] != 0x00)
{
LOGE("tls_auth not client hello message");
return -1;
}
encryptdata += 2;
{
int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1];
if(size != datalength - 9)
{
LOGE("tls_auth wrong message size");
return -1;
}
}
encryptdata += 2;
if(encryptdata[0] != 0x03 || encryptdata[1] != 0x03)
{
LOGE("tls_auth wrong tls version");
return -1;
}
encryptdata += 2;
char *verifyid = encryptdata;
encryptdata += 32;
int sessionid_len = encryptdata[0];
if(sessionid_len < 32)
{
LOGE("tls_auth wrong sessionid_len");
return -1;
}
char *sessionid = encryptdata + 1;
memcpy(global->local_client_id , sessionid, sessionid_len);
uint8_t *key = (uint8_t*)malloc(self->server.key_len + sessionid_len);
char hash[ONETIMEAUTH_BYTES * 2];
memcpy(key, self->server.key, self->server.key_len);
memcpy(key + self->server.key_len, global->local_client_id, sessionid_len);
ss_sha1_hmac_with_key(hash, verifyid, 22, key, self->server.key_len + sessionid_len);
free(key);
encryptdata += (sessionid_len + 1);
long utc_time = ((int)(unsigned char)verifyid[0] << 24) + ((int)(unsigned char)verifyid[1] << 16) + ((int)(unsigned char)verifyid[2] << 8) + (unsigned char)verifyid[3];
time_t t = time(NULL);
if (self->server.param && strlen(self->server.param) == 0)
{
self->server.param = NULL;
}
int max_time_dif = 0;
int time_dif = utc_time - t;
if(self->server.param)
{
max_time_dif = atoi(self->server.param);
}
if(max_time_dif > 0 && (time_dif < -max_time_dif || time_dif > max_time_dif || utc_time - global->startup_time < -max_time_dif / 2))
{
LOGE("tls_auth wrong time");
return -1;
}
if (memcmp(verifyid + 22, hash, OBFS_HMAC_SHA1_LEN)) {
LOGE("tls_auth wrong sha1");
return -1;
}
int search_result = global->client_data->have_same_cmp(global->client_data, verifyid);
if(search_result != 0)
{
LOGE("replay attack detect!");
return -1;
}
global->client_data->add_back(global->client_data, verifyid);
encryptdata += 48;
*needsendback = 1;
return 0;
}