GNUnet 0.22.1
dht_helper.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2024 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
26#include "gnunet_constants.h"
27#include "gnunet_common.h"
28#include "gnunet_signatures.h"
29#include "gnunet_dht_service.h"
30#include "gnunet_time_lib.h"
31#include "gnunet_util_lib.h"
32#include "dht.h"
33#include "dht_helper.h"
34
37 const struct GNUNET_PeerIdentity *my_identity,
38 enum GNUNET_DHT_RouteOption ro_in,
39 enum GNUNET_DHT_RouteOption *ro_out,
41 block_expiration_time,
42 const uint8_t *block_data,
43 size_t block_data_len,
44 const struct GNUNET_DHT_PathElement *
45 put_path_in,
46 unsigned int put_path_len_in,
47 unsigned int *put_path_len_out,
48 const struct GNUNET_PeerIdentity *trunc_peer,
49 struct GNUNET_PeerIdentity *trunc_peer_out,
50 bool *truncated)
51{
52 size_t msize;
53 const struct GNUNET_DHT_PathElement *put_path_out = put_path_in;
54 bool tracking = (0 != (ro_in & GNUNET_DHT_RO_RECORD_ROUTE));
55 *truncated = (0 != (ro_in & GNUNET_DHT_RO_TRUNCATED));
56 *put_path_len_out = put_path_len_in;
57 *ro_out = ro_in;
58 if (NULL != trunc_peer)
59 {
60 *trunc_peer_out = *trunc_peer;
61 }
62
63#if SANITY_CHECKS > 1
64 unsigned int failure_offset;
65
66 failure_offset
67 = GNUNET_DHT_verify_path (block_data,
68 block_data_len,
69 block_expiration_time,
70 trunc_peer,
71 put_path_in,
72 put_path_len_in, bb
73 NULL, 0, /* get_path */
75 if (0 != failure_offset)
76 {
78 truncated = true;
79 *trunc_peer_out = put_path_out[failure_offset - 1].pred;
80 put_path_out = &put_path_out[failure_offset];
81 *put_path_len_out = put_path_len_in - failure_offset;
82 *ro_out |= GNUNET_DHT_RO_TRUNCATED;
83 }
84#endif
85
86 if (block_data_len
88 - sizeof(struct PeerPutMessage))
89 {
90 GNUNET_break (0);
91 *msize_out = 0;
92 return GNUNET_SYSERR;
93 }
94 msize = block_data_len + sizeof(struct PeerPutMessage);
95 if (tracking)
96 {
97 if (msize + sizeof (struct GNUNET_CRYPTO_EddsaSignature)
99 {
101 "Discarding message that is too large due to tracking\n");
102 *msize_out = 0;
103 return GNUNET_NO;
104 }
105 msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature);
106 }
107 else
108 {
109 /* If tracking is disabled, also discard any path we might have
110 gotten from some broken peer */
111 GNUNET_break_op (0 == *put_path_len_out);
112 *put_path_len_out = 0;
113 }
114 if (*truncated)
115 msize += sizeof (struct GNUNET_PeerIdentity);
116 if (msize + *put_path_len_out * sizeof(struct GNUNET_DHT_PathElement)
118 {
119 unsigned int mlen;
120 unsigned int ppl;
121
123 "Truncating path that is too large due\n");
125 if (! *truncated)
126 {
127 /* We need extra space for the truncation, consider that,
128 too! */
129 *truncated = true;
130 mlen -= sizeof (struct GNUNET_PeerIdentity);
131 msize += sizeof (struct GNUNET_PeerIdentity);
132 }
133 /* compute maximum length of path we can keep */
134 ppl = mlen / sizeof (struct GNUNET_DHT_PathElement);
135 GNUNET_assert (*put_path_len_out - ppl > 0);
136 *trunc_peer_out = put_path_out[*put_path_len_out - ppl - 1].pred;
137 put_path_out = &put_path_out[*put_path_len_out - ppl];
138 *put_path_len_out = ppl;
139 *ro_out |= GNUNET_DHT_RO_TRUNCATED;
140 }
141 else
142 {
143 msize += put_path_len_in * sizeof(struct GNUNET_DHT_PathElement);
144 }
145 *msize_out = msize;
146 return GNUNET_OK;
147}
148
149
150void
152 size_t data_size,
153 const struct GNUNET_CRYPTO_EddsaPrivateKey *sk,
154 struct GNUNET_TIME_Absolute exp_time,
155 const struct GNUNET_PeerIdentity *pred,
156 const struct GNUNET_PeerIdentity *succ,
158{
159 struct GNUNET_DHT_HopSignature hs = {
161 .purpose.size = htonl (sizeof (hs)),
162 .expiration_time = GNUNET_TIME_absolute_hton (exp_time),
163 .succ = *succ
164 };
165
166 if (NULL != pred)
167 hs.pred = *pred;
169 data_size,
170 &hs.h_data);
172 &hs,
173 sig);
174}
175
176
177void
179 size_t msize,
180 const struct GNUNET_CRYPTO_EddsaPrivateKey *sk,
181 const struct GNUNET_PeerIdentity *target,
182 const struct GNUNET_HashCode *target_hash,
183 const struct GNUNET_CONTAINER_BloomFilter *bf,
184 const struct GNUNET_HashCode *block_key,
187 struct GNUNET_TIME_Absolute block_expiration_time,
188 const uint8_t *block_data,
189 size_t block_data_len,
190 const struct GNUNET_DHT_PathElement *put_path,
191 unsigned int put_path_len,
192 size_t hop_count,
193 uint32_t desired_replication_level,
194 const struct GNUNET_PeerIdentity *trunc_peer)
195{
196 struct GNUNET_DHT_PathElement *pp;
197 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
198 bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
199 void *data;
200
202 ppm->header.size = htons (msize);
203 ppm->type = htonl (block_type);
204 ppm->options = htons (ro);
205 ppm->hop_count = htons (hop_count + 1);
206 ppm->desired_replication_level = htons (desired_replication_level);
207 ppm->put_path_length = htons (put_path_len);
208 ppm->expiration_time = GNUNET_TIME_absolute_hton (block_expiration_time);
211 target_hash));
214 ppm->bloomfilter,
216 ppm->key = *block_key;
217 if (truncated)
218 {
219 void *tgt = &ppm[1];
220
221 GNUNET_memcpy (tgt,
222 trunc_peer,
223 sizeof (struct GNUNET_PeerIdentity));
224 pp = (struct GNUNET_DHT_PathElement *)
225 (tgt + sizeof (struct GNUNET_PeerIdentity));
226 }
227 else
228 {
229 pp = (struct GNUNET_DHT_PathElement *) &ppm[1];
230 }
231 GNUNET_memcpy (pp,
232 put_path,
233 sizeof (struct GNUNET_DHT_PathElement) * put_path_len);
234 if (tracking)
235 {
236 void *tgt = &pp[put_path_len];
237 struct GNUNET_CRYPTO_EddsaSignature last_sig;
238
239 if (0 == put_path_len)
240 {
241 /* Note that the signature in 'put_path' was not initialized before,
242 so this is crucial to avoid sending garbage. */
243 GDS_helper_sign_path (block_data,
244 block_data_len,
245 sk,
246 block_expiration_time,
247 trunc_peer,
248 target,
249 &last_sig);
250 }
251 else
252 {
253 GDS_helper_sign_path (block_data,
254 block_data_len,
255 sk,
256 block_expiration_time,
257 &pp[put_path_len - 1].pred,
258 target,
259 &last_sig);
260 }
262 "Signing PUT PATH %u => %s\n",
263 put_path_len,
264 GNUNET_B2S (&last_sig));
265 memcpy (tgt,
266 &last_sig,
267 sizeof (last_sig));
268 data = tgt + sizeof (last_sig);
269 }
270 else /* ! tracking */
271 {
272 data = &ppm[1];
273 }
275 block_data,
276 block_data_len);
277}
#define DHT_BLOOM_SIZE
Size of the bloom filter the DHT uses to filter peers.
Definition: dht.h:34
void GDS_helper_make_put_message(struct PeerPutMessage *ppm, size_t msize, const struct GNUNET_CRYPTO_EddsaPrivateKey *sk, const struct GNUNET_PeerIdentity *target, const struct GNUNET_HashCode *target_hash, const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *block_key, enum GNUNET_DHT_RouteOption ro, enum GNUNET_BLOCK_Type block_type, struct GNUNET_TIME_Absolute block_expiration_time, const uint8_t *block_data, size_t block_data_len, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_len, size_t hop_count, uint32_t desired_replication_level, const struct GNUNET_PeerIdentity *trunc_peer)
Definition: dht_helper.c:178
enum GNUNET_GenericReturnValue GDS_helper_put_message_get_size(size_t *msize_out, const struct GNUNET_PeerIdentity *my_identity, enum GNUNET_DHT_RouteOption ro_in, enum GNUNET_DHT_RouteOption *ro_out, struct GNUNET_TIME_Absolute block_expiration_time, const uint8_t *block_data, size_t block_data_len, const struct GNUNET_DHT_PathElement *put_path_in, unsigned int put_path_len_in, unsigned int *put_path_len_out, const struct GNUNET_PeerIdentity *trunc_peer, struct GNUNET_PeerIdentity *trunc_peer_out, bool *truncated)
Definition: dht_helper.c:36
void GDS_helper_sign_path(const void *data, size_t data_size, const struct GNUNET_CRYPTO_EddsaPrivateKey *sk, struct GNUNET_TIME_Absolute exp_time, const struct GNUNET_PeerIdentity *pred, const struct GNUNET_PeerIdentity *succ, struct GNUNET_CRYPTO_EddsaSignature *sig)
Sign that we are routing a message from pred to succ.
Definition: dht_helper.c:151
Helper functions for DHT.
struct GNUNET_PeerIdentity my_identity
Our peer identity.
static unsigned int block_type
The type of the query.
static char * data
The data to insert into the dht.
static size_t data_size
Number of bytes in data.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
API to the DHT service.
Functions related to time.
bool GNUNET_CONTAINER_bloomfilter_test(const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e)
Test if an element is in the filter.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_bloomfilter_get_raw_data(const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size)
Copy the raw data of this Bloom filter into the given data array.
#define GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE
What is the maximum size for encrypted messages? Note that this number imposes a clear limit on the m...
#define GNUNET_CRYPTO_eddsa_sign(priv, ps, sig)
EdDSA sign a given block.
GNUNET_DHT_RouteOption
Options for routing.
unsigned int GNUNET_DHT_verify_path(const void *data, size_t data_size, struct GNUNET_TIME_Absolute exp_time, const struct GNUNET_PeerIdentity *trunc_peer, const struct GNUNET_DHT_PathElement *put_path, unsigned int put_path_len, const struct GNUNET_DHT_PathElement *get_path, unsigned int get_path_len, const struct GNUNET_PeerIdentity *me)
Verify signatures on a path consisting of put_path and get_path in reverse order (starting at the las...
Definition: dht_api.c:1344
@ GNUNET_DHT_RO_TRUNCATED
Flag set if the path was truncated.
@ GNUNET_DHT_RO_RECORD_ROUTE
We should keep track of the route that the message took in the P2P network.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_B2S(obj)
Convert a fixed-sized object to a string using GNUNET_b2s().
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_MESSAGE_TYPE_DHT_P2P_PUT
Peer is storing data in DHT.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:640
GNUNET_BLOCK_Type
WARNING: This header is generated! In order to add DHT block types, you must register them in GANA,...
#define GNUNET_SIGNATURE_PURPOSE_DHT_HOP
Signature by which a peer affirms that it forwarded a message in the DHT.
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Private ECC key encoded for transmission.
an ECC signature using EdDSA.
Message signed by a peer when doing path tracking.
struct GNUNET_HashCode h_data
Hash over the payload of the block.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Must be GNUNET_SIGNATURE_PURPOSE_DHT_HOP.
struct GNUNET_PeerIdentity pred
Previous hop the message was received from.
struct GNUNET_PeerIdentity succ
Next hop the message was forwarded to.
A (signed) path tracking a block's flow through the DHT is represented by an array of path elements,...
struct GNUNET_PeerIdentity pred
Previous peer on the path (matches "pred" in the signed field).
struct GNUNET_CRYPTO_EddsaSignature sig
Signature affirming the hop of type GNUNET_SIGNATURE_PURPOSE_DHT_HOP.
A 512-bit hashcode.
The identity of the host (wraps the signing key of the peer).
Time for absolute times used by GNUnet, in microseconds.
P2P PUT message.
Definition: dht.h:429
uint16_t desired_replication_level
Replication level for this message.
Definition: dht.h:453
uint16_t hop_count
Hop count.
Definition: dht.h:448
uint32_t type
Content type, must not be zero.
Definition: dht.h:438
char bloomfilter[128]
Bloomfilter (for peer identities) to stop circular routes.
Definition: dht.h:468
struct GNUNET_MessageHeader header
Type: GNUNET_MESSAGE_TYPE_DHT_P2P_PUT.
Definition: dht.h:433
struct GNUNET_HashCode key
The key we are storing under.
Definition: dht.h:473
uint16_t options
Processing options.
Definition: dht.h:443
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the content expire?
Definition: dht.h:463
uint16_t put_path_length
Length of the PUT path that follows (if tracked).
Definition: dht.h:458