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