Browse Source

test: Add ESTABLISH_INTRO unit tests

This commit adds 3 unit tests which validates a wrong signature length, a
wrong authentication key length and a wrong MAC in the cell.

Closes #20992

Signed-off-by: David Goulet <dgoulet@torproject.org>
David Goulet 7 years ago
parent
commit
c0a0c19725
1 changed files with 168 additions and 0 deletions
  1. 168 0
      src/test/test_hs_intropoint.c

+ 168 - 0
src/test/test_hs_intropoint.c

@@ -12,12 +12,14 @@
 #define CIRCUITLIST_PRIVATE
 
 #include "test.h"
+#include "log_test_helpers.h"
 #include "crypto.h"
 
 #include "or.h"
 #include "ht.h"
 
 #include "hs/cell_establish_intro.h"
+#include "hs_common.h"
 #include "hs_service.h"
 #include "hs_circuitmap.h"
 #include "hs_intropoint.h"
@@ -143,6 +145,163 @@ test_establish_intro_wrong_keytype2(void *arg)
   circuit_free(TO_CIRCUIT(intro_circ));
 }
 
+/* Send a legit ESTABLISH_INTRO cell but with a wrong MAC. Should fail. */
+static void
+test_establish_intro_wrong_mac(void *arg)
+{
+  int retval;
+  hs_cell_establish_intro_t *establish_intro_cell = NULL;
+  or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
+  uint8_t cell_body[RELAY_PAYLOAD_SIZE];
+  ssize_t cell_len = 0;
+  uint8_t circuit_key_material[DIGEST_LEN] = {0};
+
+  (void)arg;
+
+  /* Get the auth key of the intro point */
+  crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
+  helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
+
+  /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
+     attempt to parse it. */
+  establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
+                                                       sizeof(circuit_key_material));
+  tt_assert(establish_intro_cell);
+  /* Mangle one byte of the MAC. */
+  uint8_t *handshake_ptr =
+    hs_cell_establish_intro_getarray_handshake_mac(establish_intro_cell);
+  handshake_ptr[TRUNNEL_SHA3_256_LEN - 1]++;
+  /* We need to resign the payload with that change. */
+  {
+    ed25519_signature_t sig;
+    ed25519_keypair_t key_struct;
+    /* New keypair for the signature since we don't have access to the private
+     * key material generated earlier when creating the cell. */
+    retval = ed25519_keypair_generate(&key_struct, 0);
+    tt_int_op(retval, OP_EQ, 0);
+    uint8_t *auth_key_ptr =
+      hs_cell_establish_intro_getarray_auth_key(establish_intro_cell);
+    memcpy(auth_key_ptr, key_struct.pubkey.pubkey, ED25519_PUBKEY_LEN);
+    /* Encode payload so we can sign it. */
+    cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
+                                           establish_intro_cell);
+    tt_int_op(cell_len, >, 0);
+
+    retval = ed25519_sign_prefixed(&sig, cell_body,
+                                   cell_len -
+                                   (ED25519_SIG_LEN +
+                                    sizeof(establish_intro_cell->sig_len)),
+                                   ESTABLISH_INTRO_SIG_PREFIX, &key_struct);
+    tt_int_op(retval, OP_EQ, 0);
+    /* And write the signature to the cell */
+    uint8_t *sig_ptr =
+      hs_cell_establish_intro_getarray_sig(establish_intro_cell);
+    memcpy(sig_ptr, sig.sig, establish_intro_cell->sig_len);
+    /* Re-encode with the new signature. */
+    cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
+                                           establish_intro_cell);
+  }
+
+  /* Receive the cell. Should fail because our MAC is wrong. */
+  setup_full_capture_of_logs(LOG_INFO);
+  retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
+  expect_log_msg_containing("ESTABLISH_INTRO handshake_auth not as expected");
+  teardown_capture_of_logs();
+  tt_int_op(retval, ==, -1);
+
+ done:
+  hs_cell_establish_intro_free(establish_intro_cell);
+  circuit_free(TO_CIRCUIT(intro_circ));
+}
+
+/* Send a legit ESTABLISH_INTRO cell but with a wrong auth key length. Should
+ * fail. */
+static void
+test_establish_intro_wrong_auth_key_len(void *arg)
+{
+  int retval;
+  hs_cell_establish_intro_t *establish_intro_cell = NULL;
+  or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
+  uint8_t cell_body[RELAY_PAYLOAD_SIZE];
+  ssize_t cell_len = 0;
+  size_t bad_auth_key_len = ED25519_PUBKEY_LEN - 1;
+  uint8_t circuit_key_material[DIGEST_LEN] = {0};
+
+  (void)arg;
+
+  /* Get the auth key of the intro point */
+  crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
+  helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
+
+  /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
+     attempt to parse it. */
+  establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
+                                                       sizeof(circuit_key_material));
+  tt_assert(establish_intro_cell);
+  /* Mangle the auth key length. */
+  hs_cell_establish_intro_set_auth_key_len(establish_intro_cell,
+                                           bad_auth_key_len);
+  hs_cell_establish_intro_setlen_auth_key(establish_intro_cell,
+                                          bad_auth_key_len);
+  cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
+                                         establish_intro_cell);
+  tt_int_op(cell_len, >, 0);
+
+  /* Receive the cell. Should fail. */
+  setup_full_capture_of_logs(LOG_INFO);
+  retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
+  expect_log_msg_containing("ESTABLISH_INTRO auth key length is invalid");
+  teardown_capture_of_logs();
+  tt_int_op(retval, ==, -1);
+
+ done:
+  hs_cell_establish_intro_free(establish_intro_cell);
+  circuit_free(TO_CIRCUIT(intro_circ));
+}
+
+/* Send a legit ESTABLISH_INTRO cell but with a wrong sig length. Should
+ * fail. */
+static void
+test_establish_intro_wrong_sig_len(void *arg)
+{
+  int retval;
+  hs_cell_establish_intro_t *establish_intro_cell = NULL;
+  or_circuit_t *intro_circ = or_circuit_new(0,NULL);;
+  uint8_t cell_body[RELAY_PAYLOAD_SIZE];
+  ssize_t cell_len = 0;
+  size_t bad_sig_len = ED25519_SIG_LEN - 1;
+  uint8_t circuit_key_material[DIGEST_LEN] = {0};
+
+  (void)arg;
+
+  /* Get the auth key of the intro point */
+  crypto_rand((char *) circuit_key_material, sizeof(circuit_key_material));
+  helper_prepare_circ_for_intro(intro_circ, circuit_key_material);
+
+  /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
+     attempt to parse it. */
+  establish_intro_cell = generate_establish_intro_cell(circuit_key_material,
+                                                       sizeof(circuit_key_material));
+  tt_assert(establish_intro_cell);
+  /* Mangle the signature length. */
+  hs_cell_establish_intro_set_sig_len(establish_intro_cell, bad_sig_len);
+  hs_cell_establish_intro_setlen_sig(establish_intro_cell, bad_sig_len);
+  cell_len = get_establish_intro_payload(cell_body, sizeof(cell_body),
+                                         establish_intro_cell);
+  tt_int_op(cell_len, >, 0);
+
+  /* Receive the cell. Should fail. */
+  setup_full_capture_of_logs(LOG_INFO);
+  retval = hs_intro_received_establish_intro(intro_circ, cell_body, cell_len);
+  expect_log_msg_containing("ESTABLISH_INTRO sig len is invalid");
+  teardown_capture_of_logs();
+  tt_int_op(retval, ==, -1);
+
+ done:
+  hs_cell_establish_intro_free(establish_intro_cell);
+  circuit_free(TO_CIRCUIT(intro_circ));
+}
+
 /* Send a legit ESTABLISH_INTRO cell but slightly change the signature. Should
  * fail. */
 static void
@@ -356,6 +515,15 @@ struct testcase_t hs_intropoint_tests[] = {
   { "receive_establish_intro_wrong_sig",
     test_establish_intro_wrong_sig, TT_FORK, NULL, NULL },
 
+  { "receive_establish_intro_wrong_sig_len",
+    test_establish_intro_wrong_sig_len, TT_FORK, NULL, NULL },
+
+  { "receive_establish_intro_wrong_auth_key_len",
+    test_establish_intro_wrong_auth_key_len, TT_FORK, NULL, NULL },
+
+  { "receive_establish_intro_wrong_mac",
+    test_establish_intro_wrong_mac, TT_FORK, NULL, NULL },
+
   END_OF_TESTCASES
 };