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