gnunet

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

gnunet-service-core_kx.c (130655B)


      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  * Enable expensive logging of decryption failures.
     55  * Note that protocol violating peers may always cause those
     56  * en masse.
     57  */
     58 #define DECRYPTION_FAILURES_LOG_LEVEL GNUNET_ERROR_TYPE_DEBUG
     59 
     60 /**
     61  * Number of times we retransmit a handshake flight before giving up on it
     62  * and starting a fresh exchange.  With the exponential backoff of RFC 9147,
     63  * Section 5.8, the retransmissions go out 1, 3, 7, 15 and 31 seconds into
     64  * the flight; the flight is then abandoned one further interval after the
     65  * last of them, at 63s.
     66  *
     67  * Note that the give-up is observed by the *next* firing of @e resend_task,
     68  * which #schedule_resend() has already armed with the doubled delay -- so
     69  * the flight always outlasts its last retransmission by one interval, and
     70  * raising this by one costs far more than the interval it adds.
     71  */
     72 #define RESEND_MAX_TRIES 5
     73 
     74 /**
     75  * libsodium has very long symbol names
     76  */
     77 #define AEAD_KEY_BYTES crypto_aead_xchacha20poly1305_ietf_KEYBYTES
     78 
     79 /**
     80  * libsodium has very long symbol names
     81  */
     82 #define AEAD_NONCE_BYTES crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
     83 
     84 /**
     85  * libsodium has very long symbol names
     86  */
     87 #define AEAD_TAG_BYTES crypto_aead_xchacha20poly1305_ietf_ABYTES
     88 
     89 /**
     90  * Initial handshake retransmission timer.  RFC 9147, Section 5.8:
     91  * "implementations SHOULD use an initial timer value of 1000 ms and double
     92  * the value at each retransmission, up to no less than 60 seconds."
     93  */
     94 #define RESEND_TIMEOUT \
     95         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
     96 
     97 /**
     98  * Ceiling for the handshake retransmission timer (RFC 9147, Section 5.8).
     99  */
    100 #define RESEND_TIMEOUT_MAX \
    101         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
    102 
    103 /**
    104  * Size of the per-epoch anti-replay window, in records.  RFC 9147,
    105  * Section 4.5.1: "The receiver SHOULD pick a window large enough to handle
    106  * any plausible reordering, which depends on the data rate."  One machine
    107  * word is the largest window we can check in constant time.
    108  */
    109 #define REPLAY_WINDOW_SIZE 64
    110 
    111 /**
    112  * How long we wait for the Ack to a heartbeat before sending another one.
    113  *
    114  * Every heartbeat is answered -- #handle_heartbeat() sends a
    115  * #GNUNET_MESSAGE_TYPE_CORE_ACK unconditionally -- so this is also how long
    116  * an association may go unconfirmed before we probe it again.
    117  */
    118 #define HEARTBEAT_PROBE_FREQUENCY \
    119         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
    120 
    121 /**
    122  * How many heartbeats in a row may go unanswered before we give up on the
    123  * association.  Together with #HEARTBEAT_PROBE_FREQUENCY this bounds how
    124  * long a dead association can look alive to us (90s).
    125  */
    126 #define MAX_UNANSWERED_HEARTBEATS 3
    127 
    128 /**
    129  * What is the minimum frequency for a HEARTBEAT message?
    130  */
    131 #define MIN_HEARTBEAT_FREQUENCY \
    132         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
    133 
    134 /**
    135  * How often do we send a heartbeat?
    136  */
    137 #define HEARTBEAT_FREQUENCY \
    138         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
    139 
    140 /**
    141  * Maximum number of epochs we keep on hand.
    142  * This implicitly defines the maximum age of
    143  * messages we accept from other peers, depending
    144  * on their rekey interval.
    145  */
    146 #define MAX_EPOCHS 10
    147 
    148 /**
    149  * How often do we rekey/switch to a new epoch?
    150  */
    151 #define EPOCH_EXPIRATION \
    152         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
    153 
    154 /**
    155  * What time difference do we tolerate?
    156  */
    157 #define REKEY_TOLERANCE \
    158         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
    159 
    160 /**
    161  * String for expanding early transport secret
    162  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    163  */
    164 #define EARLY_DATA_STR "early data"
    165 
    166 /**
    167  * String for expanding RHTS
    168  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    169  */
    170 #define R_HS_TRAFFIC_STR "r hs traffic"
    171 
    172 /**
    173  * String for expanding IHTS
    174  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    175  */
    176 #define I_HS_TRAFFIC_STR "i hs traffic"
    177 
    178 /**
    179  * String for expanding RATS
    180  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    181  */
    182 #define R_AP_TRAFFIC_STR "r ap traffic"
    183 
    184 /**
    185  * String for expanding IATS
    186  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    187  */
    188 #define I_AP_TRAFFIC_STR "i ap traffic"
    189 
    190 /**
    191  * String for expanding derived keys (Handshake and Early)
    192  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    193  */
    194 #define DERIVED_STR "derived"
    195 
    196 /**
    197  * String for expanding fk_R used for ResponderFinished field
    198  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    199  */
    200 #define R_FINISHED_STR "r finished"
    201 
    202 /**
    203  * String for expanding fk_I used for InitiatorFinished field
    204  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    205  */
    206 #define I_FINISHED_STR "i finished"
    207 
    208 /**
    209  * Labeled expand label for CAKE
    210  */
    211 #define CAKE_LABEL "cake10"
    212 
    213 /**
    214  * String for expanding derived keys (Handshake and Early)
    215  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    216  */
    217 #define KEY_STR "key"
    218 
    219 /**
    220  * String for expanding derived keys (Handshake and Early)
    221  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    222  */
    223 #define TRAFFIC_UPD_STR "traffic upd"
    224 
    225 /**
    226  * String for expanding derived keys (Handshake and Early)
    227  * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html)
    228  */
    229 #define IV_STR "iv"
    230 
    231 
    232 /**
    233  * Indicates whether a peer is in the initiating or receiving role.
    234  */
    235 enum GSC_KX_Role
    236 {
    237   /* Peer is supposed to initiate the key exchange */
    238   ROLE_INITIATOR = 0,
    239 
    240   /* Peer is supposed to wait for the key exchange */
    241   ROLE_RESPONDER = 1,
    242 };
    243 
    244 
    245 /**
    246  * Information about the status of a key exchange with another peer.
    247  */
    248 struct GSC_KeyExchangeInfo
    249 {
    250   /**
    251    * DLL.
    252    */
    253   struct GSC_KeyExchangeInfo *next;
    254 
    255   /**
    256    * DLL.
    257    */
    258   struct GSC_KeyExchangeInfo *prev;
    259 
    260   /**
    261    * Identity of the peer.
    262    */
    263   struct GNUNET_PeerIdentity peer;
    264 
    265   /**
    266    * Message queue for sending messages to @a peer.
    267    */
    268   struct GNUNET_MQ_Handle *mq;
    269 
    270   /**
    271    * Env for resending messages
    272    */
    273   struct GNUNET_MQ_Envelope *resend_env;
    274 
    275   /**
    276    * Our message stream tokenizer (for encrypted payload).
    277    */
    278   struct GNUNET_MessageStreamTokenizer *mst;
    279 
    280   // TODO check ordering - might make it less confusing
    281   // TODO consistent naming: ss_e, shared_secret_e or ephemeral_shared_secret?
    282   // TODO consider making all the structs here pointers
    283   //        - they can be checked to be NULL
    284   //        - valgrind can detect memory issues better (I guess?)
    285 
    286   /**
    287    * Own role in the key exchange. Are we supposed to initiate or receive the
    288    * handshake?
    289    */
    290   enum GSC_KX_Role role;
    291 
    292   // TODO
    293   struct GNUNET_ShortHashCode ss_R;
    294   struct GNUNET_ShortHashCode ss_e;
    295   struct GNUNET_ShortHashCode ss_I;
    296 
    297   /**
    298    * Initiator secret key
    299    */
    300   struct GNUNET_CRYPTO_HpkePrivateKey sk_e;
    301 
    302   /**
    303    * Initiator ephemeral key
    304    */
    305   struct GNUNET_CRYPTO_HpkePublicKey pk_e;
    306 
    307   /**
    308    * Hash over the entire InitiatorHello we are currently answering, or all
    309    * zeroes if there is none.  A retransmitted flight is byte-identical to
    310    * the one that was lost (#GNUNET_MQ_send_copy() of @e resend_env), so this
    311    * is what tells a retransmission apart from a genuinely new exchange.
    312    * Only meaningful while we are the responder.
    313    */
    314   struct GNUNET_HashCode ih_hash;
    315 
    316   /**
    317    * Hash over the entire ResponderHello we are currently answering, or all
    318    * zeroes if there is none.  Counterpart of @e ih_hash; only meaningful
    319    * while we are the initiator.
    320    */
    321   struct GNUNET_HashCode rh_hash;
    322 
    323   /**
    324    * The transcript hash context.
    325    * It is fed data from the handshake to be implicitly validated and used to
    326    * derive key material.
    327    */
    328   struct GNUNET_HashContext *transcript_hash_ctx;
    329 
    330   /**
    331    * ES - Early Secret Key
    332    * TODO uniform naming: _key?
    333    */
    334   struct GNUNET_ShortHashCode early_secret_key;
    335 
    336   /**
    337    * ETS - Early traffic secret
    338    * TODO
    339    */
    340   struct GNUNET_ShortHashCode early_traffic_secret; /* Decrypts InitiatorHello */
    341 
    342   /**
    343    * HS - Handshake secret
    344    * TODO
    345    */
    346   struct GNUNET_ShortHashCode handshake_secret;
    347 
    348   /**
    349    * RHTS - Responder handshake secret
    350    * TODO
    351    */
    352   struct GNUNET_ShortHashCode rhts;
    353 
    354   /**
    355    * IHTS - Initiator handshake secret
    356    * TODO
    357    */
    358   struct GNUNET_ShortHashCode ihts;
    359 
    360   /**
    361    * Master secret key
    362    * TODO
    363    */
    364   struct GNUNET_ShortHashCode master_secret;
    365 
    366   /**
    367    * *ATS - our current application traffic secret by epoch
    368    */
    369   struct GNUNET_ShortHashCode current_ats;
    370 
    371   /**
    372    * *ATS - other peers application traffic secret by epoch
    373    */
    374   struct GNUNET_ShortHashCode their_ats[MAX_EPOCHS];
    375 
    376   /**
    377    * Our currently used epoch for sending.
    378    */
    379   uint64_t current_epoch;
    380 
    381   /**
    382    * Expiration time of our current epoch
    383    */
    384   struct GNUNET_TIME_Absolute current_epoch_expiration;
    385 
    386   /**
    387    * Highest seen (or used) epoch of
    388    * responder resp initiator..
    389    */
    390   uint64_t their_max_epoch;
    391 
    392   /**
    393    * Highest sequence number we have successfully deprotected in each
    394    * epoch; the right edge of that epoch's anti-replay window.
    395    * See RFC 9147, Section 4.5.1.
    396    */
    397   uint64_t replay_max[MAX_EPOCHS];
    398 
    399   /**
    400    * Anti-replay window for each epoch: bit @a k is set if the record with
    401    * sequence number `replay_max[i] - k' has been deprotected.  Bit 0 is
    402    * `replay_max[i]' itself.  See RFC 9147, Section 4.5.1.
    403    */
    404   uint64_t replay_bitmap[MAX_EPOCHS];
    405 
    406   /**
    407    * Our current sequence number
    408    */
    409   uint64_t current_sqn;
    410 
    411   /**
    412    * When should the session time out (if there are no Acks to HEARTBEATs)?
    413    */
    414   struct GNUNET_TIME_Absolute timeout;
    415 
    416   /**
    417    * Last time we notified monitors
    418    */
    419   struct GNUNET_TIME_Absolute last_notify_timeout;
    420 
    421   /**
    422    * Task for resending messages during handshake.
    423    */
    424   struct GNUNET_SCHEDULER_Task *resend_task;
    425 
    426   /**
    427    * How long to wait before the next retransmission of the handshake
    428    * message in @e resend_env.  Doubles with every retransmission, capped
    429    * at #RESEND_TIMEOUT_MAX.  See RFC 9147, Section 5.8.
    430    */
    431   struct GNUNET_TIME_Relative resend_delay;
    432 
    433   /**
    434    * Resend tries left
    435    */
    436   unsigned int resend_tries_left;
    437 
    438   /**
    439    * ID of task used for sending keep-alive pings.
    440    * TODO still needed?
    441    */
    442   struct GNUNET_SCHEDULER_Task *heartbeat_task;
    443 
    444   /**
    445    * Heartbeats sent since the last record we deprotected from this peer.
    446    * Reset by #update_timeout(); once it reaches
    447    * #MAX_UNANSWERED_HEARTBEATS the association is gone.
    448    */
    449   unsigned int heartbeats_unanswered;
    450 
    451   /**
    452    * #GNUNET_YES if this peer currently has excess bandwidth.
    453    * TODO still needed?
    454    */
    455   int has_excess_bandwidth;
    456 
    457   /**
    458    * #GNUNET_YES once application traffic keys are installed for this peer,
    459    * i.e. once we have an association in the sense of RFC 9147.
    460    *
    461    * This is deliberately *not* derived from @e status.  RFC 9147,
    462    * Section 5.11 requires that a peer which starts a new handshake over an
    463    * existing association does not destroy that association until it has
    464    * "demonstrated reachability [...] by completing a complete handshake
    465    * including delivering a verifiable Finished message" -- so a handshake
    466    * can be in flight while an association is up, and the record layer has
    467    * to keep deprotecting records for the old epoch throughout.  @e status
    468    * tracks the handshake, this tracks the association.
    469    */
    470   int association_up;
    471 
    472   /**
    473    * What is our connection state?
    474    */
    475   enum GNUNET_CORE_KxState status;
    476 
    477   /**
    478    * Peer class of the other peer
    479    * TODO still needed?
    480    */
    481   enum GNUNET_CORE_PeerClass class;
    482 
    483 };
    484 
    485 /**
    486  * Transport service.
    487  */
    488 static struct GNUNET_TRANSPORT_CoreHandle *transport;
    489 
    490 /**
    491  * DLL head.
    492  */
    493 static struct GSC_KeyExchangeInfo *kx_head;
    494 
    495 /**
    496  * DLL tail.
    497  */
    498 static struct GSC_KeyExchangeInfo *kx_tail;
    499 
    500 /**
    501  * Task scheduled for periodic re-generation (and thus rekeying) of our
    502  * ephemeral key.
    503  */
    504 static struct GNUNET_SCHEDULER_Task *rekey_task;
    505 
    506 /**
    507  * Notification context for broadcasting to monitors.
    508  */
    509 static struct GNUNET_NotificationContext *nc;
    510 
    511 /**
    512  * Our services info string TODO
    513  */
    514 static char *my_services_info = "";
    515 
    516 static void
    517 buffer_clear (void *buf, size_t len)
    518 {
    519 #if HAVE_MEMSET_S
    520   memset_s (buf, len, 0, len);
    521 #elif HAVE_EXPLICIT_BZERO
    522   explicit_bzero (buf, len);
    523 #else
    524   volatile unsigned char *p = buf;
    525   while (len--)
    526     *p++ = 0;
    527 #endif
    528 }
    529 
    530 
    531 static void
    532 cleanup_handshake_secrets (struct GSC_KeyExchangeInfo *kx)
    533 {
    534   buffer_clear (&kx->ihts,
    535                 sizeof kx->ihts);
    536   buffer_clear (&kx->rhts,
    537                 sizeof kx->rhts);
    538   buffer_clear (&kx->sk_e,
    539                 sizeof kx->sk_e);
    540   buffer_clear (&kx->ss_I,
    541                 sizeof kx->ss_I);
    542   buffer_clear (&kx->ss_R,
    543                 sizeof kx->ss_R);
    544   buffer_clear (&kx->ss_e,
    545                 sizeof kx->ss_e);
    546   buffer_clear (&kx->master_secret,
    547                 sizeof kx->master_secret);
    548   buffer_clear (&kx->early_secret_key,
    549                 sizeof kx->early_secret_key);
    550   buffer_clear (&kx->early_traffic_secret,
    551                 sizeof kx->early_traffic_secret);
    552   buffer_clear (&kx->handshake_secret,
    553                 sizeof kx->handshake_secret);
    554 }
    555 
    556 
    557 /**
    558  * Forget the anti-replay window of @a epoch.  Called when the key material
    559  * behind that slot of the epoch ring is replaced, either by a new
    560  * association or by advancing past it, so that a sequence number is never
    561  * checked against a window belonging to a different key.
    562  *
    563  * @param kx key exchange to update
    564  * @param epoch epoch whose window to clear
    565  */
    566 static void
    567 replay_reset (struct GSC_KeyExchangeInfo *kx,
    568               uint64_t epoch)
    569 {
    570   kx->replay_max[epoch % MAX_EPOCHS] = 0;
    571   kx->replay_bitmap[epoch % MAX_EPOCHS] = 0;
    572 }
    573 
    574 
    575 /**
    576  * Forget every anti-replay window (all of #MAX_EPOCHS).
    577  *
    578  * @param kx key exchange to update
    579  */
    580 static void
    581 replay_reset_all (struct GSC_KeyExchangeInfo *kx)
    582 {
    583   memset (kx->replay_max, 0, sizeof kx->replay_max);
    584   memset (kx->replay_bitmap, 0, sizeof kx->replay_bitmap);
    585 }
    586 
    587 
    588 /**
    589  * Would a record with sequence number @a sqn in @a epoch be a replay?
    590  *
    591  * RFC 9147, Section 4.5.1.  Note this only *checks*: the window must not
    592  * be updated until the record has been deprotected successfully, which is
    593  * what #replay_commit() is for.
    594  *
    595  * @param kx key exchange the record arrived on
    596  * @param epoch epoch the record claims
    597  * @param sqn sequence number the record claims
    598  * @return #GNUNET_OK if the record is new, #GNUNET_SYSERR if it is a
    599  *         replay or falls off the left edge of the window
    600  */
    601 static enum GNUNET_GenericReturnValue
    602 replay_check (const struct GSC_KeyExchangeInfo *kx,
    603               uint64_t epoch,
    604               uint64_t sqn)
    605 {
    606   unsigned int idx = epoch % MAX_EPOCHS;
    607   uint64_t max = kx->replay_max[idx];
    608   uint64_t behind;
    609 
    610   if (sqn > max)
    611     return GNUNET_OK;     /* to the right of the window */
    612   behind = max - sqn;
    613   if (behind >= REPLAY_WINDOW_SIZE)
    614     return GNUNET_SYSERR;     /* too old to tell, so assume replay */
    615   if (0 != (kx->replay_bitmap[idx] & (1ULL << behind)))
    616     return GNUNET_SYSERR;     /* seen before */
    617   return GNUNET_OK;
    618 }
    619 
    620 
    621 /**
    622  * Record that a record with sequence number @a sqn in @a epoch has been
    623  * deprotected successfully, sliding the window right if needed.
    624  *
    625  * @param kx key exchange the record arrived on
    626  * @param epoch epoch of the record
    627  * @param sqn sequence number of the record
    628  */
    629 static void
    630 replay_commit (struct GSC_KeyExchangeInfo *kx,
    631                uint64_t epoch,
    632                uint64_t sqn)
    633 {
    634   unsigned int idx = epoch % MAX_EPOCHS;
    635   uint64_t max = kx->replay_max[idx];
    636   uint64_t shift;
    637 
    638   if (sqn > max)
    639   {
    640     shift = sqn - max;
    641     kx->replay_bitmap[idx] = (shift >= REPLAY_WINDOW_SIZE)
    642                              ? 0
    643                              : (kx->replay_bitmap[idx] << shift);
    644     kx->replay_bitmap[idx] |= 1ULL;
    645     kx->replay_max[idx] = sqn;
    646     return;
    647   }
    648   kx->replay_bitmap[idx] |= (1ULL << (max - sqn));
    649 }
    650 
    651 
    652 static void
    653 snapshot_transcript (const struct GNUNET_HashContext *ts_hash,
    654                      struct GNUNET_HashCode *snapshot)
    655 {
    656   struct GNUNET_HashContext *tmp;
    657 
    658   tmp = GNUNET_CRYPTO_hash_context_copy (ts_hash);
    659   GNUNET_CRYPTO_hash_context_finish (tmp, snapshot);
    660 }
    661 
    662 
    663 /**
    664  * Inform all monitors about the KX state of the given peer.
    665  *
    666  * @param kx key exchange state to inform about
    667  */
    668 static void
    669 monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
    670 {
    671   struct MonitorNotifyMessage msg;
    672 
    673   msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
    674   msg.header.size = htons (sizeof(msg));
    675   msg.state = htonl ((uint32_t) kx->status);
    676   msg.peer = kx->peer;
    677   msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
    678   GNUNET_notification_context_broadcast (nc, &msg.header, GNUNET_NO);
    679   kx->last_notify_timeout = kx->timeout;
    680 }
    681 
    682 
    683 static void
    684 restart_kx (struct GSC_KeyExchangeInfo *kx);
    685 
    686 /**
    687  * Task triggered when a neighbour entry is about to time out
    688  * (and we should prevent this by sending an Ack in response
    689  * to a heartbeat).
    690  *
    691  * @param cls the `struct GSC_KeyExchangeInfo`
    692  */
    693 static void
    694 send_heartbeat (void *cls)
    695 {
    696   struct GSC_KeyExchangeInfo *kx = cls;
    697   struct GNUNET_TIME_Relative retry;
    698   struct GNUNET_TIME_Relative left;
    699   struct Heartbeat hb;
    700 
    701   kx->heartbeat_task = NULL;
    702   left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
    703   /* A heartbeat is a probe, not a formality: #handle_heartbeat() answers
    704      every one of them with an Ack, and that Ack is a record whose
    705      deprotection runs #update_timeout() and clears the counter below.  So
    706      #MAX_UNANSWERED_HEARTBEATS of them in a row without a single record
    707      coming back means the association is gone, whatever @e timeout still
    708      says.  Waiting for @e timeout regardless is what made a lost session
    709      cost #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT (5 min) to notice -- and
    710      up to twice that to repair, because the peer that gives up first tears
    711      its session down silently and the other one then has to run its own
    712      full idle timeout before #restart_kx() gets a chance to re-run the
    713      exchange over the virtual link that was there the whole time. */
    714   if ((0 == left.rel_value_us) ||
    715       (kx->heartbeats_unanswered >= MAX_UNANSWERED_HEARTBEATS))
    716   {
    717     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    718                 "Session with `%s' timed out (%u heartbeats unanswered)\n",
    719                 GNUNET_i2s (&kx->peer),
    720                 kx->heartbeats_unanswered);
    721     GNUNET_STATISTICS_update (GSC_stats,
    722                               gettext_noop ("# sessions terminated by timeout"),
    723                               1,
    724                               GNUNET_NO);
    725     GSC_SESSIONS_end (&kx->peer);
    726     kx->status = GNUNET_CORE_KX_STATE_DOWN;
    727     monitor_notify_all (kx);
    728     restart_kx (kx);
    729     return;
    730   }
    731   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    732               "Sending HEARTBEAT to `%s'\n",
    733               GNUNET_i2s (&kx->peer));
    734   GNUNET_STATISTICS_update (GSC_stats,
    735                             gettext_noop ("# heartbeat messages sent"),
    736                             1,
    737                             GNUNET_NO);
    738   hb.header.type =  htons (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT);
    739   hb.header.size = htons (sizeof hb);
    740   // FIXME when do we request update?
    741   hb.flags = 0;
    742   kx->heartbeats_unanswered++;
    743   GSC_KX_encrypt_and_transmit (kx, &hb, sizeof hb);
    744   if (GNUNET_YES != kx->association_up)
    745     return;     /* #check_rekey() tore it down and restarted the exchange */
    746   /* Do not let @e timeout stretch the probe interval: the point of the
    747      counter above is that the answer, not the clock, decides. */
    748   retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_min (
    749                                       HEARTBEAT_PROBE_FREQUENCY,
    750                                       left),
    751                                     MIN_HEARTBEAT_FREQUENCY);
    752   kx->heartbeat_task =
    753     GNUNET_SCHEDULER_add_delayed (retry, &send_heartbeat, kx);
    754 }
    755 
    756 
    757 /**
    758  * We've seen a valid message from the other peer.
    759  * Update the time when the session would time out
    760  * and delay sending our keep alive message further.
    761  *
    762  * @param kx key exchange where we saw activity
    763  */
    764 static void
    765 update_timeout (struct GSC_KeyExchangeInfo *kx)
    766 {
    767   struct GNUNET_TIME_Relative delta;
    768 
    769   kx->timeout =
    770     GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
    771   delta =
    772     GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout, kx->timeout);
    773   if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
    774   {
    775     /* we only notify monitors about timeout changes if those
    776        are bigger than the threshold (5s) */
    777     monitor_notify_all (kx);
    778   }
    779   /* The peer answered, so nothing is outstanding any more. */
    780   kx->heartbeats_unanswered = 0;
    781   if (NULL != kx->heartbeat_task)
    782     GNUNET_SCHEDULER_cancel (kx->heartbeat_task);
    783   /* Probe again #HEARTBEAT_PROBE_FREQUENCY after the last thing we heard,
    784      not halfway to @e timeout: an idle association that is fine costs one
    785      heartbeat and one Ack per interval, while one that is not is noticed
    786      within #MAX_UNANSWERED_HEARTBEATS intervals instead of after the full
    787      #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.  A link carrying traffic
    788      re-arms this on every record and so still never sends one. */
    789   kx->heartbeat_task = GNUNET_SCHEDULER_add_delayed (HEARTBEAT_PROBE_FREQUENCY,
    790                                                      &send_heartbeat,
    791                                                      kx);
    792 }
    793 
    794 
    795 /**
    796  * Send initiator hello
    797  *
    798  * @param kx key exchange context
    799  */
    800 static void
    801 send_initiator_hello (struct GSC_KeyExchangeInfo *kx);
    802 
    803 
    804 /**
    805  * Deliver P2P message to interested clients.  Invokes send twice,
    806  * once for clients that want the full message, and once for clients
    807  * that only want the header
    808  *
    809  * @param cls the `struct GSC_KeyExchangeInfo`
    810  * @param m the message
    811  * @return #GNUNET_OK on success,
    812  *    #GNUNET_NO to stop further processing (no error)
    813  *    #GNUNET_SYSERR to stop further processing with error
    814  */
    815 static int
    816 deliver_message (void *cls, const struct GNUNET_MessageHeader *m)
    817 {
    818   struct GSC_KeyExchangeInfo *kx = cls;
    819 
    820   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    821               "Decrypted message of type %d from %s\n",
    822               ntohs (m->type),
    823               GNUNET_i2s (&kx->peer));
    824   GSC_CLIENTS_deliver_message (&kx->peer,
    825                                m,
    826                                ntohs (m->size),
    827                                GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
    828   GSC_CLIENTS_deliver_message (&kx->peer,
    829                                m,
    830                                sizeof(struct GNUNET_MessageHeader),
    831                                GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
    832   return GNUNET_OK;
    833 }
    834 
    835 
    836 /**
    837  * Arm @e resend_task for the next retransmission of the flight in
    838  * @e resend_env and back the timer off for the one after that.
    839  *
    840  * RFC 9147, Section 5.8: "implementations SHOULD use an initial timer
    841  * value of 1000 ms and double the value at each retransmission, up to no
    842  * less than 60 seconds."
    843  *
    844  * @param kx key exchange whose flight to schedule
    845  * @param cb task to run when the timer fires
    846  */
    847 static void
    848 schedule_resend (struct GSC_KeyExchangeInfo *kx,
    849                  GNUNET_SCHEDULER_TaskCallback cb)
    850 {
    851   GNUNET_assert (NULL == kx->resend_task);
    852   kx->resend_task = GNUNET_SCHEDULER_add_delayed (kx->resend_delay, cb, kx);
    853   kx->resend_delay =
    854     GNUNET_TIME_relative_min (RESEND_TIMEOUT_MAX,
    855                               GNUNET_TIME_relative_multiply (kx->resend_delay,
    856                                                              2));
    857 }
    858 
    859 
    860 /**
    861  * Start a handshake flight: @a kx will retransmit it #RESEND_MAX_TRIES
    862  * times, starting after #RESEND_TIMEOUT and backing off from there.
    863  *
    864  * @param kx key exchange whose flight to start
    865  * @param cb task to run when the timer fires
    866  */
    867 static void
    868 start_resend (struct GSC_KeyExchangeInfo *kx,
    869               GNUNET_SCHEDULER_TaskCallback cb)
    870 {
    871   kx->resend_tries_left = RESEND_MAX_TRIES;
    872   kx->resend_delay = RESEND_TIMEOUT;
    873   schedule_resend (kx, cb);
    874 }
    875 
    876 
    877 /**
    878  * Discard the state of the handshake @a kx is in the middle of, so that a
    879  * new one can be started.  Deliberately leaves the *session* -- traffic
    880  * keys, @e heartbeat_task, @e timeout, what clients were told -- alone:
    881  * those stay valid until a new handshake actually completes.
    882  *
    883  * @param kx key exchange whose handshake state to drop
    884  */
    885 static void
    886 reset_handshake (struct GSC_KeyExchangeInfo *kx)
    887 {
    888   /* Any handshake message we were still resending belongs to the exchange
    889      we are abandoning here.  #send_initiator_hello() /
    890      #send_responder_hello() overwrite @e resend_env and @e resend_task
    891      without clearing them first, so without this the old envelope leaks
    892      and -- worse -- the old task keeps running with its handle lost: a
    893      second resend chain that no GNUNET_SCHEDULER_cancel() can reach, still
    894      firing on @a kx after #handle_transport_notify_disconnect() has freed
    895      it. */
    896   if (NULL != kx->resend_task)
    897   {
    898     GNUNET_SCHEDULER_cancel (kx->resend_task);
    899     kx->resend_task = NULL;
    900   }
    901   if (NULL != kx->resend_env)
    902   {
    903     GNUNET_MQ_discard (kx->resend_env);
    904     kx->resend_env = NULL;
    905   }
    906   if (NULL != kx->transcript_hash_ctx)
    907   {
    908     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
    909     kx->transcript_hash_ctx = NULL;
    910   }
    911   /* There is no flight to recognise a retransmission of any more. */
    912   memset (&kx->ih_hash, 0, sizeof (kx->ih_hash));
    913   memset (&kx->rh_hash, 0, sizeof (kx->rh_hash));
    914   cleanup_handshake_secrets (kx);
    915 }
    916 
    917 
    918 /**
    919  * Give up on the exchange @a kx is in *and* on the session it may have
    920  * established, and return it to a state in which a fresh handshake can be
    921  * run.  Leaves @a kx in #GNUNET_CORE_KX_STATE_DOWN without notifying
    922  * monitors; every caller either moves on to a new state right away or
    923  * notifies itself.
    924  *
    925  * @param kx key exchange to reset
    926  */
    927 static void
    928 abandon_exchange (struct GSC_KeyExchangeInfo *kx)
    929 {
    930   reset_handshake (kx);
    931   GSC_SESSIONS_end (&kx->peer);
    932   kx->association_up = GNUNET_NO;
    933   /* An armed heartbeat task belongs to the association we are dropping
    934      here.  Left behind it keeps encrypting heartbeats with key material
    935      that is no longer current, and #handle_initiator_done() would find it
    936      still set. */
    937   if (NULL != kx->heartbeat_task)
    938   {
    939     GNUNET_SCHEDULER_cancel (kx->heartbeat_task);
    940     kx->heartbeat_task = NULL;
    941   }
    942   kx->heartbeats_unanswered = 0;
    943   /* A new association starts over at epoch 0 and sequence number 0.
    944      Carrying @e their_max_epoch of a long-lived predecessor into it makes
    945      #handle_encrypted_message() reject the first records of the new one as
    946      "too old", and a stale anti-replay window would reject them as
    947      replays. */
    948   kx->their_max_epoch = 0;
    949   kx->current_epoch = 0;
    950   kx->current_sqn = 0;
    951   replay_reset_all (kx);
    952   kx->status = GNUNET_CORE_KX_STATE_DOWN;
    953 }
    954 
    955 
    956 static void
    957 restart_kx (struct GSC_KeyExchangeInfo *kx)
    958 {
    959   const struct GNUNET_HashCode *my_identity_hash;
    960   struct GNUNET_HashCode h1;
    961 
    962   // TODO what happens if we're in the middle of a peer id change?
    963   // TODO there's a small chance this gets already called when we don't have a
    964   // peer id yet. Add a kx, insert into the list, mark it as to be completed
    965   // and let the callback to pils finish the rest once we got the peer id
    966 
    967   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    968               "Initiating key exchange with peer %s\n",
    969               GNUNET_i2s (&kx->peer));
    970   GNUNET_STATISTICS_update (GSC_stats,
    971                             gettext_noop ("# key exchanges initiated"),
    972                             1,
    973                             GNUNET_NO);
    974 
    975   /* Whatever we still had -- an exchange in progress, an established
    976      session, an armed heartbeat -- does not survive this.  Drop it before
    977      telling monitors where we are, so that they do not see the state of the
    978      exchange we are leaving reported as if it were still current: that is
    979      why a restart from #GNUNET_CORE_KX_STATE_INITIATOR_HELLO_SENT used to
    980      show up as two consecutive "Hello sent (I)" notifications. */
    981   abandon_exchange (kx);
    982   monitor_notify_all (kx);
    983   my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils);
    984   GNUNET_assert (NULL != my_identity_hash);
    985   GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1);
    986   if (0 < GNUNET_CRYPTO_hash_cmp (&h1, my_identity_hash))
    987   {
    988     /* peer with "lower" identity starts KX, otherwise we typically end up
    989        with both peers starting the exchange and transmit the 'set key'
    990        message twice */
    991     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    992                 "I am the initiator, sending hello\n");
    993     kx->role = ROLE_INITIATOR;
    994     send_initiator_hello (kx);
    995   }
    996   else
    997   {
    998     /* peer with "higher" identity starts a delayed KX, if the "lower" peer
    999      * does not start a KX since it sees no reasons to do so  */
   1000     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1001                 "I am the responder, yielding and await initiator hello\n");
   1002     kx->status = GNUNET_CORE_KX_STATE_AWAIT_INITIATION;
   1003     kx->role = ROLE_RESPONDER;
   1004     monitor_notify_all (kx);
   1005   }
   1006 }
   1007 
   1008 
   1009 /**
   1010  * Function called by transport to notify us that
   1011  * a peer connected to us (on the network level).
   1012  * Starts the key exchange with the given peer.
   1013  *
   1014  * @param cls closure (NULL)
   1015  * @param mq message queue towards peer
   1016  * @param peer_id (optional, may be NULL) the peer id of the connecting peer
   1017  * @return key exchange information context
   1018  */
   1019 static void *
   1020 handle_transport_notify_connect (void *cls,
   1021                                  const struct GNUNET_PeerIdentity *peer_id,
   1022                                  struct GNUNET_MQ_Handle *mq)
   1023 {
   1024   const struct GNUNET_PeerIdentity *my_identity;
   1025   struct GSC_KeyExchangeInfo *kx;
   1026   (void) cls;
   1027   my_identity = GNUNET_PILS_get_identity (GSC_pils);
   1028   GNUNET_assert (NULL != my_identity);
   1029   if (0 == memcmp (peer_id, my_identity, sizeof *peer_id))
   1030   {
   1031     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1032                 "Ignoring connection to self\n");
   1033     return NULL;
   1034   }
   1035   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1036               "Incoming connection of peer with %s\n",
   1037               GNUNET_i2s (peer_id));
   1038 
   1039   /* Set up kx struct */
   1040   kx = GNUNET_new (struct GSC_KeyExchangeInfo);
   1041   kx->mst = GNUNET_MST_create (&deliver_message, kx);
   1042   kx->mq = mq;
   1043   GNUNET_memcpy (&kx->peer, peer_id, sizeof (struct GNUNET_PeerIdentity));
   1044   GNUNET_CONTAINER_DLL_insert (kx_head, kx_tail, kx);
   1045 
   1046   restart_kx (kx);
   1047   return kx;
   1048 }
   1049 
   1050 
   1051 /**
   1052  * TODO
   1053  * propose a new scheme: don't choose an initiator and responder based on
   1054  * hashing the peer ids, but:
   1055  * let each peer be their own initiator (and responder) when opening a channel
   1056  * towards another peer. It should be fine to have two channels in 'both
   1057  * directions' (one as responder, one as initiator) under the hood. This can be
   1058  * opaque to the upper layers.
   1059  * FIXME: (MSC) This is probably a bad idea in terms of security of the AKE!
   1060  */
   1061 
   1062 /**
   1063  * Schedule for
   1064  *  - forwarding the transcript hash context and
   1065  *  - deriving/generating keys/finished fields
   1066  *
   1067  * Forwarding:                   Deriving               Messages
   1068  * -> pk_e
   1069  * -> c_R
   1070  * -> r_I
   1071  * -> H(pk_R)
   1072  *                               -> ETS
   1073  * -> {pk_I, svcinfo_I}ETS
   1074  * ---------------------------------------------------- send InitiatorHello
   1075  * -> c_e
   1076  * -> r_R
   1077  *                               -> *HTS
   1078  * -> {svcinfo_R, c_I}RHTS
   1079  *                               -> finished_R
   1080  * -> {finished_R}RHTS
   1081  *                               -> finished_I
   1082  *                               -> RATS_0
   1083  * -> [{payload}RATS]
   1084  * ---------------------------------------------------- send ResponderHello
   1085  * -> {finished_I}IHTS
   1086  *                               -> IATS_0
   1087  * ---------------------------------------------------- send InitiatorDone
   1088  */
   1089 
   1090 // TODO find a way to assert that a key is not yet existing before generating
   1091 // TODO find a way to assert that a key is not already existing before using
   1092 /*
   1093  * Derive early secret and transport secret.
   1094  * @param kx the key exchange info
   1095  */
   1096 static void
   1097 derive_es_ets (const struct GNUNET_HashCode *transcript,
   1098                const struct GNUNET_ShortHashCode *ss_R,
   1099                struct GNUNET_ShortHashCode *es,
   1100                struct GNUNET_ShortHashCode *ets)
   1101 {
   1102   uint64_t ret;
   1103 
   1104   ret = GNUNET_CRYPTO_hkdf_extract (es, // prk
   1105                                     0,                     // salt
   1106                                     0,                     // salt_len
   1107                                     ss_R,  // ikm - initial key material
   1108                                     sizeof (*ss_R));
   1109   if (GNUNET_OK != ret)
   1110   {
   1111     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting ES\n")
   1112     ;
   1113     GNUNET_assert (0);
   1114   }
   1115   ret = GNUNET_CRYPTO_hkdf_expand (
   1116     ets,
   1117     sizeof (*ets),
   1118     es,
   1119     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1120     GNUNET_CRYPTO_kdf_arg_string (EARLY_DATA_STR),
   1121     GNUNET_CRYPTO_kdf_arg_auto (transcript));
   1122   if (GNUNET_OK != ret)
   1123   {
   1124     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding ETS\n")
   1125     ;
   1126     GNUNET_assert (0);
   1127   }
   1128 }
   1129 
   1130 
   1131 /*
   1132  * Derive early secret and transport secret.
   1133  * @param kx the key exchange info
   1134  */
   1135 static void
   1136 derive_sn (const struct GNUNET_ShortHashCode *secret,
   1137            unsigned char*sn,
   1138            size_t sn_len)
   1139 {
   1140   GNUNET_assert (GNUNET_OK ==
   1141                  GNUNET_CRYPTO_hkdf_expand (
   1142                    sn,
   1143                    sn_len,
   1144                    secret,
   1145                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1146                    GNUNET_CRYPTO_kdf_arg_string ("sn")));
   1147 }
   1148 
   1149 
   1150 /**
   1151  * Derive the handshake secret
   1152  * @param kx key exchange info
   1153  */
   1154 static void
   1155 derive_hs (const struct GNUNET_ShortHashCode *es,
   1156            const struct GNUNET_ShortHashCode *ss_e,
   1157            struct GNUNET_ShortHashCode *handshake_secret)
   1158 {
   1159   uint64_t ret;
   1160   struct GNUNET_ShortHashCode derived_early_secret;
   1161 
   1162   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deriving HS\n");
   1163   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ES: %s\n", GNUNET_B2S (es)
   1164               );
   1165   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ss_e: %s\n", GNUNET_B2S (ss_e));
   1166   ret = GNUNET_CRYPTO_hkdf_expand (
   1167     &derived_early_secret,
   1168     sizeof (derived_early_secret),
   1169     es,
   1170     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1171     GNUNET_CRYPTO_kdf_arg_string (DERIVED_STR));
   1172   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "dES: %s\n", GNUNET_B2S (&
   1173                                                                 derived_early_secret));
   1174   if (GNUNET_OK != ret)
   1175   {
   1176     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dES\n")
   1177     ;
   1178     GNUNET_assert (0);
   1179   }
   1180   // Handshake secret
   1181   // TODO check: are dES the salt and ss_e the ikm or other way round?
   1182   ret = GNUNET_CRYPTO_hkdf_extract (handshake_secret,     // prk
   1183                                     &derived_early_secret,         // salt - dES
   1184                                     sizeof (derived_early_secret), // salt_len
   1185                                     ss_e,          // ikm - initial key material
   1186                                     sizeof (*ss_e));
   1187   if (GNUNET_OK != ret)
   1188   {
   1189     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting HS\n")
   1190     ;
   1191     GNUNET_assert (0);
   1192   }
   1193 }
   1194 
   1195 
   1196 /**
   1197  * Derive the initiator handshake secret
   1198  * @param kx key exchange info
   1199  */
   1200 static void
   1201 derive_ihts (const struct GNUNET_HashCode *transcript,
   1202              const struct GNUNET_ShortHashCode *hs,
   1203              struct GNUNET_ShortHashCode *ihts)
   1204 {
   1205   GNUNET_assert (GNUNET_OK ==
   1206                  GNUNET_CRYPTO_hkdf_expand (
   1207                    ihts,                                           // result
   1208                    sizeof (*ihts),                          // result len
   1209                    hs,                          // prk?
   1210                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1211                    GNUNET_CRYPTO_kdf_arg_string (I_HS_TRAFFIC_STR),
   1212                    GNUNET_CRYPTO_kdf_arg_auto  (transcript)));
   1213 }
   1214 
   1215 
   1216 /**
   1217  * Derive the responder handshake secret
   1218  * @param kx key exchange info
   1219  */
   1220 static void
   1221 derive_rhts (const struct GNUNET_HashCode *transcript,
   1222              const struct GNUNET_ShortHashCode *hs,
   1223              struct GNUNET_ShortHashCode *rhts)
   1224 {
   1225   GNUNET_assert (GNUNET_OK ==
   1226                  GNUNET_CRYPTO_hkdf_expand (
   1227                    rhts,
   1228                    sizeof (*rhts),
   1229                    hs,                          // prk? TODO
   1230                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1231                    GNUNET_CRYPTO_kdf_arg_string (R_HS_TRAFFIC_STR),
   1232                    GNUNET_CRYPTO_kdf_arg_auto (transcript)));
   1233 }
   1234 
   1235 
   1236 /**
   1237  * Derive the master secret
   1238  * @param kx key exchange info
   1239  */
   1240 static void
   1241 derive_ms (const struct GNUNET_ShortHashCode *hs,
   1242            const struct GNUNET_ShortHashCode *ss_I,
   1243            struct GNUNET_ShortHashCode *ms)
   1244 {
   1245   uint64_t ret;
   1246   struct GNUNET_ShortHashCode derived_handshake_secret;
   1247 
   1248   ret = GNUNET_CRYPTO_hkdf_expand (
   1249     &derived_handshake_secret,
   1250     sizeof (derived_handshake_secret),
   1251     hs,
   1252     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1253     GNUNET_CRYPTO_kdf_arg_string (DERIVED_STR));
   1254   if (GNUNET_OK != ret)
   1255   {
   1256     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dHS\n")
   1257     ;
   1258     GNUNET_assert (0);
   1259   }
   1260   // TODO check: are dHS the salt and ss_I the ikm or other way round?
   1261   ret = GNUNET_CRYPTO_hkdf_extract (ms,            // prk
   1262                                     &derived_handshake_secret,         // salt - dHS
   1263                                     sizeof (derived_handshake_secret), // salt_len
   1264                                     ss_I,              // ikm - initial key material
   1265                                     sizeof (*ss_I));
   1266   if (GNUNET_OK != ret)
   1267   {
   1268     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting MS\n")
   1269     ;
   1270     GNUNET_assert (0);
   1271   }
   1272 }
   1273 
   1274 
   1275 /**
   1276  * Generate per record nonce as per
   1277  * https://www.rfc-editor.org/rfc/rfc8446#section-5.3
   1278  * using per key nonce and sequence number
   1279  */
   1280 static void
   1281 generate_per_record_nonce (
   1282   uint64_t seq,
   1283   const uint8_t write_iv[AEAD_NONCE_BYTES],
   1284   uint8_t per_record_write_iv[AEAD_NONCE_BYTES])
   1285 {
   1286   uint64_t seq_nbo;
   1287   uint64_t *write_iv_ptr;
   1288   unsigned int byte_offset;
   1289 
   1290   seq_nbo = GNUNET_htonll (seq);
   1291   memcpy (per_record_write_iv,
   1292           write_iv,
   1293           AEAD_NONCE_BYTES);
   1294   byte_offset =
   1295     AEAD_NONCE_BYTES - sizeof (uint64_t);
   1296   write_iv_ptr = (uint64_t*) (per_record_write_iv + byte_offset);
   1297   *write_iv_ptr ^= seq_nbo;
   1298 }
   1299 
   1300 
   1301 /**
   1302  * key = HKDF-Expand [I,R][A,H]TS, "key", 32)
   1303  * nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 24)
   1304  */
   1305 static void
   1306 derive_per_message_secrets (
   1307   const struct GNUNET_ShortHashCode *ts,
   1308   uint64_t seq,
   1309   unsigned char key[AEAD_KEY_BYTES],
   1310   unsigned char nonce[AEAD_NONCE_BYTES])
   1311 {
   1312   unsigned char nonce_tmp[AEAD_NONCE_BYTES];
   1313   /* derive actual key */
   1314   GNUNET_assert (GNUNET_OK ==
   1315                  GNUNET_CRYPTO_hkdf_expand (
   1316                    key,
   1317                    AEAD_KEY_BYTES,
   1318                    ts,
   1319                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1320                    GNUNET_CRYPTO_kdf_arg_string (KEY_STR)));
   1321 
   1322   /* derive nonce */
   1323   GNUNET_assert (GNUNET_OK ==
   1324                  GNUNET_CRYPTO_hkdf_expand (
   1325                    nonce_tmp,
   1326                    AEAD_NONCE_BYTES,
   1327                    ts,
   1328                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1329                    GNUNET_CRYPTO_kdf_arg_string (IV_STR)));
   1330   generate_per_record_nonce (seq,
   1331                              nonce_tmp,
   1332                              nonce);
   1333 }
   1334 
   1335 
   1336 /**
   1337  * Derive the next application secret
   1338  * @param kx key exchange info
   1339  */
   1340 static void
   1341 derive_next_ats (const struct GNUNET_ShortHashCode *old_ats,
   1342                  struct GNUNET_ShortHashCode *new_ats)
   1343 {
   1344   int8_t ret;
   1345 
   1346   // FIXME: Not sure of PRK and output may overlap here!
   1347   ret = GNUNET_CRYPTO_hkdf_expand (
   1348     new_ats,
   1349     sizeof (*new_ats),
   1350     old_ats,
   1351     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1352     GNUNET_CRYPTO_kdf_arg_string (TRAFFIC_UPD_STR));
   1353   if (GNUNET_OK != ret)
   1354   {
   1355     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1356                 "Something went wrong deriving next *ATS key\n");
   1357     GNUNET_assert (0);
   1358   }
   1359 }
   1360 
   1361 
   1362 /**
   1363  * Derive the initiator application secret
   1364  * @param kx key exchange info
   1365  */
   1366 static void
   1367 derive_initial_ats (const struct GNUNET_HashCode *transcript,
   1368                     const struct GNUNET_ShortHashCode *ms,
   1369                     enum GSC_KX_Role role,
   1370                     struct GNUNET_ShortHashCode *initial_ats)
   1371 {
   1372   const char *traffic_str;
   1373 
   1374   if (ROLE_INITIATOR == role)
   1375     traffic_str = I_AP_TRAFFIC_STR;
   1376   else
   1377     traffic_str = R_AP_TRAFFIC_STR;
   1378   GNUNET_assert (GNUNET_OK ==
   1379                  GNUNET_CRYPTO_hkdf_expand (
   1380                    initial_ats,                                           // result
   1381                    sizeof (*initial_ats),                          // result len
   1382                    ms,
   1383                    GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1384                    GNUNET_CRYPTO_kdf_arg_string (traffic_str),
   1385                    GNUNET_CRYPTO_kdf_arg_auto (transcript)));
   1386 }
   1387 
   1388 
   1389 /**
   1390  * Generate the responder finished field
   1391  * @param kx key exchange info
   1392  * @param result location to which the responder finished field will be written
   1393  *               to
   1394  */
   1395 static void
   1396 generate_responder_finished (const struct GNUNET_HashCode *transcript,
   1397                              const struct GNUNET_ShortHashCode *ms,
   1398                              struct GNUNET_HashCode *result)
   1399 {
   1400   enum GNUNET_GenericReturnValue ret;
   1401   struct GNUNET_CRYPTO_AuthKey fk_R; // We might want to save this in kx?
   1402 
   1403   ret = GNUNET_CRYPTO_hkdf_expand (
   1404     &fk_R,                                // result
   1405     sizeof (fk_R),
   1406     ms,
   1407     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1408     GNUNET_CRYPTO_kdf_arg_string (R_FINISHED_STR));
   1409   if (GNUNET_OK != ret)
   1410   {
   1411     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1412                 "Something went wrong expanding fk_R\n");
   1413     GNUNET_assert (0);
   1414   }
   1415 
   1416   GNUNET_CRYPTO_hmac (&fk_R,
   1417                       transcript,
   1418                       sizeof (*transcript),
   1419                       result);
   1420 }
   1421 
   1422 
   1423 /**
   1424  * Generate the initiator finished field
   1425  * @param kx key exchange info
   1426  * @param result location to which the initiator finished field will be written
   1427  *               to
   1428  */
   1429 static void
   1430 generate_initiator_finished (const struct GNUNET_HashCode *transcript,
   1431                              const struct GNUNET_ShortHashCode *ms,
   1432                              struct GNUNET_HashCode *result)
   1433 {
   1434   enum GNUNET_GenericReturnValue ret;
   1435   struct GNUNET_CRYPTO_AuthKey fk_I; // We might want to save this in kx?
   1436 
   1437   ret = GNUNET_CRYPTO_hkdf_expand (
   1438     &fk_I,                                      // result
   1439     sizeof (fk_I),
   1440     ms,
   1441     GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL),
   1442     GNUNET_CRYPTO_kdf_arg_string (I_FINISHED_STR));
   1443   if (GNUNET_OK != ret)
   1444   {
   1445     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1446                 "Something went wrong expanding fk_I\n");
   1447     GNUNET_assert (0);
   1448   }
   1449   GNUNET_CRYPTO_hmac (&fk_I,
   1450                       transcript,
   1451                       sizeof (*transcript),
   1452                       result);
   1453 }
   1454 
   1455 
   1456 static void
   1457 resend_responder_hello (void *cls)
   1458 {
   1459   struct GSC_KeyExchangeInfo *kx = cls;
   1460 
   1461   kx->resend_task = NULL;
   1462   if (0 == kx->resend_tries_left)
   1463   {
   1464     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1465                 "Restarting KX\n");
   1466     restart_kx (kx);
   1467     return;
   1468   }
   1469   kx->resend_tries_left--;
   1470   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1471               "Resending responder hello. Retries left: %u\n",
   1472               kx->resend_tries_left);
   1473   GNUNET_MQ_send_copy (kx->mq, kx->resend_env);
   1474   schedule_resend (kx, &resend_responder_hello);
   1475 }
   1476 
   1477 
   1478 void
   1479 send_responder_hello (struct GSC_KeyExchangeInfo *kx)
   1480 {
   1481   enum GNUNET_GenericReturnValue ret;
   1482   struct GNUNET_CRYPTO_HpkeEncapsulation c_I;
   1483   struct ResponderHello *rhm_e; /* responder hello message - encrypted pointer */
   1484   struct GNUNET_MQ_Envelope *env;
   1485   struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_kem_challenge;
   1486   struct GNUNET_ShortHashCode rhts;
   1487   struct GNUNET_ShortHashCode ihts;
   1488   struct GNUNET_ShortHashCode hs;
   1489   struct GNUNET_ShortHashCode ms;
   1490   struct GNUNET_ShortHashCode ss_e;
   1491   struct GNUNET_ShortHashCode ss_I;
   1492   struct GNUNET_HashContext *hc;
   1493   unsigned char enc_key[AEAD_KEY_BYTES];
   1494   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   1495 
   1496   //      4. encaps -> shared_secret_e, c_e (kemChallenge)
   1497   //         TODO potentially write this directly into rhm?
   1498   ret = GNUNET_CRYPTO_hpke_kem_encaps (&kx->pk_e, // public ephemeral key of initiator
   1499                                        &ephemeral_kem_challenge,    // encapsulated key
   1500                                        &ss_e); // key - ss_e
   1501   if (GNUNET_OK != ret)
   1502   {
   1503     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1504                 "Something went wrong encapsulating ss_e\n");
   1505     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1506     return;
   1507   }
   1508   hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx);
   1509   //      6. encaps -> shared_secret_I, c_I
   1510   ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public key of I
   1511                                         &c_I,                              // encapsulated key
   1512                                         &ss_I);             // where to write the key material
   1513   if (GNUNET_OK != ret)
   1514   {
   1515     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1516                 "Something went wrong encapsulating ss_I\n");
   1517     GNUNET_CRYPTO_hash_context_abort (hc);
   1518     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1519     return;
   1520   }
   1521   //      7. generate RHTS (responder_handshare_secret_key) and RATS (responder_application_traffic_secret_key) (section 5)
   1522   {
   1523     struct GNUNET_HashCode transcript;
   1524     snapshot_transcript (hc, &transcript);
   1525 #if DEBUG_KX
   1526     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1527                 "Transcript snapshot for derivation of HS, MS: `%s'\n",
   1528                 GNUNET_h2s (&transcript));
   1529 #endif
   1530     derive_hs (&kx->early_secret_key,
   1531                &ss_e,
   1532                &hs);
   1533     derive_ms (&hs, &ss_I, &ms);
   1534   }
   1535 
   1536   // send ResponderHello
   1537   // TODO fill fields / services_info!
   1538   // 1. r_R <- random
   1539   struct ResponderHelloPayload *rhp;
   1540   size_t rhp_len = sizeof (*rhp) + strlen (my_services_info);
   1541   unsigned char rhp_buf[rhp_len];
   1542   size_t ct_len;
   1543 
   1544   rhp = (struct ResponderHelloPayload*) rhp_buf;
   1545   ct_len = rhp_len // ResponderHelloPayload, fist PT msg
   1546            + sizeof (struct GNUNET_HashCode) // Finished hash, second PT msg
   1547            + AEAD_TAG_BYTES * 2; // Two tags;
   1548   env = GNUNET_MQ_msg_extra (rhm_e,
   1549                              ct_len,
   1550                              GNUNET_MESSAGE_TYPE_CORE_RESPONDER_HELLO);
   1551 
   1552   rhm_e->r_R =
   1553     GNUNET_CRYPTO_random_u64 (UINT64_MAX);
   1554 
   1555   // c_e
   1556   GNUNET_memcpy (&rhm_e->c_e,
   1557                  &ephemeral_kem_challenge,
   1558                  sizeof (ephemeral_kem_challenge));
   1559   GNUNET_CRYPTO_hash_context_read (hc,
   1560                                    rhm_e,
   1561                                    sizeof (struct ResponderHello));
   1562   // 2. Encrypt ServicesInfo and c_I with RHTS
   1563   // derive RHTS
   1564   {
   1565     struct GNUNET_HashCode transcript;
   1566     snapshot_transcript (hc,
   1567                          &transcript);
   1568 #if DEBUG_KX
   1569     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1570                 "Transcript snapshot for derivation of *HTS: `%s'\n",
   1571                 GNUNET_h2s (&transcript));
   1572 #endif
   1573     derive_rhts (&transcript,
   1574                  &hs,
   1575                  &rhts);
   1576     derive_ihts (&transcript,
   1577                  &hs,
   1578                  &ihts);
   1579     derive_per_message_secrets (&rhts,
   1580                                 0,
   1581                                 enc_key,
   1582                                 enc_nonce);
   1583   }
   1584   // c_I
   1585   GNUNET_memcpy (&rhp->c_I, &c_I, sizeof (c_I));
   1586   // Services info empty for now.
   1587   GNUNET_memcpy (&rhp[1],
   1588                  my_services_info,
   1589                  strlen (my_services_info));
   1590 
   1591   {
   1592     unsigned long long out_ct_len;
   1593     struct GNUNET_HashCode finished;
   1594     struct GNUNET_HashCode transcript;
   1595     unsigned char *finished_buf;
   1596     GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1597                      (unsigned char*) &rhm_e[1], /* c - ciphertext */
   1598                      &out_ct_len, /* clen_p */
   1599                      rhp_buf, /* rhm_p - plaintext message */
   1600                      rhp_len, // mlen
   1601                      NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1602                               // fields?
   1603                      NULL, // nsec - unused
   1604                      enc_nonce, // npub - nonce // FIXME nonce can be reused
   1605                      enc_key)); // k - key RHTS
   1606     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1607                 "Encrypted and wrote %llu bytes\n",
   1608                 out_ct_len);
   1609     // 3. Create ResponderFinished (Section 6)
   1610     // Derive fk_I <- HKDF-Expand (MS, "r finished", NULL)
   1611     /* Forward the transcript */
   1612     /* {svcinfo, c_I}RHTS */
   1613     GNUNET_CRYPTO_hash_context_read (
   1614       hc,
   1615       &rhm_e[1],
   1616       out_ct_len);
   1617 
   1618     finished_buf = ((unsigned char*) &rhm_e[1]) + out_ct_len;
   1619     snapshot_transcript (hc,
   1620                          &transcript);
   1621 #if DEBUG_KX
   1622     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1623                 "Transcript snapshot for derivation of Rfinished: `%s'\n",
   1624                 GNUNET_h2s (&transcript));
   1625 #endif
   1626     generate_responder_finished (&transcript,
   1627                                  &ms,
   1628                                  &finished);
   1629     // 4. Encrypt ResponderFinished
   1630     derive_per_message_secrets (&rhts,
   1631                                 1,
   1632                                 enc_key,
   1633                                 enc_nonce);
   1634     GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   1635                      finished_buf,                               /* c - ciphertext */
   1636                      &out_ct_len, /* clen_p */
   1637                      (unsigned char*) &finished, /* rhm_p - plaintext message */
   1638                      sizeof (finished), // mlen
   1639                      NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   1640                               // fields?
   1641                      NULL, // nsec - unused
   1642                      enc_nonce, // npub
   1643                      enc_key)); // k - key RHTS
   1644     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1645                 "Encrypted and wrote %llu bytes\n",
   1646                 out_ct_len);
   1647     /* Forward the transcript
   1648      * after responder finished,
   1649      * before deriving *ATS and generating finished_I
   1650      * (finished_I will be generated when receiving the InitiatorFinished message
   1651      * in order to check it) */
   1652     GNUNET_CRYPTO_hash_context_read (
   1653       hc,
   1654       finished_buf,
   1655       out_ct_len);
   1656     // 5. optionally send application data - encrypted with RATS
   1657     // We do not really have any application data, instead, we send the ACK
   1658     snapshot_transcript (hc,
   1659                          &transcript);
   1660 #if DEBUG_KX
   1661     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1662                 "Transcript snapshot for derivation of *ATS: `%s'\n",
   1663                 GNUNET_h2s (&transcript));
   1664 #endif
   1665     derive_initial_ats (&transcript,
   1666                         &ms,
   1667                         ROLE_RESPONDER,
   1668                         &kx->current_ats);
   1669   }
   1670   /* Lock into struct */
   1671   GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1672   kx->transcript_hash_ctx = hc;
   1673   kx->master_secret = ms;
   1674   kx->handshake_secret = hs;
   1675   kx->ss_e = ss_e;
   1676   kx->ihts = ihts;
   1677   kx->rhts = rhts;
   1678   kx->ss_I = ss_I;
   1679   kx->current_epoch = 0;
   1680   kx->current_sqn = 0;
   1681   derive_per_message_secrets (&kx->current_ats,
   1682                               kx->current_sqn,
   1683                               enc_key,
   1684                               enc_nonce);
   1685 
   1686   GNUNET_MQ_send_copy (kx->mq, env);
   1687   kx->resend_env = env;
   1688   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent ResponderHello: %d %d\n", kx->role,
   1689               kx->status);
   1690   start_resend (kx, &resend_responder_hello);
   1691   kx->status = GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT;
   1692   monitor_notify_all (kx);
   1693   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1694 }
   1695 
   1696 
   1697 /**
   1698  * Finish handling the InitiatorHello @a ihm_e now that @a ss_R, the
   1699  * shared secret decapsulated with our peer identity's private key, is
   1700  * available.
   1701  *
   1702  * @param kx key exchange the hello arrived on
   1703  * @param ihm_e the InitiatorHello, still owned by the message handler
   1704  * @param ss_R decapsulation of @a ihm_e's @e c_R
   1705  */
   1706 static void
   1707 handle_initiator_hello_cont (struct GSC_KeyExchangeInfo *kx,
   1708                              const struct InitiatorHello *ihm_e,
   1709                              const struct GNUNET_ShortHashCode *ss_R)
   1710 {
   1711   const struct GNUNET_HashCode *my_identity_hash;
   1712   uint32_t ihm_len = ntohs (ihm_e->header.size);
   1713   unsigned char enc_key[AEAD_KEY_BYTES];
   1714   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   1715   struct GNUNET_PeerIdentity peer_before = kx->peer;
   1716   struct GNUNET_HashCode h1;
   1717   struct GNUNET_HashCode transcript;
   1718   struct GNUNET_ShortHashCode es;
   1719   struct GNUNET_ShortHashCode ets;
   1720   enum GNUNET_GenericReturnValue ret;
   1721 
   1722   GNUNET_memcpy (&kx->pk_e.ecdhe_key,
   1723                  &ihm_e->pk_e,
   1724                  sizeof (ihm_e->pk_e));
   1725   //      5. generate ETS (early_traffic_secret_key, decrypt pk_i
   1726   //         expand ETS <- expand ES <- extract ss_R
   1727   //         use ETS to decrypt
   1728 
   1729   /* Forward the transcript hash context over the unencrypted fields to get it
   1730    * to the same status that the initiator had when it needed to derive es and
   1731    * ets for the encryption */
   1732   GNUNET_CRYPTO_hash_context_read (
   1733     kx->transcript_hash_ctx,
   1734     ihm_e,
   1735     sizeof (struct InitiatorHello));
   1736   snapshot_transcript (kx->transcript_hash_ctx,
   1737                        &transcript);
   1738 #if DEBUG_KX
   1739   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1740               "Transcript snapshot for derivation of ES, ETS: `%s'\n",
   1741               GNUNET_h2s (&transcript));
   1742 #endif
   1743   derive_es_ets (&transcript, ss_R, &es, &ets);
   1744   derive_per_message_secrets (&ets,
   1745                               0,
   1746                               enc_key,
   1747                               enc_nonce);
   1748   {
   1749     struct InitiatorHelloPayload *ihmp;
   1750     size_t ct_len = ihm_len - sizeof (struct InitiatorHello);
   1751     unsigned char ihmp_buf[ct_len - AEAD_TAG_BYTES];
   1752     ihmp = (struct InitiatorHelloPayload*) ihmp_buf;
   1753     ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   1754       ihmp_buf,   // unsigned char *m
   1755       NULL,                                      // mlen_p message length
   1756       NULL,                                      // unsigned char *nsec       - unused: NULL
   1757       (unsigned char*) &ihm_e[1],   // const unsigned char *c    - ciphertext
   1758       ct_len,                                     // unsigned long long clen   - length of ciphertext
   1759       // mac,                                   // const unsigned char *mac  - authentication tag
   1760       NULL,                                      // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   1761       0,                                         // unsigned long long adlen
   1762       enc_nonce,      // const unsigned char *npub - nonce
   1763       enc_key   // const unsigned char *k    - key
   1764       );
   1765     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pid_sender: %s\n",
   1766                 GNUNET_i2s (&ihmp->pk_I));
   1767     if (0 != ret)
   1768     {
   1769       GNUNET_log (DECRYPTION_FAILURES_LOG_LEVEL,
   1770                   "Something went wrong decrypting: %d\n", ret);
   1771       GNUNET_break_op (0);
   1772       GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1773       restart_kx (kx);
   1774       return;
   1775     }
   1776     /* now forward it considering the encrypted messages that the initiator was
   1777      * able to send after deriving the es and ets */
   1778     GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx,
   1779                                      &ihm_e[1],
   1780                                      ct_len);
   1781     GNUNET_memcpy (&kx->peer,
   1782                    &ihmp->pk_I,
   1783                    sizeof (struct GNUNET_PeerIdentity));
   1784   }
   1785 
   1786   /* @e pk_I is the initiator's *claim* about who it is, and nothing has
   1787      checked it.  It must be the peer transport handed us this @a kx for:
   1788      @e role was derived from that identity, GSC_SESSIONS_create() below
   1789      keys the session on it, and transport routes everything we send by it.
   1790      Letting the claim through means one peer can make us run a session
   1791      under another peer's identity, and -- via the role comparison right
   1792      below, which is computed over exactly this value -- can pick a @e pk_I
   1793      that sends us down the reject path at will. */
   1794   if (0 != GNUNET_memcmp (&kx->peer, &peer_before))
   1795   {
   1796     GNUNET_break_op (0);
   1797     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1798                 "InitiatorHello from `%s' claims to be `%s'\n",
   1799                 GNUNET_i2s (&peer_before),
   1800                 GNUNET_i2s2 (&kx->peer));
   1801     kx->peer = peer_before;
   1802     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1803     kx->transcript_hash_ctx = NULL;
   1804     kx->status = GNUNET_CORE_KX_STATE_AWAIT_INITIATION;
   1805     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1806     return;
   1807   }
   1808 
   1809   my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils);
   1810   GNUNET_assert (NULL != my_identity_hash);
   1811 
   1812   // We could follow with the rest of the Key Schedule (dES, HS, ...) for now
   1813   /* Check that we are actually in the receiving role */
   1814   GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1);
   1815   if (0 < GNUNET_CRYPTO_hash_cmp (&h1, my_identity_hash))
   1816   {
   1817     /* peer with "lower" identity starts KX, otherwise we typically end up
   1818        with both peers starting the exchange and transmit the 'set key'
   1819        message twice */
   1820     /* Something went wrong - we have the lower value and should have sent the
   1821      * InitiatorHello, but instead received it. TODO handle this case
   1822      * We might end up in this case if the initiator didn't initiate the
   1823      * handshake long enough and the 'responder' initiates the handshake */
   1824     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1825                 "Something went wrong - we have the lower value and should have sent the InitiatorHello, but instead received it.\n");
   1826     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   1827     kx->transcript_hash_ctx = NULL;
   1828     /* Same reason the three other reject paths in #handle_initiator_hello()
   1829        do this: that function set @e status to INITIATOR_HELLO_RECEIVED
   1830        before calling us, and leaving it there makes every *later* hello hit
   1831        the "Already received InitiatorHello" guard and be dropped, forever.
   1832        Rejecting this hello must not cost us the next one. */
   1833     kx->status = GNUNET_CORE_KX_STATE_AWAIT_INITIATION;
   1834     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1835     return;
   1836   }
   1837 
   1838   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer ID of other peer: %s\n", GNUNET_i2s
   1839                 (&kx->peer));
   1840   /* We update the monitoring peers here because now we know
   1841    * that we can decrypt the message AND know the PID
   1842    */
   1843   monitor_notify_all (kx);
   1844   kx->ss_R = *ss_R;
   1845   kx->early_secret_key = es;
   1846   kx->early_traffic_secret = ets;
   1847   send_responder_hello (kx);
   1848 }
   1849 
   1850 
   1851 static int
   1852 check_initiator_hello (void *cls, const struct InitiatorHello *m)
   1853 {
   1854   uint16_t size = ntohs (m->header.size);
   1855 
   1856   if (size < sizeof (*m)
   1857       + sizeof (struct InitiatorHelloPayload)
   1858       + AEAD_TAG_BYTES)
   1859   {
   1860     return GNUNET_SYSERR;
   1861   }
   1862   return GNUNET_OK;
   1863 }
   1864 
   1865 
   1866 /**
   1867  * Handle the InitiatorHello message
   1868  *  - derives necessary keys from the plaintext parts
   1869  *  - decrypts the encrypted part
   1870  *  - replies with ResponderHello message
   1871  * @param cls the key exchange info
   1872  * @param ihm_e InitiatorHello message
   1873  */
   1874 static void
   1875 handle_initiator_hello (void *cls, const struct InitiatorHello *ihm_e)
   1876 {
   1877   const struct GNUNET_HashCode *my_identity_hash;
   1878   const struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
   1879   struct GSC_KeyExchangeInfo *kx = cls;
   1880   struct GNUNET_HashCode ih_hash;
   1881   struct GNUNET_ShortHashCode ss_R;
   1882   size_t ihm_len;
   1883 
   1884   ihm_len = ntohs (ihm_e->header.size);
   1885   GNUNET_CRYPTO_hash (ihm_e,
   1886                       ihm_len,
   1887                       &ih_hash);
   1888   if (ROLE_INITIATOR == kx->role)
   1889   {
   1890     GNUNET_break_op (0);
   1891     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1892                 "I am an initiator! Tearing down...\n");
   1893     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1894     return;
   1895   }
   1896   if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED)
   1897   {
   1898     /* Now that the decapsulation is synchronous nothing can observe this
   1899        state from the outside -- #handle_initiator_hello_cont() runs before
   1900        we return.  Keep the guard anyway: reaching it means the state
   1901        machine leaked a state, not that a peer did anything. */
   1902     GNUNET_break (0);
   1903     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1904                 "Already received InitiatorHello: %d %d\n", kx->role, kx->status
   1905                 );
   1906     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1907     return;
   1908   }
   1909   else if (kx->status > GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED)
   1910   {
   1911     if (0 == GNUNET_memcmp (&ih_hash,
   1912                             &kx->ih_hash))
   1913     {
   1914       /* Not a new exchange at all: the initiator resent the very hello we
   1915          are already answering, because our ResponderHello did not make it
   1916          back in time (#resend_initiator_hello() sends a copy of the same
   1917          envelope, so a retransmission is byte-identical).
   1918 
   1919          Starting over here is what breaks the pair.  A fresh
   1920          #send_responder_hello() picks a new @e ss_e and feeds a new
   1921          ResponderHello into the transcript, and the transcript is what both
   1922          @e finished_R and @e finished_I are computed over.  The initiator
   1923          answers whichever ResponderHello reaches it first and binds its
   1924          InitiatorDone to *that* transcript, while we have moved on to the
   1925          transcript of our latest one -- so #handle_initiator_done() cannot
   1926          verify @e finished_I and drops it, every retransmission included.
   1927          Neither side can make progress and neither side sees an error: the
   1928          initiator sits in #GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT
   1929          reporting "Unexpected ResponderHello", we sit in
   1930          #GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT, and both merely run out
   1931          of retries after RESEND_MAX_TRIES and start over -- with no reason
   1932          for the next attempt to be any luckier.  One InitiatorHello
   1933          retransmission, which any hiccup on the path produces, is enough to
   1934          lose the peer indefinitely.
   1935 
   1936          Retransmit our flight instead and leave the handshake state alone,
   1937          per RFC 9147, Section 5.8: "implementations MUST retransmit their
   1938          last flight in response to a retransmitted flight from the peer".
   1939          Our own @e resend_task keeps its schedule; this only adds the
   1940          answer the initiator is waiting for. */
   1941       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1942                   "InitiatorHello repeated by `%s' in state %d\n",
   1943                   GNUNET_i2s (&kx->peer),
   1944                   kx->status);
   1945       GNUNET_STATISTICS_update (GSC_stats,
   1946                                 gettext_noop (
   1947                                   "# InitiatorHello retransmissions received"),
   1948                                 1,
   1949                                 GNUNET_NO);
   1950       if ((GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT == kx->status) &&
   1951           (NULL != kx->resend_env))
   1952         GNUNET_MQ_send_copy (kx->mq,
   1953                              kx->resend_env);
   1954       /* Past that state the initiator already had our ResponderHello (we
   1955          only leave it once @e finished_I verifies), so this is a duplicate
   1956          that crossed with its InitiatorDone.  Nothing to answer, and
   1957          nothing that may cost us the association we just built. */
   1958       GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   1959       return;
   1960     }
   1961     /* The initiator has given up on whatever we still hold and started
   1962        over.  Only the initiator drives this handshake, so follow it rather
   1963        than dropping the hello.
   1964        This used to return, which deadlocks the pair whenever we are in
   1965        #GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED: an InitiatorHello is not
   1966        an EncryptedMessage and so does not refresh @e timeout, and nothing
   1967        else ever leaves that state, so we would reject every retransmit
   1968        until our own idle timeout fires -- five minutes during which the
   1969        initiator restarts its exchange every 50s and we report the peer as
   1970        connected.  In #GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT it is a
   1971        plain retransmit: the initiator resends precisely because it did not
   1972        get our ResponderHello, and answering the hello it actually sent
   1973        converges instead of leaving both sides to turn over on unrelated
   1974        50s timers that need not ever re-phase.
   1975 
   1976        This is RFC 9147, Section 5.11: "In cases where a server believes it
   1977        has an existing association [...] and it receives an epoch=0
   1978        ClientHello, it SHOULD proceed with a new handshake but MUST NOT
   1979        destroy the existing association until the client has demonstrated
   1980        reachability [...] by completing a complete handshake including
   1981        delivering a verifiable Finished message."
   1982 
   1983        So only the handshake state goes.  An InitiatorHello is not
   1984        authenticated -- @e finished_I in the InitiatorDone is our Finished
   1985        -- and must not be able to cost us an association on its own.  What
   1986        we have keeps its traffic keys (@e association_up stays set, and the
   1987        record layer keys off that rather than off @e status), its
   1988        @e heartbeat_task and its @e timeout, and clients keep being told the
   1989        peer is connected.  #handle_initiator_done() does the swap once, and
   1990        only once, @e finished_I verifies.  If it never does, the old
   1991        association dies of its own idle timeout exactly as it would have. */
   1992     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1993                 "Peer `%s' restarted the key exchange in state %d, following\n",
   1994                 GNUNET_i2s (&kx->peer),
   1995                 kx->status);
   1996     reset_handshake (kx);
   1997   }
   1998   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorHello: %d %d\n", kx->
   1999               role, kx->status);
   2000   GNUNET_assert (NULL == kx->transcript_hash_ctx);
   2001   kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start ();
   2002   GNUNET_assert (NULL != kx->transcript_hash_ctx);
   2003 
   2004   GNUNET_STATISTICS_update (GSC_stats,
   2005                             gettext_noop ("# key exchanges initiated"),
   2006                             1,
   2007                             GNUNET_NO);
   2008 
   2009   kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED;
   2010 
   2011   my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils);
   2012   GNUNET_assert (NULL != my_identity_hash);
   2013 
   2014   //      1. verify type _INITIATOR_HELLO
   2015   //         - This is implicytly done by arriving within this handler
   2016   //         - or is this about verifying the 'additional data' part of aead?
   2017   //           should it check the encryption + mac? (is this implicitly done
   2018   //           while decrypting?)
   2019   //      2. verify H(pk_R) matches pk_R
   2020   if (0 != memcmp (&ihm_e->h_pk_R,
   2021                    my_identity_hash,
   2022                    sizeof (struct GNUNET_HashCode)))
   2023   {
   2024     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2025                 "This message is not meant for us (H(PID) mismatch)\n");
   2026     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2027     kx->transcript_hash_ctx = NULL;
   2028     /* Leaving @e status at #GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED
   2029        here wedges the kx: every later hello then hits the "already
   2030        received" guard above and is dropped, forever. */
   2031     kx->status = GNUNET_CORE_KX_STATE_AWAIT_INITIATION;
   2032     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2033     return;
   2034   }
   2035   // FIXME this sometimes triggers in the tests - why?
   2036   //      3. decaps -> shared_secret_R, c_R (kemChallenge)
   2037   /* From here on this is the hello we answer, so a byte-identical one is a
   2038      retransmission of it and must not restart the exchange. */
   2039   kx->ih_hash = ih_hash;
   2040   my_private_key = GNUNET_PILS_get_private_key (GSC_pils);
   2041   if (NULL == my_private_key)
   2042   {
   2043     /* #GSC_KX_start() enables local key access before we ever talk to
   2044        TRANSPORT, so this means the key on disk does not match the identity
   2045        PILS announced.  We cannot answer any hello in that state. */
   2046     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2047                 "No private key for our peer identity, cannot answer hello"
   2048                 " from `%s'\n",
   2049                 GNUNET_i2s (&kx->peer));
   2050     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2051     kx->transcript_hash_ctx = NULL;
   2052     kx->status = GNUNET_CORE_KX_STATE_AWAIT_INITIATION;
   2053     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2054     return;
   2055   }
   2056   if (GNUNET_OK !=
   2057       GNUNET_CRYPTO_eddsa_kem_decaps (my_private_key,
   2058                                       &ihm_e->c_R,
   2059                                       &ss_R))
   2060   {
   2061     GNUNET_break_op (0);
   2062     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2063                 "Failed to decapsulate c_R of hello from `%s'\n",
   2064                 GNUNET_i2s (&kx->peer));
   2065     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2066     kx->transcript_hash_ctx = NULL;
   2067     kx->status = GNUNET_CORE_KX_STATE_AWAIT_INITIATION;
   2068     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2069     return;
   2070   }
   2071   handle_initiator_hello_cont (kx,
   2072                                ihm_e,
   2073                                &ss_R);
   2074 }
   2075 
   2076 
   2077 struct ResponderHelloCls
   2078 {
   2079   /* Current KX session */
   2080   struct GSC_KeyExchangeInfo *kx;
   2081 
   2082   /* responder hello message - encrypted */
   2083   struct ResponderHello rhm_e;
   2084 
   2085   /* responder hello message - plain/decrypted */
   2086   struct ResponderHelloPayload *rhp;
   2087 
   2088   /* Decrypted finish hash */
   2089   struct GNUNET_HashCode decrypted_finish;
   2090 
   2091   /* Encrypted finished CT (for transcript later) */
   2092   char finished_enc[sizeof (struct GNUNET_HashCode)
   2093                     + AEAD_TAG_BYTES];
   2094 
   2095   /* Temporary transcript context */
   2096   struct GNUNET_HashContext *hc;
   2097 
   2098   /* Temporary handshake secret */
   2099   struct GNUNET_ShortHashCode hs;
   2100 
   2101   /* Temporary handshake secret */
   2102   struct GNUNET_ShortHashCode ss_e;
   2103 
   2104   /* Temporary handshake secret */
   2105   struct GNUNET_ShortHashCode ihts;
   2106 
   2107   /* Temporary handshake secret */
   2108   struct GNUNET_ShortHashCode rhts;
   2109 };
   2110 
   2111 static void
   2112 resend_initiator_done (void *cls)
   2113 {
   2114   struct GSC_KeyExchangeInfo *kx = cls;
   2115 
   2116   kx->resend_task = NULL;
   2117   if (0 == kx->resend_tries_left)
   2118   {
   2119     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2120                 "Restarting KX\n");
   2121     restart_kx (kx);
   2122     return;
   2123   }
   2124   kx->resend_tries_left--;
   2125   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2126               "Resending initiator done. Retries left: %u\n",
   2127               kx->resend_tries_left);
   2128   GNUNET_MQ_send_copy (kx->mq, kx->resend_env);
   2129   schedule_resend (kx, &resend_initiator_done);
   2130 }
   2131 
   2132 
   2133 /**
   2134  * Finish handling a ResponderHello now that @a ss_I, the shared secret
   2135  * decapsulated with our peer identity's private key, is available.
   2136  *
   2137  * Takes ownership of @a rh_ctx.
   2138  *
   2139  * @param rh_ctx state accumulated by #handle_responder_hello()
   2140  * @param ss_I decapsulation of the ResponderHello's @e c_I
   2141  */
   2142 static void
   2143 handle_responder_hello_cont (struct ResponderHelloCls *rh_ctx,
   2144                              const struct GNUNET_ShortHashCode *ss_I)
   2145 {
   2146   struct GSC_KeyExchangeInfo *kx = rh_ctx->kx;
   2147   struct InitiatorDone *idm_e; /* encrypted */
   2148   struct InitiatorDone idm_local;
   2149   struct InitiatorDone *idm_p; /* plaintext */
   2150   struct GNUNET_MQ_Envelope *env;
   2151   unsigned char enc_key[AEAD_KEY_BYTES];
   2152   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2153   struct ConfirmationAck ack_i;
   2154   struct GNUNET_HashCode transcript;
   2155   struct GNUNET_ShortHashCode ms;
   2156 
   2157   // XXX valgrind reports uninitialized memory
   2158   //     the following is a way to check whether this memory was meant
   2159   // memset (&rhm_local, 0, sizeof (rhm_local)); - adapt to cls if still needed
   2160   memset (&idm_local, 0, sizeof (idm_local));
   2161 
   2162   kx->ss_I = *ss_I;
   2163 
   2164   /* derive *ATS */
   2165   derive_ms (&rh_ctx->hs, ss_I, &ms);;
   2166   // 5. Create ResponderFinished as per Section 6 and check against decrypted payload.
   2167   struct GNUNET_HashCode responder_finished;
   2168   // Transcript updates, snapshot again
   2169   snapshot_transcript (rh_ctx->hc,
   2170                        &transcript);
   2171 #if DEBUG_KX
   2172   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2173               "Transcript snapshot for derivation of Rfinished: `%s'\n",
   2174               GNUNET_h2s (&transcript));
   2175 #endif
   2176   generate_responder_finished (&transcript,
   2177                                &ms,
   2178                                &responder_finished);
   2179   if (0 != memcmp (&rh_ctx->decrypted_finish,
   2180                    &responder_finished,
   2181                    sizeof (struct GNUNET_HashCode)))
   2182   {
   2183     /* A peer that answers our InitiatorHello with a ResponderHello whose
   2184        finished field does not verify must not be able to abort us; this
   2185        used to be a GNUNET_assert (0). */
   2186     GNUNET_break_op (0);
   2187     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2188                 "Could not verify \"responder finished\" from `%s'\n",
   2189                 GNUNET_i2s (&kx->peer));
   2190     GNUNET_free (rh_ctx->rhp);
   2191     GNUNET_CRYPTO_hash_context_abort (rh_ctx->hc);
   2192     GNUNET_free (rh_ctx);
   2193     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2194     restart_kx (kx);
   2195     return;
   2196   }
   2197 
   2198 
   2199   /* Forward the transcript
   2200    * after generating finished_R,
   2201    * before deriving *ATS */
   2202   GNUNET_CRYPTO_hash_context_read (
   2203     rh_ctx->hc,
   2204     rh_ctx->finished_enc,
   2205     sizeof (rh_ctx->finished_enc));
   2206 
   2207   // At this point we cannot fail anymore and may lock into kx
   2208   GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2209   kx->transcript_hash_ctx = rh_ctx->hc;
   2210   kx->ss_I = *ss_I;
   2211   kx->handshake_secret = rh_ctx->hs;
   2212   kx->ss_e = rh_ctx->ss_e;
   2213   kx->ihts = rh_ctx->ihts;
   2214   kx->rhts = rh_ctx->rhts;
   2215   kx->master_secret = ms;
   2216   GNUNET_free (rh_ctx->rhp);
   2217   GNUNET_free (rh_ctx);
   2218   rh_ctx = NULL;
   2219 
   2220   snapshot_transcript (kx->transcript_hash_ctx,
   2221                        &transcript);
   2222 #if DEBUG_KX
   2223   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2224               "Transcript snapshot for derivation of *ATS: `%s'\n",
   2225               GNUNET_h2s (&transcript));
   2226 #endif
   2227   derive_initial_ats (&transcript,
   2228                       &kx->master_secret,
   2229                       ROLE_RESPONDER,
   2230                       &kx->their_ats[0]);
   2231   for (int i = 0; i < MAX_EPOCHS - 1; i++)
   2232   {
   2233     derive_next_ats (&kx->their_ats[i],
   2234                      &kx->their_ats[i + 1]);
   2235   }
   2236   kx->their_max_epoch = MAX_EPOCHS - 1;
   2237 
   2238   derive_per_message_secrets (&kx->ihts,
   2239                               0,
   2240                               enc_key,
   2241                               enc_nonce);
   2242   /* Create InitiatorDone message */
   2243   idm_p = &idm_local; /* plaintext */
   2244   env = GNUNET_MQ_msg_extra (idm_e,
   2245                              sizeof (ack_i)
   2246                              + AEAD_TAG_BYTES,
   2247                              GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE);
   2248   // 6. Create IteratorFinished as per Section 6.
   2249   generate_initiator_finished (&transcript,
   2250                                &kx->master_secret,
   2251                                &idm_p->finished);
   2252   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2253               "InteratorFinished: `%s'\n",
   2254               GNUNET_h2s (&idm_p->finished));
   2255   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2256               "Transcript `%s'\n",
   2257               GNUNET_h2s (&transcript));
   2258   // 7. Send InteratorFinished message encrypted with the key derived from IHTS to R
   2259 
   2260   GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   2261                    (unsigned char*) &idm_e->finished, /* c - ciphertext */
   2262                    NULL, /* clen_p */
   2263                    (unsigned char*) &idm_p->finished, /* idm_p - plaintext message */
   2264                    sizeof (idm_p->finished), // mlen
   2265                    NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   2266                             // fields?
   2267                    NULL, // nsec - unused
   2268                    enc_nonce, // npub - nonce
   2269                    enc_key)); // k - key IHTS
   2270   /* Forward the transcript hash context
   2271    * after generating finished_I and RATS_0
   2272    * before deriving IATS_0 */
   2273   GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx,
   2274                                    &idm_e->finished,
   2275                                    sizeof (idm_e->finished)
   2276                                    + AEAD_TAG_BYTES);
   2277   snapshot_transcript (kx->transcript_hash_ctx,
   2278                        &transcript);
   2279 #if DEBUG_KX
   2280   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2281               "Transcript snapshot for derivation of *ATS: `%s'\n",
   2282               GNUNET_h2s (&transcript));
   2283 #endif
   2284   derive_initial_ats (&transcript,
   2285                       &kx->master_secret,
   2286                       ROLE_INITIATOR,
   2287                       &kx->current_ats);
   2288   kx->current_epoch = 0;
   2289   kx->current_sqn = 0;
   2290   /* We start sending under this epoch here, so it has to be dated here too.
   2291      #check_if_ack_or_heartbeat() only sets @e current_epoch_expiration once
   2292      the responder's Ack arrives; until then it holds whatever the previous
   2293      association left (zero for a first exchange), and #check_rekey() treats
   2294      a past expiration as "rekey now".  Anything we send while waiting for
   2295      the Ack -- the Ack we answer an early heartbeat with, say -- would then
   2296      burn an epoch the responder has no reason to expect. */
   2297   kx->current_epoch_expiration =
   2298     GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2299   /* Application traffic keys are installed, so from the record layer's
   2300      point of view the association exists from here: we have to be able to
   2301      deprotect the responder's Ack, which arrives before the handshake is
   2302      confirmed.  The client-visible session is created only once it does. */
   2303   replay_reset_all (kx);
   2304   kx->association_up = GNUNET_YES;
   2305   // 8. optionally encrypt payload TODO
   2306   derive_per_message_secrets (&kx->current_ats,
   2307                               kx->current_sqn,
   2308                               enc_key,
   2309                               enc_nonce);
   2310   kx->current_sqn++;
   2311   ack_i.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   2312   ack_i.header.size = htons (sizeof ack_i);
   2313   GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
   2314                    (unsigned char*) &idm_e[1], /* c - ciphertext */
   2315                    NULL, /* clen_p */
   2316                    (unsigned char*) &ack_i, /* rhm_p - plaintext message */
   2317                    sizeof ack_i, // mlen
   2318                    NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
   2319                             // fields?
   2320                    NULL, // nsec - unused
   2321                    enc_nonce, // npub - nonce // FIXME nonce can be reused
   2322                    enc_key)); // k - key RHTS
   2323 
   2324   GNUNET_MQ_send_copy (kx->mq, env);
   2325   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent InitiatorDone: %d %d\n", kx->role,
   2326               kx->status);
   2327 
   2328 
   2329   kx->resend_env = env;
   2330   start_resend (kx, &resend_initiator_done);
   2331   kx->status = GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT;
   2332   monitor_notify_all (kx);
   2333   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2334 }
   2335 
   2336 
   2337 static int
   2338 check_responder_hello (void *cls, const struct ResponderHello *m)
   2339 {
   2340   uint16_t size = ntohs (m->header.size);
   2341 
   2342   if (size < sizeof (*m)
   2343       + sizeof (struct ResponderHelloPayload)
   2344       + sizeof (struct GNUNET_HashCode)
   2345       + AEAD_TAG_BYTES * 2)
   2346   {
   2347     return GNUNET_SYSERR;
   2348   }
   2349   return GNUNET_OK;
   2350 }
   2351 
   2352 
   2353 /**
   2354  * Handle Responder Hello message
   2355  * @param cls key exchange info
   2356  * @param rhm_e ResponderHello message
   2357  */
   2358 static void
   2359 handle_responder_hello (void *cls, const struct ResponderHello *rhm_e)
   2360 {
   2361   struct GSC_KeyExchangeInfo *kx = cls;
   2362   const struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
   2363   struct ResponderHelloCls *rh_ctx;
   2364   struct GNUNET_HashCode transcript;
   2365   struct GNUNET_HashCode rh_hash;
   2366   struct GNUNET_HashContext *hc;
   2367   struct GNUNET_ShortHashCode ss_I;
   2368   unsigned char enc_key[AEAD_KEY_BYTES];
   2369   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2370   enum GNUNET_GenericReturnValue ret;
   2371 
   2372   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ResponderHello: %d %d\n", kx->
   2373               role, kx->status);
   2374 
   2375   GNUNET_CRYPTO_hash (rhm_e,
   2376                       ntohs (rhm_e->header.size),
   2377                       &rh_hash);
   2378   if (ROLE_RESPONDER == kx->role)
   2379   {
   2380     GNUNET_break_op (0);
   2381     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2382                 "I am the responder! Ignoring.\n");
   2383     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2384     return;
   2385   }
   2386   if (GNUNET_CORE_KX_STATE_INITIATOR_HELLO_SENT != kx->status)
   2387   {
   2388     if ((GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT == kx->status) &&
   2389         (0 == GNUNET_memcmp (&rh_hash,
   2390                              &kx->rh_hash)))
   2391     {
   2392       /* The responder resent the ResponderHello we already answered, which
   2393          means our InitiatorDone did not reach it.  That is an ordinary
   2394          retransmission, not a protocol violation -- the GNUNET_break_op()
   2395          below used to report it as one, which is what "Unexpected
   2396          ResponderHello in state 6" in the logs is.  Answer it the way
   2397          RFC 9147, Section 5.8 requires: "implementations MUST retransmit
   2398          their last flight in response to a retransmitted flight from the
   2399          peer".  Our @e resend_task would get there on its own eventually;
   2400          doing it here converges at the pace of the peer's timer instead of
   2401          ours, and both are bounded by RESEND_MAX_TRIES. */
   2402       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2403                   "ResponderHello repeated by `%s', resending InitiatorDone\n",
   2404                   GNUNET_i2s (&kx->peer));
   2405       GNUNET_STATISTICS_update (GSC_stats,
   2406                                 gettext_noop (
   2407                                   "# ResponderHello retransmissions received"),
   2408                                 1,
   2409                                 GNUNET_NO);
   2410       if (NULL != kx->resend_env)
   2411         GNUNET_MQ_send_copy (kx->mq,
   2412                              kx->resend_env);
   2413       GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2414       return;
   2415     }
   2416     /* Outside of that state there is no handshake this message could
   2417        belong to.  In particular @e transcript_hash_ctx is then NULL, and
   2418        #GNUNET_CRYPTO_hash_context_copy() dereferences its argument -- so
   2419        a peer could crash us by sending a ResponderHello at any other
   2420        time.  Note that @e resend_task and @e resend_env below belong to
   2421        the exchange we *are* in the middle of and must not be cleared
   2422        before this point either. */
   2423     GNUNET_break_op (0);
   2424     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2425                 "Unexpected ResponderHello in state %d, ignoring\n",
   2426                 kx->status);
   2427     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2428     return;
   2429   }
   2430   /* From here on this is the hello we answer; recognising a retransmission
   2431      of it is what lets us resend our InitiatorDone above instead of
   2432      dropping the peer's flight on the floor. */
   2433   kx->rh_hash = rh_hash;
   2434   GNUNET_assert (NULL != kx->transcript_hash_ctx);
   2435   hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx);
   2436   if (NULL != kx->resend_task)
   2437   {
   2438     GNUNET_SCHEDULER_cancel (kx->resend_task);
   2439     kx->resend_task = NULL;
   2440   }
   2441   if (NULL != kx->resend_env)
   2442   {
   2443     GNUNET_MQ_discard (kx->resend_env);
   2444     kx->resend_env = NULL;
   2445   }
   2446 
   2447   /* Forward the transcript hash context */
   2448   GNUNET_CRYPTO_hash_context_read (hc,
   2449                                    rhm_e,
   2450                                    sizeof (struct ResponderHello));
   2451   // 1. Verify that the message type is CORE_RESPONDER_HELLO
   2452   //    - implicitly done by handling this message?
   2453   //    - or is this about verifying the 'additional data' part of aead?
   2454   //      should it check the encryption + mac? (is this implicitly done
   2455   //      while decrypting?)
   2456   // 2. sse <- Decaps(ske,ce)
   2457   rh_ctx = GNUNET_new (struct ResponderHelloCls);
   2458   ret = GNUNET_CRYPTO_hpke_kem_decaps (&kx->sk_e, // secret/private ephemeral key of initiator (us)
   2459                                        &rhm_e->c_e,    // encapsulated key
   2460                                        &rh_ctx->ss_e); // key - ss_e
   2461   if (GNUNET_OK != ret)
   2462   {
   2463     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2464                 "Something went wrong decapsulating ss_e\n");
   2465     GNUNET_CRYPTO_hash_context_abort (hc);
   2466     GNUNET_free (rh_ctx);
   2467     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2468     return;
   2469   }
   2470   // 3. Generate IHTS and RHTS from Section 5 and decrypt ServicesInfo, cI and ResponderFinished.
   2471   snapshot_transcript (hc, &transcript);
   2472 #if DEBUG_KX
   2473   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2474               "Transcript snapshot for derivation of HS, *HTS: `%s'\n",
   2475               GNUNET_h2s (&transcript));
   2476 #endif
   2477   derive_hs (&kx->early_secret_key,
   2478              &rh_ctx->ss_e,
   2479              &rh_ctx->hs);
   2480   derive_rhts (&transcript,
   2481                &rh_ctx->hs,
   2482                &rh_ctx->rhts);
   2483   derive_ihts (&transcript,
   2484                &rh_ctx->hs,
   2485                &rh_ctx->ihts);
   2486   derive_per_message_secrets (&rh_ctx->rhts,
   2487                               0,
   2488                               enc_key,
   2489                               enc_nonce);
   2490   rh_ctx->kx = kx;
   2491   GNUNET_memcpy (&rh_ctx->rhm_e, rhm_e, sizeof (*rhm_e));
   2492   {
   2493     unsigned long long int c_len;
   2494     unsigned char *finished_buf;
   2495     // use RHTS to decrypt
   2496     c_len = ntohs (rhm_e->header.size) - sizeof (*rhm_e)
   2497             - sizeof (struct GNUNET_HashCode)
   2498             - AEAD_TAG_BYTES;                                   // finished ct
   2499     rh_ctx->rhp = GNUNET_malloc (c_len
   2500                                  -
   2501                                  AEAD_TAG_BYTES);
   2502     rh_ctx->hc = hc;
   2503     finished_buf = ((unsigned char*) &rhm_e[1]) + c_len;
   2504     /* Forward the transcript_hash_ctx
   2505      * after rhts has been generated,
   2506      * before generating finished_R*/
   2507     GNUNET_CRYPTO_hash_context_read (
   2508       hc,
   2509       &rhm_e[1],
   2510       c_len);
   2511 
   2512     ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2513       (unsigned char*) rh_ctx->rhp,   // unsigned char *m
   2514       NULL,                                     // mlen_p message length
   2515       NULL,                                     // unsigned char *nsec       - unused: NULL
   2516       (unsigned char*) &rhm_e[1],   // const unsigned char *c    - ciphertext
   2517       c_len,                                    // unsigned long long clen   - length of ciphertext
   2518       NULL,                                     // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2519       0,                                        // unsigned long long adlen
   2520       enc_nonce,     // const unsigned char *npub - nonce
   2521       enc_key   // const unsigned char *k    - key
   2522       );
   2523     if (0 != ret)
   2524     {
   2525       GNUNET_log (DECRYPTION_FAILURES_LOG_LEVEL,
   2526                   "Something went wrong decrypting: %d\n", ret);
   2527       GNUNET_free (rh_ctx->rhp);
   2528       GNUNET_free (rh_ctx);
   2529       GNUNET_CRYPTO_hash_context_abort (hc);
   2530       GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2531       return;
   2532     }
   2533     // FIXME nonce reuse (see encryption)
   2534     derive_per_message_secrets (&rh_ctx->rhts,
   2535                                 1,
   2536                                 enc_key,
   2537                                 enc_nonce);
   2538     c_len = sizeof (struct GNUNET_HashCode)
   2539             + AEAD_TAG_BYTES;
   2540     ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2541       (unsigned char*) &rh_ctx->decrypted_finish,   // unsigned char *m
   2542       NULL,                                // mlen_p message length
   2543       NULL,                                // unsigned char *nsec       - unused: NULL
   2544       finished_buf,   // const unsigned char *c    - ciphertext
   2545       c_len,                               // unsigned long long clen   - length of ciphertext
   2546       NULL,                                // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2547       0,                                   // unsigned long long adlen
   2548       enc_nonce,   // const unsigned char *npub - nonce
   2549       enc_key   // const unsigned char *k    - key
   2550       );
   2551     if (0 != ret)
   2552     {
   2553       GNUNET_log (DECRYPTION_FAILURES_LOG_LEVEL,
   2554                   "Something went wrong decrypting finished field: %d\n", ret);
   2555       GNUNET_free (rh_ctx->rhp);
   2556       GNUNET_free (rh_ctx);
   2557       GNUNET_CRYPTO_hash_context_abort (hc);
   2558       GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2559       return;
   2560     }
   2561     GNUNET_memcpy (rh_ctx->finished_enc,
   2562                    finished_buf,
   2563                    c_len);
   2564   }
   2565   // 4. ssI <- Decaps(skI,cI).
   2566   my_private_key = GNUNET_PILS_get_private_key (GSC_pils);
   2567   if ( (NULL == my_private_key) ||
   2568        (GNUNET_OK !=
   2569         GNUNET_CRYPTO_eddsa_kem_decaps (my_private_key,
   2570                                         &rh_ctx->rhp->c_I,
   2571                                         &ss_I)) )
   2572   {
   2573     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2574                 "Failed to decapsulate c_I of ResponderHello from `%s'\n",
   2575                 GNUNET_i2s (&kx->peer));
   2576     GNUNET_free (rh_ctx->rhp);
   2577     GNUNET_free (rh_ctx);
   2578     GNUNET_CRYPTO_hash_context_abort (hc);
   2579     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2580     restart_kx (kx);
   2581     return;
   2582   }
   2583   handle_responder_hello_cont (rh_ctx,
   2584                                &ss_I);
   2585 }
   2586 
   2587 
   2588 static int
   2589 check_initiator_done (void *cls, const struct InitiatorDone *m)
   2590 {
   2591   uint16_t size = ntohs (m->header.size);
   2592 
   2593   if (size < sizeof (*m) + sizeof (struct ConfirmationAck))
   2594   {
   2595     return GNUNET_SYSERR;
   2596   }
   2597   return GNUNET_OK;
   2598 }
   2599 
   2600 
   2601 /**
   2602  * Handle InitiatorDone message
   2603  * @param cls key exchange info
   2604  * @param idm_e InitiatorDone message
   2605  */
   2606 static void
   2607 handle_initiator_done (void *cls, const struct InitiatorDone *idm_e)
   2608 {
   2609   struct GSC_KeyExchangeInfo *kx = cls;
   2610   struct InitiatorDone idm_local;
   2611   struct InitiatorDone *idm_p = &idm_local; /* plaintext */
   2612   struct GNUNET_HashCode initiator_finished;
   2613   struct GNUNET_HashCode transcript;
   2614   struct GNUNET_ShortHashCode their_ats;
   2615   struct GNUNET_HashContext *hc;
   2616   unsigned char enc_key[AEAD_KEY_BYTES];
   2617   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2618   struct ConfirmationAck ack_i;
   2619   struct ConfirmationAck ack_r;
   2620   int8_t ret;
   2621 
   2622   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorDone: %d %d\n", kx->
   2623               role, kx->status);
   2624   if (ROLE_INITIATOR == kx->role)
   2625   {
   2626     GNUNET_break_op (0);
   2627     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2628                 "I am the initiator! Tearing down...\n");
   2629     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2630     return;
   2631   }
   2632   if (GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED == kx->status)
   2633   {
   2634     /* The initiator did not see our ConfirmationAck and is resending (it
   2635        tries #RESEND_MAX_TRIES times).  Our handshake secrets are gone --
   2636        #cleanup_handshake_secrets() zeroed @e ihts -- so verifying this
   2637        message again is not possible and would only look like a decryption
   2638        failure.  Send what the initiator is actually missing instead. */
   2639     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2640                 "InitiatorDone repeated by `%s', resending our Ack\n",
   2641                 GNUNET_i2s (&kx->peer));
   2642     ack_r.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   2643     ack_r.header.size = htons (sizeof ack_r);
   2644     GSC_KX_encrypt_and_transmit (kx,
   2645                                  &ack_r,
   2646                                  sizeof ack_r);
   2647     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2648     return;
   2649   }
   2650   if (GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT != kx->status)
   2651   {
   2652     /* We have no handshake state this message could be checked against.
   2653        Note that @e resend_task and @e resend_env below belong to whatever
   2654        exchange we *are* in the middle of, so they must not be cleared
   2655        before this point. */
   2656     GNUNET_break_op (0);
   2657     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2658                 "Unexpected InitiatorDone in state %d, ignoring\n",
   2659                 kx->status);
   2660     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2661     return;
   2662   }
   2663   if (NULL != kx->resend_task)
   2664   {
   2665     GNUNET_SCHEDULER_cancel (kx->resend_task);
   2666     kx->resend_task = NULL;
   2667   }
   2668   if (NULL != kx->resend_env)
   2669   {
   2670     GNUNET_MQ_discard (kx->resend_env);
   2671     kx->resend_env = NULL;
   2672   }
   2673   derive_per_message_secrets (&kx->ihts,
   2674                               0,
   2675                               enc_key,
   2676                               enc_nonce);
   2677   ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2678     (unsigned char*) &idm_p->finished,     // unsigned char *m
   2679     NULL,                                  // mlen_p message length
   2680     NULL,                                  // unsigned char *nsec       - unused: NULL
   2681     (unsigned char*) &idm_e->finished,     // const unsigned char *c    - ciphertext
   2682     sizeof (idm_p->finished)               // unsigned long long clen   - length of ciphertext
   2683     + AEAD_TAG_BYTES,
   2684     NULL,                                  // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2685     0,                                     // unsigned long long adlen
   2686     enc_nonce,     // const unsigned char *npub - nonce
   2687     enc_key     // const unsigned char *k    - key
   2688     );
   2689   if (0 != ret)
   2690   {
   2691     GNUNET_log (DECRYPTION_FAILURES_LOG_LEVEL,
   2692                 "Something went wrong decrypting: %d\n", ret);
   2693     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2694     return;
   2695   }
   2696 
   2697   //      - verify finished_I
   2698   /* Generate finished_I
   2699    * after Forwarding until {finished_R}RHTS
   2700    *   (did so while we prepared responder hello)
   2701    * before forwarding to [{payload}RATS and] {finished_I}IHTS */
   2702   // (look at the end of handle_initiator_hello())
   2703   snapshot_transcript (kx->transcript_hash_ctx, &transcript);
   2704   generate_initiator_finished (&transcript,
   2705                                &kx->master_secret,
   2706                                &initiator_finished);
   2707   if (0 != memcmp (&idm_p->finished,
   2708                    &initiator_finished,
   2709                    sizeof (struct GNUNET_HashCode)))
   2710   {
   2711     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2712                 "Could not verify \"initiator finished\" hash.\n");
   2713     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2714                 "Want: `%s'\n",
   2715                 GNUNET_h2s (&initiator_finished));
   2716     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2717                 "Have: `%s'\n",
   2718                 GNUNET_h2s (&idm_p->finished));
   2719     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2720                 "Transcript `%s'\n",
   2721                 GNUNET_h2s (&transcript));
   2722     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2723     return;
   2724   }
   2725 
   2726   /* Forward the transcript hash_context_read */
   2727   hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx);
   2728   GNUNET_CRYPTO_hash_context_read (hc,
   2729                                    &idm_e->finished,
   2730                                    sizeof (idm_e->finished)
   2731                                    + AEAD_TAG_BYTES);
   2732   snapshot_transcript (hc, &transcript);
   2733   derive_initial_ats (&transcript,
   2734                       &kx->master_secret,
   2735                       ROLE_INITIATOR,
   2736                       &their_ats);
   2737   derive_per_message_secrets (&their_ats, // FIXME other HS epoch?
   2738                               0,
   2739                               enc_key,
   2740                               enc_nonce);
   2741   ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
   2742     (unsigned char*) &ack_i,     // unsigned char *m
   2743     NULL,                                  // mlen_p message length
   2744     NULL,                                  // unsigned char *nsec       - unused: NULL
   2745     (unsigned char*) &idm_e[1],     // const unsigned char *c    - ciphertext
   2746     sizeof (ack_i) + AEAD_TAG_BYTES,                                 // unsigned long long clen   - length of ciphertext
   2747     NULL,                                  // const unsigned char *ad   - additional data (optional) TODO those should be used, right?
   2748     0,                                     // unsigned long long adlen
   2749     enc_nonce,     // const unsigned char *npub - nonce
   2750     enc_key     // const unsigned char *k    - key
   2751     );
   2752   if (0 != ret)
   2753   {
   2754     GNUNET_log (DECRYPTION_FAILURES_LOG_LEVEL,
   2755                 "Something went wrong decrypting the Ack: %d\n", ret);
   2756     GNUNET_CRYPTO_hash_context_abort (hc);
   2757     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2758     return;
   2759   }
   2760   if ((sizeof ack_i != ntohs (ack_i.header.size)) ||
   2761       (GNUNET_MESSAGE_TYPE_CORE_ACK != ntohs (ack_i.header.type)))
   2762   {
   2763     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2764                 "Ack invalid!\n");
   2765     GNUNET_CRYPTO_hash_context_abort (hc);
   2766     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2767     return;
   2768   }
   2769   GNUNET_memcpy (&kx->their_ats[0],
   2770                  &their_ats,
   2771                  sizeof their_ats);
   2772   /**
   2773    * FIXME we do not really have to calculate all this now
   2774    */
   2775   for (int i = 0; i < MAX_EPOCHS - 1; i++)
   2776   {
   2777     derive_next_ats (&kx->their_ats[i],
   2778                      &kx->their_ats[i + 1]);
   2779   }
   2780   GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   2781   kx->transcript_hash_ctx = hc;
   2782   kx->status = GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED;
   2783   kx->current_epoch_expiration =
   2784     GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2785   cleanup_handshake_secrets (kx);
   2786   monitor_notify_all (kx);
   2787   /* @e finished_I has verified.  RFC 9147, Section 5.11: the peer has now
   2788      "demonstrated reachability [...] by completing a complete handshake
   2789      including delivering a verifiable Finished message", so this is the
   2790      point -- and the only point -- at which the old association may be
   2791      destroyed.  #handle_initiator_hello() deliberately left it running.
   2792      GSC_SESSIONS_create() puts into @e sessions with
   2793      #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY under a
   2794      GNUNET_assert(), so a leftover session is not merely untidy. */
   2795   GSC_SESSIONS_end (&kx->peer);
   2796   if (NULL != kx->heartbeat_task)
   2797   {
   2798     GNUNET_SCHEDULER_cancel (kx->heartbeat_task);
   2799     kx->heartbeat_task = NULL;
   2800   }
   2801   /* #send_initiator_done() starts the initiator at epoch 0 and we have to
   2802      agree: on a kx that had an association before, these still hold the
   2803      predecessor's values, and none of them was ever reset here. */
   2804   kx->current_epoch = 0;
   2805   kx->their_max_epoch = 0;
   2806   kx->current_sqn = 1;
   2807   replay_reset_all (kx);
   2808   kx->association_up = GNUNET_YES;
   2809   GSC_SESSIONS_create (&kx->peer, kx, kx->class);
   2810   update_timeout (kx);
   2811   ack_r.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   2812   ack_r.header.size = htons (sizeof ack_r);
   2813   GSC_KX_encrypt_and_transmit (kx,
   2814                                &ack_r,
   2815                                sizeof ack_r);
   2816 
   2817   GNUNET_TRANSPORT_core_receive_continue (transport,
   2818                                           &kx->peer);
   2819 }
   2820 
   2821 
   2822 /**
   2823  * Check an incoming encrypted message before handling it
   2824  * @param cls key exchange info
   2825  * @param m the encrypted message
   2826  */
   2827 static int
   2828 check_encrypted_message (void *cls, const struct EncryptedMessage *m)
   2829 {
   2830   uint16_t size = ntohs (m->header.size) - sizeof(*m);
   2831 
   2832   // TODO check (see check_encrypted ())
   2833   //       - check epoch
   2834   //       - check sequence number
   2835   if (size < sizeof(struct GNUNET_MessageHeader))
   2836   {
   2837     GNUNET_break_op (0);
   2838     return GNUNET_SYSERR;
   2839   }
   2840   return GNUNET_OK;
   2841 }
   2842 
   2843 
   2844 /**
   2845  * Handle a key update
   2846  * @param cls key exchange info
   2847  * @param m KeyUpdate message
   2848  */
   2849 static void
   2850 handle_heartbeat (struct GSC_KeyExchangeInfo *kx,
   2851                   const struct Heartbeat *m)
   2852 {
   2853   struct GNUNET_ShortHashCode new_ats;
   2854   struct ConfirmationAck ack;
   2855 
   2856   if (m->flags & GSC_HEARTBEAT_KEY_UPDATE_REQUESTED)
   2857   {
   2858     if (kx->current_epoch == UINT64_MAX)
   2859     {
   2860       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2861                   "Max epoch reached (you probably will never see this)\n");
   2862     }
   2863     else
   2864     {
   2865       kx->current_epoch++;
   2866       kx->current_epoch_expiration =
   2867         GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2868       kx->current_sqn = 0;
   2869       derive_next_ats (&kx->current_ats,
   2870                        &new_ats);
   2871       memcpy (&kx->current_ats,
   2872               &new_ats,
   2873               sizeof new_ats);
   2874     }
   2875   }
   2876   update_timeout (kx);
   2877   ack.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK);
   2878   ack.header.size = htons (sizeof ack);
   2879   GSC_KX_encrypt_and_transmit (kx,
   2880                                &ack,
   2881                                sizeof ack);
   2882   /* NOTE: no GNUNET_TRANSPORT_core_receive_continue() here.  We are called
   2883      from #handle_encrypted_message(), which owns the message and issues
   2884      exactly one call for it. */
   2885 }
   2886 
   2887 
   2888 static enum GNUNET_GenericReturnValue
   2889 check_if_ack_or_heartbeat (struct GSC_KeyExchangeInfo *kx,
   2890                            const char *buf,
   2891                            size_t buf_len)
   2892 {
   2893   struct GNUNET_MessageHeader *msg;
   2894   struct ConfirmationAck *ack;
   2895   struct Heartbeat *hb;
   2896 
   2897   if (sizeof *msg > buf_len)
   2898     return GNUNET_NO;
   2899   msg = (struct GNUNET_MessageHeader*) buf;
   2900   if (GNUNET_MESSAGE_TYPE_CORE_ACK == ntohs (msg->type))
   2901   {
   2902     ack = (struct ConfirmationAck *) buf;
   2903     if (sizeof *ack != ntohs (ack->header.size))
   2904       return GNUNET_NO;
   2905   }
   2906   else if  (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT == ntohs (msg->type))
   2907   {
   2908     hb = (struct Heartbeat*) buf;
   2909     if (sizeof *hb != ntohs (hb->header.size))
   2910       return GNUNET_NO;
   2911     handle_heartbeat (kx, hb);
   2912   }
   2913   else
   2914   {
   2915     return GNUNET_NO;
   2916   }
   2917 
   2918   /**
   2919    * Waiting for ACK or heartbeat
   2920    */
   2921   if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT)
   2922   {
   2923     GSC_SESSIONS_create (&kx->peer, kx, kx->class);
   2924     kx->status = GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED;
   2925     kx->current_epoch_expiration =
   2926       GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   2927     cleanup_handshake_secrets (kx);
   2928     if (NULL != kx->resend_task)
   2929       GNUNET_SCHEDULER_cancel (kx->resend_task);
   2930     kx->resend_task = NULL;
   2931     if (NULL != kx->resend_env)
   2932       GNUNET_MQ_discard (kx->resend_env);
   2933     kx->resend_env = NULL;
   2934     monitor_notify_all (kx);
   2935   }
   2936   update_timeout (kx);
   2937 
   2938   return GNUNET_YES;
   2939 }
   2940 
   2941 
   2942 /**
   2943  * handle an encrypted message
   2944  * @param cls key exchange info
   2945  * @param m encrypted message
   2946  */
   2947 static void
   2948 handle_encrypted_message (void *cls, const struct EncryptedMessage *m)
   2949 {
   2950   struct GSC_KeyExchangeInfo *kx = cls;
   2951   uint16_t size = ntohs (m->header.size);
   2952   char buf[size - sizeof (*m)] GNUNET_ALIGN;
   2953   unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
   2954   const unsigned char *seq_enc_nonce;
   2955   unsigned char enc_key[AEAD_KEY_BYTES];
   2956   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   2957   struct GNUNET_ShortHashCode new_ats[MAX_EPOCHS];
   2958   uint32_t seq_enc_ctr;
   2959   uint64_t epoch;
   2960   uint64_t m_seq;
   2961   uint64_t m_seq_nbo;
   2962   uint64_t c_len;
   2963   int8_t ret;
   2964 
   2965   // TODO look at handle_encrypted
   2966   //       - statistics
   2967 
   2968   /* The record layer answers to @e association_up, not to @e status: a
   2969      handshake may be in flight over an association that is still live
   2970      (RFC 9147, Section 5.11), and records of the old epoch have to keep
   2971      being deprotected while it is.  Conversely a record we have no keys
   2972      for is simply an invalid record -- RFC 9147, Section 4.5.2: "In
   2973      general, invalid records SHOULD be silently discarded, thus preserving
   2974      the association" -- so it must not end a session or restart anything.
   2975      If we are idle it does tell us the peer believes in an association we
   2976      do not have, which is worth one exchange. */
   2977   if (GNUNET_YES != kx->association_up)
   2978   {
   2979     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   2980                 "Discarding record from `%s': no keys for epoch %" PRIu64 "\n",
   2981                 GNUNET_i2s (&kx->peer),
   2982                 GNUNET_ntohll (m->epoch));
   2983     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   2984     if (GNUNET_CORE_KX_STATE_DOWN == kx->status)
   2985       restart_kx (kx);
   2986     return;
   2987   }
   2988   epoch = GNUNET_ntohll (m->epoch);
   2989   /**
   2990    * Derive temporarily as we want to discard on
   2991    * decryption failure(s)
   2992    */
   2993   memcpy (new_ats,
   2994           kx->their_ats,
   2995           MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
   2996   // FIXME here we could introduce logic that sends heartbeats
   2997   // with key update request if we have not seen a new
   2998   // epoch after a while (e.g. EPOCH_EXPIRATION)
   2999   if (kx->their_max_epoch < epoch)
   3000   {
   3001     /**
   3002      * Prevent DoS
   3003      * FIXME maybe requires its own limit.
   3004      */
   3005     if ((epoch - kx->their_max_epoch) > 2 * MAX_EPOCHS)
   3006     {
   3007       /* @e epoch is plaintext and not covered by the AEAD tag, so this is
   3008          reached by a single flipped bit as readily as by a peer that really
   3009          did skip ahead.  Drop the message like the "too old" case below
   3010          does; tearing the session down here means one unauthenticated
   3011          header field costs a full re-handshake. */
   3012       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3013                   "Epoch %" PRIu64 " is too new, will not decrypt...\n",
   3014                   epoch);
   3015       GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   3016       return;
   3017     }
   3018     for (uint64_t i = kx->their_max_epoch; i < epoch; i++)
   3019     {
   3020       derive_next_ats (&new_ats[i % MAX_EPOCHS],
   3021                        &new_ats[(i + 1) % MAX_EPOCHS]);
   3022       /* This slot of the ring now holds a different key, so the window
   3023          that went with the old one no longer means anything. */
   3024       replay_reset (kx, i + 1);
   3025     }
   3026   }
   3027   else if ((kx->their_max_epoch - epoch) > MAX_EPOCHS)
   3028   {
   3029     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3030                 "Epoch %" PRIu64 " is too old, cannot decrypt...\n",
   3031                 epoch);
   3032     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   3033     return;
   3034   }
   3035   derive_sn (
   3036     &new_ats[epoch % MAX_EPOCHS],
   3037     seq_enc_k,
   3038     sizeof seq_enc_k);
   3039   /* compute the sequence number */
   3040   seq_enc_ctr = *((uint32_t*) m->tag);
   3041   seq_enc_nonce = &m->tag[sizeof (uint32_t)];
   3042 #if DEBUG_KX
   3043   GNUNET_print_bytes (&new_ats[epoch % MAX_EPOCHS],
   3044                       sizeof (struct GNUNET_ShortHashCode),
   3045                       8,
   3046                       GNUNET_NO);
   3047   GNUNET_print_bytes (seq_enc_k,
   3048                       sizeof seq_enc_k,
   3049                       8,
   3050                       GNUNET_NO);
   3051   GNUNET_print_bytes ((char*) &seq_enc_ctr,
   3052                       sizeof seq_enc_ctr,
   3053                       8,
   3054                       GNUNET_NO);
   3055 #endif
   3056   crypto_stream_chacha20_ietf_xor_ic (
   3057     (unsigned char*) &m_seq_nbo,
   3058     (unsigned char*) &m->sequence_number,
   3059     sizeof (uint64_t),
   3060     seq_enc_nonce,
   3061     ntohl (seq_enc_ctr),
   3062     seq_enc_k);
   3063   m_seq = GNUNET_ntohll (m_seq_nbo);
   3064   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   3065               "Received encrypted message in epoch %" PRIu64
   3066               " with E(SQN=%" PRIu64 ")=%" PRIu64
   3067               "\n",
   3068               epoch,
   3069               m_seq,
   3070               m->sequence_number);
   3071   /* RFC 9147, Section 4.5.1.  Cheap enough to do before deprotection, and
   3072      doing it first means a flood of replayed records costs no AEAD work.
   3073      The window itself is only moved once the record verifies, below. */
   3074   if (GNUNET_OK != replay_check (kx, epoch, m_seq))
   3075   {
   3076     GNUNET_STATISTICS_update (GSC_stats,
   3077                               gettext_noop ("# replayed records discarded"),
   3078                               1,
   3079                               GNUNET_NO);
   3080     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   3081                 "Discarding replayed record %" PRIu64 "/%" PRIu64
   3082                 " from `%s'\n",
   3083                 epoch,
   3084                 m_seq,
   3085                 GNUNET_i2s (&kx->peer));
   3086     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   3087     return;
   3088   }
   3089   /* We are the initiator and as we are going to receive,
   3090    * we are using the responder key material */
   3091   derive_per_message_secrets (&new_ats[epoch % MAX_EPOCHS],
   3092                               m_seq,
   3093                               enc_key,
   3094                               enc_nonce);
   3095   // TODO checking sequence numbers - handle the case of out-of-sync messages!
   3096   // for now only decrypt the payload
   3097   // TODO encrypt other fields, too!
   3098   // TODO
   3099   // c_len = size - offsetof ();
   3100   c_len = size - sizeof (struct EncryptedMessage);
   3101   ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
   3102     (unsigned char*) buf,   // m - plain message
   3103     NULL,                                   // nsec - unused
   3104     (unsigned char*) &m[1],                 // c - ciphertext
   3105     c_len,                                  // clen
   3106     (const unsigned char*) &m->tag,         // mac
   3107     NULL,                                   // ad - additional data TODO
   3108     0,                                      // adlen
   3109     enc_nonce,           // npub
   3110     enc_key          // k
   3111     );
   3112   if (0 != ret)
   3113   {
   3114     /* RFC 9147, Section 4.5.2: "invalid records SHOULD be silently
   3115        discarded, thus preserving the association; however, an error MAY be
   3116        logged for diagnostic purposes."  Not a protocol violation on the
   3117        peer's part either -- anything at all can arrive here -- so no
   3118        GNUNET_break_op(). */
   3119     GNUNET_STATISTICS_update (GSC_stats,
   3120                               gettext_noop ("# invalid records discarded"),
   3121                               1,
   3122                               GNUNET_NO);
   3123     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3124                 "Discarding record %" PRIu64 "/%" PRIu64 " from `%s':"
   3125                 " does not deprotect\n",
   3126                 epoch,
   3127                 m_seq,
   3128                 GNUNET_i2s (&kx->peer));
   3129     GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   3130     return;
   3131   }
   3132   /* Deprotected, so the record is authentic and everything derived from it
   3133      may now be committed: the epoch ring, the anti-replay window (RFC 9147,
   3134      Section 4.5.1: "The window MUST NOT be updated due to a received record
   3135      until that record has been deprotected successfully") and @e timeout.
   3136      @e timeout is the only liveness signal CORE has and is what
   3137      `gnunet-core -m' reports, so refreshing it any earlier would let
   3138      anything merely shaped like a record keep a session nominally alive. */
   3139   /* Only ever forward: @e their_max_epoch is the *highest* epoch we have
   3140      seen, and the ratchet above keys off it.  A record that was merely
   3141      reordered across an epoch boundary -- entirely normal, the peer starts
   3142      the new epoch at sequence number 0 while the old one is still in flight
   3143      -- used to pull it back, so the next record of the newer epoch looked
   3144      like a fresh advance and ran the loop again, wiping that epoch's
   3145      anti-replay window (RFC 9147, Section 4.5.1) every single time. */
   3146   if (kx->their_max_epoch < epoch)
   3147     kx->their_max_epoch = epoch;
   3148   memcpy (&kx->their_ats,
   3149           new_ats,
   3150           MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
   3151   replay_commit (kx, epoch, m_seq);
   3152   update_timeout (kx);
   3153 
   3154   if (GNUNET_NO == check_if_ack_or_heartbeat (kx,
   3155                                               buf,
   3156                                               sizeof buf))
   3157   {
   3158     if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT)
   3159     {
   3160       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3161                   "Dropping message as we are still waiting for handshake ACK\n");
   3162       GNUNET_break_op (0);
   3163       GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   3164       return;
   3165     }
   3166     if (GNUNET_OK !=
   3167         GNUNET_MST_from_buffer (kx->mst,
   3168                                 buf,
   3169                                 sizeof buf,
   3170                                 GNUNET_YES,
   3171                                 GNUNET_NO))
   3172       GNUNET_break_op (0);
   3173   }
   3174   GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
   3175 }
   3176 
   3177 
   3178 /**
   3179  * Function called by transport telling us that a peer
   3180  * disconnected.
   3181  * Stop key exchange with the given peer.  Clean up key material.
   3182  *
   3183  * @param cls closure
   3184  * @param peer the peer that disconnected
   3185  * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
   3186  */
   3187 static void
   3188 handle_transport_notify_disconnect (void *cls,
   3189                                     const struct GNUNET_PeerIdentity *peer,
   3190                                     void *handler_cls)
   3191 {
   3192   struct GSC_KeyExchangeInfo *kx = handler_cls;
   3193   (void) cls;
   3194 
   3195   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   3196               "Peer `%s' disconnected from us.\n",
   3197               GNUNET_i2s (&kx->peer));
   3198   GSC_SESSIONS_end (&kx->peer);
   3199   GNUNET_STATISTICS_update (GSC_stats,
   3200                             gettext_noop ("# key exchanges stopped"),
   3201                             1,
   3202                             GNUNET_NO);
   3203   if (NULL != kx->resend_task)
   3204   {
   3205     GNUNET_SCHEDULER_cancel (kx->resend_task);
   3206     kx->resend_task = NULL;
   3207   }
   3208   if (NULL != kx->resend_env)
   3209   {
   3210     GNUNET_MQ_discard (kx->resend_env);
   3211     kx->resend_env = NULL;
   3212   }
   3213   if (NULL != kx->heartbeat_task)
   3214   {
   3215     GNUNET_SCHEDULER_cancel (kx->heartbeat_task);
   3216     kx->heartbeat_task = NULL;
   3217   }
   3218   kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
   3219   monitor_notify_all (kx);
   3220   if (kx->transcript_hash_ctx)
   3221   {
   3222     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   3223     kx->transcript_hash_ctx = NULL;
   3224   }
   3225   GNUNET_CONTAINER_DLL_remove (kx_head, kx_tail, kx);
   3226   GNUNET_MST_destroy (kx->mst);
   3227   GNUNET_free (kx);
   3228 }
   3229 
   3230 
   3231 static void
   3232 resend_initiator_hello (void *cls)
   3233 {
   3234   struct GSC_KeyExchangeInfo *kx = cls;
   3235 
   3236   kx->resend_task = NULL;
   3237   if (0 == kx->resend_tries_left)
   3238   {
   3239     /* The InitiatorHello we keep repeating carries the ephemeral public key
   3240        generated by #send_initiator_hello(), and only #restart_kx() ever
   3241        generates a new one.  Retrying the same message forever therefore
   3242        never recovers from a responder that has dropped the exchange -- it
   3243        just keeps a retransmit timer running against a peer that is not
   3244        answering.  Give up like #resend_responder_hello() and
   3245        #resend_initiator_done() do and start a fresh exchange. */
   3246     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3247                 "InitiatorHello not answered by `%s', restarting KX\n",
   3248                 GNUNET_i2s (&kx->peer));
   3249     restart_kx (kx);
   3250     return;
   3251   }
   3252   kx->resend_tries_left--;
   3253   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3254               "Resending InitiatorHello. Retries left: %u\n",
   3255               kx->resend_tries_left);
   3256   GNUNET_MQ_send_copy (kx->mq, kx->resend_env);
   3257   schedule_resend (kx, &resend_initiator_hello);
   3258 }
   3259 
   3260 
   3261 /**
   3262  * Send initiator hello
   3263  *
   3264  * @param kx key exchange context
   3265  */
   3266 static void
   3267 send_initiator_hello (struct GSC_KeyExchangeInfo *kx)
   3268 {
   3269   const struct GNUNET_PeerIdentity *my_identity;
   3270   struct GNUNET_MQ_Envelope *env;
   3271   struct GNUNET_ShortHashCode es;
   3272   struct GNUNET_ShortHashCode ets;
   3273   struct GNUNET_ShortHashCode ss_R;
   3274   struct InitiatorHelloPayload *ihmp; /* initiator hello message - buffer on stack */
   3275   struct InitiatorHello *ihm_e; /* initiator hello message - encrypted */
   3276   long long unsigned int c_len;
   3277   unsigned char enc_key[AEAD_KEY_BYTES];
   3278   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   3279   enum GNUNET_GenericReturnValue ret;
   3280   size_t pt_len;
   3281 
   3282   my_identity = GNUNET_PILS_get_identity (GSC_pils);
   3283   GNUNET_assert (NULL != my_identity);
   3284 
   3285   pt_len = sizeof (*ihmp) + strlen (my_services_info);
   3286   c_len = pt_len + AEAD_TAG_BYTES;
   3287   env = GNUNET_MQ_msg_extra (ihm_e,
   3288                              c_len,
   3289                              GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO);
   3290   ihmp = (struct InitiatorHelloPayload*) &ihm_e[1];
   3291   ihmp->peer_class = htons (GNUNET_CORE_CLASS_UNKNOWN); // TODO set this to a meaningful
   3292   GNUNET_memcpy (&ihmp->pk_I,
   3293                  my_identity,
   3294                  sizeof (struct GNUNET_PeerIdentity));
   3295   GNUNET_CRYPTO_hash (&kx->peer, /* what to hash */ // TODO do we do this twice?
   3296                       sizeof (struct GNUNET_PeerIdentity),
   3297                       &ihm_e->h_pk_R); /* result */
   3298   // TODO init hashcontext/transcript_hash
   3299   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send InitiatorHello: %d %d\n", kx->role,
   3300               kx->status);
   3301   GNUNET_assert (NULL == kx->transcript_hash_ctx);
   3302   kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start ();
   3303   GNUNET_assert (NULL != kx->transcript_hash_ctx);
   3304   // TODO fill services_info
   3305 
   3306   // 1. Encaps
   3307   ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public ephemeral key of initiator
   3308                                         &ihm_e->c_R,    // encapsulated key
   3309                                         &ss_R); // key - ss_R
   3310   if (GNUNET_OK != ret)
   3311   {
   3312     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3313                 "Something went wrong encapsulating ss_R\n");
   3314     // TODO handle
   3315   }
   3316   // 2. generate rR (uint64_t) - is this the nonce? Naming seems not quite
   3317   //    consistent
   3318   ihm_e->r_I =
   3319     GNUNET_CRYPTO_random_u64 (UINT64_MAX);
   3320   // 3. generate sk_e/pk_e - ephemeral key
   3321   GNUNET_CRYPTO_ecdhe_key_create (&kx->sk_e.ecdhe_key);
   3322   GNUNET_CRYPTO_ecdhe_key_get_public (
   3323     &kx->sk_e.ecdhe_key,
   3324     &kx->pk_e.ecdhe_key);
   3325   GNUNET_memcpy (&ihm_e->pk_e,
   3326                  &kx->pk_e.ecdhe_key,
   3327                  sizeof (kx->pk_e.ecdhe_key));
   3328   // 4. generate ETS to encrypt
   3329   //         generate ETS (early_traffic_secret_key, decrypt pk_i
   3330   //         expand ETS <- expand ES <- extract ss_R
   3331   //         use ETS to decrypt
   3332   GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx,
   3333                                    ihm_e,
   3334                                    sizeof (struct InitiatorHello));
   3335   {
   3336     struct GNUNET_HashCode transcript;
   3337     snapshot_transcript (kx->transcript_hash_ctx,
   3338                          &transcript);
   3339     derive_es_ets (&transcript,
   3340                    &ss_R,
   3341                    &es,
   3342                    &ets);
   3343     derive_per_message_secrets (&ets,
   3344                                 0,
   3345                                 enc_key,
   3346                                 enc_nonce);
   3347   }
   3348   // 5. encrypt
   3349 
   3350   ret = crypto_aead_xchacha20poly1305_ietf_encrypt (
   3351     (unsigned char*) &ihm_e[1],   /* c - ciphertext */
   3352     // mac,
   3353     // NULL, // maclen_p
   3354     &c_len,   /* clen_p */
   3355     (unsigned char*) ihmp,   /* m - plaintext message */
   3356     pt_len,   // mlen
   3357     NULL, 0,   // ad, adlen // FIXME maybe over the unencrypted header?
   3358                // fields?
   3359     NULL,   // nsec - unused
   3360     enc_nonce,   // npub - nonce
   3361     enc_key);   // k - key
   3362   if (0 != ret)
   3363   {
   3364     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong encrypting\n");
   3365     GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx);
   3366     kx->transcript_hash_ctx = NULL;
   3367     GNUNET_MQ_discard (env);
   3368     return;
   3369   }
   3370   /* Forward the transcript */
   3371   GNUNET_CRYPTO_hash_context_read (
   3372     kx->transcript_hash_ctx,
   3373     &ihm_e[1],
   3374     c_len);
   3375 
   3376   kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_SENT;
   3377   kx->early_secret_key = es;
   3378   kx->early_traffic_secret = ets;
   3379   kx->ss_R = ss_R;
   3380   monitor_notify_all (kx);
   3381   GNUNET_MQ_send_copy (kx->mq, env);
   3382   kx->resend_env = env;
   3383   start_resend (kx, &resend_initiator_hello);
   3384 }
   3385 
   3386 
   3387 /**
   3388  * Move to the next epoch if the current one is exhausted.
   3389  *
   3390  * @param kx key exchange to check
   3391  * @return #GNUNET_OK if @a kx may be used to send, #GNUNET_SYSERR if the
   3392  *         association had to be torn down instead
   3393  */
   3394 static enum GNUNET_GenericReturnValue
   3395 check_rekey (struct GSC_KeyExchangeInfo *kx)
   3396 {
   3397   struct GNUNET_ShortHashCode new_ats;
   3398 
   3399   if ((UINT64_MAX == kx->current_sqn) ||
   3400       (GNUNET_TIME_absolute_is_past (kx->current_epoch_expiration)))
   3401   {
   3402     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   3403                 "Epoch expiration %" PRIu64 " SQN %" PRIu64
   3404                 ", incrementing epoch...\n",
   3405                 kx->current_epoch_expiration.abs_value_us,
   3406                 kx->current_sqn);
   3407     if (UINT64_MAX == kx->current_epoch)
   3408     {
   3409       /* RFC 9147, Section 6.1: "Implementations MUST NOT allow the epoch to
   3410          wrap, but instead MUST establish a new association, terminating the
   3411          old association".  This used to be a GNUNET_assert(). */
   3412       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3413                   "Epoch exhausted for `%s', starting a new association\n",
   3414                   GNUNET_i2s (&kx->peer));
   3415       restart_kx (kx);
   3416       return GNUNET_SYSERR;
   3417     }
   3418     kx->current_epoch++;
   3419     kx->current_epoch_expiration =
   3420       GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION);
   3421     kx->current_sqn = 0;
   3422     derive_next_ats (&kx->current_ats,
   3423                      &new_ats);
   3424     memcpy (&kx->current_ats,
   3425             &new_ats,
   3426             sizeof new_ats);
   3427   }
   3428   return GNUNET_OK;
   3429 }
   3430 
   3431 
   3432 /**
   3433  * Encrypt and transmit payload
   3434  * @param kx key exchange info
   3435  * @param payload the payload
   3436  * @param payload_size size of the payload
   3437  */
   3438 void
   3439 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
   3440                              const void *payload,
   3441                              size_t payload_size)
   3442 {
   3443   struct GNUNET_MQ_Envelope *env;
   3444   struct EncryptedMessage *encrypted_msg;
   3445   unsigned char enc_key[AEAD_KEY_BYTES];
   3446   unsigned char enc_nonce[AEAD_NONCE_BYTES];
   3447   unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
   3448   uint64_t sqn;
   3449   uint64_t epoch;
   3450   int8_t ret;
   3451 
   3452   encrypted_msg = NULL;
   3453 
   3454   if (GNUNET_YES != kx->association_up)
   3455   {
   3456     /* No application traffic keys installed -- there is nothing to protect
   3457        this with.  Callers reach this through a session, which only exists
   3458        while the association does, so this is a should-not-happen. */
   3459     GNUNET_break (0);
   3460     return;
   3461   }
   3462   if (GNUNET_OK != check_rekey (kx))
   3463     return;     /* association was torn down, @e current_ats is gone */
   3464   sqn = kx->current_sqn;
   3465   epoch = kx->current_epoch;
   3466   /* We are the sender and as we are going to send,
   3467    * we are using the initiator key material */
   3468   derive_per_message_secrets (&kx->current_ats,
   3469                               sqn,
   3470                               enc_key,
   3471                               enc_nonce);
   3472   kx->current_sqn++;
   3473   derive_sn (&kx->current_ats,
   3474              seq_enc_k,
   3475              sizeof seq_enc_k);
   3476   env = GNUNET_MQ_msg_extra (encrypted_msg,
   3477                              payload_size,
   3478                              GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE);
   3479   // only encrypt the payload for now
   3480   // TODO encrypt other fields as well
   3481   ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
   3482     (unsigned char*) &encrypted_msg[1],     // c - resulting ciphertext
   3483     (unsigned char*) &encrypted_msg->tag,     // mac - resulting mac/tag
   3484     NULL,     // maclen
   3485     (unsigned char*) payload,     // m - plain message
   3486     payload_size,     // mlen
   3487     NULL,     // ad - additional data TODO also cover the unencrypted part (epoch)
   3488     0,     // adlen
   3489     NULL,     // nsec - unused
   3490     enc_nonce,     // npub nonce
   3491     enc_key     // k - key
   3492     );
   3493   if (0 != ret)
   3494   {
   3495     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3496                 "Something went wrong encrypting message\n");
   3497     GNUNET_assert (0);
   3498   }
   3499   {
   3500     /* compute the sequence number */
   3501     unsigned char *seq_enc_nonce;
   3502     uint64_t seq_nbo;
   3503     uint32_t seq_enc_ctr;
   3504 
   3505     seq_nbo = GNUNET_htonll (sqn);
   3506     seq_enc_ctr = *((uint32_t*) encrypted_msg->tag);
   3507     seq_enc_nonce = &encrypted_msg->tag[sizeof (uint32_t)];
   3508     crypto_stream_chacha20_ietf_xor_ic (
   3509       (unsigned char*) &encrypted_msg->sequence_number,
   3510       (unsigned char*) &seq_nbo,
   3511       sizeof seq_nbo,
   3512       seq_enc_nonce,
   3513       ntohl (seq_enc_ctr),
   3514       seq_enc_k);
   3515 #if DEBUG_KX
   3516     GNUNET_print_bytes (seq_enc_k,
   3517                         sizeof seq_enc_k,
   3518                         8,
   3519                         GNUNET_NO);
   3520     GNUNET_print_bytes ((char*) &seq_enc_ctr,
   3521                         sizeof seq_enc_ctr,
   3522                         8,
   3523                         GNUNET_NO);
   3524 #endif
   3525     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   3526                 "Sending encrypted message with E(SQN=%" PRIu64 ")=%" PRIu64
   3527                 "\n",
   3528                 sqn,
   3529                 encrypted_msg->sequence_number);
   3530   }
   3531   encrypted_msg->epoch = GNUNET_htonll (epoch);
   3532 
   3533   // TODO actually copy payload
   3534   GNUNET_MQ_send (kx->mq, env);
   3535 }
   3536 
   3537 
   3538 void
   3539 GSC_KX_start (void)
   3540 {
   3541   const struct GNUNET_PeerIdentity *my_identity;
   3542   struct GNUNET_MQ_MessageHandler handlers[] = {
   3543     GNUNET_MQ_hd_var_size (initiator_hello,
   3544                            GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO,
   3545                            struct InitiatorHello,
   3546                            NULL),
   3547     GNUNET_MQ_hd_var_size (initiator_done,
   3548                            GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE,
   3549                            struct InitiatorDone,
   3550                            NULL),
   3551     GNUNET_MQ_hd_var_size (responder_hello,
   3552                            GNUNET_MESSAGE_TYPE_CORE_RESPONDER_HELLO,
   3553                            struct ResponderHello,
   3554                            NULL),
   3555     GNUNET_MQ_hd_var_size   (encrypted_message, // TODO rename?
   3556                              GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE,  // TODO rename!
   3557                              struct EncryptedMessage,
   3558                              NULL),
   3559     GNUNET_MQ_handler_end ()
   3560   };
   3561 
   3562   my_identity = GNUNET_PILS_get_identity (GSC_pils);
   3563   GNUNET_assert (NULL != my_identity);
   3564 
   3565   /* Decapsulate with our peer identity's private key directly instead of
   3566      round-tripping through the PILS service.  The shared secret is needed
   3567      in the middle of processing a handshake message, and an asynchronous
   3568      answer meant that every InitiatorHello and ResponderHello had to be
   3569      parked with its kx across a callback: the kx could be torn down or
   3570      freed underneath it, two hellos could be in flight at once, and if
   3571      the answer never came (PILS restarting) the handshake stalled *and*
   3572      the message was never acknowledged to TRANSPORT. */
   3573   if (GNUNET_OK !=
   3574       GNUNET_PILS_enable_private_key (GSC_pils))
   3575   {
   3576     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3577                 _ ("Failed to load our private key, "
   3578                    "cannot run key exchange\n"));
   3579     GSC_KX_done ();
   3580     return;
   3581   }
   3582 
   3583   nc = GNUNET_notification_context_create (1);
   3584   transport =
   3585     GNUNET_TRANSPORT_core_connect (GSC_cfg,
   3586                                    my_identity,
   3587                                    handlers,
   3588                                    NULL, // cls - this connection-independant
   3589                                          // cls seems not to be needed.
   3590                                          // the connection-specific cls
   3591                                          // will be set as a return value
   3592                                          // of
   3593                                          // handle_transport_notify_connect
   3594                                    &handle_transport_notify_connect,
   3595                                    &handle_transport_notify_disconnect);
   3596   if (NULL == transport)
   3597   {
   3598     GSC_KX_done ();
   3599     return;
   3600   }
   3601 
   3602   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   3603               "Connected to TRANSPORT\n");
   3604 
   3605   GSC_complete_initialization_cb ();
   3606 }
   3607 
   3608 
   3609 void
   3610 pid_change_cb (void *cls,
   3611                const struct GNUNET_HELLO_Parser *parser,
   3612                const struct GNUNET_HashCode *hash)
   3613 {
   3614   if (NULL != transport)
   3615     return;
   3616 
   3617   GSC_KX_start ();
   3618 }
   3619 
   3620 
   3621 /**
   3622  * Initialize KX subsystem.
   3623  *
   3624  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
   3625  */
   3626 int
   3627 GSC_KX_init (void)
   3628 {
   3629   GSC_pils = GNUNET_PILS_connect (GSC_cfg,
   3630                                   &pid_change_cb,
   3631                                   NULL);
   3632   if (NULL == GSC_pils)
   3633   {
   3634     GSC_KX_done ();
   3635     return GNUNET_SYSERR;
   3636   }
   3637 
   3638   return GNUNET_OK;
   3639 }
   3640 
   3641 
   3642 /**
   3643  * Shutdown KX subsystem.
   3644  */
   3645 void
   3646 GSC_KX_done ()
   3647 {
   3648   if (NULL != GSC_pils)
   3649   {
   3650     GNUNET_PILS_disconnect (GSC_pils);
   3651     GSC_pils = NULL;
   3652   }
   3653   if (NULL != transport)
   3654   {
   3655     GNUNET_TRANSPORT_core_disconnect (transport);
   3656     transport = NULL;
   3657   }
   3658   if (NULL != rekey_task)
   3659   {
   3660     GNUNET_SCHEDULER_cancel (rekey_task);
   3661     rekey_task = NULL;
   3662   }
   3663   if (NULL != nc)
   3664   {
   3665     GNUNET_notification_context_destroy (nc);
   3666     nc = NULL;
   3667   }
   3668 }
   3669 
   3670 
   3671 /**
   3672  * Check how many messages are queued for the given neighbour.
   3673  *
   3674  * @param kxinfo data about neighbour to check
   3675  * @return number of items in the message queue
   3676  */
   3677 unsigned int
   3678 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
   3679 {
   3680   return GNUNET_MQ_get_length (kxinfo->mq);
   3681 }
   3682 
   3683 
   3684 int
   3685 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
   3686 {
   3687   return kxinfo->has_excess_bandwidth;
   3688 }
   3689 
   3690 
   3691 /**
   3692  * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.  For this
   3693  * request type, the client does not have to have transmitted an INIT
   3694  * request.  All current peers are returned, regardless of which
   3695  * message types they accept.
   3696  *
   3697  * @param mq message queue to add for monitoring
   3698  */
   3699 void
   3700 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
   3701 {
   3702   struct GNUNET_MQ_Envelope *env;
   3703   struct MonitorNotifyMessage *done_msg;
   3704   struct GSC_KeyExchangeInfo *kx;
   3705 
   3706   GNUNET_notification_context_add (nc, mq);
   3707   for (kx = kx_head; NULL != kx; kx = kx->next)
   3708   {
   3709     struct GNUNET_MQ_Envelope *env_notify;
   3710     struct MonitorNotifyMessage *msg;
   3711 
   3712     env_notify = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
   3713     msg->state = htonl ((uint32_t) kx->status);
   3714     msg->peer = kx->peer;
   3715     msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
   3716     GNUNET_MQ_send (mq, env_notify);
   3717   }
   3718   env = GNUNET_MQ_msg (done_msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
   3719   done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
   3720   done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
   3721   GNUNET_MQ_send (mq, env);
   3722 }
   3723 
   3724 
   3725 /* end of gnunet-service-core_kx.c */