Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

Fix of possible DoS attack related session_cipher_decrypt processing #84

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/session_builder.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ int session_builder_create(session_builder **builder,
}

int session_builder_process_pre_key_signal_message(session_builder *builder,
session_record *record, pre_key_signal_message *message, uint32_t *unsigned_pre_key_id)
session_record *record, pre_key_signal_message *message, uint32_t *unsigned_pre_key_id,
uint8_t *identity_key_changed)
{
int result = 0;
int has_unsigned_pre_key_id_result = 0;
uint32_t unsigned_pre_key_id_result = 0;
*identity_key_changed = 0;
ec_public_key *their_identity_key = pre_key_signal_message_get_identity_key(message);

result = signal_protocol_identity_is_trusted_identity(builder->store,
Expand All @@ -75,6 +77,9 @@ int session_builder_process_pre_key_signal_message(session_builder *builder,
if(result < 0) {
goto complete;
}
else if(result == 0) {
*identity_key_changed = 1;
}

result = has_unsigned_pre_key_id_result;

Expand Down
5 changes: 4 additions & 1 deletion src/session_builder_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* @param message The received pre_key_signal_message.
* @param unsigned_pre_key_id set to the unsigned pre key ID, if available.
* Return value indicates whether or not this value is available.
* @param identity_key_changed set to 1 if identity key was changed during processing,
* otherwise 0.
* @retval 0 Success, no unsigned pre key value available
* @retval 1 Success, an unsigned pre key is available
* @retval SG_ERR_INVALID_KEY_ID when there is no local pre_key_record that
Expand All @@ -21,6 +23,7 @@
* @retval SG_ERR_UNTRUSTED_IDENTITY when the identity key of the sender is untrusted.
*/
int session_builder_process_pre_key_signal_message(session_builder *builder,
session_record *record, pre_key_signal_message *message, uint32_t *unsigned_pre_key_id);
session_record *record, pre_key_signal_message *message, uint32_t *unsigned_pre_key_id,
uint8_t *identity_key_changed);

#endif /* SESSION_BUILDER_INTERNAL_H */
7 changes: 6 additions & 1 deletion src/session_cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ int session_cipher_decrypt_pre_key_signal_message(session_cipher *cipher,
session_record *record = 0;
int has_unsigned_pre_key_id = 0;
uint32_t unsigned_pre_key_id = 0;
uint8_t identity_key_changed = 0;

assert(cipher);
signal_lock(cipher->global_context);
Expand All @@ -279,7 +280,7 @@ int session_cipher_decrypt_pre_key_signal_message(session_cipher *cipher,
goto complete;
}

result = session_builder_process_pre_key_signal_message(cipher->builder, record, ciphertext, &unsigned_pre_key_id);
result = session_builder_process_pre_key_signal_message(cipher->builder, record, ciphertext, &unsigned_pre_key_id, &identity_key_changed);
if(result < 0) {
goto complete;
}
Expand All @@ -289,6 +290,10 @@ int session_cipher_decrypt_pre_key_signal_message(session_cipher *cipher,
pre_key_signal_message_get_signal_message(ciphertext),
&result_buf);
if(result < 0) {
if(identity_key_changed) {
signal_protocol_identity_save_identity(cipher->store, cipher->remote_address, NULL);
}

goto complete;
}

Expand Down
2 changes: 1 addition & 1 deletion src/signal_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ typedef struct signal_protocol_identity_key_store {
* @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
* @return 0 on success, 1 on the same identity key as already stored, negative on failure
*/
int (*save_identity)(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data);

Expand Down
8 changes: 7 additions & 1 deletion tests/test_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,13 @@ int test_identity_key_store_save_identity(const signal_protocol_address *address
HASH_FIND(hh, data->keys, &recipient_hash, sizeof(int64_t), s);
if(s) {
signal_buffer_free(s->identity_key);
s->identity_key = key_buf;
if (key_data == NULL) {
HASH_DEL(data->keys, s);
signal_buffer_free(key_buf);
return 0;
} else {
s->identity_key = key_buf;
}
}
else {
s = malloc(sizeof(test_identity_store_key));
Expand Down