2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file core/gnunet-service-core_kx.c
23 * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other peers
24 * @author Christian Grothoff
27 #include "gnunet-service-core_kx.h"
28 #include "gnunet-service-core.h"
29 #include "gnunet-service-core_sessions.h"
30 #include "gnunet_statistics_service.h"
31 #include "gnunet_transport_core_service.h"
32 #include "gnunet_constants.h"
33 #include "gnunet_signatures.h"
34 #include "gnunet_protocols.h"
38 * Enable expensive (and possibly problematic for privacy!) logging of KX.
43 * How long do we wait for SET_KEY confirmation initially?
45 #define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
48 * What is the minimum frequency for a PING message?
50 #define MIN_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
53 * How often do we rekey?
55 #define REKEY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
58 * What time difference do we tolerate?
60 #define REKEY_TOLERANCE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
63 * What is the maximum age of a message for us to consider processing
64 * it? Note that this looks at the timestamp used by the other peer,
65 * so clock skew between machines does come into play here. So this
66 * should be picked high enough so that a little bit of clock skew
67 * does not prevent peers from connecting to us.
69 #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
73 GNUNET_NETWORK_STRUCT_BEGIN
76 * Message transmitted with the signed ephemeral key of a peer. The
77 * session key is then derived from the two ephemeral keys (ECDHE).
79 struct EphemeralKeyMessage
83 * Message type is #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY.
85 struct GNUNET_MessageHeader header;
88 * Status of the sender (should be in `enum PeerStateMachine`), nbo.
90 int32_t sender_status GNUNET_PACKED;
93 * An ECC signature of the @e origin_identity asserting the validity
94 * of the given ephemeral key.
96 struct GNUNET_CRYPTO_EddsaSignature signature;
99 * Information about what is being signed.
101 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
104 * At what time was this key created (beginning of validity).
106 struct GNUNET_TIME_AbsoluteNBO creation_time;
109 * When does the given ephemeral key expire (end of validity).
111 struct GNUNET_TIME_AbsoluteNBO expiration_time;
114 * Ephemeral public ECC key.
116 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
119 * Public key of the signing peer (persistent version, not the
120 * ephemeral public key).
122 struct GNUNET_PeerIdentity origin_identity;
128 * We're sending an (encrypted) PING to the other peer to check if he
129 * can decrypt. The other peer should respond with a PONG with the
130 * same content, except this time encrypted with the receiver's key.
135 * Message type is #GNUNET_MESSAGE_TYPE_CORE_PING.
137 struct GNUNET_MessageHeader header;
142 uint32_t iv_seed GNUNET_PACKED;
145 * Intended target of the PING, used primarily to check
146 * that decryption actually worked.
148 struct GNUNET_PeerIdentity target;
151 * Random number chosen to make replay harder.
153 uint32_t challenge GNUNET_PACKED;
158 * Response to a PING. Includes data from the original PING.
163 * Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG.
165 struct GNUNET_MessageHeader header;
170 uint32_t iv_seed GNUNET_PACKED;
173 * Random number to make replay attacks harder.
175 uint32_t challenge GNUNET_PACKED;
178 * Reserved, always zero.
183 * Intended target of the PING, used primarily to check
184 * that decryption actually worked.
186 struct GNUNET_PeerIdentity target;
191 * Encapsulation for encrypted messages exchanged between
192 * peers. Followed by the actual encrypted data.
194 struct EncryptedMessage
197 * Message type is #GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE.
199 struct GNUNET_MessageHeader header;
202 * Random value used for IV generation.
204 uint32_t iv_seed GNUNET_PACKED;
207 * MAC of the encrypted message (starting at @e sequence_number),
208 * used to verify message integrity. Everything after this value
209 * (excluding this value itself) will be encrypted and
210 * authenticated. #ENCRYPTED_HEADER_SIZE must be set to the offset
211 * of the *next* field.
213 struct GNUNET_HashCode hmac;
216 * Sequence number, in network byte order. This field
217 * must be the first encrypted/decrypted field
219 uint32_t sequence_number GNUNET_PACKED;
222 * Reserved, always zero.
224 uint32_t reserved GNUNET_PACKED;
227 * Timestamp. Used to prevent replay of ancient messages
228 * (recent messages are caught with the sequence number).
230 struct GNUNET_TIME_AbsoluteNBO timestamp;
233 GNUNET_NETWORK_STRUCT_END
237 * Number of bytes (at the beginning) of `struct EncryptedMessage`
238 * that are NOT encrypted.
240 #define ENCRYPTED_HEADER_SIZE (offsetof(struct EncryptedMessage, sequence_number))
244 * Information about the status of a key exchange with another peer.
246 struct GSC_KeyExchangeInfo
252 struct GSC_KeyExchangeInfo *next;
257 struct GSC_KeyExchangeInfo *prev;
260 * Identity of the peer.
262 const struct GNUNET_PeerIdentity *peer;
265 * Message queue for sending messages to @a peer.
267 struct GNUNET_MQ_Handle *mq;
270 * Our message stream tokenizer (for encrypted payload).
272 struct GNUNET_MessageStreamTokenizer *mst;
275 * PING message we transmit to the other peer.
277 struct PingMessage ping;
280 * Ephemeral public ECC key of the other peer.
282 struct GNUNET_CRYPTO_EcdhePublicKey other_ephemeral_key;
285 * Key we use to encrypt our messages for the other peer
286 * (initialized by us when we do the handshake).
288 struct GNUNET_CRYPTO_SymmetricSessionKey encrypt_key;
291 * Key we use to decrypt messages from the other peer
292 * (given to us by the other peer during the handshake).
294 struct GNUNET_CRYPTO_SymmetricSessionKey decrypt_key;
297 * At what time did the other peer generate the decryption key?
299 struct GNUNET_TIME_Absolute foreign_key_expires;
302 * When should the session time out (if there are no PONGs)?
304 struct GNUNET_TIME_Absolute timeout;
307 * What was the last timeout we informed our monitors about?
309 struct GNUNET_TIME_Absolute last_notify_timeout;
312 * At what frequency are we currently re-trying SET_KEY messages?
314 struct GNUNET_TIME_Relative set_key_retry_frequency;
317 * ID of task used for re-trying SET_KEY and PING message.
319 struct GNUNET_SCHEDULER_Task *retry_set_key_task;
322 * ID of task used for sending keep-alive pings.
324 struct GNUNET_SCHEDULER_Task *keep_alive_task;
327 * Bit map indicating which of the 32 sequence numbers before the
328 * last were received (good for accepting out-of-order packets and
329 * estimating reliability of the connection)
331 uint32_t last_packets_bitmap;
334 * last sequence number received on this connection (highest)
336 uint32_t last_sequence_number_received;
339 * last sequence number transmitted
341 uint32_t last_sequence_number_sent;
344 * What was our PING challenge number (for this peer)?
346 uint32_t ping_challenge;
349 * #GNUNET_YES if this peer currently has excess bandwidth.
351 int has_excess_bandwidth;
354 * What is our connection status?
356 enum GNUNET_CORE_KxState status;
364 static struct GNUNET_TRANSPORT_CoreHandle *transport;
369 static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
372 * Our ephemeral private key.
374 static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key;
377 * Current message we send for a key exchange.
379 static struct EphemeralKeyMessage current_ekm;
384 static struct GSC_KeyExchangeInfo *kx_head;
389 static struct GSC_KeyExchangeInfo *kx_tail;
392 * Task scheduled for periodic re-generation (and thus rekeying) of our
395 static struct GNUNET_SCHEDULER_Task *rekey_task;
398 * Notification context for broadcasting to monitors.
400 static struct GNUNET_NotificationContext *nc;
404 * Calculate seed value we should use for a message.
406 * @param kx key exchange context
409 calculate_seed (struct GSC_KeyExchangeInfo *kx)
411 /* Note: may want to make this non-random and instead
412 derive from key material to avoid having an undetectable
414 return htonl (GNUNET_CRYPTO_random_u32
415 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
420 * Inform all monitors about the KX state of the given peer.
422 * @param kx key exchange state to inform about
425 monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
427 struct MonitorNotifyMessage msg;
429 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
430 msg.header.size = htons (sizeof (msg));
431 msg.state = htonl ((uint32_t) kx->status);
432 msg.peer = *kx->peer;
433 msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
434 GNUNET_notification_context_broadcast (nc,
437 kx->last_notify_timeout = kx->timeout;
442 * Derive an authentication key from "set key" information
444 * @param akey authentication key to derive
445 * @param skey session key to use
446 * @param seed seed to use
449 derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
450 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
453 static const char ctx[] = "authentication key";
455 struct GNUNET_HashCode sh;
457 GNUNET_CRYPTO_hash (skey,
460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
461 "Deriving Auth key from SKEY %s and seed %u\n",
463 (unsigned int) seed);
465 GNUNET_CRYPTO_hmac_derive_key (akey,
467 &seed, sizeof (seed),
468 skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
475 * Derive an IV from packet information
477 * @param iv initialization vector to initialize
478 * @param skey session key to use
479 * @param seed seed to use
480 * @param identity identity of the other peer to use
483 derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
484 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
486 const struct GNUNET_PeerIdentity *identity)
488 static const char ctx[] = "initialization vector";
490 struct GNUNET_HashCode sh;
492 GNUNET_CRYPTO_hash (skey,
495 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
496 "Deriving IV from SKEY %s and seed %u for peer %s\n",
499 GNUNET_i2s (identity));
501 GNUNET_CRYPTO_symmetric_derive_iv (iv,
503 &seed, sizeof (seed),
505 sizeof (struct GNUNET_PeerIdentity), ctx,
511 * Derive an IV from pong packet information
513 * @param iv initialization vector to initialize
514 * @param skey session key to use
515 * @param seed seed to use
516 * @param challenge nonce to use
517 * @param identity identity of the other peer to use
520 derive_pong_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
521 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
524 const struct GNUNET_PeerIdentity *identity)
526 static const char ctx[] = "pong initialization vector";
528 struct GNUNET_HashCode sh;
530 GNUNET_CRYPTO_hash (skey,
533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
534 "Deriving PONG IV from SKEY %s and seed %u/%u for %s\n",
537 (unsigned int) challenge,
538 GNUNET_i2s (identity));
540 GNUNET_CRYPTO_symmetric_derive_iv (iv,
542 &seed, sizeof (seed),
544 sizeof (struct GNUNET_PeerIdentity),
545 &challenge, sizeof (challenge),
552 * Derive an AES key from key material
554 * @param sender peer identity of the sender
555 * @param receiver peer identity of the sender
556 * @param key_material high entropy key material to use
557 * @param skey set to derived session key
560 derive_aes_key (const struct GNUNET_PeerIdentity *sender,
561 const struct GNUNET_PeerIdentity *receiver,
562 const struct GNUNET_HashCode *key_material,
563 struct GNUNET_CRYPTO_SymmetricSessionKey *skey)
565 static const char ctx[] = "aes key generation vector";
567 struct GNUNET_HashCode sh;
569 GNUNET_CRYPTO_hash (skey,
572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
573 "Deriving AES Keys for %s to %s from %s\n",
575 GNUNET_i2s2 (receiver),
576 GNUNET_h2s (key_material));
578 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
580 key_material, sizeof (struct GNUNET_HashCode),
581 sender, sizeof (struct GNUNET_PeerIdentity),
582 receiver, sizeof (struct GNUNET_PeerIdentity),
588 * Encrypt size bytes from @a in and write the result to @a out. Use the
589 * @a kx key for outbound traffic of the given neighbour.
591 * @param kx key information context
592 * @param iv initialization vector to use
593 * @param in ciphertext
594 * @param out plaintext
595 * @param size size of @a in/@a out
596 * @return #GNUNET_OK on success
599 do_encrypt (struct GSC_KeyExchangeInfo *kx,
600 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
605 if (size != (uint16_t) size)
610 GNUNET_assert (size ==
611 GNUNET_CRYPTO_symmetric_encrypt (in,
616 GNUNET_STATISTICS_update (GSC_stats,
617 gettext_noop ("# bytes encrypted"),
620 /* the following is too sensitive to write to log files by accident,
621 so we require manual intervention to get this one... */
623 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
624 "Encrypted %u bytes for `%s' using key %u, IV %u\n",
626 GNUNET_i2s (kx->peer),
627 (unsigned int) kx->encrypt_key.crc32,
628 GNUNET_CRYPTO_crc32_n (iv,
636 * Decrypt size bytes from @a in and write the result to @a out. Use
637 * the @a kx key for inbound traffic of the given neighbour. This
638 * function does NOT do any integrity-checks on the result.
640 * @param kx key information context
641 * @param iv initialization vector to use
642 * @param in ciphertext
643 * @param out plaintext
644 * @param size size of @a in / @a out
645 * @return #GNUNET_OK on success
648 do_decrypt (struct GSC_KeyExchangeInfo *kx,
649 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
654 if (size != (uint16_t) size)
659 if ( (kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
660 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
661 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT) )
664 return GNUNET_SYSERR;
667 GNUNET_CRYPTO_symmetric_decrypt (in,
674 return GNUNET_SYSERR;
676 GNUNET_STATISTICS_update (GSC_stats,
677 gettext_noop ("# bytes decrypted"),
680 /* the following is too sensitive to write to log files by accident,
681 so we require manual intervention to get this one... */
683 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
684 "Decrypted %u bytes from `%s' using key %u, IV %u\n",
686 GNUNET_i2s (kx->peer),
687 (unsigned int) kx->decrypt_key.crc32,
688 GNUNET_CRYPTO_crc32_n (iv,
697 * Send our key (and encrypted PING) to the other peer.
699 * @param kx key exchange context
702 send_key (struct GSC_KeyExchangeInfo *kx);
706 * Task that will retry #send_key() if our previous attempt failed.
708 * @param cls our `struct GSC_KeyExchangeInfo`
711 set_key_retry_task (void *cls)
713 struct GSC_KeyExchangeInfo *kx = cls;
715 kx->retry_set_key_task = NULL;
716 kx->set_key_retry_frequency = GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency);
717 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
723 * Create a fresh PING message for transmission to the other peer.
725 * @param kx key exchange context to create PING for
728 setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
730 struct PingMessage pp;
731 struct PingMessage *pm;
732 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
735 kx->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
737 pm->header.size = htons (sizeof (struct PingMessage));
738 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
739 pm->iv_seed = calculate_seed (kx);
744 pp.challenge = kx->ping_challenge;
745 pp.target = *kx->peer;
750 sizeof (struct PingMessage) - ((void *) &pm->target -
756 * Deliver P2P message to interested clients. Invokes send twice,
757 * once for clients that want the full message, and once for clients
758 * that only want the header
760 * @param cls the `struct GSC_KeyExchangeInfo`
761 * @param m the message
762 * @return #GNUNET_OK on success,
763 * #GNUNET_NO to stop further processing (no error)
764 * #GNUNET_SYSERR to stop further processing with error
767 deliver_message (void *cls,
768 const struct GNUNET_MessageHeader *m)
770 struct GSC_KeyExchangeInfo *kx = cls;
772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
773 "Decrypted message of type %d from %s\n",
775 GNUNET_i2s (kx->peer));
776 if (GNUNET_CORE_KX_STATE_UP != kx->status)
778 GNUNET_STATISTICS_update (GSC_stats,
779 gettext_noop ("# PAYLOAD dropped (out of order)"),
784 switch (ntohs (m->type))
786 case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
787 case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
788 GSC_SESSIONS_set_typemap (kx->peer, m);
790 case GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP:
791 GSC_SESSIONS_confirm_typemap (kx->peer, m);
794 GSC_CLIENTS_deliver_message (kx->peer,
797 GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
798 GSC_CLIENTS_deliver_message (kx->peer,
800 sizeof (struct GNUNET_MessageHeader),
801 GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
808 * Function called by transport to notify us that
809 * a peer connected to us (on the network level).
810 * Starts the key exchange with the given peer.
812 * @param cls closure (NULL)
813 * @param pid identity of the peer to do a key exchange with
814 * @return key exchange information context
817 handle_transport_notify_connect (void *cls,
818 const struct GNUNET_PeerIdentity *pid,
819 struct GNUNET_MQ_Handle *mq)
821 struct GSC_KeyExchangeInfo *kx;
822 struct GNUNET_HashCode h1;
823 struct GNUNET_HashCode h2;
825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
826 "Initiating key exchange with `%s'\n",
828 GNUNET_STATISTICS_update (GSC_stats,
829 gettext_noop ("# key exchanges initiated"),
832 kx = GNUNET_new (struct GSC_KeyExchangeInfo);
833 kx->mst = GNUNET_MST_create (&deliver_message,
837 kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
838 GNUNET_CONTAINER_DLL_insert (kx_head,
841 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
842 monitor_notify_all (kx);
843 GNUNET_CRYPTO_hash (pid,
844 sizeof (struct GNUNET_PeerIdentity),
846 GNUNET_CRYPTO_hash (&GSC_my_identity,
847 sizeof (struct GNUNET_PeerIdentity),
849 if (0 < GNUNET_CRYPTO_hash_cmp (&h1,
852 /* peer with "lower" identity starts KX, otherwise we typically end up
853 with both peers starting the exchange and transmit the 'set key'
859 /* peer with "higher" identity starts a delayed KX, if the "lower" peer
860 * does not start a KX since he sees no reasons to do so */
861 kx->retry_set_key_task
862 = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
871 * Function called by transport telling us that a peer
873 * Stop key exchange with the given peer. Clean up key material.
876 * @param peer the peer that disconnected
877 * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
880 handle_transport_notify_disconnect (void *cls,
881 const struct GNUNET_PeerIdentity *peer,
884 struct GSC_KeyExchangeInfo *kx = handler_cls;
886 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
887 "Peer `%s' disconnected from us.\n",
889 GSC_SESSIONS_end (kx->peer);
890 GNUNET_STATISTICS_update (GSC_stats,
891 gettext_noop ("# key exchanges stopped"),
894 if (NULL != kx->retry_set_key_task)
896 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
897 kx->retry_set_key_task = NULL;
899 if (NULL != kx->keep_alive_task)
901 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
902 kx->keep_alive_task = NULL;
904 kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
905 monitor_notify_all (kx);
906 GNUNET_CONTAINER_DLL_remove (kx_head,
909 GNUNET_MST_destroy (kx->mst);
915 * Send our PING to the other peer.
917 * @param kx key exchange context
920 send_ping (struct GSC_KeyExchangeInfo *kx)
922 struct GNUNET_MQ_Envelope *env;
924 GNUNET_STATISTICS_update (GSC_stats,
925 gettext_noop ("# PING messages transmitted"),
928 env = GNUNET_MQ_msg_copy (&kx->ping.header);
929 GNUNET_MQ_send (kx->mq,
935 * Derive fresh session keys from the current ephemeral keys.
937 * @param kx session to derive keys for
940 derive_session_keys (struct GSC_KeyExchangeInfo *kx)
942 struct GNUNET_HashCode key_material;
945 GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key,
946 &kx->other_ephemeral_key,
952 derive_aes_key (&GSC_my_identity,
956 derive_aes_key (kx->peer,
960 memset (&key_material, 0, sizeof (key_material));
961 /* fresh key, reset sequence numbers */
962 kx->last_sequence_number_received = 0;
963 kx->last_packets_bitmap = 0;
964 setup_fresh_ping (kx);
969 * We received a #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY message.
970 * Validate and update our key material and status.
972 * @param cls key exchange status for the corresponding peer
973 * @param m the set key message we received
976 handle_ephemeral_key (void *cls,
977 const struct EphemeralKeyMessage *m)
979 struct GSC_KeyExchangeInfo *kx = cls;
980 struct GNUNET_TIME_Absolute start_t;
981 struct GNUNET_TIME_Absolute end_t;
982 struct GNUNET_TIME_Absolute now;
983 enum GNUNET_CORE_KxState sender_status;
985 end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
986 if ( ( (GNUNET_CORE_KX_STATE_KEY_RECEIVED == kx->status) ||
987 (GNUNET_CORE_KX_STATE_UP == kx->status) ||
988 (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status) ) &&
989 (end_t.abs_value_us < kx->foreign_key_expires.abs_value_us) )
991 GNUNET_STATISTICS_update (GSC_stats,
992 gettext_noop ("# old ephemeral keys ignored"),
995 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
996 "Received expired EPHEMERAL_KEY from %s\n",
997 GNUNET_i2s (&m->origin_identity));
1000 if (0 == memcmp (&m->ephemeral_key,
1001 &kx->other_ephemeral_key,
1002 sizeof (m->ephemeral_key)))
1004 GNUNET_STATISTICS_update (GSC_stats,
1005 gettext_noop ("# duplicate ephemeral keys ignored"),
1008 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1009 "Ignoring duplicate EPHEMERAL_KEY from %s\n",
1010 GNUNET_i2s (&m->origin_identity));
1014 memcmp (&m->origin_identity,
1016 sizeof (struct GNUNET_PeerIdentity)))
1018 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1019 "Received EPHEMERAL_KEY from %s, but expected %s\n",
1020 GNUNET_i2s (&m->origin_identity),
1021 GNUNET_i2s_full (kx->peer));
1022 GNUNET_break_op (0);
1025 if ((ntohl (m->purpose.size) !=
1026 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
1027 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1028 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1029 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) +
1030 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) ||
1032 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY,
1035 &m->origin_identity.public_key)))
1037 /* invalid signature */
1038 GNUNET_break_op (0);
1039 GNUNET_STATISTICS_update (GSC_stats,
1040 gettext_noop ("# EPHEMERAL_KEYs rejected (bad signature)"),
1043 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1044 "Received EPHEMERAL_KEY from %s with bad signature\n",
1045 GNUNET_i2s (&m->origin_identity));
1048 now = GNUNET_TIME_absolute_get ();
1049 start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
1050 if ( (end_t.abs_value_us < GNUNET_TIME_absolute_subtract (now, REKEY_TOLERANCE).abs_value_us) ||
1051 (start_t.abs_value_us > GNUNET_TIME_absolute_add (now, REKEY_TOLERANCE).abs_value_us) )
1053 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1054 _("EPHERMAL_KEY from peer `%s' rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"),
1055 GNUNET_i2s (kx->peer),
1056 (unsigned long long) now.abs_value_us,
1057 (unsigned long long) start_t.abs_value_us,
1058 (unsigned long long) end_t.abs_value_us);
1059 GNUNET_STATISTICS_update (GSC_stats,
1060 gettext_noop ("# EPHEMERAL_KEY messages rejected due to time"),
1067 struct GNUNET_HashCode eh;
1069 GNUNET_CRYPTO_hash (&m->ephemeral_key,
1070 sizeof (m->ephemeral_key),
1072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1073 "Received valid EPHEMERAL_KEY `%s' from `%s' in state %d.\n",
1075 GNUNET_i2s (kx->peer),
1079 GNUNET_STATISTICS_update (GSC_stats,
1080 gettext_noop ("# valid ephemeral keys received"),
1083 kx->other_ephemeral_key = m->ephemeral_key;
1084 kx->foreign_key_expires = end_t;
1085 derive_session_keys (kx);
1087 /* check if we still need to send the sender our key */
1088 sender_status = (enum GNUNET_CORE_KxState) ntohl (m->sender_status);
1089 switch (sender_status)
1091 case GNUNET_CORE_KX_STATE_DOWN:
1092 GNUNET_break_op (0);
1094 case GNUNET_CORE_KX_STATE_KEY_SENT:
1095 /* fine, need to send our key after updating our status, see below */
1096 GSC_SESSIONS_reinit (kx->peer);
1098 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1099 /* other peer already got our key, but typemap did go down */
1100 GSC_SESSIONS_reinit (kx->peer);
1102 case GNUNET_CORE_KX_STATE_UP:
1103 /* other peer already got our key, typemap NOT down */
1105 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1106 /* other peer already got our key, typemap NOT down */
1112 /* check if we need to confirm everything is fine via PING + PONG */
1115 case GNUNET_CORE_KX_STATE_DOWN:
1116 GNUNET_assert (NULL == kx->keep_alive_task);
1117 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1118 monitor_notify_all (kx);
1119 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1124 case GNUNET_CORE_KX_STATE_KEY_SENT:
1125 GNUNET_assert (NULL == kx->keep_alive_task);
1126 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1127 monitor_notify_all (kx);
1128 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1133 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1134 GNUNET_assert (NULL == kx->keep_alive_task);
1135 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1140 case GNUNET_CORE_KX_STATE_UP:
1141 kx->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1142 monitor_notify_all (kx);
1143 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1148 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1149 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1162 * We received a PING message. Validate and transmit
1165 * @param cls key exchange status for the corresponding peer
1166 * @param m the encrypted PING message itself
1169 handle_ping (void *cls,
1170 const struct PingMessage *m)
1172 struct GSC_KeyExchangeInfo *kx = cls;
1173 struct PingMessage t;
1174 struct PongMessage tx;
1175 struct PongMessage *tp;
1176 struct GNUNET_MQ_Envelope *env;
1177 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1179 GNUNET_STATISTICS_update (GSC_stats,
1180 gettext_noop ("# PING messages received"),
1183 if ( (kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
1184 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
1185 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
1188 GNUNET_STATISTICS_update (GSC_stats,
1189 gettext_noop ("# PING messages dropped (out of order)"),
1194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1195 "Core service receives PING request from `%s'.\n",
1196 GNUNET_i2s (kx->peer));
1206 sizeof (struct PingMessage) - ((void *) &m->target -
1209 GNUNET_break_op (0);
1215 sizeof (struct GNUNET_PeerIdentity)))
1217 if (GNUNET_CORE_KX_STATE_REKEY_SENT != kx->status)
1218 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1219 "Decryption of PING from peer `%s' failed, PING for `%s'?\n",
1220 GNUNET_i2s (kx->peer),
1221 GNUNET_i2s2 (&t.target));
1223 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1224 "Decryption of PING from peer `%s' failed after rekey (harmless)\n",
1225 GNUNET_i2s (kx->peer));
1226 GNUNET_break_op (0);
1229 /* construct PONG */
1231 tx.challenge = t.challenge;
1232 tx.target = t.target;
1233 env = GNUNET_MQ_msg (tp,
1234 GNUNET_MESSAGE_TYPE_CORE_PONG);
1235 tp->iv_seed = calculate_seed (kx);
1236 derive_pong_iv (&iv,
1245 sizeof (struct PongMessage) - ((void *) &tp->challenge -
1247 GNUNET_STATISTICS_update (GSC_stats,
1248 gettext_noop ("# PONG messages created"),
1251 GNUNET_MQ_send (kx->mq,
1257 * Task triggered when a neighbour entry is about to time out
1258 * (and we should prevent this by sending a PING).
1260 * @param cls the `struct GSC_KeyExchangeInfo`
1263 send_keep_alive (void *cls)
1265 struct GSC_KeyExchangeInfo *kx = cls;
1266 struct GNUNET_TIME_Relative retry;
1267 struct GNUNET_TIME_Relative left;
1269 kx->keep_alive_task = NULL;
1270 left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
1271 if (0 == left.rel_value_us)
1273 GNUNET_STATISTICS_update (GSC_stats,
1274 gettext_noop ("# sessions terminated by timeout"),
1277 GSC_SESSIONS_end (kx->peer);
1278 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1279 monitor_notify_all (kx);
1283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1284 "Sending KEEPALIVE to `%s'\n",
1285 GNUNET_i2s (kx->peer));
1286 GNUNET_STATISTICS_update (GSC_stats,
1287 gettext_noop ("# keepalive messages sent"),
1290 setup_fresh_ping (kx);
1293 GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1294 MIN_PING_FREQUENCY);
1295 kx->keep_alive_task =
1296 GNUNET_SCHEDULER_add_delayed (retry,
1303 * We've seen a valid message from the other peer.
1304 * Update the time when the session would time out
1305 * and delay sending our keep alive message further.
1307 * @param kx key exchange where we saw activity
1310 update_timeout (struct GSC_KeyExchangeInfo *kx)
1312 struct GNUNET_TIME_Relative delta;
1315 GNUNET_TIME_relative_to_absolute
1316 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1317 delta = GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout,
1319 if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
1321 /* we only notify monitors about timeout changes if those
1322 are bigger than the threshold (5s) */
1323 monitor_notify_all (kx);
1325 if (NULL != kx->keep_alive_task)
1326 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1327 kx->keep_alive_task =
1328 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
1329 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1337 * We received a PONG message. Validate and update our status.
1339 * @param kx key exchange context for the the PONG
1340 * @param m the encrypted PONG message itself
1343 handle_pong (void *cls,
1344 const struct PongMessage *m)
1346 struct GSC_KeyExchangeInfo *kx = cls;
1347 struct PongMessage t;
1348 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1350 GNUNET_STATISTICS_update (GSC_stats,
1351 gettext_noop ("# PONG messages received"),
1356 case GNUNET_CORE_KX_STATE_DOWN:
1357 GNUNET_STATISTICS_update (GSC_stats,
1358 gettext_noop ("# PONG messages dropped (connection down)"), 1,
1361 case GNUNET_CORE_KX_STATE_KEY_SENT:
1362 GNUNET_STATISTICS_update (GSC_stats,
1363 gettext_noop ("# PONG messages dropped (out of order)"), 1,
1366 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1368 case GNUNET_CORE_KX_STATE_UP:
1370 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1377 "Core service receives PONG response from `%s'.\n",
1378 GNUNET_i2s (kx->peer));
1379 /* mark as garbage, just to be sure */
1380 memset (&t, 255, sizeof (t));
1381 derive_pong_iv (&iv,
1391 sizeof (struct PongMessage) - ((void *) &m->challenge -
1394 GNUNET_break_op (0);
1397 GNUNET_STATISTICS_update (GSC_stats,
1398 gettext_noop ("# PONG messages decrypted"),
1401 if ((0 != memcmp (&t.target,
1403 sizeof (struct GNUNET_PeerIdentity))) ||
1404 (kx->ping_challenge != t.challenge))
1406 /* PONG malformed */
1407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1408 "Received malformed PONG wanted sender `%s' with challenge %u\n",
1409 GNUNET_i2s (kx->peer),
1410 (unsigned int) kx->ping_challenge);
1411 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1412 "Received malformed PONG received from `%s' with challenge %u\n",
1413 GNUNET_i2s (&t.target),
1414 (unsigned int) t.challenge);
1417 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1418 "Received valid PONG from `%s'\n",
1419 GNUNET_i2s (kx->peer));
1420 /* no need to resend key any longer */
1421 if (NULL != kx->retry_set_key_task)
1423 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1424 kx->retry_set_key_task = NULL;
1428 case GNUNET_CORE_KX_STATE_DOWN:
1429 GNUNET_assert (0); /* should be impossible */
1431 case GNUNET_CORE_KX_STATE_KEY_SENT:
1432 GNUNET_assert (0); /* should be impossible */
1434 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1435 GNUNET_STATISTICS_update (GSC_stats,
1436 gettext_noop ("# session keys confirmed via PONG"),
1439 kx->status = GNUNET_CORE_KX_STATE_UP;
1440 monitor_notify_all (kx);
1441 GSC_SESSIONS_create (kx->peer, kx);
1442 GNUNET_assert (NULL == kx->keep_alive_task);
1443 update_timeout (kx);
1445 case GNUNET_CORE_KX_STATE_UP:
1446 GNUNET_STATISTICS_update (GSC_stats,
1447 gettext_noop ("# timeouts prevented via PONG"),
1450 update_timeout (kx);
1452 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1453 GNUNET_STATISTICS_update (GSC_stats,
1454 gettext_noop ("# rekey operations confirmed via PONG"),
1457 kx->status = GNUNET_CORE_KX_STATE_UP;
1458 monitor_notify_all (kx);
1459 update_timeout (kx);
1469 * Send our key to the other peer.
1471 * @param kx key exchange context
1474 send_key (struct GSC_KeyExchangeInfo *kx)
1476 struct GNUNET_MQ_Envelope *env;
1478 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
1479 if (NULL != kx->retry_set_key_task)
1481 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1482 kx->retry_set_key_task = NULL;
1484 /* always update sender status in SET KEY message */
1487 struct GNUNET_HashCode hc;
1489 GNUNET_CRYPTO_hash (¤t_ekm.ephemeral_key,
1490 sizeof (current_ekm.ephemeral_key),
1492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1493 "Sending EPHERMERAL_KEY %s to `%s' (my status: %d)\n",
1495 GNUNET_i2s (kx->peer),
1499 current_ekm.sender_status = htonl ((int32_t) (kx->status));
1500 env = GNUNET_MQ_msg_copy (¤t_ekm.header);
1501 GNUNET_MQ_send (kx->mq,
1503 if (GNUNET_CORE_KX_STATE_KEY_SENT != kx->status)
1505 kx->retry_set_key_task =
1506 GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
1507 &set_key_retry_task,
1513 * Encrypt and transmit a message with the given payload.
1515 * @param kx key exchange context
1516 * @param payload payload of the message
1517 * @param payload_size number of bytes in @a payload
1520 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
1521 const void *payload,
1522 size_t payload_size)
1524 size_t used = payload_size + sizeof (struct EncryptedMessage);
1525 char pbuf[used]; /* plaintext */
1526 struct EncryptedMessage *em; /* encrypted message */
1527 struct EncryptedMessage *ph; /* plaintext header */
1528 struct GNUNET_MQ_Envelope *env;
1529 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1530 struct GNUNET_CRYPTO_AuthKey auth_key;
1532 ph = (struct EncryptedMessage *) pbuf;
1533 ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1534 ph->iv_seed = calculate_seed (kx);
1536 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1537 GNUNET_memcpy (&ph[1],
1540 env = GNUNET_MQ_msg_extra (em,
1542 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
1543 em->iv_seed = ph->iv_seed;
1548 GNUNET_assert (GNUNET_OK ==
1551 &ph->sequence_number,
1552 &em->sequence_number,
1553 used - ENCRYPTED_HEADER_SIZE));
1556 struct GNUNET_HashCode hc;
1558 GNUNET_CRYPTO_hash (&ph->sequence_number,
1559 used - ENCRYPTED_HEADER_SIZE,
1561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1562 "Encrypted payload `%s' of %u bytes for %s\n",
1564 (unsigned int) (used - ENCRYPTED_HEADER_SIZE),
1565 GNUNET_i2s (kx->peer));
1568 derive_auth_key (&auth_key,
1571 GNUNET_CRYPTO_hmac (&auth_key,
1572 &em->sequence_number,
1573 used - ENCRYPTED_HEADER_SIZE,
1577 struct GNUNET_HashCode hc;
1579 GNUNET_CRYPTO_hash (&auth_key,
1582 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1583 "For peer %s, used AC %s to create hmac %s\n",
1584 GNUNET_i2s (kx->peer),
1586 GNUNET_h2s2 (&em->hmac));
1589 kx->has_excess_bandwidth = GNUNET_NO;
1590 GNUNET_MQ_send (kx->mq,
1596 * We received an encrypted message. Check that it is
1597 * well-formed (size-wise).
1599 * @param cls key exchange context for encrypting the message
1600 * @param m encrypted message
1601 * @return #GNUNET_OK if @a msg is well-formed (size-wise)
1604 check_encrypted (void *cls,
1605 const struct EncryptedMessage *m)
1607 uint16_t size = ntohs (m->header.size) - sizeof (*m);
1609 if (size < sizeof (struct GNUNET_MessageHeader))
1611 GNUNET_break_op (0);
1612 return GNUNET_SYSERR;
1619 * We received an encrypted message. Decrypt, validate and
1620 * pass on to the appropriate clients.
1622 * @param cls key exchange context for encrypting the message
1623 * @param m encrypted message
1626 handle_encrypted (void *cls,
1627 const struct EncryptedMessage *m)
1629 struct GSC_KeyExchangeInfo *kx = cls;
1630 struct EncryptedMessage *pt; /* plaintext */
1631 struct GNUNET_HashCode ph;
1633 struct GNUNET_TIME_Absolute t;
1634 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1635 struct GNUNET_CRYPTO_AuthKey auth_key;
1636 uint16_t size = ntohs (m->header.size);
1637 char buf[size] GNUNET_ALIGN;
1639 if (GNUNET_CORE_KX_STATE_UP != kx->status)
1641 GNUNET_STATISTICS_update (GSC_stats,
1642 gettext_noop ("# DATA message dropped (out of order)"),
1647 if (0 == GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value_us)
1649 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1650 _("Session to peer `%s' went down due to key expiration (should not happen)\n"),
1651 GNUNET_i2s (kx->peer));
1652 GNUNET_STATISTICS_update (GSC_stats,
1653 gettext_noop ("# sessions terminated by key expiration"),
1655 GSC_SESSIONS_end (kx->peer);
1656 if (NULL != kx->keep_alive_task)
1658 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1659 kx->keep_alive_task = NULL;
1661 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1662 monitor_notify_all (kx);
1670 struct GNUNET_HashCode hc;
1672 GNUNET_CRYPTO_hash (&m->sequence_number,
1673 size - ENCRYPTED_HEADER_SIZE,
1675 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1676 "Received encrypted payload `%s' of %u bytes from %s\n",
1678 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1679 GNUNET_i2s (kx->peer));
1682 derive_auth_key (&auth_key,
1685 GNUNET_CRYPTO_hmac (&auth_key,
1686 &m->sequence_number,
1687 size - ENCRYPTED_HEADER_SIZE,
1691 struct GNUNET_HashCode hc;
1693 GNUNET_CRYPTO_hash (&auth_key,
1696 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1697 "For peer %s, used AC %s to verify hmac %s\n",
1698 GNUNET_i2s (kx->peer),
1700 GNUNET_h2s2 (&m->hmac));
1703 if (0 != memcmp (&ph,
1705 sizeof (struct GNUNET_HashCode)))
1707 /* checksum failed */
1708 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1709 "Failed checksum validation for a message from `%s'\n",
1710 GNUNET_i2s (kx->peer));
1721 &m->sequence_number,
1722 &buf[ENCRYPTED_HEADER_SIZE],
1723 size - ENCRYPTED_HEADER_SIZE))
1725 GNUNET_break_op (0);
1728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1729 "Decrypted %u bytes from %s\n",
1730 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1731 GNUNET_i2s (kx->peer));
1732 pt = (struct EncryptedMessage *) buf;
1734 /* validate sequence number */
1735 snum = ntohl (pt->sequence_number);
1736 if (kx->last_sequence_number_received == snum)
1738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1739 "Received duplicate message, ignoring.\n");
1740 /* duplicate, ignore */
1741 GNUNET_STATISTICS_update (GSC_stats,
1742 gettext_noop ("# bytes dropped (duplicates)"),
1747 if ((kx->last_sequence_number_received > snum) &&
1748 (kx->last_sequence_number_received - snum > 32))
1750 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1751 "Received ancient out of sequence message, ignoring.\n");
1752 /* ancient out of sequence, ignore */
1753 GNUNET_STATISTICS_update (GSC_stats,
1755 ("# bytes dropped (out of sequence)"), size,
1759 if (kx->last_sequence_number_received > snum)
1761 uint32_t rotbit = 1U << (kx->last_sequence_number_received - snum - 1);
1763 if ((kx->last_packets_bitmap & rotbit) != 0)
1765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1766 "Received duplicate message, ignoring.\n");
1767 GNUNET_STATISTICS_update (GSC_stats,
1768 gettext_noop ("# bytes dropped (duplicates)"),
1770 /* duplicate, ignore */
1773 kx->last_packets_bitmap |= rotbit;
1775 if (kx->last_sequence_number_received < snum)
1777 unsigned int shift = (snum - kx->last_sequence_number_received);
1779 if (shift >= 8 * sizeof (kx->last_packets_bitmap))
1780 kx->last_packets_bitmap = 0;
1782 kx->last_packets_bitmap <<= shift;
1783 kx->last_sequence_number_received = snum;
1786 /* check timestamp */
1787 t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
1788 if (GNUNET_TIME_absolute_get_duration (t).rel_value_us >
1789 MAX_MESSAGE_AGE.rel_value_us)
1791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1792 "Message received far too old (%s). Content ignored.\n",
1793 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (t),
1795 GNUNET_STATISTICS_update (GSC_stats,
1797 ("# bytes dropped (ancient message)"), size,
1802 /* process decrypted message(s) */
1803 update_timeout (kx);
1804 GNUNET_STATISTICS_update (GSC_stats,
1805 gettext_noop ("# bytes of payload decrypted"),
1806 size - sizeof (struct EncryptedMessage),
1809 GNUNET_MST_from_buffer (kx->mst,
1810 &buf[sizeof (struct EncryptedMessage)],
1811 size - sizeof (struct EncryptedMessage),
1814 GNUNET_break_op (0);
1819 * One of our neighbours has excess bandwidth, remember this.
1822 * @param pid identity of the peer with excess bandwidth
1823 * @param connect_cls the `struct Neighbour`
1826 handle_transport_notify_excess_bw (void *cls,
1827 const struct GNUNET_PeerIdentity *pid,
1830 struct GSC_KeyExchangeInfo *kx = connect_cls;
1832 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1833 "Peer %s has excess bandwidth available\n",
1835 kx->has_excess_bandwidth = GNUNET_YES;
1836 GSC_SESSIONS_solicit (pid);
1841 * Setup the message that links the ephemeral key to our persistent
1842 * public key and generate the appropriate signature.
1845 sign_ephemeral_key ()
1847 current_ekm.header.size = htons (sizeof (struct EphemeralKeyMessage));
1848 current_ekm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY);
1849 current_ekm.sender_status = 0; /* to be set later */
1850 current_ekm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY);
1851 current_ekm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
1852 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1853 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1854 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
1855 sizeof (struct GNUNET_PeerIdentity));
1856 current_ekm.creation_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1858 GNUNET_CONFIGURATION_get_value_yesno (GSC_cfg,
1860 "USE_EPHEMERAL_KEYS"))
1862 current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_add (REKEY_FREQUENCY,
1867 current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1869 GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key,
1870 ¤t_ekm.ephemeral_key);
1871 current_ekm.origin_identity = GSC_my_identity;
1872 GNUNET_assert (GNUNET_OK ==
1873 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1874 ¤t_ekm.purpose,
1875 ¤t_ekm.signature));
1880 * Task run to trigger rekeying.
1882 * @param cls closure, NULL
1885 do_rekey (void *cls)
1887 struct GSC_KeyExchangeInfo *pos;
1889 rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY,
1892 if (NULL != my_ephemeral_key)
1893 GNUNET_free (my_ephemeral_key);
1894 my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
1895 GNUNET_assert (NULL != my_ephemeral_key);
1896 sign_ephemeral_key ();
1898 struct GNUNET_HashCode eh;
1900 GNUNET_CRYPTO_hash (¤t_ekm.ephemeral_key,
1901 sizeof (current_ekm.ephemeral_key),
1903 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1907 for (pos = kx_head; NULL != pos; pos = pos->next)
1909 if (GNUNET_CORE_KX_STATE_UP == pos->status)
1911 pos->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1912 monitor_notify_all (pos);
1913 derive_session_keys (pos);
1915 if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
1917 pos->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1918 monitor_notify_all (pos);
1920 monitor_notify_all (pos);
1927 * Initialize KX subsystem.
1929 * @param pk private key to use for the peer
1930 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1933 GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
1935 struct GNUNET_MQ_MessageHandler handlers[] = {
1936 GNUNET_MQ_hd_fixed_size (ephemeral_key,
1937 GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
1938 struct EphemeralKeyMessage,
1940 GNUNET_MQ_hd_fixed_size (ping,
1941 GNUNET_MESSAGE_TYPE_CORE_PING,
1944 GNUNET_MQ_hd_fixed_size (pong,
1945 GNUNET_MESSAGE_TYPE_CORE_PONG,
1948 GNUNET_MQ_hd_var_size (encrypted,
1949 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE,
1950 struct EncryptedMessage,
1952 GNUNET_MQ_handler_end()
1955 my_private_key = pk;
1956 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1957 &GSC_my_identity.public_key);
1958 my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
1959 if (NULL == my_ephemeral_key)
1962 GNUNET_free (my_private_key);
1963 my_private_key = NULL;
1964 return GNUNET_SYSERR;
1966 sign_ephemeral_key ();
1968 struct GNUNET_HashCode eh;
1970 GNUNET_CRYPTO_hash (¤t_ekm.ephemeral_key,
1971 sizeof (current_ekm.ephemeral_key),
1973 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1974 "Starting with ephemeral key %s\n",
1978 nc = GNUNET_notification_context_create (1);
1979 rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY,
1983 = GNUNET_TRANSPORT_core_connect (GSC_cfg,
1987 &handle_transport_notify_connect,
1988 &handle_transport_notify_disconnect,
1989 &handle_transport_notify_excess_bw);
1990 if (NULL == transport)
1993 return GNUNET_SYSERR;
2000 * Shutdown KX subsystem.
2005 if (NULL != transport)
2007 GNUNET_TRANSPORT_core_disconnect (transport);
2010 if (NULL != rekey_task)
2012 GNUNET_SCHEDULER_cancel (rekey_task);
2015 if (NULL != my_ephemeral_key)
2017 GNUNET_free (my_ephemeral_key);
2018 my_ephemeral_key = NULL;
2020 if (NULL != my_private_key)
2022 GNUNET_free (my_private_key);
2023 my_private_key = NULL;
2027 GNUNET_notification_context_destroy (nc);
2034 * Check how many messages are queued for the given neighbour.
2036 * @param kxinfo data about neighbour to check
2037 * @return number of items in the message queue
2040 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
2042 return GNUNET_MQ_get_length (kxinfo->mq);
2047 * Check if the given neighbour has excess bandwidth available.
2049 * @param target neighbour to check
2050 * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
2053 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
2055 return kxinfo->has_excess_bandwidth;
2060 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
2061 * request type, the client does not have to have transmitted an INIT
2062 * request. All current peers are returned, regardless of which
2063 * message types they accept.
2065 * @param mq message queue to add for monitoring
2068 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
2070 struct GNUNET_MQ_Envelope *env;
2071 struct MonitorNotifyMessage *done_msg;
2072 struct GSC_KeyExchangeInfo *kx;
2074 GNUNET_notification_context_add (nc,
2076 for (kx = kx_head; NULL != kx; kx = kx->next)
2078 struct GNUNET_MQ_Envelope *env;
2079 struct MonitorNotifyMessage *msg;
2081 env = GNUNET_MQ_msg (msg,
2082 GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
2083 msg->state = htonl ((uint32_t) kx->status);
2084 msg->peer = *kx->peer;
2085 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
2089 env = GNUNET_MQ_msg (done_msg,
2090 GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
2091 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
2092 done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
2098 /* end of gnunet-service-core_kx.c */