hs_common.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /* Copyright (c) 2016, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file hs_common.c
  5. * \brief Contains code shared between different HS protocol version as well
  6. * as useful data structures and accessors used by other subsystems.
  7. * The rendcommon.c should only contains code relating to the v2
  8. * protocol.
  9. **/
  10. #include "or.h"
  11. #include "hs_common.h"
  12. #include "rendcommon.h"
  13. /* Create a new rend_data_t for a specific given <b>version</b>.
  14. * Return a pointer to the newly allocated data structure. */
  15. static rend_data_t *
  16. rend_data_alloc(uint32_t version)
  17. {
  18. rend_data_t *rend_data = NULL;
  19. switch (version) {
  20. case HS_VERSION_TWO:
  21. {
  22. rend_data_v2_t *v2 = tor_malloc_zero(sizeof(*v2));
  23. v2->base_.version = HS_VERSION_TWO;
  24. v2->base_.hsdirs_fp = smartlist_new();
  25. rend_data = &v2->base_;
  26. break;
  27. }
  28. default:
  29. tor_assert(0);
  30. break;
  31. }
  32. return rend_data;
  33. }
  34. /** Free all storage associated with <b>data</b> */
  35. void
  36. rend_data_free(rend_data_t *data)
  37. {
  38. if (!data) {
  39. return;
  40. }
  41. /* By using our allocation function, this should always be set. */
  42. tor_assert(data->hsdirs_fp);
  43. /* Cleanup the HSDir identity digest. */
  44. SMARTLIST_FOREACH(data->hsdirs_fp, char *, d, tor_free(d));
  45. smartlist_free(data->hsdirs_fp);
  46. /* Depending on the version, cleanup. */
  47. switch (data->version) {
  48. case HS_VERSION_TWO:
  49. {
  50. rend_data_v2_t *v2_data = TO_REND_DATA_V2(data);
  51. tor_free(v2_data);
  52. break;
  53. }
  54. default:
  55. tor_assert(0);
  56. }
  57. }
  58. /* Allocate and return a deep copy of <b>data</b>. */
  59. rend_data_t *
  60. rend_data_dup(const rend_data_t *data)
  61. {
  62. rend_data_t *data_dup = NULL;
  63. smartlist_t *hsdirs_fp = smartlist_new();
  64. tor_assert(data);
  65. tor_assert(data->hsdirs_fp);
  66. SMARTLIST_FOREACH(data->hsdirs_fp, char *, fp,
  67. smartlist_add(hsdirs_fp, tor_memdup(fp, DIGEST_LEN)));
  68. switch (data->version) {
  69. case HS_VERSION_TWO:
  70. {
  71. rend_data_v2_t *v2_data = tor_memdup(TO_REND_DATA_V2(data),
  72. sizeof(*v2_data));
  73. data_dup = &v2_data->base_;
  74. data_dup->hsdirs_fp = hsdirs_fp;
  75. break;
  76. }
  77. default:
  78. tor_assert(0);
  79. break;
  80. }
  81. return data_dup;
  82. }
  83. /* Compute the descriptor ID for each HS descriptor replica and save them. A
  84. * valid onion address must be present in the <b>rend_data</b>.
  85. *
  86. * Return 0 on success else -1. */
  87. static int
  88. compute_desc_id(rend_data_t *rend_data)
  89. {
  90. int ret = 0;
  91. unsigned replica;
  92. time_t now = time(NULL);
  93. tor_assert(rend_data);
  94. switch (rend_data->version) {
  95. case HS_VERSION_TWO:
  96. {
  97. rend_data_v2_t *v2_data = TO_REND_DATA_V2(rend_data);
  98. /* Compute descriptor ID for each replicas. */
  99. for (replica = 0; replica < ARRAY_LENGTH(v2_data->descriptor_id);
  100. replica++) {
  101. ret = rend_compute_v2_desc_id(v2_data->descriptor_id[replica],
  102. v2_data->onion_address,
  103. v2_data->descriptor_cookie,
  104. now, replica);
  105. if (ret < 0) {
  106. goto end;
  107. }
  108. }
  109. break;
  110. }
  111. default:
  112. tor_assert(0);
  113. }
  114. end:
  115. return ret;
  116. }
  117. /* Allocate and initialize a rend_data_t object for a service using the
  118. * provided arguments. All arguments are optional (can be NULL), except from
  119. * <b>onion_address</b> which MUST be set.
  120. *
  121. * Return a valid rend_data_t pointer. This only returns a version 2 object of
  122. * rend_data_t. */
  123. rend_data_t *
  124. rend_data_service_create(const char *onion_address, const char *pk_digest,
  125. const uint8_t *cookie, rend_auth_type_t auth_type)
  126. {
  127. /* Create a rend_data_t object for version 2. */
  128. rend_data_t *rend_data = rend_data_alloc(HS_VERSION_TWO);
  129. rend_data_v2_t *v2= TO_REND_DATA_V2(rend_data);
  130. /* We need at least one else the call is wrong. */
  131. tor_assert(onion_address != NULL);
  132. if (pk_digest) {
  133. memcpy(v2->rend_pk_digest, pk_digest, sizeof(v2->rend_pk_digest));
  134. }
  135. if (cookie) {
  136. memcpy(rend_data->rend_cookie, cookie, sizeof(rend_data->rend_cookie));
  137. }
  138. strlcpy(v2->onion_address, onion_address, sizeof(v2->onion_address));
  139. v2->auth_type = auth_type;
  140. return rend_data;
  141. }
  142. /* Allocate and initialize a rend_data_t object for a client request using
  143. * the given arguments. Either an onion address or a descriptor ID is
  144. * needed. Both can be given but only the onion address will be used to make
  145. * the descriptor fetch.
  146. *
  147. * Return a valid rend_data_t pointer or NULL on error meaning the
  148. * descriptor IDs couldn't be computed from the given data. */
  149. rend_data_t *
  150. rend_data_client_create(const char *onion_address, const char *desc_id,
  151. const char *cookie, rend_auth_type_t auth_type)
  152. {
  153. /* Create a rend_data_t object for version 2. */
  154. rend_data_t *rend_data = rend_data_alloc(HS_VERSION_TWO);
  155. rend_data_v2_t *v2= TO_REND_DATA_V2(rend_data);
  156. /* We need at least one else the call is wrong. */
  157. tor_assert(onion_address != NULL || desc_id != NULL);
  158. if (cookie) {
  159. memcpy(v2->descriptor_cookie, cookie, sizeof(v2->descriptor_cookie));
  160. }
  161. if (desc_id) {
  162. memcpy(v2->desc_id_fetch, desc_id, sizeof(v2->desc_id_fetch));
  163. }
  164. if (onion_address) {
  165. strlcpy(v2->onion_address, onion_address, sizeof(v2->onion_address));
  166. if (compute_desc_id(rend_data) < 0) {
  167. goto error;
  168. }
  169. }
  170. v2->auth_type = auth_type;
  171. return rend_data;
  172. error:
  173. rend_data_free(rend_data);
  174. return NULL;
  175. }
  176. /* Return the onion address from the rend data. Depending on the version,
  177. * the size of the address can vary but it's always NUL terminated. */
  178. const char *
  179. rend_data_get_address(const rend_data_t *rend_data)
  180. {
  181. tor_assert(rend_data);
  182. switch (rend_data->version) {
  183. case HS_VERSION_TWO:
  184. return TO_REND_DATA_V2(rend_data)->onion_address;
  185. default:
  186. /* We should always have a supported version. */
  187. tor_assert(0);
  188. }
  189. }
  190. /* Return the descriptor ID for a specific replica number from the rend
  191. * data. The returned data is a binary digest and depending on the version its
  192. * size can vary. The size of the descriptor ID is put in <b>len_out</b> if
  193. * non NULL. */
  194. const char *
  195. rend_data_get_desc_id(const rend_data_t *rend_data, uint8_t replica,
  196. size_t *len_out)
  197. {
  198. tor_assert(rend_data);
  199. switch (rend_data->version) {
  200. case HS_VERSION_TWO:
  201. tor_assert(replica < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS);
  202. if (len_out) {
  203. *len_out = DIGEST_LEN;
  204. }
  205. return TO_REND_DATA_V2(rend_data)->descriptor_id[replica];
  206. default:
  207. /* We should always have a supported version. */
  208. tor_assert(0);
  209. }
  210. }
  211. /* Return the public key digest using the given <b>rend_data</b>. The size of
  212. * the digest is put in <b>len_out</b> (if set) which can differ depending on
  213. * the version. */
  214. const uint8_t *
  215. rend_data_get_pk_digest(const rend_data_t *rend_data, size_t *len_out)
  216. {
  217. tor_assert(rend_data);
  218. switch (rend_data->version) {
  219. case HS_VERSION_TWO:
  220. {
  221. const rend_data_v2_t *v2_data = TO_REND_DATA_V2(rend_data);
  222. if (len_out) {
  223. *len_out = sizeof(v2_data->rend_pk_digest);
  224. }
  225. return (const uint8_t *) v2_data->rend_pk_digest;
  226. }
  227. default:
  228. /* We should always have a supported version. */
  229. tor_assert(0);
  230. }
  231. }