summary refs log tree commit diff stats
path: root/libotr/libotr-4.1.1/tests/unit/test_sm.c
diff options
context:
space:
mode:
Diffstat (limited to 'libotr/libotr-4.1.1/tests/unit/test_sm.c')
-rw-r--r--libotr/libotr-4.1.1/tests/unit/test_sm.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/libotr/libotr-4.1.1/tests/unit/test_sm.c b/libotr/libotr-4.1.1/tests/unit/test_sm.c
new file mode 100644
index 0000000..8f4162a
--- /dev/null
+++ b/libotr/libotr-4.1.1/tests/unit/test_sm.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2014 - David Goulet <dgoulet@ev0ke.net>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <gcrypt.h>
+#include <pthread.h>
+
+#include <proto.h>
+#include <sm.h>
+
+#include <tap/tap.h>
+#include <utils.h>
+
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+
+#define NUM_TESTS 23
+
+/* Copied from sm.c */
+static const int SM_MOD_LEN_BITS = 1536;
+static const char *SM_GENERATOR_S = "0x02";
+static gcry_mpi_t SM_GENERATOR = NULL;
+
+static const int SM_MSG1_LEN = 6;
+static const int SM_MSG2_LEN = 11;
+static const int SM_MSG3_LEN = 8;
+static const int SM_MSG4_LEN = 3;
+
+/* Alice and Bob SM state for the SMP tests. */
+static OtrlSMState *astate;
+static OtrlSMState *bstate;
+static const char *secret = "truie";
+static unsigned char *alice_output;
+static int alice_output_len;
+static unsigned char *bob_output;
+static int bob_output_len;
+
+/* Stub. */
+void otrl_sm_msg1_init(gcry_mpi_t **msg1);
+void otrl_sm_msg2_init(gcry_mpi_t **msg2);
+void otrl_sm_msg3_init(gcry_mpi_t **msg3);
+void otrl_sm_msg4_init(gcry_mpi_t **msg4);
+void otrl_sm_msg_free(gcry_mpi_t **message, int msglen);
+
+static OtrlSMState *alloc_sm_state(void)
+{
+	OtrlSMState *smst = malloc(sizeof(*smst));
+	ok(smst, "SM State allocated");
+
+	return smst;
+}
+
+static void test_sm_state_new(void)
+{
+	OtrlSMState *smst;
+
+	smst = alloc_sm_state();
+
+	otrl_sm_state_new(smst);
+	ok(!smst->secret &&
+			!smst->x2 &&
+			!smst->x3 &&
+			!smst->g1 &&
+			!smst->g2 &&
+			!smst->g3 &&
+			!smst->g3o &&
+			!smst->p &&
+			!smst->q &&
+			!smst->pab &&
+			!smst->qab &&
+			smst->nextExpected == OTRL_SMP_EXPECT1 &&
+			smst->received_question == 0 &&
+			smst->sm_prog_state == OTRL_SMP_PROG_OK,
+			"SM state new");
+
+	otrl_sm_state_free(smst);
+	free(smst);
+}
+
+static void test_sm_state_init(void)
+{
+	OtrlSMState *smst;
+
+	smst = alloc_sm_state();
+
+	otrl_sm_state_new(smst);
+	otrl_sm_state_init(smst);
+	ok(!gcry_mpi_cmp(smst->secret, gcry_mpi_snew(SM_MOD_LEN_BITS)) &&
+			!smst->x2 &&
+			!smst->x3 &&
+			!gcry_mpi_cmp(smst->g1, gcry_mpi_copy(SM_GENERATOR)) &&
+			!gcry_mpi_cmp(smst->g2, gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(smst->g3, gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(smst->g3o, gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(smst->p, gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(smst->q, gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(smst->pab, gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(smst->qab, gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			smst->nextExpected == OTRL_SMP_EXPECT1 &&
+			smst->received_question == 0 &&
+			smst->sm_prog_state == OTRL_SMP_PROG_OK,
+			"SM state init");
+
+	otrl_sm_state_free(smst);
+	free(smst);
+}
+
+static void test_sm_msg1_init(void)
+{
+	gcry_mpi_t *msg;
+
+	otrl_sm_msg1_init(&msg);
+	ok(msg &&
+			!gcry_mpi_cmp(msg[0], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!msg[1] &&
+			!gcry_mpi_cmp(msg[2], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(msg[3], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!msg[4] &&
+			!gcry_mpi_cmp(msg[5], gcry_mpi_new(SM_MOD_LEN_BITS)),
+			"SM msg1 initialized");
+	otrl_sm_msg_free(&msg, SM_MSG1_LEN);
+	/* Test once here. */
+	ok(!msg, "SM msg1 freed");
+}
+
+static void test_sm_msg2_init(void)
+{
+	gcry_mpi_t *msg;
+
+	otrl_sm_msg2_init(&msg);
+	ok(msg &&
+			!gcry_mpi_cmp(msg[0], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!msg[1] &&
+			!gcry_mpi_cmp(msg[2], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(msg[3], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!msg[4] &&
+			!gcry_mpi_cmp(msg[5], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(msg[6], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(msg[7], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!msg[8] &&
+			!gcry_mpi_cmp(msg[9], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(msg[10], gcry_mpi_new(SM_MOD_LEN_BITS)),
+			"SM msg2 initialized");
+	otrl_sm_msg_free(&msg, SM_MSG2_LEN);
+}
+
+static void test_sm_msg3_init(void)
+{
+	gcry_mpi_t *msg;
+
+	otrl_sm_msg3_init(&msg);
+	ok(msg &&
+			!gcry_mpi_cmp(msg[0], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(msg[1], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!msg[2] &&
+			!gcry_mpi_cmp(msg[3], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(msg[4], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!gcry_mpi_cmp(msg[5], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!msg[6] &&
+			!gcry_mpi_cmp(msg[7], gcry_mpi_new(SM_MOD_LEN_BITS)),
+			"SM msg3 initialized");
+	otrl_sm_msg_free(&msg, SM_MSG3_LEN);
+}
+
+static void test_sm_msg4_init(void)
+{
+	gcry_mpi_t *msg;
+
+	otrl_sm_msg4_init(&msg);
+	ok(msg &&
+			!gcry_mpi_cmp(msg[0], gcry_mpi_new(SM_MOD_LEN_BITS)) &&
+			!msg[1] &&
+			!gcry_mpi_cmp(msg[2], gcry_mpi_new(SM_MOD_LEN_BITS)),
+			"SM msg4 initialized");
+	otrl_sm_msg_free(&msg, SM_MSG4_LEN);
+}
+
+static void test_sm_step1(void)
+{
+	gcry_error_t err;
+	unsigned char hash_secret[SM_DIGEST_SIZE];
+
+	astate = alloc_sm_state();
+	otrl_sm_state_new(astate);
+	otrl_sm_state_init(astate);
+
+	gcry_md_hash_buffer(SM_HASH_ALGORITHM, hash_secret, secret,
+			strlen(secret));
+
+	err = otrl_sm_step1(astate, hash_secret, sizeof(hash_secret),
+			&alice_output, &alice_output_len);
+	ok(err == GPG_ERR_NO_ERROR, "SMP step1 success");
+
+	gcry_mpi_t secret_mpi;
+	gcry_mpi_scan(&secret_mpi, GCRYMPI_FMT_USG, hash_secret,
+			sizeof(hash_secret), NULL);
+	ok(!gcry_mpi_cmp(astate->secret, secret_mpi) &&
+			astate->received_question == 0 &&
+			astate->x2 &&
+			astate->x3 &&
+			astate->sm_prog_state == OTRL_SMP_PROG_OK &&
+			alice_output && alice_output_len > 0,
+			"SMP step 1 validated");
+	gcry_mpi_release(secret_mpi);
+}
+
+static void test_sm_step2a(void)
+{
+	gcry_error_t err;
+
+	bstate = alloc_sm_state();
+	otrl_sm_state_new(bstate);
+	otrl_sm_state_init(bstate);
+
+	err = otrl_sm_step2a(bstate, alice_output, alice_output_len, 1);
+	ok(err == GPG_ERR_NO_ERROR, "SMP step2a success");
+
+	ok(bstate->received_question == 1 &&
+			bstate->sm_prog_state == OTRL_SMP_PROG_OK &&
+			bstate->g3o &&
+			bstate->x2 &&
+			bstate->x3,
+			"SMP step2a validate");
+}
+
+static void test_sm_step2b(void)
+{
+	gcry_error_t err;
+	unsigned char hash_secret[SM_DIGEST_SIZE];
+
+	gcry_md_hash_buffer(SM_HASH_ALGORITHM, hash_secret, secret,
+			strlen(secret));
+
+	err = otrl_sm_step2b(bstate, hash_secret, sizeof(hash_secret), &bob_output,
+			&bob_output_len);
+	ok(err == GPG_ERR_NO_ERROR, "SMP step2b success");
+
+	/* Generate expected data. */
+	gcry_mpi_t secret_mpi;
+	gcry_mpi_scan(&secret_mpi, GCRYMPI_FMT_USG, hash_secret,
+			sizeof(hash_secret), NULL);
+	ok(bob_output && bob_output_len > 0 &&
+			!gcry_mpi_cmp(bstate->secret, secret_mpi) &&
+			bstate->p &&
+			bstate->q,
+			"SMP step2b validate");
+	gcry_mpi_release(secret_mpi);
+}
+
+static void test_sm_step3(void)
+{
+	gcry_error_t err;
+
+	free(alice_output);
+
+	err = otrl_sm_step3(astate, bob_output, bob_output_len, &alice_output,
+			&alice_output_len);
+	ok(err == GPG_ERR_NO_ERROR, "SMP step3 success");
+
+	ok(alice_output && alice_output_len > 0 &&
+			astate->sm_prog_state == OTRL_SMP_PROG_OK &&
+			astate->g3o &&
+			astate->g2 &&
+			astate->g3 &&
+			astate->p &&
+			astate->q &&
+			astate->qab &&
+			astate->pab,
+			"SMP step3 validate");
+}
+
+static void test_sm_step4(void)
+{
+	gcry_error_t err;
+
+	free(bob_output);
+
+	err = otrl_sm_step4(bstate, alice_output, alice_output_len, &bob_output,
+			&bob_output_len);
+	ok(err == gcry_error(GPG_ERR_NO_ERROR), "SMP step4 success");
+
+	ok(bob_output && bob_output_len > 0 &&
+			bstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED &&
+			bstate->pab &&
+			bstate->qab,
+			"SMP step4 validate");
+}
+
+static void test_sm_step5(void)
+{
+	gcry_error_t err;
+
+	err = otrl_sm_step5(astate, bob_output, bob_output_len);
+	ok(err == gcry_error(GPG_ERR_NO_ERROR), "SMP step5 success");
+
+	ok(astate && astate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED,
+			"SMP step5 validate");
+}
+
+int main(int argc, char **argv)
+{
+	/* Libtap call for the number of tests planned. */
+	plan_tests(NUM_TESTS);
+
+	gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+	OTRL_INIT;
+
+	/* Initialize sm subsystem. We can't really unit test that because every
+	 * value that is being initialized is static to sm.c. */
+	otrl_sm_init();
+
+	/* Init variables we need for testing. */
+	gcry_mpi_scan(&SM_GENERATOR, GCRYMPI_FMT_HEX,
+			(const unsigned char *)SM_GENERATOR_S, 0, NULL);
+
+	test_sm_state_new();
+	test_sm_state_init();
+	test_sm_msg1_init();
+	test_sm_msg2_init();
+	test_sm_msg3_init();
+	test_sm_msg4_init();
+
+	test_sm_step1();
+	test_sm_step2a();
+	test_sm_step2b();
+	test_sm_step3();
+	test_sm_step4();
+	test_sm_step5();
+
+	return 0;
+}