END_TEST

START_TEST(test_serialize_sender_key_message)
{
    int result = 0;
    sender_key_message *message = 0;
    sender_key_message *result_message = 0;
    static const char ciphertext[] = "WhisperCipherText";
    ec_key_pair *signature_key_pair = 0;

    result = curve_generate_key_pair(global_context, &signature_key_pair);
    ck_assert_int_eq(result, 0);

    result = sender_key_message_create(&message,
                                       10, /* key_id */
                                       1,  /* iteration */
                                       (uint8_t *)ciphertext, sizeof(ciphertext) - 1,
                                       ec_key_pair_get_private(signature_key_pair),
                                       global_context);
    ck_assert_int_eq(result, 0);

    result = sender_key_message_verify_signature(message, ec_key_pair_get_public(signature_key_pair));
    ck_assert_int_eq(result, 0);

    signal_buffer *serialized = ciphertext_message_get_serialized((ciphertext_message *)message);
    ck_assert_ptr_ne(serialized, 0);

    result = sender_key_message_deserialize(&result_message,
                                            signal_buffer_data(serialized),
                                            signal_buffer_len(serialized),
                                            global_context);
    ck_assert_int_eq(result, 0);

    result = sender_key_message_verify_signature(result_message, ec_key_pair_get_public(signature_key_pair));
    ck_assert_int_eq(result, 0);

    int key_id1 = sender_key_message_get_key_id(message);
    int key_id2 = sender_key_message_get_key_id(result_message);
    ck_assert_int_eq(key_id1, key_id2);

    int iteration1 = sender_key_message_get_iteration(message);
    int iteration2 = sender_key_message_get_iteration(result_message);
    ck_assert_int_eq(iteration1, iteration2);

    signal_buffer *ciphertext1 = sender_key_message_get_ciphertext(message);
    signal_buffer *ciphertext2 = sender_key_message_get_ciphertext(result_message);
    ck_assert_int_eq(signal_buffer_compare(ciphertext1, ciphertext2), 0);

    /* Cleanup */
    SIGNAL_UNREF(message);
    SIGNAL_UNREF(result_message);
    SIGNAL_UNREF(signature_key_pair);
}
int group_cipher_decrypt(group_cipher *cipher,
        sender_key_message *ciphertext, void *decrypt_context,
        axolotl_buffer **plaintext)
{
    int result = 0;
    axolotl_buffer *result_buf = 0;
    sender_key_record *record = 0;
    sender_key_state *state = 0;
    sender_message_key *sender_key = 0;
    axolotl_buffer *sender_cipher_key = 0;
    axolotl_buffer *sender_cipher_iv = 0;
    axolotl_buffer *ciphertext_body = 0;

    assert(cipher);
    axolotl_lock(cipher->global_context);

    if(cipher->inside_callback == 1) {
        result = AX_ERR_INVAL;
        goto complete;
    }

    result = axolotl_sender_key_load_key(cipher->store, &record, cipher->sender_key_id);
    if(result < 0) {
        goto complete;
    }

    if(sender_key_record_is_empty(record)) {
        result = AX_ERR_NO_SESSION;
        axolotl_log(cipher->global_context, AX_LOG_WARNING, "No sender key for: %s::%s::%d",
                cipher->sender_key_id->group_id,
                cipher->sender_key_id->sender.name,
                cipher->sender_key_id->sender.device_id);
        goto complete;
    }

    result = sender_key_record_get_sender_key_state_by_id(record, &state, sender_key_message_get_key_id(ciphertext));
    if(result < 0) {
        goto complete;
    }

    result = sender_key_message_verify_signature(ciphertext, sender_key_state_get_signing_key_public(state));
    if(result < 0) {
        goto complete;
    }

    result = group_cipher_get_sender_key(cipher, &sender_key, state, sender_key_message_get_iteration(ciphertext));
    if(result < 0) {
        goto complete;
    }

    sender_cipher_key = sender_message_key_get_cipher_key(sender_key);
    sender_cipher_iv = sender_message_key_get_iv(sender_key);
    ciphertext_body = sender_key_message_get_ciphertext(ciphertext);

    result = axolotl_decrypt(cipher->global_context, &result_buf, AX_CIPHER_AES_CBC_PKCS5,
            axolotl_buffer_data(sender_cipher_key), axolotl_buffer_len(sender_cipher_key),
            axolotl_buffer_data(sender_cipher_iv), axolotl_buffer_len(sender_cipher_iv),
            axolotl_buffer_data(ciphertext_body), axolotl_buffer_len(ciphertext_body));
    if(result < 0) {
        goto complete;
    }

    result = group_cipher_decrypt_callback(cipher, result_buf, decrypt_context);
    if(result < 0) {
        goto complete;
    }

    result = axolotl_sender_key_store_key(cipher->store, cipher->sender_key_id, record);

complete:
    AXOLOTL_UNREF(sender_key);
    AXOLOTL_UNREF(record);
    if(result >= 0) {
        *plaintext = result_buf;
    }
    else {
        if(result == AX_ERR_INVALID_KEY || result == AX_ERR_INVALID_KEY_ID) {
            result = AX_ERR_INVALID_MESSAGE;
        }
        axolotl_buffer_free(result_buf);
    }
    axolotl_unlock(cipher->global_context);
    return result;
}