GNUnet 0.22.0
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{
50 size_t msize;
51 *put_path_len_out = put_path_len_in;
52 const struct GNUNET_DHT_PathElement *put_path_out = put_path_in;
53 *ro_out = ro_in;
54 bool truncated = (0 != (*ro_out & GNUNET_DHT_RO_TRUNCATED));
55 bool tracking = (0 != (*ro_out & GNUNET_DHT_RO_RECORD_ROUTE));
56
57#if SANITY_CHECKS > 1
58 unsigned int failure_offset;
59
60 failure_offset
61 = GNUNET_DHT_verify_path (block_data,
62 block_data_len,
63 block_expiration_time,
64 trunc_peer,
65 put_path_in,
66 put_path_len_in,
67 NULL, 0, /* get_path */
69 if (0 != failure_offset)
70 {
72 truncated = true;
73 trunc_peer = &put_path_out[failure_offset - 1].pred;
74 put_path_out = &put_path_out[failure_offset];
75 *put_path_len_out = put_path_len_in - failure_offset;
76 *ro_out |= GNUNET_DHT_RO_TRUNCATED;
77 }
78#endif
79
80 if (block_data_len
82 - sizeof(struct PeerPutMessage))
83 {
84 GNUNET_break (0);
85 *msize_out = 0;
86 return GNUNET_SYSERR;
87 }
88 msize = block_data_len + sizeof(struct PeerPutMessage);
89 if (tracking)
90 {
91 if (msize + sizeof (struct GNUNET_CRYPTO_EddsaSignature)
93 {
95 "Discarding message that is too large due to tracking\n");
96 *msize_out = 0;
97 return GNUNET_NO;
98 }
99 msize += sizeof (struct GNUNET_CRYPTO_EddsaSignature);
100 }
101 else
102 {
103 /* If tracking is disabled, also discard any path we might have
104 gotten from some broken peer */
105 GNUNET_break_op (0 == *put_path_len_out);
106 *put_path_len_out = 0;
107 }
108 if (truncated)
109 msize += sizeof (struct GNUNET_PeerIdentity);
110 if (msize + *put_path_len_out * sizeof(struct GNUNET_DHT_PathElement)
112 {
113 unsigned int mlen;
114 unsigned int ppl;
115
117 "Truncating path that is too large due\n");
119 if (! truncated)
120 {
121 /* We need extra space for the truncation, consider that,
122 too! */
123 truncated = true;
124 mlen -= sizeof (struct GNUNET_PeerIdentity);
125 msize += sizeof (struct GNUNET_PeerIdentity);
126 }
127 /* compute maximum length of path we can keep */
128 ppl = mlen / sizeof (struct GNUNET_DHT_PathElement);
129 GNUNET_assert (*put_path_len_out - ppl > 0);
130 trunc_peer = &put_path_out[*put_path_len_out - ppl - 1].pred;
131 put_path_out = &put_path_out[*put_path_len_out - ppl];
132 *put_path_len_out = ppl;
133 *ro_out |= GNUNET_DHT_RO_TRUNCATED;
134 }
135 else
136 {
137 msize += put_path_len_in * sizeof(struct GNUNET_DHT_PathElement);
138 }
139 *msize_out = msize;
140 return GNUNET_OK;
141}
142
143
144void
146 size_t data_size,
147 const struct GNUNET_CRYPTO_EddsaPrivateKey *sk,
148 struct GNUNET_TIME_Absolute exp_time,
149 const struct GNUNET_PeerIdentity *pred,
150 const struct GNUNET_PeerIdentity *succ,
152{
153 struct GNUNET_DHT_HopSignature hs = {
155 .purpose.size = htonl (sizeof (hs)),
156 .expiration_time = GNUNET_TIME_absolute_hton (exp_time),
157 .succ = *succ
158 };
159
160 if (NULL != pred)
161 hs.pred = *pred;
163 data_size,
164 &hs.h_data);
166 &hs,
167 sig);
168}
169
170
171void
173 size_t msize,
174 const struct GNUNET_CRYPTO_EddsaPrivateKey *sk,
175 const struct GNUNET_PeerIdentity *target,
176 const struct GNUNET_HashCode *target_hash,
177 const struct GNUNET_CONTAINER_BloomFilter *bf,
178 const struct GNUNET_HashCode *block_key,
181 struct GNUNET_TIME_Absolute block_expiration_time,
182 const uint8_t *block_data,
183 size_t block_data_len,
184 const struct GNUNET_DHT_PathElement *put_path,
185 unsigned int put_path_len,
186 size_t hop_count,
187 uint32_t desired_replication_level,
188 const struct GNUNET_PeerIdentity *trunc_peer)
189{
190 struct GNUNET_DHT_PathElement *pp;
191 bool truncated = (0 != (ro & GNUNET_DHT_RO_TRUNCATED));
192 bool tracking = (0 != (ro & GNUNET_DHT_RO_RECORD_ROUTE));
193 void *data;
194
196 ppm->header.size = htons (msize);
197 ppm->type = htonl (block_type);
198 ppm->options = htons (ro);
199 ppm->hop_count = htons (hop_count + 1);
200 ppm->desired_replication_level = htons (desired_replication_level);
201 ppm->put_path_length = htons (put_path_len);
202 ppm->expiration_time = GNUNET_TIME_absolute_hton (block_expiration_time);
205 target_hash));
208 ppm->bloomfilter,
210 ppm->key = *block_key;
211 if (truncated)
212 {
213 void *tgt = &ppm[1];
214
215 GNUNET_memcpy (tgt,
216 trunc_peer,
217 sizeof (struct GNUNET_PeerIdentity));
218 pp = (struct GNUNET_DHT_PathElement *)
219 (tgt + sizeof (struct GNUNET_PeerIdentity));
220 }
221 else
222 {
223 pp = (struct GNUNET_DHT_PathElement *) &ppm[1];
224 }
225 GNUNET_memcpy (pp,
226 put_path,
227 sizeof (struct GNUNET_DHT_PathElement) * put_path_len);
228 if (tracking)
229 {
230 void *tgt = &pp[put_path_len];
231 struct GNUNET_CRYPTO_EddsaSignature last_sig;
232
233 if (0 == put_path_len)
234 {
235 /* Note that the signature in 'put_path' was not initialized before,
236 so this is crucial to avoid sending garbage. */
237 GDS_helper_sign_path (block_data,
238 block_data_len,
239 sk,
240 block_expiration_time,
241 trunc_peer,
242 target,
243 &last_sig);
244 }
245 else
246 {
247 GDS_helper_sign_path (block_data,
248 block_data_len,
249 sk,
250 block_expiration_time,
251 &pp[put_path_len - 1].pred,
252 target,
253 &last_sig);
254 }
256 "Signing PUT PATH %u => %s\n",
257 put_path_len,
258 GNUNET_B2S (&last_sig));
259 memcpy (tgt,
260 &last_sig,
261 sizeof (last_sig));
262 data = tgt + sizeof (last_sig);
263 }
264 else /* ! tracking */
265 {
266 data = &ppm[1];
267 }
269 block_data,
270 block_data_len);
271}
#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:172
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:145
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)
Definition: dht_helper.c:36
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:1351
@ 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