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);
}
예제 #2
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;
}