hello-ng.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2018 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file hello/hello-ng.c
  18. * @brief helper library for handling HELLOs
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_signatures.h"
  23. #include "gnunet_hello_lib.h"
  24. #include "gnunet_protocols.h"
  25. #include "gnunet_util_lib.h"
  26. #include "gnunet_ats_service.h"
  27. /**
  28. * Binary block we sign when we sign an address.
  29. */
  30. struct SignedAddress
  31. {
  32. /**
  33. * Purpose must be #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS
  34. */
  35. struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
  36. /**
  37. * When was the address generated.
  38. */
  39. struct GNUNET_TIME_AbsoluteNBO mono_time;
  40. /**
  41. * Hash of the address.
  42. */
  43. struct GNUNET_HashCode h_addr;
  44. };
  45. /**
  46. * Build address record by signing raw information with private key.
  47. *
  48. * @param address text address at @a communicator to sign
  49. * @param nt network type of @a address
  50. * @param mono_time monotonic time at which @a address was valid
  51. * @param private_key signing key to use
  52. * @param result[out] where to write address record (allocated)
  53. * @param result_size[out] set to size of @a result
  54. */
  55. void
  56. GNUNET_HELLO_sign_address (
  57. const char *address,
  58. enum GNUNET_NetworkType nt,
  59. struct GNUNET_TIME_Absolute mono_time,
  60. const struct GNUNET_CRYPTO_EddsaPrivateKey *private_key,
  61. void **result,
  62. size_t *result_size)
  63. {
  64. struct SignedAddress sa;
  65. struct GNUNET_CRYPTO_EddsaSignature sig;
  66. char *sig_str;
  67. sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
  68. sa.purpose.size = htonl (sizeof(sa));
  69. sa.mono_time = GNUNET_TIME_absolute_hton (mono_time);
  70. GNUNET_CRYPTO_hash (address, strlen (address), &sa.h_addr);
  71. GNUNET_CRYPTO_eddsa_sign (private_key, &sa, &sig);
  72. sig_str = NULL;
  73. (void) GNUNET_STRINGS_base64_encode (&sig, sizeof(sig), &sig_str);
  74. *result_size =
  75. 1 + GNUNET_asprintf ((char **) result,
  76. "%s;%llu;%u;%s",
  77. sig_str,
  78. (unsigned long long) mono_time.abs_value_us,
  79. (unsigned int) nt,
  80. address);
  81. GNUNET_free (sig_str);
  82. }
  83. /**
  84. * Check signature and extract address record.
  85. *
  86. * @param raw raw signed address
  87. * @param raw_size size of @a raw
  88. * @param pid public key to use for signature verification
  89. * @param nt[out] set to network type
  90. * @param mono_time[out] when was the address generated
  91. * @return NULL on error, otherwise the address
  92. */
  93. char *
  94. GNUNET_HELLO_extract_address (const void *raw,
  95. size_t raw_size,
  96. const struct GNUNET_PeerIdentity *pid,
  97. enum GNUNET_NetworkType *nt,
  98. struct GNUNET_TIME_Absolute *mono_time)
  99. {
  100. const struct GNUNET_CRYPTO_EddsaPublicKey *public_key = &pid->public_key;
  101. const char *raws = raw;
  102. unsigned long long raw_us;
  103. unsigned int raw_nt;
  104. const char *sc;
  105. const char *sc2;
  106. const char *sc3;
  107. const char *raw_addr;
  108. struct GNUNET_TIME_Absolute raw_mono_time;
  109. struct SignedAddress sa;
  110. struct GNUNET_CRYPTO_EddsaSignature *sig;
  111. if ('\0' != raws[raw_size])
  112. {
  113. GNUNET_break_op (0);
  114. return NULL;
  115. }
  116. if (NULL == (sc = strchr (raws, ';')))
  117. {
  118. GNUNET_break_op (0);
  119. return NULL;
  120. }
  121. if (NULL == (sc2 = strchr (sc + 1, ';')))
  122. {
  123. GNUNET_break_op (0);
  124. return NULL;
  125. }
  126. if (NULL == (sc3 = strchr (sc2 + 1, ';')))
  127. {
  128. GNUNET_break_op (0);
  129. return NULL;
  130. }
  131. if (1 != sscanf (sc + 1, "%llu;%u;", &raw_us, &raw_nt))
  132. {
  133. GNUNET_break_op (0);
  134. return NULL;
  135. }
  136. raw_mono_time.abs_value_us = raw_us;
  137. sig = NULL;
  138. if (sizeof(struct GNUNET_CRYPTO_EddsaSignature) !=
  139. GNUNET_STRINGS_base64_decode (raws, sc - raws, (void **) &sig))
  140. {
  141. GNUNET_break_op (0);
  142. GNUNET_free (sig);
  143. return NULL;
  144. }
  145. raw_addr = sc3 + 1;
  146. sa.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS);
  147. sa.purpose.size = htonl (sizeof(sa));
  148. sa.mono_time = GNUNET_TIME_absolute_hton (raw_mono_time);
  149. GNUNET_CRYPTO_hash (raw_addr, strlen (raw_addr), &sa.h_addr);
  150. if (GNUNET_YES !=
  151. GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_ADDRESS,
  152. &sa,
  153. sig,
  154. public_key))
  155. {
  156. GNUNET_break_op (0);
  157. GNUNET_free (sig);
  158. return NULL;
  159. }
  160. GNUNET_free (sig);
  161. *mono_time = raw_mono_time;
  162. *nt = (enum GNUNET_NetworkType) raw_nt;
  163. return GNUNET_strdup (raw_addr);
  164. }
  165. /**
  166. * Given an address as a string, extract the prefix that identifies
  167. * the communicator offering transmissions to that address.
  168. *
  169. * @param address a peer's address
  170. * @return NULL if the address is mal-formed, otherwise the prefix
  171. */
  172. char *
  173. GNUNET_HELLO_address_to_prefix (const char *address)
  174. {
  175. const char *dash;
  176. dash = strchr (address, '-');
  177. if (NULL == dash)
  178. return NULL;
  179. return GNUNET_strndup (address, dash - address);
  180. }