Skip to content

Commit

Permalink
Implement TLS transport for MTProto-proxy.
Browse files Browse the repository at this point in the history
  • Loading branch information
levlam committed Jul 5, 2019
1 parent 2c94211 commit e4c6b8b
Show file tree
Hide file tree
Showing 8 changed files with 362 additions and 57 deletions.
12 changes: 11 additions & 1 deletion common/sha256.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
2016 Nikolai Durov
*/

#include <assert.h>
#include "sha256.h"

#include <assert.h>

#include <openssl/hmac.h>

void sha256_starts (sha256_context *ctx) {
EVP_MD_CTX_init (ctx);
EVP_DigestInit_ex (ctx, EVP_sha256(), NULL);
Expand Down Expand Up @@ -52,3 +55,10 @@ void sha256_two_chunks (const unsigned char *input1, int ilen1, const unsigned c
sha256_finish (ctx, output);
EVP_MD_CTX_free (ctx);
}

void sha256_hmac (unsigned char *key, int keylen, unsigned char *input, int ilen, unsigned char output[32]) {
unsigned int len = 0;
unsigned char *result = HMAC(EVP_sha256(), key, keylen, input, ilen, output, &len);
assert (result == output);
assert (len == 32);
}
2 changes: 2 additions & 0 deletions common/sha256.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ void sha256_update (sha256_context *ctx, const unsigned char *input, int ilen);
void sha256_finish (sha256_context *ctx, unsigned char output[32]);
void sha256 (const unsigned char *input, int ilen, unsigned char output[32]);
void sha256_two_chunks (const unsigned char *input1, int ilen1, const unsigned char *input2, int ilen2, unsigned char output[32]);

void sha256_hmac (unsigned char *key, int keylen, unsigned char *input, int ilen, unsigned char output[32]);
46 changes: 24 additions & 22 deletions net/net-connections.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,35 +54,36 @@


/* for connection flags */
#define C_WANTRD 1
#define C_WANTWR 2
#define C_WANTRW (C_WANTRD | C_WANTWR)
#define C_INCONN 4
#define C_ERROR 8
#define C_NORD 0x10
#define C_NOWR 0x20
#define C_NORW (C_NORD | C_NOWR)
#define C_INQUERY 0x40
#define C_FAILED 0x80
#define C_ALARM 0x100
#define C_WANTRD 1
#define C_WANTWR 2
#define C_WANTRW (C_WANTRD | C_WANTWR)
#define C_INCONN 4
#define C_ERROR 8
#define C_NORD 0x10
#define C_NOWR 0x20
#define C_NORW (C_NORD | C_NOWR)
#define C_INQUERY 0x40
#define C_FAILED 0x80
#define C_ALARM 0x100
#define C_AIO 0x200
#define C_INTIMEOUT 0x400
#define C_STOPREAD 0x800
#define C_REPARSE 0x1000
#define C_STOPREAD 0x800
#define C_REPARSE 0x1000
#define C_DFLUSH 0x2000
#define C_IPV6 0x4000
#define C_IPV6 0x4000
#define C_EXTERNAL 0x8000
#define C_SPECIAL 0x10000
#define C_NOQACK 0x20000
#define C_RAWMSG 0x40000
#define C_NET_FAILED 0x80000
#define C_CRYPTOIN 0x100000
#define C_CRYPTOOUT 0x200000
#define C_STOPPARSE 0x400000
#define C_NOQACK 0x20000
#define C_RAWMSG 0x40000
#define C_NET_FAILED 0x80000
#define C_CRYPTOIN 0x100000
#define C_CRYPTOOUT 0x200000
#define C_STOPPARSE 0x400000
#define C_ISDH 0x800000
#define C_READY_PENDING 0x1000000
#define C_CONNECTED 0x2000000
#define C_STOPWRITE 0x4000000
#define C_CONNECTED 0x2000000
#define C_STOPWRITE 0x4000000
#define C_IS_TLS 0x8000000

#define C_PERMANENT (C_IPV6 | C_RAWMSG)
/* for connection status */
Expand Down Expand Up @@ -232,6 +233,7 @@ struct connection_info {
void *crypto_temp;
int listening, listening_generation;
int window_clamp;
int left_tls_packet_length;

struct raw_message in_u, in, out, out_p;

Expand Down
53 changes: 45 additions & 8 deletions net/net-tcp-connections.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,22 @@ int cpu_tcp_aes_crypto_ctr128_encrypt_output (connection_job_t C) /* {{{ */ {

struct aes_crypto *T = c->crypto;
assert (c->crypto);
struct raw_message *out = &c->out;

int l = out->total_bytes;
if (l) {
assert (rwm_encrypt_decrypt_to (&c->out, &c->out_p, l, &T->write_aeskey, (void *)T->write_aeskey.type->ctr128_crypt, T->write_iv, 1, T->write_ebuf, &T->write_num) == l);
while (c->out.total_bytes) {
int len = c->out.total_bytes;
if (c->flags & C_IS_TLS) {
assert (c->left_tls_packet_length >= 0);
const int MAX_PACKET_LENGTH = 1425;
if (MAX_PACKET_LENGTH < len) {
len = MAX_PACKET_LENGTH;
}

unsigned char header[5] = {0x17, 0x03, 0x03, len >> 8, len & 255};
rwm_push_data (&c->out_p, header, 5);
vkprintf (2, "Send TLS-packet of length %d\n", len);
}

assert (rwm_encrypt_decrypt_to (&c->out, &c->out_p, len, &T->write_aeskey, (void *)T->write_aeskey.type->ctr128_crypt, T->write_iv, 1, T->write_ebuf, &T->write_num) == len);
}

return 0;
Expand All @@ -254,11 +265,37 @@ int cpu_tcp_aes_crypto_ctr128_decrypt_input (connection_job_t C) /* {{{ */ {
struct connection_info *c = CONN_INFO (C);
struct aes_crypto *T = c->crypto;
assert (c->crypto);
struct raw_message *in = &c->in_u;

int l = in->total_bytes;
if (l) {
assert (rwm_encrypt_decrypt_to (&c->in_u, &c->in, l, &T->read_aeskey, (void *)T->read_aeskey.type->ctr128_crypt, T->read_iv, 1, T->read_ebuf, &T->read_num) == l);
while (c->in_u.total_bytes) {
int len = c->in_u.total_bytes;
if (c->flags & C_IS_TLS) {
assert (c->left_tls_packet_length >= 0);
if (c->left_tls_packet_length == 0) {
if (len < 5) {
vkprintf (2, "Need %d more bytes to parse TLS header\n", 5 - len);
return 5 - len;
}

unsigned char header[5];
assert (rwm_fetch_lookup (&c->in_u, header, 5) == 5);
if (memcmp (header, "\x17\x03\x03", 3) != 0) {
vkprintf (1, "error while parsing packet: expect TLS header\n");
fail_connection (C, -1);
return 0;
}
c->left_tls_packet_length = 256 * header[3] + header[4];
vkprintf (2, "Receive TLS-packet of length %d\n", c->left_tls_packet_length);
assert (rwm_skip_data (&c->in_u, 5) == 5);
len -= 5;
}

if (c->left_tls_packet_length < len) {
len = c->left_tls_packet_length;
}
c->left_tls_packet_length -= len;
}
vkprintf (2, "Read %d bytes out of %d available\n", len, c->in_u.total_bytes);
assert (rwm_encrypt_decrypt_to (&c->in_u, &c->in, len, &T->read_aeskey, (void *)T->read_aeskey.type->ctr128_crypt, T->read_iv, 1, T->read_ebuf, &T->read_num) == len);
}

return 0;
Expand Down
5 changes: 5 additions & 0 deletions net/net-tcp-rpc-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ int tcp_rpc_write_packet_compact (connection_job_t C, struct raw_message *raw) {
rwm_union (&CONN_INFO(C)->out, raw);
return 0;
}
if ((CONN_INFO (C)->flags & C_IS_TLS) && CONN_INFO (C)->left_tls_packet_length == -1) {
// uninited TLS connection
rwm_union (&CONN_INFO(C)->out, raw);
return 0;
}

if (!(TCP_RPC_DATA(C)->flags & (RPC_F_COMPACT | RPC_F_MEDIUM))) {
return tcp_rpc_write_packet (C, raw);
Expand Down
20 changes: 10 additions & 10 deletions net/net-tcp-rpc-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,18 @@ void tcp_rpc_conn_send_data_im (JOB_REF_ARG (C), int len, void *Q);
int tcp_rpc_default_execute (connection_job_t C, int op, struct raw_message *raw);

/* for crypto_flags in struct tcp_rpc_data */
#define RPCF_ALLOW_UNENC 1
#define RPCF_ALLOW_ENC 2
#define RPCF_REQ_DH 4
#define RPCF_ALLOW_SKIP_DH 8
#define RPCF_ALLOW_UNENC 1 // allow unencrypted
#define RPCF_ALLOW_ENC 2 // allow encrypted
#define RPCF_REQ_DH 4 // require DH
#define RPCF_ALLOW_SKIP_DH 8 // crypto NONCE packet sent
#define RPCF_ENC_SENT 16
#define RPCF_SEQNO_HOLES 256
#define RPCF_QUICKACK 512
#define RPCF_COMPACT_OFF 1024
#define RPCF_USE_CRC32C 2048
#define RPCF_SEQNO_HOLES 256 // packet numbers not sequential
#define RPCF_QUICKACK 512 // allow quick ack packets
#define RPCF_COMPACT_OFF 1024 // compact mode off
#define RPCF_USE_CRC32C 2048 // use CRC32-C instead of CRC32

/* for flags in struct tcp_rpc_data */
#define RPC_F_PAD 0x8000000
#define RPC_F_PAD 0x8000000
#define RPC_F_DROPPED 0x10000000
#define RPC_F_MEDIUM 0x20000000
#define RPC_F_COMPACT 0x40000000
Expand All @@ -124,7 +124,7 @@ struct tcp_rpc_data {
int flags;
int in_packet_num;
int out_packet_num;
int crypto_flags; /* 1 = allow unencrypted, 2 = allow encrypted, 4 = require DH, 8 = crypto NONCE packet sent, 256 = packet numbers not sequential, 512 = allow quick ack packets, 1024 = compact mode off, 2048 = use CRC32-C instead of CRC32 */
int crypto_flags; /* RPCF_* flags */
struct process_id remote_pid;
char nonce[16];
int nonce_time;
Expand Down
Loading

0 comments on commit e4c6b8b

Please sign in to comment.