onion_ntor.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /* Copyright (c) 2012-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file onion_ntor.c
  5. *
  6. * \brief Implementation for the ntor handshake.
  7. *
  8. * The ntor circuit-extension handshake was developed as a replacement
  9. * for the old TAP handshake. It uses Elliptic-curve Diffie-Hellman and
  10. * a hash function in order to perform a one-way authenticated key
  11. * exchange. The ntor handshake is meant to replace the old "TAP"
  12. * handshake.
  13. *
  14. * We instantiate ntor with curve25519, HMAC-SHA256, and HKDF.
  15. *
  16. * This handshake, like the other circuit-extension handshakes, is
  17. * invoked from onion.c.
  18. */
  19. #include "orconfig.h"
  20. #define ONION_NTOR_PRIVATE
  21. #include "lib/crypt_ops/crypto_cipher.h"
  22. #include "lib/crypt_ops/crypto_digest.h"
  23. #include "lib/crypt_ops/crypto_hkdf.h"
  24. #include "lib/crypt_ops/crypto_util.h"
  25. #include "lib/ctime/di_ops.h"
  26. #include "lib/log/log.h"
  27. #include "lib/log/util_bug.h"
  28. #include "core/crypto/onion_ntor.h"
  29. #include <string.h>
  30. /** Free storage held in an ntor handshake state. */
  31. void
  32. ntor_handshake_state_free_(ntor_handshake_state_t *state)
  33. {
  34. if (!state)
  35. return;
  36. memwipe(state, 0, sizeof(*state));
  37. tor_free(state);
  38. }
  39. /** Convenience function to represent HMAC_SHA256 as our instantiation of
  40. * ntor's "tweaked hash'. Hash the <b>inp_len</b> bytes at <b>inp</b> into
  41. * a DIGEST256_LEN-byte digest at <b>out</b>, with the hash changing
  42. * depending on the value of <b>tweak</b>. */
  43. static void
  44. h_tweak(uint8_t *out,
  45. const uint8_t *inp, size_t inp_len,
  46. const char *tweak)
  47. {
  48. size_t tweak_len = strlen(tweak);
  49. crypto_hmac_sha256((char*)out, tweak, tweak_len, (const char*)inp, inp_len);
  50. }
  51. /** Wrapper around a set of tweak-values for use with the ntor handshake. */
  52. typedef struct tweakset_t {
  53. const char *t_mac;
  54. const char *t_key;
  55. const char *t_verify;
  56. const char *m_expand;
  57. } tweakset_t;
  58. /** The tweaks to be used with our handshake. */
  59. static const tweakset_t proto1_tweaks = {
  60. #define PROTOID "ntor-curve25519-sha256-1"
  61. #define PROTOID_LEN 24
  62. PROTOID ":mac",
  63. PROTOID ":key_extract",
  64. PROTOID ":verify",
  65. PROTOID ":key_expand"
  66. };
  67. /** Convenience macro: copy <b>len</b> bytes from <b>inp</b> to <b>ptr</b>,
  68. * and advance <b>ptr</b> by the number of bytes copied. */
  69. #define APPEND(ptr, inp, len) \
  70. STMT_BEGIN { \
  71. memcpy(ptr, (inp), (len)); \
  72. ptr += len; \
  73. } STMT_END
  74. /**
  75. * Compute the first client-side step of the ntor handshake for communicating
  76. * with a server whose DIGEST_LEN-byte server identity is <b>router_id</b>,
  77. * and whose onion key is <b>router_key</b>. Store the NTOR_ONIONSKIN_LEN-byte
  78. * message in <b>onion_skin_out</b>, and store the handshake state in
  79. * *<b>handshake_state_out</b>. Return 0 on success, -1 on failure.
  80. */
  81. int
  82. onion_skin_ntor_create(const uint8_t *router_id,
  83. const curve25519_public_key_t *router_key,
  84. ntor_handshake_state_t **handshake_state_out,
  85. uint8_t *onion_skin_out)
  86. {
  87. ntor_handshake_state_t *state;
  88. uint8_t *op;
  89. state = tor_malloc_zero(sizeof(ntor_handshake_state_t));
  90. memcpy(state->router_id, router_id, DIGEST_LEN);
  91. memcpy(&state->pubkey_B, router_key, sizeof(curve25519_public_key_t));
  92. if (curve25519_secret_key_generate(&state->seckey_x, 0) < 0) {
  93. /* LCOV_EXCL_START
  94. * Secret key generation should be unable to fail when the key isn't
  95. * marked as "extra-strong" */
  96. tor_assert_nonfatal_unreached();
  97. tor_free(state);
  98. return -1;
  99. /* LCOV_EXCL_STOP */
  100. }
  101. curve25519_public_key_generate(&state->pubkey_X, &state->seckey_x);
  102. op = onion_skin_out;
  103. APPEND(op, router_id, DIGEST_LEN);
  104. APPEND(op, router_key->public_key, CURVE25519_PUBKEY_LEN);
  105. APPEND(op, state->pubkey_X.public_key, CURVE25519_PUBKEY_LEN);
  106. tor_assert(op == onion_skin_out + NTOR_ONIONSKIN_LEN);
  107. *handshake_state_out = state;
  108. return 0;
  109. }
  110. #define SERVER_STR "Server"
  111. #define SERVER_STR_LEN 6
  112. #define SECRET_INPUT_LEN (CURVE25519_PUBKEY_LEN * 3 + \
  113. CURVE25519_OUTPUT_LEN * 2 + \
  114. DIGEST_LEN + PROTOID_LEN)
  115. #define AUTH_INPUT_LEN (DIGEST256_LEN + DIGEST_LEN + \
  116. CURVE25519_PUBKEY_LEN*3 + \
  117. PROTOID_LEN + SERVER_STR_LEN)
  118. /**
  119. * Perform the server side of an ntor handshake. Given an
  120. * NTOR_ONIONSKIN_LEN-byte message in <b>onion_skin</b>, our own identity
  121. * fingerprint as <b>my_node_id</b>, and an associative array mapping public
  122. * onion keys to curve25519_keypair_t in <b>private_keys</b>, attempt to
  123. * perform the handshake. Use <b>junk_keys</b> if present if the handshake
  124. * indicates an unrecognized public key. Write an NTOR_REPLY_LEN-byte
  125. * message to send back to the client into <b>handshake_reply_out</b>, and
  126. * generate <b>key_out_len</b> bytes of key material in <b>key_out</b>. Return
  127. * 0 on success, -1 on failure.
  128. */
  129. int
  130. onion_skin_ntor_server_handshake(const uint8_t *onion_skin,
  131. const di_digest256_map_t *private_keys,
  132. const curve25519_keypair_t *junk_keys,
  133. const uint8_t *my_node_id,
  134. uint8_t *handshake_reply_out,
  135. uint8_t *key_out,
  136. size_t key_out_len)
  137. {
  138. const tweakset_t *T = &proto1_tweaks;
  139. /* Sensitive stack-allocated material. Kept in an anonymous struct to make
  140. * it easy to wipe. */
  141. struct {
  142. uint8_t secret_input[SECRET_INPUT_LEN];
  143. uint8_t auth_input[AUTH_INPUT_LEN];
  144. curve25519_public_key_t pubkey_X;
  145. curve25519_secret_key_t seckey_y;
  146. curve25519_public_key_t pubkey_Y;
  147. uint8_t verify[DIGEST256_LEN];
  148. } s;
  149. uint8_t *si = s.secret_input, *ai = s.auth_input;
  150. const curve25519_keypair_t *keypair_bB;
  151. int bad;
  152. /* Decode the onion skin */
  153. /* XXXX Does this possible early-return business threaten our security? */
  154. if (tor_memneq(onion_skin, my_node_id, DIGEST_LEN))
  155. return -1;
  156. /* Note that on key-not-found, we go through with this operation anyway,
  157. * using "junk_keys". This will result in failed authentication, but won't
  158. * leak whether we recognized the key. */
  159. keypair_bB = dimap_search(private_keys, onion_skin + DIGEST_LEN,
  160. (void*)junk_keys);
  161. if (!keypair_bB)
  162. return -1;
  163. memcpy(s.pubkey_X.public_key, onion_skin+DIGEST_LEN+DIGEST256_LEN,
  164. CURVE25519_PUBKEY_LEN);
  165. /* Make y, Y */
  166. curve25519_secret_key_generate(&s.seckey_y, 0);
  167. curve25519_public_key_generate(&s.pubkey_Y, &s.seckey_y);
  168. /* NOTE: If we ever use a group other than curve25519, or a different
  169. * representation for its points, we may need to perform different or
  170. * additional checks on X here and on Y in the client handshake, or lose our
  171. * security properties. What checks we need would depend on the properties
  172. * of the group and its representation.
  173. *
  174. * In short: if you use anything other than curve25519, this aspect of the
  175. * code will need to be reconsidered carefully. */
  176. /* build secret_input */
  177. curve25519_handshake(si, &s.seckey_y, &s.pubkey_X);
  178. bad = safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN);
  179. si += CURVE25519_OUTPUT_LEN;
  180. curve25519_handshake(si, &keypair_bB->seckey, &s.pubkey_X);
  181. bad |= safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN);
  182. si += CURVE25519_OUTPUT_LEN;
  183. APPEND(si, my_node_id, DIGEST_LEN);
  184. APPEND(si, keypair_bB->pubkey.public_key, CURVE25519_PUBKEY_LEN);
  185. APPEND(si, s.pubkey_X.public_key, CURVE25519_PUBKEY_LEN);
  186. APPEND(si, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN);
  187. APPEND(si, PROTOID, PROTOID_LEN);
  188. tor_assert(si == s.secret_input + sizeof(s.secret_input));
  189. /* Compute hashes of secret_input */
  190. h_tweak(s.verify, s.secret_input, sizeof(s.secret_input), T->t_verify);
  191. /* Compute auth_input */
  192. APPEND(ai, s.verify, DIGEST256_LEN);
  193. APPEND(ai, my_node_id, DIGEST_LEN);
  194. APPEND(ai, keypair_bB->pubkey.public_key, CURVE25519_PUBKEY_LEN);
  195. APPEND(ai, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN);
  196. APPEND(ai, s.pubkey_X.public_key, CURVE25519_PUBKEY_LEN);
  197. APPEND(ai, PROTOID, PROTOID_LEN);
  198. APPEND(ai, SERVER_STR, SERVER_STR_LEN);
  199. tor_assert(ai == s.auth_input + sizeof(s.auth_input));
  200. /* Build the reply */
  201. memcpy(handshake_reply_out, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN);
  202. h_tweak(handshake_reply_out+CURVE25519_PUBKEY_LEN,
  203. s.auth_input, sizeof(s.auth_input),
  204. T->t_mac);
  205. /* Generate the key material */
  206. crypto_expand_key_material_rfc5869_sha256(
  207. s.secret_input, sizeof(s.secret_input),
  208. (const uint8_t*)T->t_key, strlen(T->t_key),
  209. (const uint8_t*)T->m_expand, strlen(T->m_expand),
  210. key_out, key_out_len);
  211. /* Wipe all of our local state */
  212. memwipe(&s, 0, sizeof(s));
  213. return bad ? -1 : 0;
  214. }
  215. /**
  216. * Perform the final client side of the ntor handshake, using the state in
  217. * <b>handshake_state</b> and the server's NTOR_REPLY_LEN-byte reply in
  218. * <b>handshake_reply</b>. Generate <b>key_out_len</b> bytes of key material
  219. * in <b>key_out</b>. Return 0 on success, -1 on failure.
  220. */
  221. int
  222. onion_skin_ntor_client_handshake(
  223. const ntor_handshake_state_t *handshake_state,
  224. const uint8_t *handshake_reply,
  225. uint8_t *key_out,
  226. size_t key_out_len,
  227. const char **msg_out)
  228. {
  229. const tweakset_t *T = &proto1_tweaks;
  230. /* Sensitive stack-allocated material. Kept in an anonymous struct to make
  231. * it easy to wipe. */
  232. struct {
  233. curve25519_public_key_t pubkey_Y;
  234. uint8_t secret_input[SECRET_INPUT_LEN];
  235. uint8_t verify[DIGEST256_LEN];
  236. uint8_t auth_input[AUTH_INPUT_LEN];
  237. uint8_t auth[DIGEST256_LEN];
  238. } s;
  239. uint8_t *ai = s.auth_input, *si = s.secret_input;
  240. const uint8_t *auth_candidate;
  241. int bad;
  242. /* Decode input */
  243. memcpy(s.pubkey_Y.public_key, handshake_reply, CURVE25519_PUBKEY_LEN);
  244. auth_candidate = handshake_reply + CURVE25519_PUBKEY_LEN;
  245. /* See note in server_handshake above about checking points. The
  246. * circumstances under which we'd need to check Y for membership are
  247. * different than those under which we'd be checking X. */
  248. /* Compute secret_input */
  249. curve25519_handshake(si, &handshake_state->seckey_x, &s.pubkey_Y);
  250. bad = safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN);
  251. si += CURVE25519_OUTPUT_LEN;
  252. curve25519_handshake(si, &handshake_state->seckey_x,
  253. &handshake_state->pubkey_B);
  254. bad |= (safe_mem_is_zero(si, CURVE25519_OUTPUT_LEN) << 1);
  255. si += CURVE25519_OUTPUT_LEN;
  256. APPEND(si, handshake_state->router_id, DIGEST_LEN);
  257. APPEND(si, handshake_state->pubkey_B.public_key, CURVE25519_PUBKEY_LEN);
  258. APPEND(si, handshake_state->pubkey_X.public_key, CURVE25519_PUBKEY_LEN);
  259. APPEND(si, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN);
  260. APPEND(si, PROTOID, PROTOID_LEN);
  261. tor_assert(si == s.secret_input + sizeof(s.secret_input));
  262. /* Compute verify from secret_input */
  263. h_tweak(s.verify, s.secret_input, sizeof(s.secret_input), T->t_verify);
  264. /* Compute auth_input */
  265. APPEND(ai, s.verify, DIGEST256_LEN);
  266. APPEND(ai, handshake_state->router_id, DIGEST_LEN);
  267. APPEND(ai, handshake_state->pubkey_B.public_key, CURVE25519_PUBKEY_LEN);
  268. APPEND(ai, s.pubkey_Y.public_key, CURVE25519_PUBKEY_LEN);
  269. APPEND(ai, handshake_state->pubkey_X.public_key, CURVE25519_PUBKEY_LEN);
  270. APPEND(ai, PROTOID, PROTOID_LEN);
  271. APPEND(ai, SERVER_STR, SERVER_STR_LEN);
  272. tor_assert(ai == s.auth_input + sizeof(s.auth_input));
  273. /* Compute auth */
  274. h_tweak(s.auth, s.auth_input, sizeof(s.auth_input), T->t_mac);
  275. bad |= (tor_memneq(s.auth, auth_candidate, DIGEST256_LEN) << 2);
  276. crypto_expand_key_material_rfc5869_sha256(
  277. s.secret_input, sizeof(s.secret_input),
  278. (const uint8_t*)T->t_key, strlen(T->t_key),
  279. (const uint8_t*)T->m_expand, strlen(T->m_expand),
  280. key_out, key_out_len);
  281. memwipe(&s, 0, sizeof(s));
  282. if (bad) {
  283. if (bad & 4) {
  284. if (msg_out)
  285. *msg_out = NULL; /* Don't report this one; we probably just had the
  286. * wrong onion key.*/
  287. log_fn(LOG_INFO, LD_PROTOCOL,
  288. "Invalid result from curve25519 handshake: %d", bad);
  289. }
  290. if (bad & 3) {
  291. if (msg_out)
  292. *msg_out = "Zero output from curve25519 handshake";
  293. log_fn(LOG_WARN, LD_PROTOCOL,
  294. "Invalid result from curve25519 handshake: %d", bad);
  295. }
  296. }
  297. return bad ? -1 : 0;
  298. }