diff options
-rw-r--r-- | binlog.c | 125 | ||||
-rw-r--r-- | binlog.tl | 6 | ||||
l--------- | encrypted_scheme.tl | 2 | ||||
-rw-r--r-- | encrypted_scheme18.tl | 38 | ||||
-rw-r--r-- | mtproto-common.h | 1 | ||||
-rw-r--r-- | queries.c | 154 | ||||
-rw-r--r-- | queries.h | 5 | ||||
-rw-r--r-- | structures.c | 108 | ||||
-rw-r--r-- | tgl-binlog.h | 6 | ||||
-rw-r--r-- | tgl-layout.h | 25 |
10 files changed, 454 insertions, 16 deletions
@@ -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); @@ -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); } @@ -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); +} @@ -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; + }; }; }; |