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