GNUnet 0.25.0
 
Loading...
Searching...
No Matches
gnunet-service-pils.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
31#include "platform.h"
32#include "gnunet_util_lib.h"
33#include "gnunet_constants.h"
34#include "gnunet_protocols.h"
35#include "gnunet_signatures.h"
36#include "gnunet_pils_service.h"
37#include "pils.h"
38
39
40/* Shorthand for Logging */
41#define LOG(kind, ...) GNUNET_log_from (kind, "pils", __VA_ARGS__)
42
46static const struct GNUNET_CONFIGURATION_Handle *cfg;
47
48
53
54
62
63
68
69
74
78static unsigned char ikm[256 / 8];
79
84{
88 struct P_Client *next;
89
93 struct P_Client *prev;
94
99
104};
105
106
110static struct P_Client *clients_head;
111
112
116static struct P_Client *clients_tail;
117
122static int have_id;
123
128
139static void
141{
142 char *keyfile;
144
145 if (GNUNET_OK !=
147 "PEER",
148 "PRIVATE_KEY",
149 &keyfile))
150 {
152 "PEER",
153 "PRIVATE_KEY");
155 return;
156 }
157 if (GNUNET_SYSERR ==
160 &key))
161 {
163 "Failed to setup peer's private key\n");
164 GNUNET_free (keyfile);
166 return;
167 }
168 GNUNET_free (keyfile);
169 GNUNET_assert (sizeof ikm == sizeof key.d);
170 memcpy (ikm, key.d, sizeof ikm);
171}
172
173
174static void
175print_uri (void *cls,
176 const struct GNUNET_PeerIdentity *pid,
177 const char *uri)
178{
180 "%s\n", uri);
181}
182
183
191static void
193{
195 struct GNUNET_HashCode new_addresses_hash;
196 LOG (GNUNET_ERROR_TYPE_INFO, "Going to generate a new peer id\n");
197 generate_pid_task = NULL;
198
199 if (NULL == parser)
200 {
202 }
203 else
204 {
206 }
208 "Got new address list to derive PID:\n");
211 &new_addresses_hash);
212#if HELLO_DETERMINISTIC_PID_DERIVATION
213 if (0 == GNUNET_CRYPTO_hash_cmp (&new_addresses_hash,
215 {
217 "Address hash unchanged at %s, ignoring...\n",
220 return;
221 }
222#endif
223 addresses_hash = new_addresses_hash;
225 (uint8_t*) ikm,
231 "Successfully generated a new peer id %s - inform clients\n",
233
234 {
235 struct P_Client *client;
236 struct PeerIdUpdateMessage *msg;
238 struct GNUNET_TIME_Absolute et;
239 size_t block_bytes;
241
242 struct PilsHelloSignaturePurpose hsp = {
243 .purpose.size = htonl (sizeof (hsp)),
244 .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_HELLO),
245 .expiration_time = GNUNET_TIME_absolute_hton (et)
246 };
250 &hsp.purpose,
251 &sig));
253
255 block_bytes,
257 msg->hash = addresses_hash;
258 msg->block_len = htonl (block_bytes);
260 builder,
262 &sig,
263 et,
264 (char *) &msg[1]);
265 client = clients_head;
266 while (NULL != client)
267 {
269 client = client->next;
270 }
271 }
272}
273
274
282static int
284 const struct FeedAddressesMessage *msg)
285{
286 size_t msg_size;
287 uint32_t block_bytes;
288 (void) cls;
289
290 msg_size = ntohs (msg->header.size);
291 block_bytes = ntohl (msg->block_len);
292 if (msg_size != sizeof (*msg) + block_bytes)
293 {
295 "The msg_size (%lu) is not %lu (header) + %u (block)\n",
296 msg_size,
297 sizeof (*msg),
298 block_bytes);
299 return GNUNET_SYSERR;
300 }
301 return GNUNET_OK;
302}
303
304
314static void
316 const struct FeedAddressesMessage *message)
317{
318 struct P_Client *client = cls;
319 struct GNUNET_HELLO_Parser *parser;
320 uint32_t block_bytes;
321
323 "PILS received FEED_ADDRESSES message from client\n");
324
325 /* If there's a peer id generation scheduled, just kill it and generate an id
326 * on the more recent address */
327 block_bytes = ntohl (message->block_len);
328 parser = GNUNET_HELLO_parser_from_block_ (&message[1],
329 block_bytes,
330 GNUNET_YES);
331 do_generate_pid (parser);
332
335}
336
337
344static void
345handle_decaps (void *cls,
346 const struct DecapsMessage *message)
347{
348 struct P_Client *client = cls;
349 struct DecapsResultMessage *rmsg;
350 struct GNUNET_MQ_Envelope *env;
352
354 "PILS received KEM_DECAPS message from client\n");
355
357 &message->c,
358 &rmsg->key))
359 {
361 "PILS failed to decapsulate encapsulation received from client\n");
362 memset (&rmsg->key, 0, sizeof (rmsg->key));
363 }
364
365 rmsg->rid = message->rid;
366 GNUNET_MQ_send (client->mq, env);
368}
369
370
378static int
379check_sign (void *cls, const struct SignRequestMessage *msg)
380{
382 size_t msg_size;
383 (void) cls;
384
385 msg_size = ntohs (msg->header.size);
386 if (msg_size <= sizeof (*msg) + sizeof (struct
388 {
390 "The msg_size (%lu) is not big enough for msg (%lu) + purpose struct (%lu)\n",
391 msg_size,
392 sizeof (*msg),
393 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
394 return GNUNET_SYSERR;
395 }
396 purp = (struct GNUNET_CRYPTO_EccSignaturePurpose*) &msg[1];
397 if (msg_size <= sizeof (*msg) + ntohs (purp->size))
398 {
400 "The msg_size (%lu) is not big enough for msg (%lu) + purpose (%u)\n",
401 msg_size,
402 sizeof (*msg),
403 ntohs (purp->size));
404 return GNUNET_SYSERR;
405 }
406 return GNUNET_OK;
407}
408
409
416static void
417handle_sign (void *cls,
418 const struct SignRequestMessage *message)
419{
420 struct P_Client *client = cls;
421 struct SignResultMessage *rmsg;
422 struct GNUNET_MQ_Envelope *env;
425
427 "PILS received SIGN message from client\n");
428
429 purp = (struct GNUNET_CRYPTO_EccSignaturePurpose*) &message[1];
431 purp,
432 &rmsg->sig))
433 {
435 "PILS failed to sign message received from client\n");
436 memset (&rmsg->sig, 0, sizeof (rmsg->sig));
437 }
439 "PILS sent SIGN_RESULT message to client %p\n",
440 client->mq);
442 rmsg->rid = message->rid;
443 GNUNET_MQ_send (client->mq, env);
445}
446
447
453static void
454shutdown_task (void *cls)
455{
456 struct P_Client *c;
457 (void) cls;
458
460 "PILS shutting down\n");
461 c = clients_head;
462 while (NULL != c)
463 {
464 struct P_Client *c_delete = c;
465
466 c = c->next;
468 /* No need to remove from DLL or free here - #client_disconnect_cb(), which
469 * is called by GNUNET_SERVICE_client_drop(), takes care of this. */
470 }
471 if (NULL != signed_hello)
473 cfg = NULL;
474 if (NULL != generate_pid_task)
477}
478
479
487static void
488run (void *cls,
489 const struct GNUNET_CONFIGURATION_Handle *c,
491{
492 cfg = c;
494 "PILS starting\n");
496 load_ikm ();
497 /* Generate an initial peer id from no addresses at all
498 * This is needed for scenarios in which we have only local addresses. */
499 do_generate_pid (NULL);
501}
502
503
515static void *
517 struct GNUNET_SERVICE_Client *c,
518 struct GNUNET_MQ_Handle *mq)
519{
520 struct P_Client *client;
521 (void) cls;
522
523 LOG (GNUNET_ERROR_TYPE_DEBUG, "A client `%p' connected\n",
524 mq);
525 client = GNUNET_new (struct P_Client);
526 client->client = c;
527 client->mq = mq;
530 client);
531 if (GNUNET_YES == have_id)
532 {
534 }
535 return client;
536}
537
538
548static void
550 struct GNUNET_SERVICE_Client *c,
551 void *internal_cls)
552{
553 struct P_Client *client_iter;
554 (void) cls;
555
556 client_iter = clients_head;
557 while (NULL != client_iter)
558 {
559 struct P_Client *client_next = client_iter->next;
560
561 if (client_iter->client == c)
562 {
565 client_iter);
566 GNUNET_free (client_iter);
567 }
568 client_iter = client_next;
569 }
570}
571
572
577 "pils",
579 &run,
582 NULL,
583 GNUNET_MQ_hd_var_size (feed_addresses,
586 NULL),
589 struct DecapsMessage,
590 NULL),
593 struct SignRequestMessage,
594 NULL),
596
597
598/* end of gnunet-service-pils.c */
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static struct HostSet * builder
NULL if we are not currently iterating over peer information.
struct GNUNET_HashCode key
The key used in the DHT.
struct GNUNET_SCHEDULER_Task * shutdown_task
static struct GNUNET_FS_Uri * uri
Value of URI provided on command-line (when not publishing a file but just creating UBlocks to refer ...
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_MQ_Envelope * signed_hello
Current signed HELLO.
static void handle_decaps(void *cls, const struct DecapsMessage *message)
Handler for decaps request message from client.
struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key
The current private key.
static struct GNUNET_SCHEDULER_Task * generate_pid_task
Task to schedule the generation of the peer id.
static unsigned char ikm[256/8]
The initial key material for the peer.
struct GNUNET_HashCode addresses_hash
Hash of the canonicalized addresses.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
static int check_feed_addresses(void *cls, const struct FeedAddressesMessage *msg)
Checker for feed messages.
static void print_uri(void *cls, const struct GNUNET_PeerIdentity *pid, const char *uri)
static void handle_feed_addresses(void *cls, const struct FeedAddressesMessage *message)
Handler for feed addresses message from client.
static struct P_Client * clients_tail
Tail of the liked list of clients.
struct GNUNET_CRYPTO_EddsaPublicKey my_public_key
The current public key.
static struct P_Client * clients_head
Head of the liked list of clients.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Set up the service.
static void load_ikm()
Get the initial secret key for generating the peer id.
static int have_id
Peer ID was calculated already at least once.
static void handle_sign(void *cls, const struct SignRequestMessage *message)
Handler for sign request message from client.
static void do_generate_pid(const struct GNUNET_HELLO_Parser *parser)
Generate the peer id from the addresses hash and the initial secret key.
static int check_sign(void *cls, const struct SignRequestMessage *msg)
Handler for sign request message from client.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback called when a client connects to the service.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback called when a client disconnected from the service.
#define LOG(kind,...)
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
void GNUNET_PILS_derive_pid(size_t seed_key_bytes, const uint8_t seed_key[seed_key_bytes], const struct GNUNET_HashCode *addrs_hash, struct GNUNET_CRYPTO_EddsaPrivateKey *outkey)
Generate the peer id from the addresses hash and the initial secret key.
Definition pils_api.c:507
Constants for network protocols.
#define GNUNET_SIGNATURE_PURPOSE_HELLO
Signature by which a peer affirms its address.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_decaps(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private EdDSA key.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_key_from_file(const char *filename, int do_create, struct GNUNET_CRYPTO_EddsaPrivateKey *pkey)
Create a new private key by reading it from a file.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition crypto_ecc.c:201
void GNUNET_CRYPTO_eddsa_key_clear(struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
Clear memory that was used to store a private key.
Definition crypto_ecc.c:447
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition crypto_ecc.c:625
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
void GNUNET_HELLO_parser_free(struct GNUNET_HELLO_Parser *parser)
Release resources of a builder.
Definition hello-uri.c:379
void GNUNET_HELLO_builder_to_block(const struct GNUNET_HELLO_Builder *builder, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_CRYPTO_EddsaSignature *sig, struct GNUNET_TIME_Absolute expiration_time, char *outbuf)
Generate DHT block from a builder.
Definition hello-uri.c:1244
void GNUNET_HELLO_builder_free(struct GNUNET_HELLO_Builder *builder)
Release resources of a builder.
Definition hello-uri.c:397
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_new()
Allocate builder.
Definition hello-uri.c:343
struct GNUNET_HELLO_Parser * GNUNET_HELLO_parser_from_block_(const void *block, size_t block_size, int noverify)
Parse block.
Definition hello-uri.c:533
void GNUNET_HELLO_builder_iterate(const struct GNUNET_HELLO_Builder *builder, GNUNET_HELLO_UriCallback uc, void *uc_cls)
Iterate over URIs in a builder.
Definition hello-uri.c:956
struct GNUNET_HELLO_Builder * GNUNET_HELLO_builder_from_parser(const struct GNUNET_HELLO_Parser *parser, struct GNUNET_PeerIdentity *pid)
Allocate builder from parser.
Definition hello-uri.c:360
size_t GNUNET_HELLO_get_builder_to_block_size(const struct GNUNET_HELLO_Builder *builder)
Get projected block size for builder.
Definition hello-uri.c:1312
#define GNUNET_HELLO_ADDRESS_EXPIRATION
For how long are HELLO signatures valid?
void GNUNET_HELLO_builder_hash_addresses(const struct GNUNET_HELLO_Builder *builder, struct GNUNET_HashCode *hash)
Compute hash over addresses in builder.
Definition hello-uri.c:1134
#define GNUNET_log(kind,...)
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_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
const char * GNUNET_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send_copy(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MQ_Envelope *ev)
Send a copy of a message with the given message queue.
Definition mq.c:384
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
#define GNUNET_MESSAGE_TYPE_PILS_SIGN_REQUEST
The client requests data to be signed with the peer identity.
#define GNUNET_MESSAGE_TYPE_PILS_KEM_DECAPS
Decaps request.
#define GNUNET_MESSAGE_TYPE_PILS_FEED_ADDRESSES
The client (core) provides new addresses to the service, so the service can generate the new peer id.
#define GNUNET_MESSAGE_TYPE_PILS_DECAPS_RESULT
Decaps result.
#define GNUNET_MESSAGE_TYPE_PILS_PEER_ID
Message passing the new peer id from the service to the client.
#define GNUNET_MESSAGE_TYPE_PILS_SIGN_RESULT
The service sends the requested signature to the client.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
#define GNUNET_SERVICE_MAIN(pd, service_name, service_options, init_cb, connect_cb, disconnect_cb, cls,...)
Creates the "main" function for a GNUnet service.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition service.c:2462
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2433
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:640
Common type definitions for the peer identity lifecycle service and API.
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
Message to request a decapsulation from PILS.
Definition pils.h:143
uint32_t rid
Request ID.
Definition pils.h:157
struct GNUNET_CRYPTO_HpkeEncapsulation c
Encapsulation to decapsulate.
Definition pils.h:152
Message containing the decapsulated key.
Definition pils.h:164
uint32_t rid
Request ID.
Definition pils.h:178
struct GNUNET_ShortHashCode key
The decapsulated key.
Definition pils.h:173
Message requesting a signature on data with the current peer id.
Definition pils.h:123
uint32_t block_len
For alignment.
Definition pils.h:132
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
Private ECC key encoded for transmission.
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
an ECC signature using EdDSA.
Context for building (or parsing) HELLO URIs.
Definition hello-uri.c:184
Context for parsing HELLOs.
Definition hello-uri.c:232
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition scheduler.c:136
Handle to a client that is connected to a service.
Definition service.c:249
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition service.c:273
Handle to a service.
Definition service.c:116
Time for absolute times used by GNUnet, in microseconds.
Data structure for each client connected to the CORE service.
struct GNUNET_MQ_Handle * mq
Message queue to talk to client.
struct P_Client * next
Clients are kept in a linked list.
struct P_Client * prev
Clients are kept in a linked list.
struct GNUNET_SERVICE_Client * client
Handle for the client with the server API.
Message containing the current peer id and the hash from which it was generated.
Definition pils.h:40
Message signed as part of a HELLO block/URL.
Definition hello-uri.c:50
struct GNUNET_HashCode h_addrs
Hash over all addresses.
Definition hello-uri.c:64
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Purpose must be GNUNET_SIGNATURE_PURPOSE_HELLO.
Definition hello-uri.c:54
Message to request a signature from PILS.
Definition pils.h:213
uint32_t rid
Request ID.
Definition pils.h:222
Message containing the signature.
Definition pils.h:185
uint32_t rid
Request ID.
Definition pils.h:204
struct GNUNET_PeerIdentity peer_id
The peer identity that produces the signature.
Definition pils.h:194
struct GNUNET_CRYPTO_EddsaSignature sig
The signature.
Definition pils.h:199