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_encrypt(group_cipher *cipher,
        const uint8_t *padded_plaintext, size_t padded_plaintext_len,
        ciphertext_message **encrypted_message)
{
    int result = 0;
    sender_key_message *result_message = 0;
    sender_key_record *record = 0;
    sender_key_state *state = 0;
    ec_private_key *signing_key_private = 0;
    sender_message_key *sender_key = 0;
    sender_chain_key *next_chain_key = 0;
    axolotl_buffer *sender_cipher_key = 0;
    axolotl_buffer *sender_cipher_iv = 0;
    axolotl_buffer *ciphertext = 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;
    }

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

    signing_key_private = sender_key_state_get_signing_key_private(state);
    if(!signing_key_private) {
        result = AX_ERR_NO_SESSION;
        goto complete;
    }

    result = sender_chain_key_create_message_key(sender_key_state_get_chain_key(state), &sender_key);
    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);

    result = axolotl_encrypt(cipher->global_context, &ciphertext, 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),
            padded_plaintext, padded_plaintext_len);
    if(result < 0) {
        goto complete;
    }

    result = sender_key_message_create(&result_message,
            sender_key_state_get_key_id(state),
            sender_message_key_get_iteration(sender_key),
            axolotl_buffer_data(ciphertext), axolotl_buffer_len(ciphertext),
            signing_key_private,
            cipher->global_context);
    if(result < 0) {
        goto complete;
    }

    result = sender_chain_key_create_next(sender_key_state_get_chain_key(state), &next_chain_key);
    if(result < 0) {
        goto complete;
    }

    sender_key_state_set_chain_key(state, next_chain_key);

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

complete:
    if(result >= 0) {
        *encrypted_message = (ciphertext_message *)result_message;
    }
    else {
        if(result == AX_ERR_INVALID_KEY_ID) {
            result = AX_ERR_NO_SESSION;
        }
        AXOLOTL_UNREF(result_message);
    }
    axolotl_buffer_free(ciphertext);
    AXOLOTL_UNREF(next_chain_key);
    AXOLOTL_UNREF(sender_key);
    AXOLOTL_UNREF(record);
    axolotl_unlock(cipher->global_context);
    return result;
}