diff --git a/src/session_builder.c b/src/session_builder.c index 2bfd6201..afdb7619 100644 --- a/src/session_builder.c +++ b/src/session_builder.c @@ -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, @@ -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; diff --git a/src/session_builder_internal.h b/src/session_builder_internal.h index 2bf8dba4..ed49fbe2 100644 --- a/src/session_builder_internal.h +++ b/src/session_builder_internal.h @@ -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 @@ -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 */ diff --git a/src/session_cipher.c b/src/session_cipher.c index 3f5dcab9..a2e5236b 100644 --- a/src/session_cipher.c +++ b/src/session_cipher.c @@ -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); @@ -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; } @@ -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; } diff --git a/src/signal_protocol.h b/src/signal_protocol.h index 26d4550c..7ce56d90 100644 --- a/src/signal_protocol.h +++ b/src/signal_protocol.h @@ -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); diff --git a/tests/test_common.c b/tests/test_common.c index 13a34001..3ec27ded 100644 --- a/tests/test_common.c +++ b/tests/test_common.c @@ -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));