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