secure_comparator_t(const data_t& shared_secret)
     : comparator_(NULL)
 {
     if (shared_secret.empty()) {
         throw themispp::exception_t("Secure Comparator must have non-empty shared secret");
     }
     res_.reserve(512);
     comparator_ = secure_comparator_create();
     if (!comparator_) {
         throw themispp::exception_t("Secure Comparator construction failed");
     }
     themis_status_t status = secure_comparator_append_secret(comparator_,
                                                              &shared_secret[0],
                                                              shared_secret.size());
     if (THEMIS_SUCCESS != status) {
         throw themispp::exception_t("Secure Comparator failed to append secret", status);
     }
 }
static void secure_comparator_api_test(void)
{
    /* setup */
    themis_status_t themis_status;
    secret_length = rand_int(MAX_SECRET_SIZE);
    if (SOTER_SUCCESS != soter_rand(secret, secret_length)) {
        testsuite_fail_if(true, "soter_rand failed");
        return;
    }

    /* match */
    alice = secure_comparator_create();
    if (!alice) {
        testsuite_fail_if(true, "secure_comparator_create failed");
        return;
    }

    bob = secure_comparator_create();
    if (!bob) {
        testsuite_fail_if(true, "secure_comparator_create failed");
        secure_comparator_destroy(alice);
        alice = NULL;
        return;
    }

    testsuite_fail_unless(THEMIS_INVALID_PARAMETER
                              == secure_comparator_append_secret(NULL, secret, secret_length),
                          "secure_comparator_append_secret: invalid context");
    testsuite_fail_unless(THEMIS_INVALID_PARAMETER
                              == secure_comparator_append_secret(alice, NULL, secret_length),
                          "secure_comparator_append_secret: invalid input buffer");
    testsuite_fail_unless(THEMIS_INVALID_PARAMETER == secure_comparator_append_secret(alice, secret, 0),
                          "secure_comparator_append_secret: invalid input length");

    themis_status = secure_comparator_append_secret(alice, secret, secret_length);
    if (THEMIS_SUCCESS != themis_status) {
        testsuite_fail_if(true, "secure_comparator_append_secret failed");
        secure_comparator_destroy(bob);
        bob = NULL;
        secure_comparator_destroy(alice);
        alice = NULL;
        return;
    }

    themis_status = secure_comparator_append_secret(bob, secret, secret_length);
    if (THEMIS_SUCCESS != themis_status) {
        testsuite_fail_if(true, "secure_comparator_append_secret failed");
        secure_comparator_destroy(bob);
        bob = NULL;
        secure_comparator_destroy(alice);
        alice = NULL;
        return;
    }

    schedule();

    testsuite_fail_unless((THEMIS_SCOMPARE_MATCH == secure_comparator_get_result(alice))
                              && (THEMIS_SCOMPARE_MATCH == secure_comparator_get_result(bob)),
                          "compare result match");

    testsuite_fail_unless(THEMIS_INVALID_PARAMETER == secure_comparator_destroy(NULL),
                          "secure_comparator_destroy: invalid context");
    testsuite_fail_unless(THEMIS_SUCCESS == secure_comparator_destroy(bob),
                          "secure_comparator_destroy: destroy bob");
    testsuite_fail_unless(THEMIS_SUCCESS == secure_comparator_destroy(alice),
                          "secure_comparator_destroy: destroy alice");

    bob = NULL;
    alice = NULL;

    alice = secure_comparator_create();
    if (!alice) {
        testsuite_fail_if(true, "secure_comparator_create failed");
        return;
    }

    bob = secure_comparator_create();
    if (!bob) {
        testsuite_fail_if(true, "secure_comparator_create failed");
        secure_comparator_destroy(alice);
        alice = NULL;
        return;
    }

    themis_status = secure_comparator_append_secret(alice, secret, secret_length);
    if (THEMIS_SUCCESS != themis_status) {
        testsuite_fail_if(true, "secure_comparator_append_secret failed");
        secure_comparator_destroy(bob);
        bob = NULL;
        secure_comparator_destroy(alice);
        alice = NULL;
        return;
    }

    themis_status = secure_comparator_append_secret(bob, secret, secret_length - 1);
    if (THEMIS_SUCCESS != themis_status) {
        testsuite_fail_if(true, "secure_comparator_append_secret failed");
        secure_comparator_destroy(bob);
        bob = NULL;
        secure_comparator_destroy(alice);
        alice = NULL;
        return;
    }

    schedule();

    testsuite_fail_unless((THEMIS_SCOMPARE_NO_MATCH == secure_comparator_get_result(alice))
                              && (THEMIS_SCOMPARE_NO_MATCH == secure_comparator_get_result(bob)),
                          "compare result no match");

    testsuite_fail_unless(THEMIS_SUCCESS == secure_comparator_destroy(bob),
                          "secure_comparator_destroy: destroy bob");
    testsuite_fail_unless(THEMIS_SUCCESS == secure_comparator_destroy(alice),
                          "secure_comparator_destroy: destroy alice");

    bob = NULL;
    alice = NULL;
}
void secure_comparator_security_test(void)
{
	const char alice_secret[] = "alice secret";
	const char bob_secret[] = "bob secret";

	size_t output_length = sizeof(shared_mem);

	secure_comparator_t alice, bob;

	if (THEMIS_SUCCESS != secure_comparator_init(&alice))
	{
		testsuite_fail_if(true, "secure_comparator_init failed");
		return;
	}

	if (THEMIS_SUCCESS != secure_comparator_init(&bob))
	{
		testsuite_fail_if(true, "secure_comparator_init failed");
		return;
	}

	if (THEMIS_SUCCESS != secure_comparator_append_secret(&alice, alice_secret, sizeof(alice_secret)))
	{
		testsuite_fail_if(true, "secure_comparator_append_secret failed");
		return;
	}

	if (THEMIS_SUCCESS != secure_comparator_append_secret(&bob, bob_secret, sizeof(bob_secret)))
	{
		testsuite_fail_if(true, "secure_comparator_append_secret failed");
		return;
	}

	current_length = sizeof(shared_mem);

	if (THEMIS_SCOMPARE_SEND_OUTPUT_TO_PEER != secure_comparator_begin_compare(&alice, shared_mem, &current_length))
	{
		testsuite_fail_if(true, "secure_comparator_begin_compare failed");
		return;
	}

	corrupt_alice_step1(&alice, shared_mem);

	corrupt_bob_step2(&bob, shared_mem, current_length, shared_mem, &output_length);

	current_length = output_length;
	output_length = sizeof(shared_mem);

	if (THEMIS_SCOMPARE_SEND_OUTPUT_TO_PEER != secure_comparator_proceed_compare(&alice, shared_mem, current_length, shared_mem, &output_length))
	{
		testsuite_fail_if(true, "secure_comparator_proceed_compare failed");
		return;
	}

	current_length = output_length;
	output_length = sizeof(shared_mem);

	if (THEMIS_SCOMPARE_SEND_OUTPUT_TO_PEER != secure_comparator_proceed_compare(&bob, shared_mem, current_length, shared_mem, &output_length))
	{
		testsuite_fail_if(true, "secure_comparator_proceed_compare failed");
		return;
	}

	current_length = output_length;
	output_length = sizeof(shared_mem);

	if (THEMIS_SUCCESS != secure_comparator_proceed_compare(&alice, shared_mem, current_length, shared_mem, &output_length))
	{
		testsuite_fail_if(true, "secure_comparator_proceed_compare failed");
		return;
	}

	testsuite_fail_unless((THEMIS_SCOMPARE_NO_MATCH == secure_comparator_get_result(&alice)) && (THEMIS_SCOMPARE_NO_MATCH == secure_comparator_get_result(&bob)), "compare result no match");
}