Merge branch 'master' of gnunet.org:gnunet
[oweals/gnunet.git] / src / core / gnunet-service-core_kx.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013, 2016 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21 /**
22  * @file core/gnunet-service-core_kx.c
23  * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other
24  * peers
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
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"
36 #include "core.h"
37
38 /**
39  * Enable expensive (and possibly problematic for privacy!) logging of KX.
40  */
41 #define DEBUG_KX 0
42
43 /**
44  * How long do we wait for SET_KEY confirmation initially?
45  */
46 #define INITIAL_SET_KEY_RETRY_FREQUENCY \
47   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
48
49 /**
50  * What is the minimum frequency for a PING message?
51  */
52 #define MIN_PING_FREQUENCY \
53   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
54
55 /**
56  * How often do we rekey?
57  */
58 #define REKEY_FREQUENCY \
59   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
60
61 /**
62  * What time difference do we tolerate?
63  */
64 #define REKEY_TOLERANCE \
65   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
66
67 /**
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.
73  */
74 #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
75
76
77 GNUNET_NETWORK_STRUCT_BEGIN
78
79 /**
80  * Message transmitted with the signed ephemeral key of a peer.  The
81  * session key is then derived from the two ephemeral keys (ECDHE).
82  */
83 struct EphemeralKeyMessage
84 {
85
86   /**
87    * Message type is #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY.
88    */
89   struct GNUNET_MessageHeader header;
90
91   /**
92    * Status of the sender (should be in `enum PeerStateMachine`), nbo.
93    */
94   int32_t sender_status GNUNET_PACKED;
95
96   /**
97    * An ECC signature of the @e origin_identity asserting the validity
98    * of the given ephemeral key.
99    */
100   struct GNUNET_CRYPTO_EddsaSignature signature;
101
102   /**
103    * Information about what is being signed.
104    */
105   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
106
107   /**
108    * At what time was this key created (beginning of validity).
109    */
110   struct GNUNET_TIME_AbsoluteNBO creation_time;
111
112   /**
113    * When does the given ephemeral key expire (end of validity).
114    */
115   struct GNUNET_TIME_AbsoluteNBO expiration_time;
116
117   /**
118    * Ephemeral public ECC key.
119    */
120   struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
121
122   /**
123    * Public key of the signing peer (persistent version, not the
124    * ephemeral public key).
125    */
126   struct GNUNET_PeerIdentity origin_identity;
127 };
128
129
130 /**
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.
134  */
135 struct PingMessage
136 {
137   /**
138    * Message type is #GNUNET_MESSAGE_TYPE_CORE_PING.
139    */
140   struct GNUNET_MessageHeader header;
141
142   /**
143    * Seed for the IV
144    */
145   uint32_t iv_seed GNUNET_PACKED;
146
147   /**
148    * Intended target of the PING, used primarily to check
149    * that decryption actually worked.
150    */
151   struct GNUNET_PeerIdentity target;
152
153   /**
154    * Random number chosen to make replay harder.
155    */
156   uint32_t challenge GNUNET_PACKED;
157 };
158
159
160 /**
161  * Response to a PING.  Includes data from the original PING.
162  */
163 struct PongMessage
164 {
165   /**
166    * Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG.
167    */
168   struct GNUNET_MessageHeader header;
169
170   /**
171    * Seed for the IV
172    */
173   uint32_t iv_seed GNUNET_PACKED;
174
175   /**
176    * Random number to make replay attacks harder.
177    */
178   uint32_t challenge GNUNET_PACKED;
179
180   /**
181    * Reserved, always zero.
182    */
183   uint32_t reserved;
184
185   /**
186    * Intended target of the PING, used primarily to check
187    * that decryption actually worked.
188    */
189   struct GNUNET_PeerIdentity target;
190 };
191
192
193 /**
194  * Encapsulation for encrypted messages exchanged between
195  * peers.  Followed by the actual encrypted data.
196  */
197 struct EncryptedMessage
198 {
199   /**
200    * Message type is #GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE.
201    */
202   struct GNUNET_MessageHeader header;
203
204   /**
205    * Random value used for IV generation.
206    */
207   uint32_t iv_seed GNUNET_PACKED;
208
209   /**
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.
215    */
216   struct GNUNET_HashCode hmac;
217
218   /**
219    * Sequence number, in network byte order.  This field
220    * must be the first encrypted/decrypted field
221    */
222   uint32_t sequence_number GNUNET_PACKED;
223
224   /**
225    * Reserved, always zero.
226    */
227   uint32_t reserved GNUNET_PACKED;
228
229   /**
230    * Timestamp.  Used to prevent replay of ancient messages
231    * (recent messages are caught with the sequence number).
232    */
233   struct GNUNET_TIME_AbsoluteNBO timestamp;
234 };
235 GNUNET_NETWORK_STRUCT_END
236
237
238 /**
239  * Number of bytes (at the beginning) of `struct EncryptedMessage`
240  * that are NOT encrypted.
241  */
242 #define ENCRYPTED_HEADER_SIZE \
243   (offsetof (struct EncryptedMessage, sequence_number))
244
245
246 /**
247  * Information about the status of a key exchange with another peer.
248  */
249 struct GSC_KeyExchangeInfo
250 {
251
252   /**
253    * DLL.
254    */
255   struct GSC_KeyExchangeInfo *next;
256
257   /**
258    * DLL.
259    */
260   struct GSC_KeyExchangeInfo *prev;
261
262   /**
263    * Identity of the peer.
264    */
265   const struct GNUNET_PeerIdentity *peer;
266
267   /**
268    * Message queue for sending messages to @a peer.
269    */
270   struct GNUNET_MQ_Handle *mq;
271
272   /**
273    * Our message stream tokenizer (for encrypted payload).
274    */
275   struct GNUNET_MessageStreamTokenizer *mst;
276
277   /**
278    * PING message we transmit to the other peer.
279    */
280   struct PingMessage ping;
281
282   /**
283    * Ephemeral public ECC key of the other peer.
284    */
285   struct GNUNET_CRYPTO_EcdhePublicKey other_ephemeral_key;
286
287   /**
288    * Key we use to encrypt our messages for the other peer
289    * (initialized by us when we do the handshake).
290    */
291   struct GNUNET_CRYPTO_SymmetricSessionKey encrypt_key;
292
293   /**
294    * Key we use to decrypt messages from the other peer
295    * (given to us by the other peer during the handshake).
296    */
297   struct GNUNET_CRYPTO_SymmetricSessionKey decrypt_key;
298
299   /**
300    * At what time did the other peer generate the decryption key?
301    */
302   struct GNUNET_TIME_Absolute foreign_key_expires;
303
304   /**
305    * When should the session time out (if there are no PONGs)?
306    */
307   struct GNUNET_TIME_Absolute timeout;
308
309   /**
310    * What was the last timeout we informed our monitors about?
311    */
312   struct GNUNET_TIME_Absolute last_notify_timeout;
313
314   /**
315    * At what frequency are we currently re-trying SET_KEY messages?
316    */
317   struct GNUNET_TIME_Relative set_key_retry_frequency;
318
319   /**
320    * ID of task used for re-trying SET_KEY and PING message.
321    */
322   struct GNUNET_SCHEDULER_Task *retry_set_key_task;
323
324   /**
325    * ID of task used for sending keep-alive pings.
326    */
327   struct GNUNET_SCHEDULER_Task *keep_alive_task;
328
329   /**
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)
333    */
334   uint32_t last_packets_bitmap;
335
336   /**
337    * last sequence number received on this connection (highest)
338    */
339   uint32_t last_sequence_number_received;
340
341   /**
342    * last sequence number transmitted
343    */
344   uint32_t last_sequence_number_sent;
345
346   /**
347    * What was our PING challenge number (for this peer)?
348    */
349   uint32_t ping_challenge;
350
351   /**
352    * #GNUNET_YES if this peer currently has excess bandwidth.
353    */
354   int has_excess_bandwidth;
355
356   /**
357    * What is our connection status?
358    */
359   enum GNUNET_CORE_KxState status;
360 };
361
362
363 /**
364  * Transport service.
365  */
366 static struct GNUNET_TRANSPORT_CoreHandle *transport;
367
368 /**
369  * Our private key.
370  */
371 static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
372
373 /**
374  * Our ephemeral private key.
375  */
376 static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key;
377
378 /**
379  * Current message we send for a key exchange.
380  */
381 static struct EphemeralKeyMessage current_ekm;
382
383 /**
384  * DLL head.
385  */
386 static struct GSC_KeyExchangeInfo *kx_head;
387
388 /**
389  * DLL tail.
390  */
391 static struct GSC_KeyExchangeInfo *kx_tail;
392
393 /**
394  * Task scheduled for periodic re-generation (and thus rekeying) of our
395  * ephemeral key.
396  */
397 static struct GNUNET_SCHEDULER_Task *rekey_task;
398
399 /**
400  * Notification context for broadcasting to monitors.
401  */
402 static struct GNUNET_NotificationContext *nc;
403
404
405 /**
406  * Calculate seed value we should use for a message.
407  *
408  * @param kx key exchange context
409  */
410 static uint32_t
411 calculate_seed (struct GSC_KeyExchangeInfo *kx)
412 {
413   /* Note: may want to make this non-random and instead
414      derive from key material to avoid having an undetectable
415      side-channel */
416   return htonl (
417     GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
418 }
419
420
421 /**
422  * Inform all monitors about the KX state of the given peer.
423  *
424  * @param kx key exchange state to inform about
425  */
426 static void
427 monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
428 {
429   struct MonitorNotifyMessage msg;
430
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;
438 }
439
440
441 /**
442  * Derive an authentication key from "set key" information
443  *
444  * @param akey authentication key to derive
445  * @param skey session key to use
446  * @param seed seed to use
447  */
448 static void
449 derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
450                  const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
451                  uint32_t seed)
452 {
453   static const char ctx[] = "authentication key";
454 #if DEBUG_KX
455   struct GNUNET_HashCode sh;
456
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",
460               GNUNET_h2s (&sh),
461               (unsigned int) seed);
462 #endif
463   GNUNET_CRYPTO_hmac_derive_key (akey,
464                                  skey,
465                                  &seed,
466                                  sizeof (seed),
467                                  skey,
468                                  sizeof (
469                                    struct GNUNET_CRYPTO_SymmetricSessionKey),
470                                  ctx,
471                                  sizeof (ctx),
472                                  NULL);
473 }
474
475
476 /**
477  * Derive an IV from packet information
478  *
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
483  */
484 static void
485 derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
486            const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
487            uint32_t seed,
488            const struct GNUNET_PeerIdentity *identity)
489 {
490   static const char ctx[] = "initialization vector";
491 #if DEBUG_KX
492   struct GNUNET_HashCode sh;
493
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",
497               GNUNET_h2s (&sh),
498               (unsigned int) seed,
499               GNUNET_i2s (identity));
500 #endif
501   GNUNET_CRYPTO_symmetric_derive_iv (iv,
502                                      skey,
503                                      &seed,
504                                      sizeof (seed),
505                                      identity,
506                                      sizeof (struct GNUNET_PeerIdentity),
507                                      ctx,
508                                      sizeof (ctx),
509                                      NULL);
510 }
511
512
513 /**
514  * Derive an IV from pong packet information
515  *
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
521  */
522 static void
523 derive_pong_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
524                 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
525                 uint32_t seed,
526                 uint32_t challenge,
527                 const struct GNUNET_PeerIdentity *identity)
528 {
529   static const char ctx[] = "pong initialization vector";
530 #if DEBUG_KX
531   struct GNUNET_HashCode sh;
532
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",
536               GNUNET_h2s (&sh),
537               (unsigned int) seed,
538               (unsigned int) challenge,
539               GNUNET_i2s (identity));
540 #endif
541   GNUNET_CRYPTO_symmetric_derive_iv (iv,
542                                      skey,
543                                      &seed,
544                                      sizeof (seed),
545                                      identity,
546                                      sizeof (struct GNUNET_PeerIdentity),
547                                      &challenge,
548                                      sizeof (challenge),
549                                      ctx,
550                                      sizeof (ctx),
551                                      NULL);
552 }
553
554
555 /**
556  * Derive an AES key from key material
557  *
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
562  */
563 static void
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)
568 {
569   static const char ctx[] = "aes key generation vector";
570 #if DEBUG_KX
571   struct GNUNET_HashCode sh;
572
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",
576               GNUNET_i2s (sender),
577               GNUNET_i2s2 (receiver),
578               GNUNET_h2s (key_material));
579 #endif
580   GNUNET_CRYPTO_kdf (skey,
581                      sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
582                      ctx,
583                      sizeof (ctx),
584                      key_material,
585                      sizeof (struct GNUNET_HashCode),
586                      sender,
587                      sizeof (struct GNUNET_PeerIdentity),
588                      receiver,
589                      sizeof (struct GNUNET_PeerIdentity),
590                      NULL);
591 }
592
593
594 /**
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.
597  *
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
604  */
605 static int
606 do_encrypt (struct GSC_KeyExchangeInfo *kx,
607             const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
608             const void *in,
609             void *out,
610             size_t size)
611 {
612   if (size != (uint16_t) size)
613   {
614     GNUNET_break (0);
615     return GNUNET_NO;
616   }
617   GNUNET_assert (size == GNUNET_CRYPTO_symmetric_encrypt (in,
618                                                           (uint16_t) size,
619                                                           &kx->encrypt_key,
620                                                           iv,
621                                                           out));
622   GNUNET_STATISTICS_update (GSC_stats,
623                             gettext_noop ("# bytes encrypted"),
624                             size,
625                             GNUNET_NO);
626   /* the following is too sensitive to write to log files by accident,
627      so we require manual intervention to get this one... */
628 #if DEBUG_KX
629   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
630               "Encrypted %u bytes for `%s' using key %u, IV %u\n",
631               (unsigned int) size,
632               GNUNET_i2s (kx->peer),
633               (unsigned int) kx->encrypt_key.crc32,
634               GNUNET_CRYPTO_crc32_n (iv, sizeof (iv)));
635 #endif
636   return GNUNET_OK;
637 }
638
639
640 /**
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.
644  *
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
651  */
652 static int
653 do_decrypt (struct GSC_KeyExchangeInfo *kx,
654             const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
655             const void *in,
656             void *out,
657             size_t size)
658 {
659   if (size != (uint16_t) size)
660   {
661     GNUNET_break (0);
662     return GNUNET_NO;
663   }
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))
667   {
668     GNUNET_break_op (0);
669     return GNUNET_SYSERR;
670   }
671   if (size != GNUNET_CRYPTO_symmetric_decrypt (in,
672                                                (uint16_t) size,
673                                                &kx->decrypt_key,
674                                                iv,
675                                                out))
676   {
677     GNUNET_break (0);
678     return GNUNET_SYSERR;
679   }
680   GNUNET_STATISTICS_update (GSC_stats,
681                             gettext_noop ("# bytes decrypted"),
682                             size,
683                             GNUNET_NO);
684   /* the following is too sensitive to write to log files by accident,
685      so we require manual intervention to get this one... */
686 #if DEBUG_KX
687   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
688               "Decrypted %u bytes from `%s' using key %u, IV %u\n",
689               (unsigned int) size,
690               GNUNET_i2s (kx->peer),
691               (unsigned int) kx->decrypt_key.crc32,
692               GNUNET_CRYPTO_crc32_n (iv, sizeof (*iv)));
693 #endif
694   return GNUNET_OK;
695 }
696
697
698 /**
699  * Send our key (and encrypted PING) to the other peer.
700  *
701  * @param kx key exchange context
702  */
703 static void
704 send_key (struct GSC_KeyExchangeInfo *kx);
705
706
707 /**
708  * Task that will retry #send_key() if our previous attempt failed.
709  *
710  * @param cls our `struct GSC_KeyExchangeInfo`
711  */
712 static void
713 set_key_retry_task (void *cls)
714 {
715   struct GSC_KeyExchangeInfo *kx = cls;
716
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);
721   send_key (kx);
722 }
723
724
725 /**
726  * Create a fresh PING message for transmission to the other peer.
727  *
728  * @param kx key exchange context to create PING for
729  */
730 static void
731 setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
732 {
733   struct PingMessage pp;
734   struct PingMessage *pm;
735   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
736
737   pm = &kx->ping;
738   kx->ping_challenge =
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;
746   do_encrypt (kx,
747               &iv,
748               &pp.target,
749               &pm->target,
750               sizeof (struct PingMessage) -
751                 ((void *) &pm->target - (void *) pm));
752 }
753
754
755 /**
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
759  *
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
765  */
766 static int
767 deliver_message (void *cls, const struct GNUNET_MessageHeader *m)
768 {
769   struct GSC_KeyExchangeInfo *kx = cls;
770
771   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
772               "Decrypted message of type %d from %s\n",
773               ntohs (m->type),
774               GNUNET_i2s (kx->peer));
775   if (GNUNET_CORE_KX_STATE_UP != kx->status)
776   {
777     GNUNET_STATISTICS_update (GSC_stats,
778                               gettext_noop ("# PAYLOAD dropped (out of order)"),
779                               1,
780                               GNUNET_NO);
781     return GNUNET_OK;
782   }
783   switch (ntohs (m->type))
784   {
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);
788     return GNUNET_OK;
789   case GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP:
790     GSC_SESSIONS_confirm_typemap (kx->peer, m);
791     return GNUNET_OK;
792   default:
793     GSC_CLIENTS_deliver_message (kx->peer,
794                                  m,
795                                  ntohs (m->size),
796                                  GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
797     GSC_CLIENTS_deliver_message (kx->peer,
798                                  m,
799                                  sizeof (struct GNUNET_MessageHeader),
800                                  GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
801   }
802   return GNUNET_OK;
803 }
804
805
806 /**
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.
810  *
811  * @param cls closure (NULL)
812  * @param pid identity of the peer to do a key exchange with
813  * @return key exchange information context
814  */
815 static void *
816 handle_transport_notify_connect (void *cls,
817                                  const struct GNUNET_PeerIdentity *pid,
818                                  struct GNUNET_MQ_Handle *mq)
819 {
820   struct GSC_KeyExchangeInfo *kx;
821   struct GNUNET_HashCode h1;
822   struct GNUNET_HashCode h2;
823
824   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
825               "Initiating key exchange with `%s'\n",
826               GNUNET_i2s (pid));
827   GNUNET_STATISTICS_update (GSC_stats,
828                             gettext_noop ("# key exchanges initiated"),
829                             1,
830                             GNUNET_NO);
831   kx = GNUNET_new (struct GSC_KeyExchangeInfo);
832   kx->mst = GNUNET_MST_create (&deliver_message, kx);
833   kx->mq = mq;
834   kx->peer = pid;
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),
842                       &h2);
843   if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2))
844   {
845     /* peer with "lower" identity starts KX, otherwise we typically end up
846        with both peers starting the exchange and transmit the 'set key'
847        message twice */
848     send_key (kx);
849   }
850   else
851   {
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,
856                                     &set_key_retry_task,
857                                     kx);
858   }
859   return kx;
860 }
861
862
863 /**
864  * Function called by transport telling us that a peer
865  * disconnected.
866  * Stop key exchange with the given peer.  Clean up key material.
867  *
868  * @param cls closure
869  * @param peer the peer that disconnected
870  * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
871  */
872 static void
873 handle_transport_notify_disconnect (void *cls,
874                                     const struct GNUNET_PeerIdentity *peer,
875                                     void *handler_cls)
876 {
877   struct GSC_KeyExchangeInfo *kx = handler_cls;
878
879   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
880               "Peer `%s' disconnected from us.\n",
881               GNUNET_i2s (peer));
882   GSC_SESSIONS_end (kx->peer);
883   GNUNET_STATISTICS_update (GSC_stats,
884                             gettext_noop ("# key exchanges stopped"),
885                             1,
886                             GNUNET_NO);
887   if (NULL != kx->retry_set_key_task)
888   {
889     GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
890     kx->retry_set_key_task = NULL;
891   }
892   if (NULL != kx->keep_alive_task)
893   {
894     GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
895     kx->keep_alive_task = NULL;
896   }
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);
901   GNUNET_free (kx);
902 }
903
904
905 /**
906  * Send our PING to the other peer.
907  *
908  * @param kx key exchange context
909  */
910 static void
911 send_ping (struct GSC_KeyExchangeInfo *kx)
912 {
913   struct GNUNET_MQ_Envelope *env;
914
915   GNUNET_STATISTICS_update (GSC_stats,
916                             gettext_noop ("# PING messages transmitted"),
917                             1,
918                             GNUNET_NO);
919   env = GNUNET_MQ_msg_copy (&kx->ping.header);
920   GNUNET_MQ_send (kx->mq, env);
921 }
922
923
924 /**
925  * Derive fresh session keys from the current ephemeral keys.
926  *
927  * @param kx session to derive keys for
928  */
929 static void
930 derive_session_keys (struct GSC_KeyExchangeInfo *kx)
931 {
932   struct GNUNET_HashCode key_material;
933
934   if (GNUNET_OK != GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key,
935                                            &kx->other_ephemeral_key,
936                                            &key_material))
937   {
938     GNUNET_break (0);
939     return;
940   }
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);
948 }
949
950
951 /**
952  * We received a #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY message.
953  * Validate and update our key material and status.
954  *
955  * @param cls key exchange status for the corresponding peer
956  * @param m the set key message we received
957  */
958 static void
959 handle_ephemeral_key (void *cls, const struct EphemeralKeyMessage *m)
960 {
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;
966
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))
972   {
973     GNUNET_STATISTICS_update (GSC_stats,
974                               gettext_noop ("# old ephemeral keys ignored"),
975                               1,
976                               GNUNET_NO);
977     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
978                 "Received expired EPHEMERAL_KEY from %s\n",
979                 GNUNET_i2s (&m->origin_identity));
980     return;
981   }
982   if (0 == memcmp (&m->ephemeral_key,
983                    &kx->other_ephemeral_key,
984                    sizeof (m->ephemeral_key)))
985   {
986     GNUNET_STATISTICS_update (GSC_stats,
987                               gettext_noop (
988                                 "# duplicate ephemeral keys ignored"),
989                               1,
990                               GNUNET_NO);
991     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
992                 "Ignoring duplicate EPHEMERAL_KEY from %s\n",
993                 GNUNET_i2s (&m->origin_identity));
994     return;
995   }
996   if (0 != memcmp (&m->origin_identity,
997                    kx->peer,
998                    sizeof (struct GNUNET_PeerIdentity)))
999   {
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);
1005     return;
1006   }
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)) ||
1013       (GNUNET_OK !=
1014        GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY,
1015                                    &m->purpose,
1016                                    &m->signature,
1017                                    &m->origin_identity.public_key)))
1018   {
1019     /* invalid signature */
1020     GNUNET_break_op (0);
1021     GNUNET_STATISTICS_update (GSC_stats,
1022                               gettext_noop (
1023                                 "# EPHEMERAL_KEYs rejected (bad signature)"),
1024                               1,
1025                               GNUNET_NO);
1026     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1027                 "Received EPHEMERAL_KEY from %s with bad signature\n",
1028                 GNUNET_i2s (&m->origin_identity));
1029     return;
1030   }
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))
1037   {
1038     GNUNET_log (
1039       GNUNET_ERROR_TYPE_WARNING,
1040       _ (
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,
1047                               gettext_noop (
1048                                 "# EPHEMERAL_KEY messages rejected due to time"),
1049                               1,
1050                               GNUNET_NO);
1051     return;
1052   }
1053 #if DEBUG_KX
1054   {
1055     struct GNUNET_HashCode eh;
1056
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",
1060                 GNUNET_h2s (&eh),
1061                 GNUNET_i2s (kx->peer),
1062                 kx->status);
1063   }
1064 #endif
1065   GNUNET_STATISTICS_update (GSC_stats,
1066                             gettext_noop ("# valid ephemeral keys received"),
1067                             1,
1068                             GNUNET_NO);
1069   kx->other_ephemeral_key = m->ephemeral_key;
1070   kx->foreign_key_expires = end_t;
1071   derive_session_keys (kx);
1072
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)
1076   {
1077   case GNUNET_CORE_KX_STATE_DOWN:
1078     GNUNET_break_op (0);
1079     break;
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);
1083     break;
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);
1087     break;
1088   case GNUNET_CORE_KX_STATE_UP:
1089     /* other peer already got our key, typemap NOT down */
1090     break;
1091   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1092     /* other peer already got our key, typemap NOT down */
1093     break;
1094   default:
1095     GNUNET_break (0);
1096     break;
1097   }
1098   /* check if we need to confirm everything is fine via PING + PONG */
1099   switch (kx->status)
1100   {
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)
1106       send_key (kx);
1107     else
1108       send_ping (kx);
1109     break;
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)
1115       send_key (kx);
1116     else
1117       send_ping (kx);
1118     break;
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)
1122       send_key (kx);
1123     else
1124       send_ping (kx);
1125     break;
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)
1130       send_key (kx);
1131     else
1132       send_ping (kx);
1133     break;
1134   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1135     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1136       send_key (kx);
1137     else
1138       send_ping (kx);
1139     break;
1140   default:
1141     GNUNET_break (0);
1142     break;
1143   }
1144 }
1145
1146
1147 /**
1148  * We received a PING message.  Validate and transmit
1149  * a PONG message.
1150  *
1151  * @param cls key exchange status for the corresponding peer
1152  * @param m the encrypted PING message itself
1153  */
1154 static void
1155 handle_ping (void *cls, const struct PingMessage *m)
1156 {
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;
1163
1164   GNUNET_STATISTICS_update (GSC_stats,
1165                             gettext_noop ("# PING messages received"),
1166                             1,
1167                             GNUNET_NO);
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))
1171   {
1172     /* ignore */
1173     GNUNET_STATISTICS_update (GSC_stats,
1174                               gettext_noop (
1175                                 "# PING messages dropped (out of order)"),
1176                               1,
1177                               GNUNET_NO);
1178     return;
1179   }
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,
1185                                &iv,
1186                                &m->target,
1187                                &t.target,
1188                                sizeof (struct PingMessage) -
1189                                  ((void *) &m->target - (void *) m)))
1190   {
1191     GNUNET_break_op (0);
1192     return;
1193   }
1194   if (0 !=
1195       memcmp (&t.target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
1196   {
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));
1202     else
1203       GNUNET_log (
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);
1208     return;
1209   }
1210   /* construct PONG */
1211   tx.reserved = 0;
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);
1217   do_encrypt (kx,
1218               &iv,
1219               &tx.challenge,
1220               &tp->challenge,
1221               sizeof (struct PongMessage) -
1222                 ((void *) &tp->challenge - (void *) tp));
1223   GNUNET_STATISTICS_update (GSC_stats,
1224                             gettext_noop ("# PONG messages created"),
1225                             1,
1226                             GNUNET_NO);
1227   GNUNET_MQ_send (kx->mq, env);
1228 }
1229
1230
1231 /**
1232  * Task triggered when a neighbour entry is about to time out
1233  * (and we should prevent this by sending a PING).
1234  *
1235  * @param cls the `struct GSC_KeyExchangeInfo`
1236  */
1237 static void
1238 send_keep_alive (void *cls)
1239 {
1240   struct GSC_KeyExchangeInfo *kx = cls;
1241   struct GNUNET_TIME_Relative retry;
1242   struct GNUNET_TIME_Relative left;
1243
1244   kx->keep_alive_task = NULL;
1245   left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
1246   if (0 == left.rel_value_us)
1247   {
1248     GNUNET_STATISTICS_update (GSC_stats,
1249                               gettext_noop ("# sessions terminated by timeout"),
1250                               1,
1251                               GNUNET_NO);
1252     GSC_SESSIONS_end (kx->peer);
1253     kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1254     monitor_notify_all (kx);
1255     send_key (kx);
1256     return;
1257   }
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"),
1263                             1,
1264                             GNUNET_NO);
1265   setup_fresh_ping (kx);
1266   send_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);
1271 }
1272
1273
1274 /**
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.
1278  *
1279  * @param kx key exchange where we saw activity
1280  */
1281 static void
1282 update_timeout (struct GSC_KeyExchangeInfo *kx)
1283 {
1284   struct GNUNET_TIME_Relative delta;
1285
1286   kx->timeout =
1287     GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1288   delta =
1289     GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout, kx->timeout);
1290   if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
1291   {
1292     /* we only notify monitors about timeout changes if those
1293        are bigger than the threshold (5s) */
1294     monitor_notify_all (kx);
1295   }
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),
1300     &send_keep_alive,
1301     kx);
1302 }
1303
1304
1305 /**
1306  * We received a PONG message.  Validate and update our status.
1307  *
1308  * @param kx key exchange context for the the PONG
1309  * @param m the encrypted PONG message itself
1310  */
1311 static void
1312 handle_pong (void *cls, const struct PongMessage *m)
1313 {
1314   struct GSC_KeyExchangeInfo *kx = cls;
1315   struct PongMessage t;
1316   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1317
1318   GNUNET_STATISTICS_update (GSC_stats,
1319                             gettext_noop ("# PONG messages received"),
1320                             1,
1321                             GNUNET_NO);
1322   switch (kx->status)
1323   {
1324   case GNUNET_CORE_KX_STATE_DOWN:
1325     GNUNET_STATISTICS_update (GSC_stats,
1326                               gettext_noop (
1327                                 "# PONG messages dropped (connection down)"),
1328                               1,
1329                               GNUNET_NO);
1330     return;
1331   case GNUNET_CORE_KX_STATE_KEY_SENT:
1332     GNUNET_STATISTICS_update (GSC_stats,
1333                               gettext_noop (
1334                                 "# PONG messages dropped (out of order)"),
1335                               1,
1336                               GNUNET_NO);
1337     return;
1338   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1339     break;
1340   case GNUNET_CORE_KX_STATE_UP:
1341     break;
1342   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1343     break;
1344   default:
1345     GNUNET_break (0);
1346     return;
1347   }
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,
1354                   &kx->decrypt_key,
1355                   m->iv_seed,
1356                   kx->ping_challenge,
1357                   &GSC_my_identity);
1358   if (GNUNET_OK != do_decrypt (kx,
1359                                &iv,
1360                                &m->challenge,
1361                                &t.challenge,
1362                                sizeof (struct PongMessage) -
1363                                  ((void *) &m->challenge - (void *) m)))
1364   {
1365     GNUNET_break_op (0);
1366     return;
1367   }
1368   GNUNET_STATISTICS_update (GSC_stats,
1369                             gettext_noop ("# PONG messages decrypted"),
1370                             1,
1371                             GNUNET_NO);
1372   if ((0 !=
1373        memcmp (&t.target, kx->peer, sizeof (struct GNUNET_PeerIdentity))) ||
1374       (kx->ping_challenge != t.challenge))
1375   {
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);
1385     return;
1386   }
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)
1392   {
1393     GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1394     kx->retry_set_key_task = NULL;
1395   }
1396   switch (kx->status)
1397   {
1398   case GNUNET_CORE_KX_STATE_DOWN:
1399     GNUNET_assert (0); /* should be impossible */
1400     return;
1401   case GNUNET_CORE_KX_STATE_KEY_SENT:
1402     GNUNET_assert (0); /* should be impossible */
1403     return;
1404   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1405     GNUNET_STATISTICS_update (GSC_stats,
1406                               gettext_noop (
1407                                 "# session keys confirmed via PONG"),
1408                               1,
1409                               GNUNET_NO);
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);
1415     break;
1416   case GNUNET_CORE_KX_STATE_UP:
1417     GNUNET_STATISTICS_update (GSC_stats,
1418                               gettext_noop ("# timeouts prevented via PONG"),
1419                               1,
1420                               GNUNET_NO);
1421     update_timeout (kx);
1422     break;
1423   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1424     GNUNET_STATISTICS_update (GSC_stats,
1425                               gettext_noop (
1426                                 "# rekey operations confirmed via PONG"),
1427                               1,
1428                               GNUNET_NO);
1429     kx->status = GNUNET_CORE_KX_STATE_UP;
1430     monitor_notify_all (kx);
1431     update_timeout (kx);
1432     break;
1433   default:
1434     GNUNET_break (0);
1435     break;
1436   }
1437 }
1438
1439
1440 /**
1441  * Send our key to the other peer.
1442  *
1443  * @param kx key exchange context
1444  */
1445 static void
1446 send_key (struct GSC_KeyExchangeInfo *kx)
1447 {
1448   struct GNUNET_MQ_Envelope *env;
1449
1450   GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
1451   if (NULL != kx->retry_set_key_task)
1452   {
1453     GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1454     kx->retry_set_key_task = NULL;
1455   }
1456   /* always update sender status in SET KEY message */
1457 #if DEBUG_KX
1458   {
1459     struct GNUNET_HashCode hc;
1460
1461     GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1462                         sizeof (current_ekm.ephemeral_key),
1463                         &hc);
1464     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1465                 "Sending EPHEMERAL_KEY %s to `%s' (my status: %d)\n",
1466                 GNUNET_h2s (&hc),
1467                 GNUNET_i2s (kx->peer),
1468                 kx->status);
1469   }
1470 #endif
1471   current_ekm.sender_status = htonl ((int32_t) (kx->status));
1472   env = GNUNET_MQ_msg_copy (&current_ekm.header);
1473   GNUNET_MQ_send (kx->mq, env);
1474   if (GNUNET_CORE_KX_STATE_KEY_SENT != kx->status)
1475     send_ping (kx);
1476   kx->retry_set_key_task =
1477     GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
1478                                   &set_key_retry_task,
1479                                   kx);
1480 }
1481
1482
1483 /**
1484  * Encrypt and transmit a message with the given payload.
1485  *
1486  * @param kx key exchange context
1487  * @param payload payload of the message
1488  * @param payload_size number of bytes in @a payload
1489  */
1490 void
1491 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
1492                              const void *payload,
1493                              size_t payload_size)
1494 {
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;
1502
1503   ph = (struct EncryptedMessage *) pbuf;
1504   ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1505   ph->iv_seed = calculate_seed (kx);
1506   ph->reserved = 0;
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,
1510                              payload_size,
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,
1515                                           &iv,
1516                                           &ph->sequence_number,
1517                                           &em->sequence_number,
1518                                           used - ENCRYPTED_HEADER_SIZE));
1519 #if DEBUG_KX
1520   {
1521     struct GNUNET_HashCode hc;
1522
1523     GNUNET_CRYPTO_hash (&ph->sequence_number,
1524                         used - ENCRYPTED_HEADER_SIZE,
1525                         &hc);
1526     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1527                 "Encrypted payload `%s' of %u bytes for %s\n",
1528                 GNUNET_h2s (&hc),
1529                 (unsigned int) (used - ENCRYPTED_HEADER_SIZE),
1530                 GNUNET_i2s (kx->peer));
1531   }
1532 #endif
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,
1537                       &em->hmac);
1538 #if DEBUG_KX
1539   {
1540     struct GNUNET_HashCode hc;
1541
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),
1546                 GNUNET_h2s (&hc),
1547                 GNUNET_h2s2 (&em->hmac));
1548   }
1549 #endif
1550   kx->has_excess_bandwidth = GNUNET_NO;
1551   GNUNET_MQ_send (kx->mq, env);
1552 }
1553
1554
1555 /**
1556  * We received an encrypted message.  Check that it is
1557  * well-formed (size-wise).
1558  *
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)
1562  */
1563 static int
1564 check_encrypted (void *cls, const struct EncryptedMessage *m)
1565 {
1566   uint16_t size = ntohs (m->header.size) - sizeof (*m);
1567
1568   if (size < sizeof (struct GNUNET_MessageHeader))
1569   {
1570     GNUNET_break_op (0);
1571     return GNUNET_SYSERR;
1572   }
1573   return GNUNET_OK;
1574 }
1575
1576
1577 /**
1578  * We received an encrypted message.  Decrypt, validate and
1579  * pass on to the appropriate clients.
1580  *
1581  * @param cls key exchange context for encrypting the message
1582  * @param m encrypted message
1583  */
1584 static void
1585 handle_encrypted (void *cls, const struct EncryptedMessage *m)
1586 {
1587   struct GSC_KeyExchangeInfo *kx = cls;
1588   struct EncryptedMessage *pt; /* plaintext */
1589   struct GNUNET_HashCode ph;
1590   uint32_t snum;
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;
1596
1597   if (GNUNET_CORE_KX_STATE_UP != kx->status)
1598   {
1599     GNUNET_STATISTICS_update (GSC_stats,
1600                               gettext_noop (
1601                                 "# DATA message dropped (out of order)"),
1602                               1,
1603                               GNUNET_NO);
1604     return;
1605   }
1606   if (0 ==
1607       GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value_us)
1608   {
1609     GNUNET_log (
1610       GNUNET_ERROR_TYPE_WARNING,
1611       _ (
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,
1615                               gettext_noop (
1616                                 "# sessions terminated by key expiration"),
1617                               1,
1618                               GNUNET_NO);
1619     GSC_SESSIONS_end (kx->peer);
1620     if (NULL != kx->keep_alive_task)
1621     {
1622       GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1623       kx->keep_alive_task = NULL;
1624     }
1625     kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1626     monitor_notify_all (kx);
1627     send_key (kx);
1628     return;
1629   }
1630
1631   /* validate hash */
1632 #if DEBUG_KX
1633   {
1634     struct GNUNET_HashCode hc;
1635
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",
1639                 GNUNET_h2s (&hc),
1640                 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1641                 GNUNET_i2s (kx->peer));
1642   }
1643 #endif
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,
1648                       &ph);
1649 #if DEBUG_KX
1650   {
1651     struct GNUNET_HashCode hc;
1652
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),
1657                 GNUNET_h2s (&hc),
1658                 GNUNET_h2s2 (&m->hmac));
1659   }
1660 #endif
1661   if (0 != memcmp (&ph, &m->hmac, sizeof (struct GNUNET_HashCode)))
1662   {
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));
1667     return;
1668   }
1669   derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1670   /* decrypt */
1671   if (GNUNET_OK != do_decrypt (kx,
1672                                &iv,
1673                                &m->sequence_number,
1674                                &buf[ENCRYPTED_HEADER_SIZE],
1675                                size - ENCRYPTED_HEADER_SIZE))
1676   {
1677     GNUNET_break_op (0);
1678     return;
1679   }
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;
1685
1686   /* validate sequence number */
1687   snum = ntohl (pt->sequence_number);
1688   if (kx->last_sequence_number_received == snum)
1689   {
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)"),
1695                               size,
1696                               GNUNET_NO);
1697     return;
1698   }
1699   if ((kx->last_sequence_number_received > snum) &&
1700       (kx->last_sequence_number_received - snum > 32))
1701   {
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,
1706                               gettext_noop (
1707                                 "# bytes dropped (out of sequence)"),
1708                               size,
1709                               GNUNET_NO);
1710     return;
1711   }
1712   if (kx->last_sequence_number_received > snum)
1713   {
1714     uint32_t rotbit = 1U << (kx->last_sequence_number_received - snum - 1);
1715
1716     if ((kx->last_packets_bitmap & rotbit) != 0)
1717     {
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)"),
1722                                 size,
1723                                 GNUNET_NO);
1724       /* duplicate, ignore */
1725       return;
1726     }
1727     kx->last_packets_bitmap |= rotbit;
1728   }
1729   if (kx->last_sequence_number_received < snum)
1730   {
1731     unsigned int shift = (snum - kx->last_sequence_number_received);
1732
1733     if (shift >= 8 * sizeof (kx->last_packets_bitmap))
1734       kx->last_packets_bitmap = 0;
1735     else
1736       kx->last_packets_bitmap <<= shift;
1737     kx->last_sequence_number_received = snum;
1738   }
1739
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)
1744   {
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),
1749                   GNUNET_YES));
1750     GNUNET_STATISTICS_update (GSC_stats,
1751                               gettext_noop (
1752                                 "# bytes dropped (ancient message)"),
1753                               size,
1754                               GNUNET_NO);
1755     return;
1756   }
1757
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),
1763                             GNUNET_NO);
1764   if (GNUNET_OK !=
1765       GNUNET_MST_from_buffer (kx->mst,
1766                               &buf[sizeof (struct EncryptedMessage)],
1767                               size - sizeof (struct EncryptedMessage),
1768                               GNUNET_YES,
1769                               GNUNET_NO))
1770     GNUNET_break_op (0);
1771 }
1772
1773
1774 /**
1775  * One of our neighbours has excess bandwidth, remember this.
1776  *
1777  * @param cls NULL
1778  * @param pid identity of the peer with excess bandwidth
1779  * @param connect_cls the `struct Neighbour`
1780  */
1781 static void
1782 handle_transport_notify_excess_bw (void *cls,
1783                                    const struct GNUNET_PeerIdentity *pid,
1784                                    void *connect_cls)
1785 {
1786   struct GSC_KeyExchangeInfo *kx = connect_cls;
1787
1788   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1789               "Peer %s has excess bandwidth available\n",
1790               GNUNET_i2s (pid));
1791   kx->has_excess_bandwidth = GNUNET_YES;
1792   GSC_SESSIONS_solicit (pid);
1793 }
1794
1795
1796 /**
1797  * Setup the message that links the ephemeral key to our persistent
1798  * public key and generate the appropriate signature.
1799  */
1800 static void
1801 sign_ephemeral_key ()
1802 {
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,
1816                                                           "core",
1817                                                           "USE_EPHEMERAL_KEYS"))
1818   {
1819     current_ekm.expiration_time =
1820       GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (
1821         GNUNET_TIME_relative_add (REKEY_FREQUENCY, REKEY_TOLERANCE)));
1822   }
1823   else
1824   {
1825     current_ekm.expiration_time =
1826       GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1827   }
1828   GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key,
1829                                       &current_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                                            &current_ekm.purpose,
1834                                            &current_ekm.signature));
1835 }
1836
1837
1838 /**
1839  * Task run to trigger rekeying.
1840  *
1841  * @param cls closure, NULL
1842  */
1843 static void
1844 do_rekey (void *cls)
1845 {
1846   struct GSC_KeyExchangeInfo *pos;
1847
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 ();
1854   {
1855     struct GNUNET_HashCode eh;
1856
1857     GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1858                         sizeof (current_ekm.ephemeral_key),
1859                         &eh);
1860     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Rekeying to %s\n", GNUNET_h2s (&eh));
1861   }
1862   for (pos = kx_head; NULL != pos; pos = pos->next)
1863   {
1864     if (GNUNET_CORE_KX_STATE_UP == pos->status)
1865     {
1866       pos->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1867       monitor_notify_all (pos);
1868       derive_session_keys (pos);
1869     }
1870     if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
1871     {
1872       pos->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1873       monitor_notify_all (pos);
1874     }
1875     monitor_notify_all (pos);
1876     send_key (pos);
1877   }
1878 }
1879
1880
1881 /**
1882  * Initialize KX subsystem.
1883  *
1884  * @param pk private key to use for the peer
1885  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1886  */
1887 int
1888 GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
1889 {
1890   struct GNUNET_MQ_MessageHandler handlers[] =
1891     {GNUNET_MQ_hd_fixed_size (ephemeral_key,
1892                               GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
1893                               struct EphemeralKeyMessage,
1894                               NULL),
1895      GNUNET_MQ_hd_fixed_size (ping,
1896                               GNUNET_MESSAGE_TYPE_CORE_PING,
1897                               struct PingMessage,
1898                               NULL),
1899      GNUNET_MQ_hd_fixed_size (pong,
1900                               GNUNET_MESSAGE_TYPE_CORE_PONG,
1901                               struct PongMessage,
1902                               NULL),
1903      GNUNET_MQ_hd_var_size (encrypted,
1904                             GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE,
1905                             struct EncryptedMessage,
1906                             NULL),
1907      GNUNET_MQ_handler_end ()};
1908
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)
1914   {
1915     GNUNET_break (0);
1916     GNUNET_free (my_private_key);
1917     my_private_key = NULL;
1918     return GNUNET_SYSERR;
1919   }
1920   sign_ephemeral_key ();
1921   {
1922     struct GNUNET_HashCode eh;
1923
1924     GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1925                         sizeof (current_ekm.ephemeral_key),
1926                         &eh);
1927     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1928                 "Starting with ephemeral key %s\n",
1929                 GNUNET_h2s (&eh));
1930   }
1931
1932   nc = GNUNET_notification_context_create (1);
1933   rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL);
1934   transport =
1935     GNUNET_TRANSPORT_core_connect (GSC_cfg,
1936                                    &GSC_my_identity,
1937                                    handlers,
1938                                    NULL,
1939                                    &handle_transport_notify_connect,
1940                                    &handle_transport_notify_disconnect,
1941                                    &handle_transport_notify_excess_bw);
1942   if (NULL == transport)
1943   {
1944     GSC_KX_done ();
1945     return GNUNET_SYSERR;
1946   }
1947   return GNUNET_OK;
1948 }
1949
1950
1951 /**
1952  * Shutdown KX subsystem.
1953  */
1954 void
1955 GSC_KX_done ()
1956 {
1957   if (NULL != transport)
1958   {
1959     GNUNET_TRANSPORT_core_disconnect (transport);
1960     transport = NULL;
1961   }
1962   if (NULL != rekey_task)
1963   {
1964     GNUNET_SCHEDULER_cancel (rekey_task);
1965     rekey_task = NULL;
1966   }
1967   if (NULL != my_ephemeral_key)
1968   {
1969     GNUNET_free (my_ephemeral_key);
1970     my_ephemeral_key = NULL;
1971   }
1972   if (NULL != my_private_key)
1973   {
1974     GNUNET_free (my_private_key);
1975     my_private_key = NULL;
1976   }
1977   if (NULL != nc)
1978   {
1979     GNUNET_notification_context_destroy (nc);
1980     nc = NULL;
1981   }
1982 }
1983
1984
1985 /**
1986  * Check how many messages are queued for the given neighbour.
1987  *
1988  * @param kxinfo data about neighbour to check
1989  * @return number of items in the message queue
1990  */
1991 unsigned int
1992 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
1993 {
1994   return GNUNET_MQ_get_length (kxinfo->mq);
1995 }
1996
1997
1998 /**
1999  * Check if the given neighbour has excess bandwidth available.
2000  *
2001  * @param target neighbour to check
2002  * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
2003  */
2004 int
2005 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
2006 {
2007   return kxinfo->has_excess_bandwidth;
2008 }
2009
2010
2011 /**
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.
2016  *
2017  * @param mq message queue to add for monitoring
2018  */
2019 void
2020 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
2021 {
2022   struct GNUNET_MQ_Envelope *env;
2023   struct MonitorNotifyMessage *done_msg;
2024   struct GSC_KeyExchangeInfo *kx;
2025
2026   GNUNET_notification_context_add (nc, mq);
2027   for (kx = kx_head; NULL != kx; kx = kx->next)
2028   {
2029     struct GNUNET_MQ_Envelope *env;
2030     struct MonitorNotifyMessage *msg;
2031
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);
2037   }
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);
2042 }
2043
2044
2045 /* end of gnunet-service-core_kx.c */