onion_tap.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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-2012, 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. * We didn't call it "TAP" ourselves -- Ian Goldberg named it in "On the
  12. * Security of the Tor Authentication Protocol". (Spoiler: it's secure, but
  13. * its security is kind of fragile and implementation dependent. Never modify
  14. * this implementation without reading and understanding that paper at least.)
  15. **/
  16. #include "or.h"
  17. #include "config.h"
  18. #include "onion_tap.h"
  19. #include "rephist.h"
  20. /*----------------------------------------------------------------------*/
  21. /** Given a router's 128 byte public key,
  22. * stores the following in onion_skin_out:
  23. * - [42 bytes] OAEP padding
  24. * - [16 bytes] Symmetric key for encrypting blob past RSA
  25. * - [70 bytes] g^x part 1 (inside the RSA)
  26. * - [58 bytes] g^x part 2 (symmetrically encrypted)
  27. *
  28. * Stores the DH private key into handshake_state_out for later completion
  29. * of the handshake.
  30. *
  31. * The meeting point/cookies and auth are zeroed out for now.
  32. */
  33. int
  34. onion_skin_create(crypto_pk_t *dest_router_key,
  35. crypto_dh_t **handshake_state_out,
  36. char *onion_skin_out) /* ONIONSKIN_CHALLENGE_LEN bytes */
  37. {
  38. char challenge[DH_KEY_LEN];
  39. crypto_dh_t *dh = NULL;
  40. int dhbytes, pkbytes;
  41. tor_assert(dest_router_key);
  42. tor_assert(handshake_state_out);
  43. tor_assert(onion_skin_out);
  44. *handshake_state_out = NULL;
  45. memset(onion_skin_out, 0, ONIONSKIN_CHALLENGE_LEN);
  46. if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT)))
  47. goto err;
  48. dhbytes = crypto_dh_get_bytes(dh);
  49. pkbytes = (int) crypto_pk_keysize(dest_router_key);
  50. tor_assert(dhbytes == 128);
  51. tor_assert(pkbytes == 128);
  52. if (crypto_dh_get_public(dh, challenge, dhbytes))
  53. goto err;
  54. note_crypto_pk_op(ENC_ONIONSKIN);
  55. /* set meeting point, meeting cookie, etc here. Leave zero for now. */
  56. if (crypto_pk_public_hybrid_encrypt(dest_router_key, onion_skin_out,
  57. ONIONSKIN_CHALLENGE_LEN,
  58. challenge, DH_KEY_LEN,
  59. PK_PKCS1_OAEP_PADDING, 1)<0)
  60. goto err;
  61. memwipe(challenge, 0, sizeof(challenge));
  62. *handshake_state_out = dh;
  63. return 0;
  64. err:
  65. memwipe(challenge, 0, sizeof(challenge));
  66. if (dh) crypto_dh_free(dh);
  67. return -1;
  68. }
  69. /** Given an encrypted DH public key as generated by onion_skin_create,
  70. * and the private key for this onion router, generate the reply (128-byte
  71. * DH plus the first 20 bytes of shared key material), and store the
  72. * next key_out_len bytes of key material in key_out.
  73. */
  74. int
  75. onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
  76. crypto_pk_t *private_key,
  77. crypto_pk_t *prev_private_key,
  78. char *handshake_reply_out, /*ONIONSKIN_REPLY_LEN*/
  79. char *key_out,
  80. size_t key_out_len)
  81. {
  82. char challenge[ONIONSKIN_CHALLENGE_LEN];
  83. crypto_dh_t *dh = NULL;
  84. ssize_t len;
  85. char *key_material=NULL;
  86. size_t key_material_len=0;
  87. int i;
  88. crypto_pk_t *k;
  89. len = -1;
  90. for (i=0;i<2;++i) {
  91. k = i==0?private_key:prev_private_key;
  92. if (!k)
  93. break;
  94. note_crypto_pk_op(DEC_ONIONSKIN);
  95. len = crypto_pk_private_hybrid_decrypt(k, challenge,
  96. ONIONSKIN_CHALLENGE_LEN,
  97. onion_skin, ONIONSKIN_CHALLENGE_LEN,
  98. PK_PKCS1_OAEP_PADDING,0);
  99. if (len>0)
  100. break;
  101. }
  102. if (len<0) {
  103. log_info(LD_PROTOCOL,
  104. "Couldn't decrypt onionskin: client may be using old onion key");
  105. goto err;
  106. } else if (len != DH_KEY_LEN) {
  107. log_warn(LD_PROTOCOL, "Unexpected onionskin length after decryption: %ld",
  108. (long)len);
  109. goto err;
  110. }
  111. dh = crypto_dh_new(DH_TYPE_CIRCUIT);
  112. if (!dh) {
  113. log_warn(LD_BUG, "Couldn't allocate DH key");
  114. goto err;
  115. }
  116. if (crypto_dh_get_public(dh, handshake_reply_out, DH_KEY_LEN)) {
  117. log_info(LD_GENERAL, "crypto_dh_get_public failed.");
  118. goto err;
  119. }
  120. key_material_len = DIGEST_LEN+key_out_len;
  121. key_material = tor_malloc(key_material_len);
  122. len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, challenge,
  123. DH_KEY_LEN, key_material,
  124. key_material_len);
  125. if (len < 0) {
  126. log_info(LD_GENERAL, "crypto_dh_compute_secret failed.");
  127. goto err;
  128. }
  129. /* send back H(K|0) as proof that we learned K. */
  130. memcpy(handshake_reply_out+DH_KEY_LEN, key_material, DIGEST_LEN);
  131. /* use the rest of the key material for our shared keys, digests, etc */
  132. memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
  133. memwipe(challenge, 0, sizeof(challenge));
  134. memwipe(key_material, 0, key_material_len);
  135. tor_free(key_material);
  136. crypto_dh_free(dh);
  137. return 0;
  138. err:
  139. memwipe(challenge, 0, sizeof(challenge));
  140. if (key_material) {
  141. memwipe(key_material, 0, key_material_len);
  142. tor_free(key_material);
  143. }
  144. if (dh) crypto_dh_free(dh);
  145. return -1;
  146. }
  147. /** Finish the client side of the DH handshake.
  148. * Given the 128 byte DH reply + 20 byte hash as generated by
  149. * onion_skin_server_handshake and the handshake state generated by
  150. * onion_skin_create, verify H(K) with the first 20 bytes of shared
  151. * key material, then generate key_out_len more bytes of shared key
  152. * material and store them in key_out.
  153. *
  154. * After the invocation, call crypto_dh_free on handshake_state.
  155. */
  156. int
  157. onion_skin_client_handshake(crypto_dh_t *handshake_state,
  158. const char *handshake_reply, /* ONIONSKIN_REPLY_LEN bytes */
  159. char *key_out,
  160. size_t key_out_len)
  161. {
  162. ssize_t len;
  163. char *key_material=NULL;
  164. size_t key_material_len;
  165. tor_assert(crypto_dh_get_bytes(handshake_state) == DH_KEY_LEN);
  166. key_material_len = DIGEST_LEN + key_out_len;
  167. key_material = tor_malloc(key_material_len);
  168. len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, handshake_state,
  169. handshake_reply, DH_KEY_LEN, key_material,
  170. key_material_len);
  171. if (len < 0)
  172. goto err;
  173. if (tor_memneq(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) {
  174. /* H(K) does *not* match. Something fishy. */
  175. log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. "
  176. "Bug or attack.");
  177. goto err;
  178. }
  179. /* use the rest of the key material for our shared keys, digests, etc */
  180. memcpy(key_out, key_material+DIGEST_LEN, key_out_len);
  181. memwipe(key_material, 0, key_material_len);
  182. tor_free(key_material);
  183. return 0;
  184. err:
  185. memwipe(key_material, 0, key_material_len);
  186. tor_free(key_material);
  187. return -1;
  188. }