reduce messages in initial KX
[oweals/gnunet.git] / src / core / gnunet-service-core_kx.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, 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_clients.h"
30 #include "gnunet-service-core_neighbours.h"
31 #include "gnunet-service-core_sessions.h"
32 #include "gnunet_statistics_service.h"
33 #include "gnunet_constants.h"
34 #include "gnunet_signatures.h"
35 #include "gnunet_protocols.h"
36 #include "core.h"
37
38
39 /**
40  * How long do we wait for SET_KEY confirmation initially?
41  */
42 #define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
43
44 /**
45  * What is the minimum frequency for a PING message?
46  */
47 #define MIN_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
48
49 /**
50  * How often do we rekey?
51  */
52 #define REKEY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
53
54 /**
55  * What time difference do we tolerate?
56  */
57 #define REKEY_TOLERANCE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
58
59 /**
60  * What is the maximum age of a message for us to consider processing
61  * it?  Note that this looks at the timestamp used by the other peer,
62  * so clock skew between machines does come into play here.  So this
63  * should be picked high enough so that a little bit of clock skew
64  * does not prevent peers from connecting to us.
65  */
66 #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
67
68
69
70 GNUNET_NETWORK_STRUCT_BEGIN
71
72 /**
73  * Message transmitted with the signed ephemeral key of a peer.  The
74  * session key is then derived from the two ephemeral keys (ECDHE).
75  */
76 struct EphemeralKeyMessage
77 {
78
79   /**
80    * Message type is CORE_EPHEMERAL_KEY.
81    */
82   struct GNUNET_MessageHeader header;
83
84   /**
85    * Status of the sender (should be in "enum PeerStateMachine"), nbo.
86    */
87   int32_t sender_status GNUNET_PACKED;
88
89   /**
90    * An ECC signature of the 'origin' asserting the validity of
91    * the given ephemeral key.
92    */
93   struct GNUNET_CRYPTO_EccSignature signature;
94
95   /**
96    * Information about what is being signed.
97    */
98   struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
99
100   /**
101    * At what time was this key created (beginning of validity).
102    */
103   struct GNUNET_TIME_AbsoluteNBO creation_time;
104   
105   /**
106    * When does the given ephemeral key expire (end of validity).
107    */
108   struct GNUNET_TIME_AbsoluteNBO expiration_time;
109
110   /**
111    * Ephemeral public ECC key (always for NIST P-521) encoded in a format suitable
112    * for network transmission as created using 'gcry_sexp_sprint'.
113    */
114   struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded ephemeral_key;  
115
116   /**
117    * Public key of the signing peer (persistent version, not the ephemeral public key).
118    */
119   struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded origin_public_key;
120
121 };
122
123
124 /**
125  * We're sending an (encrypted) PING to the other peer to check if he
126  * can decrypt.  The other peer should respond with a PONG with the
127  * same content, except this time encrypted with the receiver's key.
128  */
129 struct PingMessage
130 {
131   /**
132    * Message type is CORE_PING.
133    */
134   struct GNUNET_MessageHeader header;
135
136   /**
137    * Seed for the IV
138    */
139   uint32_t iv_seed GNUNET_PACKED;
140
141   /**
142    * Intended target of the PING, used primarily to check
143    * that decryption actually worked.
144    */
145   struct GNUNET_PeerIdentity target;
146
147   /**
148    * Random number chosen to make reply harder.
149    */
150   uint32_t challenge GNUNET_PACKED;
151 };
152
153
154 /**
155  * Response to a PING.  Includes data from the original PING.
156  */
157 struct PongMessage
158 {
159   /**
160    * Message type is CORE_PONG.
161    */
162   struct GNUNET_MessageHeader header;
163
164   /**
165    * Seed for the IV
166    */
167   uint32_t iv_seed GNUNET_PACKED;
168
169   /**
170    * Random number to make faking the reply harder.  Must be
171    * first field after header (this is where we start to encrypt!).
172    */
173   uint32_t challenge GNUNET_PACKED;
174
175   /**
176    * Reserved, always zero.
177    */
178   uint32_t reserved;
179
180   /**
181    * Intended target of the PING, used primarily to check
182    * that decryption actually worked.
183    */
184   struct GNUNET_PeerIdentity target;
185 };
186
187
188 /**
189  * Encapsulation for encrypted messages exchanged between
190  * peers.  Followed by the actual encrypted data.
191  */
192 struct EncryptedMessage
193 {
194   /**
195    * Message type is either CORE_ENCRYPTED_MESSAGE.
196    */
197   struct GNUNET_MessageHeader header;
198
199   /**
200    * Random value used for IV generation.
201    */
202   uint32_t iv_seed GNUNET_PACKED;
203
204   /**
205    * MAC of the encrypted message (starting at 'sequence_number'),
206    * used to verify message integrity. Everything after this value
207    * (excluding this value itself) will be encrypted and authenticated.
208    * ENCRYPTED_HEADER_SIZE must be set to the offset of the *next* field.
209    */
210   struct GNUNET_HashCode hmac;
211
212   /**
213    * Sequence number, in network byte order.  This field
214    * must be the first encrypted/decrypted field
215    */
216   uint32_t sequence_number GNUNET_PACKED;
217
218   /**
219    * Reserved, always zero.
220    */
221   uint32_t reserved;
222
223   /**
224    * Timestamp.  Used to prevent reply of ancient messages
225    * (recent messages are caught with the sequence number).
226    */
227   struct GNUNET_TIME_AbsoluteNBO timestamp;
228
229 };
230 GNUNET_NETWORK_STRUCT_END
231
232
233 /**
234  * Number of bytes (at the beginning) of "struct EncryptedMessage"
235  * that are NOT encrypted.
236  */
237 #define ENCRYPTED_HEADER_SIZE (offsetof(struct EncryptedMessage, sequence_number))
238
239
240 /**
241  * State machine for our P2P encryption handshake.  Everyone starts in
242  * "DOWN", if we receive the other peer's key (other peer initiated)
243  * we start in state RECEIVED (since we will immediately send our
244  * own); otherwise we start in SENT.  If we get back a PONG from
245  * within either state, we move up to CONFIRMED (the PONG will always
246  * be sent back encrypted with the key we sent to the other peer).
247  */
248 enum KxStateMachine
249 {
250   /**
251    * No handshake yet.
252    */
253   KX_STATE_DOWN,
254
255   /**
256    * We've sent our session key.
257    */
258   KX_STATE_KEY_SENT,
259
260   /**
261    * We've received the other peers session key.
262    */
263   KX_STATE_KEY_RECEIVED,
264
265   /**
266    * The other peer has confirmed our session key + PING with a PONG
267    * message encrypted with his session key (which we got).  Key
268    * exchange is done.
269    */
270   KX_STATE_UP,
271
272   /**
273    * We're rekeying (or had a timeout), so we have sent the other peer
274    * our new ephemeral key, but we did not get a matching PONG yet.
275    * This is equivalent to being 'KX_STATE_KEY_RECEIVED', except that
276    * the session is marked as 'up' with sessions (as we don't want to
277    * drop and re-establish P2P connections simply due to rekeying).
278    */
279   KX_STATE_REKEY_SENT
280
281 };
282
283
284 /**
285  * Information about the status of a key exchange with another peer.
286  */
287 struct GSC_KeyExchangeInfo
288 {
289
290   /**
291    * DLL.
292    */
293   struct GSC_KeyExchangeInfo *next;
294
295   /**
296    * DLL.
297    */
298   struct GSC_KeyExchangeInfo *prev;
299
300   /**
301    * Identity of the peer.
302    */
303   struct GNUNET_PeerIdentity peer;
304
305   /**
306    * PING message we transmit to the other peer.
307    */
308   struct PingMessage ping;
309
310   /**
311    * Key we use to encrypt our messages for the other peer
312    * (initialized by us when we do the handshake).
313    */
314   struct GNUNET_CRYPTO_AesSessionKey encrypt_key;
315
316   /**
317    * Key we use to decrypt messages from the other peer
318    * (given to us by the other peer during the handshake).
319    */
320   struct GNUNET_CRYPTO_AesSessionKey decrypt_key;
321
322   /**
323    * At what time did the other peer generate the decryption key?
324    */
325   struct GNUNET_TIME_Absolute foreign_key_expires;
326
327   /**
328    * When should the session time out (if there are no PONGs)?
329    */
330   struct GNUNET_TIME_Absolute timeout;
331
332   /**
333    * At what frequency are we currently re-trying SET_KEY messages?
334    */
335   struct GNUNET_TIME_Relative set_key_retry_frequency;
336
337   /**
338    * ID of task used for re-trying SET_KEY and PING message.
339    */
340   GNUNET_SCHEDULER_TaskIdentifier retry_set_key_task;
341
342   /**
343    * ID of task used for sending keep-alive pings.
344    */
345   GNUNET_SCHEDULER_TaskIdentifier keep_alive_task;
346
347   /**
348    * Bit map indicating which of the 32 sequence numbers before the last
349    * were received (good for accepting out-of-order packets and
350    * estimating reliability of the connection)
351    */
352   unsigned int last_packets_bitmap;
353
354   /**
355    * last sequence number received on this connection (highest)
356    */
357   uint32_t last_sequence_number_received;
358
359   /**
360    * last sequence number transmitted
361    */
362   uint32_t last_sequence_number_sent;
363
364   /**
365    * What was our PING challenge number (for this peer)?
366    */
367   uint32_t ping_challenge;
368
369   /**
370    * What is our connection status?
371    */
372   enum KxStateMachine status;
373
374 };
375
376
377 /**
378  * Our private key.
379  */
380 static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key;
381
382 /**
383  * Our ephemeral private key.
384  */
385 static struct GNUNET_CRYPTO_EccPrivateKey *my_ephemeral_key;
386
387 /**
388  * Current message we send for a key exchange.
389  */
390 static struct EphemeralKeyMessage current_ekm;
391
392 /**
393  * Our public key.
394  */
395 static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded my_public_key;
396
397 /**
398  * Our message stream tokenizer (for encrypted payload).
399  */
400 static struct GNUNET_SERVER_MessageStreamTokenizer *mst;
401
402 /**
403  * DLL head.
404  */
405 static struct GSC_KeyExchangeInfo *kx_head;
406
407 /**
408  * DLL tail.
409  */
410 static struct GSC_KeyExchangeInfo *kx_tail;
411
412 /**
413  * Task scheduled for periodic re-generation (and thus rekeying) of our
414  * ephemeral key.
415  */ 
416 static GNUNET_SCHEDULER_TaskIdentifier rekey_task;
417
418
419 /**
420  * Derive an authentication key from "set key" information
421  *
422  * @param akey authentication key to derive
423  * @param skey session key to use
424  * @param seed seed to use
425  */
426 static void
427 derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
428                  const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed)
429 {
430   static const char ctx[] = "authentication key";
431
432   GNUNET_CRYPTO_hmac_derive_key (akey, skey, &seed, sizeof (seed), &skey->key,
433                                  sizeof (skey->key), ctx,
434                                  sizeof (ctx), NULL);
435 }
436
437
438 /**
439  * Derive an IV from packet information
440  *
441  * @param iv initialization vector to initialize
442  * @param skey session key to use
443  * @param seed seed to use
444  * @param identity identity of the other peer to use
445  */
446 static void
447 derive_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
448            const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed,
449            const struct GNUNET_PeerIdentity *identity)
450 {
451   static const char ctx[] = "initialization vector";
452
453   GNUNET_CRYPTO_aes_derive_iv (iv, skey, &seed, sizeof (seed),
454                                &identity->hashPubKey.bits,
455                                sizeof (identity->hashPubKey.bits), ctx,
456                                sizeof (ctx), NULL);
457 }
458
459
460 /**
461  * Derive an IV from pong packet information
462  *
463  * @param iv initialization vector to initialize
464  * @param skey session key to use
465  * @param seed seed to use
466  * @param challenge nonce to use
467  * @param identity identity of the other peer to use
468  */
469 static void
470 derive_pong_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv,
471                 const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed,
472                 uint32_t challenge, const struct GNUNET_PeerIdentity *identity)
473 {
474   static const char ctx[] = "pong initialization vector";
475
476   GNUNET_CRYPTO_aes_derive_iv (iv, skey, &seed, sizeof (seed),
477                                &identity->hashPubKey.bits,
478                                sizeof (identity->hashPubKey.bits), &challenge,
479                                sizeof (challenge), ctx, sizeof (ctx), NULL);
480 }
481
482
483 /**
484  * Derive an AES key from key material
485  *
486  * @param sender peer identity of the sender
487  * @param receiver peer identity of the sender
488  * @param key_material high entropy key material to use
489  * @param skey set to derived session key 
490  */
491 static void
492 derive_aes_key (const struct GNUNET_PeerIdentity *sender,
493                 const struct GNUNET_PeerIdentity *receiver,
494                 const struct GNUNET_HashCode *key_material,
495                 struct GNUNET_CRYPTO_AesSessionKey *skey)
496 {
497   static const char ctx[] = "aes key generation vector";
498
499   GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_AesSessionKey),
500                      ctx, sizeof (ctx),
501                      skey, sizeof (struct GNUNET_CRYPTO_AesSessionKey),
502                      sender, sizeof (struct GNUNET_PeerIdentity),
503                      receiver, sizeof (struct GNUNET_PeerIdentity),
504                      NULL);
505 }
506
507
508 /**
509  * Encrypt size bytes from in and write the result to out.  Use the
510  * key for outbound traffic of the given neighbour.
511  *
512  * @param kx key information context
513  * @param iv initialization vector to use
514  * @param in ciphertext
515  * @param out plaintext
516  * @param size size of in/out
517  * @return GNUNET_OK on success
518  */
519 static int
520 do_encrypt (struct GSC_KeyExchangeInfo *kx,
521             const struct GNUNET_CRYPTO_AesInitializationVector *iv,
522             const void *in, void *out, size_t size)
523 {
524   if (size != (uint16_t) size)
525   {
526     GNUNET_break (0);
527     return GNUNET_NO;
528   }
529   GNUNET_assert (size ==
530                  GNUNET_CRYPTO_aes_encrypt (in, (uint16_t) size,
531                                             &kx->encrypt_key, iv, out));
532   GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes encrypted"), size,
533                             GNUNET_NO);
534   /* the following is too sensitive to write to log files by accident,
535      so we require manual intervention to get this one... */
536 #if 0
537   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
538               "Encrypted %u bytes for `%4s' using key %u, IV %u\n",
539               (unsigned int) size, GNUNET_i2s (&kx->peer),
540               (unsigned int) kx->encrypt_key.crc32, GNUNET_CRYPTO_crc32_n (iv,
541                                                                            sizeof
542                                                                            (iv)));
543 #endif
544   return GNUNET_OK;
545 }
546
547
548 /**
549  * Decrypt size bytes from in and write the result to out.  Use the
550  * key for inbound traffic of the given neighbour.  This function does
551  * NOT do any integrity-checks on the result.
552  *
553  * @param kx key information context
554  * @param iv initialization vector to use
555  * @param in ciphertext
556  * @param out plaintext
557  * @param size size of in/out
558  * @return GNUNET_OK on success
559  */
560 static int
561 do_decrypt (struct GSC_KeyExchangeInfo *kx,
562             const struct GNUNET_CRYPTO_AesInitializationVector *iv,
563             const void *in, void *out, size_t size)
564 {
565   if (size != (uint16_t) size)
566   {
567     GNUNET_break (0);
568     return GNUNET_NO;
569   }
570   if ( (kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) &&
571        (kx->status != KX_STATE_REKEY_SENT) )
572   {
573     GNUNET_break_op (0);
574     return GNUNET_SYSERR;
575   }
576   if (size !=
577       GNUNET_CRYPTO_aes_decrypt (in, (uint16_t) size, &kx->decrypt_key, iv,
578                                  out))
579   {
580     GNUNET_break (0);
581     return GNUNET_SYSERR;
582   }
583   GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes decrypted"), size,
584                             GNUNET_NO);
585   /* the following is too sensitive to write to log files by accident,
586      so we require manual intervention to get this one... */
587 #if 0
588   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
589               "Decrypted %u bytes from `%4s' using key %u, IV %u\n",
590               (unsigned int) size, GNUNET_i2s (&kx->peer),
591               (unsigned int) kx->decrypt_key.crc32, GNUNET_CRYPTO_crc32_n (iv,
592                                                                            sizeof
593                                                                            (*iv)));
594 #endif
595   return GNUNET_OK;
596 }
597
598
599 /**
600  * Send our key (and encrypted PING) to the other peer.
601  *
602  * @param kx key exchange context
603  */
604 static void
605 send_key (struct GSC_KeyExchangeInfo *kx);
606
607
608 /**
609  * Task that will retry "send_key" if our previous attempt failed.
610  *
611  * @param cls our 'struct GSC_KeyExchangeInfo'
612  * @param tc scheduler context
613  */
614 static void
615 set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
616 {
617   struct GSC_KeyExchangeInfo *kx = cls;
618
619   kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
620   kx->set_key_retry_frequency = GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency);
621   send_key (kx);
622 }
623
624
625 /**
626  * Create a fresh PING message for transmission to the other peer.
627  *
628  * @param kx key exchange context to create PING for
629  */
630 static void
631 setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
632 {
633   struct PingMessage pp;
634   struct PingMessage *pm;
635   struct GNUNET_CRYPTO_AesInitializationVector iv;
636
637   pm = &kx->ping;
638   pm->header.size = htons (sizeof (struct PingMessage));
639   pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
640   pm->iv_seed =
641       GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
642   derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, &kx->peer);
643   pp.challenge = kx->ping_challenge;
644   pp.target = kx->peer;
645   do_encrypt (kx, &iv, &pp.target, &pm->target,
646               sizeof (struct PingMessage) - ((void *) &pm->target -
647                                              (void *) pm));
648 }
649
650
651 /**
652  * Start the key exchange with the given peer.
653  *
654  * @param pid identity of the peer to do a key exchange with
655  * @return key exchange information context
656  */
657 struct GSC_KeyExchangeInfo *
658 GSC_KX_start (const struct GNUNET_PeerIdentity *pid)
659 {
660   struct GSC_KeyExchangeInfo *kx;
661
662   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
663               "Initiating key exchange with `%s'\n",
664               GNUNET_i2s (pid));
665   GNUNET_STATISTICS_update (GSC_stats,
666                             gettext_noop ("# key exchanges initiated"), 1,
667                             GNUNET_NO);
668   kx = GNUNET_malloc (sizeof (struct GSC_KeyExchangeInfo));
669   kx->peer = *pid;
670   kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
671   GNUNET_CONTAINER_DLL_insert (kx_head,
672                                kx_tail,
673                                kx);
674   if (0 < GNUNET_CRYPTO_hash_cmp (&pid->hashPubKey,
675                                   &GSC_my_identity.hashPubKey))
676   {
677     /* peer with "lower" identity starts KX, otherwise we typically end up
678        with both peers starting the exchange and transmit the 'set key' 
679        message twice */
680     kx->status = KX_STATE_KEY_SENT;
681     send_key (kx);
682   }
683   return kx;
684 }
685
686
687 /**
688  * Stop key exchange with the given peer.  Clean up key material.
689  *
690  * @param kx key exchange to stop
691  */
692 void
693 GSC_KX_stop (struct GSC_KeyExchangeInfo *kx)
694 {
695   GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# key exchanges stopped"),
696                             1, GNUNET_NO);
697   if (kx->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK)
698   {
699     GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
700     kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
701   }
702   if (kx->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
703   {
704     GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
705     kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
706   }
707   GNUNET_CONTAINER_DLL_remove (kx_head,
708                                kx_tail,
709                                kx);
710   GNUNET_free (kx);
711 }
712
713
714 /**
715  * Send our PING to the other peer.
716  *
717  * @param kx key exchange context
718  */
719 static void
720 send_ping (struct GSC_KeyExchangeInfo *kx)
721 {
722   GSC_NEIGHBOURS_transmit (&kx->peer, &kx->ping.header,
723                            MIN_PING_FREQUENCY);
724 }
725
726 /**
727  * We received a SET_KEY message.  Validate and update
728  * our key material and status.
729  *
730  * @param kx key exchange status for the corresponding peer
731  * @param msg the set key message we received
732  */
733 void
734 GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx,
735                              const struct GNUNET_MessageHeader *msg)
736 {
737   const struct EphemeralKeyMessage *m;
738   struct GNUNET_TIME_Absolute start_t;
739   struct GNUNET_TIME_Absolute end_t;
740   struct GNUNET_TIME_Absolute now;
741   struct GNUNET_PeerIdentity signer_id;
742   enum KxStateMachine sender_status;  
743   uint16_t size;
744   struct GNUNET_HashCode key_material;
745   
746   size = ntohs (msg->size);
747   if (sizeof (struct EphemeralKeyMessage) != size)
748   {
749     GNUNET_break_op (0);
750     return;
751   }
752   m = (const struct EphemeralKeyMessage *) msg;
753   end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
754   if ( ( (KX_STATE_KEY_RECEIVED == kx->status) ||
755          (KX_STATE_UP == kx->status) ||
756          (KX_STATE_REKEY_SENT == kx->status) ) &&       
757        (end_t.abs_value <= kx->foreign_key_expires.abs_value) )
758   {
759     GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# old ephemeral keys ignored"),
760                               1, GNUNET_NO);
761     return;
762   }
763   start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
764
765   GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# ephemeral keys received"),
766                             1, GNUNET_NO);
767
768   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
769               "Core service receives `%s' request from `%4s'.\n", "EPHEMERAL_KEY",
770               GNUNET_i2s (&kx->peer));
771   GNUNET_CRYPTO_hash (&m->origin_public_key,
772                       sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded),
773                       &signer_id.hashPubKey);
774   if (0 !=
775       memcmp (&signer_id, &kx->peer,
776               sizeof (struct GNUNET_PeerIdentity)))
777   {    
778     GNUNET_break_op (0);
779     return;
780   }
781   if ((ntohl (m->purpose.size) !=
782        sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
783        sizeof (struct GNUNET_TIME_AbsoluteNBO) +
784        sizeof (struct GNUNET_TIME_AbsoluteNBO) +
785        sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded) +
786        sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)) ||
787       (GNUNET_OK !=
788        GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY,
789                                  &m->purpose,
790                                  &m->signature, &m->origin_public_key)))
791   {
792     /* invalid signature */
793     GNUNET_break_op (0);
794     return;
795   }
796   now = GNUNET_TIME_absolute_get ();
797   if ( (end_t.abs_value < GNUNET_TIME_absolute_subtract (now, REKEY_TOLERANCE).abs_value) ||
798        (start_t.abs_value > GNUNET_TIME_absolute_add (now, REKEY_TOLERANCE).abs_value) )
799   {
800     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
801                 _("Ephemeral key message rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"),
802                 now.abs_value,
803                 start_t.abs_value,
804                 end_t.abs_value);
805     return;
806   }
807   if (GNUNET_OK !=
808       GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key,
809                               &m->ephemeral_key,                              
810                               &key_material))
811   {
812     GNUNET_break (0);
813     return;
814   }
815   GNUNET_STATISTICS_update (GSC_stats,
816                             gettext_noop ("# EPHEMERAL_KEY messages decrypted"), 1,
817                             GNUNET_NO);
818   derive_aes_key (&GSC_my_identity,
819                   &kx->peer,
820                   &key_material,
821                   &kx->encrypt_key);
822   derive_aes_key (&kx->peer,
823                   &GSC_my_identity,
824                   &key_material,
825                   &kx->decrypt_key);
826   /* fresh key, reset sequence numbers */
827   kx->last_sequence_number_received = 0;
828   kx->last_packets_bitmap = 0;
829   kx->foreign_key_expires = end_t;
830   setup_fresh_ping (kx);
831
832   /* check if we still need to send the sender our key */
833   sender_status = (enum KxStateMachine) ntohl (m->sender_status);  
834   switch (sender_status)
835   {
836   case KX_STATE_DOWN:
837     /* makes no sense, should be at least KX_STATE_KEY_SENT */
838     GNUNET_break_op (0);
839     break;
840   case KX_STATE_KEY_SENT:
841     send_key (kx);
842     break;
843   case KX_STATE_KEY_RECEIVED:
844   case KX_STATE_UP: 
845   case KX_STATE_REKEY_SENT:
846     /* other peer already got our key */
847     break;
848   default:
849     GNUNET_break (0);
850     break;
851   }
852   /* check if we need to confirm everything is fine via PING + PONG */
853   switch (kx->status)
854   {
855   case KX_STATE_DOWN:
856     kx->status = KX_STATE_KEY_RECEIVED;
857     send_ping (kx);
858     break;
859   case KX_STATE_KEY_SENT:
860     kx->status = KX_STATE_KEY_RECEIVED;
861     send_ping (kx);
862     break;
863   case KX_STATE_KEY_RECEIVED:
864     send_ping (kx);
865     break;
866   case KX_STATE_UP: 
867     kx->status = KX_STATE_REKEY_SENT;
868     /* we got a new key, need to reconfirm! */
869     send_ping (kx);
870     break;
871   case KX_STATE_REKEY_SENT:
872     kx->status = KX_STATE_REKEY_SENT;
873     /* we got a new key, need to reconfirm! */
874     send_ping (kx);
875     break;
876   default:
877     GNUNET_break (0);
878     break;
879   }
880 }
881
882
883 /**
884  * We received a PING message.  Validate and transmit
885  * a PONG message.
886  *
887  * @param kx key exchange status for the corresponding peer
888  * @param msg the encrypted PING message itself
889  */
890 void
891 GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx,
892                     const struct GNUNET_MessageHeader *msg)
893 {
894   const struct PingMessage *m;
895   struct PingMessage t;
896   struct PongMessage tx;
897   struct PongMessage tp;
898   struct GNUNET_CRYPTO_AesInitializationVector iv;
899   uint16_t msize;
900
901   msize = ntohs (msg->size);
902   if (msize != sizeof (struct PingMessage))
903   {
904     GNUNET_break_op (0);
905     return;
906   }
907   GNUNET_STATISTICS_update (GSC_stats,
908                             gettext_noop ("# PING messages received"), 1,
909                             GNUNET_NO);
910   if ( (kx->status != KX_STATE_KEY_RECEIVED) && 
911        (kx->status != KX_STATE_UP) &&
912        (kx->status != KX_STATE_REKEY_SENT))
913   {
914     /* ignore */
915     GNUNET_STATISTICS_update (GSC_stats,
916                               gettext_noop ("# PING messages dropped (out of order)"), 1,
917                               GNUNET_NO);
918     return;
919   }
920   m = (const struct PingMessage *) msg;
921   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
922               "Core service receives `%s' request from `%4s'.\n", "PING",
923               GNUNET_i2s (&kx->peer));
924   derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
925   if (GNUNET_OK !=
926       do_decrypt (kx, &iv, &m->target, &t.target,
927                   sizeof (struct PingMessage) - ((void *) &m->target -
928                                                  (void *) m)))
929   {
930     GNUNET_break_op (0);
931     return;
932   }
933   if (0 !=
934       memcmp (&t.target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
935   {
936     char sender[9];
937     char peer[9];
938
939     GNUNET_snprintf (sender, sizeof (sender), "%8s", GNUNET_i2s (&kx->peer));
940     GNUNET_snprintf (peer, sizeof (peer), "%8s", GNUNET_i2s (&t.target));
941     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
942                 _
943                 ("Received PING from `%s' for different identity: I am `%s', PONG identity: `%s'\n"),
944                 sender, GNUNET_i2s (&GSC_my_identity), peer);
945     GNUNET_break_op (0);
946     return;
947   }
948   /* construct PONG */
949   tx.reserved = 0;
950   tx.challenge = t.challenge;
951   tx.target = t.target;
952   tp.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG);
953   tp.header.size = htons (sizeof (struct PongMessage));
954   tp.iv_seed =
955       GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
956   derive_pong_iv (&iv, &kx->encrypt_key, tp.iv_seed, t.challenge, &kx->peer);
957   do_encrypt (kx, &iv, &tx.challenge, &tp.challenge,
958               sizeof (struct PongMessage) - ((void *) &tp.challenge -
959                                              (void *) &tp));
960   GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PONG messages created"),
961                             1, GNUNET_NO);
962   GSC_NEIGHBOURS_transmit (&kx->peer, &tp.header,
963                            GNUNET_TIME_UNIT_FOREVER_REL /* FIXME: timeout */ );
964 }
965
966
967 /**
968  * Task triggered when a neighbour entry is about to time out
969  * (and we should prevent this by sending a PING).
970  *
971  * @param cls the 'struct GSC_KeyExchangeInfo'
972  * @param tc scheduler context (not used)
973  */
974 static void
975 send_keep_alive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
976 {
977   struct GSC_KeyExchangeInfo *kx = cls;
978   struct GNUNET_TIME_Relative retry;
979   struct GNUNET_TIME_Relative left;
980
981   kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
982   left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
983   if (0 == left.rel_value)
984   {
985     GNUNET_STATISTICS_update (GSC_stats,
986                               gettext_noop ("# sessions terminated by timeout"),
987                               1, GNUNET_NO);
988     GSC_SESSIONS_end (&kx->peer);
989     kx->status = KX_STATE_KEY_SENT;
990     send_key (kx);
991     return;
992   }
993   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending KEEPALIVE to `%s'\n",
994               GNUNET_i2s (&kx->peer));
995   GNUNET_STATISTICS_update (GSC_stats,
996                             gettext_noop ("# keepalive messages sent"), 1,
997                             GNUNET_NO);
998   setup_fresh_ping (kx);
999   GSC_NEIGHBOURS_transmit (&kx->peer, &kx->ping.header,
1000                            kx->set_key_retry_frequency);
1001   retry =
1002       GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1003                                 MIN_PING_FREQUENCY);
1004   kx->keep_alive_task =
1005       GNUNET_SCHEDULER_add_delayed (retry, &send_keep_alive, kx);
1006 }
1007
1008
1009 /**
1010  * We've seen a valid message from the other peer.
1011  * Update the time when the session would time out
1012  * and delay sending our keep alive message further.
1013  *
1014  * @param kx key exchange where we saw activity
1015  */
1016 static void
1017 update_timeout (struct GSC_KeyExchangeInfo *kx)
1018 {
1019   kx->timeout =
1020       GNUNET_TIME_relative_to_absolute
1021       (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1022   if (kx->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
1023     GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1024   kx->keep_alive_task =
1025       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
1026                                     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1027                                      2), &send_keep_alive, kx);
1028 }
1029
1030
1031 /**
1032  * We received a PONG message.  Validate and update our status.
1033  *
1034  * @param kx key exchange context for the the PONG
1035  * @param msg the encrypted PONG message itself
1036  */
1037 void
1038 GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx,
1039                     const struct GNUNET_MessageHeader *msg)
1040 {
1041   const struct PongMessage *m;
1042   struct PongMessage t;
1043   struct GNUNET_CRYPTO_AesInitializationVector iv;
1044   uint16_t msize;
1045
1046   msize = ntohs (msg->size);
1047   if (sizeof (struct PongMessage) != msize)
1048   {
1049     GNUNET_break_op (0);
1050     return;
1051   }
1052   GNUNET_STATISTICS_update (GSC_stats,
1053                             gettext_noop ("# PONG messages received"), 1,
1054                             GNUNET_NO);
1055   switch (kx->status)
1056   {
1057   case KX_STATE_DOWN:
1058     GNUNET_STATISTICS_update (GSC_stats,
1059                               gettext_noop ("# PONG messages dropped (connection down)"), 1,
1060                               GNUNET_NO);
1061     return;
1062   case KX_STATE_KEY_SENT:
1063     GNUNET_STATISTICS_update (GSC_stats,
1064                               gettext_noop ("# PONG messages dropped (out of order)"), 1,
1065                               GNUNET_NO);
1066     return;
1067   case KX_STATE_KEY_RECEIVED:
1068     break;
1069   case KX_STATE_UP:
1070     break;
1071   case KX_STATE_REKEY_SENT:
1072     break;
1073   default:
1074     GNUNET_break (0);
1075     return;
1076   }
1077   m = (const struct PongMessage *) msg;
1078   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1079               "Core service receives `%s' response from `%4s'.\n", "PONG",
1080               GNUNET_i2s (&kx->peer));
1081   /* mark as garbage, just to be sure */
1082   memset (&t, 255, sizeof (t));
1083   derive_pong_iv (&iv, &kx->decrypt_key, m->iv_seed, kx->ping_challenge,
1084                   &GSC_my_identity);
1085   if (GNUNET_OK !=
1086       do_decrypt (kx, &iv, &m->challenge, &t.challenge,
1087                   sizeof (struct PongMessage) - ((void *) &m->challenge -
1088                                                  (void *) m)))
1089   {
1090     GNUNET_break_op (0);
1091     return;
1092   }
1093   GNUNET_STATISTICS_update (GSC_stats,
1094                             gettext_noop ("# PONG messages decrypted"), 1,
1095                             GNUNET_NO);
1096   if ((0 != memcmp (&t.target, &kx->peer, sizeof (struct GNUNET_PeerIdentity)))
1097       || (kx->ping_challenge != t.challenge))
1098   {
1099     /* PONG malformed */
1100     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1101                 "Received malformed `%s' wanted sender `%4s' with challenge %u\n",
1102                 "PONG", GNUNET_i2s (&kx->peer),
1103                 (unsigned int) kx->ping_challenge);
1104     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105                 "Received malformed `%s' received from `%4s' with challenge %u\n",
1106                 "PONG", GNUNET_i2s (&t.target), (unsigned int) t.challenge);
1107     return;
1108   }
1109   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received PONG from `%s'\n",
1110               GNUNET_i2s (&kx->peer));
1111   /* no need to resend key any longer */
1112   if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task)
1113   {
1114     GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1115     kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
1116   }  
1117   switch (kx->status)
1118   {
1119   case KX_STATE_DOWN:
1120     GNUNET_assert (0);           /* should be impossible */
1121     return;
1122   case KX_STATE_KEY_SENT:
1123     GNUNET_assert (0);           /* should be impossible */
1124     return;
1125   case KX_STATE_KEY_RECEIVED:
1126     GNUNET_STATISTICS_update (GSC_stats,
1127                               gettext_noop
1128                               ("# session keys confirmed via PONG"), 1,
1129                               GNUNET_NO);
1130     kx->status = KX_STATE_UP;
1131     GSC_SESSIONS_create (&kx->peer, kx);
1132     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task);
1133     update_timeout (kx);
1134     break;
1135   case KX_STATE_UP:
1136     GNUNET_STATISTICS_update (GSC_stats,
1137                               gettext_noop
1138                               ("# timeouts prevented via PONG"), 1,
1139                               GNUNET_NO);
1140     update_timeout (kx);
1141     break;
1142   case KX_STATE_REKEY_SENT:
1143     GNUNET_STATISTICS_update (GSC_stats,
1144                               gettext_noop
1145                               ("# rekey operations confirmed via PONG"), 1,
1146                               GNUNET_NO);
1147     kx->status = KX_STATE_UP;
1148     update_timeout (kx);
1149     break;
1150   default:
1151     GNUNET_break (0);
1152     break;
1153   }
1154 }
1155
1156
1157 /**
1158  * Send our key to the other peer.
1159  *
1160  * @param kx key exchange context
1161  */
1162 static void
1163 send_key (struct GSC_KeyExchangeInfo *kx)
1164 {
1165   if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task)
1166   {
1167      GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1168      kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
1169   }
1170   /* always update sender status in SET KEY message */
1171   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1172               "Sending key to `%s' (my status: %d)\n",
1173               GNUNET_i2s (&kx->peer),
1174               kx->status);
1175   current_ekm.sender_status = htonl ((int32_t) (kx->status));  
1176   GSC_NEIGHBOURS_transmit (&kx->peer, &current_ekm.header,
1177                            kx->set_key_retry_frequency);
1178   kx->retry_set_key_task =
1179       GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
1180                                     &set_key_retry_task, kx);
1181 }
1182
1183
1184 /**
1185  * Encrypt and transmit a message with the given payload.
1186  *
1187  * @param kx key exchange context
1188  * @param payload payload of the message
1189  * @param payload_size number of bytes in 'payload'
1190  */
1191 void
1192 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
1193                              const void *payload, size_t payload_size)
1194 {
1195   size_t used = payload_size + sizeof (struct EncryptedMessage);
1196   char pbuf[used];              /* plaintext */
1197   char cbuf[used];              /* ciphertext */
1198   struct EncryptedMessage *em;  /* encrypted message */
1199   struct EncryptedMessage *ph;  /* plaintext header */
1200   struct GNUNET_CRYPTO_AesInitializationVector iv;
1201   struct GNUNET_CRYPTO_AuthKey auth_key;
1202
1203   ph = (struct EncryptedMessage *) pbuf;
1204   ph->iv_seed =
1205       htonl (GNUNET_CRYPTO_random_u32
1206              (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
1207   ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1208   ph->reserved = 0;
1209   ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1210   memcpy (&ph[1], payload, payload_size);
1211
1212   em = (struct EncryptedMessage *) cbuf;
1213   em->header.size = htons (used);
1214   em->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
1215   em->iv_seed = ph->iv_seed;
1216   derive_iv (&iv, &kx->encrypt_key, ph->iv_seed, &kx->peer);
1217   GNUNET_assert (GNUNET_OK ==
1218                  do_encrypt (kx, &iv, &ph->sequence_number,
1219                              &em->sequence_number,
1220                              used - ENCRYPTED_HEADER_SIZE));
1221   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted %u bytes for %s\n",
1222               used - ENCRYPTED_HEADER_SIZE, GNUNET_i2s (&kx->peer));
1223   derive_auth_key (&auth_key, 
1224                    &kx->encrypt_key, 
1225                    ph->iv_seed);
1226   GNUNET_CRYPTO_hmac (&auth_key, &em->sequence_number,
1227                       used - ENCRYPTED_HEADER_SIZE, &em->hmac);
1228   GSC_NEIGHBOURS_transmit (&kx->peer, &em->header,
1229                            GNUNET_TIME_UNIT_FOREVER_REL);
1230 }
1231
1232
1233 /**
1234  * Closure for 'deliver_message'
1235  */
1236 struct DeliverMessageContext
1237 {
1238
1239   /**
1240    * Performance information for the connection.
1241    */
1242   const struct GNUNET_ATS_Information *atsi;
1243
1244   /**
1245    * Key exchange context.
1246    */
1247   struct GSC_KeyExchangeInfo *kx;
1248
1249   /**
1250    * Sender of the message.
1251    */
1252   const struct GNUNET_PeerIdentity *peer;
1253
1254   /**
1255    * Number of entries in 'atsi' array.
1256    */
1257   uint32_t atsi_count;
1258 };
1259
1260
1261 /**
1262  * We received an encrypted message.  Decrypt, validate and
1263  * pass on to the appropriate clients.
1264  *
1265  * @param kx key exchange context for encrypting the message
1266  * @param msg encrypted message
1267  * @param atsi performance data
1268  * @param atsi_count number of entries in ats (excluding 0-termination)
1269  */
1270 void
1271 GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx,
1272                                  const struct GNUNET_MessageHeader *msg,
1273                                  const struct GNUNET_ATS_Information *atsi,
1274                                  uint32_t atsi_count)
1275 {
1276   const struct EncryptedMessage *m;
1277   struct EncryptedMessage *pt;  /* plaintext */
1278   struct GNUNET_HashCode ph;
1279   uint32_t snum;
1280   struct GNUNET_TIME_Absolute t;
1281   struct GNUNET_CRYPTO_AesInitializationVector iv;
1282   struct GNUNET_CRYPTO_AuthKey auth_key;
1283   struct DeliverMessageContext dmc;
1284   uint16_t size = ntohs (msg->size);
1285   char buf[size] GNUNET_ALIGN;
1286
1287   if (size <
1288       sizeof (struct EncryptedMessage) + sizeof (struct GNUNET_MessageHeader))
1289   {
1290     GNUNET_break_op (0);
1291     return;
1292   }
1293   m = (const struct EncryptedMessage *) msg;
1294   if (kx->status != KX_STATE_UP)
1295   {
1296     GNUNET_STATISTICS_update (GSC_stats,
1297                               gettext_noop
1298                               ("# DATA message dropped (out of order)"),
1299                               1, GNUNET_NO);
1300     return;
1301   }
1302   if (0 == GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value)
1303   {
1304     GNUNET_STATISTICS_update (GSC_stats,
1305                               gettext_noop ("# sessions terminated by key expiration"),
1306                               1, GNUNET_NO);
1307     GSC_SESSIONS_end (&kx->peer);
1308     kx->status = KX_STATE_KEY_SENT;
1309     send_key (kx);
1310     return;
1311   }
1312
1313   /* validate hash */
1314   derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed);
1315   GNUNET_CRYPTO_hmac (&auth_key, &m->sequence_number,
1316                       size - ENCRYPTED_HEADER_SIZE, &ph);
1317   if (0 != memcmp (&ph, &m->hmac, sizeof (struct GNUNET_HashCode)))
1318   {
1319     /* checksum failed */
1320     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
1321                 "Failed checksum validation for a message from `%s'\n", 
1322                 GNUNET_i2s (&kx->peer));
1323     return;
1324   }
1325   derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1326   /* decrypt */
1327   if (GNUNET_OK !=
1328       do_decrypt (kx, &iv, &m->sequence_number, &buf[ENCRYPTED_HEADER_SIZE],
1329                   size - ENCRYPTED_HEADER_SIZE))
1330     return;
1331   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decrypted %u bytes from %s\n",
1332               size - ENCRYPTED_HEADER_SIZE, GNUNET_i2s (&kx->peer));
1333   pt = (struct EncryptedMessage *) buf;
1334
1335   /* validate sequence number */
1336   snum = ntohl (pt->sequence_number);
1337   if (kx->last_sequence_number_received == snum)
1338   {
1339     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1340                 "Received duplicate message, ignoring.\n");
1341     /* duplicate, ignore */
1342     GNUNET_STATISTICS_update (GSC_stats,
1343                               gettext_noop ("# bytes dropped (duplicates)"),
1344                               size, GNUNET_NO);
1345     return;
1346   }
1347   if ((kx->last_sequence_number_received > snum) &&
1348       (kx->last_sequence_number_received - snum > 32))
1349   {
1350     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1351                 "Received ancient out of sequence message, ignoring.\n");
1352     /* ancient out of sequence, ignore */
1353     GNUNET_STATISTICS_update (GSC_stats,
1354                               gettext_noop
1355                               ("# bytes dropped (out of sequence)"), size,
1356                               GNUNET_NO);
1357     return;
1358   }
1359   if (kx->last_sequence_number_received > snum)
1360   {
1361     unsigned int rotbit = 1 << (kx->last_sequence_number_received - snum - 1);
1362
1363     if ((kx->last_packets_bitmap & rotbit) != 0)
1364     {
1365       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1366                   "Received duplicate message, ignoring.\n");
1367       GNUNET_STATISTICS_update (GSC_stats,
1368                                 gettext_noop ("# bytes dropped (duplicates)"),
1369                                 size, GNUNET_NO);
1370       /* duplicate, ignore */
1371       return;
1372     }
1373     kx->last_packets_bitmap |= rotbit;
1374   }
1375   if (kx->last_sequence_number_received < snum)
1376   {
1377     unsigned int shift = (snum - kx->last_sequence_number_received);
1378
1379     if (shift >= 8 * sizeof (kx->last_packets_bitmap))
1380       kx->last_packets_bitmap = 0;
1381     else
1382       kx->last_packets_bitmap <<= shift;
1383     kx->last_sequence_number_received = snum;
1384   }
1385
1386   /* check timestamp */
1387   t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
1388   if (GNUNET_TIME_absolute_get_duration (t).rel_value >
1389       MAX_MESSAGE_AGE.rel_value)
1390   {
1391     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1392                 "Message received far too old (%s). Content ignored.\n",
1393                 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (t), GNUNET_YES));
1394     GNUNET_STATISTICS_update (GSC_stats,
1395                               gettext_noop
1396                               ("# bytes dropped (ancient message)"), size,
1397                               GNUNET_NO);
1398     return;
1399   }
1400
1401   /* process decrypted message(s) */
1402   update_timeout (kx);
1403   GNUNET_STATISTICS_update (GSC_stats,
1404                             gettext_noop ("# bytes of payload decrypted"),
1405                             size - sizeof (struct EncryptedMessage), GNUNET_NO);
1406   dmc.atsi = atsi;
1407   dmc.kx = kx;
1408   dmc.atsi_count = atsi_count;
1409   dmc.peer = &kx->peer;
1410   if (GNUNET_OK !=
1411       GNUNET_SERVER_mst_receive (mst, &dmc,
1412                                  &buf[sizeof (struct EncryptedMessage)],
1413                                  size - sizeof (struct EncryptedMessage),
1414                                  GNUNET_YES, GNUNET_NO))
1415     GNUNET_break_op (0);
1416 }
1417
1418
1419 /**
1420  * Deliver P2P message to interested clients.
1421  * Invokes send twice, once for clients that want the full message, and once
1422  * for clients that only want the header
1423  *
1424  * @param cls always NULL
1425  * @param client who sent us the message (struct GSC_KeyExchangeInfo)
1426  * @param m the message
1427  */
1428 static int
1429 deliver_message (void *cls, void *client, const struct GNUNET_MessageHeader *m)
1430 {
1431   struct DeliverMessageContext *dmc = client;
1432
1433   if (KX_STATE_UP != dmc->kx->status)
1434   {
1435     GNUNET_STATISTICS_update (GSC_stats,
1436                               gettext_noop
1437                               ("# PAYLOAD dropped (out of order)"),
1438                               1, GNUNET_NO);
1439     return GNUNET_OK;
1440   }
1441   switch (ntohs (m->type))
1442   {
1443   case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
1444   case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
1445     GSC_SESSIONS_set_typemap (dmc->peer, m);
1446     return GNUNET_OK;
1447   default:
1448     GSC_CLIENTS_deliver_message (dmc->peer, dmc->atsi, dmc->atsi_count, m,
1449                                  ntohs (m->size),
1450                                  GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
1451     GSC_CLIENTS_deliver_message (dmc->peer, dmc->atsi, dmc->atsi_count, m,
1452                                  sizeof (struct GNUNET_MessageHeader),
1453                                  GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
1454   }
1455   return GNUNET_OK;
1456 }
1457
1458
1459 /**
1460  * Setup the message that links the ephemeral key to our persistent
1461  * public key and generate the appropriate signature.
1462  */
1463 static void
1464 sign_ephemeral_key ()
1465 {
1466   current_ekm.header.size = htons (sizeof (struct EphemeralKeyMessage));
1467   current_ekm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY);
1468   current_ekm.sender_status = 0; /* to be set later */
1469   current_ekm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY);
1470   current_ekm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
1471                                     sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1472                                     sizeof (struct GNUNET_TIME_AbsoluteNBO) +
1473                                     sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded) +
1474                                     sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded));
1475   current_ekm.creation_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1476   current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_add (REKEY_FREQUENCY,
1477                                                                                                                        REKEY_TOLERANCE)));
1478   GNUNET_CRYPTO_ecc_key_get_public (my_ephemeral_key,
1479                                     &current_ekm.ephemeral_key);
1480   current_ekm.origin_public_key = my_public_key;
1481   GNUNET_assert (GNUNET_OK ==
1482                  GNUNET_CRYPTO_ecc_sign (my_private_key,
1483                                          &current_ekm.purpose,
1484                                          &current_ekm.signature));
1485 }
1486
1487
1488 /**
1489  * Task run to trigger rekeying.
1490  *
1491  * @param cls closure, NULL
1492  * @param tc scheduler context
1493  */
1494 static void
1495 do_rekey (void *cls,
1496           const struct GNUNET_SCHEDULER_TaskContext *tc)
1497 {
1498   struct GSC_KeyExchangeInfo *pos;
1499
1500   rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY,
1501                                              &do_rekey,
1502                                              NULL);
1503   if (NULL != my_ephemeral_key)
1504     GNUNET_CRYPTO_ecc_key_free (my_ephemeral_key);
1505   my_ephemeral_key = GNUNET_CRYPTO_ecc_key_create ();
1506   GNUNET_assert (NULL != my_ephemeral_key);
1507   sign_ephemeral_key ();
1508   for (pos = kx_head; NULL != pos; pos = pos->next)
1509   {
1510     pos->status = KX_STATE_REKEY_SENT;
1511     send_key (pos);
1512   }
1513 }
1514
1515
1516 /**
1517  * Initialize KX subsystem.
1518  *
1519  * @param pk private key to use for the peer
1520  * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1521  */
1522 int
1523 GSC_KX_init (struct GNUNET_CRYPTO_EccPrivateKey *pk)
1524 {
1525   GNUNET_assert (NULL != pk);
1526   my_private_key = pk;
1527   GNUNET_CRYPTO_ecc_key_get_public (my_private_key, &my_public_key);
1528   GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
1529                       &GSC_my_identity.hashPubKey);
1530   if (GNUNET_YES ==
1531       GNUNET_CONFIGURATION_get_value_yesno (GSC_cfg,
1532                                             "core",
1533                                             "USE_EPHEMERAL_KEYS"))
1534   {
1535     my_ephemeral_key = GNUNET_CRYPTO_ecc_key_create ();
1536     if (NULL == my_ephemeral_key)
1537     {
1538       GNUNET_break (0);
1539       GNUNET_CRYPTO_ecc_key_free (my_private_key);
1540       my_private_key = NULL;
1541       return GNUNET_SYSERR;
1542     }
1543     sign_ephemeral_key ();
1544     rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY,
1545                                                &do_rekey,
1546                                                NULL);
1547   }
1548   else
1549   {
1550     my_ephemeral_key = my_private_key;
1551     sign_ephemeral_key ();
1552   }
1553   mst = GNUNET_SERVER_mst_create (&deliver_message, NULL);
1554   return GNUNET_OK;
1555 }
1556
1557
1558 /**
1559  * Shutdown KX subsystem.
1560  */
1561 void
1562 GSC_KX_done ()
1563 {
1564   if (GNUNET_SCHEDULER_NO_TASK != rekey_task)
1565   {
1566     GNUNET_SCHEDULER_cancel (rekey_task);
1567     rekey_task = GNUNET_SCHEDULER_NO_TASK;
1568   }
1569   if ( (NULL != my_ephemeral_key) &&
1570        (my_ephemeral_key != my_private_key) )
1571   {
1572     GNUNET_CRYPTO_ecc_key_free (my_ephemeral_key);
1573     my_ephemeral_key = NULL;
1574   }
1575   if (NULL != my_private_key)
1576   {
1577     GNUNET_CRYPTO_ecc_key_free (my_private_key);
1578     my_private_key = NULL;
1579   }
1580   if (NULL != mst)
1581   {
1582     GNUNET_SERVER_mst_destroy (mst);
1583     mst = NULL;
1584   }
1585 }
1586
1587 /* end of gnunet-service-core_kx.c */