Support for chat create
This commit is contained in:
parent
96f1807729
commit
a725c0959f
5 changed files with 175 additions and 5 deletions
|
@ -249,6 +249,7 @@ char *commands[] = {
|
|||
"search",
|
||||
"mark_read",
|
||||
"visualize_key",
|
||||
"create_secret_chat",
|
||||
0 };
|
||||
|
||||
int commands_flags[] = {
|
||||
|
@ -277,6 +278,7 @@ int commands_flags[] = {
|
|||
072,
|
||||
072,
|
||||
075,
|
||||
071,
|
||||
};
|
||||
|
||||
int get_complete_mode (void) {
|
||||
|
@ -743,6 +745,9 @@ void interpreter (char *line UU) {
|
|||
} else if (IS_WORD ("visualize_key")) {
|
||||
GET_PEER_ENCR_CHAT;
|
||||
do_visualize_key (id);
|
||||
} else if (IS_WORD ("create_secret_chat")) {
|
||||
GET_PEER;
|
||||
do_create_secret_chat (id);
|
||||
}
|
||||
#undef IS_WORD
|
||||
#undef RET
|
||||
|
|
8
loop.c
8
loop.c
|
@ -322,9 +322,9 @@ void read_secret_chat_file (void) {
|
|||
if (E->state != sc_waiting) {
|
||||
E->g_key = malloc (256);
|
||||
assert (read (fd, E->g_key, 256) == 256);
|
||||
E->nonce = malloc (256);
|
||||
assert (read (fd, E->nonce, 256) == 256);
|
||||
}
|
||||
E->nonce = malloc (256);
|
||||
assert (read (fd, E->nonce, 256) == 256);
|
||||
assert (read (fd, E->key, 256) == 256);
|
||||
assert (read (fd, &E->key_fingerprint, 8) == 8);
|
||||
insert_encrypted_chat (P);
|
||||
|
@ -368,7 +368,9 @@ void write_secret_chat_file (void) {
|
|||
if (Peers[i]->encr_chat.state != sc_waiting) {
|
||||
assert (write (fd, Peers[i]->encr_chat.g_key, 256) == 256);
|
||||
}
|
||||
assert (write (fd, Peers[i]->encr_chat.nonce, 256) == 256);
|
||||
if (Peers[i]->encr_chat.state != sc_waiting) {
|
||||
assert (write (fd, Peers[i]->encr_chat.nonce, 256) == 256);
|
||||
}
|
||||
assert (write (fd, Peers[i]->encr_chat.key, 256) == 256);
|
||||
assert (write (fd, &Peers[i]->encr_chat.key_fingerprint, 8) == 8);
|
||||
}
|
||||
|
|
157
queries.c
157
queries.c
|
@ -55,6 +55,7 @@ long long cur_uploaded_bytes;
|
|||
long long cur_downloading_bytes;
|
||||
long long cur_downloaded_bytes;
|
||||
|
||||
void out_peer_id (peer_id_t id);
|
||||
#define QUERY_TIMEOUT 0.3
|
||||
|
||||
#define memcmp8(a,b) memcmp ((a), (b), 8)
|
||||
|
@ -755,7 +756,6 @@ struct query_methods msg_send_encr_methods = {
|
|||
|
||||
int out_message_num;
|
||||
int our_id;
|
||||
void out_peer_id (peer_id_t id);
|
||||
|
||||
void do_send_encr_message (peer_id_t id, const char *msg, int len) {
|
||||
peer_t *P = user_chat_get (id);
|
||||
|
@ -1952,10 +1952,37 @@ int send_encr_accept_on_answer (struct query *q UU) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int send_encr_request_on_answer (struct query *q UU) {
|
||||
struct secret_chat *E = fetch_alloc_encrypted_chat ();
|
||||
logprintf ("state = %d\n", E->state);
|
||||
if (E->state == sc_deleted) {
|
||||
print_start ();
|
||||
push_color (COLOR_YELLOW);
|
||||
printf ("Encrypted connection with ");
|
||||
print_encr_chat_name (E->id, (void *)E);
|
||||
printf (" can not be established\n");
|
||||
pop_color ();
|
||||
print_end ();
|
||||
} else {
|
||||
print_start ();
|
||||
push_color (COLOR_YELLOW);
|
||||
printf ("Establishing connection with ");
|
||||
print_encr_chat_name (E->id, (void *)E);
|
||||
printf ("\n");
|
||||
pop_color ();
|
||||
print_end ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct query_methods send_encr_accept_methods = {
|
||||
.on_answer = send_encr_accept_on_answer
|
||||
};
|
||||
|
||||
struct query_methods send_encr_request_methods = {
|
||||
.on_answer = send_encr_request_on_answer
|
||||
};
|
||||
|
||||
int encr_root;
|
||||
unsigned char *encr_prime;
|
||||
int encr_param_version;
|
||||
|
@ -2010,6 +2037,94 @@ void do_send_accept_encr_chat (struct secret_chat *E, unsigned char *random) {
|
|||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_accept_methods, E);
|
||||
}
|
||||
|
||||
void do_create_keys_end (struct secret_chat *U) {
|
||||
if (!encr_prime) {
|
||||
rprintf (COLOR_YELLOW "Something failed in bad moment. Did not fail\n"COLOR_NORMAL);
|
||||
return;
|
||||
}
|
||||
BIGNUM *g_b = BN_bin2bn (U->g_key, 256, 0);
|
||||
assert (g_b);
|
||||
if (!ctx) {
|
||||
ctx = BN_CTX_new ();
|
||||
BN_CTX_init (ctx);
|
||||
}
|
||||
BIGNUM *p = BN_bin2bn (encr_prime, 256, 0);
|
||||
BIGNUM *r = BN_new ();
|
||||
BIGNUM *a = BN_bin2bn ((void *)U->key, 256, 0);
|
||||
BN_init (r);
|
||||
BN_mod_exp (r, g_b, a, p, ctx);
|
||||
|
||||
memset (U->key, 0, sizeof (U->key));
|
||||
BN_bn2bin (r, (void *)U->key);
|
||||
int i;
|
||||
for (i = 0; i < 64; i++) {
|
||||
U->key[i] ^= *(((int *)U->nonce) + i);
|
||||
}
|
||||
|
||||
static unsigned char sha_buffer[20];
|
||||
sha1 ((void *)U->key, 256, sha_buffer);
|
||||
long long k = *(long long *)(sha_buffer + 12);
|
||||
assert (k == U->key_fingerprint);
|
||||
|
||||
BN_clear_free (p);
|
||||
BN_clear_free (g_b);
|
||||
BN_clear_free (r);
|
||||
BN_clear_free (a);
|
||||
}
|
||||
|
||||
void do_send_create_encr_chat (struct secret_chat *E, unsigned char *random) {
|
||||
int i;
|
||||
for (i = 0; i < 64; i++) {
|
||||
*(((int *)random) + i) ^= mrand48 ();
|
||||
}
|
||||
if (!ctx) {
|
||||
ctx = BN_CTX_new ();
|
||||
BN_CTX_init (ctx);
|
||||
}
|
||||
BIGNUM *a = BN_bin2bn (random, 256, 0);
|
||||
assert (a);
|
||||
BIGNUM *p = BN_bin2bn (encr_prime, 256, 0);
|
||||
|
||||
BIGNUM *g = BN_new ();
|
||||
BN_init (g);
|
||||
|
||||
BN_set_word (g, encr_root);
|
||||
|
||||
BIGNUM *r = BN_new ();
|
||||
BN_init (r);
|
||||
|
||||
BN_mod_exp (r, g, a, p, ctx);
|
||||
|
||||
memcpy (E->key, random, 256);
|
||||
|
||||
static char g_a[256];
|
||||
memset (g_a, 0, 256);
|
||||
|
||||
BN_bn2bin (r, (void *)g_a);
|
||||
|
||||
clear_packet ();
|
||||
out_int (CODE_messages_request_encryption);
|
||||
peer_t *U = user_chat_get (MK_USER (E->user_id));
|
||||
assert (U);
|
||||
if (U && U->user.access_hash) {
|
||||
out_int (CODE_input_user_foreign);
|
||||
out_int (E->user_id);
|
||||
out_long (U->user.access_hash);
|
||||
} else {
|
||||
out_int (CODE_input_user_contact);
|
||||
out_int (E->user_id);
|
||||
}
|
||||
out_int (get_peer_id (E->id));
|
||||
out_cstring (g_a, 256);
|
||||
write_secret_chat_file ();
|
||||
|
||||
BN_clear_free (g);
|
||||
BN_clear_free (p);
|
||||
BN_clear_free (r);
|
||||
|
||||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E);
|
||||
}
|
||||
|
||||
int get_dh_config_on_answer (struct query *q UU) {
|
||||
unsigned x = fetch_int ();
|
||||
assert (x == CODE_messages_dh_config || x == CODE_messages_dh_config_not_modified);
|
||||
|
@ -2025,7 +2140,12 @@ int get_dh_config_on_answer (struct query *q UU) {
|
|||
assert (l == 256);
|
||||
unsigned char *random = (void *)fetch_str_dup ();
|
||||
if (q->extra) {
|
||||
do_send_accept_encr_chat (q->extra, random);
|
||||
struct secret_chat *E = q->extra;
|
||||
if (E->state == sc_request) {
|
||||
do_send_accept_encr_chat (q->extra, random);
|
||||
} else if (E->state == sc_none) {
|
||||
do_send_create_encr_chat (q->extra, random);
|
||||
}
|
||||
free (random);
|
||||
} else {
|
||||
free (random);
|
||||
|
@ -2046,6 +2166,16 @@ void do_accept_encr_chat_request (struct secret_chat *E) {
|
|||
out_int (256);
|
||||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, E);
|
||||
}
|
||||
|
||||
void do_create_encr_chat_request (struct secret_chat *E) {
|
||||
assert (E->state == sc_none);
|
||||
|
||||
clear_packet ();
|
||||
out_int (CODE_messages_get_dh_config);
|
||||
out_int (encr_param_version);
|
||||
out_int (256);
|
||||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, E);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Get difference */
|
||||
|
@ -2201,3 +2331,26 @@ void do_visualize_key (peer_id_t id) {
|
|||
print_end ();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Create secret chat */
|
||||
char *create_print_name (peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4);
|
||||
|
||||
void do_create_secret_chat (peer_id_t id) {
|
||||
assert (get_peer_type (id) == PEER_USER);
|
||||
peer_t *U = user_chat_get (id);
|
||||
if (!U) {
|
||||
rprintf ("Can not create chat with unknown user\n");
|
||||
}
|
||||
|
||||
peer_t *P = malloc (sizeof (*P));
|
||||
memset (P, 0, sizeof (*P));
|
||||
P->id = MK_ENCR_CHAT (lrand48 ());
|
||||
|
||||
P->encr_chat.user_id = get_peer_id (id);
|
||||
|
||||
insert_encrypted_chat (P);
|
||||
P->print_name = create_print_name (P->id, "!", U->user.first_name, U->user.last_name, 0);
|
||||
|
||||
do_create_encr_chat_request (&P->encr_chat);
|
||||
}
|
||||
/* }}} */
|
||||
|
|
|
@ -81,6 +81,8 @@ void do_get_user_info (peer_id_t id);
|
|||
void do_forward_message (peer_id_t id, int n);
|
||||
void do_rename_chat (peer_id_t id, char *name);
|
||||
void do_load_encr_video (struct encr_video *V, int next);
|
||||
void do_create_encr_chat_request (struct secret_chat *E);
|
||||
void do_create_secret_chat (peer_id_t id);
|
||||
|
||||
struct photo;
|
||||
struct video;
|
||||
|
@ -99,5 +101,6 @@ void do_accept_encr_chat_request (struct secret_chat *E);
|
|||
void do_get_difference (void);
|
||||
void do_mark_read (peer_id_t id);
|
||||
void do_visualize_key (peer_id_t id);
|
||||
void do_create_keys_end (struct secret_chat *U);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <openssl/rand.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/sha.h>
|
||||
#include "queries.h"
|
||||
|
||||
#define sha1 SHA1
|
||||
|
||||
|
@ -284,6 +285,9 @@ void fetch_encrypted_chat (struct secret_chat *U) {
|
|||
} else {
|
||||
assert (U->key_fingerprint == fetch_long ());
|
||||
}
|
||||
if (old_state == sc_waiting) {
|
||||
do_create_keys_end (U);
|
||||
}
|
||||
}
|
||||
if (U->state != old_state) {
|
||||
write_secret_chat_file ();
|
||||
|
@ -799,6 +803,9 @@ int decrypt_encrypted_message (struct secret_chat *E) {
|
|||
AES_ige_encrypt ((void *)decr_ptr, (void *)decr_ptr, 4 * (decr_end - decr_ptr), &aes_key, iv, 0);
|
||||
|
||||
int x = *(decr_ptr);
|
||||
if (x < 0 || (x & 3)) {
|
||||
return -1;
|
||||
}
|
||||
assert (x >= 0 && !(x & 3));
|
||||
sha1 ((void *)decr_ptr, 4 + x, sha1a_buffer);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue