mirror of
https://github.com/profanity-im/profanity.git
synced 2025-01-03 14:57:42 -05:00
Add support for encrypted carbon
Fix {signed,}_pre_key store
This commit is contained in:
parent
20ed86c58c
commit
9b8c1d7d2c
@ -510,7 +510,7 @@ sv_ev_incoming_message(char *barejid, char *resource, char *message, char *pgp_m
|
||||
}
|
||||
|
||||
void
|
||||
sv_ev_incoming_carbon(char *barejid, char *resource, char *message, char *pgp_message)
|
||||
sv_ev_incoming_carbon(char *barejid, char *resource, char *message, char *pgp_message, gboolean omemo)
|
||||
{
|
||||
gboolean new_win = FALSE;
|
||||
ProfChatWin *chatwin = wins_get_chat(barejid);
|
||||
|
@ -74,7 +74,7 @@ void sv_ev_room_banned(const char *const room, const char *const actor, const ch
|
||||
void sv_ev_room_occupent_banned(const char *const room, const char *const nick, const char *const actor,
|
||||
const char *const reason);
|
||||
void sv_ev_outgoing_carbon(char *barejid, char *message, char *pgp_message);
|
||||
void sv_ev_incoming_carbon(char *barejid, char *resource, char *message, char *pgp_message);
|
||||
void sv_ev_incoming_carbon(char *barejid, char *resource, char *message, char *pgp_message, gboolean omemo);
|
||||
void sv_ev_xmpp_stanza(const char *const msg);
|
||||
void sv_ev_muc_self_online(const char *const room, const char *const nick, gboolean config_required,
|
||||
const char *const role, const char *const affiliation, const char *const actor, const char *const reason,
|
||||
|
@ -42,8 +42,7 @@ struct omemo_context_t {
|
||||
GHashTable *device_list_handler;
|
||||
ratchet_identity_key_pair *identity_key_pair;
|
||||
uint32_t registration_id;
|
||||
signal_protocol_key_helper_pre_key_list_node *pre_keys_head;
|
||||
session_signed_pre_key *signed_pre_key;
|
||||
uint32_t signed_pre_key_id;
|
||||
signal_protocol_store_context *store;
|
||||
GHashTable *session_store;
|
||||
GHashTable *pre_key_store;
|
||||
@ -132,7 +131,7 @@ omemo_init(void)
|
||||
.contains_signed_pre_key = contains_signed_pre_key,
|
||||
.remove_signed_pre_key = remove_signed_pre_key,
|
||||
.destroy_func = NULL,
|
||||
.user_data = omemo_ctx.pre_key_store
|
||||
.user_data = omemo_ctx.signed_pre_key_store
|
||||
};
|
||||
signal_protocol_store_context_set_signed_pre_key_store(omemo_ctx.store, &signed_pre_key_store);
|
||||
|
||||
@ -246,12 +245,23 @@ omemo_generate_crypto_materials(ProfAccount *account)
|
||||
static void
|
||||
omemo_generate_short_term_crypto_materials(ProfAccount *account)
|
||||
{
|
||||
signal_protocol_key_helper_generate_pre_keys(&omemo_ctx.pre_keys_head, randombytes_random(), 100, omemo_ctx.signal);
|
||||
signal_protocol_key_helper_pre_key_list_node *pre_keys_head;
|
||||
signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, randombytes_random(), 100, omemo_ctx.signal);
|
||||
|
||||
session_signed_pre_key *signed_pre_key;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
unsigned long long timestamp = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;
|
||||
signal_protocol_key_helper_generate_signed_pre_key(&omemo_ctx.signed_pre_key, omemo_ctx.identity_key_pair, 5, timestamp, omemo_ctx.signal);
|
||||
|
||||
omemo_ctx.signed_pre_key_id = 1;
|
||||
signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, omemo_ctx.identity_key_pair, omemo_ctx.signed_pre_key_id, timestamp, omemo_ctx.signal);
|
||||
|
||||
signal_protocol_key_helper_pre_key_list_node *p;
|
||||
for (p = pre_keys_head; p != NULL; p = signal_protocol_key_helper_key_list_next(p)) {
|
||||
session_pre_key *prekey = signal_protocol_key_helper_key_list_element(p);
|
||||
signal_protocol_pre_key_store_key(omemo_ctx.store, prekey);
|
||||
}
|
||||
signal_protocol_signed_pre_key_store_key(omemo_ctx.store, signed_pre_key);
|
||||
|
||||
loaded = TRUE;
|
||||
|
||||
@ -308,8 +318,11 @@ omemo_identity_key(unsigned char **output, size_t *length)
|
||||
void
|
||||
omemo_signed_prekey(unsigned char **output, size_t *length)
|
||||
{
|
||||
session_signed_pre_key *signed_pre_key;
|
||||
signal_buffer *buffer = NULL;
|
||||
ec_public_key_serialize(&buffer, ec_key_pair_get_public(session_signed_pre_key_get_key_pair(omemo_ctx.signed_pre_key)));
|
||||
|
||||
signal_protocol_signed_pre_key_load_key(omemo_ctx.store, &signed_pre_key, omemo_ctx.signed_pre_key_id);
|
||||
ec_public_key_serialize(&buffer, ec_key_pair_get_public(session_signed_pre_key_get_key_pair(signed_pre_key)));
|
||||
*length = signal_buffer_len(buffer);
|
||||
*output = malloc(*length);
|
||||
memcpy(*output, signal_buffer_data(buffer), *length);
|
||||
@ -319,25 +332,36 @@ omemo_signed_prekey(unsigned char **output, size_t *length)
|
||||
void
|
||||
omemo_signed_prekey_signature(unsigned char **output, size_t *length)
|
||||
{
|
||||
*length = session_signed_pre_key_get_signature_len(omemo_ctx.signed_pre_key);
|
||||
session_signed_pre_key *signed_pre_key;
|
||||
|
||||
signal_protocol_signed_pre_key_load_key(omemo_ctx.store, &signed_pre_key, omemo_ctx.signed_pre_key_id);
|
||||
*length = session_signed_pre_key_get_signature_len(signed_pre_key);
|
||||
*output = malloc(*length);
|
||||
memcpy(*output, session_signed_pre_key_get_signature(omemo_ctx.signed_pre_key), *length);
|
||||
memcpy(*output, session_signed_pre_key_get_signature(signed_pre_key), *length);
|
||||
}
|
||||
|
||||
void
|
||||
omemo_prekeys(GList **prekeys, GList **ids, GList **lengths)
|
||||
{
|
||||
signal_protocol_key_helper_pre_key_list_node *p;
|
||||
for (p = omemo_ctx.pre_keys_head; p != NULL; p = signal_protocol_key_helper_key_list_next(p)) {
|
||||
session_pre_key *prekey = signal_protocol_key_helper_key_list_element(p);
|
||||
signal_buffer *buffer = NULL;
|
||||
ec_public_key_serialize(&buffer, ec_key_pair_get_public(session_pre_key_get_key_pair(prekey)));
|
||||
size_t length = signal_buffer_len(buffer);
|
||||
GHashTableIter iter;
|
||||
gpointer id;
|
||||
|
||||
g_hash_table_iter_init(&iter, omemo_ctx.pre_key_store);
|
||||
while (g_hash_table_iter_next(&iter, &id, NULL)) {
|
||||
session_pre_key *pre_key;
|
||||
int ret;
|
||||
ret = signal_protocol_pre_key_load_key(omemo_ctx.store, &pre_key, GPOINTER_TO_INT(id));
|
||||
if (ret != SG_SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
signal_buffer *public_key;
|
||||
ec_public_key_serialize(&public_key, ec_key_pair_get_public(session_pre_key_get_key_pair(pre_key)));
|
||||
size_t length = signal_buffer_len(public_key);
|
||||
unsigned char *prekey_value = malloc(length);
|
||||
memcpy(prekey_value, signal_buffer_data(buffer), length);
|
||||
signal_buffer_free(buffer);
|
||||
memcpy(prekey_value, signal_buffer_data(public_key), length);
|
||||
*prekeys = g_list_append(*prekeys, prekey_value);
|
||||
*ids = g_list_append(*ids, GINT_TO_POINTER(session_pre_key_get_id(prekey)));
|
||||
*ids = g_list_append(*ids, GINT_TO_POINTER(id));
|
||||
*lengths = g_list_append(*lengths, GINT_TO_POINTER(length));
|
||||
}
|
||||
}
|
||||
@ -349,6 +373,10 @@ omemo_set_device_list(const char *const jid, GList * device_list)
|
||||
char *barejid = xmpp_jid_bare(ctx, jid);
|
||||
|
||||
g_hash_table_insert(omemo_ctx.device_list, strdup(barejid), device_list);
|
||||
if (strchr(barejid, '@') == NULL) {
|
||||
// barejid is server so we should handle it as our own device list
|
||||
g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), handle_own_device_list);
|
||||
}
|
||||
|
||||
OmemoDeviceListHandler handler = g_hash_table_lookup(omemo_ctx.device_list_handler, barejid);
|
||||
if (handler) {
|
||||
@ -397,16 +425,13 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean
|
||||
int res;
|
||||
xmpp_ctx_t * const ctx = connection_get_ctx();
|
||||
char *barejid = xmpp_jid_bare(ctx, session_get_account_name());
|
||||
GList *device_ids = NULL;
|
||||
|
||||
GList *recipient_device_id = g_hash_table_lookup(omemo_ctx.device_list, chatwin->barejid);
|
||||
if (!recipient_device_id) {
|
||||
return FALSE;
|
||||
}
|
||||
device_ids = g_list_copy(recipient_device_id);
|
||||
|
||||
GList *sender_device_id = g_hash_table_lookup(omemo_ctx.device_list, barejid);
|
||||
device_ids = g_list_concat(device_ids, g_list_copy(sender_device_id));
|
||||
|
||||
/* TODO generate fresh AES-GCM materials */
|
||||
/* TODO encrypt message */
|
||||
@ -430,7 +455,7 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean
|
||||
|
||||
GList *keys = NULL;
|
||||
GList *device_ids_iter;
|
||||
for (device_ids_iter = device_ids; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
|
||||
for (device_ids_iter = recipient_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
|
||||
int res;
|
||||
ciphertext_message *ciphertext;
|
||||
session_cipher *cipher;
|
||||
@ -452,7 +477,33 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean
|
||||
key->data = signal_buffer_data(buffer);
|
||||
key->length = signal_buffer_len(buffer);
|
||||
key->device_id = GPOINTER_TO_INT(device_ids_iter->data);
|
||||
key->prekey = TRUE;
|
||||
key->prekey = ciphertext_message_get_type(ciphertext) == CIPHERTEXT_PREKEY_TYPE;
|
||||
keys = g_list_append(keys, key);
|
||||
}
|
||||
|
||||
for (device_ids_iter = sender_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
|
||||
int res;
|
||||
ciphertext_message *ciphertext;
|
||||
session_cipher *cipher;
|
||||
signal_protocol_address address = {
|
||||
barejid, strlen(barejid), GPOINTER_TO_INT(device_ids_iter->data)
|
||||
};
|
||||
|
||||
res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal);
|
||||
if (res != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res = session_cipher_encrypt(cipher, key, AES128_GCM_KEY_LENGTH, &ciphertext);
|
||||
if (res != 0) {
|
||||
continue;
|
||||
}
|
||||
signal_buffer *buffer = ciphertext_message_get_serialized(ciphertext);
|
||||
omemo_key_t *key = malloc(sizeof(omemo_key_t));
|
||||
key->data = signal_buffer_data(buffer);
|
||||
key->length = signal_buffer_len(buffer);
|
||||
key->device_id = GPOINTER_TO_INT(device_ids_iter->data);
|
||||
key->prekey = ciphertext_message_get_type(ciphertext) == CIPHERTEXT_PREKEY_TYPE;
|
||||
keys = g_list_append(keys, key);
|
||||
}
|
||||
|
||||
@ -465,7 +516,6 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean
|
||||
free(ciphertext);
|
||||
sodium_free(key);
|
||||
sodium_free(iv);
|
||||
g_list_free(device_ids);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -544,7 +594,7 @@ unlock(void *user_data)
|
||||
static void
|
||||
omemo_log(int level, const char *message, size_t len, void *user_data)
|
||||
{
|
||||
cons_show(message);
|
||||
cons_show("OMEMO: %s", message);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -559,6 +609,11 @@ handle_own_device_list(const char *const jid, GList *device_list)
|
||||
omemo_devicelist_publish(device_list);
|
||||
}
|
||||
|
||||
GList *device_id;
|
||||
for (device_id = device_list; device_id != NULL; device_id = device_id->next) {
|
||||
omemo_bundle_request(jid, GPOINTER_TO_INT(device_id->data), omemo_start_device_session_handle_bundle, free, strdup(jid));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -96,9 +96,19 @@ store_session(const signal_protocol_address *address, uint8_t *record,
|
||||
int
|
||||
contains_session(const signal_protocol_address *address, void *user_data)
|
||||
{
|
||||
signal_buffer *record;
|
||||
load_session(&record, address, user_data);
|
||||
return record != NULL;
|
||||
GHashTable *session_store = (GHashTable *)user_data;
|
||||
GHashTable *device_store = NULL;
|
||||
|
||||
device_store = g_hash_table_lookup(session_store, address->name);
|
||||
if (!device_store) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!g_hash_table_lookup(device_store, GINT_TO_POINTER(address->device_id))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
@ -134,9 +144,15 @@ delete_all_sessions(const char *name, size_t name_len, void *user_data)
|
||||
int
|
||||
load_pre_key(signal_buffer **record, uint32_t pre_key_id, void *user_data)
|
||||
{
|
||||
signal_buffer *original;
|
||||
GHashTable *pre_key_store = (GHashTable *)user_data;
|
||||
|
||||
*record = g_hash_table_lookup(pre_key_store, GINT_TO_POINTER(pre_key_id));
|
||||
original = g_hash_table_lookup(pre_key_store, GINT_TO_POINTER(pre_key_id));
|
||||
if (original == NULL) {
|
||||
return SG_ERR_INVALID_KEY_ID;
|
||||
}
|
||||
|
||||
*record = signal_buffer_copy(original);
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
@ -154,10 +170,9 @@ store_pre_key(uint32_t pre_key_id, uint8_t *record, size_t record_len,
|
||||
int
|
||||
contains_pre_key(uint32_t pre_key_id, void *user_data)
|
||||
{
|
||||
signal_buffer *record;
|
||||
load_pre_key(&record, pre_key_id, user_data);
|
||||
GHashTable *pre_key_store = (GHashTable *)user_data;
|
||||
|
||||
return record != NULL;
|
||||
return g_hash_table_lookup(pre_key_store, GINT_TO_POINTER(pre_key_id)) != NULL;
|
||||
}
|
||||
|
||||
int
|
||||
@ -172,9 +187,15 @@ int
|
||||
load_signed_pre_key(signal_buffer **record, uint32_t signed_pre_key_id,
|
||||
void *user_data)
|
||||
{
|
||||
signal_buffer *original;
|
||||
GHashTable *signed_pre_key_store = (GHashTable *)user_data;
|
||||
|
||||
*record = g_hash_table_lookup(signed_pre_key_store, GINT_TO_POINTER(signed_pre_key_id));
|
||||
original = g_hash_table_lookup(signed_pre_key_store, GINT_TO_POINTER(signed_pre_key_id));
|
||||
if (!original) {
|
||||
return SG_ERR_INVALID_KEY_ID;
|
||||
}
|
||||
|
||||
*record = signal_buffer_copy(original);
|
||||
return SG_SUCCESS;
|
||||
}
|
||||
|
||||
@ -192,10 +213,9 @@ store_signed_pre_key(uint32_t signed_pre_key_id, uint8_t *record,
|
||||
int
|
||||
contains_signed_pre_key(uint32_t signed_pre_key_id, void *user_data)
|
||||
{
|
||||
signal_buffer *record;
|
||||
load_signed_pre_key(&record, signed_pre_key_id, user_data);
|
||||
GHashTable *signed_pre_key_store = (GHashTable *)user_data;
|
||||
|
||||
return record != NULL;
|
||||
return g_hash_table_lookup(signed_pre_key_store, GINT_TO_POINTER(signed_pre_key_id)) != NULL;
|
||||
}
|
||||
|
||||
int
|
||||
@ -251,7 +271,7 @@ is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data,
|
||||
signal_buffer *buffer = signal_buffer_create(key_data, key_len);
|
||||
signal_buffer *original = g_hash_table_lookup(identity_key_store->identity_key_store, node);
|
||||
|
||||
return original == NULL || signal_buffer_compare(buffer, original);
|
||||
return original == NULL || signal_buffer_compare(buffer, original) == 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -18,23 +18,221 @@ GHashTable * pre_key_store_new(void);
|
||||
GHashTable * signed_pre_key_store_new(void);
|
||||
void identity_key_store_new(identity_key_store_t *identity_key_store);
|
||||
|
||||
/**
|
||||
* Returns a copy of the serialized session record corresponding to the
|
||||
* provided recipient ID + device ID tuple.
|
||||
*
|
||||
* @param record pointer to a freshly allocated buffer containing the
|
||||
* serialized session record. Unset if no record was found.
|
||||
* The Signal Protocol library is responsible for freeing this buffer.
|
||||
* @param address the address of the remote client
|
||||
* @return 1 if the session was loaded, 0 if the session was not found, negative on failure
|
||||
*/
|
||||
int load_session(signal_buffer **record, const signal_protocol_address *address, void *user_data);
|
||||
|
||||
/**
|
||||
* Returns all known devices with active sessions for a recipient
|
||||
*
|
||||
* @param pointer to an array that will be allocated and populated with the result
|
||||
* @param name the name of the remote client
|
||||
* @param name_len the length of the name
|
||||
* @return size of the sessions array, or negative on failure
|
||||
*/
|
||||
int get_sub_device_sessions(signal_int_list **sessions, const char *name, size_t name_len, void *user_data);
|
||||
|
||||
/**
|
||||
* Commit to storage the session record for a given
|
||||
* recipient ID + device ID tuple.
|
||||
*
|
||||
* @param address the address of the remote client
|
||||
* @param record pointer to a buffer containing the serialized session
|
||||
* record for the remote client
|
||||
* @param record_len length of the serialized session record
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
int store_session(const signal_protocol_address *address, uint8_t *record, size_t record_len, void *user_data);
|
||||
|
||||
/**
|
||||
* Determine whether there is a committed session record for a
|
||||
* recipient ID + device ID tuple.
|
||||
*
|
||||
* @param address the address of the remote client
|
||||
* @return 1 if a session record exists, 0 otherwise.
|
||||
*/
|
||||
int contains_session(const signal_protocol_address *address, void *user_data);
|
||||
|
||||
/**
|
||||
* Remove a session record for a recipient ID + device ID tuple.
|
||||
*
|
||||
* @param address the address of the remote client
|
||||
* @return 1 if a session was deleted, 0 if a session was not deleted, negative on error
|
||||
*/
|
||||
int delete_session(const signal_protocol_address *address, void *user_data);
|
||||
|
||||
/**
|
||||
* Remove the session records corresponding to all devices of a recipient ID.
|
||||
*
|
||||
* @param name the name of the remote client
|
||||
* @param name_len the length of the name
|
||||
* @return the number of deleted sessions on success, negative on failure
|
||||
*/
|
||||
int delete_all_sessions(const char *name, size_t name_len, void *user_data);
|
||||
|
||||
/**
|
||||
* Load a local serialized PreKey record.
|
||||
*
|
||||
* @param record pointer to a newly allocated buffer containing the record,
|
||||
* if found. Unset if no record was found.
|
||||
* The Signal Protocol library is responsible for freeing this buffer.
|
||||
* @param pre_key_id the ID of the local serialized PreKey record
|
||||
* @retval SG_SUCCESS if the key was found
|
||||
* @retval SG_ERR_INVALID_KEY_ID if the key could not be found
|
||||
*/
|
||||
int load_pre_key(signal_buffer **record, uint32_t pre_key_id, void *user_data);
|
||||
|
||||
/**
|
||||
* Store a local serialized PreKey record.
|
||||
*
|
||||
* @param pre_key_id the ID of the PreKey record to store.
|
||||
* @param record pointer to a buffer containing the serialized record
|
||||
* @param record_len length of the serialized record
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
int store_pre_key(uint32_t pre_key_id, uint8_t *record, size_t record_len, void *user_data);
|
||||
|
||||
/**
|
||||
* Determine whether there is a committed PreKey record matching the
|
||||
* provided ID.
|
||||
*
|
||||
* @param pre_key_id A PreKey record ID.
|
||||
* @return 1 if the store has a record for the PreKey ID, 0 otherwise
|
||||
*/
|
||||
int contains_pre_key(uint32_t pre_key_id, void *user_data);
|
||||
|
||||
/**
|
||||
* Delete a PreKey record from local storage.
|
||||
*
|
||||
* @param pre_key_id The ID of the PreKey record to remove.
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
int remove_pre_key(uint32_t pre_key_id, void *user_data);
|
||||
|
||||
/**
|
||||
* Load a local serialized signed PreKey record.
|
||||
*
|
||||
* @param record pointer to a newly allocated buffer containing the record,
|
||||
* if found. Unset if no record was found.
|
||||
* The Signal Protocol library is responsible for freeing this buffer.
|
||||
* @param signed_pre_key_id the ID of the local signed PreKey record
|
||||
* @retval SG_SUCCESS if the key was found
|
||||
* @retval SG_ERR_INVALID_KEY_ID if the key could not be found
|
||||
*/
|
||||
int load_signed_pre_key(signal_buffer **record, uint32_t signed_pre_key_id, void *user_data);
|
||||
|
||||
/**
|
||||
* Store a local serialized signed PreKey record.
|
||||
*
|
||||
* @param signed_pre_key_id the ID of the signed PreKey record to store
|
||||
* @param record pointer to a buffer containing the serialized record
|
||||
* @param record_len length of the serialized record
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
int store_signed_pre_key(uint32_t signed_pre_key_id, uint8_t *record, size_t record_len, void *user_data);
|
||||
|
||||
/**
|
||||
* Determine whether there is a committed signed PreKey record matching
|
||||
* the provided ID.
|
||||
*
|
||||
* @param signed_pre_key_id A signed PreKey record ID.
|
||||
* @return 1 if the store has a record for the signed PreKey ID, 0 otherwise
|
||||
*/
|
||||
int contains_signed_pre_key(uint32_t signed_pre_key_id, void *user_data);
|
||||
|
||||
/**
|
||||
* Delete a SignedPreKeyRecord from local storage.
|
||||
*
|
||||
* @param signed_pre_key_id The ID of the signed PreKey record to remove.
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
int remove_signed_pre_key(uint32_t signed_pre_key_id, void *user_data);
|
||||
|
||||
/**
|
||||
* Get the local client's identity key pair.
|
||||
*
|
||||
* @param public_data pointer to a newly allocated buffer containing the
|
||||
* public key, if found. Unset if no record was found.
|
||||
* The Signal Protocol library is responsible for freeing this buffer.
|
||||
* @param private_data pointer to a newly allocated buffer containing the
|
||||
* private key, if found. Unset if no record was found.
|
||||
* The Signal Protocol library is responsible for freeing this buffer.
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
int get_identity_key_pair(signal_buffer **public_data, signal_buffer **private_data, void *user_data);
|
||||
|
||||
/**
|
||||
* Return the local client's registration ID.
|
||||
*
|
||||
* Clients should maintain a registration ID, a random number
|
||||
* between 1 and 16380 that's generated once at install time.
|
||||
*
|
||||
* @param registration_id pointer to be set to the local client's
|
||||
* registration ID, if it was successfully retrieved.
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
int get_local_registration_id(void *user_data, uint32_t *registration_id);
|
||||
|
||||
/**
|
||||
* Save a remote client's identity key
|
||||
* <p>
|
||||
* Store a remote client's identity key as trusted.
|
||||
* The value of key_data may be null. In this case remove the key data
|
||||
* from the identity store, but retain any metadata that may be kept
|
||||
* alongside it.
|
||||
*
|
||||
* @param address the address of the remote client
|
||||
* @param key_data Pointer to the remote client's identity key, may be null
|
||||
* @param key_len Length of the remote client's identity key
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
int save_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data);
|
||||
|
||||
/**
|
||||
* Verify a remote client's identity key.
|
||||
*
|
||||
* Determine whether a remote client's identity is trusted. Convention is
|
||||
* that the TextSecure protocol is 'trust on first use.' This means that
|
||||
* an identity key is considered 'trusted' if there is no entry for the recipient
|
||||
* in the local store, or if it matches the saved key for a recipient in the local
|
||||
* store. Only if it mismatches an entry in the local store is it considered
|
||||
* 'untrusted.'
|
||||
*
|
||||
* @param address the address of the remote client
|
||||
* @param identityKey The identity key to verify.
|
||||
* @param key_data Pointer to the identity key to verify
|
||||
* @param key_len Length of the identity key to verify
|
||||
* @return 1 if trusted, 0 if untrusted, negative on failure
|
||||
*/
|
||||
int is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data);
|
||||
|
||||
/**
|
||||
* Store a serialized sender key record for a given
|
||||
* (groupId + senderId + deviceId) tuple.
|
||||
*
|
||||
* @param sender_key_name the (groupId + senderId + deviceId) tuple
|
||||
* @param record pointer to a buffer containing the serialized record
|
||||
* @param record_len length of the serialized record
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
int store_sender_key(const signal_protocol_sender_key_name *sender_key_name, uint8_t *record, size_t record_len, uint8_t *user_record, size_t user_record_len, void *user_data);
|
||||
|
||||
/**
|
||||
* Returns a copy of the sender key record corresponding to the
|
||||
* (groupId + senderId + deviceId) tuple.
|
||||
*
|
||||
* @param record pointer to a newly allocated buffer containing the record,
|
||||
* if found. Unset if no record was found.
|
||||
* The Signal Protocol library is responsible for freeing this buffer.
|
||||
* @param sender_key_name the (groupId + senderId + deviceId) tuple
|
||||
* @return 1 if the record was loaded, 0 if the record was not found, negative on failure
|
||||
*/
|
||||
int load_sender_key(signal_buffer **record, signal_buffer **user_record, const signal_protocol_sender_key_name *sender_key_name, void *user_data);
|
||||
|
@ -840,6 +840,7 @@ _private_chat_handler(xmpp_stanza_t *const stanza, const char *const fulljid)
|
||||
static gboolean
|
||||
_handle_carbons(xmpp_stanza_t *const stanza)
|
||||
{
|
||||
char *message_txt;
|
||||
xmpp_stanza_t *carbons = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CARBONS);
|
||||
if (!carbons) {
|
||||
return FALSE;
|
||||
@ -873,10 +874,19 @@ _handle_carbons(xmpp_stanza_t *const stanza)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char *message_txt = xmpp_message_get_body(message);
|
||||
// check omemo encryption
|
||||
gboolean omemo = FALSE;
|
||||
#ifdef HAVE_OMEMO
|
||||
message_txt = omemo_receive_message(message);
|
||||
omemo = message_txt != NULL;
|
||||
#endif
|
||||
|
||||
if (!message_txt) {
|
||||
log_warning("Carbon received with no message.");
|
||||
return TRUE;
|
||||
message_txt = xmpp_message_get_body(message);
|
||||
if (!message_txt) {
|
||||
log_warning("Carbon received with no message.");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Jid *my_jid = jid_create(connection_get_fulljid());
|
||||
@ -904,7 +914,7 @@ _handle_carbons(xmpp_stanza_t *const stanza)
|
||||
|
||||
// if we are the recipient, treat as standard incoming message
|
||||
if (g_strcmp0(my_jid->barejid, jid_to->barejid) == 0) {
|
||||
sv_ev_incoming_carbon(jid_from->barejid, jid_from->resourcepart, message_txt, enc_message);
|
||||
sv_ev_incoming_carbon(jid_from->barejid, jid_from->resourcepart, message_txt, enc_message, omemo);
|
||||
|
||||
// else treat as a sent message
|
||||
} else {
|
||||
|
@ -2251,7 +2251,7 @@ stanza_create_omemo_bundle_publish(xmpp_ctx_t *ctx, uint32_t device_id,
|
||||
xmpp_stanza_t *prekey = xmpp_stanza_new(ctx);
|
||||
xmpp_stanza_set_name(prekey, "preKeyPublic");
|
||||
char *id = g_strdup_printf("%d", GPOINTER_TO_INT(i->data));
|
||||
xmpp_stanza_set_attribute(prekey, "id", id);
|
||||
xmpp_stanza_set_attribute(prekey, "preKeyId", id);
|
||||
g_free(id);
|
||||
|
||||
xmpp_stanza_t *prekey_text = xmpp_stanza_new(ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user