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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file core/gnunet-service-core_kx.c
23 * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other
25 * @author Christian Grothoff
28 #include "gnunet-service-core_kx.h"
29 #include "gnunet-service-core.h"
30 #include "gnunet-service-core_sessions.h"
31 #include "gnunet_statistics_service.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_constants.h"
34 #include "gnunet_signatures.h"
35 #include "gnunet_protocols.h"
39 * Enable expensive (and possibly problematic for privacy!) logging of KX.
44 * How long do we wait for SET_KEY confirmation initially?
46 #define INITIAL_SET_KEY_RETRY_FREQUENCY \
47 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
50 * What is the minimum frequency for a PING message?
52 #define MIN_PING_FREQUENCY \
53 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
56 * How often do we rekey?
58 #define REKEY_FREQUENCY \
59 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
62 * What time difference do we tolerate?
64 #define REKEY_TOLERANCE \
65 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
68 * What is the maximum age of a message for us to consider processing
69 * it? Note that this looks at the timestamp used by the other peer,
70 * so clock skew between machines does come into play here. So this
71 * should be picked high enough so that a little bit of clock skew
72 * does not prevent peers from connecting to us.
74 #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
77 GNUNET_NETWORK_STRUCT_BEGIN
80 * Message transmitted with the signed ephemeral key of a peer. The
81 * session key is then derived from the two ephemeral keys (ECDHE).
83 struct EphemeralKeyMessage
87 * Message type is #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY.
89 struct GNUNET_MessageHeader header;
92 * Status of the sender (should be in `enum PeerStateMachine`), nbo.
94 int32_t sender_status GNUNET_PACKED;
97 * An ECC signature of the @e origin_identity asserting the validity
98 * of the given ephemeral key.
100 struct GNUNET_CRYPTO_EddsaSignature signature;
103 * Information about what is being signed.
105 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
108 * At what time was this key created (beginning of validity).
110 struct GNUNET_TIME_AbsoluteNBO creation_time;
113 * When does the given ephemeral key expire (end of validity).
115 struct GNUNET_TIME_AbsoluteNBO expiration_time;
118 * Ephemeral public ECC key.
120 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
123 * Public key of the signing peer (persistent version, not the
124 * ephemeral public key).
126 struct GNUNET_PeerIdentity origin_identity;
131 * We're sending an (encrypted) PING to the other peer to check if it
132 * can decrypt. The other peer should respond with a PONG with the
133 * same content, except this time encrypted with the receiver's key.
138 * Message type is #GNUNET_MESSAGE_TYPE_CORE_PING.
140 struct GNUNET_MessageHeader header;
145 uint32_t iv_seed GNUNET_PACKED;
148 * Intended target of the PING, used primarily to check
149 * that decryption actually worked.
151 struct GNUNET_PeerIdentity target;
154 * Random number chosen to make replay harder.
156 uint32_t challenge GNUNET_PACKED;
161 * Response to a PING. Includes data from the original PING.
166 * Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG.
168 struct GNUNET_MessageHeader header;
173 uint32_t iv_seed GNUNET_PACKED;
176 * Random number to make replay attacks harder.
178 uint32_t challenge GNUNET_PACKED;
181 * Reserved, always zero.
186 * Intended target of the PING, used primarily to check
187 * that decryption actually worked.
189 struct GNUNET_PeerIdentity target;
194 * Encapsulation for encrypted messages exchanged between
195 * peers. Followed by the actual encrypted data.
197 struct EncryptedMessage
200 * Message type is #GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE.
202 struct GNUNET_MessageHeader header;
205 * Random value used for IV generation.
207 uint32_t iv_seed GNUNET_PACKED;
210 * MAC of the encrypted message (starting at @e sequence_number),
211 * used to verify message integrity. Everything after this value
212 * (excluding this value itself) will be encrypted and
213 * authenticated. #ENCRYPTED_HEADER_SIZE must be set to the offset
214 * of the *next* field.
216 struct GNUNET_HashCode hmac;
219 * Sequence number, in network byte order. This field
220 * must be the first encrypted/decrypted field
222 uint32_t sequence_number GNUNET_PACKED;
225 * Reserved, always zero.
227 uint32_t reserved GNUNET_PACKED;
230 * Timestamp. Used to prevent replay of ancient messages
231 * (recent messages are caught with the sequence number).
233 struct GNUNET_TIME_AbsoluteNBO timestamp;
235 GNUNET_NETWORK_STRUCT_END
239 * Number of bytes (at the beginning) of `struct EncryptedMessage`
240 * that are NOT encrypted.
242 #define ENCRYPTED_HEADER_SIZE \
243 (offsetof (struct EncryptedMessage, sequence_number))
247 * Information about the status of a key exchange with another peer.
249 struct GSC_KeyExchangeInfo
255 struct GSC_KeyExchangeInfo *next;
260 struct GSC_KeyExchangeInfo *prev;
263 * Identity of the peer.
265 const struct GNUNET_PeerIdentity *peer;
268 * Message queue for sending messages to @a peer.
270 struct GNUNET_MQ_Handle *mq;
273 * Our message stream tokenizer (for encrypted payload).
275 struct GNUNET_MessageStreamTokenizer *mst;
278 * PING message we transmit to the other peer.
280 struct PingMessage ping;
283 * Ephemeral public ECC key of the other peer.
285 struct GNUNET_CRYPTO_EcdhePublicKey other_ephemeral_key;
288 * Key we use to encrypt our messages for the other peer
289 * (initialized by us when we do the handshake).
291 struct GNUNET_CRYPTO_SymmetricSessionKey encrypt_key;
294 * Key we use to decrypt messages from the other peer
295 * (given to us by the other peer during the handshake).
297 struct GNUNET_CRYPTO_SymmetricSessionKey decrypt_key;
300 * At what time did the other peer generate the decryption key?
302 struct GNUNET_TIME_Absolute foreign_key_expires;
305 * When should the session time out (if there are no PONGs)?
307 struct GNUNET_TIME_Absolute timeout;
310 * What was the last timeout we informed our monitors about?
312 struct GNUNET_TIME_Absolute last_notify_timeout;
315 * At what frequency are we currently re-trying SET_KEY messages?
317 struct GNUNET_TIME_Relative set_key_retry_frequency;
320 * ID of task used for re-trying SET_KEY and PING message.
322 struct GNUNET_SCHEDULER_Task *retry_set_key_task;
325 * ID of task used for sending keep-alive pings.
327 struct GNUNET_SCHEDULER_Task *keep_alive_task;
330 * Bit map indicating which of the 32 sequence numbers before the
331 * last were received (good for accepting out-of-order packets and
332 * estimating reliability of the connection)
334 uint32_t last_packets_bitmap;
337 * last sequence number received on this connection (highest)
339 uint32_t last_sequence_number_received;
342 * last sequence number transmitted
344 uint32_t last_sequence_number_sent;
347 * What was our PING challenge number (for this peer)?
349 uint32_t ping_challenge;
352 * #GNUNET_YES if this peer currently has excess bandwidth.
354 int has_excess_bandwidth;
357 * What is our connection status?
359 enum GNUNET_CORE_KxState status;
366 static struct GNUNET_TRANSPORT_CoreHandle *transport;
371 static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
374 * Our ephemeral private key.
376 static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key;
379 * Current message we send for a key exchange.
381 static struct EphemeralKeyMessage current_ekm;
386 static struct GSC_KeyExchangeInfo *kx_head;
391 static struct GSC_KeyExchangeInfo *kx_tail;
394 * Task scheduled for periodic re-generation (and thus rekeying) of our
397 static struct GNUNET_SCHEDULER_Task *rekey_task;
400 * Notification context for broadcasting to monitors.
402 static struct GNUNET_NotificationContext *nc;
406 * Calculate seed value we should use for a message.
408 * @param kx key exchange context
411 calculate_seed (struct GSC_KeyExchangeInfo *kx)
413 /* Note: may want to make this non-random and instead
414 derive from key material to avoid having an undetectable
417 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
422 * Inform all monitors about the KX state of the given peer.
424 * @param kx key exchange state to inform about
427 monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
429 struct MonitorNotifyMessage msg;
431 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
432 msg.header.size = htons (sizeof (msg));
433 msg.state = htonl ((uint32_t) kx->status);
434 msg.peer = *kx->peer;
435 msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
436 GNUNET_notification_context_broadcast (nc, &msg.header, GNUNET_NO);
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, sizeof (*skey), &sh);
458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
459 "Deriving Auth key from SKEY %s and seed %u\n",
461 (unsigned int) seed);
463 GNUNET_CRYPTO_hmac_derive_key (akey,
469 struct GNUNET_CRYPTO_SymmetricSessionKey),
477 * Derive an IV from packet information
479 * @param iv initialization vector to initialize
480 * @param skey session key to use
481 * @param seed seed to use
482 * @param identity identity of the other peer to use
485 derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
486 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
488 const struct GNUNET_PeerIdentity *identity)
490 static const char ctx[] = "initialization vector";
492 struct GNUNET_HashCode sh;
494 GNUNET_CRYPTO_hash (skey, sizeof (*skey), &sh);
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,
506 sizeof (struct GNUNET_PeerIdentity),
514 * Derive an IV from pong packet information
516 * @param iv initialization vector to initialize
517 * @param skey session key to use
518 * @param seed seed to use
519 * @param challenge nonce to use
520 * @param identity identity of the other peer to use
523 derive_pong_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
524 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
527 const struct GNUNET_PeerIdentity *identity)
529 static const char ctx[] = "pong initialization vector";
531 struct GNUNET_HashCode sh;
533 GNUNET_CRYPTO_hash (skey, sizeof (*skey), &sh);
534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
535 "Deriving PONG IV from SKEY %s and seed %u/%u for %s\n",
538 (unsigned int) challenge,
539 GNUNET_i2s (identity));
541 GNUNET_CRYPTO_symmetric_derive_iv (iv,
546 sizeof (struct GNUNET_PeerIdentity),
556 * Derive an AES key from key material
558 * @param sender peer identity of the sender
559 * @param receiver peer identity of the sender
560 * @param key_material high entropy key material to use
561 * @param skey set to derived session key
564 derive_aes_key (const struct GNUNET_PeerIdentity *sender,
565 const struct GNUNET_PeerIdentity *receiver,
566 const struct GNUNET_HashCode *key_material,
567 struct GNUNET_CRYPTO_SymmetricSessionKey *skey)
569 static const char ctx[] = "aes key generation vector";
571 struct GNUNET_HashCode sh;
573 GNUNET_CRYPTO_hash (skey, sizeof (*skey), &sh);
574 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
575 "Deriving AES Keys for %s to %s from %s\n",
577 GNUNET_i2s2 (receiver),
578 GNUNET_h2s (key_material));
580 GNUNET_CRYPTO_kdf (skey,
581 sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
585 sizeof (struct GNUNET_HashCode),
587 sizeof (struct GNUNET_PeerIdentity),
589 sizeof (struct GNUNET_PeerIdentity),
595 * Encrypt size bytes from @a in and write the result to @a out. Use the
596 * @a kx key for outbound traffic of the given neighbour.
598 * @param kx key information context
599 * @param iv initialization vector to use
600 * @param in ciphertext
601 * @param out plaintext
602 * @param size size of @a in/@a out
603 * @return #GNUNET_OK on success
606 do_encrypt (struct GSC_KeyExchangeInfo *kx,
607 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
612 if (size != (uint16_t) size)
617 GNUNET_assert (size == GNUNET_CRYPTO_symmetric_encrypt (in,
622 GNUNET_STATISTICS_update (GSC_stats,
623 gettext_noop ("# bytes encrypted"),
626 /* the following is too sensitive to write to log files by accident,
627 so we require manual intervention to get this one... */
629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
630 "Encrypted %u bytes for `%s' using key %u, IV %u\n",
632 GNUNET_i2s (kx->peer),
633 (unsigned int) kx->encrypt_key.crc32,
634 GNUNET_CRYPTO_crc32_n (iv, sizeof (iv)));
641 * Decrypt size bytes from @a in and write the result to @a out. Use
642 * the @a kx key for inbound traffic of the given neighbour. This
643 * function does NOT do any integrity-checks on the result.
645 * @param kx key information context
646 * @param iv initialization vector to use
647 * @param in ciphertext
648 * @param out plaintext
649 * @param size size of @a in / @a out
650 * @return #GNUNET_OK on success
653 do_decrypt (struct GSC_KeyExchangeInfo *kx,
654 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
659 if (size != (uint16_t) size)
664 if ((kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
665 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
666 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
669 return GNUNET_SYSERR;
671 if (size != GNUNET_CRYPTO_symmetric_decrypt (in,
678 return GNUNET_SYSERR;
680 GNUNET_STATISTICS_update (GSC_stats,
681 gettext_noop ("# bytes decrypted"),
684 /* the following is too sensitive to write to log files by accident,
685 so we require manual intervention to get this one... */
687 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
688 "Decrypted %u bytes from `%s' using key %u, IV %u\n",
690 GNUNET_i2s (kx->peer),
691 (unsigned int) kx->decrypt_key.crc32,
692 GNUNET_CRYPTO_crc32_n (iv, sizeof (*iv)));
699 * Send our key (and encrypted PING) to the other peer.
701 * @param kx key exchange context
704 send_key (struct GSC_KeyExchangeInfo *kx);
708 * Task that will retry #send_key() if our previous attempt failed.
710 * @param cls our `struct GSC_KeyExchangeInfo`
713 set_key_retry_task (void *cls)
715 struct GSC_KeyExchangeInfo *kx = cls;
717 kx->retry_set_key_task = NULL;
718 kx->set_key_retry_frequency =
719 GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency);
720 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
726 * Create a fresh PING message for transmission to the other peer.
728 * @param kx key exchange context to create PING for
731 setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
733 struct PingMessage pp;
734 struct PingMessage *pm;
735 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
739 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
740 pm->header.size = htons (sizeof (struct PingMessage));
741 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
742 pm->iv_seed = calculate_seed (kx);
743 derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, kx->peer);
744 pp.challenge = kx->ping_challenge;
745 pp.target = *kx->peer;
750 sizeof (struct PingMessage) -
751 ((void *) &pm->target - (void *) pm));
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, const struct GNUNET_MessageHeader *m)
769 struct GSC_KeyExchangeInfo *kx = cls;
771 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
772 "Decrypted message of type %d from %s\n",
774 GNUNET_i2s (kx->peer));
775 if (GNUNET_CORE_KX_STATE_UP != kx->status)
777 GNUNET_STATISTICS_update (GSC_stats,
778 gettext_noop ("# PAYLOAD dropped (out of order)"),
783 switch (ntohs (m->type))
785 case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
786 case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
787 GSC_SESSIONS_set_typemap (kx->peer, m);
789 case GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP:
790 GSC_SESSIONS_confirm_typemap (kx->peer, m);
793 GSC_CLIENTS_deliver_message (kx->peer,
796 GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
797 GSC_CLIENTS_deliver_message (kx->peer,
799 sizeof (struct GNUNET_MessageHeader),
800 GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
807 * Function called by transport to notify us that
808 * a peer connected to us (on the network level).
809 * Starts the key exchange with the given peer.
811 * @param cls closure (NULL)
812 * @param pid identity of the peer to do a key exchange with
813 * @return key exchange information context
816 handle_transport_notify_connect (void *cls,
817 const struct GNUNET_PeerIdentity *pid,
818 struct GNUNET_MQ_Handle *mq)
820 struct GSC_KeyExchangeInfo *kx;
821 struct GNUNET_HashCode h1;
822 struct GNUNET_HashCode h2;
824 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
825 "Initiating key exchange with `%s'\n",
827 GNUNET_STATISTICS_update (GSC_stats,
828 gettext_noop ("# key exchanges initiated"),
831 kx = GNUNET_new (struct GSC_KeyExchangeInfo);
832 kx->mst = GNUNET_MST_create (&deliver_message, kx);
835 kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
836 GNUNET_CONTAINER_DLL_insert (kx_head, kx_tail, kx);
837 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
838 monitor_notify_all (kx);
839 GNUNET_CRYPTO_hash (pid, sizeof (struct GNUNET_PeerIdentity), &h1);
840 GNUNET_CRYPTO_hash (&GSC_my_identity,
841 sizeof (struct GNUNET_PeerIdentity),
843 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2))
845 /* peer with "lower" identity starts KX, otherwise we typically end up
846 with both peers starting the exchange and transmit the 'set key'
852 /* peer with "higher" identity starts a delayed KX, if the "lower" peer
853 * does not start a KX since it sees no reasons to do so */
854 kx->retry_set_key_task =
855 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
864 * Function called by transport telling us that a peer
866 * Stop key exchange with the given peer. Clean up key material.
869 * @param peer the peer that disconnected
870 * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
873 handle_transport_notify_disconnect (void *cls,
874 const struct GNUNET_PeerIdentity *peer,
877 struct GSC_KeyExchangeInfo *kx = handler_cls;
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
880 "Peer `%s' disconnected from us.\n",
882 GSC_SESSIONS_end (kx->peer);
883 GNUNET_STATISTICS_update (GSC_stats,
884 gettext_noop ("# key exchanges stopped"),
887 if (NULL != kx->retry_set_key_task)
889 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
890 kx->retry_set_key_task = NULL;
892 if (NULL != kx->keep_alive_task)
894 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
895 kx->keep_alive_task = NULL;
897 kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
898 monitor_notify_all (kx);
899 GNUNET_CONTAINER_DLL_remove (kx_head, kx_tail, kx);
900 GNUNET_MST_destroy (kx->mst);
906 * Send our PING to the other peer.
908 * @param kx key exchange context
911 send_ping (struct GSC_KeyExchangeInfo *kx)
913 struct GNUNET_MQ_Envelope *env;
915 GNUNET_STATISTICS_update (GSC_stats,
916 gettext_noop ("# PING messages transmitted"),
919 env = GNUNET_MQ_msg_copy (&kx->ping.header);
920 GNUNET_MQ_send (kx->mq, env);
925 * Derive fresh session keys from the current ephemeral keys.
927 * @param kx session to derive keys for
930 derive_session_keys (struct GSC_KeyExchangeInfo *kx)
932 struct GNUNET_HashCode key_material;
934 if (GNUNET_OK != GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key,
935 &kx->other_ephemeral_key,
941 derive_aes_key (&GSC_my_identity, kx->peer, &key_material, &kx->encrypt_key);
942 derive_aes_key (kx->peer, &GSC_my_identity, &key_material, &kx->decrypt_key);
943 memset (&key_material, 0, sizeof (key_material));
944 /* fresh key, reset sequence numbers */
945 kx->last_sequence_number_received = 0;
946 kx->last_packets_bitmap = 0;
947 setup_fresh_ping (kx);
952 * We received a #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY message.
953 * Validate and update our key material and status.
955 * @param cls key exchange status for the corresponding peer
956 * @param m the set key message we received
959 handle_ephemeral_key (void *cls, const struct EphemeralKeyMessage *m)
961 struct GSC_KeyExchangeInfo *kx = cls;
962 struct GNUNET_TIME_Absolute start_t;
963 struct GNUNET_TIME_Absolute end_t;
964 struct GNUNET_TIME_Absolute now;
965 enum GNUNET_CORE_KxState sender_status;
967 end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
968 if (((GNUNET_CORE_KX_STATE_KEY_RECEIVED == kx->status) ||
969 (GNUNET_CORE_KX_STATE_UP == kx->status) ||
970 (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status)) &&
971 (end_t.abs_value_us < kx->foreign_key_expires.abs_value_us))
973 GNUNET_STATISTICS_update (GSC_stats,
974 gettext_noop ("# old ephemeral keys ignored"),
977 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
978 "Received expired EPHEMERAL_KEY from %s\n",
979 GNUNET_i2s (&m->origin_identity));
982 if (0 == memcmp (&m->ephemeral_key,
983 &kx->other_ephemeral_key,
984 sizeof (m->ephemeral_key)))
986 GNUNET_STATISTICS_update (GSC_stats,
988 "# duplicate ephemeral keys ignored"),
991 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
992 "Ignoring duplicate EPHEMERAL_KEY from %s\n",
993 GNUNET_i2s (&m->origin_identity));
996 if (0 != memcmp (&m->origin_identity,
998 sizeof (struct GNUNET_PeerIdentity)))
1000 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1001 "Received EPHEMERAL_KEY from %s, but expected %s\n",
1002 GNUNET_i2s (&m->origin_identity),
1003 GNUNET_i2s_full (kx->peer));
1004 GNUNET_break_op (0);
1007 if ((ntohl (m->purpose.size) !=
1008 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
1009 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1010 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1011 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) +
1012 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) ||
1014 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY,
1017 &m->origin_identity.public_key)))
1019 /* invalid signature */
1020 GNUNET_break_op (0);
1021 GNUNET_STATISTICS_update (GSC_stats,
1023 "# EPHEMERAL_KEYs rejected (bad signature)"),
1026 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1027 "Received EPHEMERAL_KEY from %s with bad signature\n",
1028 GNUNET_i2s (&m->origin_identity));
1031 now = GNUNET_TIME_absolute_get ();
1032 start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
1033 if ((end_t.abs_value_us <
1034 GNUNET_TIME_absolute_subtract (now, REKEY_TOLERANCE).abs_value_us) ||
1035 (start_t.abs_value_us >
1036 GNUNET_TIME_absolute_add (now, REKEY_TOLERANCE).abs_value_us))
1039 GNUNET_ERROR_TYPE_WARNING,
1041 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"),
1042 GNUNET_i2s (kx->peer),
1043 (unsigned long long) now.abs_value_us,
1044 (unsigned long long) start_t.abs_value_us,
1045 (unsigned long long) end_t.abs_value_us);
1046 GNUNET_STATISTICS_update (GSC_stats,
1048 "# EPHEMERAL_KEY messages rejected due to time"),
1055 struct GNUNET_HashCode eh;
1057 GNUNET_CRYPTO_hash (&m->ephemeral_key, sizeof (m->ephemeral_key), &eh);
1058 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1059 "Received valid EPHEMERAL_KEY `%s' from `%s' in state %d.\n",
1061 GNUNET_i2s (kx->peer),
1065 GNUNET_STATISTICS_update (GSC_stats,
1066 gettext_noop ("# valid ephemeral keys received"),
1069 kx->other_ephemeral_key = m->ephemeral_key;
1070 kx->foreign_key_expires = end_t;
1071 derive_session_keys (kx);
1073 /* check if we still need to send the sender our key */
1074 sender_status = (enum GNUNET_CORE_KxState) ntohl (m->sender_status);
1075 switch (sender_status)
1077 case GNUNET_CORE_KX_STATE_DOWN:
1078 GNUNET_break_op (0);
1080 case GNUNET_CORE_KX_STATE_KEY_SENT:
1081 /* fine, need to send our key after updating our status, see below */
1082 GSC_SESSIONS_reinit (kx->peer);
1084 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1085 /* other peer already got our key, but typemap did go down */
1086 GSC_SESSIONS_reinit (kx->peer);
1088 case GNUNET_CORE_KX_STATE_UP:
1089 /* other peer already got our key, typemap NOT down */
1091 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1092 /* other peer already got our key, typemap NOT down */
1098 /* check if we need to confirm everything is fine via PING + PONG */
1101 case GNUNET_CORE_KX_STATE_DOWN:
1102 GNUNET_assert (NULL == kx->keep_alive_task);
1103 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1104 monitor_notify_all (kx);
1105 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1110 case GNUNET_CORE_KX_STATE_KEY_SENT:
1111 GNUNET_assert (NULL == kx->keep_alive_task);
1112 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1113 monitor_notify_all (kx);
1114 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1119 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1120 GNUNET_assert (NULL == kx->keep_alive_task);
1121 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1126 case GNUNET_CORE_KX_STATE_UP:
1127 kx->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1128 monitor_notify_all (kx);
1129 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1134 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1135 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1148 * We received a PING message. Validate and transmit
1151 * @param cls key exchange status for the corresponding peer
1152 * @param m the encrypted PING message itself
1155 handle_ping (void *cls, const struct PingMessage *m)
1157 struct GSC_KeyExchangeInfo *kx = cls;
1158 struct PingMessage t;
1159 struct PongMessage tx;
1160 struct PongMessage *tp;
1161 struct GNUNET_MQ_Envelope *env;
1162 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1164 GNUNET_STATISTICS_update (GSC_stats,
1165 gettext_noop ("# PING messages received"),
1168 if ((kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
1169 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
1170 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
1173 GNUNET_STATISTICS_update (GSC_stats,
1175 "# PING messages dropped (out of order)"),
1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1181 "Core service receives PING request from `%s'.\n",
1182 GNUNET_i2s (kx->peer));
1183 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1184 if (GNUNET_OK != do_decrypt (kx,
1188 sizeof (struct PingMessage) -
1189 ((void *) &m->target - (void *) m)))
1191 GNUNET_break_op (0);
1195 memcmp (&t.target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
1197 if (GNUNET_CORE_KX_STATE_REKEY_SENT != kx->status)
1198 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1199 "Decryption of PING from peer `%s' failed, PING for `%s'?\n",
1200 GNUNET_i2s (kx->peer),
1201 GNUNET_i2s2 (&t.target));
1204 GNUNET_ERROR_TYPE_DEBUG,
1205 "Decryption of PING from peer `%s' failed after rekey (harmless)\n",
1206 GNUNET_i2s (kx->peer));
1207 GNUNET_break_op (0);
1210 /* construct PONG */
1212 tx.challenge = t.challenge;
1213 tx.target = t.target;
1214 env = GNUNET_MQ_msg (tp, GNUNET_MESSAGE_TYPE_CORE_PONG);
1215 tp->iv_seed = calculate_seed (kx);
1216 derive_pong_iv (&iv, &kx->encrypt_key, tp->iv_seed, t.challenge, kx->peer);
1221 sizeof (struct PongMessage) -
1222 ((void *) &tp->challenge - (void *) tp));
1223 GNUNET_STATISTICS_update (GSC_stats,
1224 gettext_noop ("# PONG messages created"),
1227 GNUNET_MQ_send (kx->mq, env);
1232 * Task triggered when a neighbour entry is about to time out
1233 * (and we should prevent this by sending a PING).
1235 * @param cls the `struct GSC_KeyExchangeInfo`
1238 send_keep_alive (void *cls)
1240 struct GSC_KeyExchangeInfo *kx = cls;
1241 struct GNUNET_TIME_Relative retry;
1242 struct GNUNET_TIME_Relative left;
1244 kx->keep_alive_task = NULL;
1245 left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
1246 if (0 == left.rel_value_us)
1248 GNUNET_STATISTICS_update (GSC_stats,
1249 gettext_noop ("# sessions terminated by timeout"),
1252 GSC_SESSIONS_end (kx->peer);
1253 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1254 monitor_notify_all (kx);
1258 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1259 "Sending KEEPALIVE to `%s'\n",
1260 GNUNET_i2s (kx->peer));
1261 GNUNET_STATISTICS_update (GSC_stats,
1262 gettext_noop ("# keepalive messages sent"),
1265 setup_fresh_ping (kx);
1267 retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1268 MIN_PING_FREQUENCY);
1269 kx->keep_alive_task =
1270 GNUNET_SCHEDULER_add_delayed (retry, &send_keep_alive, kx);
1275 * We've seen a valid message from the other peer.
1276 * Update the time when the session would time out
1277 * and delay sending our keep alive message further.
1279 * @param kx key exchange where we saw activity
1282 update_timeout (struct GSC_KeyExchangeInfo *kx)
1284 struct GNUNET_TIME_Relative delta;
1287 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1289 GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout, kx->timeout);
1290 if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
1292 /* we only notify monitors about timeout changes if those
1293 are bigger than the threshold (5s) */
1294 monitor_notify_all (kx);
1296 if (NULL != kx->keep_alive_task)
1297 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1298 kx->keep_alive_task = GNUNET_SCHEDULER_add_delayed (
1299 GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
1306 * We received a PONG message. Validate and update our status.
1308 * @param kx key exchange context for the the PONG
1309 * @param m the encrypted PONG message itself
1312 handle_pong (void *cls, const struct PongMessage *m)
1314 struct GSC_KeyExchangeInfo *kx = cls;
1315 struct PongMessage t;
1316 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1318 GNUNET_STATISTICS_update (GSC_stats,
1319 gettext_noop ("# PONG messages received"),
1324 case GNUNET_CORE_KX_STATE_DOWN:
1325 GNUNET_STATISTICS_update (GSC_stats,
1327 "# PONG messages dropped (connection down)"),
1331 case GNUNET_CORE_KX_STATE_KEY_SENT:
1332 GNUNET_STATISTICS_update (GSC_stats,
1334 "# PONG messages dropped (out of order)"),
1338 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1340 case GNUNET_CORE_KX_STATE_UP:
1342 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1349 "Core service receives PONG response from `%s'.\n",
1350 GNUNET_i2s (kx->peer));
1351 /* mark as garbage, just to be sure */
1352 memset (&t, 255, sizeof (t));
1353 derive_pong_iv (&iv,
1358 if (GNUNET_OK != do_decrypt (kx,
1362 sizeof (struct PongMessage) -
1363 ((void *) &m->challenge - (void *) m)))
1365 GNUNET_break_op (0);
1368 GNUNET_STATISTICS_update (GSC_stats,
1369 gettext_noop ("# PONG messages decrypted"),
1373 memcmp (&t.target, kx->peer, sizeof (struct GNUNET_PeerIdentity))) ||
1374 (kx->ping_challenge != t.challenge))
1376 /* PONG malformed */
1377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1378 "Received malformed PONG wanted sender `%s' with challenge %u\n",
1379 GNUNET_i2s (kx->peer),
1380 (unsigned int) kx->ping_challenge);
1381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1382 "Received malformed PONG received from `%s' with challenge %u\n",
1383 GNUNET_i2s (&t.target),
1384 (unsigned int) t.challenge);
1387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1388 "Received valid PONG from `%s'\n",
1389 GNUNET_i2s (kx->peer));
1390 /* no need to resend key any longer */
1391 if (NULL != kx->retry_set_key_task)
1393 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1394 kx->retry_set_key_task = NULL;
1398 case GNUNET_CORE_KX_STATE_DOWN:
1399 GNUNET_assert (0); /* should be impossible */
1401 case GNUNET_CORE_KX_STATE_KEY_SENT:
1402 GNUNET_assert (0); /* should be impossible */
1404 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1405 GNUNET_STATISTICS_update (GSC_stats,
1407 "# session keys confirmed via PONG"),
1410 kx->status = GNUNET_CORE_KX_STATE_UP;
1411 monitor_notify_all (kx);
1412 GSC_SESSIONS_create (kx->peer, kx);
1413 GNUNET_assert (NULL == kx->keep_alive_task);
1414 update_timeout (kx);
1416 case GNUNET_CORE_KX_STATE_UP:
1417 GNUNET_STATISTICS_update (GSC_stats,
1418 gettext_noop ("# timeouts prevented via PONG"),
1421 update_timeout (kx);
1423 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1424 GNUNET_STATISTICS_update (GSC_stats,
1426 "# rekey operations confirmed via PONG"),
1429 kx->status = GNUNET_CORE_KX_STATE_UP;
1430 monitor_notify_all (kx);
1431 update_timeout (kx);
1441 * Send our key to the other peer.
1443 * @param kx key exchange context
1446 send_key (struct GSC_KeyExchangeInfo *kx)
1448 struct GNUNET_MQ_Envelope *env;
1450 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
1451 if (NULL != kx->retry_set_key_task)
1453 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1454 kx->retry_set_key_task = NULL;
1456 /* always update sender status in SET KEY message */
1459 struct GNUNET_HashCode hc;
1461 GNUNET_CRYPTO_hash (¤t_ekm.ephemeral_key,
1462 sizeof (current_ekm.ephemeral_key),
1464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1465 "Sending EPHEMERAL_KEY %s to `%s' (my status: %d)\n",
1467 GNUNET_i2s (kx->peer),
1471 current_ekm.sender_status = htonl ((int32_t) (kx->status));
1472 env = GNUNET_MQ_msg_copy (¤t_ekm.header);
1473 GNUNET_MQ_send (kx->mq, env);
1474 if (GNUNET_CORE_KX_STATE_KEY_SENT != kx->status)
1476 kx->retry_set_key_task =
1477 GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
1478 &set_key_retry_task,
1484 * Encrypt and transmit a message with the given payload.
1486 * @param kx key exchange context
1487 * @param payload payload of the message
1488 * @param payload_size number of bytes in @a payload
1491 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
1492 const void *payload,
1493 size_t payload_size)
1495 size_t used = payload_size + sizeof (struct EncryptedMessage);
1496 char pbuf[used]; /* plaintext */
1497 struct EncryptedMessage *em; /* encrypted message */
1498 struct EncryptedMessage *ph; /* plaintext header */
1499 struct GNUNET_MQ_Envelope *env;
1500 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1501 struct GNUNET_CRYPTO_AuthKey auth_key;
1503 ph = (struct EncryptedMessage *) pbuf;
1504 ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1505 ph->iv_seed = calculate_seed (kx);
1507 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1508 GNUNET_memcpy (&ph[1], payload, payload_size);
1509 env = GNUNET_MQ_msg_extra (em,
1511 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
1512 em->iv_seed = ph->iv_seed;
1513 derive_iv (&iv, &kx->encrypt_key, ph->iv_seed, kx->peer);
1514 GNUNET_assert (GNUNET_OK == do_encrypt (kx,
1516 &ph->sequence_number,
1517 &em->sequence_number,
1518 used - ENCRYPTED_HEADER_SIZE));
1521 struct GNUNET_HashCode hc;
1523 GNUNET_CRYPTO_hash (&ph->sequence_number,
1524 used - ENCRYPTED_HEADER_SIZE,
1526 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1527 "Encrypted payload `%s' of %u bytes for %s\n",
1529 (unsigned int) (used - ENCRYPTED_HEADER_SIZE),
1530 GNUNET_i2s (kx->peer));
1533 derive_auth_key (&auth_key, &kx->encrypt_key, ph->iv_seed);
1534 GNUNET_CRYPTO_hmac (&auth_key,
1535 &em->sequence_number,
1536 used - ENCRYPTED_HEADER_SIZE,
1540 struct GNUNET_HashCode hc;
1542 GNUNET_CRYPTO_hash (&auth_key, sizeof (auth_key), &hc);
1543 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1544 "For peer %s, used AC %s to create hmac %s\n",
1545 GNUNET_i2s (kx->peer),
1547 GNUNET_h2s2 (&em->hmac));
1550 kx->has_excess_bandwidth = GNUNET_NO;
1551 GNUNET_MQ_send (kx->mq, env);
1556 * We received an encrypted message. Check that it is
1557 * well-formed (size-wise).
1559 * @param cls key exchange context for encrypting the message
1560 * @param m encrypted message
1561 * @return #GNUNET_OK if @a msg is well-formed (size-wise)
1564 check_encrypted (void *cls, const struct EncryptedMessage *m)
1566 uint16_t size = ntohs (m->header.size) - sizeof (*m);
1568 if (size < sizeof (struct GNUNET_MessageHeader))
1570 GNUNET_break_op (0);
1571 return GNUNET_SYSERR;
1578 * We received an encrypted message. Decrypt, validate and
1579 * pass on to the appropriate clients.
1581 * @param cls key exchange context for encrypting the message
1582 * @param m encrypted message
1585 handle_encrypted (void *cls, const struct EncryptedMessage *m)
1587 struct GSC_KeyExchangeInfo *kx = cls;
1588 struct EncryptedMessage *pt; /* plaintext */
1589 struct GNUNET_HashCode ph;
1591 struct GNUNET_TIME_Absolute t;
1592 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1593 struct GNUNET_CRYPTO_AuthKey auth_key;
1594 uint16_t size = ntohs (m->header.size);
1595 char buf[size] GNUNET_ALIGN;
1597 if (GNUNET_CORE_KX_STATE_UP != kx->status)
1599 GNUNET_STATISTICS_update (GSC_stats,
1601 "# DATA message dropped (out of order)"),
1607 GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value_us)
1610 GNUNET_ERROR_TYPE_WARNING,
1612 "Session to peer `%s' went down due to key expiration (should not happen)\n"),
1613 GNUNET_i2s (kx->peer));
1614 GNUNET_STATISTICS_update (GSC_stats,
1616 "# sessions terminated by key expiration"),
1619 GSC_SESSIONS_end (kx->peer);
1620 if (NULL != kx->keep_alive_task)
1622 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1623 kx->keep_alive_task = NULL;
1625 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1626 monitor_notify_all (kx);
1634 struct GNUNET_HashCode hc;
1636 GNUNET_CRYPTO_hash (&m->sequence_number, size - ENCRYPTED_HEADER_SIZE, &hc);
1637 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1638 "Received encrypted payload `%s' of %u bytes from %s\n",
1640 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1641 GNUNET_i2s (kx->peer));
1644 derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed);
1645 GNUNET_CRYPTO_hmac (&auth_key,
1646 &m->sequence_number,
1647 size - ENCRYPTED_HEADER_SIZE,
1651 struct GNUNET_HashCode hc;
1653 GNUNET_CRYPTO_hash (&auth_key, sizeof (auth_key), &hc);
1654 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1655 "For peer %s, used AC %s to verify hmac %s\n",
1656 GNUNET_i2s (kx->peer),
1658 GNUNET_h2s2 (&m->hmac));
1661 if (0 != memcmp (&ph, &m->hmac, sizeof (struct GNUNET_HashCode)))
1663 /* checksum failed */
1664 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1665 "Failed checksum validation for a message from `%s'\n",
1666 GNUNET_i2s (kx->peer));
1669 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1671 if (GNUNET_OK != do_decrypt (kx,
1673 &m->sequence_number,
1674 &buf[ENCRYPTED_HEADER_SIZE],
1675 size - ENCRYPTED_HEADER_SIZE))
1677 GNUNET_break_op (0);
1680 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1681 "Decrypted %u bytes from %s\n",
1682 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1683 GNUNET_i2s (kx->peer));
1684 pt = (struct EncryptedMessage *) buf;
1686 /* validate sequence number */
1687 snum = ntohl (pt->sequence_number);
1688 if (kx->last_sequence_number_received == snum)
1690 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1691 "Received duplicate message, ignoring.\n");
1692 /* duplicate, ignore */
1693 GNUNET_STATISTICS_update (GSC_stats,
1694 gettext_noop ("# bytes dropped (duplicates)"),
1699 if ((kx->last_sequence_number_received > snum) &&
1700 (kx->last_sequence_number_received - snum > 32))
1702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1703 "Received ancient out of sequence message, ignoring.\n");
1704 /* ancient out of sequence, ignore */
1705 GNUNET_STATISTICS_update (GSC_stats,
1707 "# bytes dropped (out of sequence)"),
1712 if (kx->last_sequence_number_received > snum)
1714 uint32_t rotbit = 1U << (kx->last_sequence_number_received - snum - 1);
1716 if ((kx->last_packets_bitmap & rotbit) != 0)
1718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1719 "Received duplicate message, ignoring.\n");
1720 GNUNET_STATISTICS_update (GSC_stats,
1721 gettext_noop ("# bytes dropped (duplicates)"),
1724 /* duplicate, ignore */
1727 kx->last_packets_bitmap |= rotbit;
1729 if (kx->last_sequence_number_received < snum)
1731 unsigned int shift = (snum - kx->last_sequence_number_received);
1733 if (shift >= 8 * sizeof (kx->last_packets_bitmap))
1734 kx->last_packets_bitmap = 0;
1736 kx->last_packets_bitmap <<= shift;
1737 kx->last_sequence_number_received = snum;
1740 /* check timestamp */
1741 t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
1742 if (GNUNET_TIME_absolute_get_duration (t).rel_value_us >
1743 MAX_MESSAGE_AGE.rel_value_us)
1745 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1746 "Message received far too old (%s). Content ignored.\n",
1747 GNUNET_STRINGS_relative_time_to_string (
1748 GNUNET_TIME_absolute_get_duration (t),
1750 GNUNET_STATISTICS_update (GSC_stats,
1752 "# bytes dropped (ancient message)"),
1758 /* process decrypted message(s) */
1759 update_timeout (kx);
1760 GNUNET_STATISTICS_update (GSC_stats,
1761 gettext_noop ("# bytes of payload decrypted"),
1762 size - sizeof (struct EncryptedMessage),
1765 GNUNET_MST_from_buffer (kx->mst,
1766 &buf[sizeof (struct EncryptedMessage)],
1767 size - sizeof (struct EncryptedMessage),
1770 GNUNET_break_op (0);
1775 * One of our neighbours has excess bandwidth, remember this.
1778 * @param pid identity of the peer with excess bandwidth
1779 * @param connect_cls the `struct Neighbour`
1782 handle_transport_notify_excess_bw (void *cls,
1783 const struct GNUNET_PeerIdentity *pid,
1786 struct GSC_KeyExchangeInfo *kx = connect_cls;
1788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1789 "Peer %s has excess bandwidth available\n",
1791 kx->has_excess_bandwidth = GNUNET_YES;
1792 GSC_SESSIONS_solicit (pid);
1797 * Setup the message that links the ephemeral key to our persistent
1798 * public key and generate the appropriate signature.
1801 sign_ephemeral_key ()
1803 current_ekm.header.size = htons (sizeof (struct EphemeralKeyMessage));
1804 current_ekm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY);
1805 current_ekm.sender_status = 0; /* to be set later */
1806 current_ekm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY);
1807 current_ekm.purpose.size =
1808 htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
1809 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1810 sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1811 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
1812 sizeof (struct GNUNET_PeerIdentity));
1813 current_ekm.creation_time =
1814 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1815 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (GSC_cfg,
1817 "USE_EPHEMERAL_KEYS"))
1819 current_ekm.expiration_time =
1820 GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (
1821 GNUNET_TIME_relative_add (REKEY_FREQUENCY, REKEY_TOLERANCE)));
1825 current_ekm.expiration_time =
1826 GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1828 GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key,
1829 ¤t_ekm.ephemeral_key);
1830 current_ekm.origin_identity = GSC_my_identity;
1831 GNUNET_assert (GNUNET_OK ==
1832 GNUNET_CRYPTO_eddsa_sign (my_private_key,
1833 ¤t_ekm.purpose,
1834 ¤t_ekm.signature));
1839 * Task run to trigger rekeying.
1841 * @param cls closure, NULL
1844 do_rekey (void *cls)
1846 struct GSC_KeyExchangeInfo *pos;
1848 rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL);
1849 if (NULL != my_ephemeral_key)
1850 GNUNET_free (my_ephemeral_key);
1851 my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
1852 GNUNET_assert (NULL != my_ephemeral_key);
1853 sign_ephemeral_key ();
1855 struct GNUNET_HashCode eh;
1857 GNUNET_CRYPTO_hash (¤t_ekm.ephemeral_key,
1858 sizeof (current_ekm.ephemeral_key),
1860 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Rekeying to %s\n", GNUNET_h2s (&eh));
1862 for (pos = kx_head; NULL != pos; pos = pos->next)
1864 if (GNUNET_CORE_KX_STATE_UP == pos->status)
1866 pos->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1867 monitor_notify_all (pos);
1868 derive_session_keys (pos);
1870 if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
1872 pos->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1873 monitor_notify_all (pos);
1875 monitor_notify_all (pos);
1882 * Initialize KX subsystem.
1884 * @param pk private key to use for the peer
1885 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1888 GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
1890 struct GNUNET_MQ_MessageHandler handlers[] =
1891 {GNUNET_MQ_hd_fixed_size (ephemeral_key,
1892 GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
1893 struct EphemeralKeyMessage,
1895 GNUNET_MQ_hd_fixed_size (ping,
1896 GNUNET_MESSAGE_TYPE_CORE_PING,
1899 GNUNET_MQ_hd_fixed_size (pong,
1900 GNUNET_MESSAGE_TYPE_CORE_PONG,
1903 GNUNET_MQ_hd_var_size (encrypted,
1904 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE,
1905 struct EncryptedMessage,
1907 GNUNET_MQ_handler_end ()};
1909 my_private_key = pk;
1910 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1911 &GSC_my_identity.public_key);
1912 my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
1913 if (NULL == my_ephemeral_key)
1916 GNUNET_free (my_private_key);
1917 my_private_key = NULL;
1918 return GNUNET_SYSERR;
1920 sign_ephemeral_key ();
1922 struct GNUNET_HashCode eh;
1924 GNUNET_CRYPTO_hash (¤t_ekm.ephemeral_key,
1925 sizeof (current_ekm.ephemeral_key),
1927 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1928 "Starting with ephemeral key %s\n",
1932 nc = GNUNET_notification_context_create (1);
1933 rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL);
1935 GNUNET_TRANSPORT_core_connect (GSC_cfg,
1939 &handle_transport_notify_connect,
1940 &handle_transport_notify_disconnect,
1941 &handle_transport_notify_excess_bw);
1942 if (NULL == transport)
1945 return GNUNET_SYSERR;
1952 * Shutdown KX subsystem.
1957 if (NULL != transport)
1959 GNUNET_TRANSPORT_core_disconnect (transport);
1962 if (NULL != rekey_task)
1964 GNUNET_SCHEDULER_cancel (rekey_task);
1967 if (NULL != my_ephemeral_key)
1969 GNUNET_free (my_ephemeral_key);
1970 my_ephemeral_key = NULL;
1972 if (NULL != my_private_key)
1974 GNUNET_free (my_private_key);
1975 my_private_key = NULL;
1979 GNUNET_notification_context_destroy (nc);
1986 * Check how many messages are queued for the given neighbour.
1988 * @param kxinfo data about neighbour to check
1989 * @return number of items in the message queue
1992 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
1994 return GNUNET_MQ_get_length (kxinfo->mq);
1999 * Check if the given neighbour has excess bandwidth available.
2001 * @param target neighbour to check
2002 * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
2005 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
2007 return kxinfo->has_excess_bandwidth;
2012 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
2013 * request type, the client does not have to have transmitted an INIT
2014 * request. All current peers are returned, regardless of which
2015 * message types they accept.
2017 * @param mq message queue to add for monitoring
2020 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
2022 struct GNUNET_MQ_Envelope *env;
2023 struct MonitorNotifyMessage *done_msg;
2024 struct GSC_KeyExchangeInfo *kx;
2026 GNUNET_notification_context_add (nc, mq);
2027 for (kx = kx_head; NULL != kx; kx = kx->next)
2029 struct GNUNET_MQ_Envelope *env;
2030 struct MonitorNotifyMessage *msg;
2032 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
2033 msg->state = htonl ((uint32_t) kx->status);
2034 msg->peer = *kx->peer;
2035 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
2036 GNUNET_MQ_send (mq, env);
2038 env = GNUNET_MQ_msg (done_msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
2039 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
2040 done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
2041 GNUNET_MQ_send (mq, env);
2045 /* end of gnunet-service-core_kx.c */