onion_tap.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* Copyright (c) 2001 Matej Pfajfar.
  2. * Copyright (c) 2001-2004, Roger Dingledine.
  3. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  4. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  5. /* See LICENSE for licensing information */
  6. /**
  7. * \file onion_tap.c
  8. * \brief Functions to implement the original Tor circuit extension handshake
  9. * (a.k.a TAP).
  10. *
  11. * The "TAP" handshake is the first one that was widely used in Tor: It
  12. * combines RSA1024-OAEP and AES128-CTR to perform a hybrid encryption over
  13. * the first message DH1024 key exchange. (The RSA-encrypted part of the
  14. * encryption is authenticated; the AES-encrypted part isn't. This was
  15. * not a smart choice.)
  16. *
  17. * We didn't call it "TAP" ourselves -- Ian Goldberg named it in "On the
  18. * Security of the Tor Authentication Protocol". (Spoiler: it's secure, but
  19. * its security is kind of fragile and implementation dependent. Never modify
  20. * this implementation without reading and understanding that paper at least.)
  21. *
  22. * We have deprecated TAP since the ntor handshake came into general use. It
  23. * is still used for hidden service IP and RP connections, however.
  24. *
  25. * This handshake, like the other circuit-extension handshakes, is
  26. * invoked from onion.c.
  27. **/
  28. #include "core/or/or.h"
  29. #include "app/config/config.h"
  30. #include "lib/crypt_ops/crypto_dh.h"
  31. #include "lib/crypt_ops/crypto_rand.h"
  32. #include "lib/crypt_ops/crypto_util.h"
  33. #include "core/crypto/onion_tap.h"
  34. #include "feature/stats/rephist.h"
  35. /*----------------------------------------------------------------------*/
  36. /** Given a router's 128 byte public key,
  37. * stores the following in onion_skin_out:
  38. * - [42 bytes] OAEP padding
  39. * - [16 bytes] Symmetric key for encrypting blob past RSA
  40. * - [70 bytes] g^x part 1 (inside the RSA)
  41. * - [58 bytes] g^x part 2 (symmetrically encrypted)
  42. *
  43. * Stores the DH private key into handshake_state_out for later completion
  44. * of the handshake.
  45. *
  46. * The meeting point/cookies and auth are zeroed out for now.
  47. */
  48. int
  49. onion_skin_TAP_create(crypto_pk_t *dest_router_key,
  50. crypto_dh_t **handshake_state_out,
  51. char *onion_skin_out) /* TAP_ONIONSKIN_CHALLENGE_LEN bytes */
  52. {
  53. char challenge[DH1024_KEY_LEN];
  54. crypto_dh_t *dh = NULL;
  55. int dhbytes, pkbytes;
  56. tor_assert(dest_router_key);
  57. tor_assert(handshake_state_out);
  58. tor_assert(onion_skin_out);
  59. *handshake_state_out = NULL;
  60. memset(onion_skin_out, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
  61. if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT)))
  62. goto err;
  63. dhbytes = crypto_dh_get_bytes(dh);
  64. pkbytes = (int) crypto_pk_keysize(dest_router_key);
  65. tor_assert(dhbytes == 128);
  66. tor_assert(pkbytes == 128);
  67. if (crypto_dh_get_public(dh, challenge, dhbytes))
  68. goto err;
  69. /* set meeting point, meeting cookie, etc here. Leave zero for now. */
  70. if (crypto_pk_obsolete_public_hybrid_encrypt(dest_router_key, onion_skin_out,
  71. TAP_ONIONSKIN_CHALLENGE_LEN,
  72. challenge, DH1024_KEY_LEN,
  73. PK_PKCS1_OAEP_PADDING, 1)<0)
  74. goto err;
  75. memwipe(challenge, 0, sizeof(challenge));
  76. *handshake_state_out = dh;
  77. return 0;
  78. err:
  79. /* LCOV_EXCL_START
  80. * We only get here if RSA encryption fails or DH keygen fails. Those
  81. * shouldn't be possible. */
  82. memwipe(challenge, 0, sizeof(challenge));
  83. if (dh) crypto_dh_free(dh);
  84. return -1;
  85. /* LCOV_EXCL_STOP */
  86. }
  87. /** Given an encrypted DH public key as generated by onion_skin_create,
  88. * and the private key for this onion router, generate the reply (128-byte
  89. * DH plus the first 20 bytes of shared key material), and store the
  90. * next key_out_len bytes of key material in key_out.
  91. */
  92. int
  93. onion_skin_TAP_server_handshake(
  94. /*TAP_ONIONSKIN_CHALLENGE_LEN*/
  95. const char *onion_skin,
  96. crypto_pk_t *private_key,
  97. crypto_pk_t *prev_private_key,
  98. /*TAP_ONIONSKIN_REPLY_LEN*/
  99. char *handshake_reply_out,
  100. char *key_out,
  101. size_t key_out_len)
  102. {
  103. char challenge[TAP_ONIONSKIN_CHALLENGE_LEN];
  104. crypto_dh_t *dh = NULL;
  105. ssize_t len;
  106. char *key_material=NULL;
  107. size_t key_material_len=0;
  108. int i;
  109. crypto_pk_t *k;
  110. len = -1;
  111. for (i=0;i<2;++i) {
  112. k = i==0?private_key:prev_private_key;
  113. if (!k)
  114. break;
  115. len = crypto_pk_obsolete_private_hybrid_decrypt(k, challenge,
  116. TAP_ONIONSKIN_CHALLENGE_LEN,
  117. onion_skin,
  118. TAP_ONIONSKIN_CHALLENGE_LEN,
  119. PK_PKCS1_OAEP_PADDING,0);
  120. if (len>0)
  121. break;
  122. }
  123. if (len<0) {
  124. log_info(LD_PROTOCOL,
  125. "Couldn't decrypt onionskin: client may be using old onion key");
  126. goto err;
  127. } else if (len != DH1024_KEY_LEN) {
  128. log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
  129. "Unexpected onionskin length after decryption: %ld",
  130. (long)len);
  131. goto err;
  132. }
  133. dh = crypto_dh_new(DH_TYPE_CIRCUIT);
  134. if (!dh) {
  135. /* LCOV_EXCL_START
  136. * Failure to allocate a DH key should be impossible.
  137. */
  138. log_warn(LD_BUG, "Couldn't allocate DH key");
  139. goto err;
  140. /* LCOV_EXCL_STOP */
  141. }
  142. if (crypto_dh_get_public(dh, handshake_reply_out, DH1024_KEY_LEN)) {
  143. /* LCOV_EXCL_START
  144. * This can only fail if the length of the key we just allocated is too
  145. * big. That should be impossible. */
  146. log_info(LD_GENERAL, "crypto_dh_get_public failed.");
  147. goto err;
  148. /* LCOV_EXCL_STOP */
  149. }
  150. key_material_len = DIGEST_LEN+key_out_len;
  151. key_material = tor_malloc(key_material_len);
  152. len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, challenge,
  153. DH1024_KEY_LEN, key_material,
  154. key_material_len);
  155. if (len < 0) {
  156. log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
  157. goto err;
  158. }
  159. /* send back H(K|0) as proof that we learned K. */
  160. memcpy(handshake_reply_out+DH1024_KEY_LEN, key_material, DIGEST_LEN);
  161. /* use the rest of the key material for our shared keys, digests, etc */
  162. memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
  163. memwipe(challenge, 0, sizeof(challenge));
  164. memwipe(key_material, 0, key_material_len);
  165. tor_free(key_material);
  166. crypto_dh_free(dh);
  167. return 0;
  168. err:
  169. memwipe(challenge, 0, sizeof(challenge));
  170. if (key_material) {
  171. memwipe(key_material, 0, key_material_len);
  172. tor_free(key_material);
  173. }
  174. if (dh) crypto_dh_free(dh);
  175. return -1;
  176. }
  177. /** Finish the client side of the DH handshake.
  178. * Given the 128 byte DH reply + 20 byte hash as generated by
  179. * onion_skin_server_handshake and the handshake state generated by
  180. * onion_skin_create, verify H(K) with the first 20 bytes of shared
  181. * key material, then generate key_out_len more bytes of shared key
  182. * material and store them in key_out.
  183. *
  184. * After the invocation, call crypto_dh_free on handshake_state.
  185. */
  186. int
  187. onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
  188. const char *handshake_reply, /* TAP_ONIONSKIN_REPLY_LEN bytes */
  189. char *key_out,
  190. size_t key_out_len,
  191. const char **msg_out)
  192. {
  193. ssize_t len;
  194. char *key_material=NULL;
  195. size_t key_material_len;
  196. tor_assert(crypto_dh_get_bytes(handshake_state) == DH1024_KEY_LEN);
  197. key_material_len = DIGEST_LEN + key_out_len;
  198. key_material = tor_malloc(key_material_len);
  199. len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, handshake_state,
  200. handshake_reply, DH1024_KEY_LEN, key_material,
  201. key_material_len);
  202. if (len < 0) {
  203. if (msg_out)
  204. *msg_out = "DH computation failed.";
  205. goto err;
  206. }
  207. if (tor_memneq(key_material, handshake_reply+DH1024_KEY_LEN, DIGEST_LEN)) {
  208. /* H(K) does *not* match. Something fishy. */
  209. if (msg_out)
  210. *msg_out = "Digest DOES NOT MATCH on onion handshake. Bug or attack.";
  211. goto err;
  212. }
  213. /* use the rest of the key material for our shared keys, digests, etc */
  214. memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
  215. memwipe(key_material, 0, key_material_len);
  216. tor_free(key_material);
  217. return 0;
  218. err:
  219. memwipe(key_material, 0, key_material_len);
  220. tor_free(key_material);
  221. return -1;
  222. }