GNUnet 0.22.2
gnunet-service-core_kx.c File Reference

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

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:640
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 uint8_t seed
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:264
#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, seed, 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, seed, 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, seed, 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 1592 of file gnunet-service-core_kx.c.

1593{
1594 struct GNUNET_MQ_Envelope *env;
1595
1597 if (NULL != kx->retry_set_key_task)
1598 {
1600 kx->retry_set_key_task = NULL;
1601 }
1602 /* always update sender status in SET KEY message */
1603#if DEBUG_KX
1604 {
1605 struct GNUNET_HashCode hc;
1606
1608 sizeof(current_ekm.ephemeral_key),
1609 &hc);
1611 "Sending EPHEMERAL_KEY %s to `%s' (my status: %d)\n",
1612 GNUNET_h2s (&hc),
1613 GNUNET_i2s (kx->peer),
1614 kx->status);
1615 }
1616#endif
1617 current_ekm.sender_status = htonl ((int32_t) (kx->status));
1619 GNUNET_MQ_send (kx->mq, env);
1621 send_ping (kx);
1622 kx->retry_set_key_task =
1625 kx);
1626}
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:980
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:1277
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
765 {
767 pm->iv_seed = calculate_seed (kx);
768 derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, kx->peer);
769 do_encrypt (kx,
770 &iv,
771 &pp.target,
772 &pm->target,
773 sizeof(struct PingMessage)
774 - ((void *) &pm->target - (void *) pm));
775 }
776#endif
777}
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 792 of file gnunet-service-core_kx.c.

793{
794 struct GSC_KeyExchangeInfo *kx = cls;
795
797 "Decrypted message of type %d from %s\n",
798 ntohs (m->type),
799 GNUNET_i2s (kx->peer));
801 {
803 gettext_noop ("# PAYLOAD dropped (out of order)"),
804 1,
805 GNUNET_NO);
806 return GNUNET_OK;
807 }
808 switch (ntohs (m->type))
809 {
813 return GNUNET_OK;
814
817 return GNUNET_OK;
818
819 default:
821 m,
822 ntohs (m->size),
825 m,
826 sizeof(struct GNUNET_MessageHeader),
828 }
829 return GNUNET_OK;
830}
#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:103
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 843 of file gnunet-service-core_kx.c.

846{
847 struct GSC_KeyExchangeInfo *kx;
848 struct GNUNET_HashCode h1;
849 struct GNUNET_HashCode h2;
850
852 "Initiating key exchange with `%s'\n",
853 GNUNET_i2s (pid));
855 gettext_noop ("# key exchanges initiated"),
856 1,
857 GNUNET_NO);
858
859 kx = GNUNET_new (struct GSC_KeyExchangeInfo);
861 kx->mq = mq;
862 kx->peer = pid;
867 GNUNET_CRYPTO_hash (pid, sizeof(struct GNUNET_PeerIdentity), &h1);
869 sizeof(struct GNUNET_PeerIdentity),
870 &h2);
871 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2))
872 {
873 /* peer with "lower" identity starts KX, otherwise we typically end up
874 with both peers starting the exchange and transmit the 'set key'
875 message twice */
876 send_key (kx);
877 }
878 else
879 {
880 /* peer with "higher" identity starts a delayed KX, if the "lower" peer
881 * does not start a KX since it sees no reasons to do so */
885 kx);
886 }
887 return kx;
888}
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:218
#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 901 of file gnunet-service-core_kx.c.

904{
905 struct GSC_KeyExchangeInfo *kx = handler_cls;
906
908 "Peer `%s' disconnected from us.\n",
909 GNUNET_i2s (peer));
912 gettext_noop ("# key exchanges stopped"),
913 1,
914 GNUNET_NO);
915 if (NULL != kx->retry_set_key_task)
916 {
918 kx->retry_set_key_task = NULL;
919 }
920 if (NULL != kx->keep_alive_task)
921 {
923 kx->keep_alive_task = NULL;
924 }
929 GNUNET_free (kx);
930}
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 939 of file gnunet-service-core_kx.c.

940{
941 struct GNUNET_MQ_Envelope *env;
942
944 gettext_noop ("# PING messages transmitted"),
945 1,
946 GNUNET_NO);
948 GNUNET_MQ_send (kx->mq, env);
949}
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 958 of file gnunet-service-core_kx.c.

959{
960 struct GNUNET_HashCode key_material;
961
962 if (GNUNET_OK !=
965 &key_material))
966 {
967 GNUNET_break (0);
968 return;
969 }
970#if CONG_CRYPTO_ENABLED
971 derive_symmetric_key (&GSC_my_identity, kx->peer, &key_material, kx->
972 encrypt_key);
973 derive_symmetric_key (kx->peer, &GSC_my_identity, &key_material, kx->
974 decrypt_key);
975#else
976 derive_aes_key (&GSC_my_identity, kx->peer, &key_material, &kx->
977 encrypt_key);
978 derive_aes_key (kx->peer, &GSC_my_identity, &key_material, &kx->
979 decrypt_key);
980#endif
981 memset (&key_material, 0, sizeof(key_material));
982 /* fresh key, reset sequence numbers */
984 kx->last_packets_bitmap = 0;
985 setup_fresh_ping (kx);
986}
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 997 of file gnunet-service-core_kx.c.

998{
999 struct GSC_KeyExchangeInfo *kx = cls;
1000 struct GNUNET_TIME_Absolute start_t;
1001 struct GNUNET_TIME_Absolute end_t;
1002 struct GNUNET_TIME_Absolute now;
1003 enum GNUNET_CORE_KxState sender_status;
1004 enum GNUNET_GenericReturnValue do_verify = GNUNET_YES;
1005
1006 end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
1010 (end_t.abs_value_us < kx->foreign_key_expires.abs_value_us))
1011 {
1013 gettext_noop ("# old ephemeral keys ignored"),
1014 1,
1015 GNUNET_NO);
1017 "Received expired EPHEMERAL_KEY from %s\n",
1018 GNUNET_i2s (&m->origin_identity));
1019 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1020 return;
1021 }
1022 if (0 == memcmp (&m->ephemeral_key,
1024 sizeof(m->ephemeral_key)))
1025 {
1027 gettext_noop (
1028 "# duplicate ephemeral keys. Not verifying."),
1029 1,
1030 GNUNET_NO);
1032 "Duplicate EPHEMERAL_KEY from %s, do not verify\n",
1033 GNUNET_i2s (&m->origin_identity));
1034 do_verify = GNUNET_NO;
1035 }
1036 if (0 != memcmp (&m->origin_identity,
1037 kx->peer,
1038 sizeof(struct GNUNET_PeerIdentity)))
1039 {
1041 "Received EPHEMERAL_KEY from %s, but expected %s\n",
1042 GNUNET_i2s (&m->origin_identity),
1043 GNUNET_i2s_full (kx->peer));
1044 GNUNET_break_op (0);
1045 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1046 return;
1047 }
1048 if (do_verify && ((ntohl (m->purpose.size) !=
1050 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1051 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1052 + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
1053 + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) ||
1054 (GNUNET_OK !=
1057 &m->purpose,
1058 &m->signature,
1059 &m->origin_identity.public_key
1060 ))))
1061 {
1062 /* invalid signature */
1063 GNUNET_break_op (0);
1065 gettext_noop (
1066 "# EPHEMERAL_KEYs rejected (bad signature)"),
1067 1,
1068 GNUNET_NO);
1070 "Received EPHEMERAL_KEY from %s with bad signature\n",
1071 GNUNET_i2s (&m->origin_identity));
1072 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1073 return;
1074 }
1075 now = GNUNET_TIME_absolute_get ();
1076 start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
1077 if ((end_t.abs_value_us <
1079 (start_t.abs_value_us >
1081 {
1082 GNUNET_log (
1084 _ (
1085 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"),
1086 GNUNET_i2s (kx->peer),
1087 (unsigned long long) now.abs_value_us,
1088 (unsigned long long) start_t.abs_value_us,
1089 (unsigned long long) end_t.abs_value_us);
1091 gettext_noop (
1092 "# EPHEMERAL_KEY messages rejected due to time")
1093 ,
1094 1,
1095 GNUNET_NO);
1096 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1097 return;
1098 }
1099#if DEBUG_KX
1100 {
1101 struct GNUNET_HashCode eh;
1102
1103 GNUNET_CRYPTO_hash (&m->ephemeral_key, sizeof(m->ephemeral_key), &eh);
1105 "Received valid EPHEMERAL_KEY `%s' from `%s' in state %d.\n",
1106 GNUNET_h2s (&eh),
1107 GNUNET_i2s (kx->peer),
1108 kx->status);
1109 }
1110#endif
1112 gettext_noop ("# valid ephemeral keys received"),
1113 1,
1114 GNUNET_NO);
1115 kx->other_ephemeral_key = m->ephemeral_key;
1116 kx->foreign_key_expires = end_t;
1118
1119 /* check if we still need to send the sender our key */
1120 sender_status = ntohl (m->sender_status);
1121 switch (sender_status)
1122 {
1124 GNUNET_break_op (0);
1125 break;
1126
1128 /* fine, need to send our key after updating our status, see below */
1130 break;
1131
1133 /* other peer already got our key, but typemap did go down */
1135 break;
1136
1138 /* other peer already got our key, typemap NOT down */
1139 break;
1140
1142 /* other peer already got our key, typemap NOT down */
1143 break;
1144
1145 default:
1146 GNUNET_break (0);
1147 break;
1148 }
1149 /* check if we need to confirm everything is fine via PING + PONG */
1150 switch (kx->status)
1151 {
1153 GNUNET_assert (NULL == kx->keep_alive_task);
1155 monitor_notify_all (kx);
1156 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1157 send_key (kx);
1158 else
1159 send_ping (kx);
1160 break;
1161
1163 GNUNET_assert (NULL == kx->keep_alive_task);
1165 monitor_notify_all (kx);
1166 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1167 send_key (kx);
1168 else
1169 send_ping (kx);
1170 break;
1171
1173 GNUNET_assert (NULL == kx->keep_alive_task);
1174 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1175 send_key (kx);
1176 else
1177 send_ping (kx);
1178 break;
1179
1182 monitor_notify_all (kx);
1183 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1184 send_key (kx);
1185 else
1186 send_ping (kx);
1187 break;
1188
1190 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1191 send_key (kx);
1192 else
1193 send_ping (kx);
1194 break;
1195
1196 default:
1197 GNUNET_break (0);
1198 break;
1199 }
1200 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1201}
#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...
#define GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY
Purpose is to set a session key.
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:741
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:471
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:452
#define _(String)
GNU gettext support macro.
Definition: platform.h:179
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 1345 of file gnunet-service-core_kx.c.

1346{
1347 struct GSC_KeyExchangeInfo *kx = cls;
1348 struct GNUNET_TIME_Relative retry;
1349 struct GNUNET_TIME_Relative left;
1350
1351 kx->keep_alive_task = NULL;
1353 if (0 == left.rel_value_us)
1354 {
1356 gettext_noop ("# sessions terminated by timeout"),
1357 1,
1358 GNUNET_NO);
1359 GSC_SESSIONS_end (kx->peer);
1361 monitor_notify_all (kx);
1362 send_key (kx);
1363 return;
1364 }
1366 "Sending KEEPALIVE to `%s'\n",
1367 GNUNET_i2s (kx->peer));
1369 gettext_noop ("# keepalive messages sent"),
1370 1,
1371 GNUNET_NO);
1372 setup_fresh_ping (kx);
1373 send_ping (kx);
1376 kx->keep_alive_task =
1378}
#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:352
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:406
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:552
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 1216 of file gnunet-service-core_kx.c.

1217{
1218 struct GSC_KeyExchangeInfo *kx = cls;
1219 struct PingMessage t;
1220 struct PongMessage tx;
1221 struct PongMessage *tp;
1222 struct GNUNET_MQ_Envelope *env;
1223#if CONG_CRYPTO_ENABLED
1224#else
1226#endif
1227
1229 gettext_noop ("# PING messages received"),
1230 1,
1231 GNUNET_NO);
1235 {
1236 /* ignore */
1238 gettext_noop (
1239 "# PING messages dropped (out of order)"),
1240 1,
1241 GNUNET_NO);
1242 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1243 return;
1244 }
1246 "Core service receives PING request from `%s'.\n",
1247 GNUNET_i2s (kx->peer));
1248#if CONG_CRYPTO_ENABLED
1249 if (0 != crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
1250 (unsigned char*) &t.target,
1251 NULL,
1252 (unsigned char*) &m->target,
1253 sizeof (m->target) + sizeof (m->challenge),
1254 m->tag,
1255 NULL, 0,
1256 m->nonce,
1257 kx->decrypt_key))
1258 {
1259 GNUNET_break_op (0);
1260 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1261 return;
1262 }
1263#else
1264 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1265 if (GNUNET_OK != do_decrypt (kx,
1266 &iv,
1267 &m->target,
1268 &t.target,
1269 sizeof(struct PingMessage)
1270 - ((void *) &m->target - (void *) m)))
1271 {
1272 GNUNET_break_op (0);
1273 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1274 return;
1275 }
1276#endif
1277 if (0 !=
1278 memcmp (&t.target, &GSC_my_identity, sizeof(struct GNUNET_PeerIdentity)))
1279 {
1282 "Decryption of PING from peer `%s' failed, PING for `%s'?\n",
1283 GNUNET_i2s (kx->peer),
1284 GNUNET_i2s2 (&t.target));
1285 else
1286 GNUNET_log (
1288 "Decryption of PING from peer `%s' failed after rekey (harmless)\n",
1289 GNUNET_i2s (kx->peer));
1290 GNUNET_break_op (0);
1291 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1292 return;
1293 }
1294 /* construct PONG */
1295 tx.reserved = 0;
1296 tx.challenge = t.challenge;
1297 tx.target = t.target;
1299#if CONG_CRYPTO_ENABLED
1300 randombytes_buf (tp->nonce, sizeof (tp->nonce));
1301 GNUNET_assert (0 ==
1302 crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
1303 (unsigned char*) &tp->challenge,
1304 tp->tag,
1305 NULL,
1306 (unsigned char*) &tx.challenge,
1307 sizeof(struct PongMessage)
1308 - ((void *) &tp->challenge - (void *) tp),
1309 NULL, 0,
1310 NULL,
1311 tp->nonce,
1312 kx->encrypt_key));
1313#else
1314 tp->iv_seed = calculate_seed (kx);
1315 derive_pong_iv (&iv, &kx->encrypt_key, tp->iv_seed, t.challenge, kx->peer);
1316 do_encrypt (kx,
1317 &iv,
1318 &tx.challenge,
1319 &tp->challenge,
1320 sizeof(struct PongMessage)
1321 - ((void *) &tp->challenge - (void *) tp));
1322#endif
1324 gettext_noop ("# PONG messages created"),
1325 1,
1326 GNUNET_NO);
1327 GNUNET_MQ_send (kx->mq, env);
1328 if (NULL != kx->keep_alive_task)
1329 {
1332 send_keep_alive, kx);
1333 }
1334 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1335}
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:76
#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 1389 of file gnunet-service-core_kx.c.

1390{
1392
1393 kx->timeout =
1395 delta =
1397 if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
1398 {
1399 /* we only notify monitors about timeout changes if those
1400 are bigger than the threshold (5s) */
1401 monitor_notify_all (kx);
1402 }
1403 if (NULL != kx->keep_alive_task)
1408 kx);
1409}
#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:423
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 1419 of file gnunet-service-core_kx.c.

1420{
1421 struct GSC_KeyExchangeInfo *kx = cls;
1422 struct PongMessage t;
1423#if CONG_CRYPTO_ENABLED
1424#else
1426#endif
1427
1429 gettext_noop ("# PONG messages received"),
1430 1,
1431 GNUNET_NO);
1432 switch (kx->status)
1433 {
1436 gettext_noop (
1437 "# PONG messages dropped (connection down)"),
1438 1,
1439 GNUNET_NO);
1440 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1441 return;
1442
1445 gettext_noop (
1446 "# PONG messages dropped (out of order)"),
1447 1,
1448 GNUNET_NO);
1449 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1450 return;
1451
1453 break;
1454
1456 break;
1457
1459 break;
1460
1461 default:
1462 GNUNET_break (0);
1463 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1464 return;
1465 }
1467 "Core service receives PONG response from `%s'.\n",
1468 GNUNET_i2s (kx->peer));
1469 /* mark as garbage, just to be sure */
1470 memset (&t, 255, sizeof(t));
1471#if CONG_CRYPTO_ENABLED
1472 if (0 != crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
1473 (unsigned char*) &t.challenge,
1474 NULL,
1475 (unsigned char*) &m->challenge,
1476 sizeof(struct PongMessage)
1477 - ((void *) &m->challenge - (void *) m),
1478 m->tag,
1479 NULL, 0,
1480 m->nonce,
1481 kx->decrypt_key))
1482 {
1483 GNUNET_break_op (0);
1484 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1485 return;
1486 }
1487#else
1488 derive_pong_iv (&iv,
1489 &kx->decrypt_key,
1490 m->iv_seed,
1491 kx->ping_challenge,
1493 if (GNUNET_OK != do_decrypt (kx,
1494 &iv,
1495 &m->challenge,
1496 &t.challenge,
1497 sizeof(struct PongMessage)
1498 - ((void *) &m->challenge - (void *) m)))
1499 {
1500 GNUNET_break_op (0);
1501 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1502 return;
1503 }
1504#endif
1506 gettext_noop ("# PONG messages decrypted"),
1507 1,
1508 GNUNET_NO);
1509 if ((0 !=
1510 memcmp (&t.target, kx->peer, sizeof(struct GNUNET_PeerIdentity))) ||
1511 (kx->ping_challenge != t.challenge))
1512 {
1513 /* PONG malformed */
1515 "Received malformed PONG wanted sender `%s' with challenge %u\n",
1516 GNUNET_i2s (kx->peer),
1517 (unsigned int) kx->ping_challenge);
1519 "Received malformed PONG received from `%s' with challenge %u\n",
1520 GNUNET_i2s (&t.target),
1521 (unsigned int) t.challenge);
1522 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1523 return;
1524 }
1526 "Received valid PONG from `%s'\n",
1527 GNUNET_i2s (kx->peer));
1528 /* no need to resend key any longer */
1529 if (NULL != kx->retry_set_key_task)
1530 {
1532 kx->retry_set_key_task = NULL;
1533 }
1534 switch (kx->status)
1535 {
1537 GNUNET_assert (0); /* should be impossible */
1538 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1539 return;
1540
1542 GNUNET_assert (0); /* should be impossible */
1543 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1544 return;
1545
1548 gettext_noop (
1549 "# session keys confirmed via PONG"),
1550 1,
1551 GNUNET_NO);
1553 monitor_notify_all (kx);
1554 GSC_SESSIONS_create (kx->peer, kx);
1555 GNUNET_assert (NULL == kx->keep_alive_task);
1556 update_timeout (kx);
1557 break;
1558
1561 gettext_noop ("# timeouts prevented via PONG"),
1562 1,
1563 GNUNET_NO);
1564 update_timeout (kx);
1565 break;
1566
1569 gettext_noop (
1570 "# rekey operations confirmed via PONG"),
1571 1,
1572 GNUNET_NO);
1574 monitor_notify_all (kx);
1575 update_timeout (kx);
1576 break;
1577
1578 default:
1579 GNUNET_break (0);
1580 break;
1581 }
1582 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1583}
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 1630 of file gnunet-service-core_kx.c.

1633{
1634 size_t used = payload_size + sizeof(struct EncryptedMessage);
1635 char pbuf[used]; /* plaintext */
1636 struct EncryptedMessage *em; /* encrypted message */
1637 struct EncryptedMessage *ph; /* plaintext header */
1638 struct GNUNET_MQ_Envelope *env;
1639#if CONG_CRYPTO_ENABLED
1640#else
1642 struct GNUNET_CRYPTO_AuthKey auth_key;
1643#endif
1644
1645 ph = (struct EncryptedMessage *) pbuf;
1646 ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1647 ph->reserved = 0;
1649 GNUNET_memcpy (&ph[1], payload, payload_size);
1651 payload_size,
1653#if CONG_CRYPTO_ENABLED
1654 randombytes_buf (ph->nonce, sizeof (ph->nonce));
1655 GNUNET_assert (0 ==
1656 crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
1657 (unsigned char*) &em->sequence_number,
1658 em->tag,
1659 NULL,
1660 (unsigned char*) &ph->sequence_number,
1661 used - ENCRYPTED_HEADER_SIZE,
1662 NULL, 0,
1663 NULL,
1664 ph->nonce,
1665 kx->encrypt_key));
1666#else
1667 ph->iv_seed = calculate_seed (kx);
1668 em->iv_seed = ph->iv_seed;
1669 derive_iv (&iv, &kx->encrypt_key, ph->iv_seed, kx->peer);
1671 &iv,
1672 &ph->sequence_number,
1673 &em->sequence_number,
1674 used - ENCRYPTED_HEADER_SIZE));
1675#if DEBUG_KX
1676 {
1677 struct GNUNET_HashCode hc;
1678
1680 used - ENCRYPTED_HEADER_SIZE,
1681 &hc);
1683 "Encrypted payload `%s' of %u bytes for %s\n",
1684 GNUNET_h2s (&hc),
1685 (unsigned int) (used - ENCRYPTED_HEADER_SIZE),
1686 GNUNET_i2s (kx->peer));
1687 }
1688#endif
1689 derive_auth_key (&auth_key, &kx->encrypt_key, ph->iv_seed);
1690 GNUNET_CRYPTO_hmac (&auth_key,
1691 &em->sequence_number,
1692 used - ENCRYPTED_HEADER_SIZE,
1693 &em->hmac);
1694#if DEBUG_KX
1695 {
1696 struct GNUNET_HashCode hc;
1697
1698 GNUNET_CRYPTO_hash (&auth_key, sizeof(auth_key), &hc);
1700 "For peer %s, used AC %s to create hmac %s\n",
1701 GNUNET_i2s (kx->peer),
1702 GNUNET_h2s (&hc),
1703 GNUNET_h2s2 (&em->hmac));
1704 }
1705#endif
1706#endif
1708 GNUNET_MQ_send (kx->mq, env);
1709}
#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:327
#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:61
#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 1721 of file gnunet-service-core_kx.c.

1722{
1723 uint16_t size = ntohs (m->header.size) - sizeof(*m);
1724
1725 if (size < sizeof(struct GNUNET_MessageHeader))
1726 {
1727 GNUNET_break_op (0);
1728 return GNUNET_SYSERR;
1729 }
1730 return GNUNET_OK;
1731}

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 1742 of file gnunet-service-core_kx.c.

1743{
1744 struct GSC_KeyExchangeInfo *kx = cls;
1745 struct EncryptedMessage *pt; /* plaintext */
1746 uint32_t snum;
1747 struct GNUNET_TIME_Absolute t;
1748 uint16_t size = ntohs (m->header.size);
1749 char buf[size] GNUNET_ALIGN;
1750
1752 {
1754 gettext_noop (
1755 "# DATA message dropped (out of order)"),
1756 1,
1757 GNUNET_NO);
1758 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1759 return;
1760 }
1761 if (0 ==
1763 {
1764 GNUNET_log (
1766 _ (
1767 "Session to peer `%s' went down due to key expiration (should not happen)\n"),
1768 GNUNET_i2s (kx->peer));
1770 gettext_noop (
1771 "# sessions terminated by key expiration"),
1772 1,
1773 GNUNET_NO);
1774 GSC_SESSIONS_end (kx->peer);
1775 if (NULL != kx->keep_alive_task)
1776 {
1778 kx->keep_alive_task = NULL;
1779 }
1781 monitor_notify_all (kx);
1782 send_key (kx);
1783 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1784 return;
1785 }
1786
1787 /* validate hash */
1788#if DEBUG_KX
1789 {
1790 struct GNUNET_HashCode hc;
1791
1792 GNUNET_CRYPTO_hash (&m->sequence_number, size - ENCRYPTED_HEADER_SIZE, &hc);
1794 "Received encrypted payload `%s' of %u bytes from %s\n",
1795 GNUNET_h2s (&hc),
1796 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1797 GNUNET_i2s (kx->peer));
1798 }
1799#endif
1800
1801#if CONG_CRYPTO_ENABLED
1802 if (0 != crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
1803 (unsigned char*) &buf[ENCRYPTED_HEADER_SIZE],
1804 NULL,
1805 (unsigned char*) &m->sequence_number,
1807 m->tag,
1808 NULL, 0,
1809 m->nonce,
1810 kx->decrypt_key))
1811 {
1812 GNUNET_break_op (0);
1813 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1814 return;
1815 }
1816#else
1817 {
1819 struct GNUNET_CRYPTO_AuthKey auth_key;
1820 struct GNUNET_HashCode ph;
1821 derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed);
1822 GNUNET_CRYPTO_hmac (&auth_key,
1823 &m->sequence_number,
1825 &ph);
1826#if DEBUG_KX
1827 {
1828 struct GNUNET_HashCode hc;
1829
1830 GNUNET_CRYPTO_hash (&auth_key, sizeof(auth_key), &hc);
1832 "For peer %s, used AC %s to verify hmac %s\n",
1833 GNUNET_i2s (kx->peer),
1834 GNUNET_h2s (&hc),
1835 GNUNET_h2s2 (&m->hmac));
1836 }
1837#endif
1838 if (0 != memcmp (&ph, &m->hmac, sizeof(struct GNUNET_HashCode)))
1839 {
1840 /* checksum failed */
1842 "Failed checksum validation for a message from `%s'\n",
1843 GNUNET_i2s (kx->peer));
1844 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1845 return;
1846 }
1847 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1848 /* decrypt */
1849 if (GNUNET_OK != do_decrypt (kx,
1850 &iv,
1851 &m->sequence_number,
1854 {
1855 GNUNET_break_op (0);
1856 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1857 return;
1858 }
1859 }
1860#endif
1862 "Decrypted %u bytes from %s\n",
1863 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1864 GNUNET_i2s (kx->peer));
1865 pt = (struct EncryptedMessage *) buf;
1866
1867 /* validate sequence number */
1868 snum = ntohl (pt->sequence_number);
1869 if (kx->last_sequence_number_received == snum)
1870 {
1872 "Received duplicate message, ignoring.\n");
1873 /* duplicate, ignore */
1875 gettext_noop ("# bytes dropped (duplicates)"),
1876 size,
1877 GNUNET_NO);
1878 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1879 return;
1880 }
1881 if ((kx->last_sequence_number_received > snum) &&
1882 (kx->last_sequence_number_received - snum > 32))
1883 {
1885 "Received ancient out of sequence message, ignoring.\n");
1886 /* ancient out of sequence, ignore */
1888 gettext_noop (
1889 "# bytes dropped (out of sequence)"),
1890 size,
1891 GNUNET_NO);
1892 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1893 return;
1894 }
1895 if (kx->last_sequence_number_received > snum)
1896 {
1897 uint32_t rotbit = 1U << (kx->last_sequence_number_received - snum - 1);
1898
1899 if ((kx->last_packets_bitmap & rotbit) != 0)
1900 {
1902 "Received duplicate message, ignoring.\n");
1904 gettext_noop ("# bytes dropped (duplicates)"),
1905 size,
1906 GNUNET_NO);
1907 /* duplicate, ignore */
1908 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1909 return;
1910 }
1911 kx->last_packets_bitmap |= rotbit;
1912 }
1913 if (kx->last_sequence_number_received < snum)
1914 {
1915 unsigned int shift = (snum - kx->last_sequence_number_received);
1916
1917 if (shift >= 8 * sizeof(kx->last_packets_bitmap))
1918 kx->last_packets_bitmap = 0;
1919 else
1920 kx->last_packets_bitmap <<= shift;
1922 }
1923
1924 /* check timestamp */
1926 if (GNUNET_TIME_absolute_get_duration (t).rel_value_us >
1927 MAX_MESSAGE_AGE.rel_value_us)
1928 {
1930 "Message received far too old (%s). Content ignored.\n",
1933 GNUNET_YES));
1935 gettext_noop (
1936 "# bytes dropped (ancient message)"),
1937 size,
1938 GNUNET_NO);
1939 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1940 return;
1941 }
1942
1943 /* process decrypted message(s) */
1944 update_timeout (kx);
1946 gettext_noop ("# bytes of payload decrypted"),
1947 size - sizeof(struct EncryptedMessage),
1948 GNUNET_NO);
1949 if (GNUNET_OK !=
1951 &buf[sizeof(struct EncryptedMessage)],
1952 size - sizeof(struct EncryptedMessage),
1953 GNUNET_YES,
1954 GNUNET_NO))
1955 GNUNET_break_op (0);
1956
1957 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1958}
#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:438
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:579

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 1966 of file gnunet-service-core_kx.c.

1967{
1968 current_ekm.header.size = htons (sizeof(struct EphemeralKeyMessage));
1970 current_ekm.sender_status = 0; /* to be set later */
1973 htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
1974 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1975 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1976 + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
1977 + sizeof(struct GNUNET_PeerIdentity));
1981 "core",
1982 "USE_EPHEMERAL_KEYS"))
1983 {
1987 REKEY_TOLERANCE)));
1988 }
1989 else
1990 {
1993 }
2001}
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:587
#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 2010 of file gnunet-service-core_kx.c.

2011{
2012 struct GSC_KeyExchangeInfo *pos;
2013
2014 (void) cls;
2018 {
2019 struct GNUNET_HashCode eh;
2020
2022 sizeof(current_ekm.ephemeral_key),
2023 &eh);
2024 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Rekeying to %s\n", GNUNET_h2s (&eh));
2025 }
2026 for (pos = kx_head; NULL != pos; pos = pos->next)
2027 {
2028 if (GNUNET_CORE_KX_STATE_UP == pos->status)
2029 {
2031 derive_session_keys (pos);
2032 }
2033 else if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
2034 {
2036 }
2037 monitor_notify_all (pos);
2038 send_key (pos);
2039 }
2040}
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 2050 of file gnunet-service-core_kx.c.

2051{
2053 GNUNET_MQ_hd_fixed_size (ephemeral_key,
2055 struct EphemeralKeyMessage,
2056 NULL),
2059 struct PingMessage,
2060 NULL),
2063 struct PongMessage,
2064 NULL),
2065 GNUNET_MQ_hd_var_size (encrypted,
2067 struct EncryptedMessage,
2068 NULL),
2070 };
2071
2072 my_private_key = *pk;
2077 {
2078 struct GNUNET_HashCode eh;
2079
2081 sizeof(current_ekm.ephemeral_key),
2082 &eh);
2084 "Starting with ephemeral key %s\n",
2085 GNUNET_h2s (&eh));
2086 }
2087
2090 transport =
2093 handlers,
2094 NULL,
2097 if (NULL == transport)
2098 {
2099 GSC_KX_done ();
2100 return GNUNET_SYSERR;
2101 }
2102 return GNUNET_OK;
2103}
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 2110 of file gnunet-service-core_kx.c.

2111{
2112 if (NULL != transport)
2113 {
2115 transport = NULL;
2116 }
2117 if (NULL != rekey_task)
2118 {
2120 rekey_task = NULL;
2121 }
2122 memset (&my_ephemeral_key,
2123 0,
2124 sizeof (my_ephemeral_key));
2125 memset (&my_private_key,
2126 0,
2127 sizeof (my_private_key));
2128 if (NULL != nc)
2129 {
2131 nc = NULL;
2132 }
2133}
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 2143 of file gnunet-service-core_kx.c.

2144{
2145 return GNUNET_MQ_get_length (kxinfo->mq);
2146}
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 2150 of file gnunet-service-core_kx.c.

2151{
2152 return kxinfo->has_excess_bandwidth;
2153}

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 2165 of file gnunet-service-core_kx.c.

2166{
2167 struct GNUNET_MQ_Envelope *env;
2168 struct MonitorNotifyMessage *done_msg;
2169 struct GSC_KeyExchangeInfo *kx;
2170
2172 for (kx = kx_head; NULL != kx; kx = kx->next)
2173 {
2174 struct GNUNET_MQ_Envelope *env_notify;
2175 struct MonitorNotifyMessage *msg;
2176
2178 msg->state = htonl ((uint32_t) kx->status);
2179 msg->peer = *kx->peer;
2180 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
2181 GNUNET_MQ_send (mq, env_notify);
2182 }
2184 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
2187}
@ 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