GNUnet 0.21.2
gnunet-service-core_kx.c File Reference

code for managing the key exchange (SET_KEY, PING, PONG) with other peers More...

#include "platform.h"
#include "gnunet-service-core_kx.h"
#include "gnunet_transport_core_service.h"
#include "gnunet-service-core_sessions.h"
#include "gnunet-service-core.h"
#include "gnunet_constants.h"
#include "gnunet_signatures.h"
#include "gnunet_protocols.h"
Include dependency graph for gnunet-service-core_kx.c:

Go to the source code of this file.

Data Structures

struct  EncryptedMessage
 Encapsulation for encrypted messages exchanged between peers. More...
 
struct  GSC_KeyExchangeInfo
 Information about the status of a key exchange with another peer. More...
 

Macros

#define DEBUG_KX   0
 Enable expensive (and possibly problematic for privacy!) logging of KX. More...
 
#define INITIAL_SET_KEY_RETRY_FREQUENCY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
 How long do we wait for SET_KEY confirmation initially? More...
 
#define MIN_PING_FREQUENCY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
 What is the minimum frequency for a PING message? More...
 
#define REKEY_FREQUENCY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
 How often do we rekey? More...
 
#define REKEY_TOLERANCE    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
 What time difference do we tolerate? More...
 
#define MAX_MESSAGE_AGE   GNUNET_TIME_UNIT_DAYS
 What is the maximum age of a message for us to consider processing it? Note that this looks at the timestamp used by the other peer, so clock skew between machines does come into play here. More...
 
#define ENCRYPTED_HEADER_SIZE    (offsetof (struct EncryptedMessage, sequence_number))
 Number of bytes (at the beginning) of struct EncryptedMessage that are NOT encrypted. More...
 

Functions

static uint32_t calculate_seed (struct GSC_KeyExchangeInfo *kx)
 Calculate seed value we should use for a message. More...
 
static void monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
 Inform all monitors about the KX state of the given peer. More...
 
static void derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, uint32_t seed)
 Derive an authentication key from "set key" information. More...
 
static void derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, uint32_t seed, const struct GNUNET_PeerIdentity *identity)
 Derive an IV from packet information. More...
 
static void derive_pong_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, uint32_t seed, uint32_t challenge, const struct GNUNET_PeerIdentity *identity)
 Derive an IV from pong packet information. More...
 
static void derive_aes_key (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_PeerIdentity *receiver, const struct GNUNET_HashCode *key_material, struct GNUNET_CRYPTO_SymmetricSessionKey *skey)
 Derive an AES key from key material. More...
 
static int do_encrypt (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const void *in, void *out, size_t size)
 Encrypt size bytes from in and write the result to out. More...
 
static int do_decrypt (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const void *in, void *out, size_t size)
 Decrypt size bytes from in and write the result to out. More...
 
static void send_key (struct GSC_KeyExchangeInfo *kx)
 Send our key (and encrypted PING) to the other peer. More...
 
static void set_key_retry_task (void *cls)
 Task that will retry send_key() if our previous attempt failed. More...
 
static void setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
 Create a fresh PING message for transmission to the other peer. More...
 
static int deliver_message (void *cls, const struct GNUNET_MessageHeader *m)
 Deliver P2P message to interested clients. More...
 
static void * handle_transport_notify_connect (void *cls, const struct GNUNET_PeerIdentity *pid, struct GNUNET_MQ_Handle *mq)
 Function called by transport to notify us that a peer connected to us (on the network level). More...
 
static void handle_transport_notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer, void *handler_cls)
 Function called by transport telling us that a peer disconnected. More...
 
static void send_ping (struct GSC_KeyExchangeInfo *kx)
 Send our PING to the other peer. More...
 
static void derive_session_keys (struct GSC_KeyExchangeInfo *kx)
 Derive fresh session keys from the current ephemeral keys. More...
 
static void handle_ephemeral_key (void *cls, const struct EphemeralKeyMessage *m)
 We received a GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY message. More...
 
static void send_keep_alive (void *cls)
 Task triggered when a neighbour entry is about to time out (and we should prevent this by sending a PING). More...
 
static void handle_ping (void *cls, const struct PingMessage *m)
 We received a PING message. More...
 
static void update_timeout (struct GSC_KeyExchangeInfo *kx)
 We've seen a valid message from the other peer. More...
 
static void handle_pong (void *cls, const struct PongMessage *m)
 We received a PONG message. More...
 
void GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, const void *payload, size_t payload_size)
 Encrypt and transmit a message with the given payload. More...
 
static int check_encrypted (void *cls, const struct EncryptedMessage *m)
 We received an encrypted message. More...
 
static void handle_encrypted (void *cls, const struct EncryptedMessage *m)
 We received an encrypted message. More...
 
static void sign_ephemeral_key ()
 Setup the message that links the ephemeral key to our persistent public key and generate the appropriate signature. More...
 
static void do_rekey (void *cls)
 Task run to trigger rekeying. More...
 
int GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
 Initialize KX subsystem. More...
 
void GSC_KX_done ()
 Shutdown KX subsystem. More...
 
unsigned int GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
 Check how many messages are queued for the given neighbour. More...
 
int GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
 Check if the given neighbour has excess bandwidth available. More...
 
void GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
 Handle GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. More...
 

Variables

static struct GNUNET_TRANSPORT_CoreHandletransport
 Transport service. More...
 
static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key
 Our private key. More...
 
static struct GNUNET_CRYPTO_EcdhePrivateKey my_ephemeral_key
 Our ephemeral private key. More...
 
static struct EphemeralKeyMessage current_ekm
 Current message we send for a key exchange. More...
 
static struct GSC_KeyExchangeInfokx_head
 DLL head. More...
 
static struct GSC_KeyExchangeInfokx_tail
 DLL tail. More...
 
static struct GNUNET_SCHEDULER_Taskrekey_task
 Task scheduled for periodic re-generation (and thus rekeying) of our ephemeral key. More...
 
static struct GNUNET_NotificationContextnc
 Notification context for broadcasting to monitors. More...
 

Detailed Description

code for managing the key exchange (SET_KEY, PING, PONG) with other peers

Author
Christian Grothoff

Definition in file gnunet-service-core_kx.c.

Macro Definition Documentation

◆ DEBUG_KX

#define DEBUG_KX   0

Enable expensive (and possibly problematic for privacy!) logging of KX.

Definition at line 39 of file gnunet-service-core_kx.c.

◆ INITIAL_SET_KEY_RETRY_FREQUENCY

#define INITIAL_SET_KEY_RETRY_FREQUENCY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)

How long do we wait for SET_KEY confirmation initially?

Definition at line 45 of file gnunet-service-core_kx.c.

◆ MIN_PING_FREQUENCY

#define MIN_PING_FREQUENCY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)

What is the minimum frequency for a PING message?

Definition at line 51 of file gnunet-service-core_kx.c.

◆ REKEY_FREQUENCY

#define REKEY_FREQUENCY    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)

How often do we rekey?

Definition at line 57 of file gnunet-service-core_kx.c.

◆ REKEY_TOLERANCE

#define REKEY_TOLERANCE    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)

What time difference do we tolerate?

Definition at line 63 of file gnunet-service-core_kx.c.

◆ MAX_MESSAGE_AGE

#define MAX_MESSAGE_AGE   GNUNET_TIME_UNIT_DAYS

What is the maximum age of a message for us to consider processing it? Note that this looks at the timestamp used by the other peer, so clock skew between machines does come into play here.

So this should be picked high enough so that a little bit of clock skew does not prevent peers from connecting to us.

Definition at line 73 of file gnunet-service-core_kx.c.

◆ ENCRYPTED_HEADER_SIZE

#define ENCRYPTED_HEADER_SIZE    (offsetof (struct EncryptedMessage, sequence_number))

Number of bytes (at the beginning) of struct EncryptedMessage that are NOT encrypted.

Definition at line 178 of file gnunet-service-core_kx.c.

Function Documentation

◆ calculate_seed()

static uint32_t calculate_seed ( struct GSC_KeyExchangeInfo kx)
static

Calculate seed value we should use for a message.

Parameters
kxkey exchange context

Definition at line 360 of file gnunet-service-core_kx.c.

361{
362 /* Note: may want to make this non-random and instead
363 derive from key material to avoid having an undetectable
364 side-channel */
365 return htonl (
367}
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.

References GNUNET_CRYPTO_QUALITY_NONCE, and GNUNET_CRYPTO_random_u32().

Referenced by GSC_KX_encrypt_and_transmit(), handle_ping(), and setup_fresh_ping().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ monitor_notify_all()

static void monitor_notify_all ( struct GSC_KeyExchangeInfo kx)
static

Inform all monitors about the KX state of the given peer.

Parameters
kxkey exchange state to inform about

Definition at line 378 of file gnunet-service-core_kx.c.

379{
381
383 msg.header.size = htons (sizeof(msg));
384 msg.state = htonl ((uint32_t) kx->status);
385 msg.peer = *kx->peer;
386 msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
389}
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static struct GNUNET_NotificationContext * nc
Notification context for broadcasting to monitors.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_NO
void GNUNET_notification_context_broadcast(struct GNUNET_NotificationContext *nc, const struct GNUNET_MessageHeader *msg, int can_drop)
Send a message to all subscribers of this context.
Definition: nc.c:190
#define GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY
Reply for monitor by CORE service.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
struct GNUNET_TIME_Absolute last_notify_timeout
What was the last timeout we informed our monitors about?
const struct GNUNET_PeerIdentity * peer
Identity of the peer.
struct GNUNET_TIME_Absolute timeout
When should the session time out (if there are no PONGs)?
enum GNUNET_CORE_KxState status
What is our connection status?
Message sent by the service to monitor clients to notify them about a peer changing status.
Definition: core.h:301

References GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY, GNUNET_NO, GNUNET_notification_context_broadcast(), GNUNET_TIME_absolute_hton(), GSC_KeyExchangeInfo::last_notify_timeout, msg, nc, GSC_KeyExchangeInfo::peer, GNUNET_MessageHeader::size, GSC_KeyExchangeInfo::status, GSC_KeyExchangeInfo::timeout, and GNUNET_MessageHeader::type.

Referenced by do_rekey(), handle_encrypted(), handle_ephemeral_key(), handle_pong(), handle_transport_notify_connect(), handle_transport_notify_disconnect(), send_keep_alive(), and update_timeout().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ derive_auth_key()

static void derive_auth_key ( struct GNUNET_CRYPTO_AuthKey akey,
const struct GNUNET_CRYPTO_SymmetricSessionKey skey,
uint32_t  seed 
)
static

Derive an authentication key from "set key" information.

Parameters
akeyauthentication key to derive
skeysession key to use
seedseed to use

Definition at line 401 of file gnunet-service-core_kx.c.

404{
405 static const char ctx[] = "authentication key";
406
407#if DEBUG_KX
408 struct GNUNET_HashCode sh;
409
410 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
412 "Deriving Auth key from SKEY %s and seed %u\n",
413 GNUNET_h2s (&sh),
414 (unsigned int) seed);
415#endif
417 skey,
418 &seed,
419 sizeof(seed),
420 skey,
421 sizeof(
423 ctx,
424 sizeof(ctx),
425 NULL);
426}
static struct GNUNET_FS_Handle * ctx
static struct GNUNET_IDENTITY_Handle * sh
Handle to IDENTITY service.
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
void GNUNET_CRYPTO_hmac_derive_key(struct GNUNET_CRYPTO_AuthKey *key, const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey, const void *salt, size_t salt_len,...)
Derive an authentication key.
Definition: crypto_hash.c:267
#define GNUNET_log(kind,...)
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG
A 512-bit hashcode.

References ctx, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_hmac_derive_key(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_log, and sh.

Referenced by GSC_KX_encrypt_and_transmit(), and handle_encrypted().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ derive_iv()

static void derive_iv ( struct GNUNET_CRYPTO_SymmetricInitializationVector iv,
const struct GNUNET_CRYPTO_SymmetricSessionKey skey,
uint32_t  seed,
const struct GNUNET_PeerIdentity identity 
)
static

Derive an IV from packet information.

Parameters
ivinitialization vector to initialize
skeysession key to use
seedseed to use
identityidentity of the other peer to use

Definition at line 438 of file gnunet-service-core_kx.c.

442{
443 static const char ctx[] = "initialization vector";
444
445#if DEBUG_KX
446 struct GNUNET_HashCode sh;
447
448 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
450 "Deriving IV from SKEY %s and seed %u for peer %s\n",
451 GNUNET_h2s (&sh),
452 (unsigned int) seed,
454#endif
456 skey,
457 &seed,
458 sizeof(seed),
459 identity,
460 sizeof(struct GNUNET_PeerIdentity),
461 ctx,
462 sizeof(ctx),
463 NULL);
464}
static struct GNUNET_IDENTITY_Handle * identity
Which namespace do we publish to? NULL if we do not publish to a namespace.
void GNUNET_CRYPTO_symmetric_derive_iv(struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, const void *salt, size_t salt_len,...)
Derive an IV.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
The identity of the host (wraps the signing key of the peer).

References ctx, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_symmetric_derive_iv(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, identity, and sh.

Referenced by GSC_KX_encrypt_and_transmit(), handle_encrypted(), handle_ping(), and setup_fresh_ping().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ derive_pong_iv()

static void derive_pong_iv ( struct GNUNET_CRYPTO_SymmetricInitializationVector iv,
const struct GNUNET_CRYPTO_SymmetricSessionKey skey,
uint32_t  seed,
uint32_t  challenge,
const struct GNUNET_PeerIdentity identity 
)
static

Derive an IV from pong packet information.

Parameters
ivinitialization vector to initialize
skeysession key to use
seedseed to use
challengenonce to use
identityidentity of the other peer to use

Definition at line 477 of file gnunet-service-core_kx.c.

482{
483 static const char ctx[] = "pong initialization vector";
484
485#if DEBUG_KX
486 struct GNUNET_HashCode sh;
487
488 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
490 "Deriving PONG IV from SKEY %s and seed %u/%u for %s\n",
491 GNUNET_h2s (&sh),
492 (unsigned int) seed,
493 (unsigned int) challenge,
495#endif
497 skey,
498 &seed,
499 sizeof(seed),
500 identity,
501 sizeof(struct GNUNET_PeerIdentity),
502 &challenge,
503 sizeof(challenge),
504 ctx,
505 sizeof(ctx),
506 NULL);
507}

References ctx, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_symmetric_derive_iv(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, identity, and sh.

Referenced by handle_ping(), and handle_pong().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ derive_aes_key()

static void derive_aes_key ( const struct GNUNET_PeerIdentity sender,
const struct GNUNET_PeerIdentity receiver,
const struct GNUNET_HashCode key_material,
struct GNUNET_CRYPTO_SymmetricSessionKey skey 
)
static

Derive an AES key from key material.

Parameters
senderpeer identity of the sender
receiverpeer identity of the sender
key_materialhigh entropy key material to use
skeyset to derived session key

Definition at line 562 of file gnunet-service-core_kx.c.

566{
567 static const char ctx[] = "aes key generation vector";
568
569#if DEBUG_KX
570 struct GNUNET_HashCode sh;
571
572 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
574 "Deriving AES Keys for %s to %s from %s\n",
575 GNUNET_i2s (sender),
577 GNUNET_h2s (key_material));
578#endif
579 GNUNET_CRYPTO_kdf (skey,
581 ctx,
582 sizeof(ctx),
583 key_material,
584 sizeof(struct GNUNET_HashCode),
585 sender,
586 sizeof(struct GNUNET_PeerIdentity),
587 receiver,
588 sizeof(struct GNUNET_PeerIdentity),
589 NULL);
590}
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:62
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void receiver(void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode)
Callback to read from the SOCKS5 proxy.
Definition: socks.c:330

References ctx, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_kdf(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_i2s2(), GNUNET_log, receiver(), and sh.

Referenced by derive_session_keys().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_encrypt()

static int do_encrypt ( struct GSC_KeyExchangeInfo kx,
const struct GNUNET_CRYPTO_SymmetricInitializationVector iv,
const void *  in,
void *  out,
size_t  size 
)
static

Encrypt size bytes from in and write the result to out.

Use the kx key for outbound traffic of the given neighbour.

Parameters
kxkey information context
ivinitialization vector to use
inciphertext
outplaintext
sizesize of in / out
Returns
GNUNET_OK on success

Definition at line 609 of file gnunet-service-core_kx.c.

614{
615 if (size != (uint16_t) size)
616 {
617 GNUNET_break (0);
618 return GNUNET_NO;
619 }
621 (uint16_t) size,
622 &kx->encrypt_key,
623 iv,
624 out));
626 gettext_noop ("# bytes encrypted"),
627 size,
628 GNUNET_NO);
629 /* the following is too sensitive to write to log files by accident,
630 so we require manual intervention to get this one... */
631#if DEBUG_KX
633 "Encrypted %u bytes for `%s' using key %s, IV %u\n",
634 (unsigned int) size,
635 GNUNET_i2s (kx->peer),
637 GNUNET_CRYPTO_crc32_n (iv, sizeof(iv)));
638#endif
639 return GNUNET_OK;
640}
#define gettext_noop(String)
Definition: gettext.h:74
struct GNUNET_STATISTICS_Handle * GSC_stats
For creating statistics.
ssize_t GNUNET_CRYPTO_symmetric_encrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Encrypt a block using a symmetric sessionkey.
int32_t GNUNET_CRYPTO_crc32_n(const void *buf, size_t len)
Compute the CRC32 checksum for the first len bytes of the buffer.
Definition: crypto_crc.c:99
@ GNUNET_OK
#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.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
static unsigned int size
Size of the "table".
Definition: peer.c:68
unsigned char aes_key[(256/8)]
Actual key for AES.
struct GNUNET_CRYPTO_SymmetricSessionKey encrypt_key
Key we use to encrypt our messages for the other peer (initialized by us when we do the handshake).

References GNUNET_CRYPTO_SymmetricSessionKey::aes_key, GSC_KeyExchangeInfo::encrypt_key, gettext_noop, GNUNET_assert, GNUNET_break, GNUNET_CRYPTO_crc32_n(), GNUNET_CRYPTO_symmetric_encrypt(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GSC_stats, GSC_KeyExchangeInfo::peer, and size.

Referenced by GSC_KX_encrypt_and_transmit(), handle_ping(), and setup_fresh_ping().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_decrypt()

static int do_decrypt ( struct GSC_KeyExchangeInfo kx,
const struct GNUNET_CRYPTO_SymmetricInitializationVector iv,
const void *  in,
void *  out,
size_t  size 
)
static

Decrypt size bytes from in and write the result to out.

Use the kx key for inbound traffic of the given neighbour. This function does NOT do any integrity-checks on the result.

Parameters
kxkey information context
ivinitialization vector to use
inciphertext
outplaintext
sizesize of in / out
Returns
GNUNET_OK on success

Definition at line 659 of file gnunet-service-core_kx.c.

664{
665 if (size != (uint16_t) size)
666 {
667 GNUNET_break (0);
668 return GNUNET_NO;
669 }
673 {
674 GNUNET_break_op (0);
675 return GNUNET_SYSERR;
676 }
678 (uint16_t) size,
679 &kx->decrypt_key,
680 iv,
681 out))
682 {
683 GNUNET_break (0);
684 return GNUNET_SYSERR;
685 }
687 gettext_noop ("# bytes decrypted"),
688 size,
689 GNUNET_NO);
690 /* the following is too sensitive to write to log files by accident,
691 so we require manual intervention to get this one... */
692#if DEBUG_KX
694 "Decrypted %u bytes from `%s' using key %s, IV %u\n",
695 (unsigned int) size,
696 GNUNET_i2s (kx->peer),
698 GNUNET_CRYPTO_crc32_n (iv, sizeof(*iv)));
699#endif
700 return GNUNET_OK;
701}
@ GNUNET_CORE_KX_STATE_UP
The other peer has confirmed our session key + PING with a PONG message encrypted with their session ...
@ GNUNET_CORE_KX_STATE_KEY_RECEIVED
We've received the other peers session key.
@ GNUNET_CORE_KX_STATE_REKEY_SENT
We're rekeying (or had a timeout), so we have sent the other peer our new ephemeral key,...
ssize_t GNUNET_CRYPTO_symmetric_decrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Decrypt a given block using a symmetric sessionkey.
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct GNUNET_CRYPTO_SymmetricSessionKey decrypt_key
Key we use to decrypt messages from the other peer (given to us by the other peer during the handshak...

References GNUNET_CRYPTO_SymmetricSessionKey::aes_key, GSC_KeyExchangeInfo::decrypt_key, gettext_noop, GNUNET_break, GNUNET_break_op, GNUNET_CORE_KX_STATE_KEY_RECEIVED, GNUNET_CORE_KX_STATE_REKEY_SENT, GNUNET_CORE_KX_STATE_UP, GNUNET_CRYPTO_crc32_n(), GNUNET_CRYPTO_symmetric_decrypt(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GNUNET_SYSERR, GSC_stats, GSC_KeyExchangeInfo::peer, size, and GSC_KeyExchangeInfo::status.

Referenced by handle_encrypted(), handle_ping(), and handle_pong().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_key()

static void send_key ( struct GSC_KeyExchangeInfo kx)
static

Send our key (and encrypted PING) to the other peer.

Send our key to the other peer.

Parameters
kxkey exchange context

Definition at line 1584 of file gnunet-service-core_kx.c.

1585{
1586 struct GNUNET_MQ_Envelope *env;
1587
1589 if (NULL != kx->retry_set_key_task)
1590 {
1592 kx->retry_set_key_task = NULL;
1593 }
1594 /* always update sender status in SET KEY message */
1595#if DEBUG_KX
1596 {
1597 struct GNUNET_HashCode hc;
1598
1600 sizeof(current_ekm.ephemeral_key),
1601 &hc);
1603 "Sending EPHEMERAL_KEY %s to `%s' (my status: %d)\n",
1604 GNUNET_h2s (&hc),
1605 GNUNET_i2s (kx->peer),
1606 kx->status);
1607 }
1608#endif
1609 current_ekm.sender_status = htonl ((int32_t) (kx->status));
1611 GNUNET_MQ_send (kx->mq, env);
1613 send_ping (kx);
1614 kx->retry_set_key_task =
1617 kx);
1618}
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static void set_key_retry_task(void *cls)
Task that will retry send_key() if our previous attempt failed.
static struct EphemeralKeyMessage current_ekm
Current message we send for a key exchange.
static void send_ping(struct GSC_KeyExchangeInfo *kx)
Send our PING to the other peer.
@ GNUNET_CORE_KX_STATE_DOWN
No handshake yet.
@ GNUNET_CORE_KX_STATE_KEY_SENT
We've sent our session key.
struct GNUNET_MQ_Envelope * GNUNET_MQ_msg_copy(const struct GNUNET_MessageHeader *hdr)
Create a new envelope by copying an existing message.
Definition: mq.c:550
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
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1278
struct GNUNET_MessageHeader header
Message type is GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY.
int32_t sender_status
Status of the sender (should be in enum PeerStateMachine), nbo.
struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key
Ephemeral public ECC key.
struct GNUNET_SCHEDULER_Task * retry_set_key_task
ID of task used for re-trying SET_KEY and PING message.
struct GNUNET_TIME_Relative set_key_retry_frequency
At what frequency are we currently re-trying SET_KEY messages?
struct GNUNET_MQ_Handle * mq
Message queue for sending messages to peer.

References current_ekm, env, EphemeralKeyMessage::ephemeral_key, GNUNET_assert, GNUNET_CORE_KX_STATE_DOWN, GNUNET_CORE_KX_STATE_KEY_SENT, GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_i2s(), GNUNET_log, GNUNET_MQ_msg_copy(), GNUNET_MQ_send(), GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), EphemeralKeyMessage::header, GSC_KeyExchangeInfo::mq, GSC_KeyExchangeInfo::peer, GSC_KeyExchangeInfo::retry_set_key_task, send_ping(), EphemeralKeyMessage::sender_status, GSC_KeyExchangeInfo::set_key_retry_frequency, set_key_retry_task(), and GSC_KeyExchangeInfo::status.

Referenced by do_rekey(), handle_encrypted(), handle_ephemeral_key(), handle_transport_notify_connect(), send_keep_alive(), and set_key_retry_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_key_retry_task()

static void set_key_retry_task ( void *  cls)
static

Task that will retry send_key() if our previous attempt failed.

Parameters
clsour struct GSC_KeyExchangeInfo

Definition at line 721 of file gnunet-service-core_kx.c.

722{
723 struct GSC_KeyExchangeInfo *kx = cls;
724
725 kx->retry_set_key_task = NULL;
729 send_key (kx);
730}
static void send_key(struct GSC_KeyExchangeInfo *kx)
Send our key (and encrypted PING) to the other peer.
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
Information about the status of a key exchange with another peer.

References GNUNET_assert, GNUNET_CORE_KX_STATE_DOWN, GNUNET_TIME_STD_BACKOFF, GSC_KeyExchangeInfo::retry_set_key_task, send_key(), GSC_KeyExchangeInfo::set_key_retry_frequency, and GSC_KeyExchangeInfo::status.

Referenced by handle_transport_notify_connect(), and send_key().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_fresh_ping()

static void setup_fresh_ping ( struct GSC_KeyExchangeInfo kx)
static

Create a fresh PING message for transmission to the other peer.

Parameters
kxkey exchange context to create PING for

Definition at line 739 of file gnunet-service-core_kx.c.

740{
741 struct PingMessage pp;
742 struct PingMessage *pm;
743
744 pm = &kx->ping;
745 kx->ping_challenge =
747 pm->header.size = htons (sizeof(struct PingMessage));
748 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
749 pp.challenge = kx->ping_challenge;
750 pp.target = *kx->peer;
751#if CONG_CRYPTO_ENABLED
752 randombytes_buf (pm->nonce, sizeof (pm->nonce));
753 GNUNET_assert (0 ==
754 crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
755 (unsigned char*) &pm->target,
756 pm->tag,
757 NULL,
758 (unsigned char*) &pp.target,
759 sizeof(pp.target) + sizeof (pp.challenge),
760 NULL, 0,
761 NULL,
762 pm->nonce,
763 kx->encrypt_key));
764#else
766 pm->iv_seed = calculate_seed (kx);
767 derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, kx->peer);
768 do_encrypt (kx,
769 &iv,
770 &pp.target,
771 &pm->target,
772 sizeof(struct PingMessage)
773 - ((void *) &pm->target - (void *) pm));
774#endif
775}
static uint32_t calculate_seed(struct GSC_KeyExchangeInfo *kx)
Calculate seed value we should use for a message.
static void derive_iv(struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, uint32_t seed, const struct GNUNET_PeerIdentity *identity)
Derive an IV from packet information.
static int do_encrypt(struct GSC_KeyExchangeInfo *kx, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const void *in, void *out, size_t size)
Encrypt size bytes from in and write the result to out.
static struct GNUNET_TRANSPORT_PluginMonitor * pm
Handle if we are monitoring plugin session activity.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_MESSAGE_TYPE_CORE_PING
Check that other peer is alive (challenge).
uint32_t ping_challenge
What was our PING challenge number (for this peer)?
struct PingMessage ping
PING message we transmit to the other peer.
We're sending an (encrypted) PING to the other peer to check if it can decrypt.

References calculate_seed(), PingMessage::challenge, derive_iv(), do_encrypt(), GSC_KeyExchangeInfo::encrypt_key, GNUNET_assert, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_MESSAGE_TYPE_CORE_PING, GSC_KeyExchangeInfo::peer, GSC_KeyExchangeInfo::ping, GSC_KeyExchangeInfo::ping_challenge, pm, and PingMessage::target.

Referenced by derive_session_keys(), and send_keep_alive().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ deliver_message()

static int deliver_message ( void *  cls,
const struct GNUNET_MessageHeader m 
)
static

Deliver P2P message to interested clients.

Invokes send twice, once for clients that want the full message, and once for clients that only want the header

Parameters
clsthe struct GSC_KeyExchangeInfo
mthe message
Returns
GNUNET_OK on success, GNUNET_NO to stop further processing (no error) GNUNET_SYSERR to stop further processing with error

Definition at line 790 of file gnunet-service-core_kx.c.

791{
792 struct GSC_KeyExchangeInfo *kx = cls;
793
795 "Decrypted message of type %d from %s\n",
796 ntohs (m->type),
797 GNUNET_i2s (kx->peer));
799 {
801 gettext_noop ("# PAYLOAD dropped (out of order)"),
802 1,
803 GNUNET_NO);
804 return GNUNET_OK;
805 }
806 switch (ntohs (m->type))
807 {
811 return GNUNET_OK;
812
815 return GNUNET_OK;
816
817 default:
819 m,
820 ntohs (m->size),
823 m,
824 sizeof(struct GNUNET_MessageHeader),
826 }
827 return GNUNET_OK;
828}
#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND
Client wants all inbound messages in full.
Definition: core.h:53
#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND
Client just wants the 4-byte message headers of all inbound messages.
Definition: core.h:59
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
void GSC_CLIENTS_deliver_message(const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, uint16_t msize, uint32_t options)
Deliver P2P message to interested clients.
void GSC_SESSIONS_confirm_typemap(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg)
The other peer has confirmed receiving our type map, check if it is current and if so,...
void GSC_SESSIONS_set_typemap(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg)
We've received a typemap message from a peer, update ours.
#define GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP
uncompressed type map of the sender
#define GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP
gzip-compressed type map of the sender
#define GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP
Other peer confirms having received the type map.
Header for all communications.

References gettext_noop, GNUNET_CORE_KX_STATE_UP, GNUNET_CORE_OPTION_SEND_FULL_INBOUND, GNUNET_CORE_OPTION_SEND_HDR_INBOUND, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP, GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP, GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP, GNUNET_NO, GNUNET_OK, GNUNET_STATISTICS_update(), GSC_CLIENTS_deliver_message(), GSC_SESSIONS_confirm_typemap(), GSC_SESSIONS_set_typemap(), GSC_stats, m, GSC_KeyExchangeInfo::peer, and GSC_KeyExchangeInfo::status.

Referenced by handle_transport_notify_connect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_transport_notify_connect()

static void * handle_transport_notify_connect ( void *  cls,
const struct GNUNET_PeerIdentity pid,
struct GNUNET_MQ_Handle mq 
)
static

Function called by transport to notify us that a peer connected to us (on the network level).

Starts the key exchange with the given peer.

Parameters
clsclosure (NULL)
pididentity of the peer to do a key exchange with
Returns
key exchange information context

Definition at line 841 of file gnunet-service-core_kx.c.

844{
845 struct GSC_KeyExchangeInfo *kx;
846 struct GNUNET_HashCode h1;
847 struct GNUNET_HashCode h2;
848
850 "Initiating key exchange with `%s'\n",
851 GNUNET_i2s (pid));
853 gettext_noop ("# key exchanges initiated"),
854 1,
855 GNUNET_NO);
856
857 kx = GNUNET_new (struct GSC_KeyExchangeInfo);
859 kx->mq = mq;
860 kx->peer = pid;
865 GNUNET_CRYPTO_hash (pid, sizeof(struct GNUNET_PeerIdentity), &h1);
867 sizeof(struct GNUNET_PeerIdentity),
868 &h2);
869 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2))
870 {
871 /* peer with "lower" identity starts KX, otherwise we typically end up
872 with both peers starting the exchange and transmit the 'set key'
873 message twice */
874 send_key (kx);
875 }
876 else
877 {
878 /* peer with "higher" identity starts a delayed KX, if the "lower" peer
879 * does not start a KX since it sees no reasons to do so */
883 kx);
884 }
885 return kx;
886}
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_PeerIdentity GSC_my_identity
Our identity.
static struct GSC_KeyExchangeInfo * kx_tail
DLL tail.
static struct GSC_KeyExchangeInfo * kx_head
DLL head.
#define INITIAL_SET_KEY_RETRY_FREQUENCY
How long do we wait for SET_KEY confirmation initially?
static int deliver_message(void *cls, const struct GNUNET_MessageHeader *m)
Deliver P2P message to interested clients.
static void monitor_notify_all(struct GSC_KeyExchangeInfo *kx)
Inform all monitors about the KX state of the given peer.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
#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.
Definition: crypto_hash.c:221
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:86
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_MessageStreamTokenizer * mst
Our message stream tokenizer (for encrypted payload).

References deliver_message(), gettext_noop, GNUNET_CONTAINER_DLL_insert, GNUNET_CORE_KX_STATE_KEY_SENT, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_hash_cmp(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_MST_create(), GNUNET_new, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_STATISTICS_update(), GNUNET_TIME_UNIT_SECONDS, GSC_my_identity, GSC_stats, INITIAL_SET_KEY_RETRY_FREQUENCY, kx_head, kx_tail, monitor_notify_all(), mq, GSC_KeyExchangeInfo::mq, GSC_KeyExchangeInfo::mst, GSC_KeyExchangeInfo::peer, pid, GSC_KeyExchangeInfo::retry_set_key_task, send_key(), GSC_KeyExchangeInfo::set_key_retry_frequency, set_key_retry_task(), and GSC_KeyExchangeInfo::status.

Referenced by GSC_KX_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_transport_notify_disconnect()

static void handle_transport_notify_disconnect ( void *  cls,
const struct GNUNET_PeerIdentity peer,
void *  handler_cls 
)
static

Function called by transport telling us that a peer disconnected.

Stop key exchange with the given peer. Clean up key material.

Parameters
clsclosure
peerthe peer that disconnected
handler_clsthe struct GSC_KeyExchangeInfo of the peer

Definition at line 899 of file gnunet-service-core_kx.c.

902{
903 struct GSC_KeyExchangeInfo *kx = handler_cls;
904
906 "Peer `%s' disconnected from us.\n",
907 GNUNET_i2s (peer));
910 gettext_noop ("# key exchanges stopped"),
911 1,
912 GNUNET_NO);
913 if (NULL != kx->retry_set_key_task)
914 {
916 kx->retry_set_key_task = NULL;
917 }
918 if (NULL != kx->keep_alive_task)
919 {
921 kx->keep_alive_task = NULL;
922 }
927 GNUNET_free (kx);
928}
void GSC_SESSIONS_end(const struct GNUNET_PeerIdentity *pid)
End the session with the given peer (we are no longer connected).
@ GNUNET_CORE_KX_PEER_DISCONNECT
Last state of a KX (when it is being terminated).
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:404
struct GNUNET_SCHEDULER_Task * keep_alive_task
ID of task used for sending keep-alive pings.

References gettext_noop, GNUNET_CONTAINER_DLL_remove, GNUNET_CORE_KX_PEER_DISCONNECT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_MST_destroy(), GNUNET_NO, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GSC_SESSIONS_end(), GSC_stats, GSC_KeyExchangeInfo::keep_alive_task, kx_head, kx_tail, monitor_notify_all(), GSC_KeyExchangeInfo::mst, GSC_KeyExchangeInfo::peer, GSC_KeyExchangeInfo::retry_set_key_task, and GSC_KeyExchangeInfo::status.

Referenced by GSC_KX_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_ping()

static void send_ping ( struct GSC_KeyExchangeInfo kx)
static

Send our PING to the other peer.

Parameters
kxkey exchange context

Definition at line 937 of file gnunet-service-core_kx.c.

938{
939 struct GNUNET_MQ_Envelope *env;
940
942 gettext_noop ("# PING messages transmitted"),
943 1,
944 GNUNET_NO);
946 GNUNET_MQ_send (kx->mq, env);
947}
struct GNUNET_MessageHeader header
Message type is GNUNET_MESSAGE_TYPE_CORE_PING.

References env, gettext_noop, GNUNET_MQ_msg_copy(), GNUNET_MQ_send(), GNUNET_NO, GNUNET_STATISTICS_update(), GSC_stats, PingMessage::header, GSC_KeyExchangeInfo::mq, and GSC_KeyExchangeInfo::ping.

Referenced by handle_ephemeral_key(), send_keep_alive(), and send_key().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ derive_session_keys()

static void derive_session_keys ( struct GSC_KeyExchangeInfo kx)
static

Derive fresh session keys from the current ephemeral keys.

Parameters
kxsession to derive keys for

Definition at line 956 of file gnunet-service-core_kx.c.

957{
958 struct GNUNET_HashCode key_material;
959
960 if (GNUNET_OK !=
963 &key_material))
964 {
965 GNUNET_break (0);
966 return;
967 }
968#if CONG_CRYPTO_ENABLED
969 derive_symmetric_key (&GSC_my_identity, kx->peer, &key_material, kx->
970 encrypt_key);
971 derive_symmetric_key (kx->peer, &GSC_my_identity, &key_material, kx->
972 decrypt_key);
973#else
974 derive_aes_key (&GSC_my_identity, kx->peer, &key_material, &kx->
975 encrypt_key);
976 derive_aes_key (kx->peer, &GSC_my_identity, &key_material, &kx->
977 decrypt_key);
978#endif
979 memset (&key_material, 0, sizeof(key_material));
980 /* fresh key, reset sequence numbers */
982 kx->last_packets_bitmap = 0;
983 setup_fresh_ping (kx);
984}
static struct GNUNET_CRYPTO_EcdhePrivateKey my_ephemeral_key
Our ephemeral private key.
static void derive_aes_key(const struct GNUNET_PeerIdentity *sender, const struct GNUNET_PeerIdentity *receiver, const struct GNUNET_HashCode *key_material, struct GNUNET_CRYPTO_SymmetricSessionKey *skey)
Derive an AES key from key material.
static void setup_fresh_ping(struct GSC_KeyExchangeInfo *kx)
Create a fresh PING message for transmission to the other peer.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecc_ecdh(const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material)
Derive key material from a public and a private ECC key.
Definition: crypto_ecc.c:732
uint32_t last_sequence_number_received
last sequence number received on this connection (highest)
struct GNUNET_CRYPTO_EcdhePublicKey other_ephemeral_key
Ephemeral public ECC key of the other peer.
uint32_t last_packets_bitmap
Bit map indicating which of the 32 sequence numbers before the last were received (good for accepting...

References derive_aes_key(), GNUNET_break, GNUNET_CRYPTO_ecc_ecdh(), GNUNET_OK, GSC_my_identity, GSC_KeyExchangeInfo::last_packets_bitmap, GSC_KeyExchangeInfo::last_sequence_number_received, my_ephemeral_key, GSC_KeyExchangeInfo::other_ephemeral_key, GSC_KeyExchangeInfo::peer, and setup_fresh_ping().

Referenced by do_rekey(), and handle_ephemeral_key().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_ephemeral_key()

static void handle_ephemeral_key ( void *  cls,
const struct EphemeralKeyMessage m 
)
static

We received a GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY message.

Validate and update our key material and status.

Parameters
clskey exchange status for the corresponding peer
mthe set key message we received

Definition at line 995 of file gnunet-service-core_kx.c.

996{
997 struct GSC_KeyExchangeInfo *kx = cls;
998 struct GNUNET_TIME_Absolute start_t;
999 struct GNUNET_TIME_Absolute end_t;
1000 struct GNUNET_TIME_Absolute now;
1001 enum GNUNET_CORE_KxState sender_status;
1002 enum GNUNET_GenericReturnValue do_verify = GNUNET_YES;
1003
1004 end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
1008 (end_t.abs_value_us < kx->foreign_key_expires.abs_value_us))
1009 {
1011 gettext_noop ("# old ephemeral keys ignored"),
1012 1,
1013 GNUNET_NO);
1015 "Received expired EPHEMERAL_KEY from %s\n",
1016 GNUNET_i2s (&m->origin_identity));
1017 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1018 return;
1019 }
1020 if (0 == memcmp (&m->ephemeral_key,
1022 sizeof(m->ephemeral_key)))
1023 {
1025 gettext_noop (
1026 "# duplicate ephemeral keys. Not verifying."),
1027 1,
1028 GNUNET_NO);
1030 "Duplicate EPHEMERAL_KEY from %s, do not verify\n",
1031 GNUNET_i2s (&m->origin_identity));
1032 do_verify = GNUNET_NO;
1033 }
1034 if (0 != memcmp (&m->origin_identity,
1035 kx->peer,
1036 sizeof(struct GNUNET_PeerIdentity)))
1037 {
1039 "Received EPHEMERAL_KEY from %s, but expected %s\n",
1040 GNUNET_i2s (&m->origin_identity),
1041 GNUNET_i2s_full (kx->peer));
1042 GNUNET_break_op (0);
1043 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1044 return;
1045 }
1046 if (do_verify && ((ntohl (m->purpose.size) !=
1048 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1049 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1050 + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
1051 + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) ||
1052 (GNUNET_OK !=
1055 &m->purpose,
1056 &m->signature,
1057 &m->origin_identity.public_key
1058 ))))
1059 {
1060 /* invalid signature */
1061 GNUNET_break_op (0);
1063 gettext_noop (
1064 "# EPHEMERAL_KEYs rejected (bad signature)"),
1065 1,
1066 GNUNET_NO);
1068 "Received EPHEMERAL_KEY from %s with bad signature\n",
1069 GNUNET_i2s (&m->origin_identity));
1070 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1071 return;
1072 }
1073 now = GNUNET_TIME_absolute_get ();
1074 start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
1075 if ((end_t.abs_value_us <
1077 (start_t.abs_value_us >
1079 {
1080 GNUNET_log (
1082 _ (
1083 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"),
1084 GNUNET_i2s (kx->peer),
1085 (unsigned long long) now.abs_value_us,
1086 (unsigned long long) start_t.abs_value_us,
1087 (unsigned long long) end_t.abs_value_us);
1089 gettext_noop (
1090 "# EPHEMERAL_KEY messages rejected due to time")
1091 ,
1092 1,
1093 GNUNET_NO);
1094 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1095 return;
1096 }
1097#if DEBUG_KX
1098 {
1099 struct GNUNET_HashCode eh;
1100
1101 GNUNET_CRYPTO_hash (&m->ephemeral_key, sizeof(m->ephemeral_key), &eh);
1103 "Received valid EPHEMERAL_KEY `%s' from `%s' in state %d.\n",
1104 GNUNET_h2s (&eh),
1105 GNUNET_i2s (kx->peer),
1106 kx->status);
1107 }
1108#endif
1110 gettext_noop ("# valid ephemeral keys received"),
1111 1,
1112 GNUNET_NO);
1113 kx->other_ephemeral_key = m->ephemeral_key;
1114 kx->foreign_key_expires = end_t;
1116
1117 /* check if we still need to send the sender our key */
1118 sender_status = (enum GNUNET_CORE_KxState) ntohl (m->sender_status);
1119 switch (sender_status)
1120 {
1122 GNUNET_break_op (0);
1123 break;
1124
1126 /* fine, need to send our key after updating our status, see below */
1128 break;
1129
1131 /* other peer already got our key, but typemap did go down */
1133 break;
1134
1136 /* other peer already got our key, typemap NOT down */
1137 break;
1138
1140 /* other peer already got our key, typemap NOT down */
1141 break;
1142
1143 default:
1144 GNUNET_break (0);
1145 break;
1146 }
1147 /* check if we need to confirm everything is fine via PING + PONG */
1148 switch (kx->status)
1149 {
1151 GNUNET_assert (NULL == kx->keep_alive_task);
1153 monitor_notify_all (kx);
1154 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1155 send_key (kx);
1156 else
1157 send_ping (kx);
1158 break;
1159
1161 GNUNET_assert (NULL == kx->keep_alive_task);
1163 monitor_notify_all (kx);
1164 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1165 send_key (kx);
1166 else
1167 send_ping (kx);
1168 break;
1169
1171 GNUNET_assert (NULL == kx->keep_alive_task);
1172 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1173 send_key (kx);
1174 else
1175 send_ping (kx);
1176 break;
1177
1180 monitor_notify_all (kx);
1181 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1182 send_key (kx);
1183 else
1184 send_ping (kx);
1185 break;
1186
1188 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1189 send_key (kx);
1190 else
1191 send_ping (kx);
1192 break;
1193
1194 default:
1195 GNUNET_break (0);
1196 break;
1197 }
1198 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1199}
#define REKEY_TOLERANCE
What time difference do we tolerate?
static void derive_session_keys(struct GSC_KeyExchangeInfo *kx)
Derive fresh session keys from the current ephemeral keys.
static struct GNUNET_TRANSPORT_CoreHandle * transport
Transport service.
void GSC_SESSIONS_reinit(const struct GNUNET_PeerIdentity *peer)
The other peer has indicated that it 'lost' the session (KX down), reinitialize the session on our en...
GNUNET_CORE_KxState
State machine for our P2P encryption handshake.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Verify EdDSA signature.
Definition: crypto_ecc.c:708
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_YES
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:737
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Subtract a given relative duration from the given start time.
Definition: time.c:469
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:450
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY
Purpose is to set a session key.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
struct GNUNET_TIME_Absolute foreign_key_expires
At what time did the other peer generate the decryption key?

References _, GNUNET_TIME_Absolute::abs_value_us, derive_session_keys(), GSC_KeyExchangeInfo::foreign_key_expires, gettext_noop, GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CORE_KX_STATE_DOWN, GNUNET_CORE_KX_STATE_KEY_RECEIVED, GNUNET_CORE_KX_STATE_KEY_SENT, GNUNET_CORE_KX_STATE_REKEY_SENT, GNUNET_CORE_KX_STATE_UP, GNUNET_CRYPTO_eddsa_verify_(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_h2s(), GNUNET_i2s(), GNUNET_i2s_full(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY, GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_add(), GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_absolute_subtract(), GNUNET_YES, GSC_SESSIONS_reinit(), GSC_stats, GSC_KeyExchangeInfo::keep_alive_task, m, monitor_notify_all(), GSC_KeyExchangeInfo::other_ephemeral_key, GSC_KeyExchangeInfo::peer, REKEY_TOLERANCE, send_key(), send_ping(), GSC_KeyExchangeInfo::status, and transport.

Here is the call graph for this function:

◆ send_keep_alive()

static void send_keep_alive ( void *  cls)
static

Task triggered when a neighbour entry is about to time out (and we should prevent this by sending a PING).

Parameters
clsthe struct GSC_KeyExchangeInfo

Definition at line 1340 of file gnunet-service-core_kx.c.

1341{
1342 struct GSC_KeyExchangeInfo *kx = cls;
1343 struct GNUNET_TIME_Relative retry;
1344 struct GNUNET_TIME_Relative left;
1345
1346 kx->keep_alive_task = NULL;
1348 if (0 == left.rel_value_us)
1349 {
1351 gettext_noop ("# sessions terminated by timeout"),
1352 1,
1353 GNUNET_NO);
1354 GSC_SESSIONS_end (kx->peer);
1356 monitor_notify_all (kx);
1357 send_key (kx);
1358 return;
1359 }
1361 "Sending KEEPALIVE to `%s'\n",
1362 GNUNET_i2s (kx->peer));
1364 gettext_noop ("# keepalive messages sent"),
1365 1,
1366 GNUNET_NO);
1367 setup_fresh_ping (kx);
1368 send_ping (kx);
1371 kx->keep_alive_task =
1373}
#define MIN_PING_FREQUENCY
What is the minimum frequency for a PING message?
static void send_keep_alive(void *cls)
Task triggered when a neighbour entry is about to time out (and we should prevent this by sending a P...
struct GNUNET_TIME_Relative GNUNET_TIME_relative_max(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the maximum of two relative time values.
Definition: time.c:351
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:405
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:550
Time for relative time used by GNUnet, in microseconds.

References gettext_noop, GNUNET_CORE_KX_STATE_KEY_SENT, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_max(), GSC_SESSIONS_end(), GSC_stats, GSC_KeyExchangeInfo::keep_alive_task, MIN_PING_FREQUENCY, monitor_notify_all(), GSC_KeyExchangeInfo::peer, GNUNET_TIME_Relative::rel_value_us, send_keep_alive(), send_key(), send_ping(), setup_fresh_ping(), GSC_KeyExchangeInfo::status, and GSC_KeyExchangeInfo::timeout.

Referenced by handle_ping(), send_keep_alive(), and update_timeout().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_ping()

static void handle_ping ( void *  cls,
const struct PingMessage m 
)
static

We received a PING message.

Validate and transmit a PONG message.

Parameters
clskey exchange status for the corresponding peer
mthe encrypted PING message itself

Definition at line 1214 of file gnunet-service-core_kx.c.

1215{
1216 struct GSC_KeyExchangeInfo *kx = cls;
1217 struct PingMessage t;
1218 struct PongMessage tx;
1219 struct PongMessage *tp;
1220 struct GNUNET_MQ_Envelope *env;
1221
1223 gettext_noop ("# PING messages received"),
1224 1,
1225 GNUNET_NO);
1229 {
1230 /* ignore */
1232 gettext_noop (
1233 "# PING messages dropped (out of order)"),
1234 1,
1235 GNUNET_NO);
1236 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1237 return;
1238 }
1240 "Core service receives PING request from `%s'.\n",
1241 GNUNET_i2s (kx->peer));
1242#if CONG_CRYPTO_ENABLED
1243 if (0 != crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
1244 (unsigned char*) &t.target,
1245 NULL,
1246 (unsigned char*) &m->target,
1247 sizeof (m->target) + sizeof (m->challenge),
1248 m->tag,
1249 NULL, 0,
1250 m->nonce,
1251 kx->decrypt_key))
1252 {
1253 GNUNET_break_op (0);
1254 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1255 return;
1256 }
1257#else
1259 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1260 if (GNUNET_OK != do_decrypt (kx,
1261 &iv,
1262 &m->target,
1263 &t.target,
1264 sizeof(struct PingMessage)
1265 - ((void *) &m->target - (void *) m)))
1266 {
1267 GNUNET_break_op (0);
1268 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1269 return;
1270 }
1271#endif
1272 if (0 !=
1273 memcmp (&t.target, &GSC_my_identity, sizeof(struct GNUNET_PeerIdentity)))
1274 {
1277 "Decryption of PING from peer `%s' failed, PING for `%s'?\n",
1278 GNUNET_i2s (kx->peer),
1279 GNUNET_i2s2 (&t.target));
1280 else
1281 GNUNET_log (
1283 "Decryption of PING from peer `%s' failed after rekey (harmless)\n",
1284 GNUNET_i2s (kx->peer));
1285 GNUNET_break_op (0);
1286 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1287 return;
1288 }
1289 /* construct PONG */
1290 tx.reserved = 0;
1291 tx.challenge = t.challenge;
1292 tx.target = t.target;
1294#if CONG_CRYPTO_ENABLED
1295 randombytes_buf (tp->nonce, sizeof (tp->nonce));
1296 GNUNET_assert (0 ==
1297 crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
1298 (unsigned char*) &tp->challenge,
1299 tp->tag,
1300 NULL,
1301 (unsigned char*) &tx.challenge,
1302 sizeof(struct PongMessage)
1303 - ((void *) &tp->challenge - (void *) tp),
1304 NULL, 0,
1305 NULL,
1306 tp->nonce,
1307 kx->encrypt_key));
1308#else
1309 tp->iv_seed = calculate_seed (kx);
1310 derive_pong_iv (&iv, &kx->encrypt_key, tp->iv_seed, t.challenge, kx->peer);
1311 do_encrypt (kx,
1312 &iv,
1313 &tx.challenge,
1314 &tp->challenge,
1315 sizeof(struct PongMessage)
1316 - ((void *) &tp->challenge - (void *) tp));
1317#endif
1319 gettext_noop ("# PONG messages created"),
1320 1,
1321 GNUNET_NO);
1322 GNUNET_MQ_send (kx->mq, env);
1323 if (NULL != kx->keep_alive_task)
1324 {
1327 send_keep_alive, kx);
1328 }
1329 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1330}
static int do_decrypt(struct GSC_KeyExchangeInfo *kx, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const void *in, void *out, size_t size)
Decrypt size bytes from in and write the result to out.
static void derive_pong_iv(struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, uint32_t seed, uint32_t challenge, const struct GNUNET_PeerIdentity *identity)
Derive an IV from pong packet information.
static struct GNUNET_SCHEDULER_Task * t
Main task.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:78
#define GNUNET_MESSAGE_TYPE_CORE_PONG
Confirmation that other peer is alive.
Response to a PING.
uint32_t challenge
Random number to make replay attacks harder.
uint32_t iv_seed
Seed for the IV.

References calculate_seed(), PongMessage::challenge, GSC_KeyExchangeInfo::decrypt_key, derive_iv(), derive_pong_iv(), do_decrypt(), do_encrypt(), GSC_KeyExchangeInfo::encrypt_key, env, gettext_noop, GNUNET_assert, GNUNET_break_op, GNUNET_CORE_KX_STATE_KEY_RECEIVED, GNUNET_CORE_KX_STATE_REKEY_SENT, GNUNET_CORE_KX_STATE_UP, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_i2s(), GNUNET_i2s2(), GNUNET_log, GNUNET_MESSAGE_TYPE_CORE_PONG, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GSC_my_identity, GSC_stats, PongMessage::iv_seed, GSC_KeyExchangeInfo::keep_alive_task, m, MIN_PING_FREQUENCY, GSC_KeyExchangeInfo::mq, GSC_KeyExchangeInfo::peer, PongMessage::reserved, send_keep_alive(), GSC_KeyExchangeInfo::status, t, PongMessage::target, and transport.

Here is the call graph for this function:

◆ update_timeout()

static void update_timeout ( struct GSC_KeyExchangeInfo kx)
static

We've seen a valid message from the other peer.

Update the time when the session would time out and delay sending our keep alive message further.

Parameters
kxkey exchange where we saw activity

Definition at line 1384 of file gnunet-service-core_kx.c.

1385{
1387
1388 kx->timeout =
1390 delta =
1392 if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
1393 {
1394 /* we only notify monitors about timeout changes if those
1395 are bigger than the threshold (5s) */
1396 monitor_notify_all (kx);
1397 }
1398 if (NULL != kx->keep_alive_task)
1403 kx);
1404}
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
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_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition: time.c:421
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
uint64_t rel_value_us
The actual value.

References delta, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_TIME_absolute_get_difference(), GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_to_absolute(), GSC_KeyExchangeInfo::keep_alive_task, GSC_KeyExchangeInfo::last_notify_timeout, monitor_notify_all(), GNUNET_TIME_Relative::rel_value_us, send_keep_alive(), and GSC_KeyExchangeInfo::timeout.

Referenced by handle_encrypted(), and handle_pong().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_pong()

static void handle_pong ( void *  cls,
const struct PongMessage m 
)
static

We received a PONG message.

Validate and update our status.

Parameters
kxkey exchange context for the the PONG
mthe encrypted PONG message itself

Definition at line 1414 of file gnunet-service-core_kx.c.

1415{
1416 struct GSC_KeyExchangeInfo *kx = cls;
1417 struct PongMessage t;
1418
1420 gettext_noop ("# PONG messages received"),
1421 1,
1422 GNUNET_NO);
1423 switch (kx->status)
1424 {
1427 gettext_noop (
1428 "# PONG messages dropped (connection down)"),
1429 1,
1430 GNUNET_NO);
1431 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1432 return;
1433
1436 gettext_noop (
1437 "# PONG messages dropped (out of order)"),
1438 1,
1439 GNUNET_NO);
1440 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1441 return;
1442
1444 break;
1445
1447 break;
1448
1450 break;
1451
1452 default:
1453 GNUNET_break (0);
1454 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1455 return;
1456 }
1458 "Core service receives PONG response from `%s'.\n",
1459 GNUNET_i2s (kx->peer));
1460 /* mark as garbage, just to be sure */
1461 memset (&t, 255, sizeof(t));
1462#if CONG_CRYPTO_ENABLED
1463 if (0 != crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
1464 (unsigned char*) &t.challenge,
1465 NULL,
1466 (unsigned char*) &m->challenge,
1467 sizeof(struct PongMessage)
1468 - ((void *) &m->challenge - (void *) m),
1469 m->tag,
1470 NULL, 0,
1471 m->nonce,
1472 kx->decrypt_key))
1473 {
1474 GNUNET_break_op (0);
1475 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1476 return;
1477 }
1478#else
1480 derive_pong_iv (&iv,
1481 &kx->decrypt_key,
1482 m->iv_seed,
1483 kx->ping_challenge,
1485 if (GNUNET_OK != do_decrypt (kx,
1486 &iv,
1487 &m->challenge,
1488 &t.challenge,
1489 sizeof(struct PongMessage)
1490 - ((void *) &m->challenge - (void *) m)))
1491 {
1492 GNUNET_break_op (0);
1493 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1494 return;
1495 }
1496#endif
1498 gettext_noop ("# PONG messages decrypted"),
1499 1,
1500 GNUNET_NO);
1501 if ((0 !=
1502 memcmp (&t.target, kx->peer, sizeof(struct GNUNET_PeerIdentity))) ||
1503 (kx->ping_challenge != t.challenge))
1504 {
1505 /* PONG malformed */
1507 "Received malformed PONG wanted sender `%s' with challenge %u\n",
1508 GNUNET_i2s (kx->peer),
1509 (unsigned int) kx->ping_challenge);
1511 "Received malformed PONG received from `%s' with challenge %u\n",
1512 GNUNET_i2s (&t.target),
1513 (unsigned int) t.challenge);
1514 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1515 return;
1516 }
1518 "Received valid PONG from `%s'\n",
1519 GNUNET_i2s (kx->peer));
1520 /* no need to resend key any longer */
1521 if (NULL != kx->retry_set_key_task)
1522 {
1524 kx->retry_set_key_task = NULL;
1525 }
1526 switch (kx->status)
1527 {
1529 GNUNET_assert (0); /* should be impossible */
1530 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1531 return;
1532
1534 GNUNET_assert (0); /* should be impossible */
1535 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1536 return;
1537
1540 gettext_noop (
1541 "# session keys confirmed via PONG"),
1542 1,
1543 GNUNET_NO);
1545 monitor_notify_all (kx);
1546 GSC_SESSIONS_create (kx->peer, kx);
1547 GNUNET_assert (NULL == kx->keep_alive_task);
1548 update_timeout (kx);
1549 break;
1550
1553 gettext_noop ("# timeouts prevented via PONG"),
1554 1,
1555 GNUNET_NO);
1556 update_timeout (kx);
1557 break;
1558
1561 gettext_noop (
1562 "# rekey operations confirmed via PONG"),
1563 1,
1564 GNUNET_NO);
1566 monitor_notify_all (kx);
1567 update_timeout (kx);
1568 break;
1569
1570 default:
1571 GNUNET_break (0);
1572 break;
1573 }
1574 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1575}
static void update_timeout(struct GSC_KeyExchangeInfo *kx)
We've seen a valid message from the other peer.
void GSC_SESSIONS_create(const struct GNUNET_PeerIdentity *peer, struct GSC_KeyExchangeInfo *kx)
Create a session, a key exchange was just completed.

References GSC_KeyExchangeInfo::decrypt_key, derive_pong_iv(), do_decrypt(), gettext_noop, GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CORE_KX_STATE_DOWN, GNUNET_CORE_KX_STATE_KEY_RECEIVED, GNUNET_CORE_KX_STATE_KEY_SENT, GNUNET_CORE_KX_STATE_REKEY_SENT, GNUNET_CORE_KX_STATE_UP, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GSC_my_identity, GSC_SESSIONS_create(), GSC_stats, GSC_KeyExchangeInfo::keep_alive_task, m, monitor_notify_all(), GSC_KeyExchangeInfo::peer, GSC_KeyExchangeInfo::ping_challenge, GSC_KeyExchangeInfo::retry_set_key_task, GSC_KeyExchangeInfo::status, t, transport, and update_timeout().

Here is the call graph for this function:

◆ GSC_KX_encrypt_and_transmit()

void GSC_KX_encrypt_and_transmit ( struct GSC_KeyExchangeInfo kx,
const void *  payload,
size_t  payload_size 
)

Encrypt and transmit a message with the given payload.

Parameters
kxkey exchange context
payloadpayload of the message
payload_sizenumber of bytes in 'payload'

Definition at line 1622 of file gnunet-service-core_kx.c.

1625{
1626 size_t used = payload_size + sizeof(struct EncryptedMessage);
1627 char pbuf[used]; /* plaintext */
1628 struct EncryptedMessage *em; /* encrypted message */
1629 struct EncryptedMessage *ph; /* plaintext header */
1630 struct GNUNET_MQ_Envelope *env;
1631
1632 ph = (struct EncryptedMessage *) pbuf;
1633 ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1634 ph->reserved = 0;
1636 GNUNET_memcpy (&ph[1], payload, payload_size);
1638 payload_size,
1640#if CONG_CRYPTO_ENABLED
1641 randombytes_buf (ph->nonce, sizeof (ph->nonce));
1642 GNUNET_assert (0 ==
1643 crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
1644 (unsigned char*) &em->sequence_number,
1645 em->tag,
1646 NULL,
1647 (unsigned char*) &ph->sequence_number,
1648 used - ENCRYPTED_HEADER_SIZE,
1649 NULL, 0,
1650 NULL,
1651 ph->nonce,
1652 kx->encrypt_key));
1653#else
1655 struct GNUNET_CRYPTO_AuthKey auth_key;
1656 ph->iv_seed = calculate_seed (kx);
1657 em->iv_seed = ph->iv_seed;
1658 derive_iv (&iv, &kx->encrypt_key, ph->iv_seed, kx->peer);
1660 &iv,
1661 &ph->sequence_number,
1662 &em->sequence_number,
1663 used - ENCRYPTED_HEADER_SIZE));
1664#if DEBUG_KX
1665 {
1666 struct GNUNET_HashCode hc;
1667
1669 used - ENCRYPTED_HEADER_SIZE,
1670 &hc);
1672 "Encrypted payload `%s' of %u bytes for %s\n",
1673 GNUNET_h2s (&hc),
1674 (unsigned int) (used - ENCRYPTED_HEADER_SIZE),
1675 GNUNET_i2s (kx->peer));
1676 }
1677#endif
1678 derive_auth_key (&auth_key, &kx->encrypt_key, ph->iv_seed);
1679 GNUNET_CRYPTO_hmac (&auth_key,
1680 &em->sequence_number,
1681 used - ENCRYPTED_HEADER_SIZE,
1682 &em->hmac);
1683#if DEBUG_KX
1684 {
1685 struct GNUNET_HashCode hc;
1686
1687 GNUNET_CRYPTO_hash (&auth_key, sizeof(auth_key), &hc);
1689 "For peer %s, used AC %s to create hmac %s\n",
1690 GNUNET_i2s (kx->peer),
1691 GNUNET_h2s (&hc),
1692 GNUNET_h2s2 (&em->hmac));
1693 }
1694#endif
1695#endif
1697 GNUNET_MQ_send (kx->mq, env);
1698}
#define ENCRYPTED_HEADER_SIZE
Number of bytes (at the beginning) of struct EncryptedMessage that are NOT encrypted.
static void derive_auth_key(struct GNUNET_CRYPTO_AuthKey *akey, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, uint32_t seed)
Derive an authentication key from "set key" information.
static unsigned long long payload
How much data are we currently storing in the database?
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
Definition: crypto_hash.c:330
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
const char * GNUNET_h2s2(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
#define GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE
Encapsulation for an encrypted message between peers.
Encapsulation for encrypted messages exchanged between peers.
uint32_t iv_seed
Random value used for IV generation.
struct GNUNET_TIME_AbsoluteNBO timestamp
Timestamp.
uint32_t sequence_number
Sequence number, in network byte order.
struct GNUNET_HashCode hmac
MAC of the encrypted message (starting at sequence_number), used to verify message integrity.
uint32_t reserved
Reserved, always zero.
type for (message) authentication keys
uint32_t last_sequence_number_sent
last sequence number transmitted
int has_excess_bandwidth
GNUNET_YES if this peer currently has excess bandwidth.

References calculate_seed(), derive_auth_key(), derive_iv(), do_encrypt(), GSC_KeyExchangeInfo::encrypt_key, ENCRYPTED_HEADER_SIZE, env, GNUNET_assert, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_hmac(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_h2s(), GNUNET_h2s2(), GNUNET_i2s(), GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_OK, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_hton(), GSC_KeyExchangeInfo::has_excess_bandwidth, EncryptedMessage::hmac, EncryptedMessage::iv_seed, GSC_KeyExchangeInfo::last_sequence_number_sent, GSC_KeyExchangeInfo::mq, payload, GSC_KeyExchangeInfo::peer, EncryptedMessage::reserved, EncryptedMessage::sequence_number, and EncryptedMessage::timestamp.

Referenced by transmit_typemap_task(), and try_transmission().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_encrypted()

static int check_encrypted ( void *  cls,
const struct EncryptedMessage m 
)
static

We received an encrypted message.

Check that it is well-formed (size-wise).

Parameters
clskey exchange context for encrypting the message
mencrypted message
Returns
GNUNET_OK if msg is well-formed (size-wise)

Definition at line 1710 of file gnunet-service-core_kx.c.

1711{
1712 uint16_t size = ntohs (m->header.size) - sizeof(*m);
1713
1714 if (size < sizeof(struct GNUNET_MessageHeader))
1715 {
1716 GNUNET_break_op (0);
1717 return GNUNET_SYSERR;
1718 }
1719 return GNUNET_OK;
1720}

References GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, m, and size.

◆ handle_encrypted()

static void handle_encrypted ( void *  cls,
const struct EncryptedMessage m 
)
static

We received an encrypted message.

Decrypt, validate and pass on to the appropriate clients.

Parameters
clskey exchange context for encrypting the message
mencrypted message

Definition at line 1731 of file gnunet-service-core_kx.c.

1732{
1733 struct GSC_KeyExchangeInfo *kx = cls;
1734 struct EncryptedMessage *pt; /* plaintext */
1735 uint32_t snum;
1736 struct GNUNET_TIME_Absolute t;
1737 uint16_t size = ntohs (m->header.size);
1738 char buf[size] GNUNET_ALIGN;
1739
1741 {
1743 gettext_noop (
1744 "# DATA message dropped (out of order)"),
1745 1,
1746 GNUNET_NO);
1747 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1748 return;
1749 }
1750 if (0 ==
1752 {
1753 GNUNET_log (
1755 _ (
1756 "Session to peer `%s' went down due to key expiration (should not happen)\n"),
1757 GNUNET_i2s (kx->peer));
1759 gettext_noop (
1760 "# sessions terminated by key expiration"),
1761 1,
1762 GNUNET_NO);
1763 GSC_SESSIONS_end (kx->peer);
1764 if (NULL != kx->keep_alive_task)
1765 {
1767 kx->keep_alive_task = NULL;
1768 }
1770 monitor_notify_all (kx);
1771 send_key (kx);
1772 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1773 return;
1774 }
1775
1776 /* validate hash */
1777#if DEBUG_KX
1778 {
1779 struct GNUNET_HashCode hc;
1780
1781 GNUNET_CRYPTO_hash (&m->sequence_number, size - ENCRYPTED_HEADER_SIZE, &hc);
1783 "Received encrypted payload `%s' of %u bytes from %s\n",
1784 GNUNET_h2s (&hc),
1785 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1786 GNUNET_i2s (kx->peer));
1787 }
1788#endif
1789
1790#if CONG_CRYPTO_ENABLED
1791 if (0 != crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
1792 (unsigned char*) &buf[ENCRYPTED_HEADER_SIZE],
1793 NULL,
1794 (unsigned char*) &m->sequence_number,
1796 m->tag,
1797 NULL, 0,
1798 m->nonce,
1799 kx->decrypt_key))
1800 {
1801 GNUNET_break_op (0);
1802 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1803 return;
1804 }
1805#else
1807 struct GNUNET_CRYPTO_AuthKey auth_key;
1808 struct GNUNET_HashCode ph;
1809 derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed);
1810 GNUNET_CRYPTO_hmac (&auth_key,
1811 &m->sequence_number,
1813 &ph);
1814#if DEBUG_KX
1815 {
1816 struct GNUNET_HashCode hc;
1817
1818 GNUNET_CRYPTO_hash (&auth_key, sizeof(auth_key), &hc);
1820 "For peer %s, used AC %s to verify hmac %s\n",
1821 GNUNET_i2s (kx->peer),
1822 GNUNET_h2s (&hc),
1823 GNUNET_h2s2 (&m->hmac));
1824 }
1825#endif
1826 if (0 != memcmp (&ph, &m->hmac, sizeof(struct GNUNET_HashCode)))
1827 {
1828 /* checksum failed */
1830 "Failed checksum validation for a message from `%s'\n",
1831 GNUNET_i2s (kx->peer));
1832 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1833 return;
1834 }
1835 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1836 /* decrypt */
1837 if (GNUNET_OK != do_decrypt (kx,
1838 &iv,
1839 &m->sequence_number,
1842 {
1843 GNUNET_break_op (0);
1844 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1845 return;
1846 }
1847#endif
1849 "Decrypted %u bytes from %s\n",
1850 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1851 GNUNET_i2s (kx->peer));
1852 pt = (struct EncryptedMessage *) buf;
1853
1854 /* validate sequence number */
1855 snum = ntohl (pt->sequence_number);
1856 if (kx->last_sequence_number_received == snum)
1857 {
1859 "Received duplicate message, ignoring.\n");
1860 /* duplicate, ignore */
1862 gettext_noop ("# bytes dropped (duplicates)"),
1863 size,
1864 GNUNET_NO);
1865 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1866 return;
1867 }
1868 if ((kx->last_sequence_number_received > snum) &&
1869 (kx->last_sequence_number_received - snum > 32))
1870 {
1872 "Received ancient out of sequence message, ignoring.\n");
1873 /* ancient out of sequence, ignore */
1875 gettext_noop (
1876 "# bytes dropped (out of sequence)"),
1877 size,
1878 GNUNET_NO);
1879 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1880 return;
1881 }
1882 if (kx->last_sequence_number_received > snum)
1883 {
1884 uint32_t rotbit = 1U << (kx->last_sequence_number_received - snum - 1);
1885
1886 if ((kx->last_packets_bitmap & rotbit) != 0)
1887 {
1889 "Received duplicate message, ignoring.\n");
1891 gettext_noop ("# bytes dropped (duplicates)"),
1892 size,
1893 GNUNET_NO);
1894 /* duplicate, ignore */
1895 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1896 return;
1897 }
1898 kx->last_packets_bitmap |= rotbit;
1899 }
1900 if (kx->last_sequence_number_received < snum)
1901 {
1902 unsigned int shift = (snum - kx->last_sequence_number_received);
1903
1904 if (shift >= 8 * sizeof(kx->last_packets_bitmap))
1905 kx->last_packets_bitmap = 0;
1906 else
1907 kx->last_packets_bitmap <<= shift;
1909 }
1910
1911 /* check timestamp */
1913 if (GNUNET_TIME_absolute_get_duration (t).rel_value_us >
1914 MAX_MESSAGE_AGE.rel_value_us)
1915 {
1917 "Message received far too old (%s). Content ignored.\n",
1920 GNUNET_YES));
1922 gettext_noop (
1923 "# bytes dropped (ancient message)"),
1924 size,
1925 GNUNET_NO);
1926 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1927 return;
1928 }
1929
1930 /* process decrypted message(s) */
1931 update_timeout (kx);
1933 gettext_noop ("# bytes of payload decrypted"),
1934 size - sizeof(struct EncryptedMessage),
1935 GNUNET_NO);
1936 if (GNUNET_OK !=
1938 &buf[sizeof(struct EncryptedMessage)],
1939 size - sizeof(struct EncryptedMessage),
1940 GNUNET_YES,
1941 GNUNET_NO))
1942 GNUNET_break_op (0);
1943
1944 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1945}
#define MAX_MESSAGE_AGE
What is the maximum age of a message for us to consider processing it? Note that this looks at the ti...
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
enum GNUNET_GenericReturnValue GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:101
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:436
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:570

References _, GSC_KeyExchangeInfo::decrypt_key, derive_auth_key(), derive_iv(), do_decrypt(), ENCRYPTED_HEADER_SIZE, GSC_KeyExchangeInfo::foreign_key_expires, gettext_noop, GNUNET_ALIGN, GNUNET_break_op, GNUNET_CORE_KX_STATE_KEY_SENT, GNUNET_CORE_KX_STATE_UP, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_hmac(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_h2s(), GNUNET_h2s2(), GNUNET_i2s(), GNUNET_log, GNUNET_MST_from_buffer(), GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_ntoh(), GNUNET_YES, GSC_my_identity, GSC_SESSIONS_end(), GSC_stats, GSC_KeyExchangeInfo::keep_alive_task, GSC_KeyExchangeInfo::last_packets_bitmap, GSC_KeyExchangeInfo::last_sequence_number_received, m, MAX_MESSAGE_AGE, monitor_notify_all(), GSC_KeyExchangeInfo::mst, GSC_KeyExchangeInfo::peer, GNUNET_TIME_Relative::rel_value_us, send_key(), EncryptedMessage::sequence_number, size, GSC_KeyExchangeInfo::status, t, EncryptedMessage::timestamp, transport, and update_timeout().

Here is the call graph for this function:

◆ sign_ephemeral_key()

static void sign_ephemeral_key ( )
static

Setup the message that links the ephemeral key to our persistent public key and generate the appropriate signature.

Definition at line 1953 of file gnunet-service-core_kx.c.

1954{
1955 current_ekm.header.size = htons (sizeof(struct EphemeralKeyMessage));
1957 current_ekm.sender_status = 0; /* to be set later */
1960 htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
1961 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1962 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1963 + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
1964 + sizeof(struct GNUNET_PeerIdentity));
1968 "core",
1969 "USE_EPHEMERAL_KEYS"))
1970 {
1974 REKEY_TOLERANCE)));
1975 }
1976 else
1977 {
1980 }
1988}
const struct GNUNET_CONFIGURATION_Handle * GSC_cfg
Our configuration.
static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key
Our private key.
#define REKEY_FREQUENCY
How often do we rekey?
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
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
void GNUNET_CRYPTO_ecdhe_key_get_public(const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, struct GNUNET_CRYPTO_EcdhePublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:217
#define GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY
Session key exchange between peers.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition: time.c:585
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
Message transmitted with the signed ephemeral key of a peer.
struct GNUNET_PeerIdentity origin_identity
Public key of the signing peer (persistent version, not the ephemeral public key).
struct GNUNET_TIME_AbsoluteNBO expiration_time
When does the given ephemeral key expire (end of validity).
struct GNUNET_CRYPTO_EddsaSignature signature
An ECC signature of the origin_identity asserting the validity of the given ephemeral key.
struct GNUNET_TIME_AbsoluteNBO creation_time
At what time was this key created (beginning of validity).
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Information about what is being signed.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...

References EphemeralKeyMessage::creation_time, current_ekm, EphemeralKeyMessage::ephemeral_key, EphemeralKeyMessage::expiration_time, GNUNET_assert, GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CRYPTO_ecdhe_key_get_public(), GNUNET_CRYPTO_eddsa_sign_(), GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY, GNUNET_OK, GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_relative_add(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_YES, GSC_cfg, GSC_my_identity, EphemeralKeyMessage::header, my_ephemeral_key, my_private_key, EphemeralKeyMessage::origin_identity, EphemeralKeyMessage::purpose, GNUNET_CRYPTO_EccSignaturePurpose::purpose, REKEY_FREQUENCY, REKEY_TOLERANCE, EphemeralKeyMessage::sender_status, EphemeralKeyMessage::signature, GNUNET_MessageHeader::size, GNUNET_CRYPTO_EccSignaturePurpose::size, and GNUNET_MessageHeader::type.

Referenced by do_rekey(), and GSC_KX_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_rekey()

static void do_rekey ( void *  cls)
static

Task run to trigger rekeying.

Parameters
clsclosure, NULL

Definition at line 1997 of file gnunet-service-core_kx.c.

1998{
1999 struct GSC_KeyExchangeInfo *pos;
2000
2001 (void) cls;
2005 {
2006 struct GNUNET_HashCode eh;
2007
2009 sizeof(current_ekm.ephemeral_key),
2010 &eh);
2011 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Rekeying to %s\n", GNUNET_h2s (&eh));
2012 }
2013 for (pos = kx_head; NULL != pos; pos = pos->next)
2014 {
2015 if (GNUNET_CORE_KX_STATE_UP == pos->status)
2016 {
2018 derive_session_keys (pos);
2019 }
2020 else if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
2021 {
2023 }
2024 monitor_notify_all (pos);
2025 send_key (pos);
2026 }
2027}
static void sign_ephemeral_key()
Setup the message that links the ephemeral key to our persistent public key and generate the appropri...
static void do_rekey(void *cls)
Task run to trigger rekeying.
static struct GNUNET_SCHEDULER_Task * rekey_task
Task scheduled for periodic re-generation (and thus rekeying) of our ephemeral key.
void GNUNET_CRYPTO_ecdhe_key_create(struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
Create a new private key.
Definition: crypto_ecc.c:454
@ GNUNET_ERROR_TYPE_INFO
struct GSC_KeyExchangeInfo * next
DLL.

References current_ekm, derive_session_keys(), do_rekey(), EphemeralKeyMessage::ephemeral_key, GNUNET_CORE_KX_STATE_DOWN, GNUNET_CORE_KX_STATE_KEY_SENT, GNUNET_CORE_KX_STATE_REKEY_SENT, GNUNET_CORE_KX_STATE_UP, GNUNET_CRYPTO_ecdhe_key_create(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_INFO, GNUNET_h2s(), GNUNET_log, GNUNET_SCHEDULER_add_delayed(), kx_head, monitor_notify_all(), my_ephemeral_key, GSC_KeyExchangeInfo::next, REKEY_FREQUENCY, rekey_task, send_key(), sign_ephemeral_key(), and GSC_KeyExchangeInfo::status.

Referenced by do_rekey(), and GSC_KX_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GSC_KX_init()

int GSC_KX_init ( struct GNUNET_CRYPTO_EddsaPrivateKey pk)

Initialize KX subsystem.

Parameters
pkprivate key to use for the peer
Returns
GNUNET_OK on success, GNUNET_SYSERR on failure

Definition at line 2037 of file gnunet-service-core_kx.c.

2038{
2040 GNUNET_MQ_hd_fixed_size (ephemeral_key,
2042 struct EphemeralKeyMessage,
2043 NULL),
2046 struct PingMessage,
2047 NULL),
2050 struct PongMessage,
2051 NULL),
2052 GNUNET_MQ_hd_var_size (encrypted,
2054 struct EncryptedMessage,
2055 NULL),
2057 };
2058
2059 my_private_key = *pk;
2064 {
2065 struct GNUNET_HashCode eh;
2066
2068 sizeof(current_ekm.ephemeral_key),
2069 &eh);
2071 "Starting with ephemeral key %s\n",
2072 GNUNET_h2s (&eh));
2073 }
2074
2077 transport =
2080 handlers,
2081 NULL,
2084 if (NULL == transport)
2085 {
2086 GSC_KX_done ();
2087 return GNUNET_SYSERR;
2088 }
2089 return GNUNET_OK;
2090}
struct GNUNET_MQ_MessageHandlers handlers[]
Definition: 003.c:1
struct GNUNET_CRYPTO_PrivateKey pk
Private key from command line option, or NULL.
static void handle_transport_notify_disconnect(void *cls, const struct GNUNET_PeerIdentity *peer, void *handler_cls)
Function called by transport telling us that a peer disconnected.
void GSC_KX_done()
Shutdown KX subsystem.
static void * handle_transport_notify_connect(void *cls, const struct GNUNET_PeerIdentity *pid, struct GNUNET_MQ_Handle *mq)
Function called by transport to notify us that a peer connected to us (on the network level).
struct GNUNET_TRANSPORT_CoreHandle * GNUNET_TRANSPORT_core_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *self, const struct GNUNET_MQ_MessageHandler *handlers, void *cls, GNUNET_TRANSPORT_NotifyConnect nc, GNUNET_TRANSPORT_NotifyDisconnect nd)
Connect to the transport service.
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
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:122
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
Message handler for a specific message type.
struct GNUNET_CRYPTO_EddsaPublicKey public_key

References current_ekm, do_rekey(), EphemeralKeyMessage::ephemeral_key, GNUNET_CRYPTO_ecdhe_key_create(), GNUNET_CRYPTO_eddsa_key_get_public(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_INFO, GNUNET_h2s(), GNUNET_log, GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE, GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY, GNUNET_MESSAGE_TYPE_CORE_PING, GNUNET_MESSAGE_TYPE_CORE_PONG, GNUNET_MQ_handler_end, GNUNET_MQ_hd_fixed_size, GNUNET_MQ_hd_var_size, GNUNET_notification_context_create(), GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SYSERR, GNUNET_TRANSPORT_core_connect(), GSC_cfg, GSC_KX_done(), GSC_my_identity, handle_transport_notify_connect(), handle_transport_notify_disconnect(), handlers, my_ephemeral_key, my_private_key, nc, pk, GNUNET_PeerIdentity::public_key, REKEY_FREQUENCY, rekey_task, sign_ephemeral_key(), and transport.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GSC_KX_done()

void GSC_KX_done ( void  )

Shutdown KX subsystem.

Definition at line 2097 of file gnunet-service-core_kx.c.

2098{
2099 if (NULL != transport)
2100 {
2102 transport = NULL;
2103 }
2104 if (NULL != rekey_task)
2105 {
2107 rekey_task = NULL;
2108 }
2109 memset (&my_ephemeral_key,
2110 0,
2111 sizeof (my_ephemeral_key));
2112 memset (&my_private_key,
2113 0,
2114 sizeof (my_private_key));
2115 if (NULL != nc)
2116 {
2118 nc = NULL;
2119 }
2120}
void GNUNET_TRANSPORT_core_disconnect(struct GNUNET_TRANSPORT_CoreHandle *handle)
Disconnect from the transport service.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:138

References GNUNET_notification_context_destroy(), GNUNET_SCHEDULER_cancel(), GNUNET_TRANSPORT_core_disconnect(), my_ephemeral_key, my_private_key, nc, rekey_task, and transport.

Referenced by GSC_KX_init(), and shutdown_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GSC_NEIGHBOURS_get_queue_length()

unsigned int GSC_NEIGHBOURS_get_queue_length ( const struct GSC_KeyExchangeInfo kxinfo)

Check how many messages are queued for the given neighbour.

Parameters
kxinfodata about neighbour to check
Returns
number of items in the message queue

Definition at line 2130 of file gnunet-service-core_kx.c.

2131{
2132 return GNUNET_MQ_get_length (kxinfo->mq);
2133}
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:293

References GNUNET_MQ_get_length(), and GSC_KeyExchangeInfo::mq.

Referenced by try_transmission().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GSC_NEIGHBOURS_check_excess_bandwidth()

int GSC_NEIGHBOURS_check_excess_bandwidth ( const struct GSC_KeyExchangeInfo target)

Check if the given neighbour has excess bandwidth available.

Parameters
targetneighbour to check
Returns
GNUNET_YES if excess bandwidth is available, GNUNET_NO if not

Definition at line 2137 of file gnunet-service-core_kx.c.

2138{
2139 return kxinfo->has_excess_bandwidth;
2140}

References GSC_KeyExchangeInfo::has_excess_bandwidth.

Referenced by try_transmission().

Here is the caller graph for this function:

◆ GSC_KX_handle_client_monitor_peers()

void GSC_KX_handle_client_monitor_peers ( struct GNUNET_MQ_Handle mq)

Handle GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.

For this request type, the client does not have to have transmitted an INIT request. All current peers are returned, regardless of which message types they accept.

Parameters
mqmessage queue to add for monitoring

Definition at line 2152 of file gnunet-service-core_kx.c.

2153{
2154 struct GNUNET_MQ_Envelope *env;
2155 struct MonitorNotifyMessage *done_msg;
2156 struct GSC_KeyExchangeInfo *kx;
2157
2159 for (kx = kx_head; NULL != kx; kx = kx->next)
2160 {
2161 struct GNUNET_MQ_Envelope *env;
2162 struct MonitorNotifyMessage *msg;
2163
2165 msg->state = htonl ((uint32_t) kx->status);
2166 msg->peer = *kx->peer;
2167 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
2169 }
2171 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
2174}
@ GNUNET_CORE_KX_ITERATION_FINISHED
This is not a state in a peer's state machine, but a special value used with the GNUNET_CORE_MonitorC...
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:161
uint32_t state
New peer state, an enum GNUNET_CORE_KxState in NBO.
Definition: core.h:310
struct GNUNET_TIME_AbsoluteNBO timeout
How long will we stay in this state (if nothing else happens)?
Definition: core.h:320

References env, GNUNET_CORE_KX_ITERATION_FINISHED, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_notification_context_add(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_UNIT_FOREVER_ABS, kx_head, mq, msg, nc, GSC_KeyExchangeInfo::next, GSC_KeyExchangeInfo::peer, MonitorNotifyMessage::state, GSC_KeyExchangeInfo::status, MonitorNotifyMessage::timeout, and GSC_KeyExchangeInfo::timeout.

Referenced by handle_client_monitor_peers().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ transport

struct GNUNET_TRANSPORT_CoreHandle* transport
static

Transport service.

Definition at line 315 of file gnunet-service-core_kx.c.

Referenced by GSC_KX_done(), GSC_KX_init(), handle_encrypted(), handle_ephemeral_key(), handle_ping(), and handle_pong().

◆ my_private_key

struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key
static

Our private key.

Definition at line 320 of file gnunet-service-core_kx.c.

Referenced by GSC_KX_done(), GSC_KX_init(), and sign_ephemeral_key().

◆ my_ephemeral_key

struct GNUNET_CRYPTO_EcdhePrivateKey my_ephemeral_key
static

Our ephemeral private key.

Definition at line 325 of file gnunet-service-core_kx.c.

Referenced by derive_session_keys(), do_rekey(), GSC_KX_done(), GSC_KX_init(), and sign_ephemeral_key().

◆ current_ekm

struct EphemeralKeyMessage current_ekm
static

Current message we send for a key exchange.

Definition at line 330 of file gnunet-service-core_kx.c.

Referenced by do_rekey(), GSC_KX_init(), send_key(), and sign_ephemeral_key().

◆ kx_head

◆ kx_tail

struct GSC_KeyExchangeInfo* kx_tail
static

◆ rekey_task

struct GNUNET_SCHEDULER_Task* rekey_task
static

Task scheduled for periodic re-generation (and thus rekeying) of our ephemeral key.

Definition at line 346 of file gnunet-service-core_kx.c.

Referenced by do_rekey(), GSC_KX_done(), and GSC_KX_init().

◆ nc