glitch in the license text detected by hyazinthe, thank you!
[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
16 /**
17  * @file core/gnunet-service-core_kx.c
18  * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other peers
19  * @author Christian Grothoff
20  */
21 #include "platform.h"
22 #include "gnunet-service-core_kx.h"
23 #include "gnunet-service-core.h"
24 #include "gnunet-service-core_sessions.h"
25 #include "gnunet_statistics_service.h"
26 #include "gnunet_transport_core_service.h"
27 #include "gnunet_constants.h"
28 #include "gnunet_signatures.h"
29 #include "gnunet_protocols.h"
30 #include "core.h"
31
32 /**
33  * Enable expensive (and possibly problematic for privacy!) logging of KX.
34  */
35 #define DEBUG_KX 0
36
37 /**
38  * How long do we wait for SET_KEY confirmation initially?
39  */
40 #define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
41
42 /**
43  * What is the minimum frequency for a PING message?
44  */
45 #define MIN_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
46
47 /**
48  * How often do we rekey?
49  */
50 #define REKEY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
51
52 /**
53  * What time difference do we tolerate?
54  */
55 #define REKEY_TOLERANCE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
56
57 /**
58  * What is the maximum age of a message for us to consider processing
59  * it?  Note that this looks at the timestamp used by the other peer,
60  * so clock skew between machines does come into play here.  So this
61  * should be picked high enough so that a little bit of clock skew
62  * does not prevent peers from connecting to us.
63  */
64 #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
65
66
67
68 GNUNET_NETWORK_STRUCT_BEGIN
69
70 /**
71  * Message transmitted with the signed ephemeral key of a peer.  The
72  * session key is then derived from the two ephemeral keys (ECDHE).
73  */
74 struct EphemeralKeyMessage
75 {
76
77   /**
78    * Message type is #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY.
79    */
80   struct GNUNET_MessageHeader header;
81
82   /**
83    * Status of the sender (should be in `enum PeerStateMachine`), nbo.
84    */
85   int32_t sender_status GNUNET_PACKED;
86
87   /**
88    * An ECC signature of the @e origin_identity asserting the validity
89    * of the given ephemeral key.
90    */
91   struct GNUNET_CRYPTO_EddsaSignature signature;
92
93   /**
94    * Information about what is being signed.
95    */
96   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
97
98   /**
99    * At what time was this key created (beginning of validity).
100    */
101   struct GNUNET_TIME_AbsoluteNBO creation_time;
102
103   /**
104    * When does the given ephemeral key expire (end of validity).
105    */
106   struct GNUNET_TIME_AbsoluteNBO expiration_time;
107
108   /**
109    * Ephemeral public ECC key.
110    */
111   struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key;
112
113   /**
114    * Public key of the signing peer (persistent version, not the
115    * ephemeral public key).
116    */
117   struct GNUNET_PeerIdentity origin_identity;
118
119 };
120
121
122 /**
123  * We're sending an (encrypted) PING to the other peer to check if he
124  * can decrypt.  The other peer should respond with a PONG with the
125  * same content, except this time encrypted with the receiver's key.
126  */
127 struct PingMessage
128 {
129   /**
130    * Message type is #GNUNET_MESSAGE_TYPE_CORE_PING.
131    */
132   struct GNUNET_MessageHeader header;
133
134   /**
135    * Seed for the IV
136    */
137   uint32_t iv_seed GNUNET_PACKED;
138
139   /**
140    * Intended target of the PING, used primarily to check
141    * that decryption actually worked.
142    */
143   struct GNUNET_PeerIdentity target;
144
145   /**
146    * Random number chosen to make replay harder.
147    */
148   uint32_t challenge GNUNET_PACKED;
149 };
150
151
152 /**
153  * Response to a PING.  Includes data from the original PING.
154  */
155 struct PongMessage
156 {
157   /**
158    * Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG.
159    */
160   struct GNUNET_MessageHeader header;
161
162   /**
163    * Seed for the IV
164    */
165   uint32_t iv_seed GNUNET_PACKED;
166
167   /**
168    * Random number to make replay attacks harder.
169    */
170   uint32_t challenge GNUNET_PACKED;
171
172   /**
173    * Reserved, always zero.
174    */
175   uint32_t reserved;
176
177   /**
178    * Intended target of the PING, used primarily to check
179    * that decryption actually worked.
180    */
181   struct GNUNET_PeerIdentity target;
182 };
183
184
185 /**
186  * Encapsulation for encrypted messages exchanged between
187  * peers.  Followed by the actual encrypted data.
188  */
189 struct EncryptedMessage
190 {
191   /**
192    * Message type is #GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE.
193    */
194   struct GNUNET_MessageHeader header;
195
196   /**
197    * Random value used for IV generation.
198    */
199   uint32_t iv_seed GNUNET_PACKED;
200
201   /**
202    * MAC of the encrypted message (starting at @e sequence_number),
203    * used to verify message integrity. Everything after this value
204    * (excluding this value itself) will be encrypted and
205    * authenticated.  #ENCRYPTED_HEADER_SIZE must be set to the offset
206    * of the *next* field.
207    */
208   struct GNUNET_HashCode hmac;
209
210   /**
211    * Sequence number, in network byte order.  This field
212    * must be the first encrypted/decrypted field
213    */
214   uint32_t sequence_number GNUNET_PACKED;
215
216   /**
217    * Reserved, always zero.
218    */
219   uint32_t reserved GNUNET_PACKED;
220
221   /**
222    * Timestamp.  Used to prevent replay of ancient messages
223    * (recent messages are caught with the sequence number).
224    */
225   struct GNUNET_TIME_AbsoluteNBO timestamp;
226
227 };
228 GNUNET_NETWORK_STRUCT_END
229
230
231 /**
232  * Number of bytes (at the beginning) of `struct EncryptedMessage`
233  * that are NOT encrypted.
234  */
235 #define ENCRYPTED_HEADER_SIZE (offsetof(struct EncryptedMessage, sequence_number))
236
237
238 /**
239  * Information about the status of a key exchange with another peer.
240  */
241 struct GSC_KeyExchangeInfo
242 {
243
244   /**
245    * DLL.
246    */
247   struct GSC_KeyExchangeInfo *next;
248
249   /**
250    * DLL.
251    */
252   struct GSC_KeyExchangeInfo *prev;
253
254   /**
255    * Identity of the peer.
256    */
257   const struct GNUNET_PeerIdentity *peer;
258
259   /**
260    * Message queue for sending messages to @a peer.
261    */
262   struct GNUNET_MQ_Handle *mq;
263
264   /**
265    * Our message stream tokenizer (for encrypted payload).
266    */
267   struct GNUNET_MessageStreamTokenizer *mst;
268
269   /**
270    * PING message we transmit to the other peer.
271    */
272   struct PingMessage ping;
273
274   /**
275    * Ephemeral public ECC key of the other peer.
276    */
277   struct GNUNET_CRYPTO_EcdhePublicKey other_ephemeral_key;
278
279   /**
280    * Key we use to encrypt our messages for the other peer
281    * (initialized by us when we do the handshake).
282    */
283   struct GNUNET_CRYPTO_SymmetricSessionKey encrypt_key;
284
285   /**
286    * Key we use to decrypt messages from the other peer
287    * (given to us by the other peer during the handshake).
288    */
289   struct GNUNET_CRYPTO_SymmetricSessionKey decrypt_key;
290
291   /**
292    * At what time did the other peer generate the decryption key?
293    */
294   struct GNUNET_TIME_Absolute foreign_key_expires;
295
296   /**
297    * When should the session time out (if there are no PONGs)?
298    */
299   struct GNUNET_TIME_Absolute timeout;
300
301   /**
302    * What was the last timeout we informed our monitors about?
303    */
304   struct GNUNET_TIME_Absolute last_notify_timeout;
305
306   /**
307    * At what frequency are we currently re-trying SET_KEY messages?
308    */
309   struct GNUNET_TIME_Relative set_key_retry_frequency;
310
311   /**
312    * ID of task used for re-trying SET_KEY and PING message.
313    */
314   struct GNUNET_SCHEDULER_Task *retry_set_key_task;
315
316   /**
317    * ID of task used for sending keep-alive pings.
318    */
319   struct GNUNET_SCHEDULER_Task *keep_alive_task;
320
321   /**
322    * Bit map indicating which of the 32 sequence numbers before the
323    * last were received (good for accepting out-of-order packets and
324    * estimating reliability of the connection)
325    */
326   uint32_t last_packets_bitmap;
327
328   /**
329    * last sequence number received on this connection (highest)
330    */
331   uint32_t last_sequence_number_received;
332
333   /**
334    * last sequence number transmitted
335    */
336   uint32_t last_sequence_number_sent;
337
338   /**
339    * What was our PING challenge number (for this peer)?
340    */
341   uint32_t ping_challenge;
342
343   /**
344    * #GNUNET_YES if this peer currently has excess bandwidth.
345    */
346   int has_excess_bandwidth;
347
348   /**
349    * What is our connection status?
350    */
351   enum GNUNET_CORE_KxState status;
352
353 };
354
355
356 /**
357  * Transport service.
358  */
359 static struct GNUNET_TRANSPORT_CoreHandle *transport;
360
361 /**
362  * Our private key.
363  */
364 static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
365
366 /**
367  * Our ephemeral private key.
368  */
369 static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key;
370
371 /**
372  * Current message we send for a key exchange.
373  */
374 static struct EphemeralKeyMessage current_ekm;
375
376 /**
377  * DLL head.
378  */
379 static struct GSC_KeyExchangeInfo *kx_head;
380
381 /**
382  * DLL tail.
383  */
384 static struct GSC_KeyExchangeInfo *kx_tail;
385
386 /**
387  * Task scheduled for periodic re-generation (and thus rekeying) of our
388  * ephemeral key.
389  */
390 static struct GNUNET_SCHEDULER_Task *rekey_task;
391
392 /**
393  * Notification context for broadcasting to monitors.
394  */
395 static struct GNUNET_NotificationContext *nc;
396
397
398 /**
399  * Calculate seed value we should use for a message.
400  *
401  * @param kx key exchange context
402  */
403 static uint32_t
404 calculate_seed (struct GSC_KeyExchangeInfo *kx)
405 {
406   /* Note: may want to make this non-random and instead
407      derive from key material to avoid having an undetectable
408      side-channel */
409   return htonl (GNUNET_CRYPTO_random_u32
410                 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
411 }
412
413
414 /**
415  * Inform all monitors about the KX state of the given peer.
416  *
417  * @param kx key exchange state to inform about
418  */
419 static void
420 monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
421 {
422   struct MonitorNotifyMessage msg;
423
424   msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
425   msg.header.size = htons (sizeof (msg));
426   msg.state = htonl ((uint32_t) kx->status);
427   msg.peer = *kx->peer;
428   msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
429   GNUNET_notification_context_broadcast (nc,
430                                          &msg.header,
431                                          GNUNET_NO);
432   kx->last_notify_timeout = kx->timeout;
433 }
434
435
436 /**
437  * Derive an authentication key from "set key" information
438  *
439  * @param akey authentication key to derive
440  * @param skey session key to use
441  * @param seed seed to use
442  */
443 static void
444 derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
445                  const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
446                  uint32_t seed)
447 {
448   static const char ctx[] = "authentication key";
449 #if DEBUG_KX
450   struct GNUNET_HashCode sh;
451   
452   GNUNET_CRYPTO_hash (skey,
453                       sizeof (*skey),
454                       &sh);
455   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
456               "Deriving Auth key from SKEY %s and seed %u\n",
457               GNUNET_h2s (&sh),
458               (unsigned int) seed);
459 #endif
460   GNUNET_CRYPTO_hmac_derive_key (akey,
461                                  skey,
462                                  &seed, sizeof (seed),
463                                  skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
464                                  ctx, sizeof (ctx),
465                                  NULL);
466 }
467
468
469 /**
470  * Derive an IV from packet information
471  *
472  * @param iv initialization vector to initialize
473  * @param skey session key to use
474  * @param seed seed to use
475  * @param identity identity of the other peer to use
476  */
477 static void
478 derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
479            const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
480            uint32_t seed,
481            const struct GNUNET_PeerIdentity *identity)
482 {
483   static const char ctx[] = "initialization vector";
484 #if DEBUG_KX
485   struct GNUNET_HashCode sh;
486   
487   GNUNET_CRYPTO_hash (skey,
488                       sizeof (*skey),
489                       &sh);
490   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491               "Deriving IV from SKEY %s and seed %u for peer %s\n",
492               GNUNET_h2s (&sh),
493               (unsigned int) seed,
494               GNUNET_i2s (identity));
495 #endif
496   GNUNET_CRYPTO_symmetric_derive_iv (iv,
497                                      skey,
498                                      &seed, sizeof (seed),
499                                      identity,
500                                      sizeof (struct GNUNET_PeerIdentity), ctx,
501                                      sizeof (ctx), NULL);
502 }
503
504
505 /**
506  * Derive an IV from pong packet information
507  *
508  * @param iv initialization vector to initialize
509  * @param skey session key to use
510  * @param seed seed to use
511  * @param challenge nonce to use
512  * @param identity identity of the other peer to use
513  */
514 static void
515 derive_pong_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
516                 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
517                 uint32_t seed,
518                 uint32_t challenge,
519                 const struct GNUNET_PeerIdentity *identity)
520 {
521   static const char ctx[] = "pong initialization vector";
522 #if DEBUG_KX
523   struct GNUNET_HashCode sh;
524   
525   GNUNET_CRYPTO_hash (skey,
526                       sizeof (*skey),
527                       &sh);
528   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529               "Deriving PONG IV from SKEY %s and seed %u/%u for %s\n",
530               GNUNET_h2s (&sh),
531               (unsigned int) seed,
532               (unsigned int) challenge,
533               GNUNET_i2s (identity));
534 #endif
535   GNUNET_CRYPTO_symmetric_derive_iv (iv,
536                                      skey,
537                                      &seed, sizeof (seed),
538                                      identity,
539                                      sizeof (struct GNUNET_PeerIdentity),
540                                      &challenge, sizeof (challenge),
541                                      ctx, sizeof (ctx),
542                                      NULL);
543 }
544
545
546 /**
547  * Derive an AES key from key material
548  *
549  * @param sender peer identity of the sender
550  * @param receiver peer identity of the sender
551  * @param key_material high entropy key material to use
552  * @param skey set to derived session key
553  */
554 static void
555 derive_aes_key (const struct GNUNET_PeerIdentity *sender,
556                 const struct GNUNET_PeerIdentity *receiver,
557                 const struct GNUNET_HashCode *key_material,
558                 struct GNUNET_CRYPTO_SymmetricSessionKey *skey)
559 {
560   static const char ctx[] = "aes key generation vector";
561 #if DEBUG_KX
562   struct GNUNET_HashCode sh;
563   
564   GNUNET_CRYPTO_hash (skey,
565                       sizeof (*skey),
566                       &sh);
567   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
568               "Deriving AES Keys for %s to %s from %s\n",
569               GNUNET_i2s (sender),
570               GNUNET_i2s2 (receiver),
571               GNUNET_h2s (key_material));
572 #endif
573   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
574                      ctx, sizeof (ctx),
575                      key_material, sizeof (struct GNUNET_HashCode),
576                      sender, sizeof (struct GNUNET_PeerIdentity),
577                      receiver, sizeof (struct GNUNET_PeerIdentity),
578                      NULL);
579 }
580
581
582 /**
583  * Encrypt size bytes from @a in and write the result to @a out.  Use the
584  * @a kx key for outbound traffic of the given neighbour.
585  *
586  * @param kx key information context
587  * @param iv initialization vector to use
588  * @param in ciphertext
589  * @param out plaintext
590  * @param size size of @a in/@a out
591  * @return #GNUNET_OK on success
592  */
593 static int
594 do_encrypt (struct GSC_KeyExchangeInfo *kx,
595             const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
596             const void *in,
597             void *out,
598             size_t size)
599 {
600   if (size != (uint16_t) size)
601   {
602     GNUNET_break (0);
603     return GNUNET_NO;
604   }
605   GNUNET_assert (size ==
606                  GNUNET_CRYPTO_symmetric_encrypt (in,
607                                                   (uint16_t) size,
608                                                   &kx->encrypt_key,
609                                                   iv,
610                                                   out));
611   GNUNET_STATISTICS_update (GSC_stats,
612                             gettext_noop ("# bytes encrypted"),
613                             size,
614                             GNUNET_NO);
615   /* the following is too sensitive to write to log files by accident,
616      so we require manual intervention to get this one... */
617 #if DEBUG_KX
618   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
619               "Encrypted %u bytes for `%s' using key %u, IV %u\n",
620               (unsigned int) size,
621               GNUNET_i2s (kx->peer),
622               (unsigned int) kx->encrypt_key.crc32,
623               GNUNET_CRYPTO_crc32_n (iv,
624                                      sizeof (iv)));
625 #endif
626   return GNUNET_OK;
627 }
628
629
630 /**
631  * Decrypt size bytes from @a in and write the result to @a out.  Use
632  * the @a kx key for inbound traffic of the given neighbour.  This
633  * function does NOT do any integrity-checks on the result.
634  *
635  * @param kx key information context
636  * @param iv initialization vector to use
637  * @param in ciphertext
638  * @param out plaintext
639  * @param size size of @a in / @a out
640  * @return #GNUNET_OK on success
641  */
642 static int
643 do_decrypt (struct GSC_KeyExchangeInfo *kx,
644             const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
645             const void *in,
646             void *out,
647             size_t size)
648 {
649   if (size != (uint16_t) size)
650   {
651     GNUNET_break (0);
652     return GNUNET_NO;
653   }
654   if ( (kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
655        (kx->status != GNUNET_CORE_KX_STATE_UP) &&
656        (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT) )
657   {
658     GNUNET_break_op (0);
659     return GNUNET_SYSERR;
660   }
661   if (size !=
662       GNUNET_CRYPTO_symmetric_decrypt (in,
663                                        (uint16_t) size,
664                                        &kx->decrypt_key,
665                                        iv,
666                                        out))
667   {
668     GNUNET_break (0);
669     return GNUNET_SYSERR;
670   }
671   GNUNET_STATISTICS_update (GSC_stats,
672                             gettext_noop ("# bytes decrypted"),
673                             size,
674                             GNUNET_NO);
675   /* the following is too sensitive to write to log files by accident,
676      so we require manual intervention to get this one... */
677 #if DEBUG_KX
678   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
679               "Decrypted %u bytes from `%s' using key %u, IV %u\n",
680               (unsigned int) size,
681               GNUNET_i2s (kx->peer),
682               (unsigned int) kx->decrypt_key.crc32,
683               GNUNET_CRYPTO_crc32_n (iv,
684                                      sizeof
685                                      (*iv)));
686 #endif
687   return GNUNET_OK;
688 }
689
690
691 /**
692  * Send our key (and encrypted PING) to the other peer.
693  *
694  * @param kx key exchange context
695  */
696 static void
697 send_key (struct GSC_KeyExchangeInfo *kx);
698
699
700 /**
701  * Task that will retry #send_key() if our previous attempt failed.
702  *
703  * @param cls our `struct GSC_KeyExchangeInfo`
704  */
705 static void
706 set_key_retry_task (void *cls)
707 {
708   struct GSC_KeyExchangeInfo *kx = cls;
709
710   kx->retry_set_key_task = NULL;
711   kx->set_key_retry_frequency = GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency);
712   GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
713   send_key (kx);
714 }
715
716
717 /**
718  * Create a fresh PING message for transmission to the other peer.
719  *
720  * @param kx key exchange context to create PING for
721  */
722 static void
723 setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
724 {
725   struct PingMessage pp;
726   struct PingMessage *pm;
727   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
728
729   pm = &kx->ping;
730   kx->ping_challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
731                                                  UINT32_MAX);
732   pm->header.size = htons (sizeof (struct PingMessage));
733   pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
734   pm->iv_seed = calculate_seed (kx);
735   derive_iv (&iv,
736              &kx->encrypt_key,
737              pm->iv_seed,
738              kx->peer);
739   pp.challenge = kx->ping_challenge;
740   pp.target = *kx->peer;
741   do_encrypt (kx,
742               &iv,
743               &pp.target,
744               &pm->target,
745               sizeof (struct PingMessage) - ((void *) &pm->target -
746                                              (void *) pm));
747 }
748
749
750 /**
751  * Deliver P2P message to interested clients.  Invokes send twice,
752  * once for clients that want the full message, and once for clients
753  * that only want the header
754  *
755  * @param cls the `struct GSC_KeyExchangeInfo`
756  * @param m the message
757  * @return #GNUNET_OK on success,
758  *    #GNUNET_NO to stop further processing (no error)
759  *    #GNUNET_SYSERR to stop further processing with error
760  */
761 static int
762 deliver_message (void *cls,
763                  const struct GNUNET_MessageHeader *m)
764 {
765   struct GSC_KeyExchangeInfo *kx = cls;
766
767   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
768               "Decrypted message of type %d from %s\n",
769               ntohs (m->type),
770               GNUNET_i2s (kx->peer));
771   if (GNUNET_CORE_KX_STATE_UP != kx->status)
772   {
773     GNUNET_STATISTICS_update (GSC_stats,
774                               gettext_noop ("# PAYLOAD dropped (out of order)"),
775                               1,
776                               GNUNET_NO);
777     return GNUNET_OK;
778   }
779   switch (ntohs (m->type))
780   {
781   case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
782   case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
783     GSC_SESSIONS_set_typemap (kx->peer, m);
784     return GNUNET_OK;
785   case GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP:
786     GSC_SESSIONS_confirm_typemap (kx->peer, m);
787     return GNUNET_OK;
788   default:
789     GSC_CLIENTS_deliver_message (kx->peer,
790                                  m,
791                                  ntohs (m->size),
792                                  GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
793     GSC_CLIENTS_deliver_message (kx->peer,
794                                  m,
795                                  sizeof (struct GNUNET_MessageHeader),
796                                  GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
797   }
798   return GNUNET_OK;
799 }
800
801
802 /**
803  * Function called by transport to notify us that
804  * a peer connected to us (on the network level).
805  * Starts the key exchange with the given peer.
806  *
807  * @param cls closure (NULL)
808  * @param pid identity of the peer to do a key exchange with
809  * @return key exchange information context
810  */
811 static void *
812 handle_transport_notify_connect (void *cls,
813                                  const struct GNUNET_PeerIdentity *pid,
814                                  struct GNUNET_MQ_Handle *mq)
815 {
816   struct GSC_KeyExchangeInfo *kx;
817   struct GNUNET_HashCode h1;
818   struct GNUNET_HashCode h2;
819
820   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
821               "Initiating key exchange with `%s'\n",
822               GNUNET_i2s (pid));
823   GNUNET_STATISTICS_update (GSC_stats,
824                             gettext_noop ("# key exchanges initiated"),
825                             1,
826                             GNUNET_NO);
827   kx = GNUNET_new (struct GSC_KeyExchangeInfo);
828   kx->mst = GNUNET_MST_create (&deliver_message,
829                                kx);
830   kx->mq = mq;
831   kx->peer = pid;
832   kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
833   GNUNET_CONTAINER_DLL_insert (kx_head,
834                                kx_tail,
835                                kx);
836   kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
837   monitor_notify_all (kx);
838   GNUNET_CRYPTO_hash (pid,
839                       sizeof (struct GNUNET_PeerIdentity),
840                       &h1);
841   GNUNET_CRYPTO_hash (&GSC_my_identity,
842                       sizeof (struct GNUNET_PeerIdentity),
843                       &h2);
844   if (0 < GNUNET_CRYPTO_hash_cmp (&h1,
845                                   &h2))
846   {
847     /* peer with "lower" identity starts KX, otherwise we typically end up
848        with both peers starting the exchange and transmit the 'set key'
849        message twice */
850     send_key (kx);
851   }
852   else
853   {
854     /* peer with "higher" identity starts a delayed  KX, if the "lower" peer
855      * does not start a KX since he sees no reasons to do so  */
856     kx->retry_set_key_task
857       = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
858                                       &set_key_retry_task,
859                                       kx);
860   }
861   return kx;
862 }
863
864
865 /**
866  * Function called by transport telling us that a peer
867  * disconnected.
868  * Stop key exchange with the given peer.  Clean up key material.
869  *
870  * @param cls closure
871  * @param peer the peer that disconnected
872  * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
873  */
874 static void
875 handle_transport_notify_disconnect (void *cls,
876                                     const struct GNUNET_PeerIdentity *peer,
877                                     void *handler_cls)
878 {
879   struct GSC_KeyExchangeInfo *kx = handler_cls;
880
881   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
882               "Peer `%s' disconnected from us.\n",
883               GNUNET_i2s (peer));
884   GSC_SESSIONS_end (kx->peer);
885   GNUNET_STATISTICS_update (GSC_stats,
886                             gettext_noop ("# key exchanges stopped"),
887                             1,
888                             GNUNET_NO);
889   if (NULL != kx->retry_set_key_task)
890   {
891     GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
892     kx->retry_set_key_task = NULL;
893   }
894   if (NULL != kx->keep_alive_task)
895   {
896     GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
897     kx->keep_alive_task = NULL;
898   }
899   kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
900   monitor_notify_all (kx);
901   GNUNET_CONTAINER_DLL_remove (kx_head,
902                                kx_tail,
903                                kx);
904   GNUNET_MST_destroy (kx->mst);
905   GNUNET_free (kx);
906 }
907
908
909 /**
910  * Send our PING to the other peer.
911  *
912  * @param kx key exchange context
913  */
914 static void
915 send_ping (struct GSC_KeyExchangeInfo *kx)
916 {
917   struct GNUNET_MQ_Envelope *env;
918
919   GNUNET_STATISTICS_update (GSC_stats,
920                             gettext_noop ("# PING messages transmitted"),
921                             1,
922                             GNUNET_NO);
923   env = GNUNET_MQ_msg_copy (&kx->ping.header);
924   GNUNET_MQ_send (kx->mq,
925                   env);
926 }
927
928
929 /**
930  * Derive fresh session keys from the current ephemeral keys.
931  *
932  * @param kx session to derive keys for
933  */
934 static void
935 derive_session_keys (struct GSC_KeyExchangeInfo *kx)
936 {
937   struct GNUNET_HashCode key_material;
938
939   if (GNUNET_OK !=
940       GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key,
941                               &kx->other_ephemeral_key,
942                               &key_material))
943   {
944     GNUNET_break (0);
945     return;
946   }
947   derive_aes_key (&GSC_my_identity,
948                   kx->peer,
949                   &key_material,
950                   &kx->encrypt_key);
951   derive_aes_key (kx->peer,
952                   &GSC_my_identity,
953                   &key_material,
954                   &kx->decrypt_key);
955   memset (&key_material, 0, sizeof (key_material));
956   /* fresh key, reset sequence numbers */
957   kx->last_sequence_number_received = 0;
958   kx->last_packets_bitmap = 0;
959   setup_fresh_ping (kx);
960 }
961
962
963 /**
964  * We received a #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY message.
965  * Validate and update our key material and status.
966  *
967  * @param cls key exchange status for the corresponding peer
968  * @param m the set key message we received
969  */
970 static void
971 handle_ephemeral_key (void *cls,
972                       const struct EphemeralKeyMessage *m)
973 {
974   struct GSC_KeyExchangeInfo *kx = cls;
975   struct GNUNET_TIME_Absolute start_t;
976   struct GNUNET_TIME_Absolute end_t;
977   struct GNUNET_TIME_Absolute now;
978   enum GNUNET_CORE_KxState sender_status;
979
980   end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
981   if ( ( (GNUNET_CORE_KX_STATE_KEY_RECEIVED == kx->status) ||
982          (GNUNET_CORE_KX_STATE_UP == kx->status) ||
983          (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status) ) &&
984        (end_t.abs_value_us < kx->foreign_key_expires.abs_value_us) )
985   {
986     GNUNET_STATISTICS_update (GSC_stats,
987                               gettext_noop ("# old ephemeral keys ignored"),
988                               1,
989                               GNUNET_NO);
990     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
991                 "Received expired EPHEMERAL_KEY from %s\n",
992                 GNUNET_i2s (&m->origin_identity));
993     return;
994   }
995   if (0 == memcmp (&m->ephemeral_key,
996                    &kx->other_ephemeral_key,
997                    sizeof (m->ephemeral_key)))
998   {
999     GNUNET_STATISTICS_update (GSC_stats,
1000                               gettext_noop ("# duplicate ephemeral keys ignored"),
1001                               1,
1002                               GNUNET_NO);
1003     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1004                 "Ignoring duplicate EPHEMERAL_KEY from %s\n",
1005                 GNUNET_i2s (&m->origin_identity));
1006     return;
1007   }
1008   if (0 !=
1009       memcmp (&m->origin_identity,
1010               kx->peer,
1011               sizeof (struct GNUNET_PeerIdentity)))
1012   {
1013     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1014                 "Received EPHEMERAL_KEY from %s, but expected %s\n",
1015                 GNUNET_i2s (&m->origin_identity),
1016                 GNUNET_i2s_full (kx->peer));
1017     GNUNET_break_op (0);
1018     return;
1019   }
1020   if ((ntohl (m->purpose.size) !=
1021        sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
1022        sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1023        sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1024        sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) +
1025        sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) ||
1026       (GNUNET_OK !=
1027        GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY,
1028                                    &m->purpose,
1029                                    &m->signature,
1030                                    &m->origin_identity.public_key)))
1031   {
1032     /* invalid signature */
1033     GNUNET_break_op (0);
1034     GNUNET_STATISTICS_update (GSC_stats,
1035                               gettext_noop ("# EPHEMERAL_KEYs rejected (bad signature)"),
1036                               1,
1037                               GNUNET_NO);
1038     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1039                 "Received EPHEMERAL_KEY from %s with bad signature\n",
1040                 GNUNET_i2s (&m->origin_identity));
1041     return;
1042   }
1043   now = GNUNET_TIME_absolute_get ();
1044   start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
1045   if ( (end_t.abs_value_us < GNUNET_TIME_absolute_subtract (now, REKEY_TOLERANCE).abs_value_us) ||
1046        (start_t.abs_value_us > GNUNET_TIME_absolute_add (now, REKEY_TOLERANCE).abs_value_us) )
1047   {
1048     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1049                 _("EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"),
1050                 GNUNET_i2s (kx->peer),
1051                 (unsigned long long) now.abs_value_us,
1052                 (unsigned long long) start_t.abs_value_us,
1053                 (unsigned long long) end_t.abs_value_us);
1054     GNUNET_STATISTICS_update (GSC_stats,
1055                               gettext_noop ("# EPHEMERAL_KEY messages rejected due to time"),
1056                               1,
1057                               GNUNET_NO);
1058     return;
1059   }
1060 #if DEBUG_KX
1061   {
1062     struct GNUNET_HashCode eh;
1063
1064     GNUNET_CRYPTO_hash (&m->ephemeral_key,
1065                         sizeof (m->ephemeral_key),
1066                         &eh);
1067     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1068                 "Received valid EPHEMERAL_KEY `%s' from `%s' in state %d.\n",
1069                 GNUNET_h2s (&eh),
1070                 GNUNET_i2s (kx->peer),
1071                 kx->status);
1072   }
1073 #endif
1074   GNUNET_STATISTICS_update (GSC_stats,
1075                             gettext_noop ("# valid ephemeral keys received"),
1076                             1,
1077                             GNUNET_NO);
1078   kx->other_ephemeral_key = m->ephemeral_key;
1079   kx->foreign_key_expires = end_t;
1080   derive_session_keys (kx);
1081
1082   /* check if we still need to send the sender our key */
1083   sender_status = (enum GNUNET_CORE_KxState) ntohl (m->sender_status);
1084   switch (sender_status)
1085   {
1086   case GNUNET_CORE_KX_STATE_DOWN:
1087     GNUNET_break_op (0);
1088     break;
1089   case GNUNET_CORE_KX_STATE_KEY_SENT:
1090     /* fine, need to send our key after updating our status, see below */
1091     GSC_SESSIONS_reinit (kx->peer);
1092     break;
1093   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1094     /* other peer already got our key, but typemap did go down */
1095     GSC_SESSIONS_reinit (kx->peer);
1096     break;
1097   case GNUNET_CORE_KX_STATE_UP:
1098     /* other peer already got our key, typemap NOT down */
1099     break;
1100   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1101     /* other peer already got our key, typemap NOT down */
1102     break;
1103   default:
1104     GNUNET_break (0);
1105     break;
1106   }
1107   /* check if we need to confirm everything is fine via PING + PONG */
1108   switch (kx->status)
1109   {
1110   case GNUNET_CORE_KX_STATE_DOWN:
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_SENT:
1120     GNUNET_assert (NULL == kx->keep_alive_task);
1121     kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1122     monitor_notify_all (kx);
1123     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1124       send_key (kx);
1125     else
1126       send_ping (kx);
1127     break;
1128   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1129     GNUNET_assert (NULL == kx->keep_alive_task);
1130     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1131       send_key (kx);
1132     else
1133       send_ping (kx);
1134     break;
1135   case GNUNET_CORE_KX_STATE_UP:
1136     kx->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1137     monitor_notify_all (kx);
1138     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1139       send_key (kx);
1140     else
1141       send_ping (kx);
1142     break;
1143   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1144     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1145       send_key (kx);
1146     else
1147       send_ping (kx);
1148     break;
1149   default:
1150     GNUNET_break (0);
1151     break;
1152   }
1153 }
1154
1155
1156 /**
1157  * We received a PING message.  Validate and transmit
1158  * a PONG message.
1159  *
1160  * @param cls key exchange status for the corresponding peer
1161  * @param m the encrypted PING message itself
1162  */
1163 static void
1164 handle_ping (void *cls,
1165              const struct PingMessage *m)
1166 {
1167   struct GSC_KeyExchangeInfo *kx = cls;
1168   struct PingMessage t;
1169   struct PongMessage tx;
1170   struct PongMessage *tp;
1171   struct GNUNET_MQ_Envelope *env;
1172   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1173
1174   GNUNET_STATISTICS_update (GSC_stats,
1175                             gettext_noop ("# PING messages received"),
1176                             1,
1177                             GNUNET_NO);
1178   if ( (kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
1179        (kx->status != GNUNET_CORE_KX_STATE_UP) &&
1180        (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
1181   {
1182     /* ignore */
1183     GNUNET_STATISTICS_update (GSC_stats,
1184                               gettext_noop ("# PING messages dropped (out of order)"),
1185                               1,
1186                               GNUNET_NO);
1187     return;
1188   }
1189   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1190               "Core service receives PING request from `%s'.\n",
1191               GNUNET_i2s (kx->peer));
1192   derive_iv (&iv,
1193              &kx->decrypt_key,
1194              m->iv_seed,
1195              &GSC_my_identity);
1196   if (GNUNET_OK !=
1197       do_decrypt (kx,
1198                   &iv,
1199                   &m->target,
1200                   &t.target,
1201                   sizeof (struct PingMessage) - ((void *) &m->target -
1202                                                  (void *) m)))
1203   {
1204     GNUNET_break_op (0);
1205     return;
1206   }
1207   if (0 !=
1208       memcmp (&t.target,
1209               &GSC_my_identity,
1210               sizeof (struct GNUNET_PeerIdentity)))
1211   {
1212     if (GNUNET_CORE_KX_STATE_REKEY_SENT != kx->status)
1213       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1214                   "Decryption of PING from peer `%s' failed, PING for `%s'?\n",
1215                   GNUNET_i2s (kx->peer),
1216                   GNUNET_i2s2 (&t.target));
1217     else
1218       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1219                   "Decryption of PING from peer `%s' failed after rekey (harmless)\n",
1220                   GNUNET_i2s (kx->peer));
1221     GNUNET_break_op (0);
1222     return;
1223   }
1224   /* construct PONG */
1225   tx.reserved = 0;
1226   tx.challenge = t.challenge;
1227   tx.target = t.target;
1228   env = GNUNET_MQ_msg (tp,
1229                        GNUNET_MESSAGE_TYPE_CORE_PONG);
1230   tp->iv_seed = calculate_seed (kx);
1231   derive_pong_iv (&iv,
1232                   &kx->encrypt_key,
1233                   tp->iv_seed,
1234                   t.challenge,
1235                   kx->peer);
1236   do_encrypt (kx,
1237               &iv,
1238               &tx.challenge,
1239               &tp->challenge,
1240               sizeof (struct PongMessage) - ((void *) &tp->challenge -
1241                                              (void *) tp));
1242   GNUNET_STATISTICS_update (GSC_stats,
1243                             gettext_noop ("# PONG messages created"),
1244                             1,
1245                             GNUNET_NO);
1246   GNUNET_MQ_send (kx->mq,
1247                   env);
1248 }
1249
1250
1251 /**
1252  * Task triggered when a neighbour entry is about to time out
1253  * (and we should prevent this by sending a PING).
1254  *
1255  * @param cls the `struct GSC_KeyExchangeInfo`
1256  */
1257 static void
1258 send_keep_alive (void *cls)
1259 {
1260   struct GSC_KeyExchangeInfo *kx = cls;
1261   struct GNUNET_TIME_Relative retry;
1262   struct GNUNET_TIME_Relative left;
1263
1264   kx->keep_alive_task = NULL;
1265   left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
1266   if (0 == left.rel_value_us)
1267   {
1268     GNUNET_STATISTICS_update (GSC_stats,
1269                               gettext_noop ("# sessions terminated by timeout"),
1270                               1,
1271                               GNUNET_NO);
1272     GSC_SESSIONS_end (kx->peer);
1273     kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1274     monitor_notify_all (kx);
1275     send_key (kx);
1276     return;
1277   }
1278   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1279               "Sending KEEPALIVE to `%s'\n",
1280               GNUNET_i2s (kx->peer));
1281   GNUNET_STATISTICS_update (GSC_stats,
1282                             gettext_noop ("# keepalive messages sent"),
1283                             1,
1284                             GNUNET_NO);
1285   setup_fresh_ping (kx);
1286   send_ping (kx);
1287   retry =
1288       GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1289                                 MIN_PING_FREQUENCY);
1290   kx->keep_alive_task =
1291       GNUNET_SCHEDULER_add_delayed (retry,
1292                                     &send_keep_alive,
1293                                     kx);
1294 }
1295
1296
1297 /**
1298  * We've seen a valid message from the other peer.
1299  * Update the time when the session would time out
1300  * and delay sending our keep alive message further.
1301  *
1302  * @param kx key exchange where we saw activity
1303  */
1304 static void
1305 update_timeout (struct GSC_KeyExchangeInfo *kx)
1306 {
1307   struct GNUNET_TIME_Relative delta;
1308
1309   kx->timeout =
1310       GNUNET_TIME_relative_to_absolute
1311       (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1312   delta = GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout,
1313                                                kx->timeout);
1314   if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
1315   {
1316     /* we only notify monitors about timeout changes if those
1317        are bigger than the threshold (5s) */
1318     monitor_notify_all (kx);
1319   }
1320   if (NULL != kx->keep_alive_task)
1321     GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1322   kx->keep_alive_task =
1323       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
1324                                     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1325                                      2),
1326                                     &send_keep_alive,
1327                                     kx);
1328 }
1329
1330
1331 /**
1332  * We received a PONG message.  Validate and update our status.
1333  *
1334  * @param kx key exchange context for the the PONG
1335  * @param m the encrypted PONG message itself
1336  */
1337 static void
1338 handle_pong (void *cls,
1339              const struct PongMessage *m)
1340 {
1341   struct GSC_KeyExchangeInfo *kx = cls;
1342   struct PongMessage t;
1343   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1344
1345   GNUNET_STATISTICS_update (GSC_stats,
1346                             gettext_noop ("# PONG messages received"),
1347                             1,
1348                             GNUNET_NO);
1349   switch (kx->status)
1350   {
1351   case GNUNET_CORE_KX_STATE_DOWN:
1352     GNUNET_STATISTICS_update (GSC_stats,
1353                               gettext_noop ("# PONG messages dropped (connection down)"), 1,
1354                               GNUNET_NO);
1355     return;
1356   case GNUNET_CORE_KX_STATE_KEY_SENT:
1357     GNUNET_STATISTICS_update (GSC_stats,
1358                               gettext_noop ("# PONG messages dropped (out of order)"), 1,
1359                               GNUNET_NO);
1360     return;
1361   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1362     break;
1363   case GNUNET_CORE_KX_STATE_UP:
1364     break;
1365   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1366     break;
1367   default:
1368     GNUNET_break (0);
1369     return;
1370   }
1371   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1372               "Core service receives PONG response from `%s'.\n",
1373               GNUNET_i2s (kx->peer));
1374   /* mark as garbage, just to be sure */
1375   memset (&t, 255, sizeof (t));
1376   derive_pong_iv (&iv,
1377                   &kx->decrypt_key,
1378                   m->iv_seed,
1379                   kx->ping_challenge,
1380                   &GSC_my_identity);
1381   if (GNUNET_OK !=
1382       do_decrypt (kx,
1383                   &iv,
1384                   &m->challenge,
1385                   &t.challenge,
1386                   sizeof (struct PongMessage) - ((void *) &m->challenge -
1387                                                  (void *) m)))
1388   {
1389     GNUNET_break_op (0);
1390     return;
1391   }
1392   GNUNET_STATISTICS_update (GSC_stats,
1393                             gettext_noop ("# PONG messages decrypted"),
1394                             1,
1395                             GNUNET_NO);
1396   if ((0 != memcmp (&t.target,
1397                     kx->peer,
1398                     sizeof (struct GNUNET_PeerIdentity))) ||
1399       (kx->ping_challenge != t.challenge))
1400   {
1401     /* PONG malformed */
1402     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1403                 "Received malformed PONG wanted sender `%s' with challenge %u\n",
1404                 GNUNET_i2s (kx->peer),
1405                 (unsigned int) kx->ping_challenge);
1406     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1407                 "Received malformed PONG received from `%s' with challenge %u\n",
1408                 GNUNET_i2s (&t.target),
1409                 (unsigned int) t.challenge);
1410     return;
1411   }
1412   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1413               "Received valid PONG from `%s'\n",
1414               GNUNET_i2s (kx->peer));
1415   /* no need to resend key any longer */
1416   if (NULL != kx->retry_set_key_task)
1417   {
1418     GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1419     kx->retry_set_key_task = NULL;
1420   }
1421   switch (kx->status)
1422   {
1423   case GNUNET_CORE_KX_STATE_DOWN:
1424     GNUNET_assert (0);           /* should be impossible */
1425     return;
1426   case GNUNET_CORE_KX_STATE_KEY_SENT:
1427     GNUNET_assert (0);           /* should be impossible */
1428     return;
1429   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1430     GNUNET_STATISTICS_update (GSC_stats,
1431                               gettext_noop ("# session keys confirmed via PONG"),
1432                               1,
1433                               GNUNET_NO);
1434     kx->status = GNUNET_CORE_KX_STATE_UP;
1435     monitor_notify_all (kx);
1436     GSC_SESSIONS_create (kx->peer, kx);
1437     GNUNET_assert (NULL == kx->keep_alive_task);
1438     update_timeout (kx);
1439     break;
1440   case GNUNET_CORE_KX_STATE_UP:
1441     GNUNET_STATISTICS_update (GSC_stats,
1442                               gettext_noop ("# timeouts prevented via PONG"),
1443                               1,
1444                               GNUNET_NO);
1445     update_timeout (kx);
1446     break;
1447   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1448     GNUNET_STATISTICS_update (GSC_stats,
1449                               gettext_noop ("# rekey operations confirmed via PONG"),
1450                               1,
1451                               GNUNET_NO);
1452     kx->status = GNUNET_CORE_KX_STATE_UP;
1453     monitor_notify_all (kx);
1454     update_timeout (kx);
1455     break;
1456   default:
1457     GNUNET_break (0);
1458     break;
1459   }
1460 }
1461
1462
1463 /**
1464  * Send our key to the other peer.
1465  *
1466  * @param kx key exchange context
1467  */
1468 static void
1469 send_key (struct GSC_KeyExchangeInfo *kx)
1470 {
1471   struct GNUNET_MQ_Envelope *env;
1472
1473   GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
1474   if (NULL != kx->retry_set_key_task)
1475   {
1476      GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1477      kx->retry_set_key_task = NULL;
1478   }
1479   /* always update sender status in SET KEY message */
1480 #if DEBUG_KX
1481   {
1482     struct GNUNET_HashCode hc;
1483
1484     GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1485                         sizeof (current_ekm.ephemeral_key),
1486                         &hc);
1487     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1488                 "Sending EPHEMERAL_KEY %s to `%s' (my status: %d)\n",
1489                 GNUNET_h2s (&hc),
1490                 GNUNET_i2s (kx->peer),
1491                 kx->status);
1492   }
1493 #endif
1494   current_ekm.sender_status = htonl ((int32_t) (kx->status));
1495   env = GNUNET_MQ_msg_copy (&current_ekm.header);
1496   GNUNET_MQ_send (kx->mq,
1497                   env);
1498   if (GNUNET_CORE_KX_STATE_KEY_SENT != kx->status)
1499     send_ping (kx);
1500   kx->retry_set_key_task =
1501       GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
1502                                     &set_key_retry_task,
1503                                     kx);
1504 }
1505
1506
1507 /**
1508  * Encrypt and transmit a message with the given payload.
1509  *
1510  * @param kx key exchange context
1511  * @param payload payload of the message
1512  * @param payload_size number of bytes in @a payload
1513  */
1514 void
1515 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
1516                              const void *payload,
1517                              size_t payload_size)
1518 {
1519   size_t used = payload_size + sizeof (struct EncryptedMessage);
1520   char pbuf[used];              /* plaintext */
1521   struct EncryptedMessage *em;  /* encrypted message */
1522   struct EncryptedMessage *ph;  /* plaintext header */
1523   struct GNUNET_MQ_Envelope *env;
1524   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1525   struct GNUNET_CRYPTO_AuthKey auth_key;
1526
1527   ph = (struct EncryptedMessage *) pbuf;
1528   ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1529   ph->iv_seed = calculate_seed (kx);
1530   ph->reserved = 0;
1531   ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1532   GNUNET_memcpy (&ph[1],
1533                  payload,
1534                  payload_size);
1535   env = GNUNET_MQ_msg_extra (em,
1536                              payload_size,
1537                              GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
1538   em->iv_seed = ph->iv_seed;
1539   derive_iv (&iv,
1540              &kx->encrypt_key,
1541              ph->iv_seed,
1542              kx->peer);
1543   GNUNET_assert (GNUNET_OK ==
1544                  do_encrypt (kx,
1545                              &iv,
1546                              &ph->sequence_number,
1547                              &em->sequence_number,
1548                              used - ENCRYPTED_HEADER_SIZE));
1549 #if DEBUG_KX
1550   {
1551     struct GNUNET_HashCode hc;
1552
1553     GNUNET_CRYPTO_hash (&ph->sequence_number,
1554                         used - ENCRYPTED_HEADER_SIZE,
1555                         &hc);
1556     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1557                 "Encrypted payload `%s' of %u bytes for %s\n",
1558                 GNUNET_h2s (&hc),
1559                 (unsigned int) (used - ENCRYPTED_HEADER_SIZE),
1560                 GNUNET_i2s (kx->peer));
1561   }
1562 #endif
1563   derive_auth_key (&auth_key,
1564                    &kx->encrypt_key,
1565                    ph->iv_seed);
1566   GNUNET_CRYPTO_hmac (&auth_key,
1567                       &em->sequence_number,
1568                       used - ENCRYPTED_HEADER_SIZE,
1569                       &em->hmac);
1570 #if DEBUG_KX
1571   {
1572     struct GNUNET_HashCode hc;
1573
1574     GNUNET_CRYPTO_hash (&auth_key,
1575                         sizeof (auth_key),
1576                         &hc);
1577     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1578                 "For peer %s, used AC %s to create hmac %s\n",
1579                 GNUNET_i2s (kx->peer),
1580                 GNUNET_h2s (&hc),
1581                 GNUNET_h2s2 (&em->hmac));
1582   }
1583 #endif
1584   kx->has_excess_bandwidth = GNUNET_NO;
1585   GNUNET_MQ_send (kx->mq,
1586                   env);
1587 }
1588
1589
1590 /**
1591  * We received an encrypted message.  Check that it is
1592  * well-formed (size-wise).
1593  *
1594  * @param cls key exchange context for encrypting the message
1595  * @param m encrypted message
1596  * @return #GNUNET_OK if @a msg is well-formed (size-wise)
1597  */
1598 static int
1599 check_encrypted (void *cls,
1600                  const struct EncryptedMessage *m)
1601 {
1602   uint16_t size = ntohs (m->header.size) - sizeof (*m);
1603
1604   if (size < sizeof (struct GNUNET_MessageHeader))
1605   {
1606     GNUNET_break_op (0);
1607     return GNUNET_SYSERR;
1608   }
1609   return GNUNET_OK;
1610 }
1611
1612
1613 /**
1614  * We received an encrypted message.  Decrypt, validate and
1615  * pass on to the appropriate clients.
1616  *
1617  * @param cls key exchange context for encrypting the message
1618  * @param m encrypted message
1619  */
1620 static void
1621 handle_encrypted (void *cls,
1622                   const struct EncryptedMessage *m)
1623 {
1624   struct GSC_KeyExchangeInfo *kx = cls;
1625   struct EncryptedMessage *pt;  /* plaintext */
1626   struct GNUNET_HashCode ph;
1627   uint32_t snum;
1628   struct GNUNET_TIME_Absolute t;
1629   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1630   struct GNUNET_CRYPTO_AuthKey auth_key;
1631   uint16_t size = ntohs (m->header.size);
1632   char buf[size] GNUNET_ALIGN;
1633
1634   if (GNUNET_CORE_KX_STATE_UP != kx->status)
1635   {
1636     GNUNET_STATISTICS_update (GSC_stats,
1637                               gettext_noop ("# DATA message dropped (out of order)"),
1638                               1,
1639                               GNUNET_NO);
1640     return;
1641   }
1642   if (0 == GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value_us)
1643   {
1644     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1645                 _("Session to peer `%s' went down due to key expiration (should not happen)\n"),
1646                 GNUNET_i2s (kx->peer));
1647     GNUNET_STATISTICS_update (GSC_stats,
1648                               gettext_noop ("# sessions terminated by key expiration"),
1649                               1, GNUNET_NO);
1650     GSC_SESSIONS_end (kx->peer);
1651     if (NULL != kx->keep_alive_task)
1652     {
1653       GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1654       kx->keep_alive_task = NULL;
1655     }
1656     kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1657     monitor_notify_all (kx);
1658     send_key (kx);
1659     return;
1660   }
1661
1662   /* validate hash */
1663 #if DEBUG_KX
1664   {
1665     struct GNUNET_HashCode hc;
1666
1667     GNUNET_CRYPTO_hash (&m->sequence_number,
1668                         size - ENCRYPTED_HEADER_SIZE,
1669                         &hc);
1670     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1671                 "Received encrypted payload `%s' of %u bytes from %s\n",
1672                 GNUNET_h2s (&hc),
1673                 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1674                 GNUNET_i2s (kx->peer));
1675   }
1676 #endif
1677   derive_auth_key (&auth_key,
1678                    &kx->decrypt_key,
1679                    m->iv_seed);
1680   GNUNET_CRYPTO_hmac (&auth_key,
1681                       &m->sequence_number,
1682                       size - ENCRYPTED_HEADER_SIZE,
1683                       &ph);
1684 #if DEBUG_KX
1685   {
1686     struct GNUNET_HashCode hc;
1687
1688     GNUNET_CRYPTO_hash (&auth_key,
1689                         sizeof (auth_key),
1690                         &hc);
1691     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1692                 "For peer %s, used AC %s to verify hmac %s\n",
1693                 GNUNET_i2s (kx->peer),
1694                 GNUNET_h2s (&hc),
1695                 GNUNET_h2s2 (&m->hmac));
1696   }
1697 #endif
1698   if (0 != memcmp (&ph,
1699                    &m->hmac,
1700                    sizeof (struct GNUNET_HashCode)))
1701   {
1702     /* checksum failed */
1703     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1704                 "Failed checksum validation for a message from `%s'\n",
1705                 GNUNET_i2s (kx->peer));
1706     return;
1707   }
1708   derive_iv (&iv,
1709              &kx->decrypt_key,
1710              m->iv_seed,
1711              &GSC_my_identity);
1712   /* decrypt */
1713   if (GNUNET_OK !=
1714       do_decrypt (kx,
1715                   &iv,
1716                   &m->sequence_number,
1717                   &buf[ENCRYPTED_HEADER_SIZE],
1718                   size - ENCRYPTED_HEADER_SIZE))
1719   {
1720     GNUNET_break_op (0);
1721     return;
1722   }
1723   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1724               "Decrypted %u bytes from %s\n",
1725               (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1726               GNUNET_i2s (kx->peer));
1727   pt = (struct EncryptedMessage *) buf;
1728
1729   /* validate sequence number */
1730   snum = ntohl (pt->sequence_number);
1731   if (kx->last_sequence_number_received == snum)
1732   {
1733     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1734                 "Received duplicate message, ignoring.\n");
1735     /* duplicate, ignore */
1736     GNUNET_STATISTICS_update (GSC_stats,
1737                               gettext_noop ("# bytes dropped (duplicates)"),
1738                               size,
1739                               GNUNET_NO);
1740     return;
1741   }
1742   if ((kx->last_sequence_number_received > snum) &&
1743       (kx->last_sequence_number_received - snum > 32))
1744   {
1745     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1746                 "Received ancient out of sequence message, ignoring.\n");
1747     /* ancient out of sequence, ignore */
1748     GNUNET_STATISTICS_update (GSC_stats,
1749                               gettext_noop
1750                               ("# bytes dropped (out of sequence)"), size,
1751                               GNUNET_NO);
1752     return;
1753   }
1754   if (kx->last_sequence_number_received > snum)
1755   {
1756     uint32_t rotbit = 1U << (kx->last_sequence_number_received - snum - 1);
1757
1758     if ((kx->last_packets_bitmap & rotbit) != 0)
1759     {
1760       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1761                   "Received duplicate message, ignoring.\n");
1762       GNUNET_STATISTICS_update (GSC_stats,
1763                                 gettext_noop ("# bytes dropped (duplicates)"),
1764                                 size, GNUNET_NO);
1765       /* duplicate, ignore */
1766       return;
1767     }
1768     kx->last_packets_bitmap |= rotbit;
1769   }
1770   if (kx->last_sequence_number_received < snum)
1771   {
1772     unsigned int shift = (snum - kx->last_sequence_number_received);
1773
1774     if (shift >= 8 * sizeof (kx->last_packets_bitmap))
1775       kx->last_packets_bitmap = 0;
1776     else
1777       kx->last_packets_bitmap <<= shift;
1778     kx->last_sequence_number_received = snum;
1779   }
1780
1781   /* check timestamp */
1782   t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
1783   if (GNUNET_TIME_absolute_get_duration (t).rel_value_us >
1784       MAX_MESSAGE_AGE.rel_value_us)
1785   {
1786     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1787                 "Message received far too old (%s). Content ignored.\n",
1788                 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (t),
1789                                                         GNUNET_YES));
1790     GNUNET_STATISTICS_update (GSC_stats,
1791                               gettext_noop
1792                               ("# bytes dropped (ancient message)"), size,
1793                               GNUNET_NO);
1794     return;
1795   }
1796
1797   /* process decrypted message(s) */
1798   update_timeout (kx);
1799   GNUNET_STATISTICS_update (GSC_stats,
1800                             gettext_noop ("# bytes of payload decrypted"),
1801                             size - sizeof (struct EncryptedMessage),
1802                             GNUNET_NO);
1803   if (GNUNET_OK !=
1804       GNUNET_MST_from_buffer (kx->mst,
1805                               &buf[sizeof (struct EncryptedMessage)],
1806                               size - sizeof (struct EncryptedMessage),
1807                               GNUNET_YES,
1808                               GNUNET_NO))
1809     GNUNET_break_op (0);
1810 }
1811
1812
1813 /**
1814  * One of our neighbours has excess bandwidth, remember this.
1815  *
1816  * @param cls NULL
1817  * @param pid identity of the peer with excess bandwidth
1818  * @param connect_cls the `struct Neighbour`
1819  */
1820 static void
1821 handle_transport_notify_excess_bw (void *cls,
1822                                    const struct GNUNET_PeerIdentity *pid,
1823                                    void *connect_cls)
1824 {
1825   struct GSC_KeyExchangeInfo *kx = connect_cls;
1826
1827   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1828               "Peer %s has excess bandwidth available\n",
1829               GNUNET_i2s (pid));
1830   kx->has_excess_bandwidth = GNUNET_YES;
1831   GSC_SESSIONS_solicit (pid);
1832 }
1833
1834
1835 /**
1836  * Setup the message that links the ephemeral key to our persistent
1837  * public key and generate the appropriate signature.
1838  */
1839 static void
1840 sign_ephemeral_key ()
1841 {
1842   current_ekm.header.size = htons (sizeof (struct EphemeralKeyMessage));
1843   current_ekm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY);
1844   current_ekm.sender_status = 0; /* to be set later */
1845   current_ekm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY);
1846   current_ekm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
1847                                     sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1848                                     sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1849                                     sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
1850                                     sizeof (struct GNUNET_PeerIdentity));
1851   current_ekm.creation_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1852   if (GNUNET_YES ==
1853       GNUNET_CONFIGURATION_get_value_yesno (GSC_cfg,
1854                                             "core",
1855                                             "USE_EPHEMERAL_KEYS"))
1856   {
1857     current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_add (REKEY_FREQUENCY,
1858                                                                                                                          REKEY_TOLERANCE)));
1859   }
1860   else
1861   {
1862     current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1863   }
1864   GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key,
1865                                       &current_ekm.ephemeral_key);
1866   current_ekm.origin_identity = GSC_my_identity;
1867   GNUNET_assert (GNUNET_OK ==
1868                  GNUNET_CRYPTO_eddsa_sign (my_private_key,
1869                                            &current_ekm.purpose,
1870                                            &current_ekm.signature));
1871 }
1872
1873
1874 /**
1875  * Task run to trigger rekeying.
1876  *
1877  * @param cls closure, NULL
1878  */
1879 static void
1880 do_rekey (void *cls)
1881 {
1882   struct GSC_KeyExchangeInfo *pos;
1883
1884   rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY,
1885                                              &do_rekey,
1886                                              NULL);
1887   if (NULL != my_ephemeral_key)
1888     GNUNET_free (my_ephemeral_key);
1889   my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
1890   GNUNET_assert (NULL != my_ephemeral_key);
1891   sign_ephemeral_key ();
1892   {
1893     struct GNUNET_HashCode eh;
1894
1895     GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1896                         sizeof (current_ekm.ephemeral_key),
1897                         &eh);
1898     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1899                 "Rekeying to %s\n",
1900                 GNUNET_h2s (&eh));
1901   }
1902   for (pos = kx_head; NULL != pos; pos = pos->next)
1903   {
1904     if (GNUNET_CORE_KX_STATE_UP == pos->status)
1905     {
1906       pos->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1907       monitor_notify_all (pos);
1908       derive_session_keys (pos);
1909     }
1910     if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
1911     {
1912       pos->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1913       monitor_notify_all (pos);
1914     }
1915     monitor_notify_all (pos);
1916     send_key (pos);
1917   }
1918 }
1919
1920
1921 /**
1922  * Initialize KX subsystem.
1923  *
1924  * @param pk private key to use for the peer
1925  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1926  */
1927 int
1928 GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
1929 {
1930   struct GNUNET_MQ_MessageHandler handlers[] = {
1931     GNUNET_MQ_hd_fixed_size (ephemeral_key,
1932                              GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
1933                              struct EphemeralKeyMessage,
1934                              NULL),
1935     GNUNET_MQ_hd_fixed_size (ping,
1936                              GNUNET_MESSAGE_TYPE_CORE_PING,
1937                              struct PingMessage,
1938                              NULL),
1939     GNUNET_MQ_hd_fixed_size (pong,
1940                              GNUNET_MESSAGE_TYPE_CORE_PONG,
1941                              struct PongMessage,
1942                              NULL),
1943     GNUNET_MQ_hd_var_size (encrypted,
1944                            GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE,
1945                            struct EncryptedMessage,
1946                            NULL),
1947     GNUNET_MQ_handler_end()
1948   };
1949
1950   my_private_key = pk;
1951   GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1952                                       &GSC_my_identity.public_key);
1953   my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
1954   if (NULL == my_ephemeral_key)
1955   {
1956     GNUNET_break (0);
1957     GNUNET_free (my_private_key);
1958     my_private_key = NULL;
1959     return GNUNET_SYSERR;
1960   }
1961   sign_ephemeral_key ();
1962   {
1963     struct GNUNET_HashCode eh;
1964
1965     GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1966                         sizeof (current_ekm.ephemeral_key),
1967                         &eh);
1968     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1969                 "Starting with ephemeral key %s\n",
1970                 GNUNET_h2s (&eh));
1971   }
1972
1973   nc = GNUNET_notification_context_create (1);
1974   rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY,
1975                                              &do_rekey,
1976                                              NULL);
1977   transport
1978     = GNUNET_TRANSPORT_core_connect (GSC_cfg,
1979                                      &GSC_my_identity,
1980                                      handlers,
1981                                      NULL,
1982                                      &handle_transport_notify_connect,
1983                                      &handle_transport_notify_disconnect,
1984                                      &handle_transport_notify_excess_bw);
1985   if (NULL == transport)
1986   {
1987     GSC_KX_done ();
1988     return GNUNET_SYSERR;
1989   }
1990   return GNUNET_OK;
1991 }
1992
1993
1994 /**
1995  * Shutdown KX subsystem.
1996  */
1997 void
1998 GSC_KX_done ()
1999 {
2000   if (NULL != transport)
2001   {
2002     GNUNET_TRANSPORT_core_disconnect (transport);
2003     transport = NULL;
2004   }
2005   if (NULL != rekey_task)
2006   {
2007     GNUNET_SCHEDULER_cancel (rekey_task);
2008     rekey_task = NULL;
2009   }
2010   if (NULL != my_ephemeral_key)
2011   {
2012     GNUNET_free (my_ephemeral_key);
2013     my_ephemeral_key = NULL;
2014   }
2015   if (NULL != my_private_key)
2016   {
2017     GNUNET_free (my_private_key);
2018     my_private_key = NULL;
2019   }
2020   if (NULL != nc)
2021   {
2022     GNUNET_notification_context_destroy (nc);
2023     nc = NULL;
2024   }
2025 }
2026
2027
2028  /**
2029  * Check how many messages are queued for the given neighbour.
2030  *
2031  * @param kxinfo data about neighbour to check
2032  * @return number of items in the message queue
2033  */
2034 unsigned int
2035 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
2036 {
2037   return GNUNET_MQ_get_length (kxinfo->mq);
2038 }
2039
2040
2041 /**
2042  * Check if the given neighbour has excess bandwidth available.
2043  *
2044  * @param target neighbour to check
2045  * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
2046  */
2047 int
2048 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
2049 {
2050   return kxinfo->has_excess_bandwidth;
2051 }
2052
2053
2054 /**
2055  * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.  For this
2056  * request type, the client does not have to have transmitted an INIT
2057  * request.  All current peers are returned, regardless of which
2058  * message types they accept.
2059  *
2060  * @param mq message queue to add for monitoring
2061  */
2062 void
2063 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
2064 {
2065   struct GNUNET_MQ_Envelope *env;
2066   struct MonitorNotifyMessage *done_msg;
2067   struct GSC_KeyExchangeInfo *kx;
2068
2069   GNUNET_notification_context_add (nc,
2070                                    mq);
2071   for (kx = kx_head; NULL != kx; kx = kx->next)
2072   {
2073     struct GNUNET_MQ_Envelope *env;
2074     struct MonitorNotifyMessage *msg;
2075
2076     env = GNUNET_MQ_msg (msg,
2077                          GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
2078     msg->state = htonl ((uint32_t) kx->status);
2079     msg->peer = *kx->peer;
2080     msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
2081     GNUNET_MQ_send (mq,
2082                     env);
2083   }
2084   env = GNUNET_MQ_msg (done_msg,
2085                        GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
2086   done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
2087   done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
2088   GNUNET_MQ_send (mq,
2089                   env);
2090 }
2091
2092
2093 /* end of gnunet-service-core_kx.c */