removing dead/legacy server/connection logic, except for in tcp/wlan/bt plugins ...
[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  */
712 static int
713 deliver_message (void *cls,
714                  const struct GNUNET_MessageHeader *m)
715 {
716   struct GSC_KeyExchangeInfo *kx = cls;
717
718   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
719               "Decrypted message of type %d from %s\n",
720               ntohs (m->type),
721               GNUNET_i2s (kx->peer));
722   if (GNUNET_CORE_KX_STATE_UP != kx->status)
723   {
724     GNUNET_STATISTICS_update (GSC_stats,
725                               gettext_noop ("# PAYLOAD dropped (out of order)"),
726                               1,
727                               GNUNET_NO);
728     return GNUNET_OK;
729   }
730   switch (ntohs (m->type))
731   {
732   case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
733   case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
734     GSC_SESSIONS_set_typemap (kx->peer, m);
735     return GNUNET_OK;
736   case GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP:
737     GSC_SESSIONS_confirm_typemap (kx->peer, m);
738     return GNUNET_OK;
739   default:
740     GSC_CLIENTS_deliver_message (kx->peer,
741                                  m,
742                                  ntohs (m->size),
743                                  GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
744     GSC_CLIENTS_deliver_message (kx->peer,
745                                  m,
746                                  sizeof (struct GNUNET_MessageHeader),
747                                  GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
748   }
749   return GNUNET_OK;
750 }
751
752
753 /**
754  * Function called by transport to notify us that
755  * a peer connected to us (on the network level).
756  * Starts the key exchange with the given peer.
757  *
758  * @param cls closure (NULL)
759  * @param pid identity of the peer to do a key exchange with
760  * @return key exchange information context
761  */
762 static void *
763 handle_transport_notify_connect (void *cls,
764                                  const struct GNUNET_PeerIdentity *pid,
765                                  struct GNUNET_MQ_Handle *mq)
766 {
767   struct GSC_KeyExchangeInfo *kx;
768   struct GNUNET_HashCode h1;
769   struct GNUNET_HashCode h2;
770
771   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
772               "Initiating key exchange with `%s'\n",
773               GNUNET_i2s (pid));
774   GNUNET_STATISTICS_update (GSC_stats,
775                             gettext_noop ("# key exchanges initiated"),
776                             1,
777                             GNUNET_NO);
778   kx = GNUNET_new (struct GSC_KeyExchangeInfo);
779   kx->mst = GNUNET_MST_create (&deliver_message,
780                                kx);
781   kx->mq = mq;
782   kx->peer = pid;
783   kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
784   GNUNET_CONTAINER_DLL_insert (kx_head,
785                                kx_tail,
786                                kx);
787   kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
788   monitor_notify_all (kx);
789   GNUNET_CRYPTO_hash (pid,
790                       sizeof (struct GNUNET_PeerIdentity),
791                       &h1);
792   GNUNET_CRYPTO_hash (&GSC_my_identity,
793                       sizeof (struct GNUNET_PeerIdentity),
794                       &h2);
795   if (0 < GNUNET_CRYPTO_hash_cmp (&h1,
796                                   &h2))
797   {
798     /* peer with "lower" identity starts KX, otherwise we typically end up
799        with both peers starting the exchange and transmit the 'set key'
800        message twice */
801     send_key (kx);
802   }
803   else
804   {
805     /* peer with "higher" identity starts a delayed  KX, if the "lower" peer
806      * does not start a KX since he sees no reasons to do so  */
807     kx->retry_set_key_task
808       = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
809                                       &set_key_retry_task,
810                                       kx);
811   }
812   return kx;
813 }
814
815
816 /**
817  * Function called by transport telling us that a peer
818  * disconnected.
819  * Stop key exchange with the given peer.  Clean up key material.
820  *
821  * @param cls closure
822  * @param peer the peer that disconnected
823  * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
824  */
825 static void
826 handle_transport_notify_disconnect (void *cls,
827                                     const struct GNUNET_PeerIdentity *peer,
828                                     void *handler_cls)
829 {
830   struct GSC_KeyExchangeInfo *kx = handler_cls;
831
832   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
833               "Peer `%s' disconnected from us.\n",
834               GNUNET_i2s (peer));
835   GSC_SESSIONS_end (kx->peer);
836   GNUNET_STATISTICS_update (GSC_stats,
837                             gettext_noop ("# key exchanges stopped"),
838                             1,
839                             GNUNET_NO);
840   if (NULL != kx->retry_set_key_task)
841   {
842     GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
843     kx->retry_set_key_task = NULL;
844   }
845   if (NULL != kx->keep_alive_task)
846   {
847     GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
848     kx->keep_alive_task = NULL;
849   }
850   kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
851   monitor_notify_all (kx);
852   GNUNET_CONTAINER_DLL_remove (kx_head,
853                                kx_tail,
854                                kx);
855   GNUNET_MST_destroy (kx->mst);
856   GNUNET_free (kx);
857 }
858
859
860 /**
861  * Send our PING to the other peer.
862  *
863  * @param kx key exchange context
864  */
865 static void
866 send_ping (struct GSC_KeyExchangeInfo *kx)
867 {
868   struct GNUNET_MQ_Envelope *env;
869
870   GNUNET_STATISTICS_update (GSC_stats,
871                             gettext_noop ("# PING messages transmitted"),
872                             1,
873                             GNUNET_NO);
874   env = GNUNET_MQ_msg_copy (&kx->ping.header);
875   GNUNET_MQ_send (kx->mq,
876                   env);
877 }
878
879
880 /**
881  * Derive fresh session keys from the current ephemeral keys.
882  *
883  * @param kx session to derive keys for
884  */
885 static void
886 derive_session_keys (struct GSC_KeyExchangeInfo *kx)
887 {
888   struct GNUNET_HashCode key_material;
889
890   if (GNUNET_OK !=
891       GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key,
892                               &kx->other_ephemeral_key,
893                               &key_material))
894   {
895     GNUNET_break (0);
896     return;
897   }
898   derive_aes_key (&GSC_my_identity,
899                   kx->peer,
900                   &key_material,
901                   &kx->encrypt_key);
902   derive_aes_key (kx->peer,
903                   &GSC_my_identity,
904                   &key_material,
905                   &kx->decrypt_key);
906   memset (&key_material, 0, sizeof (key_material));
907   /* fresh key, reset sequence numbers */
908   kx->last_sequence_number_received = 0;
909   kx->last_packets_bitmap = 0;
910   setup_fresh_ping (kx);
911 }
912
913
914 /**
915  * We received a #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY message.
916  * Validate and update our key material and status.
917  *
918  * @param cls key exchange status for the corresponding peer
919  * @param m the set key message we received
920  */
921 static void
922 handle_ephemeral_key (void *cls,
923                       const struct EphemeralKeyMessage *m)
924 {
925   struct GSC_KeyExchangeInfo *kx = cls;
926   struct GNUNET_TIME_Absolute start_t;
927   struct GNUNET_TIME_Absolute end_t;
928   struct GNUNET_TIME_Absolute now;
929   enum GNUNET_CORE_KxState sender_status;
930
931   end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
932   if ( ( (GNUNET_CORE_KX_STATE_KEY_RECEIVED == kx->status) ||
933          (GNUNET_CORE_KX_STATE_UP == kx->status) ||
934          (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status) ) &&
935        (end_t.abs_value_us < kx->foreign_key_expires.abs_value_us) )
936   {
937     GNUNET_STATISTICS_update (GSC_stats,
938                               gettext_noop ("# old ephemeral keys ignored"),
939                               1, GNUNET_NO);
940     return;
941   }
942   start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
943
944   GNUNET_STATISTICS_update (GSC_stats,
945                             gettext_noop ("# ephemeral keys received"),
946                             1, GNUNET_NO);
947
948   if (0 !=
949       memcmp (&m->origin_identity,
950               kx->peer,
951               sizeof (struct GNUNET_PeerIdentity)))
952   {
953     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
954                 "Received EPHEMERAL_KEY from %s, but expected %s\n",
955                 GNUNET_i2s (&m->origin_identity),
956                 GNUNET_i2s_full (kx->peer));
957     GNUNET_break_op (0);
958     return;
959   }
960   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
961               "Core service receives EPHEMERAL_KEY request from `%s'.\n",
962               GNUNET_i2s (kx->peer));
963   if ((ntohl (m->purpose.size) !=
964        sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
965        sizeof (struct GNUNET_TIME_AbsoluteNBO) +
966        sizeof (struct GNUNET_TIME_AbsoluteNBO) +
967        sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) +
968        sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) ||
969       (GNUNET_OK !=
970        GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY,
971                                    &m->purpose,
972                                    &m->signature,
973                                    &m->origin_identity.public_key)))
974   {
975     /* invalid signature */
976     GNUNET_break_op (0);
977     return;
978   }
979   now = GNUNET_TIME_absolute_get ();
980   if ( (end_t.abs_value_us < GNUNET_TIME_absolute_subtract (now, REKEY_TOLERANCE).abs_value_us) ||
981        (start_t.abs_value_us > GNUNET_TIME_absolute_add (now, REKEY_TOLERANCE).abs_value_us) )
982   {
983     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
984                 _("Ephemeral key message from peer `%s' rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"),
985                 GNUNET_i2s (kx->peer),
986                 (unsigned long long) now.abs_value_us,
987                 (unsigned long long) start_t.abs_value_us,
988                 (unsigned long long) end_t.abs_value_us);
989     return;
990   }
991   kx->other_ephemeral_key = m->ephemeral_key;
992   kx->foreign_key_expires = end_t;
993   derive_session_keys (kx);
994   GNUNET_STATISTICS_update (GSC_stats,
995                             gettext_noop ("# EPHEMERAL_KEY messages received"), 1,
996                             GNUNET_NO);
997
998   /* check if we still need to send the sender our key */
999   sender_status = (enum GNUNET_CORE_KxState) ntohl (m->sender_status);
1000   switch (sender_status)
1001   {
1002   case GNUNET_CORE_KX_STATE_DOWN:
1003     GNUNET_break_op (0);
1004     break;
1005   case GNUNET_CORE_KX_STATE_KEY_SENT:
1006     /* fine, need to send our key after updating our status, see below */
1007     GSC_SESSIONS_reinit (kx->peer);
1008     break;
1009   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1010     /* other peer already got our key, but typemap did go down */
1011     GSC_SESSIONS_reinit (kx->peer);
1012     break;
1013   case GNUNET_CORE_KX_STATE_UP:
1014     /* other peer already got our key, typemap NOT down */
1015     break;
1016   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1017     /* other peer already got our key, typemap NOT down */
1018     break;
1019   default:
1020     GNUNET_break (0);
1021     break;
1022   }
1023   /* check if we need to confirm everything is fine via PING + PONG */
1024   switch (kx->status)
1025   {
1026   case GNUNET_CORE_KX_STATE_DOWN:
1027     GNUNET_assert (NULL == kx->keep_alive_task);
1028     kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1029     monitor_notify_all (kx);
1030     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1031       send_key (kx);
1032     else
1033       send_ping (kx);
1034     break;
1035   case GNUNET_CORE_KX_STATE_KEY_SENT:
1036     GNUNET_assert (NULL == kx->keep_alive_task);
1037     kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1038     monitor_notify_all (kx);
1039     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1040       send_key (kx);
1041     else
1042       send_ping (kx);
1043     break;
1044   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1045     GNUNET_assert (NULL == kx->keep_alive_task);
1046     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1047       send_key (kx);
1048     else
1049       send_ping (kx);
1050     break;
1051   case GNUNET_CORE_KX_STATE_UP:
1052     kx->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1053     monitor_notify_all (kx);
1054     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1055       send_key (kx);
1056     else
1057       send_ping (kx);
1058     break;
1059   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1060     if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1061       send_key (kx);
1062     else
1063       send_ping (kx);
1064     break;
1065   default:
1066     GNUNET_break (0);
1067     break;
1068   }
1069 }
1070
1071
1072 /**
1073  * We received a PING message.  Validate and transmit
1074  * a PONG message.
1075  *
1076  * @param cls key exchange status for the corresponding peer
1077  * @param m the encrypted PING message itself
1078  */
1079 static void
1080 handle_ping (void *cls,
1081              const struct PingMessage *m)
1082 {
1083   struct GSC_KeyExchangeInfo *kx = cls;
1084   struct PingMessage t;
1085   struct PongMessage tx;
1086   struct PongMessage *tp;
1087   struct GNUNET_MQ_Envelope *env;
1088   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1089
1090   GNUNET_STATISTICS_update (GSC_stats,
1091                             gettext_noop ("# PING messages received"),
1092                             1,
1093                             GNUNET_NO);
1094   if ( (kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
1095        (kx->status != GNUNET_CORE_KX_STATE_UP) &&
1096        (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
1097   {
1098     /* ignore */
1099     GNUNET_STATISTICS_update (GSC_stats,
1100                               gettext_noop ("# PING messages dropped (out of order)"),
1101                               1,
1102                               GNUNET_NO);
1103     return;
1104   }
1105   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1106               "Core service receives PING request from `%s'.\n",
1107               GNUNET_i2s (kx->peer));
1108   derive_iv (&iv,
1109              &kx->decrypt_key,
1110              m->iv_seed,
1111              &GSC_my_identity);
1112   if (GNUNET_OK !=
1113       do_decrypt (kx,
1114                   &iv,
1115                   &m->target,
1116                   &t.target,
1117                   sizeof (struct PingMessage) - ((void *) &m->target -
1118                                                  (void *) m)))
1119   {
1120     GNUNET_break_op (0);
1121     return;
1122   }
1123   if (0 !=
1124       memcmp (&t.target,
1125               &GSC_my_identity,
1126               sizeof (struct GNUNET_PeerIdentity)))
1127   {
1128     if (GNUNET_CORE_KX_STATE_REKEY_SENT != kx->status)
1129       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1130                   "Decryption of PING from peer `%s' failed\n",
1131                   GNUNET_i2s (kx->peer));
1132     else
1133       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1134                   "Decryption of PING from peer `%s' failed after rekey (harmless)\n",
1135                   GNUNET_i2s (kx->peer));
1136     GNUNET_break_op (0);
1137     return;
1138   }
1139   /* construct PONG */
1140   tx.reserved = 0;
1141   tx.challenge = t.challenge;
1142   tx.target = t.target;
1143   env = GNUNET_MQ_msg (tp,
1144                        GNUNET_MESSAGE_TYPE_CORE_PONG);
1145   tp->iv_seed = calculate_seed (kx);
1146   derive_pong_iv (&iv,
1147                   &kx->encrypt_key,
1148                   tp->iv_seed,
1149                   t.challenge,
1150                   kx->peer);
1151   do_encrypt (kx,
1152               &iv,
1153               &tx.challenge,
1154               &tp->challenge,
1155               sizeof (struct PongMessage) - ((void *) &tp->challenge -
1156                                              (void *) tp));
1157   GNUNET_STATISTICS_update (GSC_stats,
1158                             gettext_noop ("# PONG messages created"),
1159                             1,
1160                             GNUNET_NO);
1161   GNUNET_MQ_send (kx->mq,
1162                   env);
1163 }
1164
1165
1166 /**
1167  * Task triggered when a neighbour entry is about to time out
1168  * (and we should prevent this by sending a PING).
1169  *
1170  * @param cls the `struct GSC_KeyExchangeInfo`
1171  */
1172 static void
1173 send_keep_alive (void *cls)
1174 {
1175   struct GSC_KeyExchangeInfo *kx = cls;
1176   struct GNUNET_TIME_Relative retry;
1177   struct GNUNET_TIME_Relative left;
1178
1179   kx->keep_alive_task = NULL;
1180   left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
1181   if (0 == left.rel_value_us)
1182   {
1183     GNUNET_STATISTICS_update (GSC_stats,
1184                               gettext_noop ("# sessions terminated by timeout"),
1185                               1,
1186                               GNUNET_NO);
1187     GSC_SESSIONS_end (kx->peer);
1188     kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1189     monitor_notify_all (kx);
1190     send_key (kx);
1191     return;
1192   }
1193   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1194               "Sending KEEPALIVE to `%s'\n",
1195               GNUNET_i2s (kx->peer));
1196   GNUNET_STATISTICS_update (GSC_stats,
1197                             gettext_noop ("# keepalive messages sent"),
1198                             1,
1199                             GNUNET_NO);
1200   setup_fresh_ping (kx);
1201   send_ping (kx);
1202   retry =
1203       GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1204                                 MIN_PING_FREQUENCY);
1205   kx->keep_alive_task =
1206       GNUNET_SCHEDULER_add_delayed (retry,
1207                                     &send_keep_alive,
1208                                     kx);
1209 }
1210
1211
1212 /**
1213  * We've seen a valid message from the other peer.
1214  * Update the time when the session would time out
1215  * and delay sending our keep alive message further.
1216  *
1217  * @param kx key exchange where we saw activity
1218  */
1219 static void
1220 update_timeout (struct GSC_KeyExchangeInfo *kx)
1221 {
1222   struct GNUNET_TIME_Relative delta;
1223
1224   kx->timeout =
1225       GNUNET_TIME_relative_to_absolute
1226       (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1227   delta = GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout,
1228                                                kx->timeout);
1229   if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
1230   {
1231     /* we only notify monitors about timeout changes if those
1232        are bigger than the threshold (5s) */
1233     monitor_notify_all (kx);
1234   }
1235   if (NULL != kx->keep_alive_task)
1236     GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1237   kx->keep_alive_task =
1238       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
1239                                     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1240                                      2),
1241                                     &send_keep_alive,
1242                                     kx);
1243 }
1244
1245
1246 /**
1247  * We received a PONG message.  Validate and update our status.
1248  *
1249  * @param kx key exchange context for the the PONG
1250  * @param m the encrypted PONG message itself
1251  */
1252 static void
1253 handle_pong (void *cls,
1254              const struct PongMessage *m)
1255 {
1256   struct GSC_KeyExchangeInfo *kx = cls;
1257   struct PongMessage t;
1258   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1259
1260   GNUNET_STATISTICS_update (GSC_stats,
1261                             gettext_noop ("# PONG messages received"),
1262                             1,
1263                             GNUNET_NO);
1264   switch (kx->status)
1265   {
1266   case GNUNET_CORE_KX_STATE_DOWN:
1267     GNUNET_STATISTICS_update (GSC_stats,
1268                               gettext_noop ("# PONG messages dropped (connection down)"), 1,
1269                               GNUNET_NO);
1270     return;
1271   case GNUNET_CORE_KX_STATE_KEY_SENT:
1272     GNUNET_STATISTICS_update (GSC_stats,
1273                               gettext_noop ("# PONG messages dropped (out of order)"), 1,
1274                               GNUNET_NO);
1275     return;
1276   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1277     break;
1278   case GNUNET_CORE_KX_STATE_UP:
1279     break;
1280   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1281     break;
1282   default:
1283     GNUNET_break (0);
1284     return;
1285   }
1286   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1287               "Core service receives PONG response from `%s'.\n",
1288               GNUNET_i2s (kx->peer));
1289   /* mark as garbage, just to be sure */
1290   memset (&t, 255, sizeof (t));
1291   derive_pong_iv (&iv,
1292                   &kx->decrypt_key,
1293                   m->iv_seed,
1294                   kx->ping_challenge,
1295                   &GSC_my_identity);
1296   if (GNUNET_OK !=
1297       do_decrypt (kx,
1298                   &iv,
1299                   &m->challenge,
1300                   &t.challenge,
1301                   sizeof (struct PongMessage) - ((void *) &m->challenge -
1302                                                  (void *) m)))
1303   {
1304     GNUNET_break_op (0);
1305     return;
1306   }
1307   GNUNET_STATISTICS_update (GSC_stats,
1308                             gettext_noop ("# PONG messages decrypted"),
1309                             1,
1310                             GNUNET_NO);
1311   if ((0 != memcmp (&t.target,
1312                     kx->peer,
1313                     sizeof (struct GNUNET_PeerIdentity))) ||
1314       (kx->ping_challenge != t.challenge))
1315   {
1316     /* PONG malformed */
1317     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1318                 "Received malformed PONG wanted sender `%s' with challenge %u\n",
1319                 GNUNET_i2s (kx->peer),
1320                 (unsigned int) kx->ping_challenge);
1321     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1322                 "Received malformed PONG received from `%s' with challenge %u\n",
1323                 GNUNET_i2s (&t.target),
1324                 (unsigned int) t.challenge);
1325     return;
1326   }
1327   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1328               "Received PONG from `%s'\n",
1329               GNUNET_i2s (kx->peer));
1330   /* no need to resend key any longer */
1331   if (NULL != kx->retry_set_key_task)
1332   {
1333     GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1334     kx->retry_set_key_task = NULL;
1335   }
1336   switch (kx->status)
1337   {
1338   case GNUNET_CORE_KX_STATE_DOWN:
1339     GNUNET_assert (0);           /* should be impossible */
1340     return;
1341   case GNUNET_CORE_KX_STATE_KEY_SENT:
1342     GNUNET_assert (0);           /* should be impossible */
1343     return;
1344   case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1345     GNUNET_STATISTICS_update (GSC_stats,
1346                               gettext_noop ("# session keys confirmed via PONG"),
1347                               1,
1348                               GNUNET_NO);
1349     kx->status = GNUNET_CORE_KX_STATE_UP;
1350     monitor_notify_all (kx);
1351     GSC_SESSIONS_create (kx->peer, kx);
1352     GNUNET_assert (NULL == kx->keep_alive_task);
1353     update_timeout (kx);
1354     break;
1355   case GNUNET_CORE_KX_STATE_UP:
1356     GNUNET_STATISTICS_update (GSC_stats,
1357                               gettext_noop ("# timeouts prevented via PONG"),
1358                               1,
1359                               GNUNET_NO);
1360     update_timeout (kx);
1361     break;
1362   case GNUNET_CORE_KX_STATE_REKEY_SENT:
1363     GNUNET_STATISTICS_update (GSC_stats,
1364                               gettext_noop ("# rekey operations confirmed via PONG"),
1365                               1,
1366                               GNUNET_NO);
1367     kx->status = GNUNET_CORE_KX_STATE_UP;
1368     monitor_notify_all (kx);
1369     update_timeout (kx);
1370     break;
1371   default:
1372     GNUNET_break (0);
1373     break;
1374   }
1375 }
1376
1377
1378 /**
1379  * Send our key to the other peer.
1380  *
1381  * @param kx key exchange context
1382  */
1383 static void
1384 send_key (struct GSC_KeyExchangeInfo *kx)
1385 {
1386   struct GNUNET_MQ_Envelope *env;
1387
1388   GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
1389   if (NULL != kx->retry_set_key_task)
1390   {
1391      GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1392      kx->retry_set_key_task = NULL;
1393   }
1394   /* always update sender status in SET KEY message */
1395   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1396               "Sending key to `%s' (my status: %d)\n",
1397               GNUNET_i2s (kx->peer),
1398               kx->status);
1399   current_ekm.sender_status = htonl ((int32_t) (kx->status));
1400   env = GNUNET_MQ_msg_copy (&current_ekm.header);
1401   GNUNET_MQ_send (kx->mq,
1402                   env);
1403   if (GNUNET_CORE_KX_STATE_KEY_SENT != kx->status)
1404     send_ping (kx);
1405   kx->retry_set_key_task =
1406       GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
1407                                     &set_key_retry_task,
1408                                     kx);
1409 }
1410
1411
1412 /**
1413  * Encrypt and transmit a message with the given payload.
1414  *
1415  * @param kx key exchange context
1416  * @param payload payload of the message
1417  * @param payload_size number of bytes in @a payload
1418  */
1419 void
1420 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
1421                              const void *payload,
1422                              size_t payload_size)
1423 {
1424   size_t used = payload_size + sizeof (struct EncryptedMessage);
1425   char pbuf[used];              /* plaintext */
1426   struct EncryptedMessage *em;  /* encrypted message */
1427   struct EncryptedMessage *ph;  /* plaintext header */
1428   struct GNUNET_MQ_Envelope *env;
1429   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1430   struct GNUNET_CRYPTO_AuthKey auth_key;
1431
1432   ph = (struct EncryptedMessage *) pbuf;
1433   ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1434   ph->iv_seed = calculate_seed (kx);
1435   ph->reserved = 0;
1436   ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1437   GNUNET_memcpy (&ph[1],
1438                  payload,
1439                  payload_size);
1440   env = GNUNET_MQ_msg_extra (em,
1441                              payload_size,
1442                              GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
1443   em->iv_seed = ph->iv_seed;
1444   derive_iv (&iv,
1445              &kx->encrypt_key,
1446              ph->iv_seed,
1447              kx->peer);
1448   GNUNET_assert (GNUNET_OK ==
1449                  do_encrypt (kx,
1450                              &iv,
1451                              &ph->sequence_number,
1452                              &em->sequence_number,
1453                              used - ENCRYPTED_HEADER_SIZE));
1454   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1455               "Encrypted %u bytes for %s\n",
1456               (unsigned int) (used - ENCRYPTED_HEADER_SIZE),
1457               GNUNET_i2s (kx->peer));
1458   derive_auth_key (&auth_key,
1459                    &kx->encrypt_key,
1460                    ph->iv_seed);
1461   GNUNET_CRYPTO_hmac (&auth_key,
1462                       &em->sequence_number,
1463                       used - ENCRYPTED_HEADER_SIZE,
1464                       &em->hmac);
1465   kx->has_excess_bandwidth = GNUNET_NO;
1466   GNUNET_MQ_send (kx->mq,
1467                   env);
1468 }
1469
1470
1471 /**
1472  * We received an encrypted message.  Check that it is
1473  * well-formed (size-wise).
1474  *
1475  * @param cls key exchange context for encrypting the message
1476  * @param m encrypted message
1477  * @return #GNUNET_OK if @a msg is well-formed (size-wise)
1478  */
1479 static int
1480 check_encrypted (void *cls,
1481                  const struct EncryptedMessage *m)
1482 {
1483   uint16_t size = ntohs (m->header.size) - sizeof (*m);
1484
1485   if (size < sizeof (struct GNUNET_MessageHeader))
1486   {
1487     GNUNET_break_op (0);
1488     return GNUNET_SYSERR;
1489   }
1490   return GNUNET_OK;
1491 }
1492
1493
1494 /**
1495  * We received an encrypted message.  Decrypt, validate and
1496  * pass on to the appropriate clients.
1497  *
1498  * @param cls key exchange context for encrypting the message
1499  * @param m encrypted message
1500  */
1501 static void
1502 handle_encrypted (void *cls,
1503                   const struct EncryptedMessage *m)
1504 {
1505   struct GSC_KeyExchangeInfo *kx = cls;
1506   struct EncryptedMessage *pt;  /* plaintext */
1507   struct GNUNET_HashCode ph;
1508   uint32_t snum;
1509   struct GNUNET_TIME_Absolute t;
1510   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1511   struct GNUNET_CRYPTO_AuthKey auth_key;
1512   uint16_t size = ntohs (m->header.size);
1513   char buf[size] GNUNET_ALIGN;
1514
1515   if (GNUNET_CORE_KX_STATE_UP != kx->status)
1516   {
1517     GNUNET_STATISTICS_update (GSC_stats,
1518                               gettext_noop ("# DATA message dropped (out of order)"),
1519                               1,
1520                               GNUNET_NO);
1521     return;
1522   }
1523   if (0 == GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value_us)
1524   {
1525     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1526                 _("Session to peer `%s' went down due to key expiration (should not happen)\n"),
1527                 GNUNET_i2s (kx->peer));
1528     GNUNET_STATISTICS_update (GSC_stats,
1529                               gettext_noop ("# sessions terminated by key expiration"),
1530                               1, GNUNET_NO);
1531     GSC_SESSIONS_end (kx->peer);
1532     if (NULL != kx->keep_alive_task)
1533     {
1534       GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1535       kx->keep_alive_task = NULL;
1536     }
1537     kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1538     monitor_notify_all (kx);
1539     send_key (kx);
1540     return;
1541   }
1542
1543   /* validate hash */
1544   derive_auth_key (&auth_key,
1545                    &kx->decrypt_key,
1546                    m->iv_seed);
1547   GNUNET_CRYPTO_hmac (&auth_key,
1548                       &m->sequence_number,
1549                       size - ENCRYPTED_HEADER_SIZE,
1550                       &ph);
1551   if (0 != memcmp (&ph,
1552                    &m->hmac,
1553                    sizeof (struct GNUNET_HashCode)))
1554   {
1555     /* checksum failed */
1556     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1557                 "Failed checksum validation for a message from `%s'\n",
1558                 GNUNET_i2s (kx->peer));
1559     return;
1560   }
1561   derive_iv (&iv,
1562              &kx->decrypt_key,
1563              m->iv_seed,
1564              &GSC_my_identity);
1565   /* decrypt */
1566   if (GNUNET_OK !=
1567       do_decrypt (kx,
1568                   &iv,
1569                   &m->sequence_number,
1570                   &buf[ENCRYPTED_HEADER_SIZE],
1571                   size - ENCRYPTED_HEADER_SIZE))
1572   {
1573     GNUNET_break_op (0);
1574     return;
1575   }
1576   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1577               "Decrypted %u bytes from %s\n",
1578               (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1579               GNUNET_i2s (kx->peer));
1580   pt = (struct EncryptedMessage *) buf;
1581
1582   /* validate sequence number */
1583   snum = ntohl (pt->sequence_number);
1584   if (kx->last_sequence_number_received == snum)
1585   {
1586     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1587                 "Received duplicate message, ignoring.\n");
1588     /* duplicate, ignore */
1589     GNUNET_STATISTICS_update (GSC_stats,
1590                               gettext_noop ("# bytes dropped (duplicates)"),
1591                               size,
1592                               GNUNET_NO);
1593     return;
1594   }
1595   if ((kx->last_sequence_number_received > snum) &&
1596       (kx->last_sequence_number_received - snum > 32))
1597   {
1598     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1599                 "Received ancient out of sequence message, ignoring.\n");
1600     /* ancient out of sequence, ignore */
1601     GNUNET_STATISTICS_update (GSC_stats,
1602                               gettext_noop
1603                               ("# bytes dropped (out of sequence)"), size,
1604                               GNUNET_NO);
1605     return;
1606   }
1607   if (kx->last_sequence_number_received > snum)
1608   {
1609     uint32_t rotbit = 1U << (kx->last_sequence_number_received - snum - 1);
1610
1611     if ((kx->last_packets_bitmap & rotbit) != 0)
1612     {
1613       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1614                   "Received duplicate message, ignoring.\n");
1615       GNUNET_STATISTICS_update (GSC_stats,
1616                                 gettext_noop ("# bytes dropped (duplicates)"),
1617                                 size, GNUNET_NO);
1618       /* duplicate, ignore */
1619       return;
1620     }
1621     kx->last_packets_bitmap |= rotbit;
1622   }
1623   if (kx->last_sequence_number_received < snum)
1624   {
1625     unsigned int shift = (snum - kx->last_sequence_number_received);
1626
1627     if (shift >= 8 * sizeof (kx->last_packets_bitmap))
1628       kx->last_packets_bitmap = 0;
1629     else
1630       kx->last_packets_bitmap <<= shift;
1631     kx->last_sequence_number_received = snum;
1632   }
1633
1634   /* check timestamp */
1635   t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
1636   if (GNUNET_TIME_absolute_get_duration (t).rel_value_us >
1637       MAX_MESSAGE_AGE.rel_value_us)
1638   {
1639     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1640                 "Message received far too old (%s). Content ignored.\n",
1641                 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (t),
1642                                                         GNUNET_YES));
1643     GNUNET_STATISTICS_update (GSC_stats,
1644                               gettext_noop
1645                               ("# bytes dropped (ancient message)"), size,
1646                               GNUNET_NO);
1647     return;
1648   }
1649
1650   /* process decrypted message(s) */
1651   update_timeout (kx);
1652   GNUNET_STATISTICS_update (GSC_stats,
1653                             gettext_noop ("# bytes of payload decrypted"),
1654                             size - sizeof (struct EncryptedMessage),
1655                             GNUNET_NO);
1656   if (GNUNET_OK !=
1657       GNUNET_MST_from_buffer (kx->mst,
1658                               &buf[sizeof (struct EncryptedMessage)],
1659                               size - sizeof (struct EncryptedMessage),
1660                               GNUNET_YES,
1661                               GNUNET_NO))
1662     GNUNET_break_op (0);
1663 }
1664
1665
1666 /**
1667  * One of our neighbours has excess bandwidth, remember this.
1668  *
1669  * @param cls NULL
1670  * @param pid identity of the peer with excess bandwidth
1671  * @param connect_cls the `struct Neighbour`
1672  */
1673 static void
1674 handle_transport_notify_excess_bw (void *cls,
1675                                    const struct GNUNET_PeerIdentity *pid,
1676                                    void *connect_cls)
1677 {
1678   struct GSC_KeyExchangeInfo *kx = connect_cls;
1679
1680   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1681               "Peer %s has excess bandwidth available\n",
1682               GNUNET_i2s (pid));
1683   kx->has_excess_bandwidth = GNUNET_YES;
1684   GSC_SESSIONS_solicit (pid);
1685 }
1686
1687
1688 /**
1689  * Setup the message that links the ephemeral key to our persistent
1690  * public key and generate the appropriate signature.
1691  */
1692 static void
1693 sign_ephemeral_key ()
1694 {
1695   current_ekm.header.size = htons (sizeof (struct EphemeralKeyMessage));
1696   current_ekm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY);
1697   current_ekm.sender_status = 0; /* to be set later */
1698   current_ekm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY);
1699   current_ekm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
1700                                     sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1701                                     sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1702                                     sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) +
1703                                     sizeof (struct GNUNET_PeerIdentity));
1704   current_ekm.creation_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1705   if (GNUNET_YES ==
1706       GNUNET_CONFIGURATION_get_value_yesno (GSC_cfg,
1707                                             "core",
1708                                             "USE_EPHEMERAL_KEYS"))
1709   {
1710     current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_add (REKEY_FREQUENCY,
1711                                                                                                                          REKEY_TOLERANCE)));
1712   }
1713   else
1714   {
1715     current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1716   }
1717   GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key,
1718                                       &current_ekm.ephemeral_key);
1719   current_ekm.origin_identity = GSC_my_identity;
1720   GNUNET_assert (GNUNET_OK ==
1721                  GNUNET_CRYPTO_eddsa_sign (my_private_key,
1722                                            &current_ekm.purpose,
1723                                            &current_ekm.signature));
1724 }
1725
1726
1727 /**
1728  * Task run to trigger rekeying.
1729  *
1730  * @param cls closure, NULL
1731  */
1732 static void
1733 do_rekey (void *cls)
1734 {
1735   struct GSC_KeyExchangeInfo *pos;
1736
1737   rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY,
1738                                              &do_rekey,
1739                                              NULL);
1740   if (NULL != my_ephemeral_key)
1741     GNUNET_free (my_ephemeral_key);
1742   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1743               "Rekeying\n");
1744   my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
1745   GNUNET_assert (NULL != my_ephemeral_key);
1746   sign_ephemeral_key ();
1747   for (pos = kx_head; NULL != pos; pos = pos->next)
1748   {
1749     if (GNUNET_CORE_KX_STATE_UP == pos->status)
1750     {
1751       pos->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1752       monitor_notify_all (pos);
1753       derive_session_keys (pos);
1754     }
1755     if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
1756     {
1757       pos->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1758       monitor_notify_all (pos);
1759     }
1760     monitor_notify_all (pos);
1761     send_key (pos);
1762   }
1763 }
1764
1765
1766 /**
1767  * Initialize KX subsystem.
1768  *
1769  * @param pk private key to use for the peer
1770  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1771  */
1772 int
1773 GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
1774 {
1775   struct GNUNET_MQ_MessageHandler handlers[] = {
1776     GNUNET_MQ_hd_fixed_size (ephemeral_key,
1777                              GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
1778                              struct EphemeralKeyMessage,
1779                              NULL),
1780     GNUNET_MQ_hd_fixed_size (ping,
1781                              GNUNET_MESSAGE_TYPE_CORE_PING,
1782                              struct PingMessage,
1783                              NULL),
1784     GNUNET_MQ_hd_fixed_size (pong,
1785                              GNUNET_MESSAGE_TYPE_CORE_PONG,
1786                              struct PongMessage,
1787                              NULL),
1788     GNUNET_MQ_hd_var_size (encrypted,
1789                            GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE,
1790                            struct EncryptedMessage,
1791                            NULL),
1792     GNUNET_MQ_handler_end()
1793   };
1794
1795   my_private_key = pk;
1796   GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1797                                       &GSC_my_identity.public_key);
1798   my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create ();
1799   if (NULL == my_ephemeral_key)
1800   {
1801     GNUNET_break (0);
1802     GNUNET_free (my_private_key);
1803     my_private_key = NULL;
1804     return GNUNET_SYSERR;
1805   }
1806   sign_ephemeral_key ();
1807   nc = GNUNET_notification_context_create (1);
1808   rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY,
1809                                              &do_rekey,
1810                                              NULL);
1811   transport
1812     = GNUNET_TRANSPORT_core_connect (GSC_cfg,
1813                                      &GSC_my_identity,
1814                                      handlers,
1815                                      NULL,
1816                                      &handle_transport_notify_connect,
1817                                      &handle_transport_notify_disconnect,
1818                                      &handle_transport_notify_excess_bw);
1819   if (NULL == transport)
1820   {
1821     GSC_KX_done ();
1822     return GNUNET_SYSERR;
1823   }
1824   return GNUNET_OK;
1825 }
1826
1827
1828 /**
1829  * Shutdown KX subsystem.
1830  */
1831 void
1832 GSC_KX_done ()
1833 {
1834   if (NULL != transport)
1835   {
1836     GNUNET_TRANSPORT_core_disconnect (transport);
1837     transport = NULL;
1838   }
1839   if (NULL != rekey_task)
1840   {
1841     GNUNET_SCHEDULER_cancel (rekey_task);
1842     rekey_task = NULL;
1843   }
1844   if (NULL != my_ephemeral_key)
1845   {
1846     GNUNET_free (my_ephemeral_key);
1847     my_ephemeral_key = NULL;
1848   }
1849   if (NULL != my_private_key)
1850   {
1851     GNUNET_free (my_private_key);
1852     my_private_key = NULL;
1853   }
1854   if (NULL != nc)
1855   {
1856     GNUNET_notification_context_destroy (nc);
1857     nc = NULL;
1858   }
1859 }
1860
1861
1862  /**
1863  * Check how many messages are queued for the given neighbour.
1864  *
1865  * @param kxinfo data about neighbour to check
1866  * @return number of items in the message queue
1867  */
1868 unsigned int
1869 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
1870 {
1871   return GNUNET_MQ_get_length (kxinfo->mq);
1872 }
1873
1874
1875 /**
1876  * Check if the given neighbour has excess bandwidth available.
1877  *
1878  * @param target neighbour to check
1879  * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
1880  */
1881 int
1882 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
1883 {
1884   return kxinfo->has_excess_bandwidth;
1885 }
1886
1887
1888 /**
1889  * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.  For this
1890  * request type, the client does not have to have transmitted an INIT
1891  * request.  All current peers are returned, regardless of which
1892  * message types they accept.
1893  *
1894  * @param mq message queue to add for monitoring
1895  */
1896 void
1897 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
1898 {
1899   struct GNUNET_MQ_Envelope *env;
1900   struct MonitorNotifyMessage *done_msg;
1901   struct GSC_KeyExchangeInfo *kx;
1902
1903   GNUNET_notification_context_add (nc,
1904                                    mq);
1905   for (kx = kx_head; NULL != kx; kx = kx->next)
1906   {
1907     struct GNUNET_MQ_Envelope *env;
1908     struct MonitorNotifyMessage *msg;
1909
1910     env = GNUNET_MQ_msg (msg,
1911                          GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
1912     msg->state = htonl ((uint32_t) kx->status);
1913     msg->peer = *kx->peer;
1914     msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
1915     GNUNET_MQ_send (mq,
1916                     env);
1917   }
1918   env = GNUNET_MQ_msg (done_msg,
1919                        GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
1920   done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
1921   done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1922   GNUNET_MQ_send (mq,
1923                   env);
1924 }
1925
1926
1927 /* end of gnunet-service-core_kx.c */