/ src / tp-dkg.h
tp-dkg.h
  1  #ifndef tp_dkg_h
  2  #define tp_dkg_h
  3  /**
  4   * @file tp-dkg.h
  5   * @brief API for the Trusted Party Distributed Key Generation (TP-DKG)
  6   *        Protocol
  7  
  8   * SPDX-FileCopyrightText: 2024-25, Marsiske Stefan
  9   * SPDX-License-Identifier: LGPL-3.0-or-later
 10   *
 11   * This file implements a Distributed Key Generation (DKG) protocol.
 12   * There are two roles: the trusted party (TP) and peers.
 13   *
 14   * The trusted party connects to all the peers and orchestrates the
 15   * protocol, which communicate only via the TP with each other . This
 16   * way, the TP acts as a broadcast medium which is an essential part of
 17   * all DKG protocols.
 18   *
 19   * In this protocol, the trusted party is - as the name implies -
 20   * trusted, but does not learn the result of the DKG. If the trusted party
 21   * is so trusted that it can learn the result of the DKG, then it is much
 22   * simpler to just randomly generate a secret and then share it using
 23   * Shamir's secret sharing.
 24   *
 25   * The peers only identify themselves towards the TP using long-term
 26   * keys, but use ephemeral keys when communicating with each other. This
 27   * makes the peers unaware of the identities of each other. However, the
 28   * peers might be using the ephemeral public keys, or any of the generated
 29   * random values to use as a side-channel to leak their identity to the
 30   * other peers.
 31   *
 32   * The protocol consists of over 20 internal steps, but the API hides this
 33   * complexity behind a state-driven loop, which any user can call iteratively
 34   * while implementing the networking communication themselves. This simplifies
 35   * the network model and enables usage across different communication channels
 36   * like TCP/IP, Bluetooth, USB, UART, etc.
 37   * The STP must support all communication channels that its peers require,
 38   * while each peer only needs to support its chosen medium.
 39   *
 40   * ## Common Protocol Flow
 41   *
 42   * Both the peers and the TP share a similar API schema:
 43   *
 44   * - For peers:
 45   *   ```
 46   *   msg0 = read(); // from the TP
 47   *   start_peer(state, ...);
 48   *   peer_set_bufs();
 49   *   while (peer_not_done(state)) {
 50   *       input = allocate_memory( dkg_peer_input_size(state) )
 51   *       output = allocate_memory( dkg_peer_output_size(state) )
 52   *       input = read()
 53   *       res = peer_next_step(state, input, output)
 54   *       if res!=0: fail&abort
 55   *       msg = output
 56   *       send(msg)
 57   *   }
 58   *   store share
 59   *   peer_free(state);
 60   *   ```
 61   *
 62   * - For the TP:
 63   *   ```
 64   *   start_tp(state, ...);
 65   *   set_bufs(...);
 66   *   send(msg0); // to all peers
 67   *   while (!tp_done(state)) {
 68   *       input = allocate_memory( dkg_tp_input_size(state) )
 69   *       output = allocate_memory( dkg_tp_output_size(state) )
 70   *       input = read()
 71   *       res = tp_next_step(state, input, output)
 72   *       if res!=0: fail&abort
 73   *       dkg_tp_peer_msg(state, output, peer_index, msg)
 74   *       msg = output
 75   *       send(msg)
 76   *   }
 77   *   ```
 78   */
 79  
 80  #include <stdint.h>
 81  #include <sodium.h>
 82  #include "XK.h"
 83  #include "dkg.h"
 84  
 85  typedef DKG_Cheater TP_DKG_Cheater;
 86  
 87  #define tpdkg_msg0_SIZE ( sizeof(DKG_Message)                                            \
 88                          + crypto_generichash_BYTES/*dst*/                                \
 89                          + 2 /*n,t*/                                                      \
 90                          + crypto_sign_PUBLICKEYBYTES /* tp_sign_pk */                    )
 91  #define tpdkg_msg8_SIZE (sizeof(DKG_Message) /* header */                                \
 92                           + noise_xk_handshake3_SIZE /* 4th&final noise handshake */      \
 93                           + sizeof(TOPRF_Share) /* msg: the noise_xk wrapped share */     \
 94                           + crypto_secretbox_xchacha20poly1305_MACBYTES /* mac of msg */  \
 95                           + crypto_auth_hmacsha256_BYTES /* key-committing mac over msg*/ )
 96  
 97  /**
 98   * @struct TP_DKG_PeerState
 99   * @brief State of a peer during the execution the TP DKG protocol
100   *
101   * Some fields in this struct are internal variables and should not
102   * be used. The following fields are useful and can be accessed by
103   * users of the API:
104   *
105   * @var TP_DKG_PeerState::n Total number of peers participating in
106   *      this protocol
107   * @var TP_DKG_PeerState::t The threshold, the minimum number of
108   *      peers required to use the shared secret generated by this DKG
109   * @var TP_DKG_PeerState::index Index of this peer (1-based). This value
110   *      is between 1 to `n` inclusive
111   * @var TP_DKG_PeerState::share Resulting secret share output of the DKG for
112   *      a peer. This value should probably be persisted for later usage
113   *
114   */
115  typedef struct {
116     int step;
117     int prev;
118     uint8_t sessionid[dkg_sessionid_SIZE];
119     uint8_t n;
120     uint8_t t;
121     uint8_t index;
122     uint8_t lt_sk[crypto_sign_SECRETKEYBYTES];
123     uint8_t sig_pk[crypto_sign_PUBLICKEYBYTES];
124     uint8_t sig_sk[crypto_sign_SECRETKEYBYTES];
125     uint8_t noise_pk[crypto_scalarmult_BYTES];
126     uint8_t noise_sk[crypto_scalarmult_SCALARBYTES];
127     uint8_t tp_sig_pk[crypto_sign_PUBLICKEYBYTES];
128     uint64_t tp_last_ts;
129     uint64_t *last_ts;
130     uint64_t ts_epsilon;
131     uint8_t (*peer_sig_pks)[][crypto_sign_PUBLICKEYBYTES];
132     uint8_t (*peer_noise_pks)[][crypto_scalarmult_BYTES];
133     Noise_XK_device_t *dev;
134     Noise_XK_session_t *(*noise_outs)[];
135     Noise_XK_session_t *(*noise_ins)[];
136     uint8_t (*commitments)[][crypto_core_ristretto255_BYTES];
137     TOPRF_Share (*shares)[];
138     TOPRF_Share (*xshares)[];
139     uint16_t complaints_len;
140     uint16_t *complaints;
141     uint8_t my_complaints_len;
142     uint8_t *my_complaints;
143     crypto_generichash_state transcript;
144     TOPRF_Share share;
145  } TP_DKG_PeerState;
146  
147  size_t tpdkg_peerstate_size(void);
148  
149  /**
150   * @brief Get the total number of peers (`n`) in this DKG session
151   */
152  uint8_t tpdkg_peerstate_n(const TP_DKG_PeerState *ctx);
153  
154  /**
155   * @brief Get the threshold parameter (`t`) for this DKG session
156   */
157  uint8_t tpdkg_peerstate_t(const TP_DKG_PeerState *ctx);
158  
159  /**
160   * @brief Get the session ID (unique identifier) for this DKG run
161   */
162  const uint8_t *tpdkg_peerstate_sessionid(const TP_DKG_PeerState *ctx);
163  
164  /**
165   * @brief Get this peer's long-term signing secret key
166   */
167  const uint8_t *tpdkg_peerstate_lt_sk(const TP_DKG_PeerState *ctx);
168  
169  /**
170   * @brief Get the final secret share after successful protocol completion
171   */
172  const uint8_t *tpdkg_peerstate_share(const TP_DKG_PeerState *ctx);
173  
174  /**
175   * @brief Get current internal protocol step counter
176   */
177  int tpdkg_peerstate_step(const TP_DKG_PeerState *ctx);
178  
179  /**
180   * @brief TP-DKG Error Codes
181   *
182   * ## `recv_msg()` error codes:
183   *  1 - Invalid message length.
184   *  2 - Unexpected message number.
185   *  3 - Invalid 'from' field.
186   *  4 - Invalid 'to' field.
187   *  5 - Message expired.
188   *  6 - Signature verification failed.
189   *
190   * ## Step 18 error codes (verification phase failures):
191   *  3 - HMAC verification failure.
192   *  4 - Share decryption failure.
193   *  5 - Invalid share index.
194   *  6 - Accused revealed an unexpected key (not part of complaint).
195   *  7 - Unchecked complaint (incomplete complaint resolution).
196   *  16 + `recv_msg()` error code - Invalid msg8 (final Noise + HMAC-ed share).
197   *  32 + `recv_msg()` error code - Invalid msg11 (key reveal message).
198   * 127 - Invalid verification parameters from accused peer.
199   * 128 - False complaint (complaint rejected, peer honest).
200   * 129 - Correct complaint (peer found cheating).
201   */
202  
203  /**
204   * @struct TP_DKG_TPState
205   * @brief Internal state structure for the TP during TP DKG execution
206   *
207   * Some fields in this struct are internal variables and should not
208   * be used. The following fields are useful and can be accessed by
209   * users of the API:
210   *
211   * @var STP_DKG_STPState::n Total number of peers participating in
212   *      this protocol
213   *
214   * @var STP_DKG_STPState::t The threshold, the minimum number of
215   *      peers required to use the shared secret generated by this DKG
216   *
217   * @var STP_DKG_STPState::cheaters List of detected cheaters and protocol
218   *      violators at the end of a failed protocol run
219   *
220   * @var STP_DKG_STPState::cheater_len Length of the `cheaters` list
221   */
222  
223  typedef struct {
224     int step;
225     int prev;
226     uint8_t sessionid[dkg_sessionid_SIZE];
227     uint8_t n;
228     uint8_t t;
229     uint8_t sig_pk[crypto_sign_PUBLICKEYBYTES];
230     uint8_t sig_sk[crypto_sign_SECRETKEYBYTES];
231     uint64_t *last_ts;
232     uint64_t ts_epsilon;
233     uint8_t (*peer_sig_pks)[][crypto_sign_PUBLICKEYBYTES];
234     uint8_t (*peer_lt_pks)[][crypto_sign_PUBLICKEYBYTES];
235     uint8_t (*commitments)[][crypto_core_ristretto255_BYTES];
236     // note this could be optimized by only storing the encrypted share and the hmac
237     // and also dropping all items where i==j
238     uint8_t (*encrypted_shares)[][tpdkg_msg8_SIZE];
239     uint16_t complaints_len;
240     uint16_t (*complaints)[];
241     size_t cheater_len;
242     TP_DKG_Cheater (*cheaters)[];
243     size_t cheater_max;
244     crypto_generichash_state transcript;
245  } TP_DKG_TPState;
246  
247  /**
248   * @brief Gets the size needed for allocation of a TP_DKG_TPState struct
249   *
250   * @return The size in bytes required for TP_DKG_TPState
251   */
252  size_t tpdkg_tpstate_size(void);
253  
254  /**
255   * @brief Gets the number of peers (`n`) participating in the protocol
256   *        from the TP state
257   *
258   * @param[in] ctx Pointer to an initialized TP_DKG_TPState struct
259   *
260   * @return The number of peers (`n`)
261   */
262  uint8_t tpdkg_tpstate_n(const TP_DKG_TPState *ctx);
263  
264  /**
265   * @brief Gets the threshold (`t`) required for the DKG from the TP state
266   *
267   * @param[in] ctx Pointer to an initialized TP_DKG_TPState struct
268   *
269   * @return The threshold value (`t`)
270   */
271  uint8_t tpdkg_tpstate_t(const TP_DKG_TPState *ctx);
272  
273  /**
274   * @brief Gets the number of cheaters detected in the protocol from
275   *        the TP state
276   *
277   * @param[in] ctx Pointer to an initialized TP_DKG_TPState struct
278   *
279   * @return The number of cheaters detected (length of the `cheaters` list)
280   */
281  size_t tpdkg_tpstate_cheater_len(const TP_DKG_TPState *ctx);
282  
283  /**
284   * @brief Gets the session ID associated with the current TP state
285   *
286   * @param[in] ctx Pointer to an initialized TP_DKG_TPState struct
287   *
288   * @return Pointer to the session ID buffer
289   */
290  const uint8_t *tpdkg_tpstate_sessionid(const TP_DKG_TPState *ctx);
291  
292  /**
293   * @brief Gets the current step number in the protocol
294   *
295   * @param[in] ctx Pointer to an initialized TP_DKG_TPState struct
296   *
297   * @return The current step as an integer
298   */
299  int tpdkg_tpstate_step(const TP_DKG_TPState *ctx);
300  
301  /*
302   * Trusted Party functions
303   */
304  
305  /**
306   * @brief Starts a new execution of a TP DKG protocol for the TP
307   *
308   * This function initializes the state of the TP and creates an
309   * initial message containing the parameters for the peers.
310   *
311   * @param[in] ctx Pointer to a TP_DKG_TPState struct. This struct
312   *            will be initialized by this function
313   * @param[in] ts_epsilon Maximum allowed message age in seconds before
314   *            it is considered stale and rejected. This value is used to
315   *            prevent replay attacks and enforce freshness. For small,
316   *            local setups (e.g., 2-out-of-3 participants), values as low
317   *            as 2–3 seconds may suffice. For large-scale deployments
318   *            (e.g., 126-out-of-127), this may need to be increased to
319   *            several hours
320   * @param[in] n Number of peers participating in this execution
321   * @param[in] t Threshold necessary to use the results of this DKG
322   * @param[in] proto_name a list of bytes used as a domain separation tag
323   *            (DST). Set it to the name of your application
324   * @param[in] proto_name_len The size of the array `proto_name`, to allow
325   *            non-zero terminated DSTs
326   * @param[in] sig_pks Pointer to a (n+1)-element array of signing public
327   *            keys. The STP's public key must be at index 0. The rest of the
328   *            items must be in order
329   * @param[in] ltssk STP’s private long-term signing key
330   * @param[in] msg0_len Size of allocated memory for the output message,
331   *            `msg0`. Should be exactly `tpdkg_msg0_SIZE` long
332   * @param[out] msg0 Output parameter, the message to be sent to peers
333   *             to initialize them
334   *
335   * @return 0 on success, non-zero on error
336   */
337  int tpdkg_start_tp(TP_DKG_TPState *ctx, const uint64_t ts_epsilon,
338                     const uint8_t n, const uint8_t t,
339                     const char *proto_name, const size_t proto_name_len,
340                     const size_t msg0_len, DKG_Message *msg0);
341  
342  /**
343   * @brief Sets all the variable sized buffers in the TP_DKG_TPState structure
344   *
345   * This function sets all the variable-sized buffers in the STP_DKG_STPState
346   * struct. These buffers must be preallocated by the caller, typically on
347   * the stack, based on the number of participants `n` and the threshold `t`
348   *
349   * A number of buffers are needed in the STP state that depend on the `n`
350   * (number of participants) and `t` (threshold) parameters.
351   * These can be allocated on the stack as follows:
352   * @code
353   * uint8_t tp_commitments[n*t][crypto_core_ristretto255_BYTES];
354   * uint16_t tp_complaints[n*n];
355   * uint8_t encrypted_shares[n*n][tpdkg_msg8_SIZE];
356   * TP_DKG_Cheater cheaters[t*t - 1];
357   * uint8_t tp_peers_sig_pks[n][crypto_sign_PUBLICKEYBYTES];
358   * uint8_t peer_lt_pks[n][crypto_sign_PUBLICKEYBYTES];
359   *
360   * tpdkg_tp_set_bufs(&tp, &tp_commitments, &tp_complaints, &encrypted_shares,
361   *                   &cheaters, sizeof(cheaters) / sizeof(TP_DKG_Cheater),
362   *                   &tp_peers_sig_pks, &peer_lt_pks, &last_ts);
363   * @endcode
364   *
365   * @param[in] ctx Pointer to the STP_DKG_STPState structure being
366   *                initialized
367   * @param[in] commitments Pointer to a list of curve points representing
368   *            commitments
369   * @param[in] complaints Pointer to a list of share complaint flags
370   * @param[in] encrypted_shares Buffer of encrypted shares
371   * @param[in] cheaters List of detected cheaters and protocol violators at
372   *            the end of a failed protocol run
373   * @param[in] cheater_max Maximum number of cheat attempts to be recorded.
374   *            Normally, the maximum number of cheaters is `t * t - 1`, where
375   *            `t` is the threshold parameter. It should be provided as
376   *            (sizeof(cheaters) / sizeof(TP_DKG_Cheater))
377   * @param[in] tp_peers_sig_pks Buffer of peers' long-term signing public keys
378   * @param[in] peer_lt_pks Buffer of peers' long-term public keys. This array
379   *            must be populated in the correct order before the first call
380   *             to `tpdkg_tp_next()`
381   * @param[in] last_ts Array to store latest message timestamps for
382   *            freshness checks
383   *
384   */
385  void tpdkg_tp_set_bufs(TP_DKG_TPState *ctx,
386                         uint8_t (*commitments)[][crypto_core_ristretto255_BYTES],
387                         uint16_t (*complaints)[],
388                         uint8_t (*encrypted_shares)[][tpdkg_msg8_SIZE],
389                         TP_DKG_Cheater (*cheaters)[], const size_t cheater_max,
390                         uint8_t (*tp_peers_sig_pks)[][crypto_sign_PUBLICKEYBYTES],
391                         uint8_t (*peer_lt_pks)[][crypto_sign_PUBLICKEYBYTES],
392                         uint64_t *last_ts);
393  
394  /**
395   * @brief Calculate the input buffer size required for the next TP step
396   *
397   * This function calculates the size of the buffer needed to hold all
398     outputs from the peers serving as input to the next step of the TP.
399   *
400   * An implementer should allocate a buffer of this size and concatenate
401   * all messages from all peers in the order of the peers' indices.
402   * The allocated buffer is to be passed as an input  `tpdkg_tp_next()`.
403   * After this, the buffer SHOULD be deallocated.
404   *
405   * @param[in] ctx  An initialized TP_DKG_TPState structure
406   *
407   * @return 1 on error, otherwise the size to be allocated (can be 0)
408   */
409  size_t tpdkg_tp_input_size(const TP_DKG_TPState *ctx);
410  
411  /**
412   * @brief Calculates the size of the message from each peer to be
413   *        received by the TP
414   *
415   * This function determines, for the current step, how many bytes the TP
416   * expects from each individual peer. The result is written into the
417   * provided `sizes` array.
418   *
419   * @param[in] ctx An initialized TP_DKG_TPState structure
420   * @param[out] sizes a list of size `n` (number of peers), where the input
421   *             sizes for each peer will be written
422   *
423   * @return  0 on if the sizes differ from peer to peer, otherwise all peers
424   *          will be sending messages of equal size. In the latter case, all
425   *          items of the `sizes` array hold the same valid value
426   */
427  int tpdkg_tp_input_sizes(const TP_DKG_TPState *ctx, size_t *sizes);
428  
429  /**
430   * @brief Gets the output buffer size needed for the next TP step
431   *
432   * Determines the buffer size required to hold the output of
433   * `tpdkg_tp_next()` for the current protocol step. An implementer
434   * should allocate a buffer of this size and pass it as the `output`
435   * parameter to `tpdkg_tp_next()`
436   *
437   * @param[in] ctx An initialized TP_DKG_TPState struct
438   * @return 1 on error, otherwise the size to be allocated (can be 0)
439   */
440  size_t tpdkg_tp_output_size(const TP_DKG_TPState *ctx);
441  
442  /**
443   * @brief Executes the next step of the TP DKG protocol for the TP
444   *
445   * Processes the current protocol step using the provided input buffer
446   * and writes the result to the output buffer. Then, it advances the
447   * protocol state.
448   *
449   * This is an example of how to use this function in concert with
450   * `tpdkg_tp_input_size()` and `tpdkg_tp_output_size()`:
451   * @code
452   * uint8_t tp_out[tpdkg_tp_output_size(&tp)];
453   * uint8_t tp_in[tpdkg_tp_input_size(&tp)];
454   * recv(socket, tp_in, sizeof(tp_in));
455   * ret = tpdkg_tp_next(&tp, tp_in, sizeof(tp_in), tp_out, sizeof tp_out);
456   * @endcode
457   *
458   * @param[in] ctx Pointer to a valid TP_DKG_TPState
459   * @param[in] input Buffer containing all peer inputs for the current step
460   * @param[in] input_len Size of the input buffer
461   * @param[out] output Output buffer for messages generated by the current
462   *             step
463   * @param[in] output_len Size of the output buffer
464   *
465   * @return 0 on success, non-zero on error
466   */
467  int tpdkg_tp_next(TP_DKG_TPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len);
468  
469  /**
470   * @brief Extracts the message to be sent to a specific peer from TP output
471   *
472   * This function converts the output of `stp_dkg_stp_next()` into a message
473   * to be sent to the i-th peer.
474   * Depending on the current STP step, the
475   * output may be a broadcast (same messages to all) or dedicated and
476   * unique messages for each peer.
477   * This function returns a pointer to a message and the size of the message
478   * to be sent for a particular peer specified as a parameter.
479   *
480   * This is an example of how to use this function in concert with
481   * `stp_dkg_stp_next()`:
482   * @code
483   * ret = tpdkg_tp_next(&tp, tp_in, sizeof(tp_in), tp_out, sizeof(tp_out));
484   * for (int i = 0; i < tp.n; i++) {
485   *   const uint8_t *msg;
486   *   size_t len;
487   *   if (tpdkg_tp_peer_msg(&tp, tp_out, sizeof(tp_out), i, &msg, &len) != 0)
488   *     return 1;
489   *   send(i, msg, len);
490   * }
491   * @endcode
492   *
493   * @param[in] ctx Pointer to a valid TP_DKG_TPState
494   * @param[in] base Pointer to the output buffer from `tpdkg_tp_next()`
495   * @param[in] base_size Size of the output buffer of `tpdkg_tp_next()`
496   * @param[in] peer Index of the peer (0-based)
497   * @param[out] msg Pointer to the message to be sent to the i-th peer
498   * @param[out] len Pointer to the length of the message to be sent to the
499   *             i-th peer
500   *
501   * @return 0 on success, non-zero on error
502   */
503  int tpdkg_tp_peer_msg(const TP_DKG_TPState *ctx, const uint8_t *base, const size_t base_size, const uint8_t peer, const uint8_t **msg, size_t *len);
504  
505  /**
506   * @brief Checks if the TP protocol has more steps to execute or more
507   * `tpdkg_tp_next()` calls are necessary
508   *
509   * @param[in] tp An initialized TP_DKG_TPState struct
510   *
511   * @return 1 if more steps are outstanding
512   */
513  int tpdkg_tp_not_done(const TP_DKG_TPState *tp);
514  
515  /**
516   * @brief Converts a cheater record to a human-readable string
517   *
518   * This function takes a TP_DKG_Cheater object (produced when cheating
519   * behavior is detected) and formats a descriptive string explaining the
520   * nature of the cheating incident.
521   *
522   * This variant is used for cheater objects created by TP
523   *
524   * @param[in] c Pointer to the cheater object
525   * @param[out] out The pointer to the pre-allocated Buffer to receive the
526   *             formatted string
527   * @param[in] outlen Size of the pre-allocated `out` buffer
528   *
529   * @return The index of the cheating peer
530   */
531  uint8_t tpdkg_cheater_msg(const TP_DKG_Cheater *c, char *out, const size_t outlen);
532  
533  /*
534   * Peer functions
535   */
536  
537  /**
538   * @brief Starts a new execution of a TP DKG protocol for a peer
539   *
540   * This function initializes the state of the peer.
541   *
542   * @param[out] ctx Pointer to a TP_DKG_PeerState struct. This struct
543   *            will be initialized by this function
544   * @param[in] ts_epsilon Maximum allowed message age in seconds before
545   *            it is considered stale and rejected. This value is used to
546   *            prevent replay attacks and enforce freshness. For small,
547   *            local setups (e.g., 2-out-of-3 participants), values as low
548   *            as 2–3 seconds may suffice. For large-scale deployments
549   *            (e.g., 126-out-of-127), this may need to be increased to
550   *            several hours
551   * @param[in] peer_lt_sk The long-term private signing secret key of the
552   *            peer
553   * @param[in] msg0 The initiating message, `msg0`, received from the STP,
554   *            created after running `tpdkg_tp_start()`
555   *
556   * @return 0 on success, non-zero on error
557   **/
558  int tpdkg_start_peer(TP_DKG_PeerState *ctx, const uint64_t ts_epsilon,
559                       const uint8_t peer_lt_sk[crypto_sign_SECRETKEYBYTES],
560                       const DKG_Message *msg0);
561  
562  /**
563   * @brief Sets all the variable-sized buffers in the TP_DKG_PeerState
564   *        structure
565   *
566   * The buffer sizes depend on the `n` and `t` parameters of the DKG
567   * protocol, which could be known in advance. If not, these parameters
568   * are announced by the TP in `msg0`, which is an input to the
569   * `tpdkg_start_peer()` function. After this `tpdkg_start_peer()` call,
570   * the peer state is initialized and can be used to find out the `n` and
571   * `t` parameters.
572   *
573   * To allocate all the buffers on the stack:
574   * @code
575   * uint8_t peers_sig_pks[peerstate.n][crypto_sign_PUBLICKEYBYTES];
576   * uint8_t peers_noise_pks[peerstate.n][crypto_scalarmult_BYTES];
577   * Noise_XK_session_t *noise_outs[peerstate.n];
578   * Noise_XK_session_t *noise_ins[peerstate.n];
579   * TOPRF_Share ishares[peerstate.n];
580   * TOPRF_Share xshares[peerstate.n];
581   * uint8_t commitments[peerstate.n *peerstate.t][crypto_core_ristretto255_BYTES];
582   * uint16_t peer_complaints[peerstate.n *peerstate.n];
583   * uint8_t peer_my_complaints[peerstate.n];
584   * @endcode
585   *
586   * @param[in] ctx An initialized TP_DKG_PeerState struct
587   * @param[in] peers_sig_pks Pointer to a list of peers' signature public keys
588   * @param[in] peers_noise_pks Pointer to a list of peers' Noise_XK protocol
589   *            public keys
590   * @param[in] commitments Pointer to a list of commitments
591   * @param[in] complaints Pointer to a list holding complaint indices
592   * @param[in] my_complaints Pointer to a list holding this peer's complaints
593   * @param[in] last_ts Pointer to a list of last timestamps for each peer
594   */
595  void tpdkg_peer_set_bufs(TP_DKG_PeerState *ctx,
596                           uint8_t (*peers_sig_pks)[][crypto_sign_PUBLICKEYBYTES],
597                           uint8_t (*peers_noise_pks)[][crypto_scalarmult_BYTES],
598                           Noise_XK_session_t *(*noise_outs)[],
599                           Noise_XK_session_t *(*noise_ins)[],
600                           TOPRF_Share (*shares)[],
601                           TOPRF_Share (*xshares)[],
602                           uint8_t (*commitments)[][crypto_core_ristretto255_BYTES],
603                           uint16_t *complaints,
604                           uint8_t *my_complaints,
605                           uint64_t *last_ts);
606  
607  /**
608   * @brief Calculates the required size of the input buffer for the next
609   *        step of the peer
610   *
611   * This function returns the size in bytes of the input buffer that the peer
612   * will expect for the upcoming protocol step. The input buffer holds the
613   * data that the TP sends to the peer.
614   *
615   * The caller should allocate a buffer of at least this size and pass it as
616   * input to `tpdkg_peer_next()`. After the step completes, the buffer SHOULD
617   * be deallocated.
618   *
619   * @param[in] ctx An initialized TP_DKG_PeerState struct
620   *
621   * @return 1 on error, otherwise the size to be allocated (can be 0)
622   */
623  size_t tpdkg_peer_input_size(const TP_DKG_PeerState *ctx);
624  
625  /**
626   * @brief Calculates the size of the buffer needed to hold the output from
627   *        the `tpdkg_peer_next()` function
628   *
629   * Determines the buffer size required to hold the output of
630   * `tpdkg_peer_next()` for the current protocol step.
631   * An implementer should allocate a buffer of this size and pass it as the
632   * `output` parameter to `tpdkg_peer_next()`.
633   *
634   * @param[in] ctx An initialized TP_DKG_PeerState struct
635   *
636   * @return 1 on error, otherwise the size to be allocated (can be 0)
637   */
638  size_t tpdkg_peer_output_size(const TP_DKG_PeerState *ctx);
639  
640  /**
641   * @brief Executes the next step of the TP DKG protocol for a peer
642   *
643   * Processes the current protocol step using the provided input buffer
644   * and writes the result to the output buffer. Then, it advances the
645   * protocol state.
646   *
647   * This is an example of how to use this function in concert with
648   * `tpdkg_peer_output_size()` and `tpdkg_peer_output_size()`:
649   * @code
650   * uint8_t peers_out[tpdkg_peer_output_size(&peer)];
651   *
652   * uint8_t peer_in[tpdkg_peer_input_size(&peer)];
653   * recv(socket, peer_in, sizeof(peer_in));
654   * ret = tpdkg_peer_next(&peer,
655   *                       peer_in, sizeof(peer_in),
656   *                       peers_out, sizeof(peers_out));
657   * @endcode
658   *
659   * @param[in] ctx Pointer to a valid TP_DKG_PeerState
660   * @param[in] input Buffer containing input data for the current step
661   * @param[in] input_len Size of the input buffer
662   * @param[out] output Buffer to receive the output of the current step
663   * @param[in] output_len Size of the output buffer
664   *
665   * @return 0 on success, non-zero on error
666   *
667   */
668  int tpdkg_peer_next(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len);
669  
670  /**
671   * @brief Checks if the STP protocol has more steps to execute or more
672   * `tpdk_peer_next()` calls are necessary
673   *
674   * @param peer Pointer to a valid TP_DKG_PeerState
675   *
676   * @return 1 if more steps are outstanding
677   */
678  int tpdkg_peer_not_done(const TP_DKG_PeerState *peer);
679  
680  /**
681   * @brief Frees all resources allocated by the peer state
682   *
683   * This function MUST be called before a peer's state is deallocated.
684   * The underlying Noise_XK implementation allocates a lot of internal
685   * state on the heap, which must be freed manually to avoid memory leaks.
686   *
687   *
688   * @param ctx Pointer to the TP_DKG_PeerState to free
689   */
690  void tpdkg_peer_free(TP_DKG_PeerState *ctx);
691  
692  extern FILE* log_file;
693  
694  #endif //tp_dkg_h