gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

gnunet-service-core_kx.c (96708B)


      1 /*
      2      This file is part of GNUnet.
      3      Copyright (C) 2009-2013, 2016, 2024-2026 GNUnet e.V.
      4 
      5      GNUnet is free software: you can redistribute it and/or modify it
      6      under the terms of the GNU Affero General Public License as published
      7      by the Free Software Foundation, either version 3 of the License,
      8      or (at your option) any later version.
      9 
     10      GNUnet is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      Affero General Public License for more details.
     14 
     15      You should have received a copy of the GNU Affero General Public License
     16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18      SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 
     21 /**
     22  * TODO:
     23  *  - We need to implement a rekey (+ACK) that periodically rekeys.
     24  *  - We may want to reintroduce a heartbeat that needs to be ACKed. Maybe use / merge
     25  *    with KeyUpdate message. It already contains an update_requested field.
     26  *    Maybe rename to Heartbeat and add key_updated field to indicate a field update.
     27  *    That message then always MUST be Acked, if update_requested, then a Heartbeat is
     28  *    expected in response (w/o update_requested of course).
     29  */
     30 
     31 /**
     32  * @file core/gnunet-service-core_kx.c
     33  * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other
     34  * peers
     35  * @author Christian Grothoff, ch3
     36  */
     37 #include "gnunet_common.h"
     38 #include "gnunet_util_lib.h"
     39 #include "platform.h"
     40 #include "gnunet-service-core_kx.h"
     41 #include "gnunet_transport_core_service.h"
     42 #include "gnunet-service-core_sessions.h"
     43 #include "gnunet-service-core.h"
     44 #include "gnunet_constants.h"
     45 #include "gnunet_protocols.h"
     46 #include "gnunet_pils_service.h"
     47 
     48 /**
     49  * Enable expensive (and possibly problematic for privacy!) logging of KX.
     50  */
     51 #define DEBUG_KX 0
     52 
     53 /**
     54  * Number of times we try to resend a handshake flight.
     55  */
     56 #define RESEND_MAX_TRIES 4
     57 
     58 /**
     59  * libsodium has very long symbol names
     60  */
     61 #define AEAD_KEY_BYTES crypto_aead_xchacha20poly1305_ietf_KEYBYTES
     62 
     63 /**
     64  * libsodium has very long symbol names
     65  */
     66 #define AEAD_NONCE_BYTES crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
     67 
     68 /**
     69  * libsodium has very long symbol names
     70  */
     71 #define AEAD_TAG_BYTES crypto_aead_xchacha20poly1305_ietf_ABYTES
     72 
     73 #define RESEND_TIMEOUT \
     74         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
     75 
     76 /**
     77  * What is the minimum frequency for a heartbeat message?
     78  */
     79 #define MIN_HEARTBEAT_FREQUENCY \
     80         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
     81 
     82 /**
     83  * What is the minimum frequency for a HEARTBEAT message?
     84  */
     85 #define MIN_HEARTBEAT_FREQUENCY \
     86         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
     87 
     88 /**
     89  * How often do we send a heartbeat?
     90  */
     91 #define HEARTBEAT_FREQUENCY \
     92         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
     93 
     94 /**
     95  * Maximum number of epochs we keep on hand.
     96  * This implicitly defines the maximum age of
     97  * messages we accept from other peers, depending
     98  * on their rekey interval.
     99  */
    100 #define MAX_EPOCHS 10
    101 
    102 /**
    103  * How often do we rekey/switch to a new epoch?
    104  */
    105 #define EPOCH_EXPIRATION \
    106         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
    107 
    108 /**
    109  * What time difference do we tolerate?
    110  */
    111 #define REKEY_TOLERANCE \
    112         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
    113 
    114 /**
    115  * String for expanding early transport secret
    116  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    117  */
    118 #define EARLY_DATA_STR "early data"
    119 
    120 /**
    121  * String for expanding RHTS
    122  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    123  */
    124 #define R_HS_TRAFFIC_STR "r hs traffic"
    125 
    126 /**
    127  * String for expanding IHTS
    128  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    129  */
    130 #define I_HS_TRAFFIC_STR "i hs traffic"
    131 
    132 /**
    133  * String for expanding RATS
    134  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    135  */
    136 #define R_AP_TRAFFIC_STR "r ap traffic"
    137 
    138 /**
    139  * String for expanding IATS
    140  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    141  */
    142 #define I_AP_TRAFFIC_STR "i ap traffic"
    143 
    144 /**
    145  * String for expanding derived keys (Handshake and Early)
    146  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    147  */
    148 #define DERIVED_STR "derived"
    149 
    150 /**
    151  * String for expanding fk_R used for ResponderFinished field
    152  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    153  */
    154 #define R_FINISHED_STR "r finished"
    155 
    156 /**
    157  * String for expanding fk_I used for InitiatorFinished field
    158  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    159  */
    160 #define I_FINISHED_STR "i finished"
    161 
    162 /**
    163  * Labeled expand label for CAKE
    164  */
    165 #define CAKE_LABEL "cake10"
    166 
    167 /**
    168  * String for expanding derived keys (Handshake and Early)
    169  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    170  */
    171 #define KEY_STR "key"
    172 
    173 /**
    174  * String for expanding derived keys (Handshake and Early)
    175  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    176  */
    177 #define TRAFFIC_UPD_STR "traffic upd"
    178 
    179 /**
    180  * String for expanding derived keys (Handshake and Early)
    181  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    182  */
    183 #define IV_STR "iv"
    184 
    185 
    186 /**
    187  * Indicates whether a peer is in the initiating or receiving role.
    188  */
    189 enum GSC_KX_Role
    190 {
    191   /* Peer is supposed to initiate the key exchange */
    192   ROLE_INITIATOR = 0,
    193 
    194   /* Peer is supposed to wait for the key exchange */
    195   ROLE_RESPONDER = 1,
    196 };
    197 
    198 
    199 /**
    200  * Information about the status of a key exchange with another peer.
    201  */
    202 struct GSC_KeyExchangeInfo
    203 {
    204   /**
    205    * DLL.
    206    */
    207   struct GSC_KeyExchangeInfo *next;
    208 
    209   /**
    210    * DLL.
    211    */
    212   struct GSC_KeyExchangeInfo *prev;
    213 
    214   /**
    215    * Identity of the peer.
    216    */
    217   struct GNUNET_PeerIdentity peer;
    218 
    219   /**
    220    * Message queue for sending messages to @a peer.
    221    */
    222   struct GNUNET_MQ_Handle *mq;
    223 
    224   /**
    225    * Env for resending messages
    226    */
    227   struct GNUNET_MQ_Envelope *resend_env;
    228 
    229   /**
    230    * Our message stream tokenizer (for encrypted payload).
    231    */
    232   struct GNUNET_MessageStreamTokenizer *mst;
    233 
    234   // TODO check ordering - might make it less confusing
    235   // TODO consistent naming: ss_e, shared_secret_e or ephemeral_shared_secret?
    236   // TODO consider making all the structs here pointers
    237   //        - they can be checked to be NULL
    238   //        - valgrind can detect memory issues better (I guess?)
    239 
    240   /**
    241    * Own role in the key exchange. Are we supposed to initiate or receive the
    242    * handshake?
    243    */
    244   enum GSC_KX_Role role;
    245 
    246   // TODO
    247   struct GNUNET_ShortHashCode ss_R;
    248   struct GNUNET_ShortHashCode ss_e;
    249   struct GNUNET_ShortHashCode ss_I;
    250 
    251   /**
    252    * Initiator secret key
    253    */
    254   struct GNUNET_CRYPTO_HpkePrivateKey sk_e;
    255 
    256   /**
    257    * Initiator ephemeral key
    258    */
    259   struct GNUNET_CRYPTO_HpkePublicKey pk_e;
    260 
    261   /**
    262    * The transcript hash context.
    263    * It is fed data from the handshake to be implicitly validated and used to
    264    * derive key material.
    265    */
    266   struct GNUNET_HashContext *transcript_hash_ctx;
    267 
    268   /**
    269    * ES - Early Secret Key
    270    * TODO uniform naming: _key?
    271    */
    272   struct GNUNET_ShortHashCode early_secret_key;
    273 
    274   /**
    275    * ETS - Early traffic secret
    276    * TODO
    277    */
    278   struct GNUNET_ShortHashCode early_traffic_secret; /* Decrypts InitiatorHello */
    279 
    280   /**
    281    * HS - Handshake secret
    282    * TODO
    283    */
    284   struct GNUNET_ShortHashCode handshake_secret;
    285 
    286   /**
    287    * RHTS - Responder handshake secret
    288    * TODO
    289    */
    290   struct GNUNET_ShortHashCode rhts;
    291 
    292   /**
    293    * IHTS - Initiator handshake secret
    294    * TODO
    295    */
    296   struct GNUNET_ShortHashCode ihts;
    297 
    298   /**
    299    * Master secret key
    300    * TODO
    301    */
    302   struct GNUNET_ShortHashCode master_secret;
    303 
    304   /**
    305    * *ATS - our current application traffic secret by epoch
    306    */
    307   struct GNUNET_ShortHashCode current_ats;
    308 
    309   /**
    310    * *ATS - other peers application traffic secret by epoch
    311    */
    312   struct GNUNET_ShortHashCode their_ats[MAX_EPOCHS];
    313 
    314   /**
    315    * Our currently used epoch for sending.
    316    */
    317   uint64_t current_epoch;
    318 
    319   /**
    320    * Expiration time of our current epoch
    321    */
    322   struct GNUNET_TIME_Absolute current_epoch_expiration;
    323 
    324   /**
    325    * Highest seen (or used) epoch of
    326    * responder resp initiator..
    327    */
    328   uint64_t their_max_epoch;
    329 
    330   /**
    331    * Our current sequence number
    332    */
    333   uint64_t current_sqn;
    334 
    335   /**
    336    * When should the session time out (if there are no Acks to HEARTBEATs)?
    337    */
    338   struct GNUNET_TIME_Absolute timeout;
    339 
    340   /**
    341    * Last time we notified monitors
    342    */
    343   struct GNUNET_TIME_Absolute last_notify_timeout;
    344 
    345   /**
    346    * Task for resending messages during handshake.
    347    */
    348   struct GNUNET_SCHEDULER_Task *resend_task;
    349 
    350   /**
    351    * Resend tries left
    352    */
    353   unsigned int resend_tries_left;
    354 
    355   /**
    356    * ID of task used for sending keep-alive pings.
    357    * TODO still needed?
    358    */
    359   struct GNUNET_SCHEDULER_Task *heartbeat_task;
    360 
    361   /**
    362    * #GNUNET_YES if this peer currently has excess bandwidth.
    363    * TODO still needed?
    364    */
    365   int has_excess_bandwidth;
    366 
    367   /**
    368    * What is our connection state?
    369    */
    370   enum GNUNET_CORE_KxState status;
    371 
    372   /**
    373    * Peer class of the other peer
    374    * TODO still needed?
    375    */
    376   enum GNUNET_CORE_PeerClass class;
    377 
    378 };
    379 
    380 /**
    381  * DLL
    382  */
    383 struct PilsRequest
    384 {
    385   /**
    386    * DLL
    387    */
    388   struct PilsRequest *prev;
    389 
    390   /**
    391    * DLL
    392    */
    393   struct PilsRequest *next;
    394 
    395   /**
    396    * The pils operation
    397    */
    398   struct GNUNET_PILS_Operation *op;
    399 };
    400 
    401 /**
    402  * PILS Operation DLL
    403  */
    404 static struct PilsRequest *pils_requests_head;
    405 
    406 /**
    407  * PILS Operation DLL
    408  */
    409 static struct PilsRequest *pils_requests_tail;
    410 
    411 
    412 /**
    413  * Transport service.
    414  */
    415 static struct GNUNET_TRANSPORT_CoreHandle *transport;
    416 
    417 /**
    418  * DLL head.
    419  */
    420 static struct GSC_KeyExchangeInfo *kx_head;
    421 
    422 /**
    423  * DLL tail.
    424  */
    425 static struct GSC_KeyExchangeInfo *kx_tail;
    426 
    427 /**
    428  * Task scheduled for periodic re-generation (and thus rekeying) of our
    429  * ephemeral key.
    430  */
    431 static struct GNUNET_SCHEDULER_Task *rekey_task;
    432 
    433 /**
    434  * Notification context for broadcasting to monitors.
    435  */
    436 static struct GNUNET_NotificationContext *nc;
    437 
    438 /**
    439  * Our services info string TODO
    440  */
    441 static char *my_services_info = "";
    442 
    443 static void
    444 buffer_clear (void *buf, size_t len)
    445 {
    446 #if HAVE_MEMSET_S
    447   memset_s (buf, len, 0, len);
    448 #elif HAVE_EXPLICIT_BZERO
    449   explicit_bzero (buf, len);
    450 #else
    451   volatile unsigned char *p = buf;
    452   while (len--)
    453     *p++ = 0;
    454 #endif
    455 }
    456 
    457 
    458 static void
    459 cleanup_handshake_secrets (struct GSC_KeyExchangeInfo *kx)
    460 {
    461   buffer_clear (&kx->ihts,
    462                 sizeof kx->ihts);
    463   buffer_clear (&kx->rhts,
    464                 sizeof kx->rhts);
    465   buffer_clear (&kx->sk_e,
    466                 sizeof kx->sk_e);
    467   buffer_clear (&kx->ss_I,
    468                 sizeof kx->ss_I);
    469   buffer_clear (&kx->ss_R,
    470                 sizeof kx->ss_R);
    471   buffer_clear (&kx->ss_e,
    472                 sizeof kx->ss_e);
    473   buffer_clear (&kx->master_secret,
    474                 sizeof kx->master_secret);
    475   buffer_clear (&kx->early_secret_key,
    476                 sizeof kx->early_secret_key);
    477   buffer_clear (&kx->early_traffic_secret,
    478                 sizeof kx->early_traffic_secret);
    479   buffer_clear (&kx->handshake_secret,
    480                 sizeof kx->handshake_secret);
    481 }
    482 
    483 
    484 static void
    485 snapshot_transcript (const struct GNUNET_HashContext *ts_hash,
    486                      struct GNUNET_HashCode *snapshot)
    487 {
    488   struct GNUNET_HashContext *tmp;
    489 
    490   tmp = GNUNET_CRYPTO_hash_context_copy (ts_hash);
    491   GNUNET_CRYPTO_hash_context_finish (tmp, snapshot);
    492 }
    493 
    494 
    495 /**
    496  * Inform all monitors about the KX state of the given peer.
    497  *
    498  * @param kx key exchange state to inform about
    499  */
    500 static void
    501 monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
    502 {
    503   struct MonitorNotifyMessage msg;
    504 
    505   msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
    506   msg.header.size = htons (sizeof(msg));
    507   msg.state = htonl ((uint32_t) kx->status);
    508   msg.peer = kx->peer;
    509   msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
    510   GNUNET_notification_context_broadcast (nc, &msg.header, GNUNET_NO);
    511   kx->last_notify_timeout = kx->timeout;
    512 }
    513 
    514 
    515 static void
    516 restart_kx (struct GSC_KeyExchangeInfo *kx);
    517 
    518 /**
    519  * Task triggered when a neighbour entry is about to time out
    520  * (and we should prevent this by sending an Ack in response
    521  * to a heartbeat).
    522  *
    523  * @param cls the `struct GSC_KeyExchangeInfo`
    524  */
    525 static void
    526 send_heartbeat (void *cls)
    527 {
    528   struct GSC_KeyExchangeInfo *kx = cls;
    529   struct GNUNET_TIME_Relative retry;
    530   struct GNUNET_TIME_Relative left;
    531   struct Heartbeat hb;
    532 
    533   kx->heartbeat_task = NULL;
    534   left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
    535   if (0 == left.rel_value_us)
    536   {
    537     GNUNET_STATISTICS_update (GSC_stats,
    538                               gettext_noop ("# sessions terminated by timeout"),
    539                               1,
    540                               GNUNET_NO);
    541     GSC_SESSIONS_end (&kx->peer);
    542     kx->status = GNUNET_CORE_KX_STATE_DOWN;
    543     monitor_notify_all (kx);
    544     restart_kx (kx);
    545     return;
    546   }
    547   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    548               "Sending HEARTBEAT to `%s'\n",
    549               GNUNET_i2s (&kx->peer));
    550   GNUNET_STATISTICS_update (GSC_stats,
    551                             gettext_noop ("# heartbeat messages sent"),
    552                             1,
    553                             GNUNET_NO);
    554   hb.header.type =  htons (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT);
    555   hb.header.size = htons (sizeof hb);
    556   // FIXME when do we request update?
    557   hb.flags = 0;
    558   GSC_KX_encrypt_and_transmit (kx, &hb, sizeof hb);
    559   retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
    560                                     MIN_HEARTBEAT_FREQUENCY);
    561   kx->heartbeat_task =
    562     GNUNET_SCHEDULER_add_delayed (retry, &send_heartbeat, kx);
    563 }
    564 
    565 
    566 /**
    567  * We've seen a valid message from the other peer.
    568  * Update the time when the session would time out
    569  * and delay sending our keep alive message further.
    570  *
    571  * @param kx key exchange where we saw activity
    572  */
    573 static void
    574 update_timeout (struct GSC_KeyExchangeInfo *kx)
    575 {
    576   struct GNUNET_TIME_Relative delta;
    577 
    578   kx->timeout =
    579     GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
    580   delta =
    581     GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout, kx->timeout);
    582   if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
    583   {
    584     /* we only notify monitors about timeout changes if those
    585        are bigger than the threshold (5s) */
    586     monitor_notify_all (kx);
    587   }
    588   if (NULL != kx->heartbeat_task)
    589     GNUNET_SCHEDULER_cancel (kx->heartbeat_task);
    590   kx->heartbeat_task = GNUNET_SCHEDULER_add_delayed (
    591     GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
    592     &send_heartbeat,
    593     kx);
    594 }
    595 
    596 
    597 /**
    598  * Send initiator hello
    599  *
    600  * @param kx key exchange context
    601  */
    602 static void
    603 send_initiator_hello (struct GSC_KeyExchangeInfo *kx);
    604 
    605 
    606 /**
    607  * Deliver P2P message to interested clients.  Invokes send twice,
    608  * once for clients that want the full message, and once for clients
    609  * that only want the header
    610  *
    611  * @param cls the `struct GSC_KeyExchangeInfo`
    612  * @param m the message
    613  * @return #GNUNET_OK on success,
    614  *    #GNUNET_NO to stop further processing (no error)
    615  *    #GNUNET_SYSERR to stop further processing with error
    616  */
    617 static int
    618 deliver_message (void *cls, const struct GNUNET_MessageHeader *m)
    619 {
    620   struct GSC_KeyExchangeInfo *kx = cls;
    621 
    622   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    623               "Decrypted message of type %d from %s\n",
    624               ntohs (m->type),
    625               GNUNET_i2s (&kx->peer));
    626   GSC_CLIENTS_deliver_message (&kx->peer,
    627                                m,
    628                                ntohs (m->size),
    629                                GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
    630   GSC_CLIENTS_deliver_message (&kx->peer,
    631                                m,
    632                                sizeof(struct GNUNET_MessageHeader),
    633                                GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
    634   return GNUNET_OK;
    635 }
    636 
    637 
    638 static void
    639 restart_kx (struct GSC_KeyExchangeInfo *kx)
    640 {
    641   const struct GNUNET_HashCode *my_identity_hash;
    642   struct GNUNET_HashCode h1;
    643 
    644   // TODO what happens if we're in the middle of a peer id change?
    645   // TODO there's a small chance this gets already called when we don't have a
    646   // peer id yet. Add a kx, insert into the list, mark it as to be completed
    647   // and let the callback to pils finish the rest once we got the peer id
    648 
    649   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    650               "Initiating key exchange with peer %s\n",
    651               GNUNET_i2s (&kx->peer));
    652   GNUNET_STATISTICS_update (GSC_stats,
    653                             gettext_noop ("# key exchanges initiated"),
    654                             1,
    655                             GNUNET_NO);
    656 
    657   monitor_notify_all (kx);
    658   my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils);
    659   GNUNET_assert (NULL != my_identity_hash);
    660   GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1);
    661   if (NULL != kx->transcript_hash_ctx)
    662     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
    663   kx->transcript_hash_ctx = NULL;
    664   if (0 < GNUNET_CRYPTO_hash_cmp (&h1, my_identity_hash))
    665   {
    666     /* peer with "lower" identity starts KX, otherwise we typically end up
    667        with both peers starting the exchange and transmit the 'set key'
    668        message twice */
    669     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    670                 "I am the initiator, sending hello\n");
    671     kx->role = ROLE_INITIATOR;
    672     send_initiator_hello (kx);
    673   }
    674   else
    675   {
    676     /* peer with "higher" identity starts a delayed KX, if the "lower" peer
    677      * does not start a KX since it sees no reasons to do so  */
    678     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    679                 "I am the responder, yielding and await initiator hello\n");
    680     kx->status = GNUNET_CORE_KX_STATE_AWAIT_INITIATION;
    681     kx->role = ROLE_RESPONDER;
    682     monitor_notify_all (kx);
    683   }
    684 }
    685 
    686 
    687 /**
    688  * Function called by transport to notify us that
    689  * a peer connected to us (on the network level).
    690  * Starts the key exchange with the given peer.
    691  *
    692  * @param cls closure (NULL)
    693  * @param mq message queue towards peer
    694  * @param peer_id (optional, may be NULL) the peer id of the connecting peer
    695  * @return key exchange information context
    696  */
    697 static void *
    698 handle_transport_notify_connect (void *cls,
    699                                  const struct GNUNET_PeerIdentity *peer_id,
    700                                  struct GNUNET_MQ_Handle *mq)
    701 {
    702   const struct GNUNET_PeerIdentity *my_identity;
    703   struct GSC_KeyExchangeInfo *kx;
    704   (void) cls;
    705   my_identity = GNUNET_PILS_get_identity (GSC_pils);
    706   GNUNET_assert (NULL != my_identity);
    707   if (0 == memcmp (peer_id, my_identity, sizeof *peer_id))
    708   {
    709     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    710                 "Ignoring connection to self\n");
    711     return NULL;
    712   }
    713   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    714               "Incoming connection of peer with %s\n",
    715               GNUNET_i2s (peer_id));
    716 
    717   /* Set up kx struct */
    718   kx = GNUNET_new (struct GSC_KeyExchangeInfo);
    719   kx->mst = GNUNET_MST_create (&deliver_message, kx);
    720   kx->mq = mq;
    721   GNUNET_memcpy (&kx->peer, peer_id, sizeof (struct GNUNET_PeerIdentity));
    722   GNUNET_CONTAINER_DLL_insert (kx_head, kx_tail, kx);
    723 
    724   restart_kx (kx);
    725   return kx;
    726 }
    727 
    728 
    729 /**
    730  * TODO
    731  * propose a new scheme: don't choose an initiator and responder based on
    732  * hashing the peer ids, but:
    733  * let each peer be their own initiator (and responder) when opening a channel
    734  * towards another peer. It should be fine to have two channels in 'both
    735  * directions' (one as responder, one as initiator) under the hood. This can be
    736  * opaque to the upper layers.
    737  * FIXME: (MSC) This is probably a bad idea in terms of security of the AKE!
    738  */
    739 
    740 /**
    741  * Schedule for
    742  *  - forwarding the transcript hash context and
    743  *  - deriving/generating keys/finished fields
    744  *
    745  * Forwarding:                   Deriving               Messages
    746  * -> pk_e
    747  * -> c_R
    748  * -> r_I
    749  * -> H(pk_R)
    750  *                               -> ETS
    751  * -> {pk_I, svcinfo_I}ETS
    752  * ---------------------------------------------------- send InitiatorHello
    753  * -> c_e
    754  * -> r_R
    755  *                               -> *HTS
    756  * -> {svcinfo_R, c_I}RHTS
    757  *                               -> finished_R
    758  * -> {finished_R}RHTS
    759  *                               -> finished_I
    760  *                               -> RATS_0
    761  * -> [{payload}RATS]
    762  * ---------------------------------------------------- send ResponderHello
    763  * -> {finished_I}IHTS
    764  *                               -> IATS_0
    765  * ---------------------------------------------------- send InitiatorDone
    766  */
    767 
    768 // TODO find a way to assert that a key is not yet existing before generating
    769 // TODO find a way to assert that a key is not already existing before using
    770 /*
    771  * Derive early secret and transport secret.
    772  * @param kx the key exchange info
    773  */
    774 static void
    775 derive_es_ets (const struct GNUNET_HashCode *transcript,
    776                const struct GNUNET_ShortHashCode *ss_R,
    777                struct GNUNET_ShortHashCode *es,
    778                struct GNUNET_ShortHashCode *ets)
    779 {
    780   uint64_t ret;
    781 
    782   ret = GNUNET_CRYPTO_hkdf_extract (es, // prk
    783                                     0,                     // salt
    784                                     0,                     // salt_len
    785                                     ss_R,  // ikm - initial key material
    786                                     sizeof (*ss_R));
    787   if (GNUNET_OK != ret)
    788   {
    789     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting ES\n")
    790     ;
    791     GNUNET_assert (0);
    792   }
    793   ret = GNUNET_CRYPTO_hkdf_expand (
    794     ets,
    795     sizeof (*ets),
    796     es,
    797     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
    798     GNUNET_CRYPTO_kdf_arg_string (EARLY_DATA_STR),
    799     GNUNET_CRYPTO_kdf_arg_auto (transcript));
    800   if (GNUNET_OK != ret)
    801   {
    802     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding ETS\n")
    803     ;
    804     GNUNET_assert (0);
    805   }
    806 }
    807 
    808 
    809 /*
    810  * Derive early secret and transport secret.
    811  * @param kx the key exchange info
    812  */
    813 static void
    814 derive_sn (const struct GNUNET_ShortHashCode *secret,
    815            unsigned char*sn,
    816            size_t sn_len)
    817 {
    818   GNUNET_assert (GNUNET_OK ==
    819                  GNUNET_CRYPTO_hkdf_expand (
    820                    sn,
    821                    sn_len,
    822                    secret,
    823                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
    824                    GNUNET_CRYPTO_kdf_arg_string ("sn")));
    825 }
    826 
    827 
    828 /**
    829  * Derive the handshake secret
    830  * @param kx key exchange info
    831  */
    832 static void
    833 derive_hs (const struct GNUNET_ShortHashCode *es,
    834            const struct GNUNET_ShortHashCode *ss_e,
    835            struct GNUNET_ShortHashCode *handshake_secret)
    836 {
    837   uint64_t ret;
    838   struct GNUNET_ShortHashCode derived_early_secret;
    839 
    840   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deriving HS\n");
    841   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ES: %s\n", GNUNET_B2S (es)
    842               );
    843   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ss_e: %s\n", GNUNET_B2S (ss_e));
    844   ret = GNUNET_CRYPTO_hkdf_expand (
    845     &derived_early_secret,
    846     sizeof (derived_early_secret),
    847     es,
    848     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
    849     GNUNET_CRYPTO_kdf_arg_string (DERIVED_STR));
    850   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "dES: %s\n", GNUNET_B2S (&
    851                                                                 derived_early_secret));
    852   if (GNUNET_OK != ret)
    853   {
    854     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dES\n")
    855     ;
    856     GNUNET_assert (0);
    857   }
    858   // Handshake secret
    859   // TODO check: are dES the salt and ss_e the ikm or other way round?
    860   ret = GNUNET_CRYPTO_hkdf_extract (handshake_secret,     // prk
    861                                     &derived_early_secret,         // salt - dES
    862                                     sizeof (derived_early_secret), // salt_len
    863                                     ss_e,          // ikm - initial key material
    864                                     sizeof (*ss_e));
    865   if (GNUNET_OK != ret)
    866   {
    867     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting HS\n")
    868     ;
    869     GNUNET_assert (0);
    870   }
    871 }
    872 
    873 
    874 /**
    875  * Derive the initiator handshake secret
    876  * @param kx key exchange info
    877  */
    878 static void
    879 derive_ihts (const struct GNUNET_HashCode *transcript,
    880              const struct GNUNET_ShortHashCode *hs,
    881              struct GNUNET_ShortHashCode *ihts)
    882 {
    883   GNUNET_assert (GNUNET_OK ==
    884                  GNUNET_CRYPTO_hkdf_expand (
    885                    ihts,                                           // result
    886                    sizeof (*ihts),                          // result len
    887                    hs,                          // prk?
    888                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
    889                    GNUNET_CRYPTO_kdf_arg_string (I_HS_TRAFFIC_STR),
    890                    GNUNET_CRYPTO_kdf_arg_auto  (transcript)));
    891 }
    892 
    893 
    894 /**
    895  * Derive the responder handshake secret
    896  * @param kx key exchange info
    897  */
    898 static void
    899 derive_rhts (const struct GNUNET_HashCode *transcript,
    900              const struct GNUNET_ShortHashCode *hs,
    901              struct GNUNET_ShortHashCode *rhts)
    902 {
    903   GNUNET_assert (GNUNET_OK ==
    904                  GNUNET_CRYPTO_hkdf_expand (
    905                    rhts,
    906                    sizeof (*rhts),
    907                    hs,                          // prk? TODO
    908                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
    909                    GNUNET_CRYPTO_kdf_arg_string (R_HS_TRAFFIC_STR),
    910                    GNUNET_CRYPTO_kdf_arg_auto (transcript)));
    911 }
    912 
    913 
    914 /**
    915  * Derive the master secret
    916  * @param kx key exchange info
    917  */
    918 static void
    919 derive_ms (const struct GNUNET_ShortHashCode *hs,
    920            const struct GNUNET_ShortHashCode *ss_I,
    921            struct GNUNET_ShortHashCode *ms)
    922 {
    923   uint64_t ret;
    924   struct GNUNET_ShortHashCode derived_handshake_secret;
    925 
    926   ret = GNUNET_CRYPTO_hkdf_expand (
    927     &derived_handshake_secret,
    928     sizeof (derived_handshake_secret),
    929     hs,
    930     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
    931     GNUNET_CRYPTO_kdf_arg_string (DERIVED_STR));
    932   if (GNUNET_OK != ret)
    933   {
    934     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dHS\n")
    935     ;
    936     GNUNET_assert (0);
    937   }
    938   // TODO check: are dHS the salt and ss_I the ikm or other way round?
    939   ret = GNUNET_CRYPTO_hkdf_extract (ms,            // prk
    940                                     &derived_handshake_secret,         // salt - dHS
    941                                     sizeof (derived_handshake_secret), // salt_len
    942                                     ss_I,              // ikm - initial key material
    943                                     sizeof (*ss_I));
    944   if (GNUNET_OK != ret)
    945   {
    946     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting MS\n")
    947     ;
    948     GNUNET_assert (0);
    949   }
    950 }
    951 
    952 
    953 /**
    954  * Generate per record nonce as per
    955  * https://www.rfc-editor.org/rfc/rfc8446#section-5.3
    956  * using per key nonce and sequence number
    957  */
    958 static void
    959 generate_per_record_nonce (
    960   uint64_t seq,
    961   const uint8_t write_iv[AEAD_NONCE_BYTES],
    962   uint8_t per_record_write_iv[AEAD_NONCE_BYTES])
    963 {
    964   uint64_t seq_nbo;
    965   uint64_t *write_iv_ptr;
    966   unsigned int byte_offset;
    967 
    968   seq_nbo = GNUNET_htonll (seq);
    969   memcpy (per_record_write_iv,
    970           write_iv,
    971           AEAD_NONCE_BYTES);
    972   byte_offset =
    973     AEAD_NONCE_BYTES - sizeof (uint64_t);
    974   write_iv_ptr = (uint64_t*) (write_iv + byte_offset);
    975   *write_iv_ptr ^= seq_nbo;
    976 }
    977 
    978 
    979 /**
    980  * key = HKDF-Expand [I,R][A,H]TS, "key", 32)
    981  * nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 24)
    982  */
    983 static void
    984 derive_per_message_secrets (
    985   const struct GNUNET_ShortHashCode *ts,
    986   uint64_t seq,
    987   unsigned char key[AEAD_KEY_BYTES],
    988   unsigned char nonce[AEAD_NONCE_BYTES])
    989 {
    990   unsigned char nonce_tmp[AEAD_NONCE_BYTES];
    991   /* derive actual key */
    992   GNUNET_assert (GNUNET_OK ==
    993                  GNUNET_CRYPTO_hkdf_expand (
    994                    key,
    995                    AEAD_KEY_BYTES,
    996                    ts,
    997                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
    998                    GNUNET_CRYPTO_kdf_arg_string (KEY_STR)));
    999 
   1000   /* derive nonce */
   1001   GNUNET_assert (GNUNET_OK ==
   1002                  GNUNET_CRYPTO_hkdf_expand (
   1003                    nonce_tmp,
   1004                    AEAD_NONCE_BYTES,
   1005                    ts,
   1006                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1007                    GNUNET_CRYPTO_kdf_arg_string (IV_STR)));
   1008   generate_per_record_nonce (seq,
   1009                              nonce_tmp,
   1010                              nonce);
   1011 }
   1012 
   1013 
   1014 /**
   1015  * Derive the next application secret
   1016  * @param kx key exchange info
   1017  */
   1018 static void
   1019 derive_next_ats (const struct GNUNET_ShortHashCode *old_ats,
   1020                  struct GNUNET_ShortHashCode *new_ats)
   1021 {
   1022   int8_t ret;
   1023 
   1024   // FIXME: Not sure of PRK and output may overlap here!
   1025   ret = GNUNET_CRYPTO_hkdf_expand (
   1026     new_ats,
   1027     sizeof (*new_ats),
   1028     old_ats,
   1029     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1030     GNUNET_CRYPTO_kdf_arg_string (TRAFFIC_UPD_STR));
   1031   if (GNUNET_OK != ret)
   1032   {
   1033     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1034                 "Something went wrong deriving next *ATS key\n");
   1035     GNUNET_assert (0);
   1036   }
   1037 }
   1038 
   1039 
   1040 /**
   1041  * Derive the initiator application secret
   1042  * @param kx key exchange info
   1043  */
   1044 static void
   1045 derive_initial_ats (const struct GNUNET_HashCode *transcript,
   1046                     const struct GNUNET_ShortHashCode *ms,
   1047                     enum GSC_KX_Role role,
   1048                     struct GNUNET_ShortHashCode *initial_ats)
   1049 {
   1050   const char *traffic_str;
   1051 
   1052   if (ROLE_INITIATOR == role)
   1053     traffic_str = I_AP_TRAFFIC_STR;
   1054   else
   1055     traffic_str = R_AP_TRAFFIC_STR;
   1056   GNUNET_assert (GNUNET_OK ==
   1057                  GNUNET_CRYPTO_hkdf_expand (
   1058                    initial_ats,                                           // result
   1059                    sizeof (*initial_ats),                          // result len
   1060                    ms,
   1061                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1062                    GNUNET_CRYPTO_kdf_arg_string (traffic_str),
   1063                    GNUNET_CRYPTO_kdf_arg_auto (transcript)));
   1064 }
   1065 
   1066 
   1067 /**
   1068  * Generate the responder finished field
   1069  * @param kx key exchange info
   1070  * @param result location to which the responder finished field will be written
   1071  *               to
   1072  */
   1073 static void
   1074 generate_responder_finished (const struct GNUNET_HashCode *transcript,
   1075                              const struct GNUNET_ShortHashCode *ms,
   1076                              struct GNUNET_HashCode *result)
   1077 {
   1078   enum GNUNET_GenericReturnValue ret;
   1079   struct GNUNET_CRYPTO_AuthKey fk_R; // We might want to save this in kx?
   1080 
   1081   ret = GNUNET_CRYPTO_hkdf_expand (
   1082     &fk_R,                                // result
   1083     sizeof (fk_R),
   1084     ms,
   1085     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1086     GNUNET_CRYPTO_kdf_arg_string (R_FINISHED_STR));
   1087   if (GNUNET_OK != ret)
   1088   {
   1089     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1090                 "Something went wrong expanding fk_R\n");
   1091     GNUNET_assert (0);
   1092   }
   1093 
   1094   GNUNET_CRYPTO_hmac (&fk_R,
   1095                       transcript,
   1096                       sizeof (*transcript),
   1097                       result);
   1098 }
   1099 
   1100 
   1101 /**
   1102  * Generate the initiator finished field
   1103  * @param kx key exchange info
   1104  * @param result location to which the initiator finished field will be written
   1105  *               to
   1106  */
   1107 static void
   1108 generate_initiator_finished (const struct GNUNET_HashCode *transcript,
   1109                              const struct GNUNET_ShortHashCode *ms,
   1110                              struct GNUNET_HashCode *result)
   1111 {
   1112   enum GNUNET_GenericReturnValue ret;
   1113   struct GNUNET_CRYPTO_AuthKey fk_I; // We might want to save this in kx?
   1114 
   1115   ret = GNUNET_CRYPTO_hkdf_expand (
   1116     &fk_I,                                      // result
   1117     sizeof (fk_I),
   1118     ms,
   1119     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1120     GNUNET_CRYPTO_kdf_arg_string (I_FINISHED_STR));
   1121   if (GNUNET_OK != ret)
   1122   {
   1123     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1124                 "Something went wrong expanding fk_I\n");
   1125     GNUNET_assert (0);
   1126   }
   1127   GNUNET_CRYPTO_hmac (&fk_I,
   1128                       transcript,
   1129                       sizeof (*transcript),
   1130                       result);
   1131 }
   1132 
   1133 
   1134 struct InitiatorHelloCtx
   1135 {
   1136   struct GSC_KeyExchangeInfo *kx;
   1137   struct InitiatorHello *ihm_e;
   1138   struct PilsRequest *req;
   1139 };
   1140 
   1141 static void
   1142 resend_responder_hello (void *cls)
   1143 {
   1144   struct GSC_KeyExchangeInfo *kx = cls;
   1145 
   1146   kx->resend_task = NULL;
   1147   if (0 == kx->resend_tries_left)
   1148   {
   1149     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1150                 "Restarting KX\n");
   1151     restart_kx (kx);
   1152     return;
   1153   }
   1154   kx->resend_tries_left--;
   1155   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1156               "Resending responder hello. Retries left: %u\n",
   1157               kx->resend_tries_left);
   1158   GNUNET_MQ_send_copy (kx->mq, kx->resend_env);
   1159   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   1160                                                   &resend_responder_hello,
   1161                                                   kx);
   1162 }
   1163 
   1164 
   1165 void
   1166 send_responder_hello (struct GSC_KeyExchangeInfo *kx)
   1167 {
   1168   enum GNUNET_GenericReturnValue ret;
   1169   struct GNUNET_CRYPTO_HpkeEncapsulation c_I;
   1170   struct ResponderHello *rhm_e; /* responder hello message - encrypted pointer */
   1171   struct GNUNET_MQ_Envelope *env;
   1172   struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_kem_challenge;
   1173   struct GNUNET_ShortHashCode rhts;
   1174   struct GNUNET_ShortHashCode ihts;
   1175   struct GNUNET_ShortHashCode hs;
   1176   struct GNUNET_ShortHashCode ms;
   1177   struct GNUNET_ShortHashCode ss_e;
   1178   struct GNUNET_ShortHashCode ss_I;
   1179   struct GNUNET_HashContext *hc;
   1180   unsigned char enc_key[AEAD_KEY_BYTES];
   1181   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   1182 
   1183   //      4. encaps -> shared_secret_e, c_e (kemChallenge)
   1184   //         TODO potentially write this directly into rhm?
   1185   ret = GNUNET_CRYPTO_hpke_kem_encaps (&kx->pk_e, // public ephemeral key of initiator
   1186                                        &ephemeral_kem_challenge,    // encapsulated key
   1187                                        &ss_e); // key - ss_e
   1188   if (GNUNET_OK != ret)
   1189   {
   1190     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1191                 "Something went wrong encapsulating ss_e\n");
   1192     return;
   1193   }
   1194   hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx);
   1195   //      6. encaps -> shared_secret_I, c_I
   1196   ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public key of I
   1197                                         &c_I,                              // encapsulated key
   1198                                         &ss_I);             // where to write the key material
   1199   if (GNUNET_OK != ret)
   1200   {
   1201     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1202                 "Something went wrong encapsulating ss_I\n");
   1203     GNUNET_CRYPTO_hash_context_abort (hc);
   1204     return;
   1205   }
   1206   //      7. generate RHTS (responder_handshare_secret_key) and RATS (responder_application_traffic_secret_key) (section 5)
   1207   {
   1208     struct GNUNET_HashCode transcript;
   1209     snapshot_transcript (hc, &transcript);
   1210 #if DEBUG_KX
   1211     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1212                 "Transcript snapshot for derivation of HS, MS: `%s'\n",
   1213                 GNUNET_h2s (&transcript));
   1214 #endif
   1215     derive_hs (&kx->early_secret_key,
   1216                &ss_e,
   1217                &hs);
   1218     derive_ms (&hs, &ss_I, &ms);
   1219   }
   1220 
   1221   // send ResponderHello
   1222   // TODO fill fields / services_info!
   1223   // 1. r_R <- random
   1224   struct ResponderHelloPayload *rhp;
   1225   size_t rhp_len = sizeof (*rhp) + strlen (my_services_info);
   1226   unsigned char rhp_buf[rhp_len];
   1227   size_t ct_len;
   1228 
   1229   rhp = (struct ResponderHelloPayload*) rhp_buf;
   1230   ct_len = rhp_len // ResponderHelloPayload, fist PT msg
   1231            + sizeof (struct GNUNET_HashCode) // Finished hash, second PT msg
   1232            + AEAD_TAG_BYTES * 2; // Two tags;
   1233   env = GNUNET_MQ_msg_extra (rhm_e,
   1234                              ct_len,
   1235                              GNUNET_MESSAGE_TYPE_CORE_RESPONDER_HELLO);
   1236 
   1237   rhm_e->r_R =
   1238     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
   1239                               UINT64_MAX);
   1240 
   1241   // c_e
   1242   GNUNET_memcpy (&rhm_e->c_e,
   1243                  &ephemeral_kem_challenge,
   1244                  sizeof (ephemeral_kem_challenge));
   1245   GNUNET_CRYPTO_hash_context_read (hc,
   1246                                    rhm_e,
   1247                                    sizeof (struct ResponderHello));
   1248   // 2. Encrypt ServicesInfo and c_I with RHTS
   1249   // derive RHTS
   1250   {
   1251     struct GNUNET_HashCode transcript;
   1252     snapshot_transcript (hc,
   1253                          &transcript);
   1254 #if DEBUG_KX
   1255     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1256                 "Transcript snapshot for derivation of *HTS: `%s'\n",
   1257                 GNUNET_h2s (&transcript));
   1258 #endif
   1259     derive_rhts (&transcript,
   1260                  &hs,
   1261                  &rhts);
   1262     derive_ihts (&transcript,
   1263                  &hs,
   1264                  &ihts);
   1265     derive_per_message_secrets (&rhts,
   1266                                 0,
   1267                                 enc_key,
   1268                                 enc_nonce);
   1269   }
   1270   // c_I
   1271   GNUNET_memcpy (&rhp->c_I, &c_I, sizeof (c_I));
   1272   // Services info empty for now.
   1273   GNUNET_memcpy (&rhp[1],
   1274                  my_services_info,
   1275                  strlen (my_services_info));
   1276 
   1277   {
   1278     unsigned long long out_ct_len;
   1279     struct GNUNET_HashCode finished;
   1280     struct GNUNET_HashCode transcript;
   1281     unsigned char *finished_buf;
   1282     GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1283                      (unsigned char*) &rhm_e[1], /* c - ciphertext */
   1284                      &out_ct_len, /* clen_p */
   1285                      rhp_buf, /* rhm_p - plaintext message */
   1286                      rhp_len, // mlen
   1287                      NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1288                               // fields?
   1289                      NULL, // nsec - unused
   1290                      enc_nonce, // npub - nonce // FIXME nonce can be reused
   1291                      enc_key)); // k - key RHTS
   1292     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1293                 "Encrypted and wrote %llu bytes\n",
   1294                 out_ct_len);
   1295     // 3. Create ResponderFinished (Section 6)
   1296     // Derive fk_I <- HKDF-Expand (MS, "r finished", NULL)
   1297     /* Forward the transcript */
   1298     /* {svcinfo, c_I}RHTS */
   1299     GNUNET_CRYPTO_hash_context_read (
   1300       hc,
   1301       &rhm_e[1],
   1302       out_ct_len);
   1303 
   1304     finished_buf = ((unsigned char*) &rhm_e[1]) + out_ct_len;
   1305     snapshot_transcript (hc,
   1306                          &transcript);
   1307 #if DEBUG_KX
   1308     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1309                 "Transcript snapshot for derivation of Rfinished: `%s'\n",
   1310                 GNUNET_h2s (&transcript));
   1311 #endif
   1312     generate_responder_finished (&transcript,
   1313                                  &ms,
   1314                                  &finished);
   1315     // 4. Encrypt ResponderFinished
   1316     derive_per_message_secrets (&rhts,
   1317                                 1,
   1318                                 enc_key,
   1319                                 enc_nonce);
   1320     GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1321                      finished_buf,                               /* c - ciphertext */
   1322                      &out_ct_len, /* clen_p */
   1323                      (unsigned char*) &finished, /* rhm_p - plaintext message */
   1324                      sizeof (finished), // mlen
   1325                      NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1326                               // fields?
   1327                      NULL, // nsec - unused
   1328                      enc_nonce, // npub
   1329                      enc_key)); // k - key RHTS
   1330     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1331                 "Encrypted and wrote %llu bytes\n",
   1332                 out_ct_len);
   1333     /* Forward the transcript
   1334      * after responder finished,
   1335      * before deriving *ATS and generating finished_I
   1336      * (finished_I will be generated when receiving the InitiatorFinished message
   1337      * in order to check it) */
   1338     GNUNET_CRYPTO_hash_context_read (
   1339       hc,
   1340       finished_buf,
   1341       out_ct_len);
   1342     // 5. optionally send application data - encrypted with RATS
   1343     // We do not really have any application data, instead, we send the ACK
   1344     snapshot_transcript (hc,
   1345                          &transcript);
   1346 #if DEBUG_KX
   1347     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1348                 "Transcript snapshot for derivation of *ATS: `%s'\n",
   1349                 GNUNET_h2s (&transcript));
   1350 #endif
   1351     derive_initial_ats (&transcript,
   1352                         &ms,
   1353                         ROLE_RESPONDER,
   1354                         &kx->current_ats);
   1355   }
   1356   /* Lock into struct */
   1357   GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1358   kx->transcript_hash_ctx = hc;
   1359   kx->master_secret = ms;
   1360   kx->handshake_secret = hs;
   1361   kx->ss_e = ss_e;
   1362   kx->ihts = ihts;
   1363   kx->rhts = rhts;
   1364   kx->ss_I = ss_I;
   1365   kx->current_epoch = 0;
   1366   kx->current_sqn = 0;
   1367   derive_per_message_secrets (&kx->current_ats,
   1368                               kx->current_sqn,
   1369                               enc_key,
   1370                               enc_nonce);
   1371 
   1372   GNUNET_MQ_send_copy (kx->mq, env);
   1373   kx->resend_env = env;
   1374   kx->resend_tries_left = RESEND_MAX_TRIES;
   1375   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent ResponderHello: %d %d\n", kx->role,
   1376               kx->status);
   1377 
   1378   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   1379                                                   &resend_responder_hello,
   1380                                                   kx);
   1381   kx->status = GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT;
   1382   monitor_notify_all (kx);
   1383   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1384 }
   1385 
   1386 
   1387 static void
   1388 handle_initiator_hello_cont (void *cls, const struct GNUNET_ShortHashCode *ss_R)
   1389 {
   1390   const struct GNUNET_HashCode *my_identity_hash;
   1391   struct InitiatorHelloCtx *ihm_ctx = cls;
   1392   struct GSC_KeyExchangeInfo *kx = ihm_ctx->kx;
   1393   uint32_t ihm_len = ntohs (ihm_ctx->ihm_e->header.size);
   1394   unsigned char enc_key[AEAD_KEY_BYTES];
   1395   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   1396   struct GNUNET_HashCode h1;
   1397   struct GNUNET_HashCode transcript;
   1398   struct GNUNET_ShortHashCode es;
   1399   struct GNUNET_ShortHashCode ets;
   1400   enum GNUNET_GenericReturnValue ret;
   1401 
   1402   ihm_ctx->req->op = NULL;
   1403   GNUNET_CONTAINER_DLL_remove (pils_requests_head,
   1404                                pils_requests_tail,
   1405                                ihm_ctx->req);
   1406   GNUNET_free (ihm_ctx->req);
   1407 
   1408 
   1409   GNUNET_memcpy (&kx->pk_e.ecdhe_key,
   1410                  &ihm_ctx->ihm_e->pk_e,
   1411                  sizeof (ihm_ctx->ihm_e->pk_e));
   1412   //      5. generate ETS (early_traffic_secret_key, decrypt pk_i
   1413   //         expand ETS <- expand ES <- extract ss_R
   1414   //         use ETS to decrypt
   1415 
   1416   /* Forward the transcript hash context over the unencrypted fields to get it
   1417    * to the same status that the initiator had when it needed to derive es and
   1418    * ets for the encryption */
   1419   GNUNET_CRYPTO_hash_context_read (
   1420     kx->transcript_hash_ctx,
   1421     ihm_ctx->ihm_e,
   1422     sizeof (struct InitiatorHello));
   1423   snapshot_transcript (kx->transcript_hash_ctx,
   1424                        &transcript);
   1425 #if DEBUG_KX
   1426   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1427               "Transcript snapshot for derivation of ES, ETS: `%s'\n",
   1428               GNUNET_h2s (&transcript));
   1429 #endif
   1430   derive_es_ets (&transcript, ss_R, &es, &ets);
   1431   derive_per_message_secrets (&ets,
   1432                               0,
   1433                               enc_key,
   1434                               enc_nonce);
   1435   {
   1436     struct InitiatorHelloPayload *ihmp;
   1437     size_t ct_len = ihm_len - sizeof (struct InitiatorHello);
   1438     unsigned char ihmp_buf[ct_len - AEAD_TAG_BYTES];
   1439     ihmp = (struct InitiatorHelloPayload*) ihmp_buf;
   1440     ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   1441       ihmp_buf,   // unsigned char *m
   1442       NULL,                                      // mlen_p message length
   1443       NULL,                                      // unsigned char *nsec       - unused: NULL
   1444       (unsigned char*) &ihm_ctx->ihm_e[1],   // const unsigned char *c    - ciphertext
   1445       ct_len,                                     // unsigned long long clen   - length of ciphertext
   1446       // mac,                                   // const unsigned char *mac  - authentication tag
   1447       NULL,                                      // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   1448       0,                                         // unsigned long long adlen
   1449       enc_nonce,      // const unsigned char *npub - nonce
   1450       enc_key   // const unsigned char *k    - key
   1451       );
   1452     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pid_sender: %s\n",
   1453                 GNUNET_i2s (&ihmp->pk_I));
   1454     if (0 != ret)
   1455     {
   1456       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1457                   "Something went wrong decrypting: %d\n", ret);
   1458       GNUNET_break_op (0);
   1459       GNUNET_free (ihm_ctx->ihm_e);
   1460       GNUNET_free (ihm_ctx);
   1461       restart_kx (kx);
   1462       return;
   1463     }
   1464     /* now forward it considering the encrypted messages that the initiator was
   1465      * able to send after deriving the es and ets */
   1466     GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx,
   1467                                      &ihm_ctx->ihm_e[1],
   1468                                      ct_len);
   1469     GNUNET_memcpy (&kx->peer,
   1470                    &ihmp->pk_I,
   1471                    sizeof (struct GNUNET_PeerIdentity));
   1472   }
   1473 
   1474   my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils);
   1475   GNUNET_assert (NULL != my_identity_hash);
   1476 
   1477   // We could follow with the rest of the Key Schedule (dES, HS, ...) for now
   1478   /* Check that we are actually in the receiving role */
   1479   GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1);
   1480   if (0 < GNUNET_CRYPTO_hash_cmp (&h1, my_identity_hash))
   1481   {
   1482     /* peer with "lower" identity starts KX, otherwise we typically end up
   1483        with both peers starting the exchange and transmit the 'set key'
   1484        message twice */
   1485     /* Something went wrong - we have the lower value and should have sent the
   1486      * InitiatorHello, but instead received it. TODO handle this case
   1487      * We might end up in this case if the initiator didn't initiate the
   1488      * handshake long enough and the 'responder' initiates the handshake */
   1489     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1490                 "Something went wrong - we have the lower value and should have sent the InitiatorHello, but instead received it.\n");
   1491     GNUNET_free (ihm_ctx->ihm_e);
   1492     GNUNET_free (ihm_ctx);
   1493     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1494     kx->transcript_hash_ctx = NULL;
   1495     return;
   1496   }
   1497 
   1498   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer ID of other peer: %s\n", GNUNET_i2s
   1499                 (&kx->peer));
   1500   /* We update the monitoring peers here because now we know
   1501    * that we can decrypt the message AND know the PID
   1502    */
   1503   monitor_notify_all (kx);
   1504   kx->ss_R = *ss_R;
   1505   kx->early_secret_key = es;
   1506   kx->early_traffic_secret = ets;
   1507   send_responder_hello (kx);
   1508 }
   1509 
   1510 
   1511 static int
   1512 check_initiator_hello (void *cls, const struct InitiatorHello *m)
   1513 {
   1514   uint16_t size = ntohs (m->header.size);
   1515 
   1516   if (size < sizeof (*m)
   1517       + sizeof (struct InitiatorHelloPayload)
   1518       + AEAD_TAG_BYTES)
   1519   {
   1520     return GNUNET_SYSERR;
   1521   }
   1522   return GNUNET_OK;
   1523 }
   1524 
   1525 
   1526 /**
   1527  * Handle the InitiatorHello message
   1528  *  - derives necessary keys from the plaintext parts
   1529  *  - decrypts the encrypted part
   1530  *  - replies with ResponderHello message
   1531  * @param cls the key exchange info
   1532  * @param ihm_e InitiatorHello message
   1533  */
   1534 static void
   1535 handle_initiator_hello (void *cls, const struct InitiatorHello *ihm_e)
   1536 {
   1537   const struct GNUNET_HashCode *my_identity_hash;
   1538   struct GSC_KeyExchangeInfo *kx = cls;
   1539   struct InitiatorHelloCtx *initiator_hello_cls;
   1540   size_t ihm_len;
   1541 
   1542   if (ROLE_INITIATOR == kx->role)
   1543   {
   1544     GNUNET_break_op (0);
   1545     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1546                 "I am an initiator! Tearing down...\n");
   1547     return;
   1548   }
   1549   if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED)
   1550   {
   1551     GNUNET_break_op (0);
   1552     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1553                 "Already received InitiatorHello: %d %d\n", kx->role, kx->status
   1554                 );
   1555     return;
   1556   }
   1557   else if ((kx->status > GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED) &&
   1558            (NULL != kx->transcript_hash_ctx))
   1559   {
   1560     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1561                 "Already received InitiatorHello and sent ResponderHello: %d %d\n",
   1562                 kx->role, kx->status);
   1563     return;
   1564   }
   1565   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorHello: %d %d\n", kx->
   1566               role, kx->status);
   1567   GNUNET_assert (NULL == kx->transcript_hash_ctx);
   1568   kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start ();
   1569   GNUNET_assert (NULL != kx->transcript_hash_ctx);
   1570 
   1571   GNUNET_STATISTICS_update (GSC_stats,
   1572                             gettext_noop ("# key exchanges initiated"),
   1573                             1,
   1574                             GNUNET_NO);
   1575 
   1576   kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED;
   1577 
   1578   my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils);
   1579   GNUNET_assert (NULL != my_identity_hash);
   1580 
   1581   //      1. verify type _INITIATOR_HELLO
   1582   //         - This is implicytly done by arriving within this handler
   1583   //         - or is this about verifying the 'additional data' part of aead?
   1584   //           should it check the encryption + mac? (is this implicitly done
   1585   //           while decrypting?)
   1586   //      2. verify H(pk_R) matches pk_R
   1587   if (0 != memcmp (&ihm_e->h_pk_R,
   1588                    my_identity_hash,
   1589                    sizeof (struct GNUNET_HashCode)))
   1590   {
   1591     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1592                 "This message is not meant for us (H(PID) mismatch)\n");
   1593     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1594     kx->transcript_hash_ctx = NULL;
   1595     return;
   1596   }
   1597   // FIXME this sometimes triggers in the tests - why?
   1598   //      3. decaps -> shared_secret_R, c_R (kemChallenge)
   1599   ihm_len = ntohs (ihm_e->header.size);
   1600   initiator_hello_cls = GNUNET_new (struct InitiatorHelloCtx);
   1601   initiator_hello_cls->kx = kx;
   1602   initiator_hello_cls->ihm_e = GNUNET_malloc (ihm_len);
   1603   GNUNET_memcpy (initiator_hello_cls->ihm_e, ihm_e, ihm_len);
   1604   initiator_hello_cls->req = GNUNET_new (struct PilsRequest);
   1605   GNUNET_CONTAINER_DLL_insert (pils_requests_head,
   1606                                pils_requests_tail,
   1607                                initiator_hello_cls->req);
   1608   initiator_hello_cls->req->op =
   1609     GNUNET_PILS_kem_decaps (GSC_pils,
   1610                             &ihm_e->c_R,
   1611                             // encapsulated key
   1612                             &handle_initiator_hello_cont,
   1613                             // continuation
   1614                             initiator_hello_cls);
   1615 }
   1616 
   1617 
   1618 struct ResponderHelloCls
   1619 {
   1620   /* Current KX session */
   1621   struct GSC_KeyExchangeInfo *kx;
   1622 
   1623   /* responder hello message - encrypted */
   1624   struct ResponderHello rhm_e;
   1625 
   1626   /* responder hello message - plain/decrypted */
   1627   struct ResponderHelloPayload *rhp;
   1628 
   1629   /* Decrypted finish hash */
   1630   struct GNUNET_HashCode decrypted_finish;
   1631 
   1632   /* Encrypted finished CT (for transcript later) */
   1633   char finished_enc[sizeof (struct GNUNET_HashCode)
   1634                     + AEAD_TAG_BYTES];
   1635 
   1636   /* Temporary transcript context */
   1637   struct GNUNET_HashContext *hc;
   1638 
   1639   /* Temporary handshake secret */
   1640   struct GNUNET_ShortHashCode hs;
   1641 
   1642   /* Temporary handshake secret */
   1643   struct GNUNET_ShortHashCode ss_e;
   1644 
   1645   /* Temporary handshake secret */
   1646   struct GNUNET_ShortHashCode ihts;
   1647 
   1648   /* Temporary handshake secret */
   1649   struct GNUNET_ShortHashCode rhts;
   1650 
   1651   /* Pending PILS request */
   1652   struct PilsRequest *req;
   1653 };
   1654 
   1655 static void
   1656 resend_initiator_done (void *cls)
   1657 {
   1658   struct GSC_KeyExchangeInfo *kx = cls;
   1659 
   1660   kx->resend_task = NULL;
   1661   if (0 == kx->resend_tries_left)
   1662   {
   1663     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1664                 "Restarting KX\n");
   1665     restart_kx (kx);
   1666     return;
   1667   }
   1668   kx->resend_tries_left--;
   1669   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1670               "Resending initiator done. Retries left: %u\n",
   1671               kx->resend_tries_left);
   1672   GNUNET_MQ_send_copy (kx->mq, kx->resend_env);
   1673   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   1674                                                   &resend_initiator_done,
   1675                                                   kx);
   1676 }
   1677 
   1678 
   1679 static void
   1680 handle_responder_hello_cont (void *cls, const struct GNUNET_ShortHashCode *ss_I)
   1681 {
   1682   struct ResponderHelloCls *rh_ctx = cls;
   1683   struct GSC_KeyExchangeInfo *kx = rh_ctx->kx;
   1684   struct InitiatorDone *idm_e; /* encrypted */
   1685   struct InitiatorDone idm_local;
   1686   struct InitiatorDone *idm_p; /* plaintext */
   1687   struct GNUNET_MQ_Envelope *env;
   1688   unsigned char enc_key[AEAD_KEY_BYTES];
   1689   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   1690   struct ConfirmationAck ack_i;
   1691   struct GNUNET_HashCode transcript;
   1692   struct GNUNET_ShortHashCode ms;
   1693 
   1694   rh_ctx->req->op = NULL;
   1695   GNUNET_CONTAINER_DLL_remove (pils_requests_head,
   1696                                pils_requests_tail,
   1697                                rh_ctx->req);
   1698   GNUNET_free (rh_ctx->req);
   1699   // XXX valgrind reports uninitialized memory
   1700   //     the following is a way to check whether this memory was meant
   1701   // memset (&rhm_local, 0, sizeof (rhm_local)); - adapt to cls if still needed
   1702   memset (&idm_local, 0, sizeof (idm_local));
   1703 
   1704   kx->ss_I = *ss_I;
   1705 
   1706   /* derive *ATS */
   1707   derive_ms (&rh_ctx->hs, ss_I, &ms);;
   1708   // 5. Create ResponderFinished as per Section 6 and check against decrypted payload.
   1709   struct GNUNET_HashCode responder_finished;
   1710   // Transcript updates, snapshot again
   1711   snapshot_transcript (rh_ctx->hc,
   1712                        &transcript);
   1713 #if DEBUG_KX
   1714   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1715               "Transcript snapshot for derivation of Rfinished: `%s'\n",
   1716               GNUNET_h2s (&transcript));
   1717 #endif
   1718   generate_responder_finished (&transcript,
   1719                                &ms,
   1720                                &responder_finished);
   1721   if (0 != memcmp (&rh_ctx->decrypted_finish,
   1722                    &responder_finished,
   1723                    sizeof (struct GNUNET_HashCode)))
   1724   {
   1725     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1726                 "Could not verify \"responder finished\"\n");
   1727     GNUNET_free (rh_ctx->rhp);
   1728     GNUNET_CRYPTO_hash_context_abort (rh_ctx->hc);
   1729     GNUNET_free (rh_ctx);
   1730     GNUNET_assert (0);
   1731     return;
   1732   }
   1733 
   1734 
   1735   /* Forward the transcript
   1736    * after generating finished_R,
   1737    * before deriving *ATS */
   1738   GNUNET_CRYPTO_hash_context_read (
   1739     rh_ctx->hc,
   1740     rh_ctx->finished_enc,
   1741     sizeof (rh_ctx->finished_enc));
   1742 
   1743   // At this point we cannot fail anymore and may lock into kx
   1744   GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1745   kx->transcript_hash_ctx = rh_ctx->hc;
   1746   kx->ss_I = *ss_I;
   1747   kx->handshake_secret = rh_ctx->hs;
   1748   kx->ss_e = rh_ctx->ss_e;
   1749   kx->ihts = rh_ctx->ihts;
   1750   kx->rhts = rh_ctx->rhts;
   1751   kx->master_secret = ms;
   1752   GNUNET_free (rh_ctx->rhp);
   1753   GNUNET_free (rh_ctx);
   1754   rh_ctx = NULL;
   1755 
   1756   snapshot_transcript (kx->transcript_hash_ctx,
   1757                        &transcript);
   1758 #if DEBUG_KX
   1759   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1760               "Transcript snapshot for derivation of *ATS: `%s'\n",
   1761               GNUNET_h2s (&transcript));
   1762 #endif
   1763   derive_initial_ats (&transcript,
   1764                       &kx->master_secret,
   1765                       ROLE_RESPONDER,
   1766                       &kx->their_ats[0]);
   1767   for (int i = 0; i < MAX_EPOCHS - 1; i++)
   1768   {
   1769     derive_next_ats (&kx->their_ats[i],
   1770                      &kx->their_ats[i + 1]);
   1771   }
   1772   kx->their_max_epoch = MAX_EPOCHS - 1;
   1773 
   1774   derive_per_message_secrets (&kx->ihts,
   1775                               0,
   1776                               enc_key,
   1777                               enc_nonce);
   1778   /* Create InitiatorDone message */
   1779   idm_p = &idm_local; /* plaintext */
   1780   env = GNUNET_MQ_msg_extra (idm_e,
   1781                              sizeof (ack_i)
   1782                              + AEAD_TAG_BYTES,
   1783                              GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE);
   1784   // 6. Create IteratorFinished as per Section 6.
   1785   generate_initiator_finished (&transcript,
   1786                                &kx->master_secret,
   1787                                &idm_p->finished);
   1788   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1789               "InteratorFinished: `%s'\n",
   1790               GNUNET_h2s (&idm_p->finished));
   1791   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1792               "Transcript `%s'\n",
   1793               GNUNET_h2s (&transcript));
   1794   // 7. Send InteratorFinished message encrypted with the key derived from IHTS to R
   1795 
   1796   GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1797                    (unsigned char*) &idm_e->finished, /* c - ciphertext */
   1798                    NULL, /* clen_p */
   1799                    (unsigned char*) &idm_p->finished, /* idm_p - plaintext message */
   1800                    sizeof (idm_p->finished), // mlen
   1801                    NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1802                             // fields?
   1803                    NULL, // nsec - unused
   1804                    enc_nonce, // npub - nonce
   1805                    enc_key)); // k - key IHTS
   1806   /* Forward the transcript hash context
   1807    * after generating finished_I and RATS_0
   1808    * before deriving IATS_0 */
   1809   GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx,
   1810                                    &idm_e->finished,
   1811                                    sizeof (idm_e->finished)
   1812                                    + AEAD_TAG_BYTES);
   1813   snapshot_transcript (kx->transcript_hash_ctx,
   1814                        &transcript);
   1815 #if DEBUG_KX
   1816   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1817               "Transcript snapshot for derivation of *ATS: `%s'\n",
   1818               GNUNET_h2s (&transcript));
   1819 #endif
   1820   derive_initial_ats (&transcript,
   1821                       &kx->master_secret,
   1822                       ROLE_INITIATOR,
   1823                       &kx->current_ats);
   1824   kx->current_epoch = 0;
   1825   kx->current_sqn++;
   1826   // 8. optionally encrypt payload TODO
   1827   derive_per_message_secrets (&kx->current_ats,
   1828                               kx->current_sqn,
   1829                               enc_key,
   1830                               enc_nonce);
   1831   kx->current_sqn++;
   1832   ack_i.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   1833   ack_i.header.size = htons (sizeof ack_i);
   1834   GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1835                    (unsigned char*) &idm_e[1], /* c - ciphertext */
   1836                    NULL, /* clen_p */
   1837                    (unsigned char*) &ack_i, /* rhm_p - plaintext message */
   1838                    sizeof ack_i, // mlen
   1839                    NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1840                             // fields?
   1841                    NULL, // nsec - unused
   1842                    enc_nonce, // npub - nonce // FIXME nonce can be reused
   1843                    enc_key)); // k - key RHTS
   1844 
   1845   GNUNET_MQ_send_copy (kx->mq, env);
   1846   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent InitiatorDone: %d %d\n", kx->role,
   1847               kx->status);
   1848 
   1849 
   1850   kx->resend_env = env;
   1851   kx->resend_tries_left = RESEND_MAX_TRIES;
   1852   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   1853                                                   &resend_initiator_done,
   1854                                                   kx);
   1855   kx->status = GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT;
   1856   monitor_notify_all (kx);
   1857   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1858 }
   1859 
   1860 
   1861 static int
   1862 check_responder_hello (void *cls, const struct ResponderHello *m)
   1863 {
   1864   uint16_t size = ntohs (m->header.size);
   1865 
   1866   if (size < sizeof (*m)
   1867       + sizeof (struct ResponderHelloPayload)
   1868       + sizeof (struct GNUNET_HashCode)
   1869       + AEAD_TAG_BYTES * 2)
   1870   {
   1871     return GNUNET_SYSERR;
   1872   }
   1873   return GNUNET_OK;
   1874 }
   1875 
   1876 
   1877 /**
   1878  * Handle Responder Hello message
   1879  * @param cls key exchange info
   1880  * @param rhm_e ResponderHello message
   1881  */
   1882 static void
   1883 handle_responder_hello (void *cls, const struct ResponderHello *rhm_e)
   1884 {
   1885   struct GSC_KeyExchangeInfo *kx = cls;
   1886   struct PilsRequest *req;
   1887   struct ResponderHelloCls *rh_ctx;
   1888   struct GNUNET_HashCode transcript;
   1889   struct GNUNET_HashContext *hc;
   1890   unsigned char enc_key[AEAD_KEY_BYTES];
   1891   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   1892   enum GNUNET_GenericReturnValue ret;
   1893 
   1894   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ResponderHello: %d %d\n", kx->
   1895               role, kx->status);
   1896 
   1897   hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx);
   1898   if (NULL != kx->resend_task)
   1899   {
   1900     GNUNET_SCHEDULER_cancel (kx->resend_task);
   1901     kx->resend_task = NULL;
   1902   }
   1903   if (NULL != kx->resend_env)
   1904   {
   1905     GNUNET_free (kx->resend_env);
   1906     kx->resend_env = NULL;
   1907   }
   1908 
   1909   /* Forward the transcript hash context */
   1910   if (ROLE_RESPONDER == kx->role)
   1911   {
   1912     GNUNET_break_op (0);
   1913     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1914                 "I am the responder! Ignoring.\n");
   1915     GNUNET_CRYPTO_hash_context_abort (hc);
   1916     return;
   1917   }
   1918   GNUNET_CRYPTO_hash_context_read (hc,
   1919                                    rhm_e,
   1920                                    sizeof (struct ResponderHello));
   1921   // 1. Verify that the message type is CORE_RESPONDER_HELLO
   1922   //    - implicitly done by handling this message?
   1923   //    - or is this about verifying the 'additional data' part of aead?
   1924   //      should it check the encryption + mac? (is this implicitly done
   1925   //      while decrypting?)
   1926   // 2. sse <- Decaps(ske,ce)
   1927   rh_ctx = GNUNET_new (struct ResponderHelloCls);
   1928   ret = GNUNET_CRYPTO_hpke_kem_decaps (&kx->sk_e, // secret/private ephemeral key of initiator (us)
   1929                                        &rhm_e->c_e,    // encapsulated key
   1930                                        &rh_ctx->ss_e); // key - ss_e
   1931   if (GNUNET_OK != ret)
   1932   {
   1933     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1934                 "Something went wrong decapsulating ss_e\n");
   1935     GNUNET_CRYPTO_hash_context_abort (hc);
   1936     return;
   1937   }
   1938   // 3. Generate IHTS and RHTS from Section 5 and decrypt ServicesInfo, cI and ResponderFinished.
   1939   snapshot_transcript (hc, &transcript);
   1940 #if DEBUG_KX
   1941   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1942               "Transcript snapshot for derivation of HS, *HTS: `%s'\n",
   1943               GNUNET_h2s (&transcript));
   1944 #endif
   1945   derive_hs (&kx->early_secret_key,
   1946              &rh_ctx->ss_e,
   1947              &rh_ctx->hs);
   1948   derive_rhts (&transcript,
   1949                &rh_ctx->hs,
   1950                &rh_ctx->rhts);
   1951   derive_ihts (&transcript,
   1952                &rh_ctx->hs,
   1953                &rh_ctx->ihts);
   1954   derive_per_message_secrets (&rh_ctx->rhts,
   1955                               0,
   1956                               enc_key,
   1957                               enc_nonce);
   1958   rh_ctx->kx = kx;
   1959   GNUNET_memcpy (&rh_ctx->rhm_e, rhm_e, sizeof (*rhm_e));
   1960   {
   1961     unsigned long long int c_len;
   1962     unsigned char *finished_buf;
   1963     // use RHTS to decrypt
   1964     c_len = ntohs (rhm_e->header.size) - sizeof (*rhm_e)
   1965             - sizeof (struct GNUNET_HashCode)
   1966             - AEAD_TAG_BYTES;                                   // finished ct
   1967     rh_ctx->rhp = GNUNET_malloc (c_len
   1968                                  -
   1969                                  AEAD_TAG_BYTES);
   1970     rh_ctx->hc = hc;
   1971     finished_buf = ((unsigned char*) &rhm_e[1]) + c_len;
   1972     /* Forward the transcript_hash_ctx
   1973      * after rhts has been generated,
   1974      * before generating finished_R*/
   1975     GNUNET_CRYPTO_hash_context_read (
   1976       hc,
   1977       &rhm_e[1],
   1978       c_len);
   1979 
   1980     ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   1981       (unsigned char*) rh_ctx->rhp,   // unsigned char *m
   1982       NULL,                                     // mlen_p message length
   1983       NULL,                                     // unsigned char *nsec       - unused: NULL
   1984       (unsigned char*) &rhm_e[1],   // const unsigned char *c    - ciphertext
   1985       c_len,                                    // unsigned long long clen   - length of ciphertext
   1986       NULL,                                     // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   1987       0,                                        // unsigned long long adlen
   1988       enc_nonce,     // const unsigned char *npub - nonce
   1989       enc_key   // const unsigned char *k    - key
   1990       );
   1991     if (0 != ret)
   1992     {
   1993       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1994                   "Something went wrong decrypting: %d\n", ret);
   1995       GNUNET_free (rh_ctx->rhp);
   1996       GNUNET_free (rh_ctx);
   1997       GNUNET_CRYPTO_hash_context_abort (hc);
   1998       return;
   1999     }
   2000     // FIXME nonce reuse (see encryption)
   2001     derive_per_message_secrets (&rh_ctx->rhts,
   2002                                 1,
   2003                                 enc_key,
   2004                                 enc_nonce);
   2005     c_len = sizeof (struct GNUNET_HashCode)
   2006             + AEAD_TAG_BYTES;
   2007     ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2008       (unsigned char*) &rh_ctx->decrypted_finish,   // unsigned char *m
   2009       NULL,                                // mlen_p message length
   2010       NULL,                                // unsigned char *nsec       - unused: NULL
   2011       finished_buf,   // const unsigned char *c    - ciphertext
   2012       c_len,                               // unsigned long long clen   - length of ciphertext
   2013       NULL,                                // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2014       0,                                   // unsigned long long adlen
   2015       enc_nonce,   // const unsigned char *npub - nonce
   2016       enc_key   // const unsigned char *k    - key
   2017       );
   2018     if (0 != ret)
   2019     {
   2020       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2021                   "Something went wrong decrypting finished field: %d\n", ret);
   2022       GNUNET_free (rh_ctx->rhp);
   2023       GNUNET_free (rh_ctx);
   2024       GNUNET_CRYPTO_hash_context_abort (hc);
   2025       return;
   2026     }
   2027     GNUNET_memcpy (rh_ctx->finished_enc,
   2028                    finished_buf,
   2029                    c_len);
   2030   }
   2031   // 4. ssI <- Decaps(skI,cI).
   2032   req = GNUNET_new (struct PilsRequest);
   2033   rh_ctx->req = req;
   2034   GNUNET_CONTAINER_DLL_insert (pils_requests_head,
   2035                                pils_requests_tail,
   2036                                req);
   2037   req->op = GNUNET_PILS_kem_decaps (GSC_pils,
   2038                                     &rh_ctx->rhp->c_I, // encapsulated key
   2039                                     &handle_responder_hello_cont, // continuation
   2040                                     rh_ctx);
   2041 }
   2042 
   2043 
   2044 static int
   2045 check_initiator_done (void *cls, const struct InitiatorDone *m)
   2046 {
   2047   uint16_t size = ntohs (m->header.size);
   2048 
   2049   if (size < sizeof (*m) + sizeof (struct ConfirmationAck))
   2050   {
   2051     return GNUNET_SYSERR;
   2052   }
   2053   return GNUNET_OK;
   2054 }
   2055 
   2056 
   2057 /**
   2058  * Handle InitiatorDone message
   2059  * @param cls key exchange info
   2060  * @param idm_e InitiatorDone message
   2061  */
   2062 static void
   2063 handle_initiator_done (void *cls, const struct InitiatorDone *idm_e)
   2064 {
   2065   struct GSC_KeyExchangeInfo *kx = cls;
   2066   struct InitiatorDone idm_local;
   2067   struct InitiatorDone *idm_p = &idm_local; /* plaintext */
   2068   struct GNUNET_HashCode initiator_finished;
   2069   struct GNUNET_HashCode transcript;
   2070   struct GNUNET_ShortHashCode their_ats;
   2071   struct GNUNET_HashContext *hc;
   2072   unsigned char enc_key[AEAD_KEY_BYTES];
   2073   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2074   struct ConfirmationAck ack_i;
   2075   struct ConfirmationAck ack_r;
   2076   int8_t ret;
   2077 
   2078   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorDone: %d %d\n", kx->
   2079               role, kx->status);
   2080   if (NULL != kx->resend_task)
   2081   {
   2082     GNUNET_SCHEDULER_cancel (kx->resend_task);
   2083     kx->resend_task = NULL;
   2084   }
   2085   if (NULL != kx->resend_env)
   2086   {
   2087     GNUNET_free (kx->resend_env);
   2088     kx->resend_env = NULL;
   2089   }
   2090   if (ROLE_INITIATOR == kx->role)
   2091   {
   2092     GNUNET_break_op (0);
   2093     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2094                 "I am the initiator! Tearing down...\n");
   2095     return;
   2096   }
   2097   derive_per_message_secrets (&kx->ihts,
   2098                               0,
   2099                               enc_key,
   2100                               enc_nonce);
   2101   ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2102     (unsigned char*) &idm_p->finished,     // unsigned char *m
   2103     NULL,                                  // mlen_p message length
   2104     NULL,                                  // unsigned char *nsec       - unused: NULL
   2105     (unsigned char*) &idm_e->finished,     // const unsigned char *c    - ciphertext
   2106     sizeof (idm_p->finished)               // unsigned long long clen   - length of ciphertext
   2107     + AEAD_TAG_BYTES,
   2108     NULL,                                  // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2109     0,                                     // unsigned long long adlen
   2110     enc_nonce,     // const unsigned char *npub - nonce
   2111     enc_key     // const unsigned char *k    - key
   2112     );
   2113   if (0 != ret)
   2114   {
   2115     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2116                 "Something went wrong decrypting: %d\n", ret);
   2117     return;
   2118   }
   2119 
   2120   //      - verify finished_I
   2121   /* Generate finished_I
   2122    * after Forwarding until {finished_R}RHTS
   2123    *   (did so while we prepared responder hello)
   2124    * before forwarding to [{payload}RATS and] {finished_I}IHTS */
   2125   // (look at the end of handle_initiator_hello())
   2126   snapshot_transcript (kx->transcript_hash_ctx, &transcript);
   2127   generate_initiator_finished (&transcript,
   2128                                &kx->master_secret,
   2129                                &initiator_finished);
   2130   if (0 != memcmp (&idm_p->finished,
   2131                    &initiator_finished,
   2132                    sizeof (struct GNUNET_HashCode)))
   2133   {
   2134     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2135                 "Could not verify \"initiator finished\" hash.\n");
   2136     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2137                 "Want: `%s'\n",
   2138                 GNUNET_h2s (&initiator_finished));
   2139     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2140                 "Have: `%s'\n",
   2141                 GNUNET_h2s (&idm_p->finished));
   2142     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2143                 "Transcript `%s'\n",
   2144                 GNUNET_h2s (&transcript));
   2145     return;
   2146   }
   2147 
   2148   /* Forward the transcript hash_context_read */
   2149   hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx);
   2150   GNUNET_CRYPTO_hash_context_read (hc,
   2151                                    &idm_e->finished,
   2152                                    sizeof (idm_e->finished)
   2153                                    + AEAD_TAG_BYTES);
   2154   snapshot_transcript (hc, &transcript);
   2155   derive_initial_ats (&transcript,
   2156                       &kx->master_secret,
   2157                       ROLE_INITIATOR,
   2158                       &their_ats);
   2159   derive_per_message_secrets (&their_ats, // FIXME other HS epoch?
   2160                               0,
   2161                               enc_key,
   2162                               enc_nonce);
   2163   ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2164     (unsigned char*) &ack_i,     // unsigned char *m
   2165     NULL,                                  // mlen_p message length
   2166     NULL,                                  // unsigned char *nsec       - unused: NULL
   2167     (unsigned char*) &idm_e[1],     // const unsigned char *c    - ciphertext
   2168     sizeof (ack_i) + AEAD_TAG_BYTES,                                 // unsigned long long clen   - length of ciphertext
   2169     NULL,                                  // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2170     0,                                     // unsigned long long adlen
   2171     enc_nonce,     // const unsigned char *npub - nonce
   2172     enc_key     // const unsigned char *k    - key
   2173     );
   2174   if (0 != ret)
   2175   {
   2176     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2177                 "Something went wrong decrypting the Ack: %d\n", ret);
   2178     GNUNET_CRYPTO_hash_context_abort (hc);
   2179     return;
   2180   }
   2181   if ((sizeof ack_i != ntohs (ack_i.header.size)) ||
   2182       (GNUNET_MESSAGE_TYPE_CORE_ACK != ntohs (ack_i.header.type)))
   2183   {
   2184     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2185                 "Ack invalid!\n");
   2186     GNUNET_CRYPTO_hash_context_abort (hc);
   2187     return;
   2188   }
   2189   GNUNET_memcpy (&kx->their_ats[0],
   2190                  &their_ats,
   2191                  sizeof their_ats);
   2192   /**
   2193    * FIXME we do not really have to calculate all this now
   2194    */
   2195   for (int i = 0; i < MAX_EPOCHS - 1; i++)
   2196   {
   2197     derive_next_ats (&kx->their_ats[i],
   2198                      &kx->their_ats[i + 1]);
   2199   }
   2200   GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2201   kx->transcript_hash_ctx = hc;
   2202   kx->status = GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED;
   2203   kx->current_epoch_expiration =
   2204     GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2205   cleanup_handshake_secrets (kx);
   2206   monitor_notify_all (kx);
   2207   kx->current_sqn = 1;
   2208   GSC_SESSIONS_create (&kx->peer, kx, kx->class);
   2209   GNUNET_assert (NULL == kx->heartbeat_task);
   2210   update_timeout (kx);
   2211   ack_r.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   2212   ack_r.header.size = htons (sizeof ack_r);
   2213   GSC_KX_encrypt_and_transmit (kx,
   2214                                &ack_r,
   2215                                sizeof ack_r);
   2216 
   2217   GNUNET_TRANSPORT_core_receive_continue (transport,
   2218                                           &kx->peer);
   2219 }
   2220 
   2221 
   2222 /**
   2223  * Check an incoming encrypted message before handling it
   2224  * @param cls key exchange info
   2225  * @param m the encrypted message
   2226  */
   2227 static int
   2228 check_encrypted_message (void *cls, const struct EncryptedMessage *m)
   2229 {
   2230   uint16_t size = ntohs (m->header.size) - sizeof(*m);
   2231 
   2232   // TODO check (see check_encrypted ())
   2233   //       - check epoch
   2234   //       - check sequence number
   2235   if (size < sizeof(struct GNUNET_MessageHeader))
   2236   {
   2237     GNUNET_break_op (0);
   2238     return GNUNET_SYSERR;
   2239   }
   2240   return GNUNET_OK;
   2241 }
   2242 
   2243 
   2244 /**
   2245  * Handle a key update
   2246  * @param cls key exchange info
   2247  * @param m KeyUpdate message
   2248  */
   2249 static void
   2250 handle_heartbeat (struct GSC_KeyExchangeInfo *kx,
   2251                   const struct Heartbeat *m)
   2252 {
   2253   struct GNUNET_ShortHashCode new_ats;
   2254   struct ConfirmationAck ack;
   2255 
   2256   if (m->flags & GSC_HEARTBEAT_KEY_UPDATE_REQUESTED)
   2257   {
   2258     if (kx->current_epoch == UINT64_MAX)
   2259     {
   2260       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2261                   "Max epoch reached (you probably will never see this)\n");
   2262     }
   2263     else
   2264     {
   2265       kx->current_epoch++;
   2266       kx->current_epoch_expiration =
   2267         GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2268       kx->current_sqn = 0;
   2269       derive_next_ats (&kx->current_ats,
   2270                        &new_ats);
   2271       memcpy (&kx->current_ats,
   2272               &new_ats,
   2273               sizeof new_ats);
   2274     }
   2275   }
   2276   update_timeout (kx);
   2277   ack.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   2278   ack.header.size = htons (sizeof ack);
   2279   GSC_KX_encrypt_and_transmit (kx,
   2280                                &ack,
   2281                                sizeof ack);
   2282   if (NULL != kx->heartbeat_task)
   2283   {
   2284     GNUNET_SCHEDULER_cancel (kx->heartbeat_task);
   2285     kx->heartbeat_task = GNUNET_SCHEDULER_add_delayed (MIN_HEARTBEAT_FREQUENCY,
   2286                                                        &send_heartbeat,
   2287                                                        kx);
   2288   }
   2289   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2290 }
   2291 
   2292 
   2293 static enum GNUNET_GenericReturnValue
   2294 check_if_ack_or_heartbeat (struct GSC_KeyExchangeInfo *kx,
   2295                            const char *buf,
   2296                            size_t buf_len)
   2297 {
   2298   struct GNUNET_MessageHeader *msg;
   2299   struct ConfirmationAck *ack;
   2300   struct Heartbeat *hb;
   2301 
   2302   if (sizeof *msg > buf_len)
   2303     return GNUNET_NO;
   2304   msg = (struct GNUNET_MessageHeader*) buf;
   2305   if (GNUNET_MESSAGE_TYPE_CORE_ACK == ntohs (msg->type))
   2306   {
   2307     ack = (struct ConfirmationAck *) buf;
   2308     if (sizeof *ack != ntohs (ack->header.size))
   2309       return GNUNET_NO;
   2310   }
   2311   else if  (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT == ntohs (msg->type))
   2312   {
   2313     hb = (struct Heartbeat*) buf;
   2314     if (sizeof *hb != ntohs (hb->header.size))
   2315       return GNUNET_NO;
   2316     handle_heartbeat (kx, hb);
   2317   }
   2318   else
   2319   {
   2320     return GNUNET_NO;
   2321   }
   2322 
   2323   /**
   2324    * Waiting for ACK or heartbeat
   2325    */
   2326   if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT)
   2327   {
   2328     GSC_SESSIONS_create (&kx->peer, kx, kx->class);
   2329     kx->status = GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED;
   2330     kx->current_epoch_expiration =
   2331       GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2332     cleanup_handshake_secrets (kx);
   2333     if (NULL != kx->resend_task)
   2334       GNUNET_SCHEDULER_cancel (kx->resend_task);
   2335     kx->resend_task = NULL;
   2336     if (NULL != kx->resend_env)
   2337       GNUNET_free (kx->resend_env);
   2338     kx->resend_env = NULL;
   2339     monitor_notify_all (kx);
   2340   }
   2341   update_timeout (kx);
   2342 
   2343   return GNUNET_YES;
   2344 }
   2345 
   2346 
   2347 /**
   2348  * handle an encrypted message
   2349  * @param cls key exchange info
   2350  * @param m encrypted message
   2351  */
   2352 static void
   2353 handle_encrypted_message (void *cls, const struct EncryptedMessage *m)
   2354 {
   2355   struct GSC_KeyExchangeInfo *kx = cls;
   2356   uint16_t size = ntohs (m->header.size);
   2357   char buf[size - sizeof (*m)] GNUNET_ALIGN;
   2358   unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
   2359   const unsigned char *seq_enc_nonce;
   2360   unsigned char enc_key[AEAD_KEY_BYTES];
   2361   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2362   struct GNUNET_ShortHashCode new_ats[MAX_EPOCHS];
   2363   uint32_t seq_enc_ctr;
   2364   uint64_t epoch;
   2365   uint64_t m_seq;
   2366   uint64_t m_seq_nbo;
   2367   uint64_t c_len;
   2368   int8_t ret;
   2369 
   2370   // TODO look at handle_encrypted
   2371   //       - statistics
   2372 
   2373   if ((kx->status != GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED) &&
   2374       (kx->status != GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED) &&
   2375       (kx->status != GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT))
   2376   {
   2377     GSC_SESSIONS_end (&kx->peer);
   2378     kx->status = GNUNET_CORE_KX_STATE_DOWN;
   2379     monitor_notify_all (kx);
   2380     restart_kx (kx);
   2381     return;
   2382   }
   2383   update_timeout (kx);
   2384   epoch = GNUNET_ntohll (m->epoch);
   2385   /**
   2386    * Derive temporarily as we want to discard on
   2387    * decryption failure(s)
   2388    */
   2389   memcpy (new_ats,
   2390           kx->their_ats,
   2391           MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
   2392   // FIXME here we could introduce logic that sends heartbeats
   2393   // with key update request if we have not seen a new
   2394   // epoch after a while (e.g. EPOCH_EXPIRATION)
   2395   if (kx->their_max_epoch < epoch)
   2396   {
   2397     /**
   2398      * Prevent DoS
   2399      * FIXME maybe requires its own limit.
   2400      */
   2401     if ((epoch - kx->their_max_epoch) > 2 * MAX_EPOCHS)
   2402     {
   2403       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2404                   "Epoch %" PRIu64 " is too new, will not decrypt...\n",
   2405                   epoch);
   2406       GSC_SESSIONS_end (&kx->peer);
   2407       kx->status = GNUNET_CORE_KX_STATE_DOWN;
   2408       monitor_notify_all (kx);
   2409       restart_kx (kx);
   2410       return;
   2411     }
   2412     for (int i = kx->their_max_epoch; i < epoch; i++)
   2413     {
   2414       derive_next_ats (&new_ats[i % MAX_EPOCHS],
   2415                        &new_ats[(i + 1) % MAX_EPOCHS]);
   2416     }
   2417   }
   2418   else if ((kx->their_max_epoch - epoch) > MAX_EPOCHS)
   2419   {
   2420     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2421                 "Epoch %" PRIu64 " is too old, cannot decrypt...\n",
   2422                 epoch);
   2423     return;
   2424   }
   2425   derive_sn (
   2426     &new_ats[epoch % MAX_EPOCHS],
   2427     seq_enc_k,
   2428     sizeof seq_enc_k);
   2429   /* compute the sequence number */
   2430   seq_enc_ctr = *((uint32_t*) m->tag);
   2431   seq_enc_nonce = &m->tag[sizeof (uint32_t)];
   2432 #if DEBUG_KX
   2433   GNUNET_print_bytes (&new_ats[epoch % MAX_EPOCHS],
   2434                       sizeof (struct GNUNET_ShortHashCode),
   2435                       8,
   2436                       GNUNET_NO);
   2437   GNUNET_print_bytes (seq_enc_k,
   2438                       sizeof seq_enc_k,
   2439                       8,
   2440                       GNUNET_NO);
   2441   GNUNET_print_bytes ((char*) &seq_enc_ctr,
   2442                       sizeof seq_enc_ctr,
   2443                       8,
   2444                       GNUNET_NO);
   2445 #endif
   2446   crypto_stream_chacha20_ietf_xor_ic (
   2447     (unsigned char*) &m_seq_nbo,
   2448     (unsigned char*) &m->sequence_number,
   2449     sizeof (uint64_t),
   2450     seq_enc_nonce,
   2451     ntohl (seq_enc_ctr),
   2452     seq_enc_k);
   2453   m_seq = GNUNET_ntohll (m_seq_nbo);
   2454   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2455               "Received encrypted message in epoch %" PRIu64
   2456               " with E(SQN=%" PRIu64 ")=%" PRIu64
   2457               "\n",
   2458               epoch,
   2459               m_seq,
   2460               m->sequence_number);
   2461   /* We are the initiator and as we are going to receive,
   2462    * we are using the responder key material */
   2463   derive_per_message_secrets (&new_ats[epoch],
   2464                               m_seq,
   2465                               enc_key,
   2466                               enc_nonce);
   2467   // TODO checking sequence numbers - handle the case of out-of-sync messages!
   2468   // for now only decrypt the payload
   2469   // TODO encrypt other fields, too!
   2470   // TODO
   2471   // c_len = size - offsetof ();
   2472   c_len = size - sizeof (struct EncryptedMessage);
   2473   ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
   2474     (unsigned char*) buf,   // m - plain message
   2475     NULL,                                   // nsec - unused
   2476     (unsigned char*) &m[1],                 // c - ciphertext
   2477     c_len,                                  // clen
   2478     (const unsigned char*) &m->tag,         // mac
   2479     NULL,                                   // ad - additional data TODO
   2480     0,                                      // adlen
   2481     enc_nonce,           // npub
   2482     enc_key          // k
   2483     );
   2484   if (0 != ret)
   2485   {
   2486     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2487                 "Something went wrong decrypting message\n");
   2488     GNUNET_break_op (0); // FIXME handle gracefully
   2489     return;
   2490   }
   2491   kx->their_max_epoch = epoch;
   2492   memcpy (&kx->their_ats,
   2493           new_ats,
   2494           MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
   2495 
   2496   if (GNUNET_NO == check_if_ack_or_heartbeat (kx,
   2497                                               buf,
   2498                                               sizeof buf))
   2499   {
   2500     if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT)
   2501     {
   2502       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2503                   "Dropping message as we are still waiting for handshake ACK\n");
   2504       GNUNET_break_op (0);
   2505       return;
   2506     }
   2507     if (GNUNET_OK !=
   2508         GNUNET_MST_from_buffer (kx->mst,
   2509                                 buf,
   2510                                 sizeof buf,
   2511                                 GNUNET_YES,
   2512                                 GNUNET_NO))
   2513       GNUNET_break_op (0);
   2514   }
   2515   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2516 }
   2517 
   2518 
   2519 /**
   2520  * Function called by transport telling us that a peer
   2521  * disconnected.
   2522  * Stop key exchange with the given peer.  Clean up key material.
   2523  *
   2524  * @param cls closure
   2525  * @param peer the peer that disconnected
   2526  * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
   2527  */
   2528 static void
   2529 handle_transport_notify_disconnect (void *cls,
   2530                                     const struct GNUNET_PeerIdentity *peer,
   2531                                     void *handler_cls)
   2532 {
   2533   struct GSC_KeyExchangeInfo *kx = handler_cls;
   2534   (void) cls;
   2535 
   2536   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2537               "Peer `%s' disconnected from us.\n",
   2538               GNUNET_i2s (&kx->peer));
   2539   GSC_SESSIONS_end (&kx->peer);
   2540   GNUNET_STATISTICS_update (GSC_stats,
   2541                             gettext_noop ("# key exchanges stopped"),
   2542                             1,
   2543                             GNUNET_NO);
   2544   if (NULL != kx->resend_task)
   2545   {
   2546     GNUNET_SCHEDULER_cancel (kx->resend_task);
   2547     kx->resend_task = NULL;
   2548   }
   2549   if (NULL != kx->resend_env)
   2550   {
   2551     GNUNET_free (kx->resend_env);
   2552     kx->resend_env = NULL;
   2553   }
   2554   if (NULL != kx->heartbeat_task)
   2555   {
   2556     GNUNET_SCHEDULER_cancel (kx->heartbeat_task);
   2557     kx->heartbeat_task = NULL;
   2558   }
   2559   kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
   2560   monitor_notify_all (kx);
   2561   if (kx->transcript_hash_ctx)
   2562   {
   2563     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2564     kx->transcript_hash_ctx = NULL;
   2565   }
   2566   GNUNET_CONTAINER_DLL_remove (kx_head, kx_tail, kx);
   2567   GNUNET_MST_destroy (kx->mst);
   2568   GNUNET_free (kx);
   2569 }
   2570 
   2571 
   2572 static void
   2573 resend_initiator_hello (void *cls)
   2574 {
   2575   struct GSC_KeyExchangeInfo *kx = cls;
   2576 
   2577   kx->resend_task = NULL;
   2578   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2579               "Resending InitiatorHello.\n");
   2580   GNUNET_MQ_send_copy (kx->mq, kx->resend_env);
   2581   // FIXME (Exponential) backoff?
   2582   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   2583                                                   &resend_initiator_hello,
   2584                                                   kx);
   2585 }
   2586 
   2587 
   2588 /**
   2589  * Send initiator hello
   2590  *
   2591  * @param kx key exchange context
   2592  */
   2593 static void
   2594 send_initiator_hello (struct GSC_KeyExchangeInfo *kx)
   2595 {
   2596   const struct GNUNET_PeerIdentity *my_identity;
   2597   struct GNUNET_MQ_Envelope *env;
   2598   struct GNUNET_ShortHashCode es;
   2599   struct GNUNET_ShortHashCode ets;
   2600   struct GNUNET_ShortHashCode ss_R;
   2601   struct InitiatorHelloPayload *ihmp; /* initiator hello message - buffer on stack */
   2602   struct InitiatorHello *ihm_e; /* initiator hello message - encrypted */
   2603   long long unsigned int c_len;
   2604   unsigned char enc_key[AEAD_KEY_BYTES];
   2605   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2606   enum GNUNET_GenericReturnValue ret;
   2607   size_t pt_len;
   2608 
   2609   my_identity = GNUNET_PILS_get_identity (GSC_pils);
   2610   GNUNET_assert (NULL != my_identity);
   2611 
   2612   pt_len = sizeof (*ihmp) + strlen (my_services_info);
   2613   c_len = pt_len + AEAD_TAG_BYTES;
   2614   env = GNUNET_MQ_msg_extra (ihm_e,
   2615                              c_len,
   2616                              GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO);
   2617   ihmp = (struct InitiatorHelloPayload*) &ihm_e[1];
   2618   ihmp->peer_class = htons (GNUNET_CORE_CLASS_UNKNOWN); // TODO set this to a meaningful
   2619   GNUNET_memcpy (&ihmp->pk_I,
   2620                  my_identity,
   2621                  sizeof (struct GNUNET_PeerIdentity));
   2622   GNUNET_CRYPTO_hash (&kx->peer, /* what to hash */ // TODO do we do this twice?
   2623                       sizeof (struct GNUNET_PeerIdentity),
   2624                       &ihm_e->h_pk_R); /* result */
   2625   // TODO init hashcontext/transcript_hash
   2626   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send InitiatorHello: %d %d\n", kx->role,
   2627               kx->status);
   2628   GNUNET_assert (NULL == kx->transcript_hash_ctx);
   2629   kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start ();
   2630   GNUNET_assert (NULL != kx->transcript_hash_ctx);
   2631   // TODO fill services_info
   2632 
   2633   // 1. Encaps
   2634   ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public ephemeral key of initiator
   2635                                         &ihm_e->c_R,    // encapsulated key
   2636                                         &ss_R); // key - ss_R
   2637   if (GNUNET_OK != ret)
   2638   {
   2639     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2640                 "Something went wrong encapsulating ss_R\n");
   2641     // TODO handle
   2642   }
   2643   // 2. generate rR (uint64_t) - is this the nonce? Naming seems not quite
   2644   //    consistent
   2645   ihm_e->r_I =
   2646     GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
   2647                               UINT64_MAX);
   2648   // 3. generate sk_e/pk_e - ephemeral key
   2649   GNUNET_CRYPTO_ecdhe_key_create (&kx->sk_e.ecdhe_key);
   2650   GNUNET_CRYPTO_ecdhe_key_get_public (
   2651     &kx->sk_e.ecdhe_key,
   2652     &kx->pk_e.ecdhe_key);
   2653   GNUNET_memcpy (&ihm_e->pk_e,
   2654                  &kx->pk_e.ecdhe_key,
   2655                  sizeof (kx->pk_e.ecdhe_key));
   2656   // 4. generate ETS to encrypt
   2657   //         generate ETS (early_traffic_secret_key, decrypt pk_i
   2658   //         expand ETS <- expand ES <- extract ss_R
   2659   //         use ETS to decrypt
   2660   GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx,
   2661                                    ihm_e,
   2662                                    sizeof (struct InitiatorHello));
   2663   {
   2664     struct GNUNET_HashCode transcript;
   2665     snapshot_transcript (kx->transcript_hash_ctx,
   2666                          &transcript);
   2667     derive_es_ets (&transcript,
   2668                    &ss_R,
   2669                    &es,
   2670                    &ets);
   2671     derive_per_message_secrets (&ets,
   2672                                 0,
   2673                                 enc_key,
   2674                                 enc_nonce);
   2675   }
   2676   // 5. encrypt
   2677 
   2678   ret = crypto_aead_xchacha20poly1305_ietf_encrypt (
   2679     (unsigned char*) &ihm_e[1],   /* c - ciphertext */
   2680     // mac,
   2681     // NULL, // maclen_p
   2682     &c_len,   /* clen_p */
   2683     (unsigned char*) ihmp,   /* m - plaintext message */
   2684     pt_len,   // mlen
   2685     NULL, 0,   // ad, adlen // FIXME maybe over the unencrypted header?
   2686                // fields?
   2687     NULL,   // nsec - unused
   2688     enc_nonce,   // npub - nonce
   2689     enc_key);   // k - key
   2690   if (0 != ret)
   2691   {
   2692     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong encrypting\n");
   2693     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2694     kx->transcript_hash_ctx = NULL;
   2695     GNUNET_MQ_discard (env);
   2696     return;
   2697   }
   2698   /* Forward the transcript */
   2699   GNUNET_CRYPTO_hash_context_read (
   2700     kx->transcript_hash_ctx,
   2701     &ihm_e[1],
   2702     c_len);
   2703 
   2704   kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_SENT;
   2705   kx->early_secret_key = es;
   2706   kx->early_traffic_secret = ets;
   2707   kx->ss_R = ss_R;
   2708   monitor_notify_all (kx);
   2709   GNUNET_MQ_send_copy (kx->mq, env);
   2710   kx->resend_env = env;
   2711   kx->resend_tries_left = RESEND_MAX_TRIES;
   2712   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   2713                                                   &resend_initiator_hello,
   2714                                                   kx);
   2715 }
   2716 
   2717 
   2718 static void
   2719 check_rekey (struct GSC_KeyExchangeInfo *kx)
   2720 {
   2721   struct GNUNET_ShortHashCode new_ats;
   2722 
   2723   if ((UINT64_MAX == kx->current_sqn) ||
   2724       (GNUNET_TIME_absolute_is_past (kx->current_epoch_expiration)))
   2725   {
   2726     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2727                 "Epoch expiration %" PRIu64 " SQN %" PRIu64
   2728                 ", incrementing epoch...\n",
   2729                 kx->current_epoch_expiration.abs_value_us,
   2730                 kx->current_sqn);
   2731     // Can this trigger? Maybe if we receive a lot of
   2732     // heartbeats?
   2733     GNUNET_assert (UINT64_MAX > kx->current_epoch);
   2734     kx->current_epoch++;
   2735     kx->current_epoch_expiration =
   2736       GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2737     kx->current_sqn = 0;
   2738     derive_next_ats (&kx->current_ats,
   2739                      &new_ats);
   2740     memcpy (&kx->current_ats,
   2741             &new_ats,
   2742             sizeof new_ats);
   2743   }
   2744 }
   2745 
   2746 
   2747 /**
   2748  * Encrypt and transmit payload
   2749  * @param kx key exchange info
   2750  * @param payload the payload
   2751  * @param payload_size size of the payload
   2752  */
   2753 void
   2754 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
   2755                              const void *payload,
   2756                              size_t payload_size)
   2757 {
   2758   struct GNUNET_MQ_Envelope *env;
   2759   struct EncryptedMessage *encrypted_msg;
   2760   unsigned char enc_key[AEAD_KEY_BYTES];
   2761   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2762   unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
   2763   uint64_t sqn;
   2764   uint64_t epoch;
   2765   int8_t ret;
   2766 
   2767   encrypted_msg = NULL;
   2768 
   2769   check_rekey (kx);
   2770   sqn = kx->current_sqn;
   2771   epoch = kx->current_epoch;
   2772   /* We are the sender and as we are going to send,
   2773    * we are using the initiator key material */
   2774   derive_per_message_secrets (&kx->current_ats,
   2775                               sqn,
   2776                               enc_key,
   2777                               enc_nonce);
   2778   kx->current_sqn++;
   2779   derive_sn (&kx->current_ats,
   2780              seq_enc_k,
   2781              sizeof seq_enc_k);
   2782   env = GNUNET_MQ_msg_extra (encrypted_msg,
   2783                              payload_size,
   2784                              GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE);
   2785   // only encrypt the payload for now
   2786   // TODO encrypt other fields as well
   2787   ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
   2788     (unsigned char*) &encrypted_msg[1],     // c - resulting ciphertext
   2789     (unsigned char*) &encrypted_msg->tag,     // mac - resulting mac/tag
   2790     NULL,     // maclen
   2791     (unsigned char*) payload,     // m - plain message
   2792     payload_size,     // mlen
   2793     NULL,     // ad - additional data TODO also cover the unencrypted part (epoch)
   2794     0,     // adlen
   2795     NULL,     // nsec - unused
   2796     enc_nonce,     // npub nonce
   2797     enc_key     // k - key
   2798     );
   2799   if (0 != ret)
   2800   {
   2801     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2802                 "Something went wrong encrypting message\n");
   2803     GNUNET_assert (0);
   2804   }
   2805   {
   2806     /* compute the sequence number */
   2807     unsigned char *seq_enc_nonce;
   2808     uint64_t seq_nbo;
   2809     uint32_t seq_enc_ctr;
   2810 
   2811     seq_nbo = GNUNET_htonll (sqn);
   2812     seq_enc_ctr = *((uint32_t*) encrypted_msg->tag);
   2813     seq_enc_nonce = &encrypted_msg->tag[sizeof (uint32_t)];
   2814     crypto_stream_chacha20_ietf_xor_ic (
   2815       (unsigned char*) &encrypted_msg->sequence_number,
   2816       (unsigned char*) &seq_nbo,
   2817       sizeof seq_nbo,
   2818       seq_enc_nonce,
   2819       ntohl (seq_enc_ctr),
   2820       seq_enc_k);
   2821 #if DEBUG_KX
   2822     GNUNET_print_bytes (seq_enc_k,
   2823                         sizeof seq_enc_k,
   2824                         8,
   2825                         GNUNET_NO);
   2826     GNUNET_print_bytes ((char*) &seq_enc_ctr,
   2827                         sizeof seq_enc_ctr,
   2828                         8,
   2829                         GNUNET_NO);
   2830 #endif
   2831     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2832                 "Sending encrypted message with E(SQN=%" PRIu64 ")=%" PRIu64
   2833                 "\n",
   2834                 sqn,
   2835                 encrypted_msg->sequence_number);
   2836   }
   2837   encrypted_msg->epoch = GNUNET_htonll (epoch);
   2838 
   2839   // TODO actually copy payload
   2840   GNUNET_MQ_send (kx->mq, env);
   2841 }
   2842 
   2843 
   2844 void
   2845 GSC_KX_start (void)
   2846 {
   2847   const struct GNUNET_PeerIdentity *my_identity;
   2848   struct GNUNET_MQ_MessageHandler handlers[] = {
   2849     GNUNET_MQ_hd_var_size (initiator_hello,
   2850                            GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO,
   2851                            struct InitiatorHello,
   2852                            NULL),
   2853     GNUNET_MQ_hd_var_size (initiator_done,
   2854                            GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE,
   2855                            struct InitiatorDone,
   2856                            NULL),
   2857     GNUNET_MQ_hd_var_size (responder_hello,
   2858                            GNUNET_MESSAGE_TYPE_CORE_RESPONDER_HELLO,
   2859                            struct ResponderHello,
   2860                            NULL),
   2861     GNUNET_MQ_hd_var_size   (encrypted_message, // TODO rename?
   2862                              GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE,  // TODO rename!
   2863                              struct EncryptedMessage,
   2864                              NULL),
   2865     GNUNET_MQ_handler_end ()
   2866   };
   2867 
   2868   my_identity = GNUNET_PILS_get_identity (GSC_pils);
   2869   GNUNET_assert (NULL != my_identity);
   2870 
   2871   nc = GNUNET_notification_context_create (1);
   2872   transport =
   2873     GNUNET_TRANSPORT_core_connect (GSC_cfg,
   2874                                    my_identity,
   2875                                    handlers,
   2876                                    NULL, // cls - this connection-independant
   2877                                          // cls seems not to be needed.
   2878                                          // the connection-specific cls
   2879                                          // will be set as a return value
   2880                                          // of
   2881                                          // handle_transport_notify_connect
   2882                                    &handle_transport_notify_connect,
   2883                                    &handle_transport_notify_disconnect);
   2884   if (NULL == transport)
   2885   {
   2886     GSC_KX_done ();
   2887     return;
   2888   }
   2889 
   2890   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2891               "Connected to TRANSPORT\n");
   2892 
   2893   GSC_complete_initialization_cb ();
   2894 }
   2895 
   2896 
   2897 void
   2898 pid_change_cb (void *cls,
   2899                const struct GNUNET_HELLO_Parser *parser,
   2900                const struct GNUNET_HashCode *hash)
   2901 {
   2902   if (NULL != transport)
   2903     return;
   2904 
   2905   GSC_KX_start ();
   2906 }
   2907 
   2908 
   2909 /**
   2910  * Initialize KX subsystem.
   2911  *
   2912  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
   2913  */
   2914 int
   2915 GSC_KX_init (void)
   2916 {
   2917   GSC_pils = GNUNET_PILS_connect (GSC_cfg,
   2918                                   &pid_change_cb,
   2919                                   NULL);
   2920   if (NULL == GSC_pils)
   2921   {
   2922     GSC_KX_done ();
   2923     return GNUNET_SYSERR;
   2924   }
   2925 
   2926   return GNUNET_OK;
   2927 }
   2928 
   2929 
   2930 /**
   2931  * Shutdown KX subsystem.
   2932  */
   2933 void
   2934 GSC_KX_done ()
   2935 {
   2936   struct PilsRequest *pr;
   2937   while (NULL != (pr = pils_requests_head))
   2938   {
   2939     GNUNET_CONTAINER_DLL_remove (pils_requests_head,
   2940                                  pils_requests_tail,
   2941                                  pr);
   2942     if (NULL != pr->op)
   2943       GNUNET_PILS_cancel (pr->op);
   2944     GNUNET_free (pr);
   2945   }
   2946   if (NULL != GSC_pils)
   2947   {
   2948     GNUNET_PILS_disconnect (GSC_pils);
   2949     GSC_pils = NULL;
   2950   }
   2951   if (NULL != transport)
   2952   {
   2953     GNUNET_TRANSPORT_core_disconnect (transport);
   2954     transport = NULL;
   2955   }
   2956   if (NULL != rekey_task)
   2957   {
   2958     GNUNET_SCHEDULER_cancel (rekey_task);
   2959     rekey_task = NULL;
   2960   }
   2961   if (NULL != nc)
   2962   {
   2963     GNUNET_notification_context_destroy (nc);
   2964     nc = NULL;
   2965   }
   2966 }
   2967 
   2968 
   2969 /**
   2970  * Check how many messages are queued for the given neighbour.
   2971  *
   2972  * @param kxinfo data about neighbour to check
   2973  * @return number of items in the message queue
   2974  */
   2975 unsigned int
   2976 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
   2977 {
   2978   return GNUNET_MQ_get_length (kxinfo->mq);
   2979 }
   2980 
   2981 
   2982 int
   2983 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
   2984 {
   2985   return kxinfo->has_excess_bandwidth;
   2986 }
   2987 
   2988 
   2989 /**
   2990  * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.  For this
   2991  * request type, the client does not have to have transmitted an INIT
   2992  * request.  All current peers are returned, regardless of which
   2993  * message types they accept.
   2994  *
   2995  * @param mq message queue to add for monitoring
   2996  */
   2997 void
   2998 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
   2999 {
   3000   struct GNUNET_MQ_Envelope *env;
   3001   struct MonitorNotifyMessage *done_msg;
   3002   struct GSC_KeyExchangeInfo *kx;
   3003 
   3004   GNUNET_notification_context_add (nc, mq);
   3005   for (kx = kx_head; NULL != kx; kx = kx->next)
   3006   {
   3007     struct GNUNET_MQ_Envelope *env_notify;
   3008     struct MonitorNotifyMessage *msg;
   3009 
   3010     env_notify = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
   3011     msg->state = htonl ((uint32_t) kx->status);
   3012     msg->peer = kx->peer;
   3013     msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
   3014     GNUNET_MQ_send (mq, env_notify);
   3015   }
   3016   env = GNUNET_MQ_msg (done_msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
   3017   done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
   3018   done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
   3019   GNUNET_MQ_send (mq, env);
   3020 }
   3021 
   3022 
   3023 /* end of gnunet-service-core_kx.c */