onion_ntor.c 12 KB

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