Skip to content

Commit

Permalink
progress on reality
Browse files Browse the repository at this point in the history
  • Loading branch information
radkesvat committed May 9, 2024
1 parent 8a7cc2f commit 330415b
Showing 1 changed file with 156 additions and 96 deletions.
252 changes: 156 additions & 96 deletions tunnels/server/reality/reality_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
enum reality_consts
{
kEncryptionBlockSize = 16,
kSignHeaderLen = kEncryptionBlockSize * 2,
kSignLen = (224 / 8),
kSignPasswordLen = kEncryptionBlockSize,
kSignIVlen = 16, // IV size for *most* modes is the same as the block size. For AES this is 128 bits
kIVlen = 16, // iv size for *most* modes is the same as the block size. For AES this is 128 bits
kTLSVersion12 = 0x0303,
kTLS12ApplicationData = 0x17,
kTLSHeaderlen = 1 + 2 + 2,
};

enum connection_auth_state
Expand All @@ -36,33 +37,29 @@ typedef struct reality_server_state_s

tunnel_t *dest;
// settings
bool anti_tit; // solve tls in tls using paddings
uint32_t max_delta_time;
uint32_t counter_threshould;
char *password;
unsigned int password_length;
uint64_t hash1;
uint64_t hash2;
uint64_t hash3;
char context_password[kSignPasswordLen];
unsigned char context_base_iv[kSignIVlen];
bool anti_tit; // solve tls in tls using paddings
uint32_t max_delta_time;
uint32_t counter_threshould;
char *password;
unsigned int password_length;
uint8_t hashes[EVP_MAX_MD_SIZE];
char context_password[kSignPasswordLen];

} reality_server_state_t;

typedef struct reality_server_con_state_s
{
buffer_stream_t *stream;
EVP_MD *msg_digest;
EVP_PKEY *sign_key;
EVP_MD_CTX *sign_context;
EVP_CIPHER_CTX *encryption_context;
EVP_CIPHER_CTX *decryption_context;
uint32_t sniff_counter;
buffer_stream_t *read_stream;
uint8_t giveup_counter;
enum connection_auth_state auth_state;
bool first_sent;
bool init_sent;
uint8_t send_counter;
uint32_t magic;
uint32_t epoch;
uint32_t reply_sent_tit;
unsigned char calculated_iv[kSignIVlen];

} reality_server_con_state_t;

Expand All @@ -86,27 +83,67 @@ static void cleanup(tunnel_t *self, context_t *c)
reality_server_con_state_t *cstate = CSTATE(c);
if (cstate != NULL)
{
switch (cstate->auth_state)
{
case kConAuthPending:
case kConUnAuthorized:

break;
case kConAuthorized:
destroyBufferStream(cstate->stream);
EVP_CIPHER_CTX_free(cstate->encryption_context);
EVP_CIPHER_CTX_free(cstate->decryption_context);
break;
if (cstate->auth_state == kConAuthorized)
{
destroyBufferStream(cstate->read_stream);
}
EVP_CIPHER_CTX_free(cstate->encryption_context);
EVP_CIPHER_CTX_free(cstate->decryption_context);
EVP_MD_CTX_free(cstate->sign_context);
EVP_MD_free(cstate->msg_digest);
EVP_PKEY_free(cstate->sign_key);

free(cstate);
CSTATE_MUT(c) = NULL;
}
}
static bool verifyMessage(shift_buffer_t *buf, reality_server_con_state_t *cstate)
{
int rc = EVP_DigestSignInit(cstate->sign_context, NULL, cstate->msg_digest, NULL, cstate->sign_key);
uint8_t expect[EVP_MAX_MD_SIZE];
memcpy(expect, rawBuf(buf), kSignLen);
shiftr(buf, kSignLen);
assert(rc == 1);
rc = EVP_DigestSignUpdate(cstate->sign_context, rawBuf(buf), bufLen(buf));
assert(rc == 1);
uint8_t buff[EVP_MAX_MD_SIZE];
size_t size = sizeof(buff);
rc = EVP_DigestSignFinal(cstate->sign_context, buff, &size);
assert(rc == 1);
assert(size == kSignLen);
return ! ! CRYPTO_memcmp(expect, buff, size);
}

static void signMessage(shift_buffer_t *buf, reality_server_con_state_t *cstate)
{
int rc = EVP_DigestSignInit(cstate->sign_context, NULL, cstate->msg_digest, NULL, cstate->sign_key);
assert(rc == 1);
rc = EVP_DigestSignUpdate(cstate->sign_context, rawBuf(buf), bufLen(buf));
assert(rc == 1);
size_t req = 0;
rc = EVP_DigestSignFinal(cstate->sign_context, NULL, &req);
assert(rc == 1);
shiftl(buf, req);
size_t slen = 0;
rc = EVP_DigestSignFinal(cstate->sign_context, rawBufMut(buf), &slen);
assert(rc == 1);
assert(req == slen == kSignLen);
}

static void genericDecrypt(shift_buffer_t *in, reality_server_con_state_t *cstate, shift_buffer_t *out)
static shift_buffer_t *genericDecrypt(shift_buffer_t *in, reality_server_con_state_t *cstate, char *password,
buffer_pool_t *pool)
{
uint16_t input_length = bufLen(in);
shift_buffer_t *out = popBuffer(pool);
uint16_t input_length = bufLen(in);

uint8_t iv[kIVlen];
memcpy(iv, rawBuf(in), kIVlen);
shiftr(in, kIVlen);

EVP_DecryptInit_ex(cstate->decryption_context, EVP_aes_128_cbc(), NULL, (const uint8_t *) password,
(const uint8_t *) iv);

reserveBufSpace(out, input_length + (2 * kEncryptionBlockSize));
int out_len = 0;

Expand All @@ -128,12 +165,27 @@ static void genericDecrypt(shift_buffer_t *in, reality_server_con_state_t *cstat
{
printSSLErrorAndAbort();
}
reuseBuffer(pool, in);

setLen(out, bufLen(out) + out_len);
return out;
}
static void genericEncrypt(shift_buffer_t *in, reality_server_con_state_t *cstate, shift_buffer_t *out)
static shift_buffer_t *genericEncrypt(shift_buffer_t *in, reality_server_con_state_t *cstate, char *password,
buffer_pool_t *pool)
{
uint16_t input_length = bufLen(in);
reserveBufSpace(out, input_length + (2 * kEncryptionBlockSize));
shift_buffer_t *out = popBuffer(pool);
int input_length = (int) bufLen(in);

uint8_t iv[kIVlen];
for (int i; i < kIVlen / sizeof(uint32_t); i++)
{
((uint32_t *) iv)[i] = fastRand();
}

EVP_EncryptInit_ex(cstate->encryption_context, EVP_aes_128_cbc(), NULL, (const uint8_t *) password,
(const uint8_t *) iv);

reserveBufSpace(out, input_length + (input_length % kEncryptionBlockSize));
int out_len = 0;

/*
Expand All @@ -145,7 +197,7 @@ static void genericEncrypt(shift_buffer_t *in, reality_server_con_state_t *cstat
printSSLErrorAndAbort();
}

setLen(out, out_len);
setLen(out, bufLen(out) + out_len);

/*
* Finalise the encryption. Further ciphertext bytes may be written at
Expand All @@ -155,45 +207,28 @@ static void genericEncrypt(shift_buffer_t *in, reality_server_con_state_t *cstat
{
printSSLErrorAndAbort();
}

reuseBuffer(pool, in);
setLen(out, bufLen(out) + out_len);
}
static bool isValid(shift_buffer_t *in_buf, reality_server_state_t *state, reality_server_con_state_t *cstate)
{
if (bufLen(in_buf) < kSignHeaderLen + 1 + 2 + 2)
{
return false;
}
uint8_t *header_p8 = ((uint8_t *) rawBufMut(in_buf)) + 1 + 2 + 2;
uint64_t *header_p64 = ((uint64_t *) rawBufMut(in_buf)) + 1 + 2 + 2;

for (int i = 0; i < kSignHeaderLen / sizeof(uint64_t); i++)
{
header_p64[i] = header_p64[i] ^ (state->hash2);
}

const uint32_t max_start_pos = 1 + kSignHeaderLen - sizeof(uint32_t);
uint32_t start_pos = (uint32_t) ((state->hash1) % max_start_pos);
shiftl(out, kIVlen);
memcpy(rawBufMut(out), iv, kIVlen);
return out;
}

uint32_t header_epoch = *(uint32_t *) (header_p8 + start_pos);
static void appendTlsHeader(shift_buffer_t *buf)
{
unsigned int data_length = bufLen(buf);
assert(data_length < (1U << 16));

if (((cstate->epoch - state->max_delta_time) >= header_epoch))
{
assert(cstate->magic != 0);
shiftl(buf, sizeof(uint16_t));
writeUI16(buf, (uint16_t) data_length);

for (int i = 0; i < kSignIVlen; i++)
{
cstate->calculated_iv[i] = (uint8_t) (state->context_base_iv[i] + header_epoch + cstate->magic);
}
shiftl(buf, sizeof(uint16_t));
writeUI16(buf, kTLSVersion12);

memcpy(rawBufMut(in_buf) + kSignHeaderLen, rawBuf(in_buf), 1 + 2 + 2);
shiftr(in_buf, 5);
return true;
}
LOGD("RealityServer: packet was not reality client-hello");
return false;
shiftl(buf, sizeof(uint8_t));
writeUI8(buf, kTLS12ApplicationData);
}

static void upStream(tunnel_t *self, context_t *c)
{
reality_server_state_t *state = STATE(self);
Expand All @@ -204,61 +239,78 @@ static void upStream(tunnel_t *self, context_t *c)

switch (cstate->auth_state)
{
case kConAuthPending:
if (isValid(c->payload, state, cstate))
case kConAuthPending: {

shift_buffer_t *buf = c->payload;
shiftr(buf, kTLSHeaderlen);
bool valid = verifyMessage(buf, cstate);
shiftl(buf, kTLSHeaderlen);

if (valid)
{
cstate->auth_state = kConAuthorized;
cstate->stream = newBufferStream(getContextBufferPool(c));
EVP_EncryptInit_ex(cstate->encryption_context, EVP_aes_128_cbc(), NULL,
(const uint8_t *) state->context_password, cstate->calculated_iv);
cstate->auth_state = kConAuthorized;
cstate->read_stream = newBufferStream(getContextBufferPool(c));

EVP_EncryptInit_ex(cstate->decryption_context, EVP_aes_128_cbc(), NULL,
(const uint8_t *) state->context_password, cstate->calculated_iv);

state->dest->upStream(state->dest,newFinContextFrom(c));
self->up->upStream(self->up,newInitContext(c->line));
state->dest->upStream(state->dest, newFinContextFrom(c));
self->up->upStream(self->up, newInitContext(c->line));

goto authorized;
}
else
{
cstate->sniff_counter -= 0;
if (cstate->sniff_counter == 0)
cstate->giveup_counter -= 0;
if (cstate->giveup_counter == 0)
{
cstate->auth_state = kConUnAuthorized;
}
}
}

case kConUnAuthorized:
state->dest->upStream(state->dest, c);

break;
authorized:;
case kConAuthorized:

bufferStreamPush(cstate->stream, c->payload);
case kConAuthorized: {
bufferStreamPush(cstate->read_stream, c->payload);
c->payload = NULL;
while (bufferStreamLen(cstate->stream) >= 1 + 2 + 2)
uint8_t tls_header[1 + 2 + 2];
while (bufferStreamLen(cstate->read_stream) >= sizeof(tls_header))
{
uint8_t tls_header[1 + 2 + 2];
bufferStreamViewBytesAt(cstate->stream, 0, tls_header, sizeof(tls_header));
bufferStreamViewBytesAt(cstate->read_stream, 0, tls_header, sizeof(tls_header));
uint16_t length = *(uint16_t *) (tls_header + 3);
if (bufferStreamLen(cstate->stream) >= 1 + 2 + 2 + length)
if (bufferStreamLen(cstate->read_stream) >= sizeof(tls_header) + length)
{
context_t *data_ctx = newContextFrom(c);
data_ctx->payload = popBuffer(getContextBufferPool(c));

shift_buffer_t *cypher_buf = bufferStreamRead(cstate->stream, 1 + 2 + 2 + length);
shiftr(cypher_buf, 1 + 2 + 2);
genericDecrypt(cypher_buf, cstate, c->payload);
self->up->upStream(self->up, data_ctx);
shift_buffer_t *buf = bufferStreamRead(cstate->read_stream, sizeof(tls_header) + length);
shiftr(buf, sizeof(tls_header));

if (! verifyMessage(buf, cstate))
{
LOGE("RealityServer: verifyMessage failed");
reuseBuffer(getContextBufferPool(c), buf);
goto failed;
}

buf = genericDecrypt(buf, cstate, state->context_password, getContextBufferPool(c));
uint16_t length = 0;
readUI16(buf, &(length));
shiftr(buf, sizeof(uint16_t));
assert(length <= bufLen(buf));
setLen(buf, length);

context_t *plain_data_ctx = newContextFrom(c);
plain_data_ctx->payload = buf;
self->dw->downStream(self->dw, plain_data_ctx);
}
else
{
break;
}
}
destroyContext(c);
}

break;
break;
}
}
else
Expand All @@ -269,8 +321,7 @@ static void upStream(tunnel_t *self, context_t *c)
CSTATE_MUT(c) = malloc(sizeof(reality_server_con_state_t));
memset(CSTATE(c), 0, sizeof(reality_server_con_state_t));
cstate->auth_state = kConAuthPending;
cstate->sniff_counter = state->counter_threshould;
cstate->epoch = (uint32_t) hloop_now(c->line->loop);
cstate->giveup_counter = state->counter_threshould;
cstate->encryption_context = EVP_CIPHER_CTX_new();
cstate->decryption_context = EVP_CIPHER_CTX_new();

Expand All @@ -284,6 +335,15 @@ static void upStream(tunnel_t *self, context_t *c)
next->upStream(next, c);
}
}
return;
failed:;
context_t *fail_context_up = newFinContextFrom(c);
self->up->upStream(self->up, fail_context_up);

context_t *fail_context = newFinContextFrom(c);
cleanup(self, c);
destroyContext(c);
self->dw->downStream(self->dw, fail_context);
}

static void downStream(tunnel_t *self, context_t *c)
Expand Down

0 comments on commit 330415b

Please sign in to comment.