Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/majn/tgl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binlog.c125
-rw-r--r--binlog.tl6
l---------encrypted_scheme.tl2
-rw-r--r--encrypted_scheme18.tl38
-rw-r--r--mtproto-common.h1
-rw-r--r--queries.c154
-rw-r--r--queries.h5
-rw-r--r--structures.c108
-rw-r--r--tgl-binlog.h6
-rw-r--r--tgl-layout.h25
10 files changed, 454 insertions, 16 deletions
diff --git a/binlog.c b/binlog.c
index ae8142c..0f53f0f 100644
--- a/binlog.c
+++ b/binlog.c
@@ -505,6 +505,15 @@ static int fetch_comb_binlog_encr_chat_set_key (struct tgl_state *TLS, void *ext
return 0;
}
+static int fetch_comb_binlog_encr_chat_set_sha (struct tgl_state *TLS, void *extra) {
+ tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ());
+ tgl_peer_t *_U = tgl_peer_get (TLS, id);
+ assert (_U);
+ struct tgl_secret_chat *U = &_U->encr_chat;
+ fetch_ints (U->first_key_sha, 5);
+ return 0;
+}
+
static int fetch_comb_binlog_encr_chat_update_seq (struct tgl_state *TLS, void *extra) {
tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ());
tgl_peer_t *_U = tgl_peer_get (TLS, id);
@@ -1262,6 +1271,68 @@ static int fetch_comb_binlog_reset_authorization (struct tgl_state *TLS, void *e
return 0;
}
+static int fetch_comb_binlog_encr_chat_exchange_request (struct tgl_state *TLS, void *extra) {
+ tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (fetch_int ()));
+ assert (P);
+ P->encr_chat.exchange_id = fetch_long ();
+ fetch_ints (P->encr_chat.exchange_key, 64);
+ P->encr_chat.exchange_state = tgl_sce_requested;
+ return 0;
+}
+
+static int fetch_comb_binlog_encr_chat_exchange_accept (struct tgl_state *TLS, void *extra) {
+ tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (fetch_int ()));
+ assert (P);
+ P->encr_chat.exchange_id = fetch_long ();
+ fetch_ints (P->encr_chat.exchange_key, 64);
+ P->encr_chat.exchange_state = tgl_sce_accepted;
+
+ static unsigned char sha_buffer[20];
+ SHA1 ((unsigned char *)P->encr_chat.exchange_key, 256, sha_buffer);
+
+ P->encr_chat.exchange_key_fingerprint = *(long long *)sha_buffer;
+ return 0;
+}
+
+static int fetch_comb_binlog_encr_chat_exchange_commit (struct tgl_state *TLS, void *extra) {
+ tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (fetch_int ()));
+ assert (P);
+
+ memcpy (P->encr_chat.key, P->encr_chat.exchange_key, 256);
+ P->encr_chat.exchange_key_fingerprint = P->encr_chat.key_fingerprint;
+
+ fetch_ints (P->encr_chat.key, 64);
+ P->encr_chat.exchange_state = tgl_sce_committed;
+
+ static unsigned char sha_buffer[20];
+ SHA1 ((unsigned char *)P->encr_chat.key, 256, sha_buffer);
+
+ P->encr_chat.key_fingerprint = *(long long *)sha_buffer;
+ return 0;
+}
+
+static int fetch_comb_binlog_encr_chat_exchange_confirm (struct tgl_state *TLS, void *extra) {
+ tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (fetch_int ()));
+ assert (P);
+ if (P->encr_chat.exchange_state != tgl_sce_committed) {
+ memcpy (P->encr_chat.key, P->encr_chat.exchange_key, 256);
+ P->encr_chat.key_fingerprint = P->encr_chat.exchange_key_fingerprint;
+ }
+ P->encr_chat.exchange_state = tgl_sce_none;
+ return 0;
+}
+
+static int fetch_comb_binlog_encr_chat_exchange_abort (struct tgl_state *TLS, void *extra) {
+ tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (fetch_int ()));
+ assert (P);
+ if (P->encr_chat.exchange_state == tgl_sce_committed) {
+ memcpy (P->encr_chat.key, P->encr_chat.exchange_key, 256);
+ P->encr_chat.key_fingerprint = P->encr_chat.exchange_key_fingerprint;
+ }
+ P->encr_chat.exchange_state = tgl_sce_none;
+ return 0;
+}
+
#define FETCH_COMBINATOR_FUNCTION(NAME) \
case CODE_ ## NAME:\
ok = fetch_comb_ ## NAME (TLS, 0); \
@@ -1319,6 +1390,7 @@ static void replay_log_event (struct tgl_state *TLS) {
FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_state)
FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_accepted)
FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_key)
+ FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_sha)
FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_update_seq)
FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_seq)
FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_init)
@@ -1356,6 +1428,11 @@ static void replay_log_event (struct tgl_state *TLS) {
FETCH_COMBINATOR_FUNCTION (binlog_msg_seq_update)
FETCH_COMBINATOR_FUNCTION (binlog_msg_update)
FETCH_COMBINATOR_FUNCTION (binlog_reset_authorization)
+ FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_exchange_request)
+ FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_exchange_accept)
+ FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_exchange_commit)
+ FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_exchange_confirm)
+ FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_exchange_abort)
default:
vlogprintf (E_ERROR, "Unknown op 0x%08x\n", op);
assert (0);
@@ -1805,6 +1882,14 @@ void bl_do_encr_chat_set_key (struct tgl_state *TLS, struct tgl_secret_chat *E,
add_log_event (TLS, ev, 272);
}
+void bl_do_encr_chat_set_sha (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char sha[]) {
+ int *ev = alloc_log_event (28);
+ ev[0] = CODE_binlog_encr_chat_set_key;
+ ev[1] = tgl_get_peer_id (E->id);
+ memcpy (ev + 2, sha, 20);
+ add_log_event (TLS, ev, 28);
+}
+
void bl_do_encr_chat_update_seq (struct tgl_state *TLS, struct tgl_secret_chat *E, int in_seq_no, int out_seq_no) {
int *ev = alloc_log_event (16);
ev[0] = CODE_binlog_encr_chat_update_seq;
@@ -2248,6 +2333,46 @@ void bl_do_reset_authorization (struct tgl_state *TLS) {
out_int (CODE_binlog_reset_authorization);
add_log_event (TLS, packet_buffer, 4 * (packet_ptr - packet_buffer));
}
+
+
+void bl_do_encr_chat_exchange_request (struct tgl_state *TLS, struct tgl_secret_chat *E, long long id, unsigned char a[]) {
+ clear_packet ();
+ out_int (CODE_binlog_encr_chat_exchange_request);
+ out_int (tgl_get_peer_id (E->id));
+ out_long (id);
+ out_ints ((void *)a, 64);
+ add_log_event (TLS, packet_buffer, 4 * (packet_ptr - packet_buffer));
+}
+
+void bl_do_encr_chat_exchange_accept (struct tgl_state *TLS, struct tgl_secret_chat *E, long long id, unsigned char key[]) {
+ clear_packet ();
+ out_int (CODE_binlog_encr_chat_exchange_accept);
+ out_int (tgl_get_peer_id (E->id));
+ out_long (id);
+ out_ints ((void *)key, 64);
+ add_log_event (TLS, packet_buffer, 4 * (packet_ptr - packet_buffer));
+}
+void bl_do_encr_chat_exchange_commit (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char key[]) {
+ clear_packet ();
+ out_int (CODE_binlog_encr_chat_exchange_commit);
+ out_int (tgl_get_peer_id (E->id));
+ out_ints ((void *)key, 64);
+ add_log_event (TLS, packet_buffer, 4 * (packet_ptr - packet_buffer));
+}
+
+void bl_do_encr_chat_exchange_confirm (struct tgl_state *TLS, struct tgl_secret_chat *E) {
+ clear_packet ();
+ out_int (CODE_binlog_encr_chat_exchange_confirm);
+ out_int (tgl_get_peer_id (E->id));
+ add_log_event (TLS, packet_buffer, 4 * (packet_ptr - packet_buffer));
+}
+
+void bl_do_encr_chat_exchange_abort (struct tgl_state *TLS, struct tgl_secret_chat *E) {
+ clear_packet ();
+ out_int (CODE_binlog_encr_chat_exchange_abort);
+ out_int (tgl_get_peer_id (E->id));
+ add_log_event (TLS, packet_buffer, 4 * (packet_ptr - packet_buffer));
+}
/*void bl_do_add_dc (int id, const char *ip, int l, int port, long long auth_key_id, const char *auth_key) {
clear_packet ();
out_int (CODE_binlog_add_dc);
diff --git a/binlog.tl b/binlog.tl
index 9557b0c..fc9ac6c 100644
--- a/binlog.tl
+++ b/binlog.tl
@@ -41,6 +41,12 @@ binlog.encrChatSetTtl id:int ttl:int = binlog.Update;
binlog.encrChatSetLayer id:int layer:int = binlog.Update;
binlog.encrChatSetState id:int state:int = binlog.Update;
binlog.encrChatSetKey id:int key:64*[int] fingerprint:long = binlog.Update;
+binlog.encrChatSetSha id:int sha:5*[int] = binlog.Update;
+binlog.encrChatExchangeRequest id:int exchange_id:long a:64*[int] = binlog.Update;
+binlog.encrChatExchangeAccept id:int exchange_id:long key:64*[int] = binlog.Update;
+binlog.encrChatExchangeCommit id:int key:64*[int] = binlog.Update;
+binlog.encrChatExchangeConfirm id:int = binlog.Update;
+binlog.encrChatExchangeAbort id:int = binlog.Update;
binlog.encrChatUpdateSeq id:int in_seq_no:int out_seq_no:int = binlog.Update;
binlog.encrChatSetSeq id:int in_seq_no:int last_in_seq_no:int out_seq_no:int = binlog.Update;
diff --git a/encrypted_scheme.tl b/encrypted_scheme.tl
index b45af3d..1ec4bad 120000
--- a/encrypted_scheme.tl
+++ b/encrypted_scheme.tl
@@ -1 +1 @@
-encrypted_scheme17.tl \ No newline at end of file
+encrypted_scheme18.tl \ No newline at end of file
diff --git a/encrypted_scheme18.tl b/encrypted_scheme18.tl
new file mode 100644
index 0000000..037bb8d
--- /dev/null
+++ b/encrypted_scheme18.tl
@@ -0,0 +1,38 @@
+---types---
+decryptedMessageLayer#1be31789 layer:int message:DecryptedMessage = DecryptedMessageLayer;
+decryptedMessage_l16#1f814f1f random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
+decryptedMessageService_l16#aa48327d random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
+
+decryptedMessage#204d3878 in_seq_no:int out_seq_no:int ttl:int random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
+decryptedMessageService#73164160 in_seq_no:int out_seq_no:int random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
+
+decryptedMessageMediaEmpty#89f5c4a = DecryptedMessageMedia;
+decryptedMessageMediaPhoto#32798a8c thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
+//decryptedMessageMediaVideo#4cee6ef3 thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
+decryptedMessageMediaGeoPoint#35480a59 lat:double long:double = DecryptedMessageMedia;
+decryptedMessageMediaContact#588a0a97 phone_number:string first_name:string last_name:string user_id:int = DecryptedMessageMedia;
+decryptedMessageActionSetMessageTTL#a1733aec ttl_seconds:int = DecryptedMessageAction;
+
+decryptedMessageMediaDocument#b095434b thumb:bytes thumb_w:int thumb_h:int file_name:string mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
+//decryptedMessageMediaAudio#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
+
+decryptedMessageMediaVideo#524a415d thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
+decryptedMessageMediaAudio#57e0a9cb duration:int mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
+decryptedMessageActionReadMessages#c4f40be random_ids:Vector<long> = DecryptedMessageAction;
+decryptedMessageActionDeleteMessages#65614304 random_ids:Vector<long> = DecryptedMessageAction;
+decryptedMessageActionScreenshotMessages#8ac1f475 random_ids:Vector<long> = DecryptedMessageAction;
+decryptedMessageActionFlushHistory#6719e45c = DecryptedMessageAction;
+decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction;
+
+decryptedMessageActionResend#511110b0 start_seq_no:int end_seq_no:int = DecryptedMessageAction;
+
+decryptedMessageActionTyping#ccb27641 action:SendMessageAction = DecryptedMessageAction;
+
+decryptedMessageActionRequestKey exchange_id:long g_a:string = DecryptedMessageAction;
+decryptedMessageActionAcceptKey exchange_id:long g_b:string key_fingerprint:long = DecryptedMessageAction;
+decryptedMessageActionCommitKey exchange_id:long key_fingerprint:long = DecryptedMessageAction;
+decryptedMessageActionAbortKey exchange_id:long = DecryptedMessageAction;
+decryptedMessageActionNoop = DecryptedMessageAction;
+
+
+---functions---
diff --git a/mtproto-common.h b/mtproto-common.h
index a1d1ce5..85e7292 100644
--- a/mtproto-common.h
+++ b/mtproto-common.h
@@ -345,6 +345,7 @@ static inline void fetch256 (void *buf) {
char *s = fetch_str (l);
if (l < 256) {
memcpy (buf + 256 - l, s, l);
+ memset (buf, 0, 256 - l);
} else {
memcpy (buf, s + (l - 256), 256);
}
diff --git a/queries.c b/queries.c
index 2f04fc5..2a9d7b5 100644
--- a/queries.c
+++ b/queries.c
@@ -3095,6 +3095,7 @@ void tgl_do_send_accept_encr_chat (struct tgl_state *TLS, struct tgl_secret_chat
sha1 (kk, 256, sha_buffer);
bl_do_encr_chat_set_key (TLS, E, kk, *(long long *)(sha_buffer + 12));
+ bl_do_encr_chat_set_sha (TLS, E, sha_buffer);
clear_packet ();
out_int (CODE_messages_accept_encryption);
@@ -3149,6 +3150,7 @@ void tgl_do_create_keys_end (struct tgl_state *TLS, struct tgl_secret_chat *U) {
U->state = sc_deleted;
}
+ memcpy (U->first_key_sha, sha_buffer, 20);
tfree_secure (t, 256);
BN_clear_free (p);
@@ -3877,3 +3879,155 @@ void tgl_do_update_status (struct tgl_state *TLS, int online, void (*callback)(s
out_int (online ? CODE_bool_false : CODE_bool_true);
tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &update_status_methods, 0, callback, callback_extra);
}
+
+
+void tgl_do_request_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E) {
+ static unsigned char s[256];
+ tglt_secure_random (s, 256);
+
+ long long id;
+ tglt_secure_random (&id, 8);
+
+ bl_do_encr_chat_exchange_request (TLS, E, id, s);
+
+ BIGNUM *a = BN_bin2bn (s, 256, 0);
+ ensure_ptr (a);
+ BIGNUM *p = BN_bin2bn (TLS->encr_prime, 256, 0);
+ ensure_ptr (p);
+
+ BIGNUM *g = BN_new ();
+ ensure_ptr (g);
+
+ ensure (BN_set_word (g, TLS->encr_root));
+
+ BIGNUM *r = BN_new ();
+ ensure_ptr (r);
+
+ ensure (BN_mod_exp (r, g, a, p, TLS->BN_ctx));
+
+ static unsigned char kk[256];
+ memset (kk, 0, sizeof (kk));
+ BN_bn2bin (r, kk + (256 - BN_num_bytes (r)));
+
+ BN_clear_free (a);
+ BN_clear_free (g);
+ BN_clear_free (p);
+ BN_clear_free (r);
+
+ static int action[70];
+ action[0] = CODE_decrypted_message_action_request_key;
+ *(long long *)(action + 1) = E->exchange_id;
+ action[3] = 0x100fe;
+ memcpy (action + 4, kk, 256);
+
+ long long t;
+ tglt_secure_random (&t, 8);
+
+ bl_do_send_message_action_encr (TLS, t, TLS->our_id, tgl_get_peer_type (E->id), tgl_get_peer_id (E->id), time (0), 68, action);
+}
+
+void tgl_do_accept_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, long long exchange_id, unsigned char ga[]) {
+ static unsigned char s[256];
+ tglt_secure_random (s, 256);
+
+ BIGNUM *b = BN_bin2bn (s, 256, 0);
+ ensure_ptr (b);
+ BIGNUM *g_a = BN_bin2bn (ga, 256, 0);
+ ensure_ptr (g_a);
+
+ assert (tglmp_check_g (TLS, TLS->encr_prime, g_a) >= 0);
+ //if (!ctx) {
+ // ctx = BN_CTX_new ();
+ // ensure_ptr (ctx);
+ //}
+ BIGNUM *p = BN_bin2bn (TLS->encr_prime, 256, 0);
+ ensure_ptr (p);
+ BIGNUM *r = BN_new ();
+ ensure_ptr (r);
+ ensure (BN_mod_exp (r, g_a, b, p, TLS->BN_ctx));
+
+ static unsigned char kk[256];
+ memset (kk, 0, sizeof (kk));
+ BN_bn2bin (r, kk + (256 - BN_num_bytes (r)));
+
+ bl_do_encr_chat_exchange_accept (TLS, E, exchange_id, kk);
+
+ ensure (BN_set_word (g_a, TLS->encr_root));
+ ensure (BN_mod_exp (r, g_a, b, p, TLS->BN_ctx));
+
+ static unsigned char buf[256];
+ memset (buf, 0, sizeof (buf));
+ BN_bn2bin (r, buf + (256 - BN_num_bytes (r)));
+
+ static int action[70];
+ action[0] = CODE_decrypted_message_action_accept_key;
+ *(long long *)(action + 1) = E->exchange_id;
+ action[3] = 0x100fe;
+ memcpy (action + 4, buf, 256);
+ *(long long *)(action + 68) = E->exchange_key_fingerprint;
+
+ long long t;
+ tglt_secure_random (&t, 8);
+
+ bl_do_send_message_action_encr (TLS, t, TLS->our_id, tgl_get_peer_type (E->id), tgl_get_peer_id (E->id), time (0), 70, action);
+
+ BN_clear_free (b);
+ BN_clear_free (g_a);
+ BN_clear_free (p);
+ BN_clear_free (r);
+}
+
+void tgl_do_confirm_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, int sen_nop) {
+ bl_do_encr_chat_exchange_confirm (TLS, E);
+ if (sen_nop) {
+ int action = CODE_decrypted_message_action_noop;
+
+ long long t;
+ tglt_secure_random (&t, 8);
+
+ bl_do_send_message_action_encr (TLS, t, TLS->our_id, tgl_get_peer_type (E->id), tgl_get_peer_id (E->id), time (0), 1, &action);
+ }
+}
+
+void tgl_do_commit_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char gb[]) {
+ assert (TLS->encr_prime);
+
+ BIGNUM *g_b = BN_bin2bn (gb, 256, 0);
+ ensure_ptr (g_b);
+ assert (tglmp_check_g (TLS, TLS->encr_prime, g_b) >= 0);
+
+ BIGNUM *p = BN_bin2bn (TLS->encr_prime, 256, 0);
+ ensure_ptr (p);
+ BIGNUM *r = BN_new ();
+ ensure_ptr (r);
+ BIGNUM *a = BN_bin2bn ((void *)E->exchange_key, 256, 0);
+ ensure_ptr (a);
+ ensure (BN_mod_exp (r, g_b, a, p, TLS->BN_ctx));
+
+ static unsigned char s[256];
+ memset (s, 0, 256);
+
+ BN_bn2bin (r, s + (256 - BN_num_bytes (r)));
+
+ BN_clear_free (p);
+ BN_clear_free (g_b);
+ BN_clear_free (r);
+ BN_clear_free (a);
+
+
+ int action[4];
+ action[0] = CODE_decrypted_message_action_commit_key;
+ *(long long *)(action + 1) = E->exchange_id;
+ *(long long *)(action + 3) = E->key_fingerprint;
+
+ long long t;
+ tglt_secure_random (&t, 8);
+
+ bl_do_send_message_action_encr (TLS, t, TLS->our_id, tgl_get_peer_type (E->id), tgl_get_peer_id (E->id), time (0), 5, action);
+
+ bl_do_encr_chat_exchange_commit (TLS, E, s);
+}
+
+void tgl_do_abort_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E) {
+ bl_do_encr_chat_exchange_abort (TLS, E);
+}
diff --git a/queries.h b/queries.h
index cd43f5b..ffe63e1 100644
--- a/queries.h
+++ b/queries.h
@@ -68,6 +68,11 @@ double get_double_time (void);
void tgl_do_send_bind_temp_key (struct tgl_state *TLS, struct tgl_dc *D, long long nonce, int expires_at, void *data, int len, long long msg_id);
+void tgl_do_request_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E);
+void tgl_do_confirm_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, int sen_nop);
+void tgl_do_accept_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, long long exchange_id, unsigned char g_a[]);
+void tgl_do_commit_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char g_a[]);
+void tgl_do_abort_exchange (struct tgl_state *TLS, struct tgl_secret_chat *E);
// For binlog
//int get_dh_config_on_answer (struct query *q);
diff --git a/structures.c b/structures.c
index f59bed8..3d77888 100644
--- a/structures.c
+++ b/structures.c
@@ -1036,6 +1036,31 @@ void tglf_fetch_message_action_encrypted (struct tgl_state *TLS, struct tgl_mess
M->start_seq_no = fetch_int ();
M->end_seq_no = fetch_int ();
break;
+ case CODE_decrypted_message_action_noop:
+ M->type = tgl_message_action_noop;
+ break;
+ case CODE_decrypted_message_action_request_key:
+ M->type = tgl_message_action_request_key;
+ M->exchange_id = fetch_long ();
+ M->g_a = talloc (256);
+ fetch256 (M->g_a);
+ break;
+ case CODE_decrypted_message_action_accept_key:
+ M->type = tgl_message_action_request_key;
+ M->exchange_id = fetch_long ();
+ M->g_a = talloc (256);
+ fetch256 (M->g_a);
+ M->key_fingerprint = fetch_long ();
+ break;
+ case CODE_decrypted_message_action_commit_key:
+ M->type = tgl_message_action_request_key;
+ M->exchange_id = fetch_long ();
+ M->key_fingerprint = fetch_long ();
+ break;
+ case CODE_decrypted_message_action_abort_key:
+ M->type = tgl_message_action_request_key;
+ M->exchange_id = fetch_long ();
+ break;
default:
vlogprintf (E_ERROR, "x = 0x%08x\n", x);
assert (0);
@@ -1147,21 +1172,24 @@ static int decrypt_encrypted_message (struct tgl_secret_chat *E) {
static unsigned char sha1d_buffer[20];
static unsigned char buf[64];
+
+ int *e_key = E->exchange_state != tgl_sce_committed ? E->key : E->exchange_key;
+
memcpy (buf, msg_key, 16);
- memcpy (buf + 16, E->key, 32);
+ memcpy (buf + 16, e_key, 32);
sha1 (buf, 48, sha1a_buffer);
- memcpy (buf, E->key + 8, 16);
+ memcpy (buf, e_key + 8, 16);
memcpy (buf + 16, msg_key, 16);
- memcpy (buf + 32, E->key + 12, 16);
+ memcpy (buf + 32, e_key + 12, 16);
sha1 (buf, 48, sha1b_buffer);
- memcpy (buf, E->key + 16, 32);
+ memcpy (buf, e_key + 16, 32);
memcpy (buf + 32, msg_key, 16);
sha1 (buf, 48, sha1c_buffer);
memcpy (buf, msg_key, 16);
- memcpy (buf + 16, E->key + 24, 32);
+ memcpy (buf + 16, e_key + 24, 32);
sha1 (buf, 48, sha1d_buffer);
static unsigned char key[32];
@@ -1216,7 +1244,12 @@ void tglf_fetch_encrypted_message (struct tgl_state *TLS, struct tgl_message *M)
decr_end = decr_ptr + (len / 4);
int ok = 0;
if (P) {
- if (*(long long *)decr_ptr != P->encr_chat.key_fingerprint) {
+ if (P->encr_chat.exchange_state == tgl_sce_committed && P->encr_chat.key_fingerprint == *(long long *)decr_ptr) {
+ tgl_do_confirm_exchange (TLS, (void *)P, 0);
+ assert (P->encr_chat.exchange_state == tgl_sce_none);
+ }
+ long long key_fingerprint = P->encr_chat.exchange_state != tgl_sce_committed ? P->encr_chat.key_fingerprint : P->encr_chat.exchange_key_fingerprint;
+ if (*(long long *)decr_ptr != key_fingerprint) {
vlogprintf (E_WARNING, "Encrypted message with bad fingerprint to chat %s\n", P->print_name);
P = 0;
}
@@ -1483,6 +1516,44 @@ struct tgl_message *tglf_fetch_alloc_encrypted_message (struct tgl_state *TLS) {
assert (tgl_message_get (TLS, M->id) == M);
}
tglf_fetch_encrypted_message (TLS, M);
+
+ if (M->flags & FLAG_CREATED) {
+ tgl_peer_t *_E = tgl_peer_get (TLS, M->to_id);
+ assert (_E);
+ struct tgl_secret_chat *E = &_E->encr_chat;
+ if (M->action.type == tgl_message_action_request_key) {
+ if (E->exchange_state == tgl_sce_none || (E->exchange_state == tgl_sce_requested && E->exchange_id > M->action.exchange_id )) {
+ if (tglmp_check_g (TLS, TLS->encr_prime, (void *)M->action.g_a) < 0) {
+ vlogprintf (E_WARNING, "Exchange: Incorrect g_a\n");
+ } else {
+ tgl_do_accept_exchange (TLS, E, M->action.exchange_id, M->action.g_a);
+ }
+ } else {
+ vlogprintf (E_WARNING, "Exchange: Incorrect state (received request, state = %d)\n", E->exchange_state);
+ }
+ }
+ if (M->action.type == tgl_message_action_accept_key) {
+ if (E->exchange_state == tgl_sce_requested && E->exchange_id == M->action.exchange_id) {
+ tgl_do_commit_exchange (TLS, E, M->action.g_a);
+ } else {
+ vlogprintf (E_WARNING, "Exchange: Incorrect state (received accept, state = %d)\n", E->exchange_state);
+ }
+ }
+ if (M->action.type == tgl_message_action_commit_key) {
+ if (E->exchange_state == tgl_sce_accepted && E->exchange_id == M->action.exchange_id) {
+ tgl_do_confirm_exchange (TLS, E, 1);
+ } else {
+ vlogprintf (E_WARNING, "Exchange: Incorrect state (received commit, state = %d)\n", E->exchange_state);
+ }
+ }
+ if (M->action.type == tgl_message_action_abort_key) {
+ if (E->exchange_state != tgl_sce_none && E->exchange_id == M->action.exchange_id) {
+ tgl_do_abort_exchange (TLS, E);
+ } else {
+ vlogprintf (E_WARNING, "Exchange: Incorrect state (received abort, state = %d)\n", E->exchange_state);
+ }
+ }
+ }
return M;
}
@@ -1668,17 +1739,17 @@ void tgls_free_message_media (struct tgl_state *TLS, struct tgl_message_media *M
void tgls_free_message_action (struct tgl_state *TLS, struct tgl_message_action *M) {
switch (M->type) {
case tgl_message_action_none:
- break;
+ return;
case tgl_message_action_chat_create:
tfree_str (M->title);
tfree (M->users, M->user_num * 4);
- break;
+ return;
case tgl_message_action_chat_edit_title:
tfree_str (M->new_title);
- break;
+ return;
case tgl_message_action_chat_edit_photo:
tgls_free_photo (TLS, &M->photo);
- break;
+ return;
case tgl_message_action_chat_delete_photo:
case tgl_message_action_chat_add_user:
case tgl_message_action_chat_delete_user:
@@ -1689,14 +1760,23 @@ void tgls_free_message_action (struct tgl_state *TLS, struct tgl_message_action
case tgl_message_action_delete_messages:
case tgl_message_action_screenshot_messages:
case tgl_message_action_flush_history:
+ case tgl_message_action_typing:
case tgl_message_action_resend:
case tgl_message_action_notify_layer:
- break;
-
- default:
+ case tgl_message_action_commit_key:
+ case tgl_message_action_abort_key:
+ case tgl_message_action_noop:
+ return;
+ case tgl_message_action_request_key:
+ case tgl_message_action_accept_key:
+ tfree (M->g_a, 256);
+ return;
+/* default:
vlogprintf (E_ERROR, "type = 0x%08x\n", M->type);
- assert (0);
+ assert (0);*/
}
+ vlogprintf (E_ERROR, "type = 0x%08x\n", M->type);
+ assert (0);
}
void tgls_clear_message (struct tgl_state *TLS, struct tgl_message *M) {
diff --git a/tgl-binlog.h b/tgl-binlog.h
index e17c032..adbe27f 100644
--- a/tgl-binlog.h
+++ b/tgl-binlog.h
@@ -50,9 +50,15 @@ void bl_do_encr_chat_set_ttl (struct tgl_state *TLS, struct tgl_secret_chat *U,
void bl_do_encr_chat_set_layer (struct tgl_state *TLS, struct tgl_secret_chat *U, int layer);
void bl_do_encr_chat_accepted (struct tgl_state *TLS, struct tgl_secret_chat *U, const unsigned char g_key[], const unsigned char nonce[], long long key_fingerprint);
void bl_do_encr_chat_set_key (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char key[], long long key_fingerprint);
+void bl_do_encr_chat_set_sha (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char sha[]);
void bl_do_encr_chat_init (struct tgl_state *TLS, int id, int user_id, unsigned char random[], unsigned char g_a[]);
void bl_do_encr_chat_update_seq (struct tgl_state *TLS, struct tgl_secret_chat *E, int in_seq_no, int out_seq_no);
void bl_do_encr_chat_set_seq (struct tgl_state *TLS, struct tgl_secret_chat *E, int in_seq_no, int last_in_seq_no, int out_seq_no);
+void bl_do_encr_chat_exchange_request (struct tgl_state *TLS, struct tgl_secret_chat *E, long long id, unsigned char a[]);
+void bl_do_encr_chat_exchange_accept (struct tgl_state *TLS, struct tgl_secret_chat *E, long long id, unsigned char key[]);
+void bl_do_encr_chat_exchange_commit (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char key[]);
+void bl_do_encr_chat_exchange_confirm (struct tgl_state *TLS, struct tgl_secret_chat *E);
+void bl_do_encr_chat_exchange_abort (struct tgl_state *TLS, struct tgl_secret_chat *E);
void bl_do_dc_signed (struct tgl_state *TLS, int id);
void bl_do_set_working_dc (struct tgl_state *TLS, int num);
diff --git a/tgl-layout.h b/tgl-layout.h
index 50177ef..da87933 100644
--- a/tgl-layout.h
+++ b/tgl-layout.h
@@ -121,7 +121,12 @@ enum tgl_message_action_type {
tgl_message_action_flush_history,
tgl_message_action_resend,
tgl_message_action_notify_layer,
- tgl_message_action_typing
+ tgl_message_action_typing,
+ tgl_message_action_noop,
+ tgl_message_action_commit_key,
+ tgl_message_action_abort_key,
+ tgl_message_action_request_key,
+ tgl_message_action_accept_key
};
enum tgl_typing_status {
@@ -291,6 +296,13 @@ enum tgl_secret_chat_state {
sc_deleted
};
+enum tgl_secret_chat_exchange_state {
+ tgl_sce_none,
+ tgl_sce_requested,
+ tgl_sce_accepted,
+ tgl_sce_committed
+};
+
struct tgl_secret_chat {
tgl_peer_id_t id;
int flags;
@@ -315,6 +327,12 @@ struct tgl_secret_chat {
enum tgl_secret_chat_state state;
int key[64];
long long key_fingerprint;
+ unsigned char first_key_sha[20];
+
+ long long exchange_id;
+ enum tgl_secret_chat_exchange_state exchange_state;
+ int exchange_key[64];
+ long long exchange_key_fingerprint;
};
typedef union tgl_peer {
@@ -392,6 +410,11 @@ struct tgl_message_action {
int start_seq_no;
int end_seq_no;
};
+ struct {
+ unsigned char *g_a;
+ long long exchange_id;
+ long long key_fingerprint;
+ };
};
};