Esempio n. 1
0
File: bench.c Progetto: 1234max/tor
static void
bench_onion_ntor_impl(void)
{
  const int iters = 1<<10;
  int i;
  curve25519_keypair_t keypair1, keypair2;
  uint64_t start, end;
  uint8_t os[NTOR_ONIONSKIN_LEN];
  uint8_t or[NTOR_REPLY_LEN];
  ntor_handshake_state_t *state = NULL;
  uint8_t nodeid[DIGEST_LEN];
  di_digest256_map_t *keymap = NULL;

  curve25519_secret_key_generate(&keypair1.seckey, 0);
  curve25519_public_key_generate(&keypair1.pubkey, &keypair1.seckey);
  curve25519_secret_key_generate(&keypair2.seckey, 0);
  curve25519_public_key_generate(&keypair2.pubkey, &keypair2.seckey);
  dimap_add_entry(&keymap, keypair1.pubkey.public_key, &keypair1);
  dimap_add_entry(&keymap, keypair2.pubkey.public_key, &keypair2);

  reset_perftime();
  start = perftime();
  for (i = 0; i < iters; ++i) {
    onion_skin_ntor_create(nodeid, &keypair1.pubkey, &state, os);
    ntor_handshake_state_free(state);
    state = NULL;
  }
  end = perftime();
  printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start, end, iters)/1e3);

  state = NULL;
  onion_skin_ntor_create(nodeid, &keypair1.pubkey, &state, os);
  start = perftime();
  for (i = 0; i < iters; ++i) {
    uint8_t key_out[CPATH_KEY_MATERIAL_LEN];
    onion_skin_ntor_server_handshake(os, keymap, NULL, nodeid, or,
                                key_out, sizeof(key_out));
  }
  end = perftime();
  printf("Server-side: %f usec\n",
         NANOCOUNT(start, end, iters)/1e3);

  start = perftime();
  for (i = 0; i < iters; ++i) {
    uint8_t key_out[CPATH_KEY_MATERIAL_LEN];
    int s;
    s = onion_skin_ntor_client_handshake(state, or, key_out, sizeof(key_out),
                                         NULL);
    tor_assert(s == 0);
  }
  end = perftime();
  printf("Client-side, part 2: %f usec.\n",
         NANOCOUNT(start, end, iters)/1e3);

  ntor_handshake_state_free(state);
  dimap_free(keymap, NULL);
}
Esempio n. 2
0
static void
test_crypto_curve25519_encode(void *arg)
{
  curve25519_secret_key_t seckey;
  curve25519_public_key_t key1, key2, key3;
  char buf[64];

  (void)arg;

  curve25519_secret_key_generate(&seckey, 0);
  curve25519_public_key_generate(&key1, &seckey);
  tt_int_op(0, ==, curve25519_public_to_base64(buf, &key1));
  tt_int_op(CURVE25519_BASE64_PADDED_LEN, ==, strlen(buf));

  tt_int_op(0, ==, curve25519_public_from_base64(&key2, buf));
  test_memeq(key1.public_key, key2.public_key, CURVE25519_PUBKEY_LEN);

  buf[CURVE25519_BASE64_PADDED_LEN - 1] = '\0';
  tt_int_op(CURVE25519_BASE64_PADDED_LEN-1, ==, strlen(buf));
  tt_int_op(0, ==, curve25519_public_from_base64(&key3, buf));
  test_memeq(key1.public_key, key3.public_key, CURVE25519_PUBKEY_LEN);

  /* Now try bogus parses. */
  strlcpy(buf, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$=", sizeof(buf));
  tt_int_op(-1, ==, curve25519_public_from_base64(&key3, buf));

  strlcpy(buf, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", sizeof(buf));
  tt_int_op(-1, ==, curve25519_public_from_base64(&key3, buf));

  strlcpy(buf, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", sizeof(buf));
  tt_int_op(-1, ==, curve25519_public_from_base64(&key3, buf));

 done:
  ;
}
Esempio n. 3
0
/**
 * Compute the first client-side step of the ntor handshake for communicating
 * with a server whose DIGEST_LEN-byte server identity is <b>router_id</b>,
 * and whose onion key is <b>router_key</b>. Store the NTOR_ONIONSKIN_LEN-byte
 * message in <b>onion_skin_out</b>, and store the handshake state in
 * *<b>handshake_state_out</b>.  Return 0 on success, -1 on failure.
 */
int
onion_skin_ntor_create(const uint8_t *router_id,
                       const curve25519_public_key_t *router_key,
                       ntor_handshake_state_t **handshake_state_out,
                       uint8_t *onion_skin_out)
{
  ntor_handshake_state_t *state;
  uint8_t *op;

  state = tor_malloc_zero(sizeof(ntor_handshake_state_t));

  memcpy(state->router_id, router_id, DIGEST_LEN);
  memcpy(&state->pubkey_B, router_key, sizeof(curve25519_public_key_t));
  if (curve25519_secret_key_generate(&state->seckey_x, 0) < 0) {
    tor_free(state);
    return -1;
  }
  curve25519_public_key_generate(&state->pubkey_X, &state->seckey_x);

  op = onion_skin_out;
  APPEND(op, router_id, DIGEST_LEN);
  APPEND(op, router_key->public_key, CURVE25519_PUBKEY_LEN);
  APPEND(op, state->pubkey_X.public_key, CURVE25519_PUBKEY_LEN);
  tor_assert(op == onion_skin_out + NTOR_ONIONSKIN_LEN);

  *handshake_state_out = state;

  return 0;
}
Esempio n. 4
0
/* DOCDOC */
int
curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
                                  char **tag_out,
                                  const char *fname)
{
  uint8_t content[CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN];
  ssize_t len;
  int r = -1;

  len = crypto_read_tagged_contents_from_file(fname, "c25519v1", tag_out,
                                              content, sizeof(content));
  if (len != sizeof(content))
    goto end;

  memcpy(keypair_out->seckey.secret_key, content, CURVE25519_SECKEY_LEN);
  curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
  if (tor_memneq(keypair_out->pubkey.public_key,
                 content + CURVE25519_SECKEY_LEN,
                 CURVE25519_PUBKEY_LEN))
    goto end;

  r = 0;

 end:
  memwipe(content, 0, sizeof(content));
  if (r != 0) {
    memset(keypair_out, 0, sizeof(*keypair_out));
    tor_free(*tag_out);
  }
  return r;
}
Esempio n. 5
0
File: test.c Progetto: ageis/tor
static void
test_ntor_handshake(void *arg)
{
  /* client-side */
  ntor_handshake_state_t *c_state = NULL;
  uint8_t c_buf[NTOR_ONIONSKIN_LEN];
  uint8_t c_keys[400];

  /* server-side */
  di_digest256_map_t *s_keymap=NULL;
  curve25519_keypair_t s_keypair;
  uint8_t s_buf[NTOR_REPLY_LEN];
  uint8_t s_keys[400];

  /* shared */
  const curve25519_public_key_t *server_pubkey;
  uint8_t node_id[20] = "abcdefghijklmnopqrst";

  (void) arg;

  /* Make the server some keys */
  curve25519_secret_key_generate(&s_keypair.seckey, 0);
  curve25519_public_key_generate(&s_keypair.pubkey, &s_keypair.seckey);
  dimap_add_entry(&s_keymap, s_keypair.pubkey.public_key, &s_keypair);
  server_pubkey = &s_keypair.pubkey;

  /* client handshake 1. */
  memset(c_buf, 0, NTOR_ONIONSKIN_LEN);
  tt_int_op(0, OP_EQ, onion_skin_ntor_create(node_id, server_pubkey,
                                          &c_state, c_buf));

  /* server handshake */
  memset(s_buf, 0, NTOR_REPLY_LEN);
  memset(s_keys, 0, 40);
  tt_int_op(0, OP_EQ, onion_skin_ntor_server_handshake(c_buf, s_keymap, NULL,
                                                    node_id,
                                                    s_buf, s_keys, 400));

  /* client handshake 2 */
  memset(c_keys, 0, 40);
  tt_int_op(0, OP_EQ, onion_skin_ntor_client_handshake(c_state, s_buf,
                                                       c_keys, 400, NULL));

  tt_mem_op(c_keys,OP_EQ, s_keys, 400);
  memset(s_buf, 0, 40);
  tt_mem_op(c_keys,OP_NE, s_buf, 40);

  /* Now try with a bogus server response. Zero input should trigger
   * All The Problems. */
  memset(c_keys, 0, 400);
  memset(s_buf, 0, NTOR_REPLY_LEN);
  const char *msg = NULL;
  tt_int_op(-1, OP_EQ, onion_skin_ntor_client_handshake(c_state, s_buf,
                                                        c_keys, 400, &msg));
  tt_str_op(msg, OP_EQ, "Zero output from curve25519 handshake");

 done:
  ntor_handshake_state_free(c_state);
  dimap_free(s_keymap, NULL);
}
Esempio n. 6
0
/**
 * Compute the first client-side step of the ntor handshake for communicating
 * with a server whose DIGEST_LEN-byte server identity is <b>router_id</b>,
 * and whose onion key is <b>router_key</b>. Store the NTOR_ONIONSKIN_LEN-byte
 * message in <b>onion_skin_out</b>, and store the handshake state in
 * *<b>handshake_state_out</b>.  Return 0 on success, -1 on failure.
 */
int
onion_skin_ntor_create(const uint8_t *router_id,
                       const curve25519_public_key_t *router_key,
                       ntor_handshake_state_t **handshake_state_out,
                       uint8_t *onion_skin_out)
{
  ntor_handshake_state_t *state;
  uint8_t *op;

  state = tor_malloc_zero(sizeof(ntor_handshake_state_t));

  memcpy(state->router_id, router_id, DIGEST_LEN);
  memcpy(&state->pubkey_B, router_key, sizeof(curve25519_public_key_t));
  if (curve25519_secret_key_generate(&state->seckey_x, 0) < 0) {
    /* LCOV_EXCL_START
     * Secret key generation should be unable to fail when the key isn't
     * marked as "extra-strong" */
    tor_assert_nonfatal_unreached();
    tor_free(state);
    return -1;
    /* LCOV_EXCL_STOP */
  }
  curve25519_public_key_generate(&state->pubkey_X, &state->seckey_x);

  op = onion_skin_out;
  APPEND(op, router_id, DIGEST_LEN);
  APPEND(op, router_key->public_key, CURVE25519_PUBKEY_LEN);
  APPEND(op, state->pubkey_X.public_key, CURVE25519_PUBKEY_LEN);
  tor_assert(op == onion_skin_out + NTOR_ONIONSKIN_LEN);

  *handshake_state_out = state;

  return 0;
}
Esempio n. 7
0
int
curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
                            int extra_strong)
{
  if (curve25519_secret_key_generate(&keypair_out->seckey, extra_strong) < 0)
    return -1;
  curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
  return 0;
}
Esempio n. 8
0
static void
test_crypto_curve25519_wrappers(void *arg)
{
  curve25519_public_key_t pubkey1, pubkey2;
  curve25519_secret_key_t seckey1, seckey2;

  uint8_t output1[CURVE25519_OUTPUT_LEN];
  uint8_t output2[CURVE25519_OUTPUT_LEN];
  (void)arg;

  /* Test a simple handshake, serializing and deserializing some stuff. */
  curve25519_secret_key_generate(&seckey1, 0);
  curve25519_secret_key_generate(&seckey2, 1);
  curve25519_public_key_generate(&pubkey1, &seckey1);
  curve25519_public_key_generate(&pubkey2, &seckey2);
  test_assert(curve25519_public_key_is_ok(&pubkey1));
  test_assert(curve25519_public_key_is_ok(&pubkey2));
  curve25519_handshake(output1, &seckey1, &pubkey2);
  curve25519_handshake(output2, &seckey2, &pubkey1);
  test_memeq(output1, output2, sizeof(output1));

 done:
  ;
}
Esempio n. 9
0
static int
server1(int argc, char **argv)
{
  uint8_t msg_in[NTOR_ONIONSKIN_LEN];
  curve25519_keypair_t kp;
  di_digest256_map_t *keymap=NULL;
  uint8_t node_id[DIGEST_LEN];
  int keybytes;

  uint8_t msg_out[NTOR_REPLY_LEN];
  uint8_t *keys = NULL;
  char *hexkeys = NULL;
  int result = 0;

  char buf[256];

  /* server1: b nodeID msg N -> msg keys */
  N_ARGS(6);
  BASE16(2, kp.seckey.secret_key, CURVE25519_SECKEY_LEN);
  BASE16(3, node_id, DIGEST_LEN);
  BASE16(4, msg_in, NTOR_ONIONSKIN_LEN);
  INT(5, keybytes);

  curve25519_public_key_generate(&kp.pubkey, &kp.seckey);
  dimap_add_entry(&keymap, kp.pubkey.public_key, &kp);

  keys = tor_malloc(keybytes);
  hexkeys = tor_malloc(keybytes*2+1);
  if (onion_skin_ntor_server_handshake(
                                msg_in, keymap, NULL, node_id, msg_out, keys,
                                (size_t)keybytes)<0) {
    fprintf(stderr, "handshake failed");
    result = 2;
    goto done;
  }

  base16_encode(buf, sizeof(buf), (const char*)msg_out, sizeof(msg_out));
  printf("%s\n", buf);
  base16_encode(hexkeys, keybytes*2+1, (const char*)keys, keybytes);
  printf("%s\n", hexkeys);

 done:
  tor_free(keys);
  tor_free(hexkeys);
  dimap_free(keymap, NULL);
  return result;
}
Esempio n. 10
0
/**
 * Perform the server side of an ntor handshake. Given an
 * NTOR_ONIONSKIN_LEN-byte message in <b>onion_skin</b>, our own identity
 * fingerprint as <b>my_node_id</b>, and an associative array mapping public
 * onion keys to curve25519_keypair_t in <b>private_keys</b>, attempt to
 * perform the handshake.  Use <b>junk_keys</b> if present if the handshake
 * indicates an unrecognized public key.  Write an NTOR_REPLY_LEN-byte
 * message to send back to the client into <b>handshake_reply_out</b>, and
 * generate <b>key_out_len</b> bytes of key material in <b>key_out</b>. Return
 * 0 on success, -1 on failure.
 */
int
onion_skin_ntor_server_handshake(const uint8_t *onion_skin,
                                 const di_digest256_map_t *private_keys,
                                 const curve25519_keypair_t *junk_keys,
                                 const uint8_t *my_node_id,
                                 uint8_t *handshake_reply_out,
                                 uint8_t *key_out,
                                 size_t key_out_len)
{
  const tweakset_t *T = &proto1_tweaks;
  /* Sensitive stack-allocated material. Kept in an anonymous struct to make
   * it easy to wipe. */
  struct {
    uint8_t secret_input[SECRET_INPUT_LEN];
    uint8_t auth_input[AUTH_INPUT_LEN];
    curve25519_public_key_t pubkey_X;
    curve25519_secret_key_t seckey_y;
    curve25519_public_key_t pubkey_Y;
    uint8_t verify[DIGEST256_LEN];
  } s;
  uint8_t *si = s.secret_input, *ai = s.auth_input;
  const curve25519_keypair_t *keypair_bB;
  int bad;

  /* Decode the onion skin */
  /* XXXX Does this possible early-return business threaten our security? */
  if (tor_memneq(onion_skin, my_node_id, DIGEST_LEN))
    return -1;
  /* Note that on key-not-found, we go through with this operation anyway,
   * using "junk_keys". This will result in failed authentication, but won't
   * leak whether we recognized the key. */
  keypair_bB = dimap_search(private_keys, onion_skin + DIGEST_LEN,
                            (void*)junk_keys);
  if (!keypair_bB)
    return -1;

  memcpy(s.pubkey_X.public_key, onion_skin+DIGEST_LEN+DIGEST256_LEN,
         CURVE25519_PUBKEY_LEN);

  /* Make y, Y */
  curve25519_secret_key_generate(&s.seckey_y, 0);
  curve25519_public_key_generate(&s.pubkey_Y, &s.seckey_y);

  /* NOTE: If we ever use a group other than curve25519, or a different
   * representation for its points, we may need to perform different or
   * additional checks on X here and on Y in the client handshake, or lose our
   * security properties. What checks we need would depend on the properties
   * of the group and its representation.
   *
   * In short: if you use anything other than curve25519, this aspect of the
   * code will need to be reconsidered carefully. */

  /* build secret_input */
  curve25519_handshake(si, &s.seckey_y, &s.pubkey_X);
  bad = safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN);
  si += CURVE25519_OUTPUT_LEN;
  curve25519_handshake(si, &keypair_bB->seckey, &s.pubkey_X);
  bad |= safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN);
  si += CURVE25519_OUTPUT_LEN;

  APPEND(si, my_node_id, DIGEST_LEN);
  APPEND(si, keypair_bB->pubkey.public_key, CURVE25519_PUBKEY_LEN);
  APPEND(si, s.pubkey_X.public_key, CURVE25519_PUBKEY_LEN);
  APPEND(si, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN);
  APPEND(si, PROTOID, PROTOID_LEN);
  tor_assert(si == s.secret_input + sizeof(s.secret_input));

  /* Compute hashes of secret_input */
  h_tweak(s.verify, s.secret_input, sizeof(s.secret_input), T->t_verify);

  /* Compute auth_input */
  APPEND(ai, s.verify, DIGEST256_LEN);
  APPEND(ai, my_node_id, DIGEST_LEN);
  APPEND(ai, keypair_bB->pubkey.public_key, CURVE25519_PUBKEY_LEN);
  APPEND(ai, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN);
  APPEND(ai, s.pubkey_X.public_key, CURVE25519_PUBKEY_LEN);
  APPEND(ai, PROTOID, PROTOID_LEN);
  APPEND(ai, SERVER_STR, SERVER_STR_LEN);
  tor_assert(ai == s.auth_input + sizeof(s.auth_input));

  /* Build the reply */
  memcpy(handshake_reply_out, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN);
  h_tweak(handshake_reply_out+CURVE25519_PUBKEY_LEN,
          s.auth_input, sizeof(s.auth_input),
          T->t_mac);

  /* Generate the key material */
  crypto_expand_key_material_rfc5869_sha256(
                           s.secret_input, sizeof(s.secret_input),
                           (const uint8_t*)T->t_key, strlen(T->t_key),
                           (const uint8_t*)T->m_expand, strlen(T->m_expand),
                           key_out, key_out_len);

  /* Wipe all of our local state */
  memwipe(&s, 0, sizeof(s));

  return bad ? -1 : 0;
}