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; }