#include #include #include #include "../src/signal_protocol.h" #include "hkdf.h" #include "session_record.h" #include "session_state.h" #include "test_common.h" signal_context *global_context; void test_setup() { int result; result = signal_context_create(&global_context, 0); ck_assert_int_eq(result, 0); signal_context_set_log_function(global_context, test_log); setup_test_crypto_provider(global_context); } void test_teardown() { signal_context_destroy(global_context); } void fill_test_session_state(session_state *state, ec_public_key *receiver_chain_ratchet_key1, ec_public_key *receiver_chain_ratchet_key2) { int result = 0; hkdf_context *kdf = 0; result = hkdf_create(&kdf, 2, global_context); ck_assert_int_eq(result, 0); uint8_t keySeed[32]; memset(keySeed, 0x42, sizeof(keySeed)); /* Set the session version */ session_state_set_session_version(state, 2); /* Set local and remote identity keys */ ec_public_key *local_identity_key = create_test_ec_public_key(global_context); ec_public_key *remote_identity_key = create_test_ec_public_key(global_context); session_state_set_local_identity_key(state, local_identity_key); session_state_set_remote_identity_key(state, remote_identity_key); SIGNAL_UNREF(local_identity_key); SIGNAL_UNREF(remote_identity_key); /* Set the root key */ ratchet_root_key *root_key; result = ratchet_root_key_create(&root_key, kdf, keySeed, sizeof(keySeed), global_context); ck_assert_int_eq(result, 0); session_state_set_root_key(state, root_key); SIGNAL_UNREF(root_key); /* Set the previous counter */ session_state_set_previous_counter(state, 4); /* Set the sender chain */ ec_key_pair *sender_ratchet_key_pair; result = curve_generate_key_pair(global_context, &sender_ratchet_key_pair); ck_assert_int_eq(result, 0); ratchet_chain_key *sender_chain_key; result = ratchet_chain_key_create(&sender_chain_key, kdf, keySeed, sizeof(keySeed), 0, global_context); ck_assert_int_eq(result, 0); session_state_set_sender_chain(state, sender_ratchet_key_pair, sender_chain_key); SIGNAL_UNREF(sender_ratchet_key_pair); SIGNAL_UNREF(sender_chain_key); /* Set the receiver chains */ if(receiver_chain_ratchet_key1) { ratchet_chain_key *receiver_chain_chain_key1; result = ratchet_chain_key_create(&receiver_chain_chain_key1, kdf, keySeed, sizeof(keySeed), 0, global_context); ck_assert_int_eq(result, 0); result = session_state_add_receiver_chain(state, receiver_chain_ratchet_key1, receiver_chain_chain_key1); ck_assert_int_eq(result, 0); ratchet_message_keys message_keys; result = ratchet_chain_key_get_message_keys(receiver_chain_chain_key1, &message_keys); ck_assert_int_eq(result, 0); result = session_state_set_message_keys(state, receiver_chain_ratchet_key1, &message_keys); ck_assert_int_eq(result, 0); SIGNAL_UNREF(receiver_chain_chain_key1); } if(receiver_chain_ratchet_key2) { ratchet_chain_key *receiver_chain_chain_key2; result = ratchet_chain_key_create(&receiver_chain_chain_key2, kdf, keySeed, sizeof(keySeed), 0, global_context); ck_assert_int_eq(result, 0); result = session_state_add_receiver_chain(state, receiver_chain_ratchet_key2, receiver_chain_chain_key2); ck_assert_int_eq(result, 0); ratchet_message_keys message_keys; result = ratchet_chain_key_get_message_keys(receiver_chain_chain_key2, &message_keys); ck_assert_int_eq(result, 0); result = session_state_set_message_keys(state, receiver_chain_ratchet_key2, &message_keys); ck_assert_int_eq(result, 0); SIGNAL_UNREF(receiver_chain_chain_key2); } /* Set pending key exchange */ ec_key_pair *our_base_key; result = curve_generate_key_pair(global_context, &our_base_key); ck_assert_int_eq(result, 0); ec_key_pair *our_ratchet_key; result = curve_generate_key_pair(global_context, &our_ratchet_key); ck_assert_int_eq(result, 0); ec_key_pair *our_identity_key_pair; result = curve_generate_key_pair(global_context, &our_identity_key_pair); ck_assert_int_eq(result, 0); ratchet_identity_key_pair *our_identity_key; result = ratchet_identity_key_pair_create(&our_identity_key, ec_key_pair_get_public(our_identity_key_pair), ec_key_pair_get_private(our_identity_key_pair)); ck_assert_int_eq(result, 0); SIGNAL_UNREF(our_identity_key_pair); session_state_set_pending_key_exchange(state, 42, our_base_key, our_ratchet_key, our_identity_key); SIGNAL_UNREF(our_base_key); SIGNAL_UNREF(our_ratchet_key); SIGNAL_UNREF(our_identity_key); /* Set pending pre-key */ ec_public_key *pending_pre_key_base_key = create_test_ec_public_key(global_context); uint32_t pre_key_id = 1234; session_state_set_unacknowledged_pre_key_message(state, &pre_key_id, 5678, pending_pre_key_base_key); SIGNAL_UNREF(pending_pre_key_base_key); session_state_set_remote_registration_id(state, 0xDEADBEEF); session_state_set_local_registration_id(state, 0xBAADF00D); session_state_set_needs_refresh(state, 0); ec_public_key *alice_base_key = create_test_ec_public_key(global_context); session_state_set_alice_base_key(state, alice_base_key); SIGNAL_UNREF(alice_base_key); SIGNAL_UNREF(kdf); } session_state *create_test_session_state(ec_public_key *receiver_chain_ratchet_key1, ec_public_key *receiver_chain_ratchet_key2) { int result = 0; session_state *state = 0; result = session_state_create(&state, global_context); ck_assert_int_eq(result, 0); fill_test_session_state(state, receiver_chain_ratchet_key1, receiver_chain_ratchet_key2); return state; } void compare_session_states_receiver_chain(session_state *state1, session_state *state2, ec_public_key *sender_ephemeral); void compare_session_states(session_state *state1, session_state *state2, ec_public_key *receiver_chain_ratchet_key1, ec_public_key *receiver_chain_ratchet_key2) { int result = 0; /* Compare session versions */ int version1 = session_state_get_session_version(state1); int version2 = session_state_get_session_version(state2); ck_assert_int_eq(version1, version2); /* Compare local identity keys */ ec_public_key *local_identity_key1 = session_state_get_local_identity_key(state1); ec_public_key *local_identity_key2 = session_state_get_local_identity_key(state2); ck_assert_int_eq(ec_public_key_compare(local_identity_key1, local_identity_key2), 0); /* Compare remote identity keys */ ec_public_key *remote_identity_key1 = session_state_get_remote_identity_key(state1); ec_public_key *remote_identity_key2 = session_state_get_remote_identity_key(state2); ck_assert_int_eq(ec_public_key_compare(remote_identity_key1, remote_identity_key2), 0); /* Compare root keys */ ratchet_root_key *root_key1 = session_state_get_root_key(state1); ratchet_root_key *root_key2 = session_state_get_root_key(state2); ck_assert_int_eq(ratchet_root_key_compare(root_key1, root_key2), 0); /* Compare previous counters */ int previous_counter1 = session_state_get_previous_counter(state1); int previous_counter2 = session_state_get_previous_counter(state2); ck_assert_int_eq(previous_counter1, previous_counter2); /* Compare sender chain */ int has_sender_chain1 = session_state_has_sender_chain(state1); int has_sender_chain2 = session_state_has_sender_chain(state2); ck_assert_int_eq(has_sender_chain1, has_sender_chain2); if(has_sender_chain1 == 1) { /* Compare sender ratchet keys */ ec_key_pair *sender_ratchet_key_pair1 = session_state_get_sender_ratchet_key_pair(state1); ec_key_pair *sender_ratchet_key_pair2 = session_state_get_sender_ratchet_key_pair(state2); ec_public_key *sender_ratchet_key_public1 = ec_key_pair_get_public(sender_ratchet_key_pair1); ec_public_key *sender_ratchet_key_public2 = ec_key_pair_get_public(sender_ratchet_key_pair2); ck_assert_int_eq(ec_public_key_compare(sender_ratchet_key_public1, sender_ratchet_key_public2), 0); ec_private_key *sender_ratchet_key_private1 = ec_key_pair_get_private(sender_ratchet_key_pair1); ec_private_key *sender_ratchet_key_private2 = ec_key_pair_get_private(sender_ratchet_key_pair2); ck_assert_int_eq(ec_private_key_compare(sender_ratchet_key_private1, sender_ratchet_key_private2), 0); /* Compare sender chain keys */ ratchet_chain_key *sender_chain_key1 = session_state_get_sender_chain_key(state1); ratchet_chain_key *sender_chain_key2 = session_state_get_sender_chain_key(state2); signal_buffer *sender_chain_key_buf1; signal_buffer *sender_chain_key_buf2; result = ratchet_chain_key_get_key(sender_chain_key1, &sender_chain_key_buf1); ck_assert_int_eq(result, 0); result = ratchet_chain_key_get_key(sender_chain_key2, &sender_chain_key_buf2); ck_assert_int_eq(result, 0); ck_assert_int_eq(signal_buffer_compare(sender_chain_key_buf1, sender_chain_key_buf2), 0); signal_buffer_free(sender_chain_key_buf1); signal_buffer_free(sender_chain_key_buf2); int sender_chain_key_index1 = ratchet_chain_key_get_index(sender_chain_key1); int sender_chain_key_index2 = ratchet_chain_key_get_index(sender_chain_key2); ck_assert_int_eq(sender_chain_key_index1, sender_chain_key_index2); } /* Compare receiver chains */ if(receiver_chain_ratchet_key1) { compare_session_states_receiver_chain(state1, state2, receiver_chain_ratchet_key1); } if(receiver_chain_ratchet_key2) { compare_session_states_receiver_chain(state1, state2, receiver_chain_ratchet_key2); } /* Compare pending key exchange */ int has_pending_key_exchange1 = session_state_has_pending_key_exchange(state1); int has_pending_key_exchange2 = session_state_has_pending_key_exchange(state2); ck_assert_int_eq(has_pending_key_exchange1, has_pending_key_exchange2); if(has_pending_key_exchange1 == 1) { /* Compare sequence numbers */ int sequence1 = session_state_get_pending_key_exchange_sequence(state1); int sequence2 = session_state_get_pending_key_exchange_sequence(state2); ck_assert_int_eq(sequence1, sequence2); /* Compare base keys */ ec_key_pair *base_key1 = session_state_get_pending_key_exchange_base_key(state1); ec_key_pair *base_key2 = session_state_get_pending_key_exchange_base_key(state2); ec_public_key *base_key_public1 = ec_key_pair_get_public(base_key1); ec_public_key *base_key_public2 = ec_key_pair_get_public(base_key2); ck_assert_int_eq(ec_public_key_compare(base_key_public1, base_key_public2), 0); ec_private_key *base_key_private1 = ec_key_pair_get_private(base_key1); ec_private_key *base_key_private2 = ec_key_pair_get_private(base_key2); ck_assert_int_eq(ec_private_key_compare(base_key_private1, base_key_private2), 0); /* Compare ratchet keys */ ec_key_pair *ratchet_key1 = session_state_get_pending_key_exchange_ratchet_key(state1); ec_key_pair *ratchet_key2 = session_state_get_pending_key_exchange_ratchet_key(state2); ec_public_key *ratchet_key_public1 = ec_key_pair_get_public(ratchet_key1); ec_public_key *ratchet_key_public2 = ec_key_pair_get_public(ratchet_key2); ck_assert_int_eq(ec_public_key_compare(ratchet_key_public1, ratchet_key_public2), 0); ec_private_key *ratchet_key_private1 = ec_key_pair_get_private(ratchet_key1); ec_private_key *ratchet_key_private2 = ec_key_pair_get_private(ratchet_key2); ck_assert_int_eq(ec_private_key_compare(ratchet_key_private1, ratchet_key_private2), 0); /* Compare identity keys */ ratchet_identity_key_pair *identity_key1 = session_state_get_pending_key_exchange_identity_key(state1); ratchet_identity_key_pair *identity_key2 = session_state_get_pending_key_exchange_identity_key(state2); ec_public_key *identity_key_public1 = ratchet_identity_key_pair_get_public(identity_key1); ec_public_key *identity_key_public2 = ratchet_identity_key_pair_get_public(identity_key2); ck_assert_int_eq(ec_public_key_compare(identity_key_public1, identity_key_public2), 0); ec_private_key *identity_key_private1 = ratchet_identity_key_pair_get_private(identity_key1); ec_private_key *identity_key_private2 = ratchet_identity_key_pair_get_private(identity_key2); ck_assert_int_eq(ec_private_key_compare(identity_key_private1, identity_key_private2), 0); } /* Compare pending pre-key */ int has_pending_pre_key1 = session_state_has_unacknowledged_pre_key_message(state1); int has_pending_pre_key2 = session_state_has_unacknowledged_pre_key_message(state2); ck_assert_int_eq(has_pending_pre_key1, has_pending_pre_key2); if(has_pending_pre_key1 == 1) { int has_key_id1 = session_state_unacknowledged_pre_key_message_has_pre_key_id(state1); int has_key_id2 = session_state_unacknowledged_pre_key_message_has_pre_key_id(state2); ck_assert_int_eq(has_key_id1, has_key_id2); if(has_key_id1) { /* Compare pre-key IDs */ uint32_t pre_key_id1 = session_state_unacknowledged_pre_key_message_get_pre_key_id(state1); uint32_t pre_key_id2 = session_state_unacknowledged_pre_key_message_get_pre_key_id(state2); ck_assert_int_eq(pre_key_id1, pre_key_id2); /* Compare signed pre-key IDs */ int32_t signed_pre_key_id1 = session_state_unacknowledged_pre_key_message_get_signed_pre_key_id(state1); int32_t signed_pre_key_id2 = session_state_unacknowledged_pre_key_message_get_signed_pre_key_id(state2); ck_assert_int_eq(signed_pre_key_id1, signed_pre_key_id2); /* Compare base keys */ ec_public_key *base_key1 = session_state_unacknowledged_pre_key_message_get_base_key(state1); ec_public_key *base_key2 = session_state_unacknowledged_pre_key_message_get_base_key(state2); ck_assert_int_eq(ec_public_key_compare(base_key1, base_key2), 0); } } /* Compare remote registration IDs */ uint32_t remote_registration_id1 = session_state_get_remote_registration_id(state1); uint32_t remote_registration_id2 = session_state_get_remote_registration_id(state2); ck_assert_int_eq(remote_registration_id1, remote_registration_id2); /* Compare local registration IDs */ uint32_t local_registration_id1 = session_state_get_local_registration_id(state1); uint32_t local_registration_id2 = session_state_get_local_registration_id(state2); ck_assert_int_eq(local_registration_id1, local_registration_id2); /* Compare refresh flags */ int needs_refresh1 = session_state_get_needs_refresh(state1); int needs_refresh2 = session_state_get_needs_refresh(state2); ck_assert_int_eq(needs_refresh1, needs_refresh2); /* Compare Alice base keys */ ec_public_key *alice_base_key1 = session_state_get_alice_base_key(state1); ec_public_key *alice_base_key2 = session_state_get_alice_base_key(state2); ck_assert_int_eq(ec_public_key_compare(alice_base_key1, alice_base_key2), 0); } void compare_session_states_receiver_chain(session_state *state1, session_state *state2, ec_public_key *sender_ephemeral) { int result = 0; ratchet_chain_key *receiver_chain_key1 = session_state_get_receiver_chain_key(state1, sender_ephemeral); ck_assert_ptr_ne(receiver_chain_key1, 0); ratchet_chain_key *receiver_chain_key2 = session_state_get_receiver_chain_key(state2, sender_ephemeral); ck_assert_ptr_ne(receiver_chain_key2, 0); ck_assert_ptr_ne(receiver_chain_key1, receiver_chain_key2); signal_buffer *receiver_chain_key_buf1; signal_buffer *receiver_chain_key_buf2; result = ratchet_chain_key_get_key(receiver_chain_key1, &receiver_chain_key_buf1); ck_assert_int_eq(result, 0); result = ratchet_chain_key_get_key(receiver_chain_key2, &receiver_chain_key_buf2); ck_assert_int_eq(result, 0); ck_assert_int_eq(signal_buffer_compare(receiver_chain_key_buf1, receiver_chain_key_buf2), 0); signal_buffer_free(receiver_chain_key_buf1); signal_buffer_free(receiver_chain_key_buf2); int receiver_chain_key_index1 = ratchet_chain_key_get_index(receiver_chain_key1); int receiver_chain_key_index2 = ratchet_chain_key_get_index(receiver_chain_key2); ck_assert_int_eq(receiver_chain_key_index1, receiver_chain_key_index2); int has_message_keys1 = session_state_has_message_keys(state1, sender_ephemeral, 0); ck_assert_int_eq(has_message_keys1, 1); int has_message_keys2 = session_state_has_message_keys(state2, sender_ephemeral, 0); ck_assert_int_eq(has_message_keys2, 1); ratchet_message_keys message_keys1; result = session_state_remove_message_keys(state1, &message_keys1, sender_ephemeral, 0); ck_assert_int_eq(result, 1); ratchet_message_keys message_keys2; result = session_state_remove_message_keys(state2, &message_keys2, sender_ephemeral, 0); ck_assert_int_eq(result, 1); ck_assert_int_eq(memcmp(&message_keys1, &message_keys2, sizeof(ratchet_message_keys)), 0); } START_TEST(test_serialize_single_session) { int result = 0; ec_public_key *receiver_chain_ratchet_key1 = create_test_ec_public_key(global_context); ec_public_key *receiver_chain_ratchet_key2 = create_test_ec_public_key(global_context); session_state *state = create_test_session_state(receiver_chain_ratchet_key1, receiver_chain_ratchet_key2); session_record *record = 0; result = session_record_create(&record, state, global_context); ck_assert_int_eq(result, 0); signal_buffer *buffer = 0; result = session_record_serialize(&buffer, record); ck_assert_int_ge(result, 0); uint8_t *data = signal_buffer_data(buffer); int len = signal_buffer_len(buffer); /* Deserialize the record */ session_record *record_deserialized = 0; result = session_record_deserialize(&record_deserialized, data, len, global_context); ck_assert_int_ge(result, 0); session_state *state_deserialized = session_record_get_state(record_deserialized); ck_assert_ptr_ne(state_deserialized, 0); ck_assert_ptr_ne(state_deserialized, state); /* Verify that the initial and deserialized states match */ compare_session_states(state, state_deserialized, receiver_chain_ratchet_key1, receiver_chain_ratchet_key2); /* Verify that there aren't any previous states */ session_record_state_node *previous_node = session_record_get_previous_states_head(record_deserialized); ck_assert_ptr_eq(previous_node, 0); /* Cleanup */ SIGNAL_UNREF(state); signal_buffer_free(buffer); SIGNAL_UNREF(receiver_chain_ratchet_key1); SIGNAL_UNREF(receiver_chain_ratchet_key2); SIGNAL_UNREF(record); SIGNAL_UNREF(record_deserialized); } END_TEST START_TEST(test_serialize_multiple_sessions) { int result = 0; /* Create several test keys */ ec_public_key *receiver_chain_ratchet_key1a = create_test_ec_public_key(global_context); ec_public_key *receiver_chain_ratchet_key1b = create_test_ec_public_key(global_context); ec_public_key *receiver_chain_ratchet_key2a = create_test_ec_public_key(global_context); ec_public_key *receiver_chain_ratchet_key2b = create_test_ec_public_key(global_context); ec_public_key *receiver_chain_ratchet_key3a = create_test_ec_public_key(global_context); ec_public_key *receiver_chain_ratchet_key3b = create_test_ec_public_key(global_context); /* Create the session record with the first state */ session_state *state1 = create_test_session_state(receiver_chain_ratchet_key1a, receiver_chain_ratchet_key1b); session_record *record = 0; result = session_record_create(&record, state1, global_context); ck_assert_int_eq(result, 0); /* Archive the current state and fill the new state */ result = session_record_archive_current_state(record); ck_assert_int_eq(result, 0); session_state *state2 = session_record_get_state(record); ck_assert_ptr_ne(state1, state2); fill_test_session_state(state2, receiver_chain_ratchet_key2a, receiver_chain_ratchet_key2b); /* Archive the current state and fill the new state */ result = session_record_archive_current_state(record); ck_assert_int_eq(result, 0); session_state *state3 = session_record_get_state(record); ck_assert_ptr_ne(state1, state2); ck_assert_ptr_ne(state1, state3); fill_test_session_state(state3, receiver_chain_ratchet_key3a, receiver_chain_ratchet_key3b); signal_buffer *buffer = 0; result = session_record_serialize(&buffer, record); ck_assert_int_ge(result, 0); uint8_t *data = signal_buffer_data(buffer); int len = signal_buffer_len(buffer); /* Deserialize the record */ session_record *record_deserialized = 0; result = session_record_deserialize(&record_deserialized, data, len, global_context); ck_assert_int_ge(result, 0); session_state *state_deserialized3 = session_record_get_state(record_deserialized); ck_assert_ptr_ne(state_deserialized3, 0); ck_assert_ptr_ne(state_deserialized3, state3); /* Verify that the expected and actual current states match */ compare_session_states(state3, state_deserialized3, receiver_chain_ratchet_key3a, receiver_chain_ratchet_key3b); /* Verify that we have the expected number of previous states */ session_record_state_node *previous_node = session_record_get_previous_states_head(record_deserialized); ck_assert_ptr_ne(previous_node, 0); session_state *state_deserialized2 = session_record_get_previous_states_element(previous_node); ck_assert_ptr_ne(state_deserialized2, 0); previous_node = session_record_get_previous_states_next(previous_node); ck_assert_ptr_ne(previous_node, 0); session_state *state_deserialized1 = session_record_get_previous_states_element(previous_node); ck_assert_ptr_ne(state_deserialized1, 0); previous_node = session_record_get_previous_states_next(previous_node); ck_assert_ptr_eq(previous_node, 0); /* Verify that the expected and actual previous states match */ compare_session_states(state2, state_deserialized2, receiver_chain_ratchet_key2a, receiver_chain_ratchet_key2b); compare_session_states(state1, state_deserialized1, receiver_chain_ratchet_key1a, receiver_chain_ratchet_key1b); /* Cleanup */ SIGNAL_UNREF(state1); signal_buffer_free(buffer); SIGNAL_UNREF(receiver_chain_ratchet_key1a); SIGNAL_UNREF(receiver_chain_ratchet_key1b); SIGNAL_UNREF(receiver_chain_ratchet_key2a); SIGNAL_UNREF(receiver_chain_ratchet_key2b); SIGNAL_UNREF(receiver_chain_ratchet_key3a); SIGNAL_UNREF(receiver_chain_ratchet_key3b); SIGNAL_UNREF(record); SIGNAL_UNREF(record_deserialized); } END_TEST START_TEST(test_session_receiver_chain_count) { int result = 0; int i = 0; hkdf_context *kdf = 0; session_state *state = 0; ratchet_chain_key *chain_key[7]; ec_public_key *ratchet_key[7]; result = hkdf_create(&kdf, 2, global_context); ck_assert_int_eq(result, 0); uint8_t keySeed[32]; memset(keySeed, 0x42, sizeof(keySeed)); /* Create 7 instances of receiver chain data */ for(i = 0; i < 7; i++) { result = ratchet_chain_key_create(&chain_key[i], kdf, keySeed, sizeof(keySeed), 0, global_context); ck_assert_int_eq(result, 0); ratchet_key[i] = create_test_ec_public_key(global_context); ck_assert_ptr_ne(ratchet_key[i], 0); } /* Create a new session state instance */ result = session_state_create(&state, global_context); ck_assert_int_eq(result, 0); /* Add 6 instances of receiver chain data */ for(i = 0; i < 7; i++) { result = session_state_add_receiver_chain(state, ratchet_key[i], chain_key[i]); ck_assert_int_eq(result, 0); } /* Verify that only the latter 5 are actually there */ for(i = 0; i < 7; i++) { ratchet_chain_key *cur_chain_key; signal_buffer *chain_key_buf; signal_buffer *cur_chain_key_buf; cur_chain_key = session_state_get_receiver_chain_key(state, ratchet_key[i]); if(i < 2) { ck_assert_ptr_eq(cur_chain_key, 0); } else { ck_assert_ptr_ne(cur_chain_key, 0); result = ratchet_chain_key_get_key(chain_key[i], &chain_key_buf); ck_assert_int_eq(result, 0); result = ratchet_chain_key_get_key(cur_chain_key, &cur_chain_key_buf); ck_assert_int_eq(result, 0); ck_assert_int_eq(signal_buffer_compare(chain_key_buf, cur_chain_key_buf), 0); signal_buffer_free(chain_key_buf); signal_buffer_free(cur_chain_key_buf); } } /* Cleanup */ for(i = 0; i < 7; i++) { SIGNAL_UNREF(chain_key[i]); SIGNAL_UNREF(ratchet_key[i]); } SIGNAL_UNREF(kdf); SIGNAL_UNREF(state); } END_TEST Suite *session_record_suite(void) { Suite *suite = suite_create("session_record"); TCase *tcase = tcase_create("case"); tcase_add_checked_fixture(tcase, test_setup, test_teardown); tcase_add_test(tcase, test_serialize_single_session); tcase_add_test(tcase, test_serialize_multiple_sessions); tcase_add_test(tcase, test_session_receiver_chain_count); suite_add_tcase(suite, tcase); return suite; } int main(void) { int number_failed; Suite *suite; SRunner *runner; suite = session_record_suite(); runner = srunner_create(suite); srunner_run_all(runner, CK_VERBOSE); number_failed = srunner_ntests_failed(runner); srunner_free(runner); return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; }