summaryrefslogtreecommitdiffstats
path: root/comm/third_party/libotr/tests/unit/test_sm.c
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/libotr/tests/unit/test_sm.c')
-rw-r--r--comm/third_party/libotr/tests/unit/test_sm.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/comm/third_party/libotr/tests/unit/test_sm.c b/comm/third_party/libotr/tests/unit/test_sm.c
new file mode 100644
index 0000000000..8f4162ab1a
--- /dev/null
+++ b/comm/third_party/libotr/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;
+}