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