void compare_signal_messages(signal_message *message1, signal_message *message2) { ec_public_key *sender_ratchet_key1 = signal_message_get_sender_ratchet_key(message1); ec_public_key *sender_ratchet_key2 = signal_message_get_sender_ratchet_key(message2); ck_assert_int_eq(ec_public_key_compare(sender_ratchet_key1, sender_ratchet_key2), 0); int version1 = signal_message_get_message_version(message1); int version2 = signal_message_get_message_version(message2); ck_assert_int_eq(version1, version2); int counter1 = signal_message_get_counter(message1); int counter2 = signal_message_get_counter(message2); ck_assert_int_eq(counter1, counter2); signal_buffer *body1 = signal_message_get_body(message1); signal_buffer *body2 = signal_message_get_body(message2); ck_assert_int_eq(signal_buffer_compare(body1, body2), 0); }
static int session_cipher_decrypt_from_state_and_signal_message(session_cipher *cipher, session_state *state, signal_message *ciphertext, signal_buffer **plaintext) { int result = 0; signal_buffer *result_buf = 0; ec_public_key *their_ephemeral = 0; uint32_t counter = 0; ratchet_chain_key *chain_key = 0; ratchet_message_keys message_keys; uint8_t message_version = 0; uint32_t session_version = 0; ec_public_key *remote_identity_key = 0; ec_public_key *local_identity_key = 0; signal_buffer *ciphertext_body = 0; if(!session_state_has_sender_chain(state)) { signal_log(cipher->global_context, SG_LOG_WARNING, "Uninitialized session!"); result = SG_ERR_INVALID_MESSAGE; goto complete; } message_version = signal_message_get_message_version(ciphertext); session_version = session_state_get_session_version(state); if(message_version != session_version) { signal_log(cipher->global_context, SG_LOG_WARNING, "Message version %d, but session version %d", message_version, session_version); result = SG_ERR_INVALID_MESSAGE; goto complete; } their_ephemeral = signal_message_get_sender_ratchet_key(ciphertext); if(!their_ephemeral) { result = SG_ERR_UNKNOWN; goto complete; } counter = signal_message_get_counter(ciphertext); result = session_cipher_get_or_create_chain_key(cipher, &chain_key, state, their_ephemeral); if(result < 0) { goto complete; } result = session_cipher_get_or_create_message_keys(&message_keys, state, their_ephemeral, chain_key, counter, cipher->global_context); if(result < 0) { goto complete; } remote_identity_key = session_state_get_remote_identity_key(state); if(!remote_identity_key) { result = SG_ERR_UNKNOWN; goto complete; } local_identity_key = session_state_get_local_identity_key(state); if(!local_identity_key) { result = SG_ERR_UNKNOWN; goto complete; } result = signal_message_verify_mac(ciphertext, remote_identity_key, local_identity_key, message_keys.mac_key, sizeof(message_keys.mac_key), cipher->global_context); if(result != 1) { if(result == 0) { signal_log(cipher->global_context, SG_LOG_WARNING, "Message mac not verified"); result = SG_ERR_INVALID_MESSAGE; } else if(result < 0) { signal_log(cipher->global_context, SG_LOG_WARNING, "Error attempting to verify message mac"); } goto complete; } ciphertext_body = signal_message_get_body(ciphertext); if(!ciphertext_body) { signal_log(cipher->global_context, SG_LOG_WARNING, "Message body does not exist"); result = SG_ERR_INVALID_MESSAGE; goto complete; } result = session_cipher_get_plaintext(cipher, &result_buf, message_version, &message_keys, signal_buffer_data(ciphertext_body), signal_buffer_len(ciphertext_body)); if(result < 0) { goto complete; } session_state_clear_unacknowledged_pre_key_message(state); complete: SIGNAL_UNREF(chain_key); if(result >= 0) { *plaintext = result_buf; } else { signal_buffer_free(result_buf); } signal_explicit_bzero(&message_keys, sizeof(ratchet_message_keys)); return result; }