gnunet

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

gnunet-service-core_kx.c (96590B)


      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 "platform.h"
     38 #include "gnunet_common.h"
     39 #include "gnunet_util_lib.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 (UINT64_MAX);
   1239 
   1240   // c_e
   1241   GNUNET_memcpy (&rhm_e->c_e,
   1242                  &ephemeral_kem_challenge,
   1243                  sizeof (ephemeral_kem_challenge));
   1244   GNUNET_CRYPTO_hash_context_read (hc,
   1245                                    rhm_e,
   1246                                    sizeof (struct ResponderHello));
   1247   // 2. Encrypt ServicesInfo and c_I with RHTS
   1248   // derive RHTS
   1249   {
   1250     struct GNUNET_HashCode transcript;
   1251     snapshot_transcript (hc,
   1252                          &transcript);
   1253 #if DEBUG_KX
   1254     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1255                 "Transcript snapshot for derivation of *HTS: `%s'\n",
   1256                 GNUNET_h2s (&transcript));
   1257 #endif
   1258     derive_rhts (&transcript,
   1259                  &hs,
   1260                  &rhts);
   1261     derive_ihts (&transcript,
   1262                  &hs,
   1263                  &ihts);
   1264     derive_per_message_secrets (&rhts,
   1265                                 0,
   1266                                 enc_key,
   1267                                 enc_nonce);
   1268   }
   1269   // c_I
   1270   GNUNET_memcpy (&rhp->c_I, &c_I, sizeof (c_I));
   1271   // Services info empty for now.
   1272   GNUNET_memcpy (&rhp[1],
   1273                  my_services_info,
   1274                  strlen (my_services_info));
   1275 
   1276   {
   1277     unsigned long long out_ct_len;
   1278     struct GNUNET_HashCode finished;
   1279     struct GNUNET_HashCode transcript;
   1280     unsigned char *finished_buf;
   1281     GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1282                      (unsigned char*) &rhm_e[1], /* c - ciphertext */
   1283                      &out_ct_len, /* clen_p */
   1284                      rhp_buf, /* rhm_p - plaintext message */
   1285                      rhp_len, // mlen
   1286                      NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1287                               // fields?
   1288                      NULL, // nsec - unused
   1289                      enc_nonce, // npub - nonce // FIXME nonce can be reused
   1290                      enc_key)); // k - key RHTS
   1291     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1292                 "Encrypted and wrote %llu bytes\n",
   1293                 out_ct_len);
   1294     // 3. Create ResponderFinished (Section 6)
   1295     // Derive fk_I <- HKDF-Expand (MS, "r finished", NULL)
   1296     /* Forward the transcript */
   1297     /* {svcinfo, c_I}RHTS */
   1298     GNUNET_CRYPTO_hash_context_read (
   1299       hc,
   1300       &rhm_e[1],
   1301       out_ct_len);
   1302 
   1303     finished_buf = ((unsigned char*) &rhm_e[1]) + out_ct_len;
   1304     snapshot_transcript (hc,
   1305                          &transcript);
   1306 #if DEBUG_KX
   1307     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1308                 "Transcript snapshot for derivation of Rfinished: `%s'\n",
   1309                 GNUNET_h2s (&transcript));
   1310 #endif
   1311     generate_responder_finished (&transcript,
   1312                                  &ms,
   1313                                  &finished);
   1314     // 4. Encrypt ResponderFinished
   1315     derive_per_message_secrets (&rhts,
   1316                                 1,
   1317                                 enc_key,
   1318                                 enc_nonce);
   1319     GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1320                      finished_buf,                               /* c - ciphertext */
   1321                      &out_ct_len, /* clen_p */
   1322                      (unsigned char*) &finished, /* rhm_p - plaintext message */
   1323                      sizeof (finished), // mlen
   1324                      NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1325                               // fields?
   1326                      NULL, // nsec - unused
   1327                      enc_nonce, // npub
   1328                      enc_key)); // k - key RHTS
   1329     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1330                 "Encrypted and wrote %llu bytes\n",
   1331                 out_ct_len);
   1332     /* Forward the transcript
   1333      * after responder finished,
   1334      * before deriving *ATS and generating finished_I
   1335      * (finished_I will be generated when receiving the InitiatorFinished message
   1336      * in order to check it) */
   1337     GNUNET_CRYPTO_hash_context_read (
   1338       hc,
   1339       finished_buf,
   1340       out_ct_len);
   1341     // 5. optionally send application data - encrypted with RATS
   1342     // We do not really have any application data, instead, we send the ACK
   1343     snapshot_transcript (hc,
   1344                          &transcript);
   1345 #if DEBUG_KX
   1346     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1347                 "Transcript snapshot for derivation of *ATS: `%s'\n",
   1348                 GNUNET_h2s (&transcript));
   1349 #endif
   1350     derive_initial_ats (&transcript,
   1351                         &ms,
   1352                         ROLE_RESPONDER,
   1353                         &kx->current_ats);
   1354   }
   1355   /* Lock into struct */
   1356   GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1357   kx->transcript_hash_ctx = hc;
   1358   kx->master_secret = ms;
   1359   kx->handshake_secret = hs;
   1360   kx->ss_e = ss_e;
   1361   kx->ihts = ihts;
   1362   kx->rhts = rhts;
   1363   kx->ss_I = ss_I;
   1364   kx->current_epoch = 0;
   1365   kx->current_sqn = 0;
   1366   derive_per_message_secrets (&kx->current_ats,
   1367                               kx->current_sqn,
   1368                               enc_key,
   1369                               enc_nonce);
   1370 
   1371   GNUNET_MQ_send_copy (kx->mq, env);
   1372   kx->resend_env = env;
   1373   kx->resend_tries_left = RESEND_MAX_TRIES;
   1374   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent ResponderHello: %d %d\n", kx->role,
   1375               kx->status);
   1376 
   1377   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   1378                                                   &resend_responder_hello,
   1379                                                   kx);
   1380   kx->status = GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT;
   1381   monitor_notify_all (kx);
   1382   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1383 }
   1384 
   1385 
   1386 static void
   1387 handle_initiator_hello_cont (void *cls, const struct GNUNET_ShortHashCode *ss_R)
   1388 {
   1389   const struct GNUNET_HashCode *my_identity_hash;
   1390   struct InitiatorHelloCtx *ihm_ctx = cls;
   1391   struct GSC_KeyExchangeInfo *kx = ihm_ctx->kx;
   1392   uint32_t ihm_len = ntohs (ihm_ctx->ihm_e->header.size);
   1393   unsigned char enc_key[AEAD_KEY_BYTES];
   1394   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   1395   struct GNUNET_HashCode h1;
   1396   struct GNUNET_HashCode transcript;
   1397   struct GNUNET_ShortHashCode es;
   1398   struct GNUNET_ShortHashCode ets;
   1399   enum GNUNET_GenericReturnValue ret;
   1400 
   1401   ihm_ctx->req->op = NULL;
   1402   GNUNET_CONTAINER_DLL_remove (pils_requests_head,
   1403                                pils_requests_tail,
   1404                                ihm_ctx->req);
   1405   GNUNET_free (ihm_ctx->req);
   1406 
   1407 
   1408   GNUNET_memcpy (&kx->pk_e.ecdhe_key,
   1409                  &ihm_ctx->ihm_e->pk_e,
   1410                  sizeof (ihm_ctx->ihm_e->pk_e));
   1411   //      5. generate ETS (early_traffic_secret_key, decrypt pk_i
   1412   //         expand ETS <- expand ES <- extract ss_R
   1413   //         use ETS to decrypt
   1414 
   1415   /* Forward the transcript hash context over the unencrypted fields to get it
   1416    * to the same status that the initiator had when it needed to derive es and
   1417    * ets for the encryption */
   1418   GNUNET_CRYPTO_hash_context_read (
   1419     kx->transcript_hash_ctx,
   1420     ihm_ctx->ihm_e,
   1421     sizeof (struct InitiatorHello));
   1422   snapshot_transcript (kx->transcript_hash_ctx,
   1423                        &transcript);
   1424 #if DEBUG_KX
   1425   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1426               "Transcript snapshot for derivation of ES, ETS: `%s'\n",
   1427               GNUNET_h2s (&transcript));
   1428 #endif
   1429   derive_es_ets (&transcript, ss_R, &es, &ets);
   1430   derive_per_message_secrets (&ets,
   1431                               0,
   1432                               enc_key,
   1433                               enc_nonce);
   1434   {
   1435     struct InitiatorHelloPayload *ihmp;
   1436     size_t ct_len = ihm_len - sizeof (struct InitiatorHello);
   1437     unsigned char ihmp_buf[ct_len - AEAD_TAG_BYTES];
   1438     ihmp = (struct InitiatorHelloPayload*) ihmp_buf;
   1439     ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   1440       ihmp_buf,   // unsigned char *m
   1441       NULL,                                      // mlen_p message length
   1442       NULL,                                      // unsigned char *nsec       - unused: NULL
   1443       (unsigned char*) &ihm_ctx->ihm_e[1],   // const unsigned char *c    - ciphertext
   1444       ct_len,                                     // unsigned long long clen   - length of ciphertext
   1445       // mac,                                   // const unsigned char *mac  - authentication tag
   1446       NULL,                                      // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   1447       0,                                         // unsigned long long adlen
   1448       enc_nonce,      // const unsigned char *npub - nonce
   1449       enc_key   // const unsigned char *k    - key
   1450       );
   1451     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pid_sender: %s\n",
   1452                 GNUNET_i2s (&ihmp->pk_I));
   1453     if (0 != ret)
   1454     {
   1455       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1456                   "Something went wrong decrypting: %d\n", ret);
   1457       GNUNET_break_op (0);
   1458       GNUNET_free (ihm_ctx->ihm_e);
   1459       GNUNET_free (ihm_ctx);
   1460       restart_kx (kx);
   1461       return;
   1462     }
   1463     /* now forward it considering the encrypted messages that the initiator was
   1464      * able to send after deriving the es and ets */
   1465     GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx,
   1466                                      &ihm_ctx->ihm_e[1],
   1467                                      ct_len);
   1468     GNUNET_memcpy (&kx->peer,
   1469                    &ihmp->pk_I,
   1470                    sizeof (struct GNUNET_PeerIdentity));
   1471   }
   1472 
   1473   my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils);
   1474   GNUNET_assert (NULL != my_identity_hash);
   1475 
   1476   // We could follow with the rest of the Key Schedule (dES, HS, ...) for now
   1477   /* Check that we are actually in the receiving role */
   1478   GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1);
   1479   if (0 < GNUNET_CRYPTO_hash_cmp (&h1, my_identity_hash))
   1480   {
   1481     /* peer with "lower" identity starts KX, otherwise we typically end up
   1482        with both peers starting the exchange and transmit the 'set key'
   1483        message twice */
   1484     /* Something went wrong - we have the lower value and should have sent the
   1485      * InitiatorHello, but instead received it. TODO handle this case
   1486      * We might end up in this case if the initiator didn't initiate the
   1487      * handshake long enough and the 'responder' initiates the handshake */
   1488     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1489                 "Something went wrong - we have the lower value and should have sent the InitiatorHello, but instead received it.\n");
   1490     GNUNET_free (ihm_ctx->ihm_e);
   1491     GNUNET_free (ihm_ctx);
   1492     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1493     kx->transcript_hash_ctx = NULL;
   1494     return;
   1495   }
   1496 
   1497   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer ID of other peer: %s\n", GNUNET_i2s
   1498                 (&kx->peer));
   1499   /* We update the monitoring peers here because now we know
   1500    * that we can decrypt the message AND know the PID
   1501    */
   1502   monitor_notify_all (kx);
   1503   kx->ss_R = *ss_R;
   1504   kx->early_secret_key = es;
   1505   kx->early_traffic_secret = ets;
   1506   send_responder_hello (kx);
   1507 }
   1508 
   1509 
   1510 static int
   1511 check_initiator_hello (void *cls, const struct InitiatorHello *m)
   1512 {
   1513   uint16_t size = ntohs (m->header.size);
   1514 
   1515   if (size < sizeof (*m)
   1516       + sizeof (struct InitiatorHelloPayload)
   1517       + AEAD_TAG_BYTES)
   1518   {
   1519     return GNUNET_SYSERR;
   1520   }
   1521   return GNUNET_OK;
   1522 }
   1523 
   1524 
   1525 /**
   1526  * Handle the InitiatorHello message
   1527  *  - derives necessary keys from the plaintext parts
   1528  *  - decrypts the encrypted part
   1529  *  - replies with ResponderHello message
   1530  * @param cls the key exchange info
   1531  * @param ihm_e InitiatorHello message
   1532  */
   1533 static void
   1534 handle_initiator_hello (void *cls, const struct InitiatorHello *ihm_e)
   1535 {
   1536   const struct GNUNET_HashCode *my_identity_hash;
   1537   struct GSC_KeyExchangeInfo *kx = cls;
   1538   struct InitiatorHelloCtx *initiator_hello_cls;
   1539   size_t ihm_len;
   1540 
   1541   if (ROLE_INITIATOR == kx->role)
   1542   {
   1543     GNUNET_break_op (0);
   1544     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1545                 "I am an initiator! Tearing down...\n");
   1546     return;
   1547   }
   1548   if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED)
   1549   {
   1550     GNUNET_break_op (0);
   1551     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1552                 "Already received InitiatorHello: %d %d\n", kx->role, kx->status
   1553                 );
   1554     return;
   1555   }
   1556   else if ((kx->status > GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED) &&
   1557            (NULL != kx->transcript_hash_ctx))
   1558   {
   1559     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1560                 "Already received InitiatorHello and sent ResponderHello: %d %d\n",
   1561                 kx->role, kx->status);
   1562     return;
   1563   }
   1564   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorHello: %d %d\n", kx->
   1565               role, kx->status);
   1566   GNUNET_assert (NULL == kx->transcript_hash_ctx);
   1567   kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start ();
   1568   GNUNET_assert (NULL != kx->transcript_hash_ctx);
   1569 
   1570   GNUNET_STATISTICS_update (GSC_stats,
   1571                             gettext_noop ("# key exchanges initiated"),
   1572                             1,
   1573                             GNUNET_NO);
   1574 
   1575   kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED;
   1576 
   1577   my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils);
   1578   GNUNET_assert (NULL != my_identity_hash);
   1579 
   1580   //      1. verify type _INITIATOR_HELLO
   1581   //         - This is implicytly done by arriving within this handler
   1582   //         - or is this about verifying the 'additional data' part of aead?
   1583   //           should it check the encryption + mac? (is this implicitly done
   1584   //           while decrypting?)
   1585   //      2. verify H(pk_R) matches pk_R
   1586   if (0 != memcmp (&ihm_e->h_pk_R,
   1587                    my_identity_hash,
   1588                    sizeof (struct GNUNET_HashCode)))
   1589   {
   1590     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1591                 "This message is not meant for us (H(PID) mismatch)\n");
   1592     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1593     kx->transcript_hash_ctx = NULL;
   1594     return;
   1595   }
   1596   // FIXME this sometimes triggers in the tests - why?
   1597   //      3. decaps -> shared_secret_R, c_R (kemChallenge)
   1598   ihm_len = ntohs (ihm_e->header.size);
   1599   initiator_hello_cls = GNUNET_new (struct InitiatorHelloCtx);
   1600   initiator_hello_cls->kx = kx;
   1601   initiator_hello_cls->ihm_e = GNUNET_malloc (ihm_len);
   1602   GNUNET_memcpy (initiator_hello_cls->ihm_e, ihm_e, ihm_len);
   1603   initiator_hello_cls->req = GNUNET_new (struct PilsRequest);
   1604   GNUNET_CONTAINER_DLL_insert (pils_requests_head,
   1605                                pils_requests_tail,
   1606                                initiator_hello_cls->req);
   1607   initiator_hello_cls->req->op =
   1608     GNUNET_PILS_kem_decaps (GSC_pils,
   1609                             &ihm_e->c_R,
   1610                             // encapsulated key
   1611                             &handle_initiator_hello_cont,
   1612                             // continuation
   1613                             initiator_hello_cls);
   1614 }
   1615 
   1616 
   1617 struct ResponderHelloCls
   1618 {
   1619   /* Current KX session */
   1620   struct GSC_KeyExchangeInfo *kx;
   1621 
   1622   /* responder hello message - encrypted */
   1623   struct ResponderHello rhm_e;
   1624 
   1625   /* responder hello message - plain/decrypted */
   1626   struct ResponderHelloPayload *rhp;
   1627 
   1628   /* Decrypted finish hash */
   1629   struct GNUNET_HashCode decrypted_finish;
   1630 
   1631   /* Encrypted finished CT (for transcript later) */
   1632   char finished_enc[sizeof (struct GNUNET_HashCode)
   1633                     + AEAD_TAG_BYTES];
   1634 
   1635   /* Temporary transcript context */
   1636   struct GNUNET_HashContext *hc;
   1637 
   1638   /* Temporary handshake secret */
   1639   struct GNUNET_ShortHashCode hs;
   1640 
   1641   /* Temporary handshake secret */
   1642   struct GNUNET_ShortHashCode ss_e;
   1643 
   1644   /* Temporary handshake secret */
   1645   struct GNUNET_ShortHashCode ihts;
   1646 
   1647   /* Temporary handshake secret */
   1648   struct GNUNET_ShortHashCode rhts;
   1649 
   1650   /* Pending PILS request */
   1651   struct PilsRequest *req;
   1652 };
   1653 
   1654 static void
   1655 resend_initiator_done (void *cls)
   1656 {
   1657   struct GSC_KeyExchangeInfo *kx = cls;
   1658 
   1659   kx->resend_task = NULL;
   1660   if (0 == kx->resend_tries_left)
   1661   {
   1662     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1663                 "Restarting KX\n");
   1664     restart_kx (kx);
   1665     return;
   1666   }
   1667   kx->resend_tries_left--;
   1668   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1669               "Resending initiator done. Retries left: %u\n",
   1670               kx->resend_tries_left);
   1671   GNUNET_MQ_send_copy (kx->mq, kx->resend_env);
   1672   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   1673                                                   &resend_initiator_done,
   1674                                                   kx);
   1675 }
   1676 
   1677 
   1678 static void
   1679 handle_responder_hello_cont (void *cls, const struct GNUNET_ShortHashCode *ss_I)
   1680 {
   1681   struct ResponderHelloCls *rh_ctx = cls;
   1682   struct GSC_KeyExchangeInfo *kx = rh_ctx->kx;
   1683   struct InitiatorDone *idm_e; /* encrypted */
   1684   struct InitiatorDone idm_local;
   1685   struct InitiatorDone *idm_p; /* plaintext */
   1686   struct GNUNET_MQ_Envelope *env;
   1687   unsigned char enc_key[AEAD_KEY_BYTES];
   1688   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   1689   struct ConfirmationAck ack_i;
   1690   struct GNUNET_HashCode transcript;
   1691   struct GNUNET_ShortHashCode ms;
   1692 
   1693   rh_ctx->req->op = NULL;
   1694   GNUNET_CONTAINER_DLL_remove (pils_requests_head,
   1695                                pils_requests_tail,
   1696                                rh_ctx->req);
   1697   GNUNET_free (rh_ctx->req);
   1698   // XXX valgrind reports uninitialized memory
   1699   //     the following is a way to check whether this memory was meant
   1700   // memset (&rhm_local, 0, sizeof (rhm_local)); - adapt to cls if still needed
   1701   memset (&idm_local, 0, sizeof (idm_local));
   1702 
   1703   kx->ss_I = *ss_I;
   1704 
   1705   /* derive *ATS */
   1706   derive_ms (&rh_ctx->hs, ss_I, &ms);;
   1707   // 5. Create ResponderFinished as per Section 6 and check against decrypted payload.
   1708   struct GNUNET_HashCode responder_finished;
   1709   // Transcript updates, snapshot again
   1710   snapshot_transcript (rh_ctx->hc,
   1711                        &transcript);
   1712 #if DEBUG_KX
   1713   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1714               "Transcript snapshot for derivation of Rfinished: `%s'\n",
   1715               GNUNET_h2s (&transcript));
   1716 #endif
   1717   generate_responder_finished (&transcript,
   1718                                &ms,
   1719                                &responder_finished);
   1720   if (0 != memcmp (&rh_ctx->decrypted_finish,
   1721                    &responder_finished,
   1722                    sizeof (struct GNUNET_HashCode)))
   1723   {
   1724     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1725                 "Could not verify \"responder finished\"\n");
   1726     GNUNET_free (rh_ctx->rhp);
   1727     GNUNET_CRYPTO_hash_context_abort (rh_ctx->hc);
   1728     GNUNET_free (rh_ctx);
   1729     GNUNET_assert (0);
   1730     return;
   1731   }
   1732 
   1733 
   1734   /* Forward the transcript
   1735    * after generating finished_R,
   1736    * before deriving *ATS */
   1737   GNUNET_CRYPTO_hash_context_read (
   1738     rh_ctx->hc,
   1739     rh_ctx->finished_enc,
   1740     sizeof (rh_ctx->finished_enc));
   1741 
   1742   // At this point we cannot fail anymore and may lock into kx
   1743   GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1744   kx->transcript_hash_ctx = rh_ctx->hc;
   1745   kx->ss_I = *ss_I;
   1746   kx->handshake_secret = rh_ctx->hs;
   1747   kx->ss_e = rh_ctx->ss_e;
   1748   kx->ihts = rh_ctx->ihts;
   1749   kx->rhts = rh_ctx->rhts;
   1750   kx->master_secret = ms;
   1751   GNUNET_free (rh_ctx->rhp);
   1752   GNUNET_free (rh_ctx);
   1753   rh_ctx = NULL;
   1754 
   1755   snapshot_transcript (kx->transcript_hash_ctx,
   1756                        &transcript);
   1757 #if DEBUG_KX
   1758   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1759               "Transcript snapshot for derivation of *ATS: `%s'\n",
   1760               GNUNET_h2s (&transcript));
   1761 #endif
   1762   derive_initial_ats (&transcript,
   1763                       &kx->master_secret,
   1764                       ROLE_RESPONDER,
   1765                       &kx->their_ats[0]);
   1766   for (int i = 0; i < MAX_EPOCHS - 1; i++)
   1767   {
   1768     derive_next_ats (&kx->their_ats[i],
   1769                      &kx->their_ats[i + 1]);
   1770   }
   1771   kx->their_max_epoch = MAX_EPOCHS - 1;
   1772 
   1773   derive_per_message_secrets (&kx->ihts,
   1774                               0,
   1775                               enc_key,
   1776                               enc_nonce);
   1777   /* Create InitiatorDone message */
   1778   idm_p = &idm_local; /* plaintext */
   1779   env = GNUNET_MQ_msg_extra (idm_e,
   1780                              sizeof (ack_i)
   1781                              + AEAD_TAG_BYTES,
   1782                              GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE);
   1783   // 6. Create IteratorFinished as per Section 6.
   1784   generate_initiator_finished (&transcript,
   1785                                &kx->master_secret,
   1786                                &idm_p->finished);
   1787   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1788               "InteratorFinished: `%s'\n",
   1789               GNUNET_h2s (&idm_p->finished));
   1790   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1791               "Transcript `%s'\n",
   1792               GNUNET_h2s (&transcript));
   1793   // 7. Send InteratorFinished message encrypted with the key derived from IHTS to R
   1794 
   1795   GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1796                    (unsigned char*) &idm_e->finished, /* c - ciphertext */
   1797                    NULL, /* clen_p */
   1798                    (unsigned char*) &idm_p->finished, /* idm_p - plaintext message */
   1799                    sizeof (idm_p->finished), // mlen
   1800                    NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1801                             // fields?
   1802                    NULL, // nsec - unused
   1803                    enc_nonce, // npub - nonce
   1804                    enc_key)); // k - key IHTS
   1805   /* Forward the transcript hash context
   1806    * after generating finished_I and RATS_0
   1807    * before deriving IATS_0 */
   1808   GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx,
   1809                                    &idm_e->finished,
   1810                                    sizeof (idm_e->finished)
   1811                                    + AEAD_TAG_BYTES);
   1812   snapshot_transcript (kx->transcript_hash_ctx,
   1813                        &transcript);
   1814 #if DEBUG_KX
   1815   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1816               "Transcript snapshot for derivation of *ATS: `%s'\n",
   1817               GNUNET_h2s (&transcript));
   1818 #endif
   1819   derive_initial_ats (&transcript,
   1820                       &kx->master_secret,
   1821                       ROLE_INITIATOR,
   1822                       &kx->current_ats);
   1823   kx->current_epoch = 0;
   1824   kx->current_sqn++;
   1825   // 8. optionally encrypt payload TODO
   1826   derive_per_message_secrets (&kx->current_ats,
   1827                               kx->current_sqn,
   1828                               enc_key,
   1829                               enc_nonce);
   1830   kx->current_sqn++;
   1831   ack_i.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   1832   ack_i.header.size = htons (sizeof ack_i);
   1833   GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1834                    (unsigned char*) &idm_e[1], /* c - ciphertext */
   1835                    NULL, /* clen_p */
   1836                    (unsigned char*) &ack_i, /* rhm_p - plaintext message */
   1837                    sizeof ack_i, // mlen
   1838                    NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1839                             // fields?
   1840                    NULL, // nsec - unused
   1841                    enc_nonce, // npub - nonce // FIXME nonce can be reused
   1842                    enc_key)); // k - key RHTS
   1843 
   1844   GNUNET_MQ_send_copy (kx->mq, env);
   1845   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent InitiatorDone: %d %d\n", kx->role,
   1846               kx->status);
   1847 
   1848 
   1849   kx->resend_env = env;
   1850   kx->resend_tries_left = RESEND_MAX_TRIES;
   1851   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   1852                                                   &resend_initiator_done,
   1853                                                   kx);
   1854   kx->status = GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT;
   1855   monitor_notify_all (kx);
   1856   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1857 }
   1858 
   1859 
   1860 static int
   1861 check_responder_hello (void *cls, const struct ResponderHello *m)
   1862 {
   1863   uint16_t size = ntohs (m->header.size);
   1864 
   1865   if (size < sizeof (*m)
   1866       + sizeof (struct ResponderHelloPayload)
   1867       + sizeof (struct GNUNET_HashCode)
   1868       + AEAD_TAG_BYTES * 2)
   1869   {
   1870     return GNUNET_SYSERR;
   1871   }
   1872   return GNUNET_OK;
   1873 }
   1874 
   1875 
   1876 /**
   1877  * Handle Responder Hello message
   1878  * @param cls key exchange info
   1879  * @param rhm_e ResponderHello message
   1880  */
   1881 static void
   1882 handle_responder_hello (void *cls, const struct ResponderHello *rhm_e)
   1883 {
   1884   struct GSC_KeyExchangeInfo *kx = cls;
   1885   struct PilsRequest *req;
   1886   struct ResponderHelloCls *rh_ctx;
   1887   struct GNUNET_HashCode transcript;
   1888   struct GNUNET_HashContext *hc;
   1889   unsigned char enc_key[AEAD_KEY_BYTES];
   1890   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   1891   enum GNUNET_GenericReturnValue ret;
   1892 
   1893   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ResponderHello: %d %d\n", kx->
   1894               role, kx->status);
   1895 
   1896   hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx);
   1897   if (NULL != kx->resend_task)
   1898   {
   1899     GNUNET_SCHEDULER_cancel (kx->resend_task);
   1900     kx->resend_task = NULL;
   1901   }
   1902   if (NULL != kx->resend_env)
   1903   {
   1904     GNUNET_free (kx->resend_env);
   1905     kx->resend_env = NULL;
   1906   }
   1907 
   1908   /* Forward the transcript hash context */
   1909   if (ROLE_RESPONDER == kx->role)
   1910   {
   1911     GNUNET_break_op (0);
   1912     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1913                 "I am the responder! Ignoring.\n");
   1914     GNUNET_CRYPTO_hash_context_abort (hc);
   1915     return;
   1916   }
   1917   GNUNET_CRYPTO_hash_context_read (hc,
   1918                                    rhm_e,
   1919                                    sizeof (struct ResponderHello));
   1920   // 1. Verify that the message type is CORE_RESPONDER_HELLO
   1921   //    - implicitly done by handling this message?
   1922   //    - or is this about verifying the 'additional data' part of aead?
   1923   //      should it check the encryption + mac? (is this implicitly done
   1924   //      while decrypting?)
   1925   // 2. sse <- Decaps(ske,ce)
   1926   rh_ctx = GNUNET_new (struct ResponderHelloCls);
   1927   ret = GNUNET_CRYPTO_hpke_kem_decaps (&kx->sk_e, // secret/private ephemeral key of initiator (us)
   1928                                        &rhm_e->c_e,    // encapsulated key
   1929                                        &rh_ctx->ss_e); // key - ss_e
   1930   if (GNUNET_OK != ret)
   1931   {
   1932     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1933                 "Something went wrong decapsulating ss_e\n");
   1934     GNUNET_CRYPTO_hash_context_abort (hc);
   1935     return;
   1936   }
   1937   // 3. Generate IHTS and RHTS from Section 5 and decrypt ServicesInfo, cI and ResponderFinished.
   1938   snapshot_transcript (hc, &transcript);
   1939 #if DEBUG_KX
   1940   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1941               "Transcript snapshot for derivation of HS, *HTS: `%s'\n",
   1942               GNUNET_h2s (&transcript));
   1943 #endif
   1944   derive_hs (&kx->early_secret_key,
   1945              &rh_ctx->ss_e,
   1946              &rh_ctx->hs);
   1947   derive_rhts (&transcript,
   1948                &rh_ctx->hs,
   1949                &rh_ctx->rhts);
   1950   derive_ihts (&transcript,
   1951                &rh_ctx->hs,
   1952                &rh_ctx->ihts);
   1953   derive_per_message_secrets (&rh_ctx->rhts,
   1954                               0,
   1955                               enc_key,
   1956                               enc_nonce);
   1957   rh_ctx->kx = kx;
   1958   GNUNET_memcpy (&rh_ctx->rhm_e, rhm_e, sizeof (*rhm_e));
   1959   {
   1960     unsigned long long int c_len;
   1961     unsigned char *finished_buf;
   1962     // use RHTS to decrypt
   1963     c_len = ntohs (rhm_e->header.size) - sizeof (*rhm_e)
   1964             - sizeof (struct GNUNET_HashCode)
   1965             - AEAD_TAG_BYTES;                                   // finished ct
   1966     rh_ctx->rhp = GNUNET_malloc (c_len
   1967                                  -
   1968                                  AEAD_TAG_BYTES);
   1969     rh_ctx->hc = hc;
   1970     finished_buf = ((unsigned char*) &rhm_e[1]) + c_len;
   1971     /* Forward the transcript_hash_ctx
   1972      * after rhts has been generated,
   1973      * before generating finished_R*/
   1974     GNUNET_CRYPTO_hash_context_read (
   1975       hc,
   1976       &rhm_e[1],
   1977       c_len);
   1978 
   1979     ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   1980       (unsigned char*) rh_ctx->rhp,   // unsigned char *m
   1981       NULL,                                     // mlen_p message length
   1982       NULL,                                     // unsigned char *nsec       - unused: NULL
   1983       (unsigned char*) &rhm_e[1],   // const unsigned char *c    - ciphertext
   1984       c_len,                                    // unsigned long long clen   - length of ciphertext
   1985       NULL,                                     // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   1986       0,                                        // unsigned long long adlen
   1987       enc_nonce,     // const unsigned char *npub - nonce
   1988       enc_key   // const unsigned char *k    - key
   1989       );
   1990     if (0 != ret)
   1991     {
   1992       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1993                   "Something went wrong decrypting: %d\n", ret);
   1994       GNUNET_free (rh_ctx->rhp);
   1995       GNUNET_free (rh_ctx);
   1996       GNUNET_CRYPTO_hash_context_abort (hc);
   1997       return;
   1998     }
   1999     // FIXME nonce reuse (see encryption)
   2000     derive_per_message_secrets (&rh_ctx->rhts,
   2001                                 1,
   2002                                 enc_key,
   2003                                 enc_nonce);
   2004     c_len = sizeof (struct GNUNET_HashCode)
   2005             + AEAD_TAG_BYTES;
   2006     ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2007       (unsigned char*) &rh_ctx->decrypted_finish,   // unsigned char *m
   2008       NULL,                                // mlen_p message length
   2009       NULL,                                // unsigned char *nsec       - unused: NULL
   2010       finished_buf,   // const unsigned char *c    - ciphertext
   2011       c_len,                               // unsigned long long clen   - length of ciphertext
   2012       NULL,                                // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2013       0,                                   // unsigned long long adlen
   2014       enc_nonce,   // const unsigned char *npub - nonce
   2015       enc_key   // const unsigned char *k    - key
   2016       );
   2017     if (0 != ret)
   2018     {
   2019       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2020                   "Something went wrong decrypting finished field: %d\n", ret);
   2021       GNUNET_free (rh_ctx->rhp);
   2022       GNUNET_free (rh_ctx);
   2023       GNUNET_CRYPTO_hash_context_abort (hc);
   2024       return;
   2025     }
   2026     GNUNET_memcpy (rh_ctx->finished_enc,
   2027                    finished_buf,
   2028                    c_len);
   2029   }
   2030   // 4. ssI <- Decaps(skI,cI).
   2031   req = GNUNET_new (struct PilsRequest);
   2032   rh_ctx->req = req;
   2033   GNUNET_CONTAINER_DLL_insert (pils_requests_head,
   2034                                pils_requests_tail,
   2035                                req);
   2036   req->op = GNUNET_PILS_kem_decaps (GSC_pils,
   2037                                     &rh_ctx->rhp->c_I, // encapsulated key
   2038                                     &handle_responder_hello_cont, // continuation
   2039                                     rh_ctx);
   2040 }
   2041 
   2042 
   2043 static int
   2044 check_initiator_done (void *cls, const struct InitiatorDone *m)
   2045 {
   2046   uint16_t size = ntohs (m->header.size);
   2047 
   2048   if (size < sizeof (*m) + sizeof (struct ConfirmationAck))
   2049   {
   2050     return GNUNET_SYSERR;
   2051   }
   2052   return GNUNET_OK;
   2053 }
   2054 
   2055 
   2056 /**
   2057  * Handle InitiatorDone message
   2058  * @param cls key exchange info
   2059  * @param idm_e InitiatorDone message
   2060  */
   2061 static void
   2062 handle_initiator_done (void *cls, const struct InitiatorDone *idm_e)
   2063 {
   2064   struct GSC_KeyExchangeInfo *kx = cls;
   2065   struct InitiatorDone idm_local;
   2066   struct InitiatorDone *idm_p = &idm_local; /* plaintext */
   2067   struct GNUNET_HashCode initiator_finished;
   2068   struct GNUNET_HashCode transcript;
   2069   struct GNUNET_ShortHashCode their_ats;
   2070   struct GNUNET_HashContext *hc;
   2071   unsigned char enc_key[AEAD_KEY_BYTES];
   2072   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2073   struct ConfirmationAck ack_i;
   2074   struct ConfirmationAck ack_r;
   2075   int8_t ret;
   2076 
   2077   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorDone: %d %d\n", kx->
   2078               role, kx->status);
   2079   if (NULL != kx->resend_task)
   2080   {
   2081     GNUNET_SCHEDULER_cancel (kx->resend_task);
   2082     kx->resend_task = NULL;
   2083   }
   2084   if (NULL != kx->resend_env)
   2085   {
   2086     GNUNET_free (kx->resend_env);
   2087     kx->resend_env = NULL;
   2088   }
   2089   if (ROLE_INITIATOR == kx->role)
   2090   {
   2091     GNUNET_break_op (0);
   2092     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2093                 "I am the initiator! Tearing down...\n");
   2094     return;
   2095   }
   2096   derive_per_message_secrets (&kx->ihts,
   2097                               0,
   2098                               enc_key,
   2099                               enc_nonce);
   2100   ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2101     (unsigned char*) &idm_p->finished,     // unsigned char *m
   2102     NULL,                                  // mlen_p message length
   2103     NULL,                                  // unsigned char *nsec       - unused: NULL
   2104     (unsigned char*) &idm_e->finished,     // const unsigned char *c    - ciphertext
   2105     sizeof (idm_p->finished)               // unsigned long long clen   - length of ciphertext
   2106     + AEAD_TAG_BYTES,
   2107     NULL,                                  // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2108     0,                                     // unsigned long long adlen
   2109     enc_nonce,     // const unsigned char *npub - nonce
   2110     enc_key     // const unsigned char *k    - key
   2111     );
   2112   if (0 != ret)
   2113   {
   2114     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2115                 "Something went wrong decrypting: %d\n", ret);
   2116     return;
   2117   }
   2118 
   2119   //      - verify finished_I
   2120   /* Generate finished_I
   2121    * after Forwarding until {finished_R}RHTS
   2122    *   (did so while we prepared responder hello)
   2123    * before forwarding to [{payload}RATS and] {finished_I}IHTS */
   2124   // (look at the end of handle_initiator_hello())
   2125   snapshot_transcript (kx->transcript_hash_ctx, &transcript);
   2126   generate_initiator_finished (&transcript,
   2127                                &kx->master_secret,
   2128                                &initiator_finished);
   2129   if (0 != memcmp (&idm_p->finished,
   2130                    &initiator_finished,
   2131                    sizeof (struct GNUNET_HashCode)))
   2132   {
   2133     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2134                 "Could not verify \"initiator finished\" hash.\n");
   2135     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2136                 "Want: `%s'\n",
   2137                 GNUNET_h2s (&initiator_finished));
   2138     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2139                 "Have: `%s'\n",
   2140                 GNUNET_h2s (&idm_p->finished));
   2141     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2142                 "Transcript `%s'\n",
   2143                 GNUNET_h2s (&transcript));
   2144     return;
   2145   }
   2146 
   2147   /* Forward the transcript hash_context_read */
   2148   hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx);
   2149   GNUNET_CRYPTO_hash_context_read (hc,
   2150                                    &idm_e->finished,
   2151                                    sizeof (idm_e->finished)
   2152                                    + AEAD_TAG_BYTES);
   2153   snapshot_transcript (hc, &transcript);
   2154   derive_initial_ats (&transcript,
   2155                       &kx->master_secret,
   2156                       ROLE_INITIATOR,
   2157                       &their_ats);
   2158   derive_per_message_secrets (&their_ats, // FIXME other HS epoch?
   2159                               0,
   2160                               enc_key,
   2161                               enc_nonce);
   2162   ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2163     (unsigned char*) &ack_i,     // unsigned char *m
   2164     NULL,                                  // mlen_p message length
   2165     NULL,                                  // unsigned char *nsec       - unused: NULL
   2166     (unsigned char*) &idm_e[1],     // const unsigned char *c    - ciphertext
   2167     sizeof (ack_i) + AEAD_TAG_BYTES,                                 // unsigned long long clen   - length of ciphertext
   2168     NULL,                                  // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2169     0,                                     // unsigned long long adlen
   2170     enc_nonce,     // const unsigned char *npub - nonce
   2171     enc_key     // const unsigned char *k    - key
   2172     );
   2173   if (0 != ret)
   2174   {
   2175     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2176                 "Something went wrong decrypting the Ack: %d\n", ret);
   2177     GNUNET_CRYPTO_hash_context_abort (hc);
   2178     return;
   2179   }
   2180   if ((sizeof ack_i != ntohs (ack_i.header.size)) ||
   2181       (GNUNET_MESSAGE_TYPE_CORE_ACK != ntohs (ack_i.header.type)))
   2182   {
   2183     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2184                 "Ack invalid!\n");
   2185     GNUNET_CRYPTO_hash_context_abort (hc);
   2186     return;
   2187   }
   2188   GNUNET_memcpy (&kx->their_ats[0],
   2189                  &their_ats,
   2190                  sizeof their_ats);
   2191   /**
   2192    * FIXME we do not really have to calculate all this now
   2193    */
   2194   for (int i = 0; i < MAX_EPOCHS - 1; i++)
   2195   {
   2196     derive_next_ats (&kx->their_ats[i],
   2197                      &kx->their_ats[i + 1]);
   2198   }
   2199   GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2200   kx->transcript_hash_ctx = hc;
   2201   kx->status = GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED;
   2202   kx->current_epoch_expiration =
   2203     GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2204   cleanup_handshake_secrets (kx);
   2205   monitor_notify_all (kx);
   2206   kx->current_sqn = 1;
   2207   GSC_SESSIONS_create (&kx->peer, kx, kx->class);
   2208   GNUNET_assert (NULL == kx->heartbeat_task);
   2209   update_timeout (kx);
   2210   ack_r.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   2211   ack_r.header.size = htons (sizeof ack_r);
   2212   GSC_KX_encrypt_and_transmit (kx,
   2213                                &ack_r,
   2214                                sizeof ack_r);
   2215 
   2216   GNUNET_TRANSPORT_core_receive_continue (transport,
   2217                                           &kx->peer);
   2218 }
   2219 
   2220 
   2221 /**
   2222  * Check an incoming encrypted message before handling it
   2223  * @param cls key exchange info
   2224  * @param m the encrypted message
   2225  */
   2226 static int
   2227 check_encrypted_message (void *cls, const struct EncryptedMessage *m)
   2228 {
   2229   uint16_t size = ntohs (m->header.size) - sizeof(*m);
   2230 
   2231   // TODO check (see check_encrypted ())
   2232   //       - check epoch
   2233   //       - check sequence number
   2234   if (size < sizeof(struct GNUNET_MessageHeader))
   2235   {
   2236     GNUNET_break_op (0);
   2237     return GNUNET_SYSERR;
   2238   }
   2239   return GNUNET_OK;
   2240 }
   2241 
   2242 
   2243 /**
   2244  * Handle a key update
   2245  * @param cls key exchange info
   2246  * @param m KeyUpdate message
   2247  */
   2248 static void
   2249 handle_heartbeat (struct GSC_KeyExchangeInfo *kx,
   2250                   const struct Heartbeat *m)
   2251 {
   2252   struct GNUNET_ShortHashCode new_ats;
   2253   struct ConfirmationAck ack;
   2254 
   2255   if (m->flags & GSC_HEARTBEAT_KEY_UPDATE_REQUESTED)
   2256   {
   2257     if (kx->current_epoch == UINT64_MAX)
   2258     {
   2259       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2260                   "Max epoch reached (you probably will never see this)\n");
   2261     }
   2262     else
   2263     {
   2264       kx->current_epoch++;
   2265       kx->current_epoch_expiration =
   2266         GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2267       kx->current_sqn = 0;
   2268       derive_next_ats (&kx->current_ats,
   2269                        &new_ats);
   2270       memcpy (&kx->current_ats,
   2271               &new_ats,
   2272               sizeof new_ats);
   2273     }
   2274   }
   2275   update_timeout (kx);
   2276   ack.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   2277   ack.header.size = htons (sizeof ack);
   2278   GSC_KX_encrypt_and_transmit (kx,
   2279                                &ack,
   2280                                sizeof ack);
   2281   if (NULL != kx->heartbeat_task)
   2282   {
   2283     GNUNET_SCHEDULER_cancel (kx->heartbeat_task);
   2284     kx->heartbeat_task = GNUNET_SCHEDULER_add_delayed (MIN_HEARTBEAT_FREQUENCY,
   2285                                                        &send_heartbeat,
   2286                                                        kx);
   2287   }
   2288   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2289 }
   2290 
   2291 
   2292 static enum GNUNET_GenericReturnValue
   2293 check_if_ack_or_heartbeat (struct GSC_KeyExchangeInfo *kx,
   2294                            const char *buf,
   2295                            size_t buf_len)
   2296 {
   2297   struct GNUNET_MessageHeader *msg;
   2298   struct ConfirmationAck *ack;
   2299   struct Heartbeat *hb;
   2300 
   2301   if (sizeof *msg > buf_len)
   2302     return GNUNET_NO;
   2303   msg = (struct GNUNET_MessageHeader*) buf;
   2304   if (GNUNET_MESSAGE_TYPE_CORE_ACK == ntohs (msg->type))
   2305   {
   2306     ack = (struct ConfirmationAck *) buf;
   2307     if (sizeof *ack != ntohs (ack->header.size))
   2308       return GNUNET_NO;
   2309   }
   2310   else if  (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT == ntohs (msg->type))
   2311   {
   2312     hb = (struct Heartbeat*) buf;
   2313     if (sizeof *hb != ntohs (hb->header.size))
   2314       return GNUNET_NO;
   2315     handle_heartbeat (kx, hb);
   2316   }
   2317   else
   2318   {
   2319     return GNUNET_NO;
   2320   }
   2321 
   2322   /**
   2323    * Waiting for ACK or heartbeat
   2324    */
   2325   if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT)
   2326   {
   2327     GSC_SESSIONS_create (&kx->peer, kx, kx->class);
   2328     kx->status = GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED;
   2329     kx->current_epoch_expiration =
   2330       GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2331     cleanup_handshake_secrets (kx);
   2332     if (NULL != kx->resend_task)
   2333       GNUNET_SCHEDULER_cancel (kx->resend_task);
   2334     kx->resend_task = NULL;
   2335     if (NULL != kx->resend_env)
   2336       GNUNET_free (kx->resend_env);
   2337     kx->resend_env = NULL;
   2338     monitor_notify_all (kx);
   2339   }
   2340   update_timeout (kx);
   2341 
   2342   return GNUNET_YES;
   2343 }
   2344 
   2345 
   2346 /**
   2347  * handle an encrypted message
   2348  * @param cls key exchange info
   2349  * @param m encrypted message
   2350  */
   2351 static void
   2352 handle_encrypted_message (void *cls, const struct EncryptedMessage *m)
   2353 {
   2354   struct GSC_KeyExchangeInfo *kx = cls;
   2355   uint16_t size = ntohs (m->header.size);
   2356   char buf[size - sizeof (*m)] GNUNET_ALIGN;
   2357   unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
   2358   const unsigned char *seq_enc_nonce;
   2359   unsigned char enc_key[AEAD_KEY_BYTES];
   2360   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2361   struct GNUNET_ShortHashCode new_ats[MAX_EPOCHS];
   2362   uint32_t seq_enc_ctr;
   2363   uint64_t epoch;
   2364   uint64_t m_seq;
   2365   uint64_t m_seq_nbo;
   2366   uint64_t c_len;
   2367   int8_t ret;
   2368 
   2369   // TODO look at handle_encrypted
   2370   //       - statistics
   2371 
   2372   if ((kx->status != GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED) &&
   2373       (kx->status != GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED) &&
   2374       (kx->status != GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT))
   2375   {
   2376     GSC_SESSIONS_end (&kx->peer);
   2377     kx->status = GNUNET_CORE_KX_STATE_DOWN;
   2378     monitor_notify_all (kx);
   2379     restart_kx (kx);
   2380     return;
   2381   }
   2382   update_timeout (kx);
   2383   epoch = GNUNET_ntohll (m->epoch);
   2384   /**
   2385    * Derive temporarily as we want to discard on
   2386    * decryption failure(s)
   2387    */
   2388   memcpy (new_ats,
   2389           kx->their_ats,
   2390           MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
   2391   // FIXME here we could introduce logic that sends heartbeats
   2392   // with key update request if we have not seen a new
   2393   // epoch after a while (e.g. EPOCH_EXPIRATION)
   2394   if (kx->their_max_epoch < epoch)
   2395   {
   2396     /**
   2397      * Prevent DoS
   2398      * FIXME maybe requires its own limit.
   2399      */
   2400     if ((epoch - kx->their_max_epoch) > 2 * MAX_EPOCHS)
   2401     {
   2402       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2403                   "Epoch %" PRIu64 " is too new, will not decrypt...\n",
   2404                   epoch);
   2405       GSC_SESSIONS_end (&kx->peer);
   2406       kx->status = GNUNET_CORE_KX_STATE_DOWN;
   2407       monitor_notify_all (kx);
   2408       restart_kx (kx);
   2409       return;
   2410     }
   2411     for (int i = kx->their_max_epoch; i < epoch; i++)
   2412     {
   2413       derive_next_ats (&new_ats[i % MAX_EPOCHS],
   2414                        &new_ats[(i + 1) % MAX_EPOCHS]);
   2415     }
   2416   }
   2417   else if ((kx->their_max_epoch - epoch) > MAX_EPOCHS)
   2418   {
   2419     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2420                 "Epoch %" PRIu64 " is too old, cannot decrypt...\n",
   2421                 epoch);
   2422     return;
   2423   }
   2424   derive_sn (
   2425     &new_ats[epoch % MAX_EPOCHS],
   2426     seq_enc_k,
   2427     sizeof seq_enc_k);
   2428   /* compute the sequence number */
   2429   seq_enc_ctr = *((uint32_t*) m->tag);
   2430   seq_enc_nonce = &m->tag[sizeof (uint32_t)];
   2431 #if DEBUG_KX
   2432   GNUNET_print_bytes (&new_ats[epoch % MAX_EPOCHS],
   2433                       sizeof (struct GNUNET_ShortHashCode),
   2434                       8,
   2435                       GNUNET_NO);
   2436   GNUNET_print_bytes (seq_enc_k,
   2437                       sizeof seq_enc_k,
   2438                       8,
   2439                       GNUNET_NO);
   2440   GNUNET_print_bytes ((char*) &seq_enc_ctr,
   2441                       sizeof seq_enc_ctr,
   2442                       8,
   2443                       GNUNET_NO);
   2444 #endif
   2445   crypto_stream_chacha20_ietf_xor_ic (
   2446     (unsigned char*) &m_seq_nbo,
   2447     (unsigned char*) &m->sequence_number,
   2448     sizeof (uint64_t),
   2449     seq_enc_nonce,
   2450     ntohl (seq_enc_ctr),
   2451     seq_enc_k);
   2452   m_seq = GNUNET_ntohll (m_seq_nbo);
   2453   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2454               "Received encrypted message in epoch %" PRIu64
   2455               " with E(SQN=%" PRIu64 ")=%" PRIu64
   2456               "\n",
   2457               epoch,
   2458               m_seq,
   2459               m->sequence_number);
   2460   /* We are the initiator and as we are going to receive,
   2461    * we are using the responder key material */
   2462   derive_per_message_secrets (&new_ats[epoch],
   2463                               m_seq,
   2464                               enc_key,
   2465                               enc_nonce);
   2466   // TODO checking sequence numbers - handle the case of out-of-sync messages!
   2467   // for now only decrypt the payload
   2468   // TODO encrypt other fields, too!
   2469   // TODO
   2470   // c_len = size - offsetof ();
   2471   c_len = size - sizeof (struct EncryptedMessage);
   2472   ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
   2473     (unsigned char*) buf,   // m - plain message
   2474     NULL,                                   // nsec - unused
   2475     (unsigned char*) &m[1],                 // c - ciphertext
   2476     c_len,                                  // clen
   2477     (const unsigned char*) &m->tag,         // mac
   2478     NULL,                                   // ad - additional data TODO
   2479     0,                                      // adlen
   2480     enc_nonce,           // npub
   2481     enc_key          // k
   2482     );
   2483   if (0 != ret)
   2484   {
   2485     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2486                 "Something went wrong decrypting message\n");
   2487     GNUNET_break_op (0); // FIXME handle gracefully
   2488     return;
   2489   }
   2490   kx->their_max_epoch = epoch;
   2491   memcpy (&kx->their_ats,
   2492           new_ats,
   2493           MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
   2494 
   2495   if (GNUNET_NO == check_if_ack_or_heartbeat (kx,
   2496                                               buf,
   2497                                               sizeof buf))
   2498   {
   2499     if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT)
   2500     {
   2501       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2502                   "Dropping message as we are still waiting for handshake ACK\n");
   2503       GNUNET_break_op (0);
   2504       return;
   2505     }
   2506     if (GNUNET_OK !=
   2507         GNUNET_MST_from_buffer (kx->mst,
   2508                                 buf,
   2509                                 sizeof buf,
   2510                                 GNUNET_YES,
   2511                                 GNUNET_NO))
   2512       GNUNET_break_op (0);
   2513   }
   2514   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2515 }
   2516 
   2517 
   2518 /**
   2519  * Function called by transport telling us that a peer
   2520  * disconnected.
   2521  * Stop key exchange with the given peer.  Clean up key material.
   2522  *
   2523  * @param cls closure
   2524  * @param peer the peer that disconnected
   2525  * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
   2526  */
   2527 static void
   2528 handle_transport_notify_disconnect (void *cls,
   2529                                     const struct GNUNET_PeerIdentity *peer,
   2530                                     void *handler_cls)
   2531 {
   2532   struct GSC_KeyExchangeInfo *kx = handler_cls;
   2533   (void) cls;
   2534 
   2535   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2536               "Peer `%s' disconnected from us.\n",
   2537               GNUNET_i2s (&kx->peer));
   2538   GSC_SESSIONS_end (&kx->peer);
   2539   GNUNET_STATISTICS_update (GSC_stats,
   2540                             gettext_noop ("# key exchanges stopped"),
   2541                             1,
   2542                             GNUNET_NO);
   2543   if (NULL != kx->resend_task)
   2544   {
   2545     GNUNET_SCHEDULER_cancel (kx->resend_task);
   2546     kx->resend_task = NULL;
   2547   }
   2548   if (NULL != kx->resend_env)
   2549   {
   2550     GNUNET_free (kx->resend_env);
   2551     kx->resend_env = NULL;
   2552   }
   2553   if (NULL != kx->heartbeat_task)
   2554   {
   2555     GNUNET_SCHEDULER_cancel (kx->heartbeat_task);
   2556     kx->heartbeat_task = NULL;
   2557   }
   2558   kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
   2559   monitor_notify_all (kx);
   2560   if (kx->transcript_hash_ctx)
   2561   {
   2562     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2563     kx->transcript_hash_ctx = NULL;
   2564   }
   2565   GNUNET_CONTAINER_DLL_remove (kx_head, kx_tail, kx);
   2566   GNUNET_MST_destroy (kx->mst);
   2567   GNUNET_free (kx);
   2568 }
   2569 
   2570 
   2571 static void
   2572 resend_initiator_hello (void *cls)
   2573 {
   2574   struct GSC_KeyExchangeInfo *kx = cls;
   2575 
   2576   kx->resend_task = NULL;
   2577   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2578               "Resending InitiatorHello.\n");
   2579   GNUNET_MQ_send_copy (kx->mq, kx->resend_env);
   2580   // FIXME (Exponential) backoff?
   2581   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   2582                                                   &resend_initiator_hello,
   2583                                                   kx);
   2584 }
   2585 
   2586 
   2587 /**
   2588  * Send initiator hello
   2589  *
   2590  * @param kx key exchange context
   2591  */
   2592 static void
   2593 send_initiator_hello (struct GSC_KeyExchangeInfo *kx)
   2594 {
   2595   const struct GNUNET_PeerIdentity *my_identity;
   2596   struct GNUNET_MQ_Envelope *env;
   2597   struct GNUNET_ShortHashCode es;
   2598   struct GNUNET_ShortHashCode ets;
   2599   struct GNUNET_ShortHashCode ss_R;
   2600   struct InitiatorHelloPayload *ihmp; /* initiator hello message - buffer on stack */
   2601   struct InitiatorHello *ihm_e; /* initiator hello message - encrypted */
   2602   long long unsigned int c_len;
   2603   unsigned char enc_key[AEAD_KEY_BYTES];
   2604   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2605   enum GNUNET_GenericReturnValue ret;
   2606   size_t pt_len;
   2607 
   2608   my_identity = GNUNET_PILS_get_identity (GSC_pils);
   2609   GNUNET_assert (NULL != my_identity);
   2610 
   2611   pt_len = sizeof (*ihmp) + strlen (my_services_info);
   2612   c_len = pt_len + AEAD_TAG_BYTES;
   2613   env = GNUNET_MQ_msg_extra (ihm_e,
   2614                              c_len,
   2615                              GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO);
   2616   ihmp = (struct InitiatorHelloPayload*) &ihm_e[1];
   2617   ihmp->peer_class = htons (GNUNET_CORE_CLASS_UNKNOWN); // TODO set this to a meaningful
   2618   GNUNET_memcpy (&ihmp->pk_I,
   2619                  my_identity,
   2620                  sizeof (struct GNUNET_PeerIdentity));
   2621   GNUNET_CRYPTO_hash (&kx->peer, /* what to hash */ // TODO do we do this twice?
   2622                       sizeof (struct GNUNET_PeerIdentity),
   2623                       &ihm_e->h_pk_R); /* result */
   2624   // TODO init hashcontext/transcript_hash
   2625   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send InitiatorHello: %d %d\n", kx->role,
   2626               kx->status);
   2627   GNUNET_assert (NULL == kx->transcript_hash_ctx);
   2628   kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start ();
   2629   GNUNET_assert (NULL != kx->transcript_hash_ctx);
   2630   // TODO fill services_info
   2631 
   2632   // 1. Encaps
   2633   ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public ephemeral key of initiator
   2634                                         &ihm_e->c_R,    // encapsulated key
   2635                                         &ss_R); // key - ss_R
   2636   if (GNUNET_OK != ret)
   2637   {
   2638     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2639                 "Something went wrong encapsulating ss_R\n");
   2640     // TODO handle
   2641   }
   2642   // 2. generate rR (uint64_t) - is this the nonce? Naming seems not quite
   2643   //    consistent
   2644   ihm_e->r_I =
   2645     GNUNET_CRYPTO_random_u64 (UINT64_MAX);
   2646   // 3. generate sk_e/pk_e - ephemeral key
   2647   GNUNET_CRYPTO_ecdhe_key_create (&kx->sk_e.ecdhe_key);
   2648   GNUNET_CRYPTO_ecdhe_key_get_public (
   2649     &kx->sk_e.ecdhe_key,
   2650     &kx->pk_e.ecdhe_key);
   2651   GNUNET_memcpy (&ihm_e->pk_e,
   2652                  &kx->pk_e.ecdhe_key,
   2653                  sizeof (kx->pk_e.ecdhe_key));
   2654   // 4. generate ETS to encrypt
   2655   //         generate ETS (early_traffic_secret_key, decrypt pk_i
   2656   //         expand ETS <- expand ES <- extract ss_R
   2657   //         use ETS to decrypt
   2658   GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx,
   2659                                    ihm_e,
   2660                                    sizeof (struct InitiatorHello));
   2661   {
   2662     struct GNUNET_HashCode transcript;
   2663     snapshot_transcript (kx->transcript_hash_ctx,
   2664                          &transcript);
   2665     derive_es_ets (&transcript,
   2666                    &ss_R,
   2667                    &es,
   2668                    &ets);
   2669     derive_per_message_secrets (&ets,
   2670                                 0,
   2671                                 enc_key,
   2672                                 enc_nonce);
   2673   }
   2674   // 5. encrypt
   2675 
   2676   ret = crypto_aead_xchacha20poly1305_ietf_encrypt (
   2677     (unsigned char*) &ihm_e[1],   /* c - ciphertext */
   2678     // mac,
   2679     // NULL, // maclen_p
   2680     &c_len,   /* clen_p */
   2681     (unsigned char*) ihmp,   /* m - plaintext message */
   2682     pt_len,   // mlen
   2683     NULL, 0,   // ad, adlen // FIXME maybe over the unencrypted header?
   2684                // fields?
   2685     NULL,   // nsec - unused
   2686     enc_nonce,   // npub - nonce
   2687     enc_key);   // k - key
   2688   if (0 != ret)
   2689   {
   2690     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong encrypting\n");
   2691     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2692     kx->transcript_hash_ctx = NULL;
   2693     GNUNET_MQ_discard (env);
   2694     return;
   2695   }
   2696   /* Forward the transcript */
   2697   GNUNET_CRYPTO_hash_context_read (
   2698     kx->transcript_hash_ctx,
   2699     &ihm_e[1],
   2700     c_len);
   2701 
   2702   kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_SENT;
   2703   kx->early_secret_key = es;
   2704   kx->early_traffic_secret = ets;
   2705   kx->ss_R = ss_R;
   2706   monitor_notify_all (kx);
   2707   GNUNET_MQ_send_copy (kx->mq, env);
   2708   kx->resend_env = env;
   2709   kx->resend_tries_left = RESEND_MAX_TRIES;
   2710   kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT,
   2711                                                   &resend_initiator_hello,
   2712                                                   kx);
   2713 }
   2714 
   2715 
   2716 static void
   2717 check_rekey (struct GSC_KeyExchangeInfo *kx)
   2718 {
   2719   struct GNUNET_ShortHashCode new_ats;
   2720 
   2721   if ((UINT64_MAX == kx->current_sqn) ||
   2722       (GNUNET_TIME_absolute_is_past (kx->current_epoch_expiration)))
   2723   {
   2724     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2725                 "Epoch expiration %" PRIu64 " SQN %" PRIu64
   2726                 ", incrementing epoch...\n",
   2727                 kx->current_epoch_expiration.abs_value_us,
   2728                 kx->current_sqn);
   2729     // Can this trigger? Maybe if we receive a lot of
   2730     // heartbeats?
   2731     GNUNET_assert (UINT64_MAX > kx->current_epoch);
   2732     kx->current_epoch++;
   2733     kx->current_epoch_expiration =
   2734       GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2735     kx->current_sqn = 0;
   2736     derive_next_ats (&kx->current_ats,
   2737                      &new_ats);
   2738     memcpy (&kx->current_ats,
   2739             &new_ats,
   2740             sizeof new_ats);
   2741   }
   2742 }
   2743 
   2744 
   2745 /**
   2746  * Encrypt and transmit payload
   2747  * @param kx key exchange info
   2748  * @param payload the payload
   2749  * @param payload_size size of the payload
   2750  */
   2751 void
   2752 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
   2753                              const void *payload,
   2754                              size_t payload_size)
   2755 {
   2756   struct GNUNET_MQ_Envelope *env;
   2757   struct EncryptedMessage *encrypted_msg;
   2758   unsigned char enc_key[AEAD_KEY_BYTES];
   2759   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2760   unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
   2761   uint64_t sqn;
   2762   uint64_t epoch;
   2763   int8_t ret;
   2764 
   2765   encrypted_msg = NULL;
   2766 
   2767   check_rekey (kx);
   2768   sqn = kx->current_sqn;
   2769   epoch = kx->current_epoch;
   2770   /* We are the sender and as we are going to send,
   2771    * we are using the initiator key material */
   2772   derive_per_message_secrets (&kx->current_ats,
   2773                               sqn,
   2774                               enc_key,
   2775                               enc_nonce);
   2776   kx->current_sqn++;
   2777   derive_sn (&kx->current_ats,
   2778              seq_enc_k,
   2779              sizeof seq_enc_k);
   2780   env = GNUNET_MQ_msg_extra (encrypted_msg,
   2781                              payload_size,
   2782                              GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE);
   2783   // only encrypt the payload for now
   2784   // TODO encrypt other fields as well
   2785   ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
   2786     (unsigned char*) &encrypted_msg[1],     // c - resulting ciphertext
   2787     (unsigned char*) &encrypted_msg->tag,     // mac - resulting mac/tag
   2788     NULL,     // maclen
   2789     (unsigned char*) payload,     // m - plain message
   2790     payload_size,     // mlen
   2791     NULL,     // ad - additional data TODO also cover the unencrypted part (epoch)
   2792     0,     // adlen
   2793     NULL,     // nsec - unused
   2794     enc_nonce,     // npub nonce
   2795     enc_key     // k - key
   2796     );
   2797   if (0 != ret)
   2798   {
   2799     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2800                 "Something went wrong encrypting message\n");
   2801     GNUNET_assert (0);
   2802   }
   2803   {
   2804     /* compute the sequence number */
   2805     unsigned char *seq_enc_nonce;
   2806     uint64_t seq_nbo;
   2807     uint32_t seq_enc_ctr;
   2808 
   2809     seq_nbo = GNUNET_htonll (sqn);
   2810     seq_enc_ctr = *((uint32_t*) encrypted_msg->tag);
   2811     seq_enc_nonce = &encrypted_msg->tag[sizeof (uint32_t)];
   2812     crypto_stream_chacha20_ietf_xor_ic (
   2813       (unsigned char*) &encrypted_msg->sequence_number,
   2814       (unsigned char*) &seq_nbo,
   2815       sizeof seq_nbo,
   2816       seq_enc_nonce,
   2817       ntohl (seq_enc_ctr),
   2818       seq_enc_k);
   2819 #if DEBUG_KX
   2820     GNUNET_print_bytes (seq_enc_k,
   2821                         sizeof seq_enc_k,
   2822                         8,
   2823                         GNUNET_NO);
   2824     GNUNET_print_bytes ((char*) &seq_enc_ctr,
   2825                         sizeof seq_enc_ctr,
   2826                         8,
   2827                         GNUNET_NO);
   2828 #endif
   2829     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2830                 "Sending encrypted message with E(SQN=%" PRIu64 ")=%" PRIu64
   2831                 "\n",
   2832                 sqn,
   2833                 encrypted_msg->sequence_number);
   2834   }
   2835   encrypted_msg->epoch = GNUNET_htonll (epoch);
   2836 
   2837   // TODO actually copy payload
   2838   GNUNET_MQ_send (kx->mq, env);
   2839 }
   2840 
   2841 
   2842 void
   2843 GSC_KX_start (void)
   2844 {
   2845   const struct GNUNET_PeerIdentity *my_identity;
   2846   struct GNUNET_MQ_MessageHandler handlers[] = {
   2847     GNUNET_MQ_hd_var_size (initiator_hello,
   2848                            GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO,
   2849                            struct InitiatorHello,
   2850                            NULL),
   2851     GNUNET_MQ_hd_var_size (initiator_done,
   2852                            GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE,
   2853                            struct InitiatorDone,
   2854                            NULL),
   2855     GNUNET_MQ_hd_var_size (responder_hello,
   2856                            GNUNET_MESSAGE_TYPE_CORE_RESPONDER_HELLO,
   2857                            struct ResponderHello,
   2858                            NULL),
   2859     GNUNET_MQ_hd_var_size   (encrypted_message, // TODO rename?
   2860                              GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE,  // TODO rename!
   2861                              struct EncryptedMessage,
   2862                              NULL),
   2863     GNUNET_MQ_handler_end ()
   2864   };
   2865 
   2866   my_identity = GNUNET_PILS_get_identity (GSC_pils);
   2867   GNUNET_assert (NULL != my_identity);
   2868 
   2869   nc = GNUNET_notification_context_create (1);
   2870   transport =
   2871     GNUNET_TRANSPORT_core_connect (GSC_cfg,
   2872                                    my_identity,
   2873                                    handlers,
   2874                                    NULL, // cls - this connection-independant
   2875                                          // cls seems not to be needed.
   2876                                          // the connection-specific cls
   2877                                          // will be set as a return value
   2878                                          // of
   2879                                          // handle_transport_notify_connect
   2880                                    &handle_transport_notify_connect,
   2881                                    &handle_transport_notify_disconnect);
   2882   if (NULL == transport)
   2883   {
   2884     GSC_KX_done ();
   2885     return;
   2886   }
   2887 
   2888   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2889               "Connected to TRANSPORT\n");
   2890 
   2891   GSC_complete_initialization_cb ();
   2892 }
   2893 
   2894 
   2895 void
   2896 pid_change_cb (void *cls,
   2897                const struct GNUNET_HELLO_Parser *parser,
   2898                const struct GNUNET_HashCode *hash)
   2899 {
   2900   if (NULL != transport)
   2901     return;
   2902 
   2903   GSC_KX_start ();
   2904 }
   2905 
   2906 
   2907 /**
   2908  * Initialize KX subsystem.
   2909  *
   2910  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
   2911  */
   2912 int
   2913 GSC_KX_init (void)
   2914 {
   2915   GSC_pils = GNUNET_PILS_connect (GSC_cfg,
   2916                                   &pid_change_cb,
   2917                                   NULL);
   2918   if (NULL == GSC_pils)
   2919   {
   2920     GSC_KX_done ();
   2921     return GNUNET_SYSERR;
   2922   }
   2923 
   2924   return GNUNET_OK;
   2925 }
   2926 
   2927 
   2928 /**
   2929  * Shutdown KX subsystem.
   2930  */
   2931 void
   2932 GSC_KX_done ()
   2933 {
   2934   struct PilsRequest *pr;
   2935   while (NULL != (pr = pils_requests_head))
   2936   {
   2937     GNUNET_CONTAINER_DLL_remove (pils_requests_head,
   2938                                  pils_requests_tail,
   2939                                  pr);
   2940     if (NULL != pr->op)
   2941       GNUNET_PILS_cancel (pr->op);
   2942     GNUNET_free (pr);
   2943   }
   2944   if (NULL != GSC_pils)
   2945   {
   2946     GNUNET_PILS_disconnect (GSC_pils);
   2947     GSC_pils = NULL;
   2948   }
   2949   if (NULL != transport)
   2950   {
   2951     GNUNET_TRANSPORT_core_disconnect (transport);
   2952     transport = NULL;
   2953   }
   2954   if (NULL != rekey_task)
   2955   {
   2956     GNUNET_SCHEDULER_cancel (rekey_task);
   2957     rekey_task = NULL;
   2958   }
   2959   if (NULL != nc)
   2960   {
   2961     GNUNET_notification_context_destroy (nc);
   2962     nc = NULL;
   2963   }
   2964 }
   2965 
   2966 
   2967 /**
   2968  * Check how many messages are queued for the given neighbour.
   2969  *
   2970  * @param kxinfo data about neighbour to check
   2971  * @return number of items in the message queue
   2972  */
   2973 unsigned int
   2974 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
   2975 {
   2976   return GNUNET_MQ_get_length (kxinfo->mq);
   2977 }
   2978 
   2979 
   2980 int
   2981 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
   2982 {
   2983   return kxinfo->has_excess_bandwidth;
   2984 }
   2985 
   2986 
   2987 /**
   2988  * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.  For this
   2989  * request type, the client does not have to have transmitted an INIT
   2990  * request.  All current peers are returned, regardless of which
   2991  * message types they accept.
   2992  *
   2993  * @param mq message queue to add for monitoring
   2994  */
   2995 void
   2996 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
   2997 {
   2998   struct GNUNET_MQ_Envelope *env;
   2999   struct MonitorNotifyMessage *done_msg;
   3000   struct GSC_KeyExchangeInfo *kx;
   3001 
   3002   GNUNET_notification_context_add (nc, mq);
   3003   for (kx = kx_head; NULL != kx; kx = kx->next)
   3004   {
   3005     struct GNUNET_MQ_Envelope *env_notify;
   3006     struct MonitorNotifyMessage *msg;
   3007 
   3008     env_notify = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
   3009     msg->state = htonl ((uint32_t) kx->status);
   3010     msg->peer = kx->peer;
   3011     msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
   3012     GNUNET_MQ_send (mq, env_notify);
   3013   }
   3014   env = GNUNET_MQ_msg (done_msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
   3015   done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
   3016   done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
   3017   GNUNET_MQ_send (mq, env);
   3018 }
   3019 
   3020 
   3021 /* end of gnunet-service-core_kx.c */