/ src / toprf-update.c
toprf-update.c
   1  #include <arpa/inet.h> //htons
   2  #include "utils.h"
   3  #include "toprf-update.h"
   4  #include "dkg-vss.h"
   5  #include "mpmult.h"
   6  #ifndef HAVE_SODIUM_HKDF
   7  #include "aux_/crypto_kdf_hkdf_sha256.h"
   8  #endif
   9  #ifdef __ZEPHYR__
  10  #include <zephyr/kernel.h>
  11  #endif
  12  
  13  // todo handle adding new peers who don't have a share of kc
  14  // todo handle random order of peers - related to prev todo
  15  // todo revert to non-fast-track mult to catch the case when dealer
  16  //      deals something else than λ_iα_iβ_i but 𝓒_i0 is based on the
  17  //      correct value, so the ZK proof does not fail.
  18  // todo add toprf_update_(stp|peer)_cheater_msg()
  19  
  20  #ifdef UNITTEST_CORRUPT
  21  static void corrupt_ci0_good_ci(const uint8_t peer, uint8_t commitments[][crypto_core_ristretto255_BYTES]) {
  22    // this corruption does not influence the outcome of the protocol
  23    // it merely fails the zkp *and* the vsps, but the end result is correct!
  24    uint8_t secret[crypto_core_ristretto255_SCALARBYTES];
  25    crypto_core_ristretto255_scalar_random(secret);
  26    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"!!! Corrupting C_i0 λ_iα_iβ_i %d\n"NORMAL, peer);
  27    dkg_vss_commit(secret,secret,commitments[0]);
  28  }
  29  
  30  /// deals shares with polynomial t+1 instead of 1
  31  static void corrupt_vsps_t1(const TOPRF_Update_PeerState *ctx,
  32                              const uint8_t peer,
  33                              TOPRF_Share (*shares)[][2],
  34                              uint8_t (*commitments)[][crypto_core_ristretto255_BYTES]) {
  35    if(ctx->index!=peer) return;
  36    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"!!! Corrupting with wrong degree of the polynom peer %d\n"NORMAL, peer);
  37    (void)dkg_vss_share(ctx->n, ctx->t+1, NULL, (*commitments), (*shares), NULL);
  38  }
  39  
  40  static void corrupt_mult_vsps_t1(TOPRF_Update_PeerState *ctx,
  41                                   const uint8_t peer) {
  42    if(ctx->index!=peer) return;
  43    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] !!! Corrupting mult sharing with degree t+1 polynomial\n"NORMAL, peer);
  44    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
  45    (void)toprf_mpc_ftmult_step1(dealers, ctx->n, ctx->t+1, ctx->index-1,
  46                                 ctx->kc0_share, ctx->p_share, (*ctx->lambdas),
  47                                 // we reuse p_shares as we need to store n shares, and k0p_shares has only dealer entries
  48                                 (*ctx->p_shares), (*ctx->k0p_commitments), ctx->k0p_tau);
  49  }
  50  
  51  static void corrupt_commitment(TOPRF_Update_PeerState *ctx, const uint8_t peer,
  52                                 uint8_t (*commitments)[][crypto_core_ristretto255_BYTES]) { // corrupts the 1st commitment with the 2nd
  53    if(ctx->index!=peer) return;
  54    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"!!! Corrupting commitment of peer %d\n"NORMAL, peer);
  55    memcpy((*commitments)[2], (*commitments)[1], crypto_core_ristretto255_BYTES);
  56  }
  57  
  58  static void corrupt_wrongshare_correct_commitment(TOPRF_Update_PeerState *ctx, // swaps the share and it's blinder,
  59                                                    const uint8_t peer,     // recalculates commitment
  60                                                    const uint8_t share_idx,
  61                                                    TOPRF_Share (*shares)[][2],
  62                                                    uint8_t (*commitments)[][crypto_core_ristretto255_BYTES]) {
  63    if(ctx->index!=peer) return;
  64    TOPRF_Share tmp;
  65    // swap shares
  66    memcpy(&tmp, &(*shares)[share_idx][0], sizeof tmp);
  67    memcpy(&(*shares)[share_idx][0], &(*shares)[share_idx][1], sizeof tmp);
  68    memcpy(&(*shares)[share_idx][1], &tmp, sizeof tmp);
  69    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"!!! Corrupting share (but correct commitment) of peer %d\n"NORMAL, peer);
  70    dkg_vss_commit((*shares)[share_idx][0].value,(*shares)[share_idx][1].value,(*commitments)[share_idx]);
  71  }
  72  
  73  static void corrupt_share(TOPRF_Update_PeerState *ctx, const uint8_t peer,
  74                            const uint8_t share_idx,
  75                            const uint8_t share_type,
  76                            TOPRF_Share (*shares)[][2]) {
  77    if(ctx->index!=peer) return;
  78    if(liboprf_log_file!=NULL) {
  79      fprintf(liboprf_log_file, RED"!!! Corrupting share of peer %d\n"NORMAL, peer);
  80      dump((uint8_t*) (*shares)[share_idx], TOPRF_Share_BYTES * 2, "correct share");
  81    }
  82    (*shares)[share_idx][share_type].value[2]^=0xff; // flip some bits
  83    if(liboprf_log_file!=NULL) {
  84      dump((uint8_t*) (*shares)[share_idx], TOPRF_Share_BYTES * 2, "corrupt share");
  85    }
  86  }
  87  
  88  static void corrupt_false_accuse(TOPRF_Update_PeerState *ctx,
  89                                   const uint8_t peer,
  90                                   const uint8_t p2,
  91                                   uint8_t *fails_len, uint8_t *fails) {
  92    if(ctx->index!=peer) return;
  93    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"!!! Corrupting falsely accusing peer %d by peer %d\n"NORMAL, p2, peer);
  94    fails[(*fails_len)++]=p2;
  95  }
  96  #endif // UNITTEST_CORRUPT
  97  
  98  size_t toprf_update_peerstate_size(void) {
  99    return sizeof(TOPRF_Update_PeerState);
 100  }
 101  uint8_t toprf_update_peerstate_n(const TOPRF_Update_PeerState *ctx) {
 102    return ctx->n;
 103  }
 104  uint8_t toprf_update_peerstate_t(const TOPRF_Update_PeerState *ctx) {
 105    return ctx->t;
 106  }
 107  const uint8_t* toprf_update_peerstate_sessionid(const TOPRF_Update_PeerState *ctx) {
 108    return ctx->sessionid;
 109  }
 110  const uint8_t* toprf_update_peerstate_share(const TOPRF_Update_PeerState *ctx) {
 111    if(toprf_update_peer_not_done(ctx)) return NULL;
 112    return (const uint8_t*) &ctx->k0p_share;
 113  }
 114  const uint8_t* toprf_update_peerstate_commitments(const TOPRF_Update_PeerState *ctx) {
 115    if(toprf_update_peer_not_done(ctx)) return NULL;
 116    return (const uint8_t*) (*ctx->p_commitments);
 117  }
 118  const uint8_t* toprf_update_peerstate_commitment(const TOPRF_Update_PeerState *ctx) {
 119    if(toprf_update_peer_not_done(ctx)) return NULL;
 120    return (const uint8_t*) ctx->k0p_commitment;
 121  }
 122  int toprf_update_peerstate_step(const TOPRF_Update_PeerState *ctx) {
 123    return ctx->step;
 124  }
 125  
 126  size_t toprf_update_stpstate_size(void) {
 127    return sizeof(TOPRF_Update_STPState);
 128  }
 129  uint8_t toprf_update_stpstate_n(const TOPRF_Update_STPState *ctx) {
 130    return ctx->n;
 131  }
 132  uint8_t toprf_update_stpstate_t(const TOPRF_Update_STPState *ctx) {
 133    return ctx->t;
 134  }
 135  size_t toprf_update_stpstate_cheater_len(const TOPRF_Update_STPState *ctx) {
 136    return ctx->cheater_len;
 137  }
 138  const uint8_t* toprf_update_stpstate_sessionid(const TOPRF_Update_STPState *ctx) {
 139    return ctx->sessionid;
 140  }
 141  const uint8_t* toprf_update_stpstate_delta(const TOPRF_Update_STPState *ctx) {
 142    if(toprf_update_stp_not_done(ctx)) return NULL;
 143    return ctx->delta;
 144  }
 145  const uint8_t* toprf_update_stpstate_commitments(const TOPRF_Update_STPState *ctx) {
 146    if(toprf_update_stp_not_done(ctx)) return NULL;
 147    return (const uint8_t*) (*ctx->k0p_final_commitments);
 148  }
 149  int toprf_update_stpstate_step(const TOPRF_Update_STPState *ctx) {
 150    return ctx->step;
 151  }
 152  
 153  static int toprf_send_msg(uint8_t* msg_buf, const size_t msg_buf_len,
 154                            const uint8_t msgno,
 155                            const uint8_t from, const uint8_t to,
 156                            const uint8_t *sig_sk, const uint8_t sessionid[dkg_sessionid_SIZE]) {
 157    int ret = send_msg(msg_buf, msg_buf_len, MSG_TYPE_SEMI_TRUSTED | MSG_TYPE_UPDATE, 0, msgno, from, to, sig_sk, sessionid);
 158    //dkg_dump_msg(msg_buf, msg_buf_len, from);
 159    return ret;
 160  }
 161  
 162  static int toprf_recv_msg(const uint8_t *msg_buf, const size_t msg_buf_len,
 163                            const uint8_t msgno,
 164                            const uint8_t from, const uint8_t to,
 165                            const uint8_t *sig_pk, const uint8_t sessionid[dkg_sessionid_SIZE],
 166                            const uint64_t ts_epsilon, uint64_t *last_ts) {
 167    return recv_msg(msg_buf, msg_buf_len, MSG_TYPE_SEMI_TRUSTED | MSG_TYPE_UPDATE, 0, msgno, from, to, sig_pk, sessionid, ts_epsilon, last_ts);
 168  }
 169  
 170  static void set_cheater(TOPRF_Update_Cheater *cheater, const int step, const int error, const uint8_t peer, const uint8_t other_peer) {
 171    cheater->step = step;
 172    cheater->error = error;
 173    cheater->peer = peer;
 174    cheater->other_peer=other_peer;
 175  }
 176  
 177  static TOPRF_Update_Cheater* stp_add_cheater(TOPRF_Update_STPState *ctx, const int error, const uint8_t peer, const uint8_t other_peer) {
 178    if(ctx->cheater_len >= ctx->cheater_max) return NULL;
 179    TOPRF_Update_Cheater *cheater = &(*ctx->cheaters)[ctx->cheater_len++];
 180    set_cheater(cheater, ctx->step, error, peer, other_peer);
 181    return cheater;
 182  }
 183  
 184  static TOPRF_Update_Cheater* peer_add_cheater(TOPRF_Update_PeerState *ctx,const int error, const uint8_t peer, const uint8_t other_peer) {
 185    if(ctx->cheater_len >= ctx->cheater_max) return NULL;
 186    TOPRF_Update_Cheater *cheater = &(*ctx->cheaters)[ctx->cheater_len++];
 187    set_cheater(cheater, ctx->step, error, peer, other_peer);
 188    return cheater;
 189  }
 190  
 191  static unsigned isdealer(const uint8_t i, const uint8_t t) {
 192    return  i <= ((t-1)*2 + 1);
 193  }
 194  
 195  static int stp_recv_msg(TOPRF_Update_STPState *ctx,
 196                          const uint8_t *msg_buf, const size_t msg_buf_len,
 197                          const uint8_t msgno,
 198                          const uint8_t from, const uint8_t to) {
 199    //dkg_dump_msg(msg_buf, msg_buf_len, 0);
 200    int ret = toprf_recv_msg(msg_buf, msg_buf_len, msgno, from, to, (*ctx->sig_pks)[from], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[from-1]);
 201    if(0!=ret) {
 202      if(stp_add_cheater(ctx, 64+ret, from, to) == NULL) return TOPRF_Update_Err_CheatersFull;
 203      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"failed to validate msg %d from %d, err: %d\n"NORMAL, msgno, from, ret);
 204      return 1;
 205    }
 206    return 0;
 207  }
 208  
 209  static int peer_recv_msg(TOPRF_Update_PeerState *ctx,
 210                           const uint8_t *msg_buf, const size_t msg_buf_len,
 211                           const uint8_t msgno,
 212                           const uint8_t from, const uint8_t to) {
 213    //dkg_dump_msg(msg_buf, msg_buf_len, ctx->index);
 214    int ret = toprf_recv_msg(msg_buf, msg_buf_len, msgno, from, to, (*ctx->sig_pks)[from], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[from-1]);
 215    if(0!=ret) {
 216      if(peer_add_cheater(ctx, 64+ret, from, to) == NULL) return TOPRF_Update_Err_CheatersFull;
 217      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] failed to validate msg %d from %d, err: %d\n"NORMAL, ctx->index, msgno, from, ret);
 218      return 1;
 219    }
 220    return 0;
 221  }
 222  
 223  static TOPRF_Update_Err stp_broadcast(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len,
 224                                        const char *step_title,
 225                                        const uint8_t msg_count,          // usually n, sometimes dealers
 226                                        const size_t msg_size,
 227                                        const uint8_t msgno,
 228                                        const TOPRF_Update_STP_Steps next_step) {
 229    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] %s\x1b[0m\n", step_title);
 230    if(msg_count * msg_size != input_len) return TOPRF_Update_Err_ISize;
 231    const size_t cheaters = ctx->cheater_len;
 232    if(sizeof(TOPRF_Update_Message) + input_len != output_len) return TOPRF_Update_Err_OSize;
 233    const uint8_t *ptr = input;
 234    uint8_t *wptr = ((TOPRF_Update_Message *) output)->data;
 235    for(uint8_t i=0;i<msg_count;i++,ptr+=msg_size) {
 236      if(stp_recv_msg(ctx,ptr,msg_size,msgno,i+1,0xff)) continue;
 237      memcpy(wptr, ptr, msg_size);
 238      wptr+=msg_size;
 239    }
 240    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
 241  
 242    if(0!=toprf_send_msg(output, output_len, msgno+1, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
 243  
 244    // add broadcast msg to transcript
 245    update_transcript(&ctx->transcript_state, output, output_len);
 246  
 247    ctx->step = next_step;
 248  
 249    return TOPRF_Update_Err_OK;
 250  }
 251  
 252  static TOPRF_Update_Err stp_route(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len,
 253                                    const char *step_title,
 254                                    const uint8_t send_count,
 255                                    const uint8_t recv_count,
 256                                    const uint8_t msgno,
 257                                    const size_t msg_size,
 258                                    const TOPRF_Update_STP_Steps next_step) {
 259    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] %s\x1b[0m\n", step_title);
 260    if(input_len != msg_size * send_count * recv_count) return TOPRF_Update_Err_ISize;
 261    if(input_len != output_len) return TOPRF_Update_Err_OSize;
 262    //const size_t cheaters = ctx->cheater_len;
 263  
 264    const uint8_t (*inputs)[send_count][recv_count][msg_size] = (const uint8_t (*)[send_count][recv_count][msg_size]) input;
 265    uint8_t *wptr = output;
 266    for(uint8_t i=0;i<recv_count;i++) {
 267      for(uint8_t j=0;j<send_count;j++) {
 268        int ret = toprf_recv_msg((*inputs)[j][i], msg_size,
 269                                 msgno, j+1, i+1, (*ctx->sig_pks)[j+1],
 270                                 ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[j]);
 271        if(0!=ret) {
 272          if(stp_add_cheater(ctx, 64+ret, j+1, i+1) == NULL) return TOPRF_Update_Err_CheatersFull;
 273          const TOPRF_Update_Message *msg = (const TOPRF_Update_Message*) (*inputs)[j][i];
 274          fprintf(liboprf_log_file,"[x] msgno: %d, from: %d to: %d ", msg->msgno, msg->from, msg->to);
 275          dump((*inputs)[j][i], msg_size, "msg");
 276          continue;
 277        }
 278        memcpy(wptr, (*inputs)[j][i], msg_size);
 279        wptr+=msg_size;
 280      }
 281    }
 282    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
 283  
 284    ctx->step = next_step;
 285    return TOPRF_Update_Err_OK;
 286  }
 287  
 288  static TOPRF_Update_Err unwrap_envelope(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, const uint8_t msgno, const uint8_t **contents) {
 289    // verify STP message envelope
 290    const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) input;
 291    //dkg_dump_msg(input, input_len, ctx->index);
 292    int ret = toprf_recv_msg(input, input_len, msgno, 0, 0xff, (*ctx->sig_pks)[0], ctx->sessionid, ctx->ts_epsilon, &ctx->stp_last_ts);
 293    if(0!=ret) return TOPRF_Update_Err_BroadcastEnv+ret;
 294  
 295    // add broadcast msg to transcript
 296    update_transcript(&ctx->transcript_state, input, input_len);
 297  
 298    *contents = msg->data;
 299    return TOPRF_Update_Err_OK;
 300  }
 301  
 302  static void handle_complaints(const uint8_t n,
 303                                const uint8_t accuser,
 304                                const uint8_t fails_len, const uint8_t fails[],
 305                                uint16_t *ctx_complaints_len, uint16_t *ctx_complaints,
 306                                const uint8_t self,
 307                                uint8_t *ctx_my_complaints_len, uint8_t *ctx_my_complaints) {
 308    // keep a copy all complaint pairs (complainer, complained)
 309    for(unsigned k=0;k<fails_len && k<n;k++) {
 310      if(fails[k] > n || fails[k] < 1) {
 311        //fails[k] has an invalid peer idx value.
 312        // todo cheater handling
 313        //if(stp_add_cheater(ctx, 7, i+1, msg->data[k+1]) == NULL) return 6;
 314        continue;
 315      }
 316      uint16_t pair=(uint16_t) ((accuser<<8) | fails[k]);
 317      int j=0;
 318      for(j=0;j<*ctx_complaints_len;j++) if(ctx_complaints[j]==pair) break;
 319      if(j<*ctx_complaints_len) {
 320        //already seen this accuser/accused pair.
 321        // todo cheater handling
 322        //if(stp_add_cheater(ctx, 18, 8, i+1, msg->data[k+1]) == NULL) return 6;
 323        continue;
 324      }
 325      ctx_complaints[(*ctx_complaints_len)++] = pair;
 326  
 327      if(self!=0 && fails[k] == self && ctx_my_complaints_len != NULL && ctx_my_complaints != NULL) {
 328          ctx_my_complaints[(*ctx_my_complaints_len)++] = accuser;
 329      }
 330      if(liboprf_log_file!=NULL) {
 331        fprintf(liboprf_log_file,"\x1b[0;31m[%d] peer %d failed to verify commitments from peer %d!\x1b[0m\n", self, accuser, fails[k]);
 332      }
 333    }
 334  }
 335  
 336  static TOPRF_Update_Err stp_complaint_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len,
 337                                                const char* step_title,
 338                                                const uint8_t msg_count,
 339                                                const size_t msg_size,
 340                                                const uint8_t msgno,
 341                                                const uint8_t dealers,
 342  
 343                                                const TOPRF_Update_STP_Steps pass_step,
 344                                                const TOPRF_Update_STP_Steps fail_step) {
 345    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] %s\x1b[0m\n", step_title);
 346  
 347    if(input_len != msg_size * msg_count) return TOPRF_Update_Err_ISize;
 348    if(sizeof(TOPRF_Update_Message) + input_len != output_len) return TOPRF_Update_Err_OSize;
 349    //const size_t cheaters = ctx->cheater_len;
 350  
 351    ctx->p_complaints_len = 0;
 352  
 353    const uint8_t *ptr = input;
 354    uint8_t *wptr = ((TOPRF_Update_Message *) output)->data;
 355    for(uint8_t i=0;i<msg_count;i++, ptr+=msg_size) {
 356      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
 357      if(stp_recv_msg(ctx,ptr,msg_size,msgno,i+1,0xff)) continue;
 358      if(ntohl(msg->len) - sizeof(TOPRF_Update_Message) < msg->data[0]) return TOPRF_Update_Err_OOB;
 359  
 360      const uint8_t *fails_len = msg->data;
 361      const uint8_t *fails = msg->data+1;
 362      handle_complaints(msg_count, i+1, *fails_len, fails, &ctx->p_complaints_len, ctx->p_complaints, 0, 0, 0);
 363  
 364      memcpy(wptr, ptr, msg_size);
 365      wptr+=msg_size;
 366    }
 367  
 368    // if more than t^2 complaints are received the protocol also fails
 369    if(ctx->p_complaints_len >= ctx->t * ctx->t) {
 370      if(stp_add_cheater(ctx, 6, 0xfe, 0xfe) == NULL) return TOPRF_Update_Err_CheatersFull;
 371      return TOPRF_Update_Err_TooManyCheaters;
 372    }
 373  
 374    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
 375  
 376    if(0!=toprf_send_msg(output, output_len, msgno+1, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
 377  
 378    // add broadcast msg to transcript
 379    update_transcript(&ctx->transcript_state, output, output_len);
 380  
 381    ctx->prev = ctx->step;
 382    if(ctx->p_complaints_len == 0) {
 383      ctx->step = pass_step;
 384    } else {
 385      dump((uint8_t*) ctx->p_complaints, ctx->p_complaints_len*sizeof(uint16_t), "[!] complaints_2");
 386      ctx->step = fail_step;
 387    }
 388  
 389    return TOPRF_Update_Err_OK;
 390  }
 391  
 392  static TOPRF_Update_Err peer_complaint_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len,
 393                                                 const char *step_title,
 394                                                 const size_t msg_size,
 395                                                 const uint8_t msgno,
 396                                                 const uint8_t dealers,
 397                                                 const TOPRF_Update_Peer_Steps pass_step,
 398                                                 const TOPRF_Update_Peer_Steps fail_step) {
 399    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] %s\x1b[0m\n", ctx->index, step_title);
 400    if(input_len != sizeof(TOPRF_Update_Message) + msg_size * ctx->n) return TOPRF_Update_Err_ISize;
 401    //const size_t cheaters = ctx->cheater_len;
 402  
 403    // verify STP message envelope
 404    const uint8_t *ptr=NULL;
 405    int ret = unwrap_envelope(ctx,input,input_len,msgno+1,&ptr);
 406    if(ret!=TOPRF_Update_Err_OK) return ret;
 407  
 408    for(uint8_t i=0;i<ctx->n;i++, ptr+=msg_size) {
 409      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
 410      if(peer_recv_msg(ctx,ptr,msg_size,msgno,i+1,0xff)) continue;
 411      if(ntohl(msg->len) - sizeof(TOPRF_Update_Message) < msg->data[0]) return TOPRF_Update_Err_OOB;
 412      const uint8_t *fails_len = msg->data;
 413      const uint8_t *fails = msg->data+1;
 414      handle_complaints(ctx->n, i+1, *fails_len, fails, &ctx->p_complaints_len, ctx->p_complaints, ctx->index, &ctx->my_p_complaints_len, ctx->my_p_complaints);
 415    }
 416  
 417    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
 418  
 419    ctx->prev = ctx->step;
 420    if(ctx->p_complaints_len == 0) {
 421      ctx->step = pass_step;
 422    } else {
 423      dump((uint8_t*) ctx->p_complaints, ctx->p_complaints_len*sizeof(uint16_t), "[!] complaints_2");
 424      ctx->step = fail_step;
 425    }
 426  
 427    return TOPRF_Update_Err_OK;
 428  }
 429  
 430  static TOPRF_Update_Err ft_or_full_vsps(const uint8_t n, const uint8_t t, const uint8_t dealers, const uint8_t self,
 431                                          const uint8_t C_i[n][crypto_core_ristretto255_BYTES],
 432                                          const uint8_t (*C_ij)[dealers][n][crypto_core_ristretto255_BYTES],
 433                                          const char *ft_msg, const char *sub_msg, const char *no_sub_msg,
 434                                          uint8_t *fails_len, uint8_t fails[dealers]) {
 435    //fprintf(stderr,"asdf %d %d %d %d\n", n, t, dealers, self);
 436    //for(unsigned i=0;i<n;i++) dump(C_i[i], crypto_core_ristretto255_BYTES, "C_%d",i);
 437    //for(unsigned i=0;i<n;i++)
 438    //  for(unsigned j=0;j<n;j++)
 439    //    dump((*C_ij)[i][j], crypto_core_ristretto255_BYTES, "C_%d,%d", i, j);
 440  
 441    int _debug=liboprf_debug; liboprf_debug=0;
 442    if(0!=toprf_mpc_vsps_check(t-1, C_i)) {
 443      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] %s\n"NORMAL, self, ft_msg);
 444      for(uint8_t i=0;i<dealers;i++) {
 445        if(0!=toprf_mpc_vsps_check(t-1, (*C_ij)[i])) {
 446          if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] %s [%d]\n"NORMAL, self, sub_msg, i+1);
 447          fails[(*fails_len)++]=i+1;
 448        }
 449      }
 450      liboprf_debug=_debug;
 451      if(*fails_len == 0) {
 452        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] %s\n"NORMAL, self, no_sub_msg);
 453        return TOPRF_Update_Err_NoSubVSPSFail;
 454      }
 455    }
 456    return TOPRF_Update_Err_OK;
 457  }
 458  
 459  int toprf_update_start_stp(TOPRF_Update_STPState *ctx, const uint64_t ts_epsilon,
 460                             const uint8_t n, const uint8_t t,
 461                             const char *proto_name, const size_t proto_name_len,
 462                             const uint8_t keyid[toprf_keyid_SIZE],
 463                             const uint8_t (*sig_pks)[][crypto_sign_PUBLICKEYBYTES],
 464                             const uint8_t ltssk[crypto_sign_SECRETKEYBYTES],
 465                             const size_t msg0_len,
 466                             TOPRF_Update_Message *msg0) {
 467    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] init 0. start toprf update\x1b[0m\n");
 468    if(2>n || t>=n || n>128 || n<2*t+1) return 1;
 469    if(proto_name_len<1) return 2;
 470    if(proto_name_len>1024) return 3;
 471    if(msg0_len != toprfupdate_stp_start_msg_SIZE) return 4;
 472  
 473    ctx->ts_epsilon = ts_epsilon;
 474    ctx->step = TOPRF_Update_STP_Broadcast_NPKs;
 475    ctx->n = n;
 476    ctx->t = t;
 477    ctx->p_complaints_len = 0;
 478    ctx->y2_complaints_len = 0;
 479    ctx->cheater_len = 0;
 480  
 481    // dst hash(len(protoname) | "TOPRF Update for protocol " | protoname | n | t)
 482    crypto_generichash_state dst_state;
 483    crypto_generichash_init(&dst_state, NULL, 0, crypto_generichash_BYTES);
 484    uint16_t len=htons((uint16_t) proto_name_len+20); // we have a guard above restricting to 1KB the proto_name_len
 485    crypto_generichash_update(&dst_state, (uint8_t*) &len, 2);
 486    crypto_generichash_update(&dst_state, (const uint8_t*) "TOPRF Update for protocol ", 26);
 487    crypto_generichash_update(&dst_state, (const uint8_t*) proto_name, proto_name_len);
 488    crypto_generichash_update(&dst_state, &n, 1);
 489    crypto_generichash_update(&dst_state, &t, 1);
 490    uint8_t dst[crypto_generichash_BYTES];
 491    crypto_generichash_final(&dst_state,dst,sizeof dst);
 492  
 493    // set sessionid nonce, we abuse this session_id field in the state
 494    // to temporarily store the session id nonce; which will later
 495    // become the real session_id after the other peers also contributed
 496    // their nonces
 497    randombytes_buf(&ctx->sessionid, sizeof ctx->sessionid);
 498  
 499    // a list of all long-term pubkeys
 500    ctx->sig_pks = sig_pks;
 501    // keep a copy of our long-term signing key
 502    memcpy(ctx->sig_sk, ltssk, crypto_sign_SECRETKEYBYTES);
 503  
 504    // data = {stp_lt_pks, dst, keyid}
 505    uint8_t *ptr = msg0->data;
 506    memcpy(ptr, (*sig_pks)[0], crypto_sign_PUBLICKEYBYTES);
 507    ptr+=crypto_sign_PUBLICKEYBYTES;
 508    memcpy(ptr, dst, sizeof dst);
 509    ptr+=sizeof dst;
 510    memcpy(ptr, keyid, toprf_keyid_SIZE);
 511  
 512    if(0!=toprf_send_msg((uint8_t*) msg0, toprfupdate_stp_start_msg_SIZE, toprfupdate_stp_start_msg, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return 5;
 513  
 514    // init transcript
 515    crypto_generichash_init(&ctx->transcript_state, NULL, 0, crypto_generichash_BYTES);
 516    crypto_generichash_update(&ctx->transcript_state, (const uint8_t*) "toprf update session transcript", 31);
 517    // feed msg0 into transcript
 518    update_transcript(&ctx->transcript_state, (uint8_t*) msg0, msg0_len);
 519  
 520    return 0;
 521  }
 522  
 523  void toprf_update_stp_set_bufs(TOPRF_Update_STPState *ctx,
 524                                 uint16_t p_complaints[],
 525                                 uint16_t y2_complaints[],
 526                                 TOPRF_Update_Cheater (*cheaters)[], const size_t cheater_max,
 527                                 uint8_t (*p_commitments_hashes)[][toprf_update_commitment_HASHBYTES],
 528                                 uint8_t (*p_share_macs)[][crypto_auth_hmacsha256_BYTES],
 529                                 uint8_t (*p_commitments)[][crypto_core_ristretto255_BYTES],
 530                                 uint8_t (*kc0_commitments)[][crypto_core_ristretto255_BYTES],
 531                                 uint8_t (*k0p_commitments)[][crypto_core_ristretto255_BYTES],
 532                                 uint8_t (*zk_challenge_commitments)[][3][crypto_scalarmult_ristretto255_SCALARBYTES],
 533                                 uint8_t (*zk_challenge_e_i)[][crypto_scalarmult_ristretto255_SCALARBYTES],
 534                                 uint8_t (*k0p_final_commitments)[][crypto_scalarmult_ristretto255_BYTES],
 535                                 uint64_t *last_ts) {
 536    ctx->p_complaints = p_complaints;
 537    memset(ctx->p_complaints, 0, sizeof(uint16_t) * ctx->n*ctx->n);
 538    ctx->y2_complaints = y2_complaints;
 539    memset(ctx->y2_complaints, 0, sizeof(uint16_t) * ctx->n*ctx->n);
 540    ctx->cheaters = cheaters;
 541    memset(*cheaters, 0, cheater_max*sizeof(TOPRF_Update_Cheater));
 542    ctx->cheater_max = cheater_max;
 543    ctx->last_ts = last_ts;
 544    ctx->p_commitments_hashes = p_commitments_hashes;
 545    ctx->p_share_macs = p_share_macs;
 546    ctx->p_commitments = p_commitments;
 547    ctx->kc0_commitments = kc0_commitments;
 548    ctx->k0p_commitments = k0p_commitments;
 549    ctx->zk_challenge_commitments = zk_challenge_commitments;
 550    ctx->zk_challenge_e_i = zk_challenge_e_i;
 551    ctx->k0p_final_commitments = k0p_final_commitments;
 552  #ifdef __ZEPHYR__
 553    uint64_t now = (uint64_t) k_uptime_get();
 554  #else
 555    uint64_t now = (uint64_t)time(NULL);
 556  #endif
 557    for(uint8_t i=0;i<ctx->n;i++) ctx->last_ts[i]=now;
 558  }
 559  
 560  TOPRF_Update_Err toprf_update_start_peer(TOPRF_Update_PeerState *ctx,
 561                                           const uint64_t ts_epsilon,
 562                                           const uint8_t lt_sk[crypto_sign_SECRETKEYBYTES],
 563                                           const uint8_t noise_sk[crypto_scalarmult_SCALARBYTES],
 564                                           const TOPRF_Update_Message *msg0,
 565                                           uint8_t keyid[toprf_keyid_SIZE],
 566                                           uint8_t stp_ltpk[crypto_sign_PUBLICKEYBYTES]) {
 567    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[?] init1 start peer\x1b[0m\n");
 568    //dkg_dump_msg((const uint8_t*) msg0, toprfupdate_stp_start_msg_SIZE, msg0->from);
 569  
 570    ctx->ts_epsilon = ts_epsilon;
 571    ctx->stp_last_ts = 0;
 572  
 573    int ret = toprf_recv_msg((const uint8_t*) msg0, toprfupdate_stp_start_msg_SIZE, toprfupdate_stp_start_msg, 0, 0xff, msg0->data, msg0->sessionid, ts_epsilon, &ctx->stp_last_ts);
 574    if(0!=ret) return TOPRF_Update_Err_Env+ ret;
 575  
 576    // extract data from message
 577    // we abuse sessionid as a temporary storage for the nonce_stp value, until we have the final sessionid
 578    memcpy(ctx->sessionid, msg0->sessionid, sizeof ctx->sessionid);
 579  
 580    const uint8_t *ptr=msg0->data;
 581    memcpy(stp_ltpk,ptr,crypto_sign_PUBLICKEYBYTES);
 582    ptr+=crypto_sign_PUBLICKEYBYTES + crypto_generichash_BYTES; // also skip DST
 583    memcpy(keyid,ptr,toprf_keyid_SIZE);
 584  
 585    ctx->p_complaints_len = 0;
 586    ctx->my_p_complaints_len = 0;
 587    ctx->cheater_len = 0;
 588    memcpy(ctx->sig_sk, lt_sk, crypto_sign_SECRETKEYBYTES);
 589    memcpy(ctx->noise_sk, noise_sk, crypto_scalarmult_SCALARBYTES);
 590  
 591    crypto_generichash_init(&ctx->transcript_state, NULL, 0, crypto_generichash_BYTES);
 592    crypto_generichash_update(&ctx->transcript_state, (const uint8_t*) "toprf update session transcript", 31);
 593    // feed msg0 into transcript
 594    update_transcript(&ctx->transcript_state, (const uint8_t*) msg0, toprfupdate_stp_start_msg_SIZE);
 595  
 596    ctx->dev = NULL;
 597    ctx->step = TOPRF_Update_Peer_Broadcast_NPK_SIDNonce;
 598  
 599    return TOPRF_Update_Err_OK;
 600  }
 601  
 602  int toprf_update_peer_set_bufs(TOPRF_Update_PeerState *ctx,
 603                                 const uint8_t self,
 604                                 const uint8_t n, const uint8_t t,
 605                                 const TOPRF_Share k0[2],
 606                                 uint8_t (*kc0_commitments)[][crypto_core_ristretto255_BYTES],
 607                                 const uint8_t (*sig_pks)[][crypto_sign_PUBLICKEYBYTES],
 608                                 uint8_t (*peer_noise_pks)[][crypto_scalarmult_BYTES],
 609                                 Noise_XK_session_t *(*noise_outs)[],
 610                                 Noise_XK_session_t *(*noise_ins)[],
 611                                 TOPRF_Share (*p_shares)[][2],
 612                                 uint8_t (*p_commitments)[][crypto_core_ristretto255_BYTES],
 613                                 uint8_t (*p_commitments_hashes)[][toprf_update_commitment_HASHBYTES],
 614                                 uint8_t (*p_share_macs)[][crypto_auth_hmacsha256_BYTES],
 615                                 uint8_t (*encrypted_shares)[][noise_xk_handshake3_SIZE + toprf_update_encrypted_shares_SIZE],
 616                                 TOPRF_Update_Cheater (*cheaters)[], const size_t cheater_max,
 617                                 uint8_t (*lambdas)[][crypto_core_ristretto255_SCALARBYTES],
 618                                 TOPRF_Share (*k0p_shares)[][2],
 619                                 uint8_t (*k0p_commitments)[][crypto_core_ristretto255_BYTES],
 620                                 uint8_t (*zk_challenge_nonce_commitments)[][crypto_scalarmult_ristretto255_BYTES],
 621                                 uint8_t (*zk_challenge_nonces)[][2][crypto_scalarmult_ristretto255_SCALARBYTES],
 622                                 uint8_t (*zk_challenge_commitments)[][3][crypto_scalarmult_ristretto255_SCALARBYTES],
 623                                 uint8_t (*zk_challenge_e_i)[][crypto_scalarmult_ristretto255_SCALARBYTES],
 624                                 uint16_t *p_complaints,
 625                                 uint8_t *my_p_complaints,
 626                                 uint64_t *last_ts) {
 627    if(2>n || t>=n || n>128 || n<2*t+1) return 1;
 628    ctx->index = self;
 629    ctx->n = n;
 630    ctx->t = t;
 631    memcpy((uint8_t*) ctx->kc0_share, (const uint8_t*) k0, sizeof(TOPRF_Share)*2);
 632    ctx->kc0_commitments = kc0_commitments;
 633    ctx->sig_pks = sig_pks;
 634    ctx->peer_noise_pks = peer_noise_pks;
 635  
 636    ctx->noise_outs = noise_outs;
 637    ctx->noise_ins = noise_ins;
 638    ctx->p_shares = p_shares;
 639    ctx->p_commitments = p_commitments;
 640    ctx->p_commitments_hashes = p_commitments_hashes;
 641    ctx->p_share_macs = p_share_macs;
 642    ctx->encrypted_shares = encrypted_shares;
 643    ctx->lambdas = lambdas;
 644    ctx->k0p_shares = k0p_shares;
 645    ctx->k0p_commitments = k0p_commitments;
 646    ctx->zk_challenge_nonce_commitments = zk_challenge_nonce_commitments;
 647    ctx->zk_challenge_nonces = zk_challenge_nonces;
 648    ctx->zk_challenge_commitments = zk_challenge_commitments;
 649    ctx->zk_challenge_e_i = zk_challenge_e_i;
 650    ctx->p_complaints = p_complaints;
 651    memset(ctx->p_complaints, 0, sizeof(uint16_t) * n);
 652    ctx->my_p_complaints = my_p_complaints;
 653    memset(ctx->my_p_complaints, 0, n);
 654    ctx->cheaters = cheaters;
 655    memset(cheaters,0,sizeof(TOPRF_Update_Cheater)*cheater_max);
 656    ctx->cheater_max = cheater_max;
 657    ctx->last_ts = last_ts;
 658    for(uint8_t i=0;i<ctx->n;i++) ctx->last_ts[i]=0;
 659    return 0;
 660  }
 661  
 662  #define toprfupdate_peer_init_msg_SIZE (sizeof(TOPRF_Update_Message) + dkg_sessionid_SIZE + crypto_core_ristretto255_BYTES)
 663  static TOPRF_Update_Err peer_step1_handler(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
 664    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] init2 send msg1 containing session id nonce\x1b[0m\n", ctx->index);
 665    if(output_len != toprfupdate_peer_init_msg_SIZE) return TOPRF_Update_Err_OSize;
 666  
 667    uint8_t *wptr = ((TOPRF_Update_Message *) output)->data;
 668    randombytes_buf(wptr, dkg_sessionid_SIZE);
 669    wptr+=dkg_sessionid_SIZE;
 670    if(0!=dkg_vss_commit(ctx->kc0_share[0].value, ctx->kc0_share[1].value,wptr)) return TOPRF_Update_Err_VSSCommit;
 671    if(0!=toprf_send_msg(output, toprfupdate_peer_init_msg_SIZE, toprfupdate_peer_init_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
 672  
 673    ctx->step = TOPRF_Update_Peer_Rcv_NPK_SIDNonce;
 674  
 675    return TOPRF_Update_Err_OK;
 676  }
 677  
 678  static TOPRF_Update_Err stp_step2_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 679    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] init3 broadcast msg1 containing session id nonces of peers\x1b[0m\n");
 680    if(input_len  != toprfupdate_peer_init_msg_SIZE * ctx->n) return TOPRF_Update_Err_ISize;
 681    if(output_len != toprfupdate_peer_init_msg_SIZE * ctx->n + sizeof(TOPRF_Update_Message)) return TOPRF_Update_Err_OSize;
 682  
 683    crypto_generichash_state sid_state;
 684    crypto_generichash_init(&sid_state, NULL, 0, dkg_sessionid_SIZE);
 685    crypto_generichash_update(&sid_state, ctx->sessionid, dkg_sessionid_SIZE);
 686  
 687    const uint8_t *ptr = input;
 688    uint8_t *wptr = ((TOPRF_Update_Message *) output)->data;
 689    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_init_msg_SIZE) {
 690      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
 691      if(stp_recv_msg(ctx,ptr,toprfupdate_peer_init_msg_SIZE,toprfupdate_peer_init_msg,i+1,0xff)) continue;
 692      const uint8_t *dptr = msg->data;
 693      crypto_generichash_update(&sid_state, dptr, dkg_sessionid_SIZE);
 694      dptr+=dkg_sessionid_SIZE;
 695      memcpy((*ctx->kc0_commitments)[i], dptr, crypto_core_ristretto255_BYTES);
 696  
 697      memcpy(wptr, ptr, toprfupdate_peer_init_msg_SIZE);
 698      wptr+=toprfupdate_peer_init_msg_SIZE;
 699    }
 700    if(ctx->cheater_len>0) return TOPRF_Update_Err_CheatersFound;
 701  
 702    crypto_generichash_final(&sid_state,ctx->sessionid,sizeof ctx->sessionid);
 703  
 704    if(0!=toprf_send_msg(output, output_len, toprfupdate_stp_bc_init_msg, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
 705    update_transcript(&ctx->transcript_state, output, output_len);
 706  
 707    ctx->step = TOPRF_Update_STP_Route_Noise_Handshakes1;
 708    return TOPRF_Update_Err_OK;
 709  }
 710  
 711  #define toprfupdate_peer_ake1_msg_SIZE (sizeof(TOPRF_Update_Message) + noise_xk_handshake1_SIZE)
 712  static TOPRF_Update_Err peer_step3_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 713    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] noise1 receive peers session nonces, finalize sessionid, start noise sessions\x1b[0m\n", ctx->index);
 714    if(input_len != toprfupdate_peer_init_msg_SIZE * ctx->n + sizeof(TOPRF_Update_Message)) return TOPRF_Update_Err_ISize;
 715    if(output_len != toprfupdate_peer_ake1_msg_SIZE * ctx->n) return TOPRF_Update_Err_OSize;
 716  
 717    const TOPRF_Update_Message* msg2 = (const TOPRF_Update_Message*) input;
 718    int ret = toprf_recv_msg(input, input_len, toprfupdate_stp_bc_init_msg, 0, 0xff, (*ctx->sig_pks)[0], msg2->sessionid, ctx->ts_epsilon, &ctx->stp_last_ts);
 719    if(0!=ret) return TOPRF_Update_Err_BroadcastEnv+ret;
 720  
 721    update_transcript(&ctx->transcript_state, input, input_len);
 722  
 723    // create noise device
 724    uint8_t iname[15];
 725    snprintf((char*) iname, sizeof iname, "toprf peer %02x", ctx->index);
 726    uint8_t dummy[32]={0}; // the following function needs a deserialization key, which we never use.
 727  
 728    ctx->dev = Noise_XK_device_create(13, (uint8_t*) "toprf p2p v0.1", iname, dummy, ctx->noise_sk);
 729  
 730    crypto_generichash_state sid_state;
 731    crypto_generichash_init(&sid_state, NULL, 0, dkg_sessionid_SIZE);
 732    crypto_generichash_update(&sid_state, ctx->sessionid, dkg_sessionid_SIZE);
 733  
 734    const uint8_t *ptr = msg2->data;
 735    for(uint8_t i=0;i<ctx->n;i++, ptr+=toprfupdate_peer_init_msg_SIZE) {
 736      const TOPRF_Update_Message* msg1 = (const TOPRF_Update_Message*) ptr;
 737      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_init_msg_SIZE,toprfupdate_peer_init_msg,i+1,0xff)) continue;
 738      const uint8_t *dptr = msg1->data;
 739      // extract peer sig and noise pk
 740      crypto_generichash_update(&sid_state, dptr, dkg_sessionid_SIZE);
 741      dptr+=dkg_sessionid_SIZE;
 742      if(memcmp(dptr, (*ctx->kc0_commitments)[i], crypto_core_ristretto255_BYTES)!=0) {
 743        return TOPRF_Update_Err_CommmitmentsMismatch;
 744      }
 745    }
 746  
 747    if(ctx->cheater_len>0) return TOPRF_Update_Err_CheatersFound;
 748  
 749    crypto_generichash_final(&sid_state,ctx->sessionid,sizeof ctx->sessionid);
 750    if(memcmp(ctx->sessionid, msg2->sessionid, dkg_sessionid_SIZE)!=0) {
 751      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "invalid sessionid generated\n");
 752      return TOPRF_Update_Err_InvSessionID;
 753    }
 754  
 755    uint8_t *wptr = output;
 756    for(uint8_t i=0;i<ctx->n;i++, wptr+=toprfupdate_peer_ake1_msg_SIZE) {
 757      TOPRF_Update_Message *msg3 = (TOPRF_Update_Message *) wptr;
 758      uint8_t rname[15];
 759      snprintf((char*) rname, sizeof rname, "toprf peer %02x", i+1);
 760      if(0!=dkg_init_noise_handshake(ctx->index, ctx->dev, (*ctx->peer_noise_pks)[i], rname, &(*ctx->noise_outs)[i], msg3->data)) return TOPRF_Update_Err_Noise;
 761      if(0!=toprf_send_msg(wptr, toprfupdate_peer_ake1_msg_SIZE, toprfupdate_peer_ake1_msg, ctx->index, i+1, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
 762    }
 763  
 764    ctx->step = TOPRF_Update_Peer_Noise_Handshake;
 765  
 766    return TOPRF_Update_Err_OK;
 767  }
 768  
 769  
 770  static TOPRF_Update_Err stp_step4_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 771    return stp_route(ctx, input, input_len, output, output_len,
 772                     "noise2 route p2p noise handshakes to peers",
 773                     ctx->n, ctx->n, toprfupdate_peer_ake1_msg, toprfupdate_peer_ake1_msg_SIZE, TOPRF_Update_STP_Route_Noise_Handshakes2);
 774  }
 775  
 776  #define toprfupdate_peer_ake2_msg_SIZE (sizeof(TOPRF_Update_Message) + noise_xk_handshake2_SIZE)
 777  static TOPRF_Update_Err peer_step5_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 778    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] noise3 receive session requests\x1b[0m\n", ctx->index);
 779    if(input_len != toprfupdate_peer_ake1_msg_SIZE * ctx->n) return TOPRF_Update_Err_ISize;
 780    if(output_len != toprfupdate_peer_ake2_msg_SIZE * ctx->n) return TOPRF_Update_Err_OSize;
 781  
 782    const uint8_t *ptr = input;
 783    uint8_t *wptr = output;
 784    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_ake1_msg_SIZE,wptr+=toprfupdate_peer_ake2_msg_SIZE) {
 785      TOPRF_Update_Message* msg3 = (TOPRF_Update_Message*) ptr;
 786      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_ake1_msg_SIZE,toprfupdate_peer_ake1_msg,i+1,ctx->index)) continue;
 787  
 788      // respond to noise handshake request
 789      TOPRF_Update_Message *msg4 = (TOPRF_Update_Message *) wptr;
 790      uint8_t rname[15];
 791      snprintf((char*) rname, sizeof rname, "toprf peer %02x", i+1);
 792      if(0!=dkg_respond_noise_handshake(ctx->index, ctx->dev, rname, &(*ctx->noise_ins)[i], msg3->data, msg4->data)) return TOPRF_Update_Err_Noise;
 793      if(0!=toprf_send_msg(wptr, toprfupdate_peer_ake2_msg_SIZE, toprfupdate_peer_ake2_msg, ctx->index, i+1, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
 794    }
 795    if(ctx->cheater_len>0) return TOPRF_Update_Err_CheatersFound;
 796  
 797    ctx->step=TOPRF_Update_Peer_Finish_Noise_Handshake;
 798    return TOPRF_Update_Err_OK;
 799  }
 800  
 801  static TOPRF_Update_Err stp_step6_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 802    return stp_route(ctx, input, input_len, output, output_len,
 803                     "noise4 route p2p noise handshakes to peers",
 804                     ctx->n, ctx->n, toprfupdate_peer_ake2_msg, toprfupdate_peer_ake2_msg_SIZE, TOPRF_Update_STP_Broadcast_DKG_Hash_Commitments);
 805  }
 806  
 807  static void hash_commitments(const TOPRF_Update_PeerState *ctx,
 808                               const uint8_t c_len,
 809                               const uint8_t commitments[c_len][crypto_core_ristretto255_BYTES],
 810                               uint8_t **wptr) {
 811    crypto_generichash(*wptr, toprf_update_commitment_HASHBYTES, (uint8_t*) commitments, crypto_core_ristretto255_BYTES*c_len, NULL, 0);
 812    if(liboprf_log_file!=NULL) {
 813      dump(*wptr, toprf_update_commitment_HASHBYTES, "[%d] commitment hash", ctx->index);
 814      dump((uint8_t*) commitments, crypto_core_ristretto255_BYTES*c_len, "[%d] committed", ctx->index);
 815    }
 816    *wptr+=toprf_update_commitment_HASHBYTES;
 817  }
 818  
 819  static TOPRF_Update_Err dkg1(TOPRF_Update_PeerState *ctx, const uint8_t n,
 820                               const char *type,
 821                               const uint8_t secret[crypto_core_ristretto255_SCALARBYTES],
 822                               TOPRF_Share shares[n][2],
 823                               uint8_t commitments[n][crypto_core_ristretto255_BYTES],
 824                               uint8_t **wptr) {
 825    // start DKG
 826    if(dkg_vss_share(ctx->n, ctx->t, secret, commitments, shares, NULL)) {
 827      return TOPRF_Update_Err_VSSShare;
 828    }
 829  
 830  #ifdef UNITTEST_CORRUPT
 831    corrupt_vsps_t1(ctx,1, ctx->p_shares, ctx->p_commitments);
 832    //corrupt_commitment(ctx,2,ctx->p_commitments);
 833    //corrupt_commitment(ctx,3,ctx->p_commitments);
 834    //corrupt_wrongshare_correct_commitment(ctx,4,2,ctx->p_shares,ctx->p_commitments);
 835    //corrupt_share(ctx,5,3,1,ctx->p_shares);
 836    //corrupt_share(ctx,5,2,0,ctx->p_shares);
 837  #endif // UNITTEST_CORRUPT
 838  
 839    if(liboprf_log_file!=NULL) {
 840      dump((const uint8_t*) commitments, crypto_core_ristretto255_BYTES*ctx->n, "[%d] dealer %s commitments", ctx->index, type);
 841    }
 842    hash_commitments(ctx,ctx->n,commitments,wptr);
 843  
 844    return TOPRF_Update_Err_OK;
 845  }
 846  
 847  static void derive_key(const Noise_XK_session_t *noise_session,
 848                         const uint8_t i,
 849                         const char *type,
 850                         uint8_t key[crypto_auth_KEYBYTES]) {
 851    const uint8_t *mk = Noise_XK_session_get_key(noise_session);
 852    char kdf_context[64];
 853    size_t context_len = (size_t) snprintf(kdf_context, sizeof(kdf_context), "key for encryption of %s share for %d", type, i);
 854    crypto_kdf_hkdf_sha256_expand(key, crypto_auth_KEYBYTES, kdf_context, context_len, mk);
 855  }
 856  
 857  static void encrypt_shares(const TOPRF_Update_PeerState *ctx,
 858                             const uint8_t i,
 859                             const char *type,
 860                             const TOPRF_Share share[2],
 861                             const uint8_t nonce_ctr,
 862                             uint8_t hmac[crypto_auth_hmacsha256_BYTES],
 863                             uint8_t ct[toprf_update_encrypted_shares_SIZE]) {
 864  
 865    uint8_t key[crypto_auth_KEYBYTES];
 866    derive_key((*ctx->noise_outs)[i],i+1,type,key);
 867    uint8_t nonce[crypto_stream_NONCEBYTES]={0};
 868    nonce[0]=nonce_ctr;
 869  
 870    crypto_stream_xor(ct, (const uint8_t*) share, TOPRF_Share_BYTES*2, nonce, key);
 871    crypto_auth(hmac, ct, toprf_update_encrypted_shares_SIZE, key);
 872    if(liboprf_log_file!=NULL) {
 873      //dump(key, sizeof key, "[%d] key for %s share of p_%d", ctx->index, type, i+1);
 874      //dump(ct, toprf_update_encrypted_shares_SIZE, "[%d] encrypted %s share of p_%d", ctx->index, type, i+1);
 875      //dump(hmac, crypto_auth_hmacsha256_BYTES, "[%d] hmac for %s share of p_%d", ctx->index, type, i+1);
 876    }
 877  }
 878  
 879  #define toprfupdate_peer_dkg1_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + (toprf_update_commitment_HASHBYTES + ctx->n * crypto_auth_hmacsha256_BYTES))
 880  static TOPRF_Update_Err peer_dkg1_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 881    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] noise5 finish session handshake, start core update with dkg for p\x1b[0m\n", ctx->index);
 882    if(input_len != toprfupdate_peer_ake2_msg_SIZE * ctx->n) return TOPRF_Update_Err_ISize;
 883    if(output_len != toprfupdate_peer_dkg1_msg_SIZE(ctx)) return TOPRF_Update_Err_OSize;
 884  
 885    const uint8_t *ptr = input;
 886    for(uint8_t i=0;i<ctx->n;i++, ptr+=toprfupdate_peer_ake2_msg_SIZE) {
 887      TOPRF_Update_Message* msg4 = (TOPRF_Update_Message*) ptr;
 888      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_ake2_msg_SIZE,toprfupdate_peer_ake2_msg,i+1,ctx->index)) continue;
 889      // process final step of noise handshake
 890      if(0!=dkg_finish_noise_handshake(ctx->index, ctx->dev, &(*ctx->noise_outs)[i], msg4->data)) return TOPRF_Update_Err_Noise;
 891    }
 892    if(ctx->cheater_len>0) return TOPRF_Update_Err_CheatersFound;
 893  
 894    TOPRF_Update_Message* msg5 = (TOPRF_Update_Message*) output;
 895    uint8_t *wptr = msg5->data;
 896    uint8_t *dptr = (uint8_t*) (*ctx->encrypted_shares);
 897  
 898    TOPRF_Update_Err ret;
 899    ret = dkg1(ctx, ctx->n, "p", NULL, (*ctx->p_shares), (*ctx->p_commitments), &wptr);
 900    if(ret != TOPRF_Update_Err_OK) return ret;
 901  
 902    for(uint8_t i=0;i<ctx->n;i++) {
 903      // we need to send an empty packet, so that the handshake completes
 904      // and we have a final symetric key, the key during the handshake changes, only
 905      // when the handshake completes does the key become static.
 906      // this is important, so that when there are complaints, we can disclose the key.
 907      uint8_t empty[1]={0}; // would love to do [0] but that is undefined c
 908      if(0!=dkg_noise_encrypt(empty, 0, dptr, noise_xk_handshake3_SIZE, &(*ctx->noise_outs)[i])) return TOPRF_Update_Err_NoiseEncrypt;
 909      dptr+=noise_xk_handshake3_SIZE;
 910  
 911      // we might need to disclose the encryption key for the p shares,
 912      // but we don't want even the STP to learn more than necessary for
 913      // proving the correct encryption of the shares, hence the
 914      // following: we extract the current noise key, hkdf() it into two
 915      // dedicated subkeys, encrypt the shares using a stream cipher,
 916      // and calculate an hmac over these with the subkeys.
 917      encrypt_shares(ctx,i,"p",(*ctx->p_shares)[i],0,wptr,dptr);
 918      dptr+=toprf_update_encrypted_shares_SIZE;
 919      wptr+=crypto_auth_hmacsha256_BYTES;
 920    }
 921  
 922    //broadcast dealer_commitments
 923  
 924    if(0!=toprf_send_msg(output, toprfupdate_peer_dkg1_msg_SIZE(ctx), toprfupdate_peer_dkg1_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
 925  
 926    ctx->step = TOPRF_Update_Peer_Rcv_CHashes_Send_Commitments;
 927  
 928    return TOPRF_Update_Err_OK;
 929  }
 930  
 931  static TOPRF_Update_Err stp_dkg1_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 932    TOPRF_Update_Err ret;
 933    ret = stp_broadcast(ctx, input, input_len, output, output_len,
 934                        "dkg1 broadcast commitment hashes and share hmacs for p dkg step 1",
 935                        ctx->n, toprfupdate_peer_dkg1_msg_SIZE(ctx), toprfupdate_peer_dkg1_msg, TOPRF_Update_STP_Broadcast_DKG_Commitments);
 936    if(ret != TOPRF_Update_Err_OK) return ret;
 937    const uint8_t *ptr = input;
 938    for(unsigned i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_dkg1_msg_SIZE(ctx)) {
 939      const DKG_Message* msg = (const DKG_Message*) ptr;
 940      const uint8_t *dptr=msg->data;
 941      memcpy((*ctx->p_commitments_hashes)[i], dptr, toprf_update_commitment_HASHBYTES);
 942      dptr+=toprf_update_commitment_HASHBYTES;
 943  
 944      for(uint8_t j=0;j<ctx->n;j++) {
 945        memcpy((*ctx->p_share_macs)[i*ctx->n+j], dptr, crypto_auth_hmacsha256_BYTES);
 946        dptr+=crypto_auth_hmacsha256_BYTES;
 947      }
 948    }
 949    return TOPRF_Update_Err_OK;
 950  }
 951  
 952  #define toprfupdate_peer_dkg2_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + crypto_core_ristretto255_BYTES * ctx->n)
 953  static TOPRF_Update_Err peer_dkg2_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 954    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] dkg2 receive commitment hashes, broadcast commitments\x1b[0m\n", ctx->index);
 955    if(input_len != sizeof(TOPRF_Update_Message) + toprfupdate_peer_dkg1_msg_SIZE(ctx) * ctx->n) return TOPRF_Update_Err_ISize;
 956    if(output_len != toprfupdate_peer_dkg2_msg_SIZE(ctx)) return TOPRF_Update_Err_OSize;
 957  
 958    // verify STP message envelope
 959    const uint8_t *ptr=NULL;
 960    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_dkg1_msg,&ptr);
 961    if(ret!=TOPRF_Update_Err_OK) return ret;
 962  
 963    for(uint8_t i=0;i<ctx->n;i++, ptr+=toprfupdate_peer_dkg1_msg_SIZE(ctx)) {
 964      const TOPRF_Update_Message* msg5 = (const TOPRF_Update_Message*) ptr;
 965      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_dkg1_msg_SIZE(ctx),toprfupdate_peer_dkg1_msg,i+1,0xff)) continue;
 966  
 967      const uint8_t *dptr=msg5->data;
 968      // extract peer p commitment hash
 969      memcpy((*ctx->p_commitments_hashes)[i], dptr, toprf_update_commitment_HASHBYTES);
 970      dptr+=toprf_update_commitment_HASHBYTES;
 971  
 972  
 973      for(uint8_t j=0;j<ctx->n;j++) {
 974        // extract and store encrypted p share mac
 975        memcpy((*ctx->p_share_macs)[j*ctx->n + i], dptr, crypto_auth_hmacsha256_BYTES);
 976        //dump(dptr, crypto_auth_hmacsha256_BYTES, "[%d] p   share macs [%d,%d]", ctx->index, j+1, i+1);
 977        dptr+=crypto_auth_hmacsha256_BYTES;
 978      }
 979  
 980      if(liboprf_log_file!=NULL) {
 981        dump((*ctx->p_commitments_hashes)[i], toprf_update_commitment_HASHBYTES, "[%d] p   commitment hash [%d]", ctx->index, i+1);
 982      }
 983    }
 984    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
 985  
 986    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
 987    uint8_t *wptr = msg->data;
 988    // we stashed our commitments temporarily in k_commitments
 989    memcpy(wptr, (*ctx->p_commitments), ctx->n * crypto_core_ristretto255_BYTES);
 990    //broadcast dealer_commitments
 991    if(0!=toprf_send_msg(output, toprfupdate_peer_dkg2_msg_SIZE(ctx), toprfupdate_peer_dkg2_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
 992  
 993    ctx->step = TOPRF_Update_Peer_Rcv_Commitments_Send_Shares;
 994  
 995    return TOPRF_Update_Err_OK;
 996  }
 997  
 998  static TOPRF_Update_Err stp_vsps_check(TOPRF_Update_STPState *ctx,
 999                                         const char *type,
1000                                         const uint8_t dealers,
1001                                         const uint8_t clen,
1002                                         const uint8_t (*ctx_commitments)[][crypto_core_ristretto255_BYTES]) {
1003    TOPRF_Update_Err ret;
1004    const uint8_t (*c)[dealers][clen][crypto_core_ristretto255_BYTES] = (const uint8_t (*)[dealers][clen][crypto_core_ristretto255_BYTES]) ctx_commitments;
1005    // calculate preliminary final commitments
1006    uint8_t kcom[clen][crypto_core_ristretto255_BYTES];
1007    for(unsigned i=0;i<clen;i++) {
1008      memcpy(kcom[i], (*c)[0][i], crypto_scalarmult_ristretto255_BYTES);
1009      for(unsigned j=1;j<dealers;j++) {
1010        crypto_core_ristretto255_add(kcom[i], kcom[i], (*c)[j][i]);
1011      }
1012    }
1013  
1014    uint8_t fails_len=0;
1015    uint8_t fails[dealers];
1016    memset(fails,0,dealers);
1017  
1018    ret = ft_or_full_vsps(clen, ctx->t, dealers, 0, kcom, c,
1019                          "VSPS failed k during DKG, doing full VSPS check on all peers",
1020                          "VSPS failed k",
1021                          "ERROR, could not find any dealer commitments that fail the VSPS check",
1022                          &fails_len, fails);
1023    if(ret!=TOPRF_Update_Err_OK) {
1024      return ret;
1025    }
1026  
1027    for(unsigned i=0;i<fails_len;i++) {
1028      if(stp_add_cheater(ctx,1,fails[i],0) == NULL) {
1029        return TOPRF_Update_Err_CheatersFull;
1030      }
1031    }
1032  
1033    if(ctx->n - fails_len < 2) {
1034      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[!] less than 2 honest %s dealers: %d \n"NORMAL, type, ctx->n - fails_len);
1035      if(stp_add_cheater(ctx,2,0,0) == NULL) {
1036        return TOPRF_Update_Err_CheatersFull;
1037      }
1038    }
1039    if(fails_len >= ctx->t) {
1040      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[!] more than t %s cheaters (t=%d, cheaters=%d)\n"NORMAL, type, ctx->t, fails_len);
1041      if(stp_add_cheater(ctx,3,fails_len,0) == NULL) {
1042        return TOPRF_Update_Err_CheatersFull;
1043      }
1044    }
1045    return TOPRF_Update_Err_OK;
1046  }
1047  
1048  static TOPRF_Update_Err stp_check_chash(TOPRF_Update_STPState *ctx,
1049                                          const uint8_t i,
1050                                          const char *type,
1051                                          const uint8_t dealers,
1052                                          const uint8_t clen,
1053                                          const uint8_t *commitments,
1054                                          const uint8_t (*commitments_hashes)[][toprf_update_commitment_HASHBYTES],
1055                                          uint8_t (*ctx_commitments)[][crypto_core_ristretto255_BYTES]) {
1056    uint8_t (*c)[dealers][clen][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][clen][crypto_core_ristretto255_BYTES]) ctx_commitments;
1057    uint8_t chash[toprf_update_commitment_HASHBYTES];
1058    crypto_generichash(chash, toprf_update_commitment_HASHBYTES, commitments, crypto_core_ristretto255_BYTES*clen, NULL, 0);
1059    if(memcmp(chash, (*commitments_hashes)[i], toprf_update_commitment_HASHBYTES)!=0) {
1060      dump((*commitments_hashes)[i], toprf_update_commitment_HASHBYTES, "[%d] commitment hash", i+1);
1061      dump(commitments, crypto_core_ristretto255_BYTES*clen, "[%d] committed", i+1);
1062      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[!] failed to verify hash for %s commitments of dealer %d\n"NORMAL, type, i+1);
1063      if(stp_add_cheater(ctx, 4, i+1, 0) == NULL) {
1064        return TOPRF_Update_Err_CheatersFull;
1065      }
1066    }
1067    memcpy((*c)[i], commitments, crypto_core_ristretto255_BYTES * clen);
1068  
1069    return TOPRF_Update_Err_OK;
1070  }
1071  
1072  static TOPRF_Update_Err stp_dkg2_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1073    TOPRF_Update_Err ret = stp_broadcast(ctx, input, input_len, output, output_len,
1074                                         "dkg3 broadcast commitments dkg step 1",
1075                                         ctx->n, toprfupdate_peer_dkg2_msg_SIZE(ctx), toprfupdate_peer_dkg2_msg, TOPRF_Update_STP_Route_Encrypted_Shares);
1076    if(ret!=TOPRF_Update_Err_OK) return ret;
1077    const uint8_t *ptr = input;
1078  
1079    // fixup step, that has already been advanced in the call to stp_broadcast above.
1080    uint8_t step = ctx->step;
1081    ctx->step = TOPRF_Update_STP_Broadcast_DKG_Commitments;
1082  
1083    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_dkg2_msg_SIZE(ctx)) {
1084      const DKG_Message* msg = (const DKG_Message*) ptr;
1085      const uint8_t *dptr = msg->data;
1086      ret = stp_check_chash(ctx,i,"p",ctx->n, ctx->n, dptr,ctx->p_commitments_hashes,ctx->p_commitments);
1087      if(TOPRF_Update_Err_OK!=ret) {
1088        ctx->step=step;
1089        return ret;
1090      }
1091    }
1092    ret = stp_vsps_check(ctx, "p", ctx->n, ctx->n, ctx->p_commitments);
1093  
1094    ctx->step=step;
1095    return ret;
1096  }
1097  
1098  #define toprfupdate_peer_dkg3_msg_SIZE (sizeof(TOPRF_Update_Message) /* header */                      \
1099                                          + noise_xk_handshake3_SIZE /* 4th&final noise handshake */     \
1100                                          + toprf_update_encrypted_shares_SIZE                           )
1101  static TOPRF_Update_Err peer_dkg3_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1102    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] dkg4 receive commitments & distribute encrypted shares\x1b[0m\n", ctx->index);
1103    if(input_len != sizeof(TOPRF_Update_Message) + toprfupdate_peer_dkg2_msg_SIZE(ctx) * ctx->n) return TOPRF_Update_Err_ISize;
1104    if(output_len != ctx->n * toprfupdate_peer_dkg3_msg_SIZE) return TOPRF_Update_Err_OSize;
1105  
1106    // verify STP message envelope
1107    const uint8_t *ptr=NULL;
1108    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_dkg2_msg,&ptr);
1109    if(ret!=TOPRF_Update_Err_OK) return ret;
1110  
1111    for(uint8_t i=0;i<ctx->n;i++, ptr+=toprfupdate_peer_dkg2_msg_SIZE(ctx)) {
1112      const TOPRF_Update_Message* msg5 = (const TOPRF_Update_Message*) ptr;
1113      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_dkg2_msg_SIZE(ctx),toprfupdate_peer_dkg2_msg,i+1,0xff)) continue;
1114  
1115      // extract peer commitments
1116      const uint8_t *dptr = msg5->data;
1117      memcpy((*ctx->p_commitments)[i*ctx->n], dptr, crypto_core_ristretto255_BYTES * ctx->n);
1118      if(liboprf_log_file!=NULL) {
1119        dump((*ctx->p_commitments)[i*ctx->n], crypto_core_ristretto255_BYTES*ctx->n, "[%d] p commitments [%d]", ctx->index, i+1);
1120      }
1121  
1122      // verify against commitment hashes
1123      uint8_t chash[toprf_update_commitment_HASHBYTES];
1124      crypto_generichash(chash, toprf_update_commitment_HASHBYTES, (*ctx->p_commitments)[i*ctx->n], crypto_core_ristretto255_BYTES*ctx->n, NULL, 0);
1125      if(memcmp(chash, (*ctx->p_commitments_hashes)[i], toprf_update_commitment_HASHBYTES)!=0) {
1126        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] failed to verify hash for p commitments of dealer %d\n"NORMAL, ctx->index, i+1);
1127        if(peer_add_cheater(ctx, 2, i+1, 0) == NULL) return TOPRF_Update_Err_CheatersFull;
1128      }
1129    }
1130    // yes we abort here if the hash commitment fails.
1131    if(ctx->cheater_len>0) return TOPRF_Update_Err_CheatersFound;
1132    // we could check VSPS here, but that would complicate msg size
1133    // calculation taking into account demoted dealers, so we do it
1134    // after the shares have been dealt.
1135  
1136    uint8_t *wptr = output;
1137    for(uint8_t i=0;i<ctx->n;i++, wptr+=toprfupdate_peer_dkg3_msg_SIZE) {
1138      TOPRF_Update_Message *msg7 = (TOPRF_Update_Message *) wptr;
1139      memcpy(msg7->data, (*ctx->encrypted_shares)[i], noise_xk_handshake3_SIZE + toprf_update_encrypted_shares_SIZE);
1140  
1141      if(0!=toprf_send_msg(wptr, toprfupdate_peer_dkg3_msg_SIZE, toprfupdate_peer_dkg3_msg, ctx->index, i+1, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1142    }
1143  
1144    ctx->step = TOPRF_Update_Peer_Verify_Commitments;
1145  
1146    return TOPRF_Update_Err_OK;
1147  }
1148  
1149  static TOPRF_Update_Err stp_dkg3_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1150    return stp_route(ctx, input, input_len, output, output_len,
1151                     "dkg4 route shares to peers",
1152                     ctx->n, ctx->n, toprfupdate_peer_dkg3_msg, toprfupdate_peer_dkg3_msg_SIZE, TOPRF_Update_STP_Broadcast_Complaints);
1153  }
1154  
1155  
1156  static TOPRF_Update_Err decrypt_shares(const TOPRF_Update_PeerState *ctx,
1157                                         const uint8_t i,
1158                                         const char *type,
1159                                         const uint8_t hmac[crypto_auth_hmacsha256_BYTES],
1160                                         const uint8_t ct[toprf_update_encrypted_shares_SIZE],
1161                                         const uint8_t nonce_ctr,
1162                                         TOPRF_Share share[2]) {
1163    uint8_t key[crypto_auth_KEYBYTES];
1164    derive_key((*ctx->noise_ins)[i],ctx->index,type,key);
1165    uint8_t nonce[crypto_stream_NONCEBYTES]={0};
1166    nonce[0]=nonce_ctr;
1167  #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
1168    if(0!=crypto_auth_verify(hmac, ct, toprf_update_encrypted_shares_SIZE, key)) {
1169      //dump(key, sizeof key, "[%d] key for %s share of p_%d", ctx->index, type, i+1);
1170      dump(ct, toprf_update_encrypted_shares_SIZE, "[%d] encrypted %s share of p_%d", ctx->index, type, i+1);
1171      return TOPRF_Update_Err_HMac;
1172    }
1173  #endif
1174    crypto_stream_xor((uint8_t*) share, ct, TOPRF_Share_BYTES*2, nonce, key);
1175  
1176    return TOPRF_Update_Err_OK;
1177  }
1178  
1179  static void verify_commitments(const TOPRF_Update_PeerState *ctx,
1180                                 const char *type,
1181                                 const uint8_t dealers,
1182                                 const uint8_t clen,
1183                                 const uint8_t cidx,
1184                                 const uint8_t commitments[][crypto_core_ristretto255_BYTES],
1185                                 const TOPRF_Share (*shares)[][2],
1186                                 uint8_t *fails_len,
1187                                 uint8_t *fails) {
1188    *fails_len=0;
1189    memset(fails, 0, dealers);
1190  
1191    const uint8_t (*c)[clen][crypto_core_ristretto255_BYTES] = (const uint8_t (*)[clen][crypto_core_ristretto255_BYTES]) commitments;
1192    // verify that the shares match the commitment
1193    for(uint8_t i=0;i<dealers;i++) {
1194      if(0!=dkg_vss_verify_commitment(c[i][cidx],(*shares)[i])) {
1195        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file,"\x1b[0;31m[%d] failed to verify %s commitments from %d!\x1b[0m\n", ctx->index, type, i+1);
1196        fails[(*fails_len)++]=i+1;
1197      }
1198    }
1199  
1200    if(liboprf_log_file!=NULL) {
1201      if(*fails_len>0) {
1202        fprintf(liboprf_log_file, RED"[%d] %s commitment fails#: %d -> ", ctx->index, type, *fails_len);
1203        for(unsigned i=0;i<*fails_len;i++) fprintf(liboprf_log_file, "%s%d", (i>0)?", ":"", fails[i]);
1204        fprintf(liboprf_log_file, NORMAL"\n");
1205      } else {
1206        fprintf(liboprf_log_file, GREEN"[%d] no %s commitment fails\n"NORMAL, ctx->index, type);
1207      }
1208    }
1209  }
1210  
1211  #define toprfupdate_peer_verify_shares_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + (size_t)(ctx->n + 1))
1212  static TOPRF_Update_Err peer_verify_shares_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1213    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] dkg-verify1 DKG step 2 - receive shares, verify commitments\x1b[0m\n", ctx->index);
1214    if(input_len != toprfupdate_peer_dkg3_msg_SIZE * ctx->n) return TOPRF_Update_Err_ISize;
1215    if(output_len != toprfupdate_peer_verify_shares_msg_SIZE(ctx)) return TOPRF_Update_Err_OSize;
1216  
1217    const uint8_t *ptr = input;
1218    for(uint8_t i=0;i<ctx->n;i++) {
1219      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_dkg3_msg_SIZE,toprfupdate_peer_dkg3_msg,i+1,ctx->index)) continue;
1220  
1221      const uint8_t *dptr = ((const TOPRF_Update_Message*) ptr)->data;
1222      // decrypt final empty handshake packet
1223      if(0!=dkg_noise_decrypt(dptr, noise_xk_handshake3_SIZE, NULL, 0, &(*ctx->noise_ins)[i])) return TOPRF_Update_Err_NoiseDecrypt;
1224      dptr += noise_xk_handshake3_SIZE;
1225  
1226      TOPRF_Update_Err ret;
1227      ret = decrypt_shares(ctx, i, "p", (*ctx->p_share_macs)[(ctx->index-1)*ctx->n + i], dptr, 0, (*ctx->p_shares)[i]);
1228      if(TOPRF_Update_Err_OK!=ret) {
1229        dump((*ctx->p_share_macs)[(ctx->index-1)*ctx->n + i], crypto_auth_hmacsha256_BYTES, "[%d] p hmac_%d", ctx->index, i+1);
1230        return ret;
1231      }
1232  
1233      ptr+=toprfupdate_peer_dkg3_msg_SIZE;
1234    }
1235    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
1236  
1237    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
1238    uint8_t *fails_len = msg->data;
1239    uint8_t *fails = fails_len+1;
1240    verify_commitments(ctx, "p", ctx->n, ctx->n, ctx->index-1, (*ctx->p_commitments), ctx->p_shares, fails_len, fails);
1241  #ifdef UNITTEST_CORRUPT
1242    corrupt_false_accuse(ctx, 2, 3, fails_len, fails);
1243  #endif //UNITTEST_CORRUPT
1244  
1245    if(0!=toprf_send_msg(output, toprfupdate_peer_verify_shares_msg_SIZE(ctx), toprfupdate_peer_verify_shares_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1246  
1247    ctx->step = TOPRF_Update_Peer_Handle_DKG_Complaints;
1248  
1249    return TOPRF_Update_Err_OK;
1250  }
1251  
1252  #define toprfupdate_stp_bc_verify_shares_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + (toprfupdate_peer_verify_shares_msg_SIZE(ctx) * ctx->n))
1253  static TOPRF_Update_Err stp_verify_shares_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1254    return stp_complaint_handler(ctx, input, input_len, output, output_len,
1255                                 "dkg-verify2 broadcast complaints of peers",
1256                                 ctx->n, toprfupdate_peer_verify_shares_msg_SIZE(ctx),
1257                                 toprfupdate_peer_verify_shares_msg,
1258                                 ctx->n,
1259                                 TOPRF_Update_STP_Broadcast_DKG_Transcripts,
1260                                 TOPRF_Update_STP_Broadcast_DKG_Defenses);
1261  }
1262  
1263  static TOPRF_Update_Err peer_dkg_fork(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len) {
1264    return peer_complaint_handler(ctx, input, input_len,
1265                                  "dkg-verify3 receive complaints broadcast",
1266                                  toprfupdate_peer_verify_shares_msg_SIZE(ctx),
1267                                  toprfupdate_peer_verify_shares_msg,
1268                                  ctx->n,
1269                                  TOPRF_Update_Peer_Finish_DKG,
1270                                  TOPRF_Update_Peer_Defend_DKG_Accusations);
1271  }
1272  
1273  static TOPRF_Update_Err peer_defend(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
1274    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] dkg-defend1 disclose share encryption key\x1b[0m\n", ctx->index);
1275    if(output_len != toprf_update_peer_output_size(ctx)) return TOPRF_Update_Err_OSize;
1276    if(output_len == 0) {
1277      if(liboprf_log_file!=NULL) {
1278        fprintf(liboprf_log_file,"[%d] nothing to defend against, no message to send\n", ctx->index);
1279      }
1280      ctx->step = TOPRF_Update_Peer_Check_Shares;
1281      return 0;
1282    }
1283  
1284    // send out all shares that belong to peers that complained.
1285    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
1286    uint8_t *wptr = msg->data;
1287    for(int i=0;i<ctx->my_p_complaints_len;i++) {
1288      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;36m[%d] defending against p complaint from %d\x1b[0m\n", ctx->index, ctx->my_p_complaints[i]);
1289  
1290      *wptr++ = ctx->my_p_complaints[i];
1291      // reveal key for noise wrapped share sent previously
1292      derive_key((*ctx->noise_outs)[ctx->my_p_complaints[i]-1],ctx->my_p_complaints[i],"p",wptr);
1293      wptr+=dkg_noise_key_SIZE;
1294  
1295      memcpy(wptr, (*ctx->encrypted_shares)[ctx->my_p_complaints[i]-1] + noise_xk_handshake3_SIZE, toprf_update_encrypted_shares_SIZE);
1296      wptr+=toprf_update_encrypted_shares_SIZE;
1297    }
1298  
1299    if(0!=toprf_send_msg(output, output_len, toprfupdate_peer_share_key_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1300  
1301    ctx->step = TOPRF_Update_Peer_Check_Shares;
1302    return TOPRF_Update_Err_OK;
1303  }
1304  
1305  static TOPRF_Update_Err stp_check_defenses(TOPRF_Update_STPState *ctx,
1306                                             const uint8_t dealers,
1307                                             const uint8_t clen,
1308                                             const uint8_t coffset,
1309                                             const unsigned int ctr,
1310                                             const unsigned i,
1311                                             const uint8_t nonce_ctr,
1312                                             const uint8_t (*share_macs)[][crypto_auth_hmacsha256_BYTES],
1313                                             const uint8_t commitments[][crypto_core_ristretto255_BYTES],
1314                                             uint16_t *complaints_len,
1315                                             uint16_t *complaints,
1316                                             const uint8_t **dptr) {
1317    if(ctr>=ctx->n) return TOPRF_Update_Err_OOB;
1318    const uint8_t (*c)[clen][crypto_core_ristretto255_BYTES] = (const uint8_t (*)[clen][crypto_core_ristretto255_BYTES]) commitments;
1319    for(unsigned j=0;j<ctr;j++) {
1320      const uint8_t accused=(uint8_t) i+1U;
1321      const uint8_t accuser=(*dptr)[0];
1322      if(accuser<1 || accuser>ctx->n) return TOPRF_Update_Err_OOB;
1323      const uint8_t *key=(*dptr)+1;
1324      const uint8_t *shares=key+dkg_noise_key_SIZE;
1325      *dptr += 1U + dkg_noise_key_SIZE + toprf_update_encrypted_shares_SIZE;
1326      if(liboprf_log_file!=NULL) {
1327        fprintf(liboprf_log_file,"[!] accused: %d, by %d\n", accused, accuser);
1328        dump(key,dkg_noise_key_SIZE,"key");
1329        dump(shares,toprf_update_encrypted_shares_SIZE,"encrypted shares");
1330      }
1331  
1332  #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
1333      if(0!=crypto_auth_verify((*share_macs)[(accused-1)*ctx->n+(accuser-1)], shares, toprf_update_encrypted_shares_SIZE, key)) {
1334        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file,RED"[!] invalid HMAC on shares of accused: %d, by %d\n"NORMAL, accused, accuser);
1335        if(stp_add_cheater(ctx, 1, accused, accuser) == NULL) return TOPRF_Update_Err_CheatersFull;
1336        complaints[(*complaints_len)++]=accuser << 8 | accused;
1337        continue;
1338      }
1339  #endif
1340      TOPRF_Share share[2];
1341      uint8_t nonce[crypto_stream_NONCEBYTES]={0};
1342      nonce[0]=nonce_ctr;
1343      crypto_stream_xor((uint8_t*) share, shares, TOPRF_Share_BYTES*2, nonce, key);
1344      if(share[0].index != accuser) {
1345        // invalid share index
1346        TOPRF_Update_Cheater* cheater = stp_add_cheater(ctx, 3, accused, accuser);
1347        if(cheater == NULL) return TOPRF_Update_Err_CheatersFull;
1348        cheater->invalid_index = share[0].index;
1349        complaints[(*complaints_len)++]=accuser << 8 | accused;
1350        continue;
1351      }
1352      if(0!=dkg_vss_verify_commitment(c[accused-1][accuser-coffset],share)) {
1353        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file,"\x1b[0;31m[!] failed to verify commitment of accused %d by accuser %d!\x1b[0m\n", accused, accuser);
1354        TOPRF_Update_Cheater* cheater = stp_add_cheater(ctx, 4, accused, accuser);
1355        if(cheater == NULL) return TOPRF_Update_Err_CheatersFull;
1356        cheater->invalid_index = share[0].index;
1357        complaints[(*complaints_len)++]=accuser << 8 | accused;
1358        continue;
1359      } else {
1360        if(liboprf_log_file!=NULL) {
1361          fprintf(liboprf_log_file,GREEN"[!] succeeded to verify commitment of accused %d by accuser %d!\x1b[0m\n", accused, accuser);
1362          dump((uint8_t*) share, sizeof share, "share");
1363          dump(c[accused-1][accuser-coffset], crypto_core_ristretto255_BYTES, "commitment");
1364        }
1365        if(stp_add_cheater(ctx, 5, accuser, accused) == NULL) return TOPRF_Update_Err_CheatersFull;
1366      }
1367    }
1368    return TOPRF_Update_Err_OK;
1369  }
1370  
1371  static TOPRF_Update_Err stp_broadcast_defenses(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1372    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] dkg-defend2 broadcast defenses\x1b[0m\n");
1373    if(input_len != toprf_update_stp_input_size(ctx)) return TOPRF_Update_Err_ISize;
1374    if(output_len != toprf_update_stp_output_size(ctx)) return TOPRF_Update_Err_OSize;
1375  
1376    unsigned int ctr1[ctx->n];
1377    memset(ctr1,0,sizeof(ctr1));
1378    for(int i=0;i<ctx->p_complaints_len;i++) {
1379      const uint8_t peer = (uint8_t) ((ctx->p_complaints[i] & 0xff)-1U);
1380      if(peer>=ctx->n) return TOPRF_Update_Err_OOB;
1381      ctr1[peer]++;
1382    }
1383  
1384    const uint8_t *ptr = input;
1385    uint8_t *wptr = ((TOPRF_Update_Message *) output)->data;
1386    size_t msg_size;
1387    for(uint8_t i=0;i<ctx->n;i++,ptr += msg_size) {
1388      if(ctr1[i]==0) {
1389        msg_size = 0;
1390        continue; // no complaints against this peer
1391      }
1392      msg_size = sizeof(TOPRF_Update_Message) \
1393               + (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
1394      if(stp_recv_msg(ctx,ptr,msg_size,toprfupdate_peer_share_key_msg,i+1,0xff)) continue;
1395  
1396      const TOPRF_Update_Message *msg = (const TOPRF_Update_Message *) ptr;
1397      const uint8_t *dptr = msg->data;
1398  
1399      TOPRF_Update_Err ret;
1400      ret = stp_check_defenses(ctx, ctx->n, ctx->n, 1, ctr1[i], i, 0, ctx->p_share_macs, *ctx->p_commitments, &ctx->p_complaints_len, ctx->p_complaints, &dptr);
1401      if(TOPRF_Update_Err_OK != ret) {
1402        return ret;
1403      }
1404  
1405      memcpy(wptr, ptr, msg_size);
1406      wptr+=msg_size;
1407    }
1408    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
1409  
1410    if(0!=toprf_send_msg(output, output_len, toprfupdate_stp_bc_key_msg, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1411  
1412    // add broadcast msg to transcript
1413    update_transcript(&ctx->transcript_state, output, output_len);
1414  
1415    ctx->step = TOPRF_Update_STP_Broadcast_DKG_Transcripts;
1416  
1417    return TOPRF_Update_Err_OK;
1418  }
1419  
1420  #define toprfupdate_peer_bc_transcript_msg_SIZE (sizeof(TOPRF_Update_Message) + crypto_generichash_BYTES + crypto_core_ristretto255_BYTES*2)
1421  static TOPRF_Update_Err peer_verify_vsps(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len);
1422  
1423  static TOPRF_Update_Err check_defenses(TOPRF_Update_PeerState *ctx,
1424                                         const uint8_t dealers,
1425                                         const uint8_t clen,
1426                                         const uint8_t coffset,
1427                                         const unsigned int ctr,
1428                                         const uint8_t i,
1429                                         const uint8_t nonce_ctr,
1430                                         const uint8_t (*share_macs)[][crypto_auth_hmacsha256_BYTES],
1431                                         const uint8_t commitments[][crypto_core_ristretto255_BYTES],
1432                                         uint16_t *complaints_len,
1433                                         uint16_t *complaints,
1434                                         const uint8_t **dptr) {
1435    if(ctr>=ctx->n) return TOPRF_Update_Err_OOB;
1436    const uint8_t (*c)[clen][crypto_core_ristretto255_BYTES] = (const uint8_t (*)[clen][crypto_core_ristretto255_BYTES]) commitments;
1437    for(unsigned j=0;j<ctr;j++) {
1438      const uint8_t accused=i+1;
1439      const uint8_t accuser=(*dptr)[0];
1440      if(accuser<1 || accuser>ctx->n) return TOPRF_Update_Err_OOB;
1441      const uint8_t *key=(*dptr)+1;
1442      const uint8_t *shares=key+dkg_noise_key_SIZE;
1443      *dptr += 1U + dkg_noise_key_SIZE + toprf_update_encrypted_shares_SIZE;
1444      if(liboprf_log_file!=NULL) {
1445        fprintf(liboprf_log_file,"[%d] accused: %d, by %d\n", ctx->index, accused, accuser);
1446        dump(key,dkg_noise_key_SIZE,"key");
1447        dump(shares,toprf_update_encrypted_shares_SIZE,"encrypted shares");
1448      }
1449  
1450  #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
1451      if(0!=crypto_auth_verify((*share_macs)[(accuser-1)*ctx->n+(accused-1)], shares, toprf_update_encrypted_shares_SIZE, key)) {
1452        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file,RED"[%d] invalid HMAC on shares of accused: %d, by %d\n"NORMAL, ctx->index, accused, accuser);
1453        if(peer_add_cheater(ctx, 1, accused, accuser) == NULL) return TOPRF_Update_Err_CheatersFull;
1454        complaints[(*complaints_len)++]=accuser << 8 | accused;
1455        continue;
1456      }
1457  #endif
1458      TOPRF_Share share[2];
1459      uint8_t nonce[crypto_stream_NONCEBYTES]={0};
1460      nonce[0]=nonce_ctr;
1461      crypto_stream_xor((uint8_t*) share, shares, TOPRF_Share_BYTES*2, nonce, key);
1462      if(share[0].index != accuser) {
1463        // invalid share index
1464        TOPRF_Update_Cheater* cheater = peer_add_cheater(ctx, 3, accused, accuser);
1465        if(cheater == NULL) return TOPRF_Update_Err_CheatersFull;
1466        cheater->invalid_index = share[0].index;
1467        complaints[(*complaints_len)++]=accuser << 8 | accused;
1468        continue;
1469      }
1470      if(0!=dkg_vss_verify_commitment(c[accused-1][accuser-coffset],share)) {
1471        if(liboprf_log_file!=NULL) {
1472          fprintf(liboprf_log_file,"\x1b[0;31m[%d] failed to verify commitment of accused %d by accuser %d!\x1b[0m\n", ctx->index, accused, accuser);
1473          dump((uint8_t*) share, sizeof share, "share");
1474          dump(c[accused-1][accuser-1], crypto_core_ristretto255_BYTES, "commitment");
1475        }
1476        TOPRF_Update_Cheater* cheater = peer_add_cheater(ctx, 4, accused, accuser);
1477        if(cheater == NULL) return TOPRF_Update_Err_CheatersFull;
1478        cheater->invalid_index = share[0].index;
1479        complaints[(*complaints_len)++]=accuser << 8 | accused;
1480        continue;
1481      } else {
1482        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file,GREEN"[%d] succeeded to verify commitment of accused %d by accuser %d!\x1b[0m\n", ctx->index, accused, accuser);
1483        if(peer_add_cheater(ctx, 5, accuser, accused) == NULL) return TOPRF_Update_Err_CheatersFull;
1484        //ctx->share_complaints[ctx->share_complaints_len++]=accused;
1485      }
1486    }
1487    return TOPRF_Update_Err_OK;
1488  }
1489  
1490  static TOPRF_Update_Err aggregate_complaints(const uint8_t n, unsigned *ctr, uint16_t *complaints_len, uint16_t *complaints) {
1491    memset(ctr,0,n*sizeof(unsigned));
1492    for(int i=0;i<*complaints_len;i++) {
1493      const uint8_t peer = (uint8_t) (complaints[i] & 0xff)-1;
1494      if(peer>=n) return TOPRF_Update_Err_OOB;
1495      ctr[peer]++;
1496      complaints[i]=0;
1497    }
1498    *complaints_len=0;
1499  
1500    return TOPRF_Update_Err_OK;
1501  }
1502  
1503  static TOPRF_Update_Err peer_check_shares(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1504    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] dkg-defend3 verify disclosed shares\x1b[0m\n", ctx->index);
1505    if(input_len != toprf_update_peer_input_size(ctx)) return TOPRF_Update_Err_ISize;
1506    if(output_len != toprfupdate_peer_bc_transcript_msg_SIZE) return TOPRF_Update_Err_OSize;
1507  
1508    // verify STP message envelope
1509    const uint8_t *ptr=NULL;
1510    TOPRF_Update_Err ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_key_msg,&ptr);
1511    if(ret!=TOPRF_Update_Err_OK) return ret;
1512  
1513    unsigned int ctr1[ctx->n];
1514    aggregate_complaints(ctx->n,ctr1,&ctx->p_complaints_len,ctx->p_complaints);
1515  
1516    size_t msg_size;
1517    for(uint8_t i=0;i<ctx->n;i++,ptr += msg_size) {
1518      if(ctr1[i]==0) {
1519        msg_size = 0;
1520        continue; // no complaints against this peer
1521      }
1522      msg_size = sizeof(TOPRF_Update_Message) \
1523                 + (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
1524  
1525      if(peer_recv_msg(ctx,ptr,msg_size,toprfupdate_peer_share_key_msg,i+1,0xff)) continue;
1526      const TOPRF_Update_Message *msg = (const TOPRF_Update_Message *) ptr;
1527      const uint8_t *dptr = msg->data;
1528  
1529      ret = check_defenses(ctx, ctx->n, ctx->n, 1, ctr1[i], i, 0, ctx->p_share_macs, (*ctx->p_commitments), &ctx->p_complaints_len, ctx->p_complaints, &dptr);
1530      if(TOPRF_Update_Err_OK != ret) return ret;
1531  
1532    }
1533    return peer_verify_vsps(ctx, output, output_len);
1534  }
1535  
1536  static TOPRF_Update_Err finalize_dkg(TOPRF_Update_PeerState *ctx,
1537                                       const char *type,
1538                                       const uint16_t complaints_len,
1539                                       const uint16_t *complaints,
1540                                       const TOPRF_Share (*dealer_shares)[][2],
1541                                       uint8_t (*dealer_commitments)[][crypto_core_ristretto255_BYTES],
1542                                       TOPRF_Share my_share[2],
1543                                       uint8_t my_commitment[crypto_core_ristretto255_BYTES]) {
1544    // 2. Players verify the VSPS property of the sum of the shared secrets by running
1545    //     VSPS-Check on  𝓐_i,..,𝓐_n where
1546    //
1547    //           𝓐_j = Π 𝓐_i,j
1548    //                 i
1549    //
1550    // If this check fails the players run VSPS-Check on each individual
1551    // sharing from step 1. Any player that fails this check is disqualified.
1552    uint8_t (*c)[ctx->n][ctx->n][crypto_core_ristretto255_BYTES] = (uint8_t (*)[ctx->n][ctx->n][crypto_core_ristretto255_BYTES]) dealer_commitments;
1553    uint8_t kcom[ctx->n][crypto_core_ristretto255_BYTES];
1554    for(unsigned i=0;i<ctx->n;i++) {
1555      memcpy(kcom[i], (*c)[0][i], crypto_scalarmult_ristretto255_BYTES);
1556      for(unsigned j=1;j<ctx->n;j++) {
1557        crypto_core_ristretto255_add(kcom[i], kcom[i], (*c)[j][i]);
1558      }
1559    }
1560  
1561    uint8_t fails_len=0;
1562    uint8_t fails[ctx->n];
1563    memset(fails,0,ctx->n);
1564    TOPRF_Update_Err ret = ft_or_full_vsps(ctx->n, ctx->t, ctx->n, ctx->index, kcom, c,
1565                                         "VSPS failed k during DKG, doing full VSPS check on all peers",
1566                                         "VSPS failed k",
1567                                         "ERROR, could not find any dealer commitments that fail the VSPS check",
1568                                         &fails_len, fails);
1569    if(ret!=TOPRF_Update_Err_OK) return ret;
1570    if(ctx->n - fails_len < 2) {
1571      if(liboprf_log_file!=NULL) {
1572        fprintf(liboprf_log_file, RED"[%d] less than 2 honest dealers for %s: %d \n"NORMAL, ctx->index, type, ctx->n - fails_len);
1573        if(peer_add_cheater(ctx, 6, 0, 0) == NULL) return TOPRF_Update_Err_CheatersFull;
1574      }
1575      return TOPRF_Update_Err_NotEnoughDealers;
1576    }
1577    if(fails_len >= ctx->t) {
1578      if(liboprf_log_file!=NULL) {
1579        fprintf(liboprf_log_file, RED"[%d] more than t cheaters for %s (t=%d, cheaters=%d)\n"NORMAL, ctx->index, type, ctx->t, fails_len);
1580        if(peer_add_cheater(ctx, 7, fails_len, 0) == NULL) return TOPRF_Update_Err_CheatersFull;
1581      }
1582      return TOPRF_Update_Err_TooManyCheaters;
1583    }
1584  
1585    // todo persist qual so we can consider who is a dealer for the ft-mult proto
1586    uint8_t qual[ctx->n+1];
1587    uint8_t qual_len=0;
1588    for(uint8_t i=0;i<ctx->n;i++) {
1589      unsigned j,k;
1590      for(j=0;j<fails_len;j++) {
1591        if(fails[j]==i+1) break;
1592      }
1593      for(k=0;k<complaints_len;k++) {
1594        if(complaints[k]==i+1) break;
1595      }
1596      if(j>=fails_len) {
1597        if(k>=complaints_len) qual[qual_len++]=i+1;
1598      } else if(peer_add_cheater(ctx, 8, ctx->index, i+1) == NULL) return TOPRF_Update_Err_CheatersFull;
1599    }
1600    qual[qual_len]=0;
1601    if(liboprf_log_file!=NULL) {
1602      fprintf(liboprf_log_file,"[%d] %s qual is: ", ctx->index, type);
1603      for(unsigned i=0;i<qual_len;i++) fprintf(liboprf_log_file,"%s%d", ((i==0)?"":", "), qual[i]);
1604      fprintf(liboprf_log_file,"\n");
1605    }
1606  
1607    my_share[0].index=ctx->index;
1608    my_share[1].index=ctx->index;
1609    // finalize dkg
1610    if(0!=dkg_vss_finish(ctx->n,qual,(*dealer_shares),ctx->index,my_share, my_commitment)) return TOPRF_Update_Err_DKGFinish;
1611  
1612    return TOPRF_Update_Err_OK;
1613  }
1614  
1615  static TOPRF_Update_Err peer_verify_vsps(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
1616    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] dkg-verify4 VSPS check commitments, calculate share and broadcast transcript and final commitment\x1b[0m\n", ctx->index);
1617    if(output_len != toprfupdate_peer_bc_transcript_msg_SIZE) return TOPRF_Update_Err_OSize;
1618  
1619    TOPRF_Update_Message* msg20 = (TOPRF_Update_Message*) output;
1620    uint8_t *wptr = msg20->data;
1621    crypto_generichash_state transcript_state;
1622    memcpy((uint8_t*) &transcript_state, (const uint8_t*) &ctx->transcript_state, sizeof transcript_state);
1623    crypto_generichash_final(&transcript_state, wptr, crypto_generichash_BYTES);
1624    memcpy(ctx->transcript, wptr, crypto_generichash_BYTES);
1625    wptr+=crypto_generichash_BYTES;
1626  
1627    TOPRF_Update_Err ret;
1628    ret=finalize_dkg(ctx, "p", ctx->p_complaints_len, ctx->p_complaints, ctx->p_shares, ctx->p_commitments, ctx->p_share, wptr);
1629    if(TOPRF_Update_Err_OK != ret) return ret;
1630  
1631    if(0!=toprf_send_msg(output, toprfupdate_peer_bc_transcript_msg_SIZE, toprfupdate_peer_bc_transcript_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1632  
1633    ctx->step = TOPRF_Update_Peer_Confirm_Transcripts;
1634    return TOPRF_Update_Err_OK;
1635  }
1636  
1637  #define toprfupdate_stp_bc_transcript_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + toprfupdate_peer_bc_transcript_msg_SIZE*ctx->n)
1638  static TOPRF_Update_Err stp_bc_transcript_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1639    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] dkg-final1 broadcast DKG transcripts\x1b[0m\n");
1640  
1641    if((toprfupdate_peer_bc_transcript_msg_SIZE * ctx->n) != input_len) return TOPRF_Update_Err_ISize;
1642    if(output_len != toprfupdate_stp_bc_transcript_msg_SIZE(ctx)) return TOPRF_Update_Err_OSize;
1643  
1644    uint8_t transcript_hash[crypto_generichash_BYTES];
1645    crypto_generichash_state transcript_state;
1646    memcpy((uint8_t*) &transcript_state, (const uint8_t*) &ctx->transcript_state, sizeof transcript_state);
1647    crypto_generichash_final(&transcript_state, transcript_hash, crypto_generichash_BYTES);
1648  
1649    size_t cheaters = ctx->cheater_len;
1650    uint8_t *wptr = ((TOPRF_Update_Message *) output)->data;
1651    const uint8_t *ptr = input;
1652    for(uint8_t i=0;i<ctx->n;i++, ptr+=toprfupdate_peer_bc_transcript_msg_SIZE) {
1653      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
1654      if(stp_recv_msg(ctx,ptr,toprfupdate_peer_bc_transcript_msg_SIZE,toprfupdate_peer_bc_transcript_msg,i+1,0xff)) continue;
1655      const uint8_t *dptr=msg->data;
1656  
1657      if(sodium_memcmp(transcript_hash, dptr, sizeof(transcript_hash))!=0) {
1658        if(liboprf_log_file!=NULL) {
1659          fprintf(liboprf_log_file,"\x1b[0;31m[!] failed to verify transcript from %d!\x1b[0m\n", i);
1660        }
1661        if(stp_add_cheater(ctx, 1, i+1, 0) == NULL) return TOPRF_Update_Err_CheatersFull;
1662        continue;
1663      }
1664      dptr+=crypto_generichash_BYTES;
1665      memcpy((*ctx->p_commitments)[i], dptr, crypto_core_ristretto255_BYTES);
1666  
1667      memcpy(wptr, ptr, toprfupdate_peer_bc_transcript_msg_SIZE);
1668      wptr+=toprfupdate_peer_bc_transcript_msg_SIZE;
1669    }
1670    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
1671  
1672    int _debug=liboprf_debug; liboprf_debug=0;
1673    if(0!=toprf_mpc_vsps_check(ctx->t-1, (*ctx->p_commitments))) {
1674      liboprf_debug=_debug;
1675      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[!] result of DKG final commitments fail VSPS\n"NORMAL);
1676      if(stp_add_cheater(ctx, 2, 0, 0) == NULL) return TOPRF_Update_Err_CheatersFull;
1677    }
1678    liboprf_debug=_debug;
1679  
1680    if(0!=toprf_send_msg(output, output_len, toprfupdate_stp_bc_transcript_msg, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1681  
1682    ctx->step = TOPRF_Update_STP_Route_Mult_Step1;
1683    return TOPRF_Update_Err_OK;
1684  }
1685  
1686  #define toprfupdate_peer_mult1_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + (toprf_update_commitment_HASHBYTES + ctx->n * crypto_auth_hmacsha256_BYTES))
1687  static TOPRF_Update_Err peer_final_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1688    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] dkg-final2 receive&check final transcript, receive & VSPS check p commitments\n"NORMAL, ctx->index);
1689    if(input_len != toprfupdate_stp_bc_transcript_msg_SIZE(ctx)) return TOPRF_Update_Err_ISize;
1690    if(output_len != isdealer(ctx->index, ctx->t) * toprfupdate_peer_mult1_msg_SIZE(ctx)) return TOPRF_Update_Err_OSize;
1691  
1692    // verify STP message envelope
1693    const uint8_t *ptr=NULL;
1694    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_transcript_msg,&ptr);
1695    if(ret!=TOPRF_Update_Err_OK) return ret;
1696  
1697    size_t cheaters = ctx->cheater_len;
1698    uint8_t (*pcom)[ctx->n][crypto_core_ristretto255_BYTES] = (uint8_t (*)[ctx->n][crypto_core_ristretto255_BYTES]) ctx->p_commitments;
1699    for(uint8_t i=0;i<ctx->n;i++, ptr+=toprfupdate_peer_bc_transcript_msg_SIZE) {
1700      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
1701      const uint8_t *dptr = msg->data;
1702      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_bc_transcript_msg_SIZE,toprfupdate_peer_bc_transcript_msg,i+1,0xff)) continue;
1703  
1704      if(sodium_memcmp(ctx->transcript, dptr, crypto_generichash_BYTES)!=0) {
1705        if(liboprf_log_file!=NULL) {
1706          fprintf(liboprf_log_file,"\x1b[0;31m[!] failed to verify transcript from %d!\x1b[0m\n", i);
1707        }
1708        if(peer_add_cheater(ctx, 1, i+1, 0) == NULL) return TOPRF_Update_Err_CheatersFull;
1709        continue;
1710      }
1711      dptr+=crypto_generichash_BYTES;
1712      memcpy((*pcom)[i], dptr, crypto_core_ristretto255_BYTES);
1713    }
1714    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
1715  
1716    // in theory this should not be needed, and not fail. except for the
1717    // case when the dealer shares were corrupted after calculating a
1718    // correct commitment for them. but that should also be previously detected.
1719    int _debug=liboprf_debug; liboprf_debug=0;
1720    if(0!=toprf_mpc_vsps_check(ctx->t-1, (*pcom))) {
1721      liboprf_debug=_debug;
1722      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] result of p DKG commitments fail VSPS\n"NORMAL, ctx->index);
1723      if(peer_add_cheater(ctx, 2, 0, 0) == NULL) return TOPRF_Update_Err_CheatersFull;
1724    }
1725    liboprf_debug=_debug;
1726  
1727    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
1728  
1729    // reset complaints
1730    ctx->p_complaints_len = 0;
1731    ctx->my_p_complaints_len = 0;
1732    memset(ctx->p_complaints, 0, ctx->n*2);
1733    memset(ctx->my_p_complaints, 0, ctx->n);
1734  
1735    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] mult1 dealers calculate and share λ_iα_iβ_i\x1b[0m\n", ctx->index);
1736  
1737    // todo dealers based on cheaters and knowledge of kc0
1738    const uint8_t dealers = (uint8_t) ((ctx->t-1)*2 + 1);
1739  
1740    // precompute lambdas
1741    // λ_i is row 1 of inv VDM matrix
1742    uint8_t indexes[dealers];
1743    for(uint8_t i=0;i<dealers;i++) indexes[i]=i+1;
1744    uint8_t lambdas[dealers][dealers][crypto_core_ristretto255_SCALARBYTES];
1745    invertedVDMmatrix(dealers, indexes, lambdas);
1746    memcpy((*ctx->lambdas), lambdas[0], dealers*crypto_core_ristretto255_SCALARBYTES);
1747    //dump((uint8_t*) lambdas[0], dealers*crypto_core_ristretto255_SCALARBYTES, "vdm[0] ");
1748    //dump((uint8_t*) (*ctx->lambdas), dealers*crypto_core_ristretto255_SCALARBYTES, "lambdas");
1749  
1750    if(ctx->index>dealers) { // non-dealers are done
1751      ctx->step = TOPRF_Update_Peer_Rcv_Mult_CHashes_Send_Commitments;
1752      return TOPRF_Update_Err_OK;
1753    }
1754    // dealers only
1755    // step 1. Each player P_i shares λ_iα_iβ_i, using VSS
1756    if(0!=toprf_mpc_ftmult_step1(dealers, ctx->n, ctx->t, ctx->index-1,
1757                                 ctx->kc0_share, ctx->p_share, (*ctx->lambdas),
1758                                 // we reuse p_shares as we need to store n shares, and k0p_shares has only dealer entries
1759                                 (*ctx->p_shares), (*ctx->k0p_commitments), ctx->k0p_tau)) {
1760        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[%d] failed toprf_mpc_ftmult_step1\n", ctx->index);
1761        return TOPRF_Update_Err_FTMULTStep1;
1762    }
1763  #ifdef UNITTEST_CORRUPT
1764    corrupt_mult_vsps_t1(ctx, 1);
1765    corrupt_wrongshare_correct_commitment(ctx,2,4,ctx->p_shares,ctx->k0p_commitments);
1766    if(ctx->index==3) corrupt_ci0_good_ci(3, (*ctx->k0p_commitments));
1767    corrupt_commitment(ctx,4,ctx->k0p_commitments);
1768    corrupt_share(ctx,6,3,1,ctx->p_shares);
1769  #endif // UNITTEST_CORRUPT
1770  
1771    // similar to dkg1 encrypt shares, broadcast commitment hash and hmacs.
1772    TOPRF_Update_Message* msg24 = (TOPRF_Update_Message*) output;
1773    uint8_t *wptr = msg24->data;
1774    // hash of k0p commitments
1775    hash_commitments(ctx,ctx->n+1,(*ctx->k0p_commitments),&wptr);
1776  
1777    for(uint8_t i=0;i<ctx->n;i++) {
1778      // we might need to disclose the encryption key for the p shares,
1779      // but we don't want even the STP to learn more than necessary for
1780      // proving the correct encryption of the shares, hence the
1781      // following: we extract the current noise key, hkdf() it into two
1782      // dedicated subkeys, encrypt the shares using a stream cipher,
1783      // and calculate an hmac over these with the subkeys.
1784      uint8_t *dptr = (uint8_t*) (*ctx->encrypted_shares)[i];
1785      encrypt_shares(ctx,i,"k0p",(*ctx->p_shares)[i],1,wptr,dptr);
1786      dptr+=toprf_update_encrypted_shares_SIZE;
1787      wptr+=crypto_auth_hmacsha256_BYTES;
1788    }
1789  
1790    if(0!=toprf_send_msg(output, toprfupdate_peer_mult1_msg_SIZE(ctx), toprfupdate_peer_mult1_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1791  
1792    ctx->step = TOPRF_Update_Peer_Rcv_Mult_CHashes_Send_Commitments;
1793    return TOPRF_Update_Err_OK;
1794  }
1795  
1796  static TOPRF_Update_Err stp_step25_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1797    const uint8_t dealers = (uint8_t) ((ctx->t-1)*2 + 1);
1798    TOPRF_Update_Err ret;
1799    ret = stp_broadcast(ctx, input, input_len, output, output_len,
1800                        "mult2 broadcast commitment hashes and share hmacs for k0p ft-mult step 1",
1801                        dealers, toprfupdate_peer_mult1_msg_SIZE(ctx), toprfupdate_peer_mult1_msg, TOPRF_Update_STP_Broadcast_Mult_Commitments);
1802    if(ret != TOPRF_Update_Err_OK) return ret;
1803    const uint8_t *ptr = input;
1804    for(unsigned i=0;i<dealers;i++,ptr+=toprfupdate_peer_mult1_msg_SIZE(ctx)) {
1805      const DKG_Message* msg = (const DKG_Message*) ptr;
1806      const uint8_t *dptr=msg->data;
1807      memcpy((*ctx->p_commitments_hashes)[i], dptr, toprf_update_commitment_HASHBYTES);
1808      dptr+=toprf_update_commitment_HASHBYTES;
1809  
1810      for(uint8_t j=0;j<ctx->n;j++) {
1811        memcpy((*ctx->p_share_macs)[i*ctx->n+j], dptr, crypto_auth_hmacsha256_BYTES);
1812        dptr+=crypto_auth_hmacsha256_BYTES;
1813      }
1814    }
1815    return TOPRF_Update_Err_OK;
1816  }
1817  
1818  #define toprfupdate_peer_mult_coms_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + crypto_core_ristretto255_BYTES * (ctx->n+1U) * 2)
1819  static TOPRF_Update_Err peer_mult2_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1820    const uint8_t dealers = (uint8_t) ((ctx->t-1)*2 + 1);
1821    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] mult3 receive commitment hashes, broadcast commitments\x1b[0m\n", ctx->index);
1822    if(input_len != sizeof(TOPRF_Update_Message) + toprfupdate_peer_mult1_msg_SIZE(ctx) * dealers) return TOPRF_Update_Err_ISize;
1823    if(output_len != isdealer(ctx->index, ctx->t) * toprfupdate_peer_mult_coms_msg_SIZE(ctx)) return TOPRF_Update_Err_OSize;
1824  
1825    // verify STP message envelope
1826    const uint8_t *ptr=NULL;
1827    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_mult1_msg,&ptr);
1828    if(ret!=TOPRF_Update_Err_OK) return ret;
1829  
1830    for(uint8_t i=0;i<dealers;i++, ptr+=toprfupdate_peer_mult1_msg_SIZE(ctx)) {
1831      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
1832      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_dkg1_msg_SIZE(ctx),toprfupdate_peer_mult1_msg,i+1,0xff)) continue;
1833  
1834      const uint8_t *dptr=msg->data;
1835      // extract peer p commitment hash
1836      memcpy((*ctx->p_commitments_hashes)[i], dptr, toprf_update_commitment_HASHBYTES);
1837      dptr+=toprf_update_commitment_HASHBYTES;
1838      // todo rename {kc1|p}_{commitment_hashes|share_macs} into more
1839      // generic names so that they better fit dkg and mult usage
1840  
1841      for(uint8_t j=0;j<ctx->n;j++) {
1842        // extract and store encrypted p share mac
1843        memcpy((*ctx->p_share_macs)[j*ctx->n + i], dptr, crypto_auth_hmacsha256_BYTES);
1844        //dump(dptr, crypto_auth_hmacsha256_BYTES, "[%d] p   share macs [%d,%d]", ctx->index, j+1, i+1);
1845        dptr+=crypto_auth_hmacsha256_BYTES;
1846      }
1847  
1848      if(liboprf_log_file!=NULL) {
1849        dump((*ctx->p_commitments_hashes)[i], toprf_update_commitment_HASHBYTES, "[%d] p   commitment hash [%d]", ctx->index, i+1);
1850      }
1851    }
1852    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
1853  
1854    if(ctx->index>dealers) { // non-dealers are done
1855      ctx->step = TOPRF_Update_Peer_Send_K0P_Shares;
1856      return TOPRF_Update_Err_OK;
1857    }
1858  
1859    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
1860    uint8_t *wptr = msg->data;
1861    // we stashed our commitments temporarily in k_commitments
1862    memcpy(wptr, (*ctx->k0p_commitments), (ctx->n+1U) * crypto_core_ristretto255_BYTES);
1863    if(liboprf_log_file!=NULL) dump((uint8_t*)(*ctx->k0p_commitments), (ctx->n+1U) * crypto_core_ristretto255_BYTES, "[%d] commitments", ctx->index);
1864    //broadcast dealer_commitments
1865    if(0!=toprf_send_msg(output, toprfupdate_peer_mult_coms_msg_SIZE(ctx), toprfupdate_peer_mult_coms_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1866  
1867    ctx->step = TOPRF_Update_Peer_Send_K0P_Shares;
1868  
1869    return TOPRF_Update_Err_OK;
1870  }
1871  
1872  static TOPRF_Update_Err stp_mult_com_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1873    const uint8_t dealers = (uint8_t) ((ctx->t-1)*2 + 1);
1874    TOPRF_Update_Err ret = stp_broadcast(ctx, input, input_len, output, output_len,
1875                                         "mult4 broadcast commitments mult step 1",
1876                                         dealers, toprfupdate_peer_mult_coms_msg_SIZE(ctx), toprfupdate_peer_mult_coms_msg, TOPRF_Update_STP_Route_Encrypted_Mult_Shares);
1877    if(ret!=TOPRF_Update_Err_OK) return ret;
1878    const uint8_t *ptr = input;
1879  
1880    // fixup step, that has already been advanced in the call to stp_broadcast above.
1881    uint8_t step = ctx->step;
1882    ctx->step = TOPRF_Update_STP_Broadcast_Mult_Commitments;
1883  
1884    for(uint8_t i=0;i<dealers;i++,ptr+=toprfupdate_peer_mult_coms_msg_SIZE(ctx)) {
1885      const DKG_Message* msg = (const DKG_Message*) ptr;
1886      const uint8_t *dptr = msg->data;
1887      ret = stp_check_chash(ctx,i,"k0p", dealers, ctx->n+1, dptr, ctx->p_commitments_hashes, ctx->k0p_commitments);
1888      if(TOPRF_Update_Err_OK!=ret) {
1889        ctx->step=step;
1890        return ret;
1891      }
1892    }
1893  
1894    ret = stp_vsps_check(ctx, "k0p", dealers, ctx->n+1, ctx->k0p_commitments);
1895  
1896    ctx->step=step;
1897    return ret;
1898  }
1899  
1900  #define toprfupdate_peer_mult2_msg_SIZE (sizeof(TOPRF_Update_Message) + sizeof(TOPRF_Share) * 4)
1901  static TOPRF_Update_Err peer_step26_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1902    const uint8_t dealers = (uint8_t) ((ctx->t-1)*2 + 1);
1903    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] mult5 receive Mul commitments & distribute encrypted Mult shares\x1b[0m\n", ctx->index);
1904    if(input_len != sizeof(TOPRF_Update_Message) + toprfupdate_peer_mult_coms_msg_SIZE(ctx) * dealers) return TOPRF_Update_Err_ISize;
1905    if(output_len != isdealer(ctx->index, ctx->t) * ctx->n * toprfupdate_peer_mult2_msg_SIZE) return TOPRF_Update_Err_OSize;
1906  
1907    const size_t cheaters = ctx->cheater_len;
1908    // verify STP message envelope
1909    const uint8_t *ptr=NULL;
1910    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_mult_coms_msg,&ptr);
1911    if(ret!=TOPRF_Update_Err_OK) return ret;
1912  
1913    for(uint8_t i=0;i<dealers;i++,ptr+=toprfupdate_peer_mult_coms_msg_SIZE(ctx)) {
1914      const TOPRF_Update_Message* msg24 = (const TOPRF_Update_Message*) ptr;
1915      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_mult_coms_msg_SIZE(ctx),toprfupdate_peer_mult_coms_msg,i+1,0xff)) continue;
1916  
1917      const uint8_t *dptr = msg24->data;
1918      // k0*p commitments
1919      memcpy((*ctx->k0p_commitments)[i*(ctx->n+1U)], dptr, (ctx->n+1U) * crypto_core_ristretto255_BYTES);
1920  
1921      // verify against commitment hashes
1922      uint8_t chash[toprf_update_commitment_HASHBYTES];
1923      crypto_generichash(chash, toprf_update_commitment_HASHBYTES, (*ctx->k0p_commitments)[i*(ctx->n+1U)], crypto_core_ristretto255_BYTES*(ctx->n+1U), NULL, 0);
1924      if(memcmp(chash, (*ctx->p_commitments_hashes)[i], toprf_update_commitment_HASHBYTES)!=0) {
1925        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] failed to verify hash for k0p commitments of dealer %d\n"NORMAL, ctx->index, i+1);
1926        if(peer_add_cheater(ctx, 1, i+1, 0) == NULL) return TOPRF_Update_Err_CheatersFull;
1927      }
1928    }
1929    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
1930  
1931    if(ctx->index>dealers) { // non-dealers are done
1932      ctx->step = TOPRF_Update_Peer_Recv_K0P_Shares;
1933      return TOPRF_Update_Err_OK;
1934    }
1935    // dealers only
1936    // also distribute k0*p shares to all
1937    uint8_t *wptr = output;
1938    for(uint8_t i=0;i<ctx->n;i++,wptr+=toprfupdate_peer_mult2_msg_SIZE) {
1939      TOPRF_Update_Message* msg26 = (TOPRF_Update_Message*) wptr;
1940      memcpy(msg26->data, (*ctx->encrypted_shares)[i], toprf_update_encrypted_shares_SIZE*2);
1941  
1942      if(0!=toprf_send_msg(wptr, toprfupdate_peer_mult2_msg_SIZE, toprfupdate_peer_mult2_msg, ctx->index, i+1, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1943    }
1944  
1945    ctx->step = TOPRF_Update_Peer_Recv_K0P_Shares;
1946    return TOPRF_Update_Err_OK;
1947  }
1948  
1949  static TOPRF_Update_Err stp_step27_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1950    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
1951    return stp_route(ctx, input, input_len, output, output_len,
1952                     "mult6 route k0*p shares from all dealers to all peers",
1953                     dealers, ctx->n, toprfupdate_peer_mult2_msg, toprfupdate_peer_mult2_msg_SIZE, TOPRF_Update_STP_Broadcast_Mult_Complaints);
1954  }
1955  
1956  #define toprfupdate_peer_verify_mult_shares_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + 2U + (size_t)((ctx->t-1U)*2 + 1U) * 2)
1957  static TOPRF_Update_Err peer_step28_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1958    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
1959    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] mult7 receive k0*p shares, starts checking of commitments\x1b[0m\n", ctx->index);
1960    if(input_len != dealers * toprfupdate_peer_mult2_msg_SIZE) return TOPRF_Update_Err_ISize;
1961    if(output_len != toprfupdate_peer_verify_mult_shares_msg_SIZE(ctx)) return TOPRF_Update_Err_OSize;
1962  
1963    //uint8_t (*c)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES]) ctx->k0p_commitments;
1964    //for(unsigned i=0;i<dealers;i++) {
1965    //  for(unsigned j=0;j<ctx->n+1;j++) dump((*c)[i][j], crypto_core_ristretto255_BYTES, "c_%d%d", i+1,j);
1966    //}
1967    const size_t cheaters = ctx->cheater_len;
1968  
1969    const uint8_t *ptr = input;
1970    for(uint8_t i=0;i<dealers;i++) {
1971      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
1972      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_mult2_msg_SIZE,toprfupdate_peer_mult2_msg,i+1,ctx->index)) continue;
1973  
1974      const uint8_t *dptr = msg->data;
1975  
1976      TOPRF_Update_Err ret = decrypt_shares(ctx, i, "k0p", (*ctx->p_share_macs)[(ctx->index-1)*ctx->n + i], dptr, 1, (*ctx->k0p_shares)[i]);
1977      if(TOPRF_Update_Err_OK!=ret) {
1978        dump((*ctx->p_share_macs)[(ctx->index-1)*ctx->n + i], crypto_auth_hmacsha256_BYTES, "[%d] k0p hmac_%d", ctx->index, i+1);
1979        return ret;
1980      }
1981  
1982      ptr+=toprfupdate_peer_mult2_msg_SIZE;
1983    }
1984    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
1985  
1986    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
1987    uint8_t *fails_len = msg->data;
1988    uint8_t *fails = fails_len+1;
1989    verify_commitments(ctx, "k0p", dealers, ctx->n+1, ctx->index, (*ctx->k0p_commitments), ctx->k0p_shares, fails_len, fails);
1990  #ifdef UNITTEST_CORRUPT
1991    corrupt_false_accuse(ctx, 2, 3, fails_len, fails);
1992  #endif //UNITTEST_CORRUPT
1993  
1994    if(0!=toprf_send_msg(output, toprfupdate_peer_verify_mult_shares_msg_SIZE(ctx), toprfupdate_peer_verify_mult_shares_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
1995  
1996    ctx->step = TOPRF_Update_Peer_Handle_Mult_Share_Complaints;
1997  
1998    return TOPRF_Update_Err_OK;
1999  }
2000  
2001  #define toprfupdate_stp_bc_verify_mult_shares_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + (toprfupdate_peer_verify_mult_shares_msg_SIZE(ctx) * ctx->n))
2002  static TOPRF_Update_Err stp_verify_mult_shares_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2003    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2004    return stp_complaint_handler(ctx, input, input_len, output, output_len,
2005                                 "mult-verify1 broadcast mult complaints of peers",
2006                                 ctx->n, toprfupdate_peer_verify_mult_shares_msg_SIZE(ctx),
2007                                 toprfupdate_peer_verify_mult_shares_msg,
2008                                 dealers,
2009                                 TOPRF_Update_STP_Route_ZK_Challenge_Commitments,
2010                                 TOPRF_Update_STP_Broadcast_Mult_Defenses);
2011  }
2012  
2013  static TOPRF_Update_Err peer_mult_fork(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len) {
2014    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2015    return peer_complaint_handler(ctx, input, input_len,
2016                                  "mult-verify2 receive mult complaints broadcast",
2017                                  toprfupdate_peer_verify_mult_shares_msg_SIZE(ctx),
2018                                  toprfupdate_peer_verify_mult_shares_msg,
2019                                  dealers,
2020                                  TOPRF_Update_Peer_Send_ZK_Challenge_Commitments,
2021                                  TOPRF_Update_Peer_Defend_Mult_Accusations);
2022  }
2023  
2024  static TOPRF_Update_Err peer_mult_defend(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
2025    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] mult-defend1 disclose share encryption key for contested Mult shares\x1b[0m\n", ctx->index);
2026    if(output_len != toprf_update_peer_output_size(ctx)) return TOPRF_Update_Err_OSize;
2027    if(output_len == 0) {
2028      if(liboprf_log_file!=NULL) {
2029        fprintf(liboprf_log_file,"[%d] nothing to defend against, no message to send\n", ctx->index);
2030      }
2031      ctx->step = TOPRF_Update_Peer_Check_Mult_Shares;
2032      return 0;
2033    }
2034  
2035    // send out all shares that belong to peers that complained.
2036    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
2037    uint8_t *wptr = msg->data;
2038    for(int i=0;i<ctx->my_p_complaints_len;i++) {
2039      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;36m[%d] defending against k0p complaint from %d\x1b[0m\n", ctx->index, ctx->my_p_complaints[i]);
2040  
2041      *wptr++ = ctx->my_p_complaints[i];
2042      // reveal key for noise wrapped share sent previously
2043      derive_key((*ctx->noise_outs)[ctx->my_p_complaints[i]-1],ctx->my_p_complaints[i],"k0p",wptr);
2044      wptr+=dkg_noise_key_SIZE;
2045  
2046      memcpy(wptr, (*ctx->encrypted_shares)[ctx->my_p_complaints[i]-1], toprf_update_encrypted_shares_SIZE);
2047      wptr+=toprf_update_encrypted_shares_SIZE;
2048    }
2049  
2050    if(0!=toprf_send_msg(output, output_len, toprfupdate_peer_share_mult_key_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
2051  
2052    ctx->step = TOPRF_Update_Peer_Check_Mult_Shares;
2053    return TOPRF_Update_Err_OK;
2054  }
2055  
2056  static TOPRF_Update_Err stp_broadcast_mult_defenses(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2057    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2058    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] mult-defend2 broadcast mult defenses\x1b[0m\n");
2059    if(input_len != toprf_update_stp_input_size(ctx)) return TOPRF_Update_Err_ISize;
2060    if(output_len != toprf_update_stp_output_size(ctx)) return TOPRF_Update_Err_OSize;
2061  
2062    unsigned int ctr1[dealers];
2063    memset(ctr1,0,sizeof(ctr1));
2064    for(int i=0;i<ctx->p_complaints_len;i++) {
2065      const uint8_t peer = (uint8_t) ((ctx->p_complaints[i] & 0xff)-1U);
2066      if(peer>=dealers) return TOPRF_Update_Err_OOB;
2067      ctr1[peer]++;
2068    }
2069  
2070    ctx->y2_complaints_len = 0;
2071    memset(ctx->y2_complaints, 0, ctx->n*2);
2072  
2073    const uint8_t *ptr = input;
2074    uint8_t *wptr = ((TOPRF_Update_Message *) output)->data;
2075    size_t msg_size;
2076    for(uint8_t i=0;i<dealers;i++,ptr += msg_size) {
2077      if(ctr1[i]==0) {
2078        msg_size = 0;
2079        continue; // no complaints against this peer
2080      }
2081      msg_size = sizeof(TOPRF_Update_Message) \
2082                 + (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
2083      if(stp_recv_msg(ctx,ptr,msg_size,toprfupdate_peer_share_mult_key_msg,i+1,0xff)) continue;
2084  
2085      const TOPRF_Update_Message *msg = (const TOPRF_Update_Message *) ptr;
2086      const uint8_t *dptr = msg->data;
2087  
2088      TOPRF_Update_Err ret = stp_check_defenses(ctx, dealers, ctx->n + 1, 0, ctr1[i], i, 1, ctx->p_share_macs, *ctx->k0p_commitments, &ctx->y2_complaints_len, ctx->y2_complaints, &dptr);
2089      if(TOPRF_Update_Err_OK != ret) {
2090        return ret;
2091      }
2092  
2093      memcpy(wptr, ptr, msg_size);
2094      wptr+=msg_size;
2095    }
2096    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
2097  
2098    dump((uint8_t*)ctx->y2_complaints, ctx->y2_complaints_len*2, "k0p recover dealers:");
2099    if(0!=toprf_send_msg(output, output_len, toprfupdate_stp_bc_mult_key_msg, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
2100  
2101    // add broadcast msg to transcript
2102    update_transcript(&ctx->transcript_state, output, output_len);
2103  
2104    if(ctx->y2_complaints_len==0) {
2105      ctx->step = TOPRF_Update_STP_Route_ZK_Challenge_Commitments;
2106    } else {
2107      ctx->step = TOPRF_Update_STP_Broadcast_Reconst_Mult_Shares;
2108    }
2109    return TOPRF_Update_Err_OK;
2110  }
2111  
2112  static TOPRF_Update_Err peer_check_mult_shares(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len) {
2113    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2114    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] mult-defend3 verify disclosed mult shares\x1b[0m\n", ctx->index);
2115    if(input_len != toprf_update_peer_input_size(ctx)) return TOPRF_Update_Err_ISize;
2116  
2117    // verify STP message envelope
2118    const uint8_t *ptr=NULL;
2119    TOPRF_Update_Err ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_mult_key_msg,&ptr);
2120    if(ret!=TOPRF_Update_Err_OK) return ret;
2121  
2122    unsigned int ctr1[dealers];
2123    aggregate_complaints(dealers,ctr1,&ctx->p_complaints_len,ctx->p_complaints);
2124  
2125    size_t msg_size;
2126    for(uint8_t i=0;i<dealers;i++,ptr += msg_size) {
2127      if(ctr1[i]==0) {
2128        msg_size = 0;
2129        continue; // no complaints against this peer
2130      }
2131      msg_size = sizeof(TOPRF_Update_Message) \
2132                 + (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
2133  
2134      if(peer_recv_msg(ctx,ptr,msg_size,toprfupdate_peer_share_mult_key_msg,i+1,0xff)) continue;
2135      const TOPRF_Update_Message *msg = (const TOPRF_Update_Message *) ptr;
2136      const uint8_t *dptr = msg->data;
2137  
2138      ret = check_defenses(ctx, dealers, ctx->n+1, 0, ctr1[i], i, 1, ctx->p_share_macs, *ctx->k0p_commitments, &ctx->p_complaints_len, ctx->p_complaints, &dptr);
2139      if(TOPRF_Update_Err_OK != ret) return ret;
2140    }
2141  
2142    dump((uint8_t*) ctx->p_complaints, ctx->p_complaints_len*2, "k0p recover dealers:");
2143  
2144    if(ctx->p_complaints_len > 0) {
2145      ctx->step = TOPRF_Update_Peer_Disclose_Mult_Shares;
2146    } else {
2147      ctx->step = TOPRF_Update_Peer_Send_ZK_Challenge_Commitments;
2148    }
2149    return TOPRF_Update_Err_OK;
2150  }
2151  
2152  static uint8_t unique_complaints(const uint8_t n,
2153                                   const uint16_t complaints_len,
2154                                   const uint16_t complaints[complaints_len]) {
2155    if(n==0) return 0xff;
2156    uint8_t total=0;
2157    uint8_t peer[n];
2158    memset(peer, 0, sizeof peer);
2159    for(unsigned i=0;i<complaints_len;i++) {
2160      const uint8_t accused = (uint8_t) (complaints[i] & 0xff);
2161      if(accused>n || accused == 0) return 0xff; // we set them ourselves. this should not happen
2162      peer[accused-1]=1;
2163    }
2164    for(unsigned i=0;i<n;i++) total+=peer[i];
2165    return total;
2166  }
2167  #define unique_p_complaints(ctx) unique_complaints(ctx->n, ctx->p_complaints_len, ctx->p_complaints)
2168  #define unique_y2_complaints(ctx) unique_complaints(ctx->n, ctx->y2_complaints_len, ctx->y2_complaints)
2169  
2170  static TOPRF_Update_Err disclose_shares(const uint8_t n,
2171                                          const uint8_t self,
2172                                          const char *type,
2173                                          const uint16_t complaints_len,
2174                                          const uint16_t complaints[complaints_len],
2175                                          TOPRF_Share shares[][2],
2176                                          uint8_t **wptr) {
2177    if(n==0) return 0xff;
2178    int sent[n];
2179    memset(sent,0,sizeof sent);
2180    for(unsigned i=0;i<complaints_len;i++) {
2181      const uint8_t peer = (uint8_t) (complaints[i] & 0xff);
2182      if(peer==0 || peer>=n) return TOPRF_Update_Err_OOB;
2183      if(sent[peer-1]!=0) continue;
2184      sent[peer-1]=1;
2185      memcpy(*wptr, shares[peer-1], TOPRF_Share_BYTES*2);
2186      dump(*wptr, TOPRF_Share_BYTES*2, "[%d] disclosing %s share of %d", self, type, peer);
2187      *wptr+=TOPRF_Share_BYTES*2;
2188    }
2189    return TOPRF_Update_Err_OK;
2190  }
2191  
2192  #define toprfupdate_peer_reconst_mult_shares_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message)                                  \
2193                                                              + unique_p_complaints(ctx) * toprf_update_encrypted_shares_SIZE)
2194  static TOPRF_Update_Err peer_disclose_mult_shares(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
2195    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] mult-reconst1 disclose shares to reconstruct Mult secrets of cheaters\x1b[0m\n", ctx->index);
2196    if(output_len != toprfupdate_peer_reconst_mult_shares_msg_SIZE(ctx)) return TOPRF_Update_Err_OSize;
2197  
2198    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
2199    uint8_t *wptr = msg->data;
2200    TOPRF_Update_Err ret;
2201    ret =  disclose_shares(ctx->n, ctx->index, "k0p", ctx->p_complaints_len, ctx->p_complaints, (*ctx->k0p_shares), &wptr);
2202    if(ret != TOPRF_Update_Err_OK) return ret;
2203  
2204    if(0!=toprf_send_msg(output,
2205                         output_len,
2206                         toprfupdate_peer_reconst_mult_shares_msg,
2207                         ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
2208  
2209    ctx->step = TOPRF_Update_Peer_Reconstruct_Mult_Shares;
2210    return TOPRF_Update_Err_OK;
2211  }
2212  
2213  static TOPRF_Update_Err reconstruct(const uint8_t n, const uint8_t t,
2214                                      const char *type,
2215                                      const uint16_t complaints_len,
2216                                      const uint16_t complaints[complaints_len],
2217                                      const TOPRF_Share shares[unique_complaints(n, complaints_len, complaints)][n][2],
2218                                      const uint8_t (*commitments)[][crypto_core_ristretto255_BYTES],
2219                                      uint8_t secrets[unique_complaints(n, complaints_len, complaints)][2][crypto_core_ristretto255_SCALARBYTES]) {
2220    const uint8_t dealers = (uint8_t) ((t-1U)*2 + 1U);
2221    uint8_t (*c)[dealers][n+1][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][n+1][crypto_core_ristretto255_BYTES]) commitments;
2222    uint8_t seen[n];
2223    memset(seen, 0, sizeof seen);
2224    for(unsigned i=0, share_idx=0;i<complaints_len;i++) {
2225      TOPRF_Share r[2];
2226      const uint8_t accused = (uint8_t) (complaints[i] & 0xff);
2227      const uint8_t accuser = (uint8_t) (complaints[i] >> 8);
2228  
2229      if(accused == 0 || accused>=n) return TOPRF_Update_Err_OOB;
2230      if(seen[accused-1]) continue;
2231      seen[accused-1]=1;
2232  
2233      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[!] reconstructing %s share/commitment of dealer %d accused by %d\n", type, accused, accuser);
2234      uint8_t t1=t;
2235      for(t1=t;t1<n;t1++) {
2236        fprintf(liboprf_log_file, "trying degree t+%d\n", t1-t);
2237        if(0!=dkg_vss_reconstruct(t1, 0, n, shares[share_idx], &(*commitments)[(n+1) * (accused - 1) + 1], r[0].value, r[1].value)) continue;
2238        if(0!=dkg_vss_verify_commitment((*c)[accused-1][0],r)) continue;
2239        break;
2240      }
2241      if(t1>=n) return TOPRF_Update_Err_Reconstruct;
2242  
2243      if(secrets!=NULL) {
2244        if(0!=dkg_vss_reconstruct(t1, 0, n, shares[share_idx], &(*commitments)[(n+1) * (accused - 1) + 1], secrets[i][0], secrets[i][1])) return TOPRF_Update_Err_Reconstruct;
2245        dump((uint8_t*) secrets[i], 2*crypto_core_ristretto255_SCALARBYTES, "[!] reconstructed secret of %d", accused);
2246      }
2247  
2248      if(0!=dkg_vss_reconstruct(t1, accuser, n, shares[share_idx], &(*commitments)[(n+1) * (accused - 1) + 1], r[0].value, r[1].value)) return TOPRF_Update_Err_Reconstruct;
2249      dump((uint8_t*) &r, sizeof r, "[!] reconstructed share of %d - accused by %d", accused, accuser);
2250  
2251      if(0!=dkg_vss_verify_commitment((*c)[accused-1][accuser],r)) {
2252        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[!] failed to validate commitment for reconstructed %s share from %d\n"NORMAL, type, accused);
2253        dump((*c)[accused-1][accuser], 32, "[!] commitment", accuser);
2254        if(0!=dkg_vss_commit(r[0].value, r[1].value,(*c)[accused-1][accuser])) return TOPRF_Update_Err_VSSCommit;
2255        dump((*c)[accused-1][accuser], 32, "[!] corrected ", accuser);
2256        // todo check vsps on these commitments and if that fails return TOPRF_Update_Err_BadReconstruct;
2257        // better to do this only after all reconstructions have been
2258        // done in case multiple shares from the same dealer have
2259        // adjusted commitments.
2260      }
2261  
2262      share_idx++;
2263    }
2264    return TOPRF_Update_Err_OK;
2265  }
2266  
2267  
2268  #define toprfupdate_stp_reconst_mult_shares_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message)      \
2269                                                             + unique_y2_complaints(ctx) * toprf_update_encrypted_shares_SIZE)
2270  static TOPRF_Update_Err stp_broadcast_reconst_mult_shares(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2271    TOPRF_Update_Err ret;
2272    ret = stp_broadcast(ctx, input, input_len, output, output_len,
2273                         "mult-reconst2 broadcast shares to reconstruct mult secrets of cheating dealers",
2274                         ctx->n, toprfupdate_stp_reconst_mult_shares_msg_SIZE(ctx), toprfupdate_peer_reconst_mult_shares_msg, TOPRF_Update_STP_Route_ZK_Challenge_Commitments);
2275    if(ret != TOPRF_Update_Err_OK) return ret;
2276  
2277    TOPRF_Share k0p_shares[unique_y2_complaints(ctx)][ctx->n][2];
2278    const uint8_t *ptr = input;
2279    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_stp_reconst_mult_shares_msg_SIZE(ctx)) {
2280      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
2281      const uint8_t *dptr = msg->data;
2282      for(unsigned j=0;j<unique_y2_complaints(ctx);j++) {
2283        memcpy(k0p_shares[j][msg->from-1], dptr, TOPRF_Share_BYTES*2);
2284        dptr+=TOPRF_Share_BYTES*2;
2285      }
2286    }
2287  
2288    ret = reconstruct(ctx->n, ctx->t,"k0p", ctx->y2_complaints_len,ctx->y2_complaints,k0p_shares,ctx->k0p_commitments, NULL);
2289  
2290    return ret;
2291  }
2292  
2293  static TOPRF_Update_Err peer_reconstruct(TOPRF_Update_PeerState *ctx,
2294                                           const char *type,
2295                                           uint16_t *complaints_len,
2296                                           uint16_t complaints[*complaints_len],
2297                                           const TOPRF_Share shares[unique_complaints(ctx->n, *complaints_len, complaints)][ctx->n][2],
2298                                           const uint8_t (*commitments)[][crypto_core_ristretto255_BYTES],
2299                                           TOPRF_Share (*my_shares)[2]) {
2300    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2301    uint8_t (*c)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES]) commitments;
2302    uint8_t seen[ctx->n];
2303    memset(seen, 0, sizeof seen);
2304    for(unsigned i=0, share_idx=0;i<*complaints_len;i++) {
2305      TOPRF_Share r[2];
2306      const uint8_t accused = (uint8_t) (complaints[i] & 0xff);
2307      const uint8_t accuser = (uint8_t) (complaints[i] >> 8);
2308  
2309      if(accused == 0 || accused>=ctx->n) return TOPRF_Update_Err_OOB;
2310      if(seen[accused-1]) continue;
2311      seen[accused-1]=1;
2312  
2313      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[%d] reconstructing %s share/commitment of dealer %d accused by %d\n", ctx->index, type, accused, accuser);
2314      uint8_t t1=ctx->t;
2315      for(t1=ctx->t;t1<ctx->n;t1++) {
2316        fprintf(liboprf_log_file, "trying degree t+%d\n", t1-ctx->t);
2317        if(0!=dkg_vss_reconstruct(t1, 0, ctx->n, shares[share_idx], &(*commitments)[(ctx->n+1) * (accused - 1) + 1], r[0].value, r[1].value)) continue;
2318        if(0!=dkg_vss_verify_commitment((*c)[accused-1][0],r)) continue;
2319        break;
2320      }
2321      if(t1>=ctx->n) return TOPRF_Update_Err_Reconstruct;
2322  
2323      if(0!=dkg_vss_reconstruct(t1, accuser, ctx->n, shares[share_idx], &(*commitments)[(ctx->n+1) * (accused - 1) + 1], r[0].value, r[1].value)) return TOPRF_Update_Err_Reconstruct;
2324      dump((uint8_t*) &r, sizeof r, "[%d] reconstructed share of %d - accused by %d", ctx->index, accused, accuser);
2325  
2326      if(0!=dkg_vss_verify_commitment((*c)[accused-1][accuser],r)) {
2327        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] failed to validate commitment for reconstructed %s share from %d\n"NORMAL, ctx->index, type, accused);
2328        dump((*c)[accused-1][accuser], 32, "[%d] commitment", ctx->index);
2329        if(0!=dkg_vss_commit(r[0].value, r[1].value, (*c)[accused-1][accuser])) return TOPRF_Update_Err_VSSCommit;
2330        dump((*c)[accused-1][accuser], 32, "[%d] corrected ", ctx->index);
2331        // todo check vsps on these commitments and if that fails return TOPRF_Update_Err_BadReconstruct;
2332        // better to do this only after all reconstructions have been
2333        // done in case multiple shares from the same dealer have
2334        // adjusted commitments.
2335      }
2336  
2337      int incorrect = 0;
2338      for(unsigned j=0;j<*complaints_len;j++) {
2339        if((accused == (complaints[j] & 0xff)) && (ctx->index == (complaints[j] >> 8))) {
2340          incorrect = 1;
2341          break;
2342        }
2343      }
2344  
2345      if(accuser != ctx->index) {
2346        if(0!=dkg_vss_reconstruct(t1, ctx->index, ctx->n, shares[share_idx], &(*commitments)[(ctx->n+1) * (accused - 1) + 1], r[0].value, r[1].value)) return TOPRF_Update_Err_Reconstruct;
2347      }
2348  
2349      const int diff = (memcmp(r[0].value, my_shares[accused - 1][0].value, 32)!=0) |  (memcmp(r[1].value, my_shares[accused - 1][1].value, 32)!=0) << 1;
2350      if(diff!=0) {
2351        if(!incorrect) {
2352          if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] reconstructed a different %s share from %d than " \
2353                                     "was previously validated using its commitment, was accused by %d\n"NORMAL, ctx->index, type, accused, accuser);
2354          return TOPRF_Update_Err_BadReconstruct;
2355        }
2356        if(diff & 1) {
2357          dump(r[0].value, 32, "[%d] reconstructed s share %d", ctx->index, accused);
2358          memcpy(my_shares[accused - 1][0].value, r[0].value, 32);
2359        }
2360        if(diff & 2) {
2361          dump(r[1].value, 32, "[%d] reconstructed r share %d", ctx->index, accused);
2362          memcpy(my_shares[accused - 1][1].value, r[1].value, 32);
2363        }
2364      }
2365      share_idx++;
2366    }
2367    *complaints_len = 0;
2368    memset(complaints, 0, ctx->n*2);
2369    return TOPRF_Update_Err_OK;
2370  }
2371  
2372  static TOPRF_Update_Err peer_send_zk_chalcoms(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len);
2373  static TOPRF_Update_Err peer_reconst_mult_shares(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2374    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] mult-reconst3 reconstruct secrets of cheating mult dealers\x1b[0m\n", ctx->index);
2375    if(input_len!= sizeof(TOPRF_Update_Message) + toprfupdate_peer_reconst_mult_shares_msg_SIZE(ctx) * ctx->n) return TOPRF_Update_Err_ISize;
2376  
2377    // verify STP message envelope
2378    const uint8_t *ptr=NULL;
2379    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_reconst_mult_shares_msg,&ptr);
2380    if(ret!=TOPRF_Update_Err_OK) return ret;
2381  
2382    TOPRF_Share k0p_shares[unique_p_complaints(ctx)][ctx->n][2];
2383    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_reconst_mult_shares_msg_SIZE(ctx)) {
2384      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
2385      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_reconst_mult_shares_msg_SIZE(ctx),toprfupdate_peer_reconst_mult_shares_msg,i+1,0xff)) continue;
2386      const uint8_t *dptr = msg->data;
2387      for(unsigned j=0;j<unique_p_complaints(ctx);j++) {
2388        memcpy(k0p_shares[j][msg->from-1], dptr, TOPRF_Share_BYTES*2);
2389        dptr+=TOPRF_Share_BYTES*2;
2390      }
2391    }
2392  
2393    ret = peer_reconstruct(ctx,"k0p", &ctx->p_complaints_len,ctx->p_complaints,k0p_shares,ctx->k0p_commitments,(*ctx->k0p_shares));
2394    if(ret != TOPRF_Update_Err_OK) return ret;
2395  
2396    // reset my_complaints
2397    ctx->my_p_complaints_len = 0;
2398    memset(ctx->my_p_complaints, 0, ctx->n);
2399  
2400    return peer_send_zk_chalcoms(ctx, output, output_len);
2401  }
2402  
2403  //ctx->step = TOPRF_Update_Peer_Send_ZK_Challenge_Commitments;
2404  #define toprfupdate_peer_zkp1_msg_SIZE (sizeof(TOPRF_Update_Message) + crypto_scalarmult_ristretto255_BYTES)
2405  static TOPRF_Update_Err peer_send_zk_chalcoms(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
2406    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] zk1 send ZK challenge commitments\x1b[0m\n", ctx->index);
2407    if(output_len != toprfupdate_peer_zkp1_msg_SIZE) return TOPRF_Update_Err_OSize;
2408  
2409    // generate 2x nonces for ZK proof challenge, broadcast a commitment to it.
2410    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
2411    crypto_core_ristretto255_scalar_random(ctx->zk_chal_nonce[0]);
2412    crypto_core_ristretto255_scalar_random(ctx->zk_chal_nonce[1]);
2413    if(0!=dkg_vss_commit(ctx->zk_chal_nonce[0], ctx->zk_chal_nonce[1], msg->data)) return TOPRF_Update_Err_VSSCommit;
2414    //dump(msg->data + i*crypto_scalarmult_ristretto255_BYTES, crypto_scalarmult_ristretto255_BYTES, "<zk_challenge_commitment[%d][%d]", ctx->index, i);
2415  
2416    if(0!=toprf_send_msg(output, toprfupdate_peer_zkp1_msg_SIZE, toprfupdate_peer_zkp1_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
2417  
2418    ctx->step = TOPRF_Update_Peer_Send_ZK_Commitments;
2419    return TOPRF_Update_Err_OK;
2420  }
2421  
2422  static TOPRF_Update_Err stp_step29_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2423    return stp_broadcast(ctx, input, input_len, output, output_len,
2424                         "step 29. broadcast zk challenge commitments",
2425                         ctx->n, toprfupdate_peer_zkp1_msg_SIZE, toprfupdate_peer_zkp1_msg, TOPRF_Update_STP_Route_ZK_commitments);
2426  }
2427  
2428  #define toprfupdate_peer_zkp2_msg_SIZE (sizeof(TOPRF_Update_Message) + 2 * 3 * crypto_scalarmult_ristretto255_SCALARBYTES)
2429  static TOPRF_Update_Err peer_step30_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2430    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2431    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] zk2 everyone receives all e_j nonces, dealers broadcast ZK commitments\x1b[0m\n", ctx->index);
2432    if(input_len != sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp1_msg_SIZE * ctx->n) return TOPRF_Update_Err_ISize;
2433    if(output_len != isdealer(ctx->index, ctx->t) * toprfupdate_peer_zkp2_msg_SIZE) return TOPRF_Update_Err_OSize;
2434    const size_t cheaters = ctx->cheater_len;
2435  
2436    // verify STP message envelope
2437    const uint8_t *ptr=NULL;
2438    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_zkp1_msg,&ptr);
2439    if(ret!=TOPRF_Update_Err_OK) return ret;
2440  
2441    uint8_t (*zk_challenge_nonce_commitments)[ctx->n][crypto_scalarmult_ristretto255_BYTES] =
2442                                 (uint8_t (*)[ctx->n][crypto_scalarmult_ristretto255_BYTES]) (ctx->zk_challenge_nonce_commitments);
2443  
2444    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_zkp1_msg_SIZE) {
2445      const TOPRF_Update_Message* msg27 = (const TOPRF_Update_Message*) ptr;
2446      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_zkp1_msg_SIZE,toprfupdate_peer_zkp1_msg,i+1,0xff)) continue;
2447  
2448      //dump(msg27->data, crypto_scalarmult_ristretto255_BYTES, "zk_e_nonce_%d commitment", i);
2449      memcpy((*zk_challenge_nonce_commitments)[i], msg27->data, crypto_scalarmult_ristretto255_BYTES);
2450      //dump((*ctx->zk_challenge_nonce_commitments)[i], crypto_scalarmult_ristretto255_BYTES, ">zk_challenge_commitment[%d]", i+1);
2451    }
2452    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
2453  
2454    if(ctx->index>dealers) { // non-dealers are done
2455      ctx->step = TOPRF_Update_Peer_Send_ZK_nonces;
2456      return TOPRF_Update_Err_OK;
2457    }
2458    // dealers only
2459    // also distribute k0*p shares to all
2460    uint8_t *wptr = output;
2461    TOPRF_Update_Message* msg29 = (TOPRF_Update_Message*) wptr;
2462    //dump((*ctx->p_commitments)[ctx->index-1], crypto_core_ristretto255_BYTES, "B[%d]", ctx->index);
2463    uint8_t (*msgs)[crypto_scalarmult_ristretto255_SCALARBYTES] = (uint8_t (*)[crypto_scalarmult_ristretto255_SCALARBYTES]) msg29->data;
2464    if(0!=toprf_mpc_ftmult_zk_commitments((*ctx->p_commitments)[ctx->index-1],
2465                                          ctx->zk_params.d,     // uint8_t d[crypto_scalarmult_ristretto255_SCALARBYTES],
2466                                          ctx->zk_params.s,     // uint8_t s[crypto_scalarmult_ristretto255_SCALARBYTES],
2467                                          ctx->zk_params.x,     // uint8_t x[crypto_scalarmult_ristretto255_SCALARBYTES],
2468                                          ctx->zk_params.s_1,   // uint8_t s_1[crypto_scalarmult_ristretto255_SCALARBYTES],
2469                                          ctx->zk_params.s_2,   // uint8_t s_2[crypto_scalarmult_ristretto255_SCALARBYTES],
2470                                          msgs)) {
2471      return TOPRF_Update_Err_FTMULTZKCommitments;
2472    }
2473    //dump(ctx->zk_params.d, crypto_core_ristretto255_SCALARBYTES, "[%d] d[%d]", ctx->index, ctx->index);
2474    //dump(ctx->zk_params.s, crypto_core_ristretto255_SCALARBYTES, "[%d] s[%d]", ctx->index, ctx->index);
2475    //dump(ctx->zk_params.x, crypto_core_ristretto255_SCALARBYTES, "[%d] x[%d]", ctx->index, ctx->index);
2476    //dump(ctx->zk_params.s_1, crypto_core_ristretto255_SCALARBYTES, "[%d] s_1[%d]", ctx->index, ctx->index);
2477    //dump(ctx->zk_params.s_2, crypto_core_ristretto255_SCALARBYTES, "[%d] s_2[%d]", ctx->index, ctx->index);
2478    //dump(msgs[0], crypto_scalarmult_ristretto255_SCALARBYTES, "[%d] M[%d]", ctx->index, ctx->index);
2479    //dump(msgs[1], crypto_scalarmult_ristretto255_SCALARBYTES, "[%d] M1[%d]", ctx->index, ctx->index);
2480    //dump(msgs[2], crypto_scalarmult_ristretto255_SCALARBYTES, "[%d] M2[%d]", ctx->index, ctx->index);
2481  
2482    if(0!=toprf_send_msg(wptr, toprfupdate_peer_zkp2_msg_SIZE, toprfupdate_peer_zkp2_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
2483  
2484    ctx->step = TOPRF_Update_Peer_Send_ZK_nonces;
2485    return TOPRF_Update_Err_OK;
2486  }
2487  
2488  static TOPRF_Update_Err stp_step31_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2489    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2490    TOPRF_Update_Err ret;
2491    ret = stp_broadcast(ctx, input, input_len, output, output_len,
2492                         "zk3 broadcast ZK commitments",
2493                         dealers, toprfupdate_peer_zkp2_msg_SIZE, toprfupdate_peer_zkp2_msg, TOPRF_Update_STP_Broadcast_ZK_nonces);
2494    if(ret != TOPRF_Update_Err_OK) return ret;
2495    uint8_t (*zk_challenge_commitments)[dealers][3][crypto_scalarmult_ristretto255_SCALARBYTES] =
2496      (uint8_t (*)[dealers][3][crypto_scalarmult_ristretto255_SCALARBYTES]) ctx->zk_challenge_commitments;
2497  
2498    const uint8_t *ptr = input;
2499    for(uint8_t i=0;i<dealers;i++,ptr+=toprfupdate_peer_zkp2_msg_SIZE) {
2500      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
2501      //dump(msg27->data, crypto_scalarmult_ristretto255_BYTES, "zk_e_nonce_%d commitment", i);
2502      memcpy((*zk_challenge_commitments)[i], msg->data, 3*crypto_scalarmult_ristretto255_SCALARBYTES);
2503      //dump((uint8_t*) (*zk_challenge_commitments)[i], 3*crypto_scalarmult_ristretto255_SCALARBYTES, "zk_chal_com[%d]",i);
2504    }
2505    return TOPRF_Update_Err_OK;
2506  }
2507  
2508  #define toprfupdate_peer_zkp3_msg_SIZE (sizeof(TOPRF_Update_Message) + 4*crypto_scalarmult_ristretto255_SCALARBYTES)
2509  static TOPRF_Update_Err peer_step32_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2510    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2511    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] zk4 receive dealers ZK commitments, broadcast zk nonce\x1b[0m\n", ctx->index);
2512    if(input_len != sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp2_msg_SIZE * dealers) return TOPRF_Update_Err_ISize;
2513    if(output_len != toprfupdate_peer_zkp3_msg_SIZE) return TOPRF_Update_Err_OSize;
2514    const size_t cheaters = ctx->cheater_len;
2515  
2516    // verify STP message envelope
2517    const uint8_t *ptr=NULL;
2518    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_zkp2_msg,&ptr);
2519    if(ret!=TOPRF_Update_Err_OK) return ret;
2520  
2521    uint8_t (*zk_challenge_commitments)[dealers][3][crypto_scalarmult_ristretto255_SCALARBYTES] =
2522      (uint8_t (*)[dealers][3][crypto_scalarmult_ristretto255_SCALARBYTES]) ctx->zk_challenge_commitments;
2523  
2524    for(uint8_t i=0;i<dealers;i++,ptr+=toprfupdate_peer_zkp2_msg_SIZE) {
2525      const TOPRF_Update_Message* msg29 = (const TOPRF_Update_Message*) ptr;
2526      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_zkp2_msg_SIZE,toprfupdate_peer_zkp2_msg,i+1,0xff)) continue;
2527  
2528      //dump(msg27->data, crypto_scalarmult_ristretto255_BYTES, "zk_e_nonce_%d commitment", i);
2529      memcpy((*zk_challenge_commitments)[i], msg29->data, 3*crypto_scalarmult_ristretto255_SCALARBYTES);
2530      //uint8_t (*msgs)[3][crypto_scalarmult_ristretto255_SCALARBYTES] = (uint8_t (*)[3][crypto_scalarmult_ristretto255_SCALARBYTES]) (*ctx->zk_challenge_commitments);
2531      //dump(msgs[i][0], crypto_scalarmult_ristretto255_SCALARBYTES, "[%d] M[%d]", ctx->index, i+1);
2532      //dump(msgs[i][1], crypto_scalarmult_ristretto255_SCALARBYTES, "[%d] M1[%d]", ctx->index, i+1);
2533      //dump(msgs[i][2], crypto_scalarmult_ristretto255_SCALARBYTES, "[%d] M2[%d]", ctx->index, i+1);
2534      //
2535    }
2536    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
2537  
2538    TOPRF_Update_Message* msg31 = (TOPRF_Update_Message*) output;
2539    uint8_t *dptr = msg31->data;
2540    memcpy(dptr, ctx->zk_chal_nonce[0], 2*crypto_core_ristretto255_SCALARBYTES);
2541    //dump(dptr, 2*crypto_core_ristretto255_SCALARBYTES, "<zk_nonce[%d][0]", ctx->index);
2542  
2543    if(0!=toprf_send_msg(output, toprfupdate_peer_zkp3_msg_SIZE, toprfupdate_peer_zkp3_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
2544  
2545    ctx->step = TOPRF_Update_Peer_Send_ZK_proofs;
2546  
2547    return TOPRF_Update_Err_OK;
2548  }
2549  
2550  static TOPRF_Update_Err stp_step33_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2551    TOPRF_Update_Err ret;
2552    ret = stp_broadcast(ctx, input, input_len, output, output_len,
2553                         "zk5 broadcast ZK nonces",
2554                         ctx->n, toprfupdate_peer_zkp3_msg_SIZE, toprfupdate_peer_zkp3_msg, TOPRF_Update_STP_Broadcast_ZK_Proofs);
2555    if(ret!=TOPRF_Update_Err_OK) return ret;
2556    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2557    const uint8_t *ptr = input;
2558  
2559    uint8_t zk_challenge_nonces[ctx->n][2][crypto_scalarmult_ristretto255_SCALARBYTES];
2560    // todo? we skip verifying the challenge_nonce commitments, but we also don't base any decision on this
2561    // we do this merely to anticipate how many dealers will be exposed/reconstructed
2562    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_zkp3_msg_SIZE) {
2563      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
2564      const uint8_t *dptr=msg->data;
2565      memcpy(zk_challenge_nonces[i], dptr, 2*crypto_scalarmult_ristretto255_SCALARBYTES);
2566      //dump(dptr, 2*crypto_core_ristretto255_SCALARBYTES, ">zk_nonce[%d][0]", i+1);
2567    }
2568  
2569    uint8_t (*zk_challenge_e_i)[dealers][crypto_scalarmult_ristretto255_SCALARBYTES] =
2570      (uint8_t (*)[dealers][crypto_scalarmult_ristretto255_SCALARBYTES]) ctx->zk_challenge_e_i;
2571    for(unsigned dealer=0;dealer<dealers;dealer++) {
2572      memset((*zk_challenge_e_i)[dealer], 0, crypto_scalarmult_ristretto255_SCALARBYTES);
2573      for(unsigned i=0;i<ctx->n;i++) {
2574        if(dealer==i) continue;
2575        crypto_core_ristretto255_scalar_add((*zk_challenge_e_i)[dealer],
2576                                            (*zk_challenge_e_i)[dealer],
2577                                            zk_challenge_nonces[i][0]);
2578      }
2579      //dump((*zk_challenge_e_i)[p][dealer], crypto_scalarmult_ristretto255_SCALARBYTES, "zk%d_e_%d", p+1, dealer+1);
2580    }
2581    return TOPRF_Update_Err_OK;
2582  }
2583  
2584  static TOPRF_Update_Err aggregate_zk_challenges(TOPRF_Update_PeerState *ctx,
2585                                                  const uint8_t dealers, const uint8_t n,
2586                                                  const uint8_t zk_challenge_nonces[n][2][crypto_scalarmult_ristretto255_SCALARBYTES],
2587                                                  const uint8_t zk_challenge_nonce_commitments[n][crypto_scalarmult_ristretto255_BYTES],
2588                                                  uint8_t zk_challenge_e_i[dealers][crypto_scalarmult_ristretto255_SCALARBYTES]) {
2589    // P_i verifies commitments for e_j,r_j
2590    // P_i computes e'_i:
2591    //  e'_i = Σ e_j
2592    //       j!=i
2593    for(unsigned dealer=0;dealer<dealers;dealer++) {
2594      memset(zk_challenge_e_i[dealer], 0, crypto_scalarmult_ristretto255_SCALARBYTES);
2595      uint8_t zk_challenge_commitment[crypto_scalarmult_ristretto255_BYTES];
2596      for(uint8_t i=0;i<n;i++) {
2597        if(dealer==i) continue;
2598        if(0!=dkg_vss_commit(zk_challenge_nonces[i][0], zk_challenge_nonces[i][1], zk_challenge_commitment)) {
2599          if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "vss-commit got an invalid point %d\n",i);
2600          return TOPRF_Update_Err_VSSCommit;
2601        }
2602        if(memcmp(zk_challenge_commitment, zk_challenge_nonce_commitments[i], crypto_scalarmult_ristretto255_BYTES)!=0) {
2603          if(peer_add_cheater(ctx, 1, i+1, 0) == NULL) return TOPRF_Update_Err_CheatersFull;
2604          if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "invalid e_i nonce commitment from %d\n",i);
2605          dump((const uint8_t*)zk_challenge_nonces[i], 2*crypto_scalarmult_ristretto255_SCALARBYTES, "zk_nonce[%d]", i+1);
2606          dump(zk_challenge_nonce_commitments[i], crypto_scalarmult_ristretto255_BYTES, "zk_challenge_commmitments[%d]", i+1);
2607        }
2608        crypto_core_ristretto255_scalar_add(zk_challenge_e_i[dealer],
2609                                            zk_challenge_e_i[dealer],
2610                                            zk_challenge_nonces[i][0]);
2611      }
2612      //dump(zk_challenge_e_i[dealer], crypto_scalarmult_ristretto255_SCALARBYTES, "zk%d_e",dealer+1);
2613    }
2614    return TOPRF_Update_Err_OK;
2615  }
2616  
2617  static uint8_t* gen_zk_witnesses(const uint8_t self, const uint8_t dealers,
2618                                   const TOPRF_Share *alpha, const TOPRF_Share *beta, const uint8_t *tau,
2619                                   const uint8_t e_i[dealers][crypto_scalarmult_ristretto255_SCALARBYTES],
2620                                   const TOPRF_Update_ZK_params zk_params,
2621                                   const uint8_t lambdas[dealers][crypto_core_ristretto255_SCALARBYTES],
2622                                   uint8_t *wptr
2623                                   ) {
2624    // P_i replies with the following values:
2625    // y   = d + e'_iβ,
2626    crypto_core_ristretto255_scalar_mul(wptr, e_i[self-1], beta[0].value);
2627    crypto_core_ristretto255_scalar_add(wptr, wptr, zk_params.d);
2628    wptr+=crypto_scalarmult_ristretto255_SCALARBYTES;
2629    // w   = s + e'_iσ
2630    crypto_core_ristretto255_scalar_mul(wptr, e_i[self-1], beta[1].value);
2631    crypto_core_ristretto255_scalar_add(wptr, wptr, zk_params.s);
2632    wptr+=crypto_scalarmult_ristretto255_SCALARBYTES;
2633    // z   = x + e'_iα
2634    crypto_core_ristretto255_scalar_mul(wptr, e_i[self-1], alpha[0].value);
2635    crypto_core_ristretto255_scalar_mul(wptr, wptr, lambdas[self-1]);
2636    crypto_core_ristretto255_scalar_add(wptr, wptr, zk_params.x);
2637    wptr+=crypto_scalarmult_ristretto255_SCALARBYTES;
2638    // w_1 = s_1 + e'_iρ
2639    crypto_core_ristretto255_scalar_mul(wptr, e_i[self-1], alpha[1].value);
2640    crypto_core_ristretto255_scalar_mul(wptr, wptr, lambdas[self-1]);
2641    crypto_core_ristretto255_scalar_add(wptr, wptr, zk_params.s_1);
2642    wptr+=crypto_scalarmult_ristretto255_SCALARBYTES;
2643    // w_2 = s_2 + e'_i(τ - σα)
2644    crypto_core_ristretto255_scalar_mul(wptr, beta[1].value, alpha[0].value);
2645    crypto_core_ristretto255_scalar_mul(wptr, wptr, lambdas[self-1]);
2646    crypto_core_ristretto255_scalar_sub(wptr, tau, wptr);
2647    crypto_core_ristretto255_scalar_mul(wptr, e_i[self-1], wptr);
2648    crypto_core_ristretto255_scalar_add(wptr, wptr, zk_params.s_2);
2649    wptr+=crypto_scalarmult_ristretto255_SCALARBYTES;
2650    return wptr;
2651  }
2652  
2653  #define toprfupdate_peer_zkp4_msg_SIZE (sizeof(TOPRF_Update_Message) + 5 * crypto_scalarmult_ristretto255_SCALARBYTES)
2654  static TOPRF_Update_Err peer_step34_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2655    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2656    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] zk6 receive ZK nonces, dealers broadcast zk proof\x1b[0m\n", ctx->index);
2657    if(input_len != sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp3_msg_SIZE * ctx->n) return TOPRF_Update_Err_ISize;
2658    if(output_len != isdealer(ctx->index, ctx->t) * toprfupdate_peer_zkp4_msg_SIZE) return TOPRF_Update_Err_OSize;
2659    const size_t cheaters = ctx->cheater_len;
2660  
2661    // verify STP message envelope
2662    const uint8_t *ptr=NULL;
2663    int ret = unwrap_envelope(ctx, input, input_len, toprfupdate_stp_bc_zkp3_msg, &ptr);
2664    if(ret!=TOPRF_Update_Err_OK) return ret;
2665  
2666    uint8_t (*zk_challenge_nonces)[ctx->n][2][crypto_scalarmult_ristretto255_SCALARBYTES] =
2667                      (uint8_t (*)[ctx->n][2][crypto_scalarmult_ristretto255_SCALARBYTES]) ctx->zk_challenge_nonces;
2668    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_zkp3_msg_SIZE) {
2669      const TOPRF_Update_Message* msg31 = (const TOPRF_Update_Message*) ptr;
2670      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_zkp3_msg_SIZE,toprfupdate_peer_zkp3_msg,i+1,0xff)) continue;
2671  
2672      const uint8_t *dptr=msg31->data;
2673      memcpy((*zk_challenge_nonces)[i], dptr, 2*crypto_scalarmult_ristretto255_SCALARBYTES);
2674      //dump(dptr, 2*crypto_core_ristretto255_SCALARBYTES, ">zk_nonce[%d][0]", i+1);
2675    }
2676    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
2677  
2678    uint8_t (*zk_challenge_e_i)[dealers][crypto_scalarmult_ristretto255_SCALARBYTES] =
2679                   (uint8_t (*)[dealers][crypto_scalarmult_ristretto255_SCALARBYTES]) ctx->zk_challenge_e_i;
2680    uint8_t (*zk_challenge_nonce_commitments)[ctx->n][crypto_scalarmult_ristretto255_BYTES] =
2681                                 (uint8_t (*)[ctx->n][crypto_scalarmult_ristretto255_BYTES]) ctx->zk_challenge_nonce_commitments;
2682  
2683    ret = aggregate_zk_challenges(ctx, dealers, ctx->n, (*zk_challenge_nonces), (*zk_challenge_nonce_commitments), (*zk_challenge_e_i));
2684    if(ret!=TOPRF_Update_Err_OK) return ret;
2685  
2686    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
2687  
2688    if(ctx->index>dealers) { // non-dealers are done
2689      ctx->step = TOPRF_Update_Peer_Verify_ZK_proofs;
2690      return TOPRF_Update_Err_OK;
2691    }
2692  
2693    // dealers only
2694    TOPRF_Update_Message* msg31 = (TOPRF_Update_Message*) output;
2695    uint8_t *wptr=msg31->data;
2696    wptr=gen_zk_witnesses(ctx->index, dealers, ctx->kc0_share, ctx->p_share, ctx->k0p_tau,
2697                     (*zk_challenge_e_i), ctx->zk_params, (*ctx->lambdas), wptr);
2698  
2699    if(0!=toprf_send_msg(output, toprfupdate_peer_zkp4_msg_SIZE, toprfupdate_peer_zkp4_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
2700  
2701    ctx->step = TOPRF_Update_Peer_Verify_ZK_proofs;
2702    return TOPRF_Update_Err_OK;
2703  }
2704  
2705  static TOPRF_Update_Err zk_verify_proof(TOPRF_Update_PeerState *ctx,
2706                                          const uint8_t self,
2707                                          const uint8_t prover,
2708                                          const uint8_t A_i[crypto_core_ristretto255_BYTES],
2709                                          const uint8_t B_i[crypto_core_ristretto255_BYTES],
2710                                          const uint8_t C_i0[crypto_core_ristretto255_BYTES],
2711                                          const uint8_t e_i[crypto_scalarmult_ristretto255_SCALARBYTES],
2712                                          const uint8_t zk_challenge_commitments[3][crypto_scalarmult_ristretto255_SCALARBYTES],
2713                                          const uint8_t lambda[crypto_core_ristretto255_SCALARBYTES],
2714                                          const TOPRF_Update_ZK_proof proof,
2715                                          uint8_t *fails) {
2716    uint8_t v0[crypto_scalarmult_ristretto255_BYTES];
2717    uint8_t v1[crypto_scalarmult_ristretto255_BYTES];
2718    const uint8_t *M  = zk_challenge_commitments[0];
2719    const uint8_t *M1 = zk_challenge_commitments[1];
2720    const uint8_t *M2 = zk_challenge_commitments[2];
2721    //   g^y * h^w   == M * B^e'_i
2722    if(0!=dkg_vss_commit(proof.y, proof.w, v0)) return TOPRF_Update_Err_VSSCommit;
2723    if(crypto_scalarmult_ristretto255(v1, e_i, B_i)) return TOPRF_Update_Err_InvPoint;
2724    crypto_core_ristretto255_add(v1, M, v1);
2725    if(memcmp(v1, v0, crypto_scalarmult_ristretto255_BYTES)!=0) {
2726      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] failed g^y * h^w   == M * B^e'_i for dealer %d\n"NORMAL, self, prover+1);
2727      dump(v1, crypto_scalarmult_ristretto255_BYTES, "lhs");
2728      dump(v0, crypto_scalarmult_ristretto255_BYTES, "rhs");
2729      fails[1+fails[0]++]=prover+1;
2730      if(self!=0 && peer_add_cheater(ctx, 1, prover+1, 0xff) == NULL) return TOPRF_Update_Err_CheatersFull;
2731      return TOPRF_Update_Err_OK;
2732    }
2733  
2734    //   g^z * h^w_1 == M_1 * A^e'_i
2735    if(0!=dkg_vss_commit(proof.z, proof.w_1, v0)) return TOPRF_Update_Err_VSSCommit;
2736    if(crypto_scalarmult_ristretto255(v1, e_i, A_i)) return TOPRF_Update_Err_InvPoint;
2737    if(crypto_scalarmult_ristretto255(v1, lambda, v1)) return TOPRF_Update_Err_InvPoint;
2738    crypto_core_ristretto255_add(v1, M1, v1);
2739    if(memcmp(v1, v0, crypto_scalarmult_ristretto255_BYTES)!=0) {
2740      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] failed g^z * h^w_1 == M_1 * A^e'_i for dealer %d\n"NORMAL, self, prover+1);
2741      dump(v1, crypto_scalarmult_ristretto255_BYTES, "lhs");
2742      dump(v0, crypto_scalarmult_ristretto255_BYTES, "rhs");
2743      fails[1+fails[0]++]=prover+1;
2744      if(self!=0 && peer_add_cheater(ctx, 3, prover+1, 0xff) == NULL) return TOPRF_Update_Err_CheatersFull;
2745      return TOPRF_Update_Err_OK;
2746    }
2747  
2748    //   B^z * h^w_2 == M_2 * C^e'_i
2749    if(crypto_scalarmult_ristretto255(v0, proof.z, B_i)) return TOPRF_Update_Err_InvPoint;
2750    // we abuse v1 as a temp storage, v1 = h^w_2
2751    if(crypto_scalarmult_ristretto255(v1, proof.w_2, H)) return TOPRF_Update_Err_InvPoint;
2752    crypto_core_ristretto255_add(v0, v0, v1);
2753  
2754    if(crypto_scalarmult_ristretto255(v1, e_i, C_i0)) return TOPRF_Update_Err_InvPoint;
2755    crypto_core_ristretto255_add(v1, M2, v1);
2756    if(memcmp(v1, v0, crypto_scalarmult_ristretto255_BYTES)!=0) {
2757      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] failed B^z * h^w_2 == M_2 * C^e'_i for dealer %d\n"NORMAL, self, prover+1);
2758      dump(v1, crypto_scalarmult_ristretto255_BYTES, "lhs");
2759      dump(v0, crypto_scalarmult_ristretto255_BYTES, "rhs");
2760      fails[1+fails[0]++]=prover+1;
2761      if(self!=0 && peer_add_cheater(ctx, 5, prover+1, 0xff) == NULL) return TOPRF_Update_Err_CheatersFull;
2762      return TOPRF_Update_Err_OK;
2763    }
2764  
2765    return TOPRF_Update_Err_OK;
2766  }
2767  
2768  static TOPRF_Update_Err stp_step35_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2769    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2770    TOPRF_Update_Err ret;
2771    ret = stp_broadcast(ctx, input, input_len, output, output_len,
2772                        "zk7 broadcast ZK proofs",
2773                        dealers, toprfupdate_peer_zkp4_msg_SIZE, toprfupdate_peer_zkp4_msg, TOPRF_Update_STP_Broadcast_Mult_Ci);
2774    if(ret!=TOPRF_Update_Err_OK) return ret;
2775  
2776    uint8_t fails[dealers+1];
2777    memset(fails, 0, sizeof fails);
2778    const uint8_t (*zk_challenge_commitments)[dealers][3][crypto_scalarmult_ristretto255_SCALARBYTES] =
2779                           (const uint8_t (*)[dealers][3][crypto_scalarmult_ristretto255_SCALARBYTES]) ctx->zk_challenge_commitments;
2780    const uint8_t (*zk_challenge_e_i)[dealers][crypto_scalarmult_ristretto255_SCALARBYTES] =
2781                         (uint8_t (*)[dealers][crypto_scalarmult_ristretto255_SCALARBYTES]) ctx->zk_challenge_e_i;
2782    const uint8_t *ptr = input;
2783  
2784    uint8_t indexes[dealers];
2785    for(uint8_t i=0;i<dealers;i++) indexes[i]=i+1;
2786    uint8_t lambdas[dealers][dealers][crypto_core_ristretto255_SCALARBYTES];
2787    invertedVDMmatrix(dealers, indexes, lambdas);
2788  
2789    for(uint8_t i=0;i<dealers;i++,ptr+=toprfupdate_peer_zkp4_msg_SIZE) {
2790      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
2791      const TOPRF_Update_ZK_proof (*proof) = (const TOPRF_Update_ZK_proof*) msg->data;
2792      ret = zk_verify_proof(NULL, 0, i,
2793                            (*ctx->kc0_commitments)[i],
2794                            (*ctx->p_commitments)[i],
2795                            (*ctx->k0p_commitments)[i*(ctx->n+1)],
2796                            (*zk_challenge_e_i)[i],
2797                            (*zk_challenge_commitments)[i],
2798                            lambdas[0][i],
2799                            (*proof),
2800                            fails);
2801      if(ret != TOPRF_Update_Err_OK) return ret;
2802    }
2803  
2804    ctx->p_complaints_len = 0;
2805    const uint8_t *fails_len = fails;
2806    const uint8_t *xfails = fails_len+1;
2807    handle_complaints(dealers, 0, *fails_len, xfails, &ctx->p_complaints_len, ctx->p_complaints, 0, 0, 0);
2808  
2809    if(ctx->p_complaints_len != 0) {
2810      dump((uint8_t*) ctx->p_complaints, ctx->p_complaints_len*sizeof(uint16_t), "[!] complaints");
2811      ctx->step = TOPRF_Update_STP_Broadcast_ZK_Disclosures;
2812    }
2813  
2814    return TOPRF_Update_Err_OK;
2815  }
2816  
2817  static TOPRF_Update_Err peer_step36_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len) {
2818    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2819    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] zk8 verify ZK proofs, accuse cheaters\x1b[0m\n", ctx->index);
2820    if(input_len != sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp4_msg_SIZE * dealers) return TOPRF_Update_Err_ISize;
2821    //const size_t cheaters = ctx->cheater_len;
2822  
2823    // verify STP message envelope
2824    const uint8_t *ptr=NULL;
2825    int ret = unwrap_envelope(ctx, input, input_len, toprfupdate_stp_bc_zkp4_msg, &ptr);
2826    if(ret!=TOPRF_Update_Err_OK) return ret;
2827  
2828    uint8_t fails[dealers+1];
2829    memset(fails, 0, sizeof fails);
2830    const uint8_t (*zk_challenge_commitments)[dealers][3][crypto_scalarmult_ristretto255_SCALARBYTES] =
2831                           (const uint8_t (*)[dealers][3][crypto_scalarmult_ristretto255_SCALARBYTES]) ctx->zk_challenge_commitments;
2832    const uint8_t (*zk_challenge_e_i)[dealers][crypto_scalarmult_ristretto255_SCALARBYTES] =
2833                         (uint8_t (*)[dealers][crypto_scalarmult_ristretto255_SCALARBYTES]) ctx->zk_challenge_e_i;
2834  
2835    for(uint8_t i=0;i<dealers;i++,ptr+=toprfupdate_peer_zkp4_msg_SIZE) {
2836      const TOPRF_Update_Message* msg33 = (const TOPRF_Update_Message*) ptr;
2837      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_zkp4_msg_SIZE,toprfupdate_peer_zkp4_msg,i+1,0xff)) continue;
2838  
2839      const TOPRF_Update_ZK_proof (*proof) = (const TOPRF_Update_ZK_proof*) msg33->data;
2840      ret = zk_verify_proof(ctx, ctx->index, i,
2841                            (*ctx->kc0_commitments)[i],
2842                            (*ctx->p_commitments)[i],
2843                            (*ctx->k0p_commitments)[i*(ctx->n+1)],
2844                            (*zk_challenge_e_i)[i],
2845                            (*zk_challenge_commitments)[i],
2846                            (*ctx->lambdas)[i],
2847                            (*proof),
2848                            fails);
2849      if(ret != TOPRF_Update_Err_OK) return ret;
2850    }
2851    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
2852  
2853    ctx->p_complaints_len = 0;
2854    const uint8_t *fails_len = &fails[0];
2855    const uint8_t *xfails = fails_len+1;
2856    handle_complaints(dealers, ctx->index, *fails_len, xfails, &ctx->p_complaints_len, ctx->p_complaints, 0, 0, 0);
2857  
2858    ctx->prev = ctx->step;
2859    if(ctx->p_complaints_len == 0) {
2860      ctx->step = TOPRF_Update_Peer_Send_Mult_Ci;
2861    } else {
2862      dump((uint8_t*) ctx->p_complaints, ctx->p_complaints_len*sizeof(uint16_t), "[%d] complaints", ctx->index);
2863      ctx->step = TOPRF_Update_Peer_Disclose_ZK_Cheaters;
2864    }
2865  
2866    return TOPRF_Update_Err_OK;
2867  }
2868  
2869  #define toprfupdate_peer_zk_disclose_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message)                         \
2870                                                      +  ctx->p_complaints_len * TOPRF_Share_BYTES * 2     )
2871  static TOPRF_Update_Err peer_zkproof_disclose(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
2872    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] zk-reconst1 disclose shares of dealers unable to prove c=a*b\n"NORMAL, ctx->index);
2873    if(output_len != toprf_update_peer_output_size(ctx)) return TOPRF_Update_Err_OSize;
2874  
2875    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
2876    uint8_t *wptr = msg->data;
2877  
2878    TOPRF_Update_Err ret;
2879    ret = disclose_shares(ctx->n, ctx->index, "k0p", ctx->p_complaints_len, ctx->p_complaints, (*ctx->k0p_shares), &wptr);
2880    if(ret != TOPRF_Update_Err_OK) return ret;
2881  
2882    if(0!=toprf_send_msg(output, output_len, toprfupdate_peer_zk_disclose_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
2883  
2884    ctx->step = TOPRF_Update_Peer_Reconstruct_ZK_Shares;
2885    return TOPRF_Update_Err_OK;
2886  }
2887  
2888  #define toprfupdate_stp_bc_zkp_disclose_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + (toprfupdate_peer_zk_disclose_msg_SIZE(ctx) * ctx->n))
2889  static TOPRF_Update_Err stp_bc_zk_disclosures(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2890    TOPRF_Update_Err ret;
2891    ret = stp_broadcast(ctx, input, input_len, output, output_len,
2892                        "zk-reconst2 broadcast shares of dealers failing ZK proofs",
2893                        ctx->n, toprfupdate_peer_zk_disclose_msg_SIZE(ctx), toprfupdate_peer_zk_disclose_msg, TOPRF_Update_STP_Broadcast_Mult_Ci);
2894    if(ret != TOPRF_Update_Err_OK) return ret;
2895  
2896    TOPRF_Share k0p_shares[ctx->p_complaints_len][ctx->n][2];
2897    const uint8_t *ptr = input;
2898    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_zk_disclose_msg_SIZE(ctx)) {
2899      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
2900      const uint8_t *dptr = msg->data;
2901      for(unsigned j=0;j<ctx->p_complaints_len;j++) {
2902        memcpy(k0p_shares[j][msg->from-1], dptr, TOPRF_Share_BYTES*2);
2903        dptr+=TOPRF_Share_BYTES*2;
2904      }
2905    }
2906  
2907    TOPRF_Share secret[2];
2908    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2909    uint8_t (*c)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES]) (*ctx->k0p_commitments);
2910    for(unsigned i=0;i<ctx->p_complaints_len;i++) {
2911      const uint8_t accused = (uint8_t) (ctx->p_complaints[i] & 0xff);
2912      if(0!=dkg_vss_reconstruct(ctx->t, 0, ctx->n, k0p_shares[i], &(*c)[accused-1][1], secret[0].value, secret[1].value)) return TOPRF_Update_Err_Reconstruct;
2913      dump(secret[0].value, sizeof secret[0].value, "reconstructed lab");
2914      if(0!=dkg_vss_commit(secret[0].value, secret[1].value, (*c)[accused-1][0])) return TOPRF_Update_Err_VSSCommit;
2915    }
2916  
2917    return TOPRF_Update_Err_OK;
2918  }
2919  
2920  static TOPRF_Update_Err peer_step39_handler(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len);
2921  static TOPRF_Update_Err peer_reconst_zk_shares(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
2922    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] zk-reconst3 reconstruct secrets of dealers failing ZK proof\x1b[0m\n", ctx->index);
2923    if(input_len!= sizeof(TOPRF_Update_Message) + toprfupdate_peer_zk_disclose_msg_SIZE(ctx) * ctx->n) return TOPRF_Update_Err_ISize;
2924  
2925    // verify STP message envelope
2926    const uint8_t *ptr=NULL;
2927    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_zk_disclose_msg,&ptr);
2928    if(ret!=TOPRF_Update_Err_OK) return ret;
2929  
2930    TOPRF_Share k0p_shares[ctx->p_complaints_len][ctx->n][2];
2931    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_zk_disclose_msg_SIZE(ctx)) {
2932      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
2933      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_zk_disclose_msg_SIZE(ctx),toprfupdate_peer_zk_disclose_msg,i+1,0xff)) continue;
2934      const uint8_t *dptr = msg->data;
2935      for(unsigned j=0;j<ctx->p_complaints_len;j++) {
2936        memcpy(k0p_shares[j][msg->from-1], dptr, TOPRF_Share_BYTES*2);
2937        dptr+=TOPRF_Share_BYTES*2;
2938      }
2939    }
2940  
2941    TOPRF_Share secret[2];
2942    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2943    uint8_t (*c)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES]) (*ctx->k0p_commitments);
2944    for(unsigned i=0;i<ctx->p_complaints_len;i++) {
2945      const uint8_t accused = (uint8_t) (ctx->p_complaints[i] & 0xff);
2946      if(0!=dkg_vss_reconstruct(ctx->t, 0, ctx->n, k0p_shares[i], &(*c)[accused-1][1], secret[0].value, secret[1].value)) return TOPRF_Update_Err_Reconstruct;
2947      dump(secret[0].value, sizeof secret[0].value, "reconstructed lab");
2948      if(0!=dkg_vss_commit(secret[0].value, secret[1].value, (*c)[accused-1][0])) return TOPRF_Update_Err_VSSCommit;
2949    }
2950  
2951    // reset my_complaints
2952    ctx->my_p_complaints_len = 0;
2953    memset(ctx->my_p_complaints, 0, ctx->n);
2954  
2955    return peer_step39_handler(ctx, output, output_len);
2956  }
2957  
2958  static TOPRF_Update_Err compute_mul_share(const uint8_t dealers,
2959                                const TOPRF_Share shares_i[][2],
2960                                TOPRF_Share rshare[2],
2961                                uint8_t commitment[crypto_scalarmult_ristretto255_BYTES]) {
2962    // step 3. P_i computes:
2963    //      2t+1
2964    //  γ_i = Σ c_ji
2965    //       j=1
2966    //  which is a share of γ = αβ, via random polynomial of degree t and
2967    //      2t+1
2968    //  τ_i = Σ τ_ji
2969    //       j=1
2970    memcpy((uint8_t*) &rshare[0], (const uint8_t*) &shares_i[0][0], TOPRF_Share_BYTES);
2971    memcpy((uint8_t*) &rshare[1], (const uint8_t*) &shares_i[0][1], TOPRF_Share_BYTES);
2972    for(unsigned i=1;i<dealers;i++) {
2973      crypto_core_ristretto255_scalar_add(rshare[0].value, rshare[0].value, shares_i[i][0].value);
2974      crypto_core_ristretto255_scalar_add(rshare[1].value, rshare[1].value, shares_i[i][1].value);
2975    }
2976    // step 4. P_i computes and broadcasts
2977    //    𝓒_i = 𝓗(γ_i, τ_i)
2978    //        = g^(γ_i)*h^(τ_i)
2979    //
2980    //        2t+1
2981    //        = Π 𝓒_ji
2982    //         j=1
2983    if(0!=dkg_vss_commit(rshare[0].value, rshare[1].value, commitment)) return TOPRF_Update_Err_VSSCommit;
2984    return TOPRF_Update_Err_OK;
2985  }
2986  
2987  #define toprfupdate_peer_mult3_msg_SIZE (sizeof(TOPRF_Update_Message) + crypto_scalarmult_ristretto255_BYTES)
2988  static TOPRF_Update_Err peer_step39_handler(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
2989    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
2990    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] final1 aggregate shares into final results and broadcast their commitment\x1b[0m\n", ctx->index);
2991    if(output_len != toprfupdate_peer_mult3_msg_SIZE) return TOPRF_Update_Err_OSize;
2992  
2993    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
2994    int ret = compute_mul_share(dealers ,(*ctx->k0p_shares), ctx->k0p_share, ctx->k0p_commitment);
2995    memcpy(msg->data, ctx->k0p_commitment, crypto_scalarmult_ristretto255_BYTES);
2996    if(ret!=TOPRF_Update_Err_OK) return ret;
2997  
2998    // use this below to calculate all commitments for the other peers
2999    uint8_t Cx_i[crypto_scalarmult_ristretto255_BYTES];
3000    uint8_t (*c)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES]) ctx->k0p_commitments;
3001    memcpy(Cx_i, (*c)[0][ctx->index], crypto_scalarmult_ristretto255_BYTES);
3002    for(unsigned j=1;j<dealers;j++) {
3003      crypto_core_ristretto255_add(Cx_i, Cx_i, (*c)[j][ctx->index]);
3004    }
3005    // todo this check might not be needed
3006    if(memcmp(Cx_i, ctx->k0p_commitment, sizeof Cx_i) != 0) {
3007      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] failed to verify commitment for k0p share"NORMAL, ctx->index);
3008      // todo cheater handling? who would be the cheater here?
3009      return TOPRF_Update_Err_CommmitmentsMismatch; // probably cannot happen?
3010    }
3011  
3012    if(0!=toprf_send_msg(output, toprfupdate_peer_mult3_msg_SIZE, toprfupdate_peer_mult3_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
3013  
3014    ctx->step = TOPRF_Update_Peer_Final_VSPS_Checks;
3015    return TOPRF_Update_Err_OK;
3016  }
3017  
3018  #define toprfupdate_stp_bc_mult3_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + toprfupdate_peer_mult3_msg_SIZE * ctx->n)
3019  static TOPRF_Update_Err stp_step40_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
3020    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
3021    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] final2 broadcast final mult commitments\x1b[0m\n");
3022    if(input_len != ctx->n * toprfupdate_peer_mult3_msg_SIZE) return TOPRF_Update_Err_ISize;
3023    if(output_len != toprfupdate_stp_bc_mult3_msg_SIZE(ctx)) return TOPRF_Update_Err_OSize;
3024    //const size_t cheaters = ctx->cheater_len;
3025  
3026    const uint8_t *ptr = input;
3027    uint8_t *wptr = ((TOPRF_Update_Message *) output)->data;
3028    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_mult3_msg_SIZE) {
3029      if(stp_recv_msg(ctx,ptr,toprfupdate_peer_mult3_msg_SIZE, toprfupdate_peer_mult3_msg,i+1,0xff)) continue;
3030      const TOPRF_Update_Message *msg = (const TOPRF_Update_Message *) ptr;
3031      // keep a copy of all commitments for final verification and for check before reconstructing r and r'
3032      memcpy((*ctx->k0p_final_commitments)[i], msg->data, crypto_scalarmult_ristretto255_BYTES);
3033  
3034      memcpy(wptr, ptr, toprfupdate_peer_mult3_msg_SIZE);
3035      wptr+=toprfupdate_peer_mult3_msg_SIZE;
3036  
3037    }
3038    //if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
3039  
3040    uint8_t fails[dealers+1];
3041    memset(fails, 0, sizeof fails);
3042    uint8_t (*c)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES]) ctx->k0p_commitments;
3043    TOPRF_Update_Err ret;
3044    ret = ft_or_full_vsps(ctx->n+1, ctx->t, dealers, 0, (*ctx->k0p_final_commitments), c,
3045                          "VSPS failed k0p, doing full VSPS check on all dealers",
3046                          "VSPS failed k0p",
3047                          "ERROR, could not find and dealer commitments that fail the VSPS check",
3048                          fails, &fails[1]);
3049    if(ret!=TOPRF_Update_Err_OK) return ret;
3050  
3051    ctx->p_complaints_len = 0;
3052  
3053    const uint8_t *fails_len = fails;
3054    const uint8_t *xfails = fails_len+1;
3055    handle_complaints(dealers, 0, *fails_len, xfails, &ctx->p_complaints_len, ctx->p_complaints, 0, 0, 0);
3056  
3057    if(0!=toprf_send_msg(output, output_len, toprfupdate_stp_bc_mult3_msg, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
3058    // add broadcast msg to transcript
3059    update_transcript(&ctx->transcript_state, output, output_len);
3060  
3061    if(ctx->p_complaints_len != 0) {
3062      dump((uint8_t*) ctx->p_complaints, ctx->p_complaints_len*sizeof(uint16_t), "[!] complaints");
3063      ctx->step = TOPRF_Update_STP_Broadcast_VSPS_Disclosures;
3064    } else {
3065      ctx->step = TOPRF_Update_STP_Reconstruct_Delta;
3066    }
3067  
3068    return TOPRF_Update_Err_OK;
3069  }
3070  
3071  static TOPRF_Update_Err peer_step41_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len) {
3072    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
3073    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] final3 receive final mult commitments, fast-track VSPS final results\x1b[0m\n", ctx->index);
3074    if(input_len != toprfupdate_stp_bc_mult3_msg_SIZE(ctx)) return TOPRF_Update_Err_ISize;
3075    const size_t cheaters = ctx->cheater_len;
3076  
3077    // verify STP message envelope
3078    const uint8_t *ptr=NULL;
3079    int ret = unwrap_envelope(ctx, input, input_len, toprfupdate_stp_bc_mult3_msg, &ptr);
3080    if(ret!=TOPRF_Update_Err_OK) return ret;
3081  
3082    uint8_t (*C_i)[crypto_scalarmult_ristretto255_BYTES] = (*ctx->p_commitments);
3083    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_mult3_msg_SIZE) {
3084      const TOPRF_Update_Message* msg37 = (const TOPRF_Update_Message*) ptr;
3085      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_mult3_msg_SIZE,toprfupdate_peer_mult3_msg,i+1,0xff)) continue;
3086      memcpy(C_i[i], msg37->data, crypto_scalarmult_ristretto255_BYTES);
3087    }
3088    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
3089  
3090    uint8_t fails[dealers+1];
3091    memset(fails, 0, sizeof fails);
3092  
3093    //liboprf_debug=0;
3094    //for(unsigned i=0;i<dealers;i++) {
3095    //  if(0!=toprf_mpc_vsps_check(ctx->t-1, (const uint8_t (*)[crypto_core_ristretto255_BYTES]) (*ctx->k0p_commitments)[i*(ctx->n+1)])) {
3096    //    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] k0p vsps fails [%d]\n"NORMAL, ctx->index, i+1);
3097    //  }
3098    //}
3099    //liboprf_debug=1;
3100  
3101    uint8_t (*c)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES]) ctx->k0p_commitments;
3102    ret = ft_or_full_vsps(ctx->n+1, ctx->t, dealers, ctx->index, C_i, c,
3103                          "VSPS failed k0p, doing full VSPS check on all dealers",
3104                          "VSPS failed k0p",
3105                          "ERROR, could not find and dealer commitments that fail the VSPS check",
3106                          fails, &fails[1]);
3107    if(ret!=TOPRF_Update_Err_OK) return ret;
3108  
3109    ctx->p_complaints_len = 0;
3110    const uint8_t *fails_len = fails;
3111    const uint8_t *xfails = fails_len+1;
3112    handle_complaints(dealers, ctx->index, *fails_len, xfails, &ctx->p_complaints_len, ctx->p_complaints, 0, 0, 0);
3113  
3114    ctx->prev = ctx->step;
3115    if(ctx->p_complaints_len == 0) {
3116      ctx->step = TOPRF_Update_Peer_Send_k0p_Share;
3117    } else {
3118      dump((uint8_t*) ctx->p_complaints, ctx->p_complaints_len*sizeof(uint16_t), "[%d] complaints", ctx->index);
3119      ctx->step = TOPRF_Update_Peer_Disclose_VSPS_Cheaters;
3120    }
3121  
3122    return TOPRF_Update_Err_OK;
3123  }
3124  
3125  #define toprfupdate_peer_vsps_disclose_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message)                         \
3126                                                        +  ctx->p_complaints_len * TOPRF_Share_BYTES * 2     )
3127  static TOPRF_Update_Err peer_vsps_disclose(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
3128    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] final-reconst1 disclose shares of dealers failing vsps\n"NORMAL, ctx->index);
3129    if(output_len != toprf_update_peer_output_size(ctx)) return TOPRF_Update_Err_OSize;
3130  
3131    TOPRF_Update_Message* msg = (TOPRF_Update_Message*) output;
3132    uint8_t *wptr = msg->data;
3133  
3134    TOPRF_Update_Err ret;
3135    ret = disclose_shares(ctx->n, ctx->index, "k0p", ctx->p_complaints_len, ctx->p_complaints, (*ctx->k0p_shares), &wptr);
3136    if(ret != TOPRF_Update_Err_OK) return ret;
3137  
3138    if(0!=toprf_send_msg(output, output_len, toprfupdate_peer_vsps_disclose_msg, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
3139  
3140    ctx->step = TOPRF_Update_Peer_Reconstruct_VSPS_Shares;
3141    return TOPRF_Update_Err_OK;
3142  }
3143  
3144  static int vss_reshare(const uint8_t n,
3145                         const uint8_t threshold,
3146                         const uint8_t *prk,
3147                         const uint8_t secret[crypto_core_ristretto255_SCALARBYTES],
3148                         TOPRF_Share shares[n][2],
3149                         uint8_t commitments[n][crypto_core_ristretto255_BYTES],
3150                         uint8_t blind[crypto_core_ristretto255_SCALARBYTES]) {
3151    if(threshold==0) return 1;
3152    if(secret==NULL) return 1;
3153    uint8_t a[threshold][crypto_core_ristretto255_SCALARBYTES];
3154    uint8_t b[threshold][crypto_core_ristretto255_SCALARBYTES];
3155    memcpy(a[0], secret, crypto_core_ristretto255_SCALARBYTES);
3156  
3157    // todo inlude also the idx of the dealer in the ctx.
3158    char share_ctx[] = "k0p lambda * a * b re-sharing";
3159    char blind_ctx[] = "k0p blind re-sharing";
3160  
3161    for(int k=0;k<threshold;k++) {
3162      uint8_t random[64];
3163      if(k!=0) {
3164        crypto_kdf_hkdf_sha256_expand(random, sizeof random, share_ctx, sizeof(share_ctx) - 1, prk);
3165        crypto_core_ristretto255_scalar_reduce(a[k], random);
3166      }
3167      crypto_kdf_hkdf_sha256_expand(random, sizeof random, blind_ctx, sizeof(blind_ctx) - 1, prk);
3168      crypto_core_ristretto255_scalar_reduce(b[k], random);
3169    }
3170  
3171    if(blind!=NULL) {
3172      memcpy(blind, b[0], crypto_core_ristretto255_SCALARBYTES);
3173    }
3174  
3175    for(uint8_t j=1;j<=n;j++) {
3176      //f(x) = a_0 + a_1*x + a_2*x^2 + a_3*x^3 + ⋯ + a_(t)*x^(t)
3177      polynom(j, threshold, a, &shares[j-1][0]);
3178      //f'(x) = b_0 + b_1*x + b_2*x^2 + b_3*x^3 + ⋯ + b_(t)*x^(t)
3179      polynom(j, threshold, b, &shares[j-1][1]);
3180  
3181      if(0!=dkg_vss_commit(shares[j-1][0].value, shares[j-1][1].value, commitments[j-1])) return 1;
3182    }
3183  
3184    return 0;
3185  }
3186  
3187  static TOPRF_Update_Err stp_reshare(TOPRF_Update_STPState *ctx
3188                                  ,const uint16_t complaints_len
3189                                  ,const uint16_t complaints[complaints_len]
3190                                  ,const TOPRF_Share shares[complaints_len][ctx->n][2]
3191                                  ,uint8_t (*commitments)[][crypto_core_ristretto255_BYTES]) {
3192    if(complaints_len==0) return TOPRF_Update_Err_OK;
3193  
3194    uint8_t secrets[complaints_len][2][crypto_core_ristretto255_SCALARBYTES];
3195    TOPRF_Update_Err ret;
3196    ret = reconstruct(ctx->n, ctx->t, "k0p", complaints_len,complaints, shares, commitments, secrets);
3197    if(ret != TOPRF_Update_Err_OK) return ret;
3198  
3199    TOPRF_Share reshares[ctx->n][2];
3200    for(unsigned i=0;i<complaints_len;i++) {
3201      if(vss_reshare(ctx->n, ctx->t, ctx->sessionid, secrets[i][0], reshares, &(*commitments)[1], secrets[i][1])) return TOPRF_Update_Err_VSSShare;
3202      if(0!=dkg_vss_commit(secrets[i][0], secrets[i][1], (*commitments)[0])) return 1;
3203  
3204      int _debug=liboprf_debug; liboprf_debug=0;
3205      if(0!=toprf_mpc_vsps_check(ctx->t-1, (*commitments))) {
3206        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[!] VSPS asdfasdf failed k0p\n"NORMAL);
3207      }
3208      liboprf_debug=_debug;
3209      dump((uint8_t*) (*commitments), (ctx->n+1U)*crypto_core_ristretto255_BYTES, "reshared k0p commitments");
3210    }
3211    return TOPRF_Update_Err_OK;
3212  }
3213  
3214  #define toprfupdate_stp_bc_vsps_disclose_msg_SIZE(ctx) (sizeof(TOPRF_Update_Message) + (toprfupdate_peer_vsps_disclose_msg_SIZE(ctx) * ctx->n))
3215  static TOPRF_Update_Err stp_bc_vsps_disclosures(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
3216    TOPRF_Update_Err ret;
3217    ret = stp_broadcast(ctx, input, input_len, output, output_len,
3218                        "final-reconst2 broadcast shares of dealers failing vsps check",
3219                        ctx->n, toprfupdate_peer_vsps_disclose_msg_SIZE(ctx), toprfupdate_peer_vsps_disclose_msg, TOPRF_Update_STP_Reconstruct_Delta);
3220    if(ret != TOPRF_Update_Err_OK) return ret;
3221  
3222    TOPRF_Share k0p_shares[ctx->p_complaints_len][ctx->n][2];
3223    const uint8_t *ptr = input;
3224    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_vsps_disclose_msg_SIZE(ctx)) {
3225      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
3226      const uint8_t *dptr = msg->data;
3227      for(unsigned j=0;j<ctx->p_complaints_len;j++) {
3228        memcpy(k0p_shares[j][msg->from-1], dptr, TOPRF_Share_BYTES*2);
3229        dptr+=TOPRF_Share_BYTES*2;
3230      }
3231    }
3232  
3233    ret = stp_reshare(ctx, ctx->p_complaints_len, ctx->p_complaints, k0p_shares, ctx->k0p_commitments);
3234    if(ret!=TOPRF_Update_Err_OK) return ret;
3235  
3236    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
3237    uint8_t (*c)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES] = (uint8_t (*)[dealers][ctx->n+1][crypto_core_ristretto255_BYTES]) ctx->k0p_commitments;
3238    for(unsigned i=0;i<ctx->n;i++) {
3239      memcpy((*ctx->k0p_final_commitments)[i], (*c)[0][i+1], crypto_scalarmult_ristretto255_BYTES);
3240      for(unsigned j=1;j<dealers;j++) {
3241        crypto_core_ristretto255_add((*ctx->k0p_final_commitments)[i], (*ctx->k0p_final_commitments)[i], (*c)[j][i+1]);
3242      }
3243    }
3244  
3245    return TOPRF_Update_Err_OK;
3246  }
3247  
3248  static TOPRF_Update_Err peer_reshare(TOPRF_Update_PeerState *ctx
3249                                       ,uint16_t *complaints_len
3250                                       ,uint16_t complaints[*complaints_len]
3251                                       ,const TOPRF_Share shares[*complaints_len][ctx->n][2]
3252                                       ,TOPRF_Share my_shares[(ctx->t-1)*2+1][2]
3253                                       ,TOPRF_Share my_share[2]
3254                                       ,uint8_t (*commitments)[][crypto_core_ristretto255_BYTES]) {
3255    if(*complaints_len==0) return TOPRF_Update_Err_OK;
3256  
3257    uint8_t secrets[*complaints_len][2][crypto_core_ristretto255_SCALARBYTES];
3258    TOPRF_Update_Err ret;
3259    ret = reconstruct(ctx->n, ctx->t, "k0p", *complaints_len, complaints, shares, commitments, secrets);
3260    if(ret != TOPRF_Update_Err_OK) return ret;
3261  
3262    TOPRF_Share reshares[ctx->n][2];
3263    for(unsigned i=0;i<*complaints_len;i++) {
3264      if(vss_reshare(ctx->n, ctx->t, ctx->sessionid, secrets[i][0], reshares, &(*commitments)[1], secrets[i][1])) return TOPRF_Update_Err_VSSShare;
3265      if(0!=dkg_vss_commit(secrets[i][0], secrets[i][1], (*commitments)[0])) return 1;
3266  
3267      int _debug=liboprf_debug; liboprf_debug=0;
3268      if(0!=toprf_mpc_vsps_check(ctx->t-1, (*commitments))) {
3269        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[!] VSPS asdfasdf failed k0p\n"NORMAL);
3270      }
3271      liboprf_debug=_debug;
3272      dump((uint8_t*) (*commitments), (ctx->n+1U)*crypto_core_ristretto255_BYTES, "reshared k0p commitments");
3273  
3274      const uint8_t accused = (uint8_t) (complaints[i] & 0xff);
3275      memcpy(my_shares[accused-1], reshares[ctx->index-1], sizeof(TOPRF_Share)*2);
3276    }
3277  
3278    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
3279    uint8_t commitment[crypto_scalarmult_ristretto255_BYTES];
3280    if(*complaints_len>0) {
3281      ret = compute_mul_share(dealers, my_shares, my_share, commitment);
3282      if(ret!=TOPRF_Update_Err_OK) return ret;
3283    }
3284  
3285    *complaints_len = 0;
3286    memset(complaints, 0, ctx->n*2);
3287    return TOPRF_Update_Err_OK;
3288  }
3289  
3290  static int peer_step44_handler(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len);
3291  static TOPRF_Update_Err peer_reconst_vsps_shares(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
3292    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] final-reconst3 reconstruct secrets of dealers failing VSPS check\x1b[0m\n", ctx->index);
3293    if(input_len!= sizeof(TOPRF_Update_Message) + toprfupdate_peer_zk_disclose_msg_SIZE(ctx) * ctx->n) return TOPRF_Update_Err_ISize;
3294  
3295    // verify STP message envelope
3296    const uint8_t *ptr=NULL;
3297    int ret = unwrap_envelope(ctx,input,input_len,toprfupdate_stp_bc_vsps_disclose_msg,&ptr);
3298    if(ret!=TOPRF_Update_Err_OK) return ret;
3299  
3300    TOPRF_Share k0p_shares[ctx->p_complaints_len][ctx->n][2];
3301    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_vsps_disclose_msg_SIZE(ctx)) {
3302      const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) ptr;
3303      if(peer_recv_msg(ctx,ptr,toprfupdate_peer_vsps_disclose_msg_SIZE(ctx),toprfupdate_peer_vsps_disclose_msg,i+1,0xff)) continue;
3304      const uint8_t *dptr = msg->data;
3305      for(unsigned j=0;j<ctx->p_complaints_len;j++) {
3306        memcpy(k0p_shares[j][msg->from-1], dptr, TOPRF_Share_BYTES*2);
3307        dptr+=TOPRF_Share_BYTES*2;
3308      }
3309    }
3310  
3311    ret = peer_reshare(ctx, &ctx->p_complaints_len, ctx->p_complaints, k0p_shares, (*ctx->k0p_shares), ctx->k0p_share, ctx->k0p_commitments);
3312    if(ret!=TOPRF_Update_Err_OK) return ret;
3313  
3314    // reset my_complaints
3315    ctx->my_p_complaints_len = 0;
3316    memset(ctx->my_p_complaints, 0, ctx->n);
3317  
3318    return peer_step44_handler(ctx, output, output_len);
3319  }
3320  
3321  #define toprfupdate_peer_end2_msg_SIZE (sizeof(TOPRF_Update_Message) + 2 * TOPRF_Share_BYTES)
3322  static int peer_step44_handler(TOPRF_Update_PeerState *ctx, uint8_t *output, const size_t output_len) {
3323    // todo maybe check the global transcript before sending the r & r' shares to stp?
3324    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] final4 send final shared p to STP\x1b[0m\n", ctx->index);
3325    if(output_len != toprfupdate_peer_end2_msg_SIZE) return TOPRF_Update_Err_OSize;
3326  
3327    TOPRF_Update_Message* msg41 = (TOPRF_Update_Message*) output;
3328    memcpy(msg41->data, (uint8_t*) ctx->p_share, 2*TOPRF_Share_BYTES);
3329  
3330    if(0!=toprf_send_msg(output, toprfupdate_peer_end2_msg_SIZE, toprfupdate_peer_end2_msg, ctx->index, 0, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
3331  
3332    ctx->step = TOPRF_Update_Peer_Final_OK;
3333    return TOPRF_Update_Err_OK;
3334  }
3335  
3336  #define toprfupdate_stp_bc_end3_msg_SIZE (sizeof(TOPRF_Update_Message) + 1)
3337  static int stp_step45_handler(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
3338    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] final5. reconstruct delta\x1b[0m\n");
3339    if(input_len != ctx->n * toprfupdate_peer_end2_msg_SIZE) return TOPRF_Update_Err_ISize;
3340    if(output_len != toprfupdate_stp_bc_end3_msg_SIZE) return TOPRF_Update_Err_OSize;
3341    const size_t cheaters = ctx->cheater_len;
3342  
3343    const uint8_t *ptr = input;
3344    TOPRF_Share p_shares[ctx->n][2];
3345    for(uint8_t i=0;i<ctx->n;i++,ptr+=toprfupdate_peer_end2_msg_SIZE) {
3346      const TOPRF_Update_Message *msg = (const TOPRF_Update_Message *) ptr;
3347      if(stp_recv_msg(ctx,ptr,toprfupdate_peer_end2_msg_SIZE, toprfupdate_peer_end2_msg,i+1,0)) continue;
3348      memcpy(p_shares[i],msg->data,2*TOPRF_Share_BYTES);
3349    }
3350    if(ctx->cheater_len>cheaters) return TOPRF_Update_Err_CheatersFound;
3351  
3352    TOPRF_Update_Message *outmsg = (TOPRF_Update_Message *) output;
3353    uint8_t *fail=outmsg->data;
3354    *fail = 0;
3355  
3356    int _debug=liboprf_debug; liboprf_debug=0;
3357    if(0!=toprf_mpc_vsps_check(ctx->t-1, (*ctx->p_commitments))) {
3358      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[!] VSPS failed k0p\n"NORMAL);
3359      *fail=1;
3360    }
3361    liboprf_debug=_debug;
3362  
3363    for(unsigned i=0;i<ctx->n;i++) {
3364      if(0!=dkg_vss_verify_commitment((*ctx->p_commitments)[i], p_shares[i])) {
3365        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[!] failed to verify commitment for p share %d\n"NORMAL, i+1);
3366        dump((*ctx->p_commitments)[i], crypto_scalarmult_ristretto255_BYTES, "[!] C[%d]", i+1);
3367        dump((uint8_t*) p_shares[i], 2*TOPRF_Share_BYTES, "[!] s[%d]", i+1);
3368        *fail=1;
3369      }
3370    }
3371  
3372    if(*fail == 0) {
3373      // reconstruct delta
3374      dkg_vss_reconstruct(ctx->t, 0, ctx->n, p_shares, (*ctx->p_commitments), ctx->delta, NULL);
3375      dump(ctx->delta, crypto_scalarmult_ristretto255_SCALARBYTES, "[!] ∆");
3376    }
3377  
3378    if(0!=toprf_send_msg(output, output_len, toprfupdate_stp_end3_msg, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return TOPRF_Update_Err_Send;
3379  
3380    ctx->step = TOPRF_Update_STP_Done;
3381    return TOPRF_Update_Err_OK;
3382  }
3383  
3384  static TOPRF_Update_Err peer_step46_handler(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len) {
3385    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] final6. receive final confirmation from STP\x1b[0m\n", ctx->index);
3386    if(input_len != toprfupdate_stp_bc_end3_msg_SIZE) return TOPRF_Update_Err_ISize;
3387  
3388    // verify STP message envelope
3389    const TOPRF_Update_Message* msg = (const TOPRF_Update_Message*) input;
3390    int ret = toprf_recv_msg(input, input_len, toprfupdate_stp_end3_msg, 0, 0xff, (*ctx->sig_pks)[0], ctx->sessionid, ctx->ts_epsilon, &ctx->stp_last_ts);
3391    if(0!=ret) return TOPRF_Update_Err_BroadcastEnv+ret;
3392  
3393    if(msg->data[0]!=0) {
3394        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, RED"[%d] STP indicated failure at final step discarding all results, keeping old key\n"NORMAL, ctx->index);
3395        return TOPRF_Update_Err_Proto;
3396    } else {
3397        if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;32m[%d] STP indicated full success updating old key to new key\n"NORMAL, ctx->index);
3398    }
3399  
3400    ctx->step = TOPRF_Update_Peer_Done;
3401    return TOPRF_Update_Err_OK;
3402  }
3403  
3404  int toprf_update_stp_not_done(const TOPRF_Update_STPState *stp) {
3405    return stp->step<TOPRF_Update_STP_Done;
3406  }
3407  
3408  int toprf_update_peer_not_done(const TOPRF_Update_PeerState *peer) {
3409    return peer->step<TOPRF_Update_Peer_Done;
3410  }
3411  
3412  void toprf_update_peer_free(TOPRF_Update_PeerState *ctx) {
3413    for(int i=0;i<ctx->n;i++) {
3414      if((*ctx->noise_ins)[i]!=NULL) Noise_XK_session_free((*ctx->noise_ins)[i]);
3415      if((*ctx->noise_outs)[i]!=NULL) Noise_XK_session_free((*ctx->noise_outs)[i]);
3416    }
3417    if(ctx->dev!=NULL) Noise_XK_device_free(ctx->dev);
3418  }
3419  
3420  size_t toprf_update_stp_input_size(const TOPRF_Update_STPState *ctx) {
3421    size_t sizes[ctx->n];
3422    memset(sizes,0,sizeof sizes);
3423    if(toprf_update_stp_input_sizes(ctx, sizes) == 1) {
3424      return sizes[0] * ctx->n;
3425    } else {
3426      size_t result=0;
3427      for(int i=0;i<ctx->n;i++) result+=sizes[i];
3428      return result;
3429    }
3430  }
3431  
3432  int toprf_update_stp_input_sizes(const TOPRF_Update_STPState *ctx, size_t *sizes) {
3433    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
3434    size_t item=0;
3435    switch(ctx->step) {
3436    case TOPRF_Update_STP_Broadcast_NPKs: { item=toprfupdate_peer_init_msg_SIZE; break; }
3437    case TOPRF_Update_STP_Route_Noise_Handshakes1: { item=toprfupdate_peer_ake1_msg_SIZE * ctx->n; break; }
3438    case TOPRF_Update_STP_Route_Noise_Handshakes2: { item=toprfupdate_peer_ake2_msg_SIZE * ctx->n; break; }
3439    case TOPRF_Update_STP_Broadcast_DKG_Hash_Commitments: { item = toprfupdate_peer_dkg1_msg_SIZE(ctx); break; }
3440    case TOPRF_Update_STP_Broadcast_DKG_Commitments: { item = toprfupdate_peer_dkg2_msg_SIZE(ctx); break; }
3441    case TOPRF_Update_STP_Route_Encrypted_Shares: { item = toprfupdate_peer_dkg3_msg_SIZE * ctx->n; break; }
3442    case TOPRF_Update_STP_Broadcast_Complaints: { item = toprfupdate_peer_verify_shares_msg_SIZE(ctx); break; }
3443    case TOPRF_Update_STP_Broadcast_DKG_Defenses: {
3444      uint8_t ctr1[ctx->n];
3445      memset(ctr1,0,ctx->n);
3446      for(int i=0;i<ctx->p_complaints_len;i++) {
3447        const uint8_t peer = (uint8_t) ((ctx->p_complaints[i] & 0xff) - 1U);
3448        if(peer>=ctx->n) return TOPRF_Update_Err_OOB;
3449        ctr1[peer]++;
3450      }
3451      for(int i=0;i<ctx->n;i++) {
3452        if(ctr1[i]>0) {
3453          sizes[i]=sizeof(TOPRF_Update_Message) \
3454                    + (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
3455        } else {
3456          sizes[i]=0;
3457        }
3458      }
3459      return 0;
3460    }
3461    case TOPRF_Update_STP_Broadcast_DKG_Transcripts: { item = toprfupdate_peer_bc_transcript_msg_SIZE; break; }
3462    case TOPRF_Update_STP_Route_Mult_Step1: {
3463      for(uint8_t i=0;i<ctx->n;i++) {
3464        sizes[i] = isdealer(i+1, ctx->t) * toprfupdate_peer_mult1_msg_SIZE(ctx);
3465      }
3466      return 0;
3467    }
3468    case TOPRF_Update_STP_Broadcast_Mult_Commitments: {
3469      for(uint8_t i=0;i<ctx->n;i++) {
3470        sizes[i] = isdealer(i+1, ctx->t) * toprfupdate_peer_mult_coms_msg_SIZE(ctx);
3471      }
3472      return 0;
3473    }
3474    case TOPRF_Update_STP_Route_Encrypted_Mult_Shares: {
3475      for(uint8_t i=0;i<ctx->n;i++) {
3476        sizes[i] = isdealer(i+1, ctx->t) * (toprfupdate_peer_mult2_msg_SIZE * ctx->n);
3477      }
3478      return 0;
3479    }
3480    case TOPRF_Update_STP_Broadcast_Mult_Complaints: { item = toprfupdate_peer_verify_mult_shares_msg_SIZE(ctx); break; }
3481    case TOPRF_Update_STP_Broadcast_Mult_Defenses: {
3482      uint8_t ctr1[dealers];
3483      memset(ctr1,0,sizeof ctr1);
3484      for(int i=0;i<ctx->p_complaints_len;i++) {
3485        const uint8_t peer = (uint8_t) ((ctx->p_complaints[i] & 0xff) - 1U);
3486        if(peer>=dealers) return TOPRF_Update_Err_OOB;
3487        ctr1[peer]++;
3488      }
3489      for(int i=0;i<ctx->n;i++) {
3490        if(i<dealers && (ctr1[i]>0)) {
3491          sizes[i]=sizeof(TOPRF_Update_Message) \
3492                    + (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
3493        } else {
3494          sizes[i]=0;
3495        }
3496      }
3497      return 0;
3498    }
3499    case TOPRF_Update_STP_Broadcast_Reconst_Mult_Shares: { item = toprfupdate_stp_reconst_mult_shares_msg_SIZE(ctx); break; }
3500  
3501    case TOPRF_Update_STP_Route_ZK_Challenge_Commitments: { item = toprfupdate_peer_zkp1_msg_SIZE; break; }
3502    case TOPRF_Update_STP_Route_ZK_commitments: {
3503      for(uint8_t i=0;i<ctx->n;i++) {
3504        sizes[i] = isdealer(i+1, ctx->t) * toprfupdate_peer_zkp2_msg_SIZE;
3505      }
3506      return 0;
3507    }
3508    case TOPRF_Update_STP_Broadcast_ZK_nonces: { item = toprfupdate_peer_zkp3_msg_SIZE; break; }
3509    case TOPRF_Update_STP_Broadcast_ZK_Proofs: {
3510      for(uint8_t i=0;i<ctx->n;i++) {
3511        sizes[i] = isdealer(i+1, ctx->t) * toprfupdate_peer_zkp4_msg_SIZE;
3512      }
3513      return 0;
3514    }
3515    case TOPRF_Update_STP_Broadcast_ZK_Disclosures: { item = toprfupdate_peer_zk_disclose_msg_SIZE(ctx); break; }
3516    case TOPRF_Update_STP_Broadcast_Mult_Ci: { item = toprfupdate_peer_mult3_msg_SIZE; break; }
3517    case TOPRF_Update_STP_Broadcast_VSPS_Disclosures: { item = toprfupdate_peer_vsps_disclose_msg_SIZE(ctx); break; }
3518    case TOPRF_Update_STP_Reconstruct_Delta: { item = toprfupdate_peer_end2_msg_SIZE; break; }
3519    default: {
3520      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[!] isize invalid stp step: %d\n", ctx->step);
3521    }
3522    }
3523  
3524    for(uint8_t i=0;i<ctx->n;i++) {
3525      sizes[i] = item;
3526    }
3527    return 1;
3528  }
3529  
3530  size_t toprf_update_stp_output_size(const TOPRF_Update_STPState *ctx) {
3531    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
3532    switch(ctx->step) {
3533    case TOPRF_Update_STP_Broadcast_NPKs: return toprfupdate_peer_init_msg_SIZE * ctx->n + sizeof(TOPRF_Update_Message);
3534    case TOPRF_Update_STP_Route_Noise_Handshakes1: return toprfupdate_peer_ake1_msg_SIZE * ctx->n * ctx->n;
3535    case TOPRF_Update_STP_Route_Noise_Handshakes2: return toprfupdate_peer_ake2_msg_SIZE * ctx->n * ctx->n;
3536  
3537    case TOPRF_Update_STP_Broadcast_DKG_Hash_Commitments: return sizeof(TOPRF_Update_Message) + (toprfupdate_peer_dkg1_msg_SIZE(ctx) * ctx->n);
3538    case TOPRF_Update_STP_Broadcast_DKG_Commitments: return sizeof(TOPRF_Update_Message) + (toprfupdate_peer_dkg2_msg_SIZE(ctx) * ctx->n);
3539  
3540    case TOPRF_Update_STP_Route_Encrypted_Shares: return toprfupdate_peer_dkg3_msg_SIZE * ctx->n * ctx->n;
3541    case TOPRF_Update_STP_Broadcast_Complaints: return toprfupdate_stp_bc_verify_shares_msg_SIZE(ctx);
3542    case TOPRF_Update_STP_Broadcast_DKG_Defenses: return sizeof(TOPRF_Update_Message) + toprf_update_stp_input_size(ctx);
3543    case TOPRF_Update_STP_Broadcast_DKG_Transcripts: return toprfupdate_stp_bc_transcript_msg_SIZE(ctx);
3544  
3545    case TOPRF_Update_STP_Route_Mult_Step1: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_mult1_msg_SIZE(ctx) * dealers;
3546    case TOPRF_Update_STP_Broadcast_Mult_Commitments: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_mult_coms_msg_SIZE(ctx) * dealers;
3547    case TOPRF_Update_STP_Broadcast_Mult_Complaints: return toprfupdate_stp_bc_verify_mult_shares_msg_SIZE(ctx);
3548    case TOPRF_Update_STP_Broadcast_Mult_Defenses: return sizeof(TOPRF_Update_Message) + toprf_update_stp_input_size(ctx);
3549    case TOPRF_Update_STP_Broadcast_Reconst_Mult_Shares: return sizeof(TOPRF_Update_Message) + toprfupdate_stp_reconst_mult_shares_msg_SIZE(ctx) * ctx->n;
3550  
3551    case TOPRF_Update_STP_Route_Encrypted_Mult_Shares: return (toprfupdate_peer_mult2_msg_SIZE * ctx->n) * dealers;
3552    case TOPRF_Update_STP_Route_ZK_Challenge_Commitments: return sizeof(TOPRF_Update_Message) + (toprfupdate_peer_zkp1_msg_SIZE * ctx->n);
3553    case TOPRF_Update_STP_Route_ZK_commitments: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp2_msg_SIZE * dealers;
3554    case TOPRF_Update_STP_Broadcast_ZK_nonces: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp3_msg_SIZE * ctx->n;
3555    case TOPRF_Update_STP_Broadcast_ZK_Proofs: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp4_msg_SIZE * dealers;
3556    case TOPRF_Update_STP_Broadcast_ZK_Disclosures: return toprfupdate_stp_bc_zkp_disclose_msg_SIZE(ctx);
3557    case TOPRF_Update_STP_Broadcast_Mult_Ci: return toprfupdate_stp_bc_mult3_msg_SIZE(ctx);
3558    case TOPRF_Update_STP_Broadcast_VSPS_Disclosures: return toprfupdate_stp_bc_vsps_disclose_msg_SIZE(ctx);
3559    case TOPRF_Update_STP_Reconstruct_Delta: return toprfupdate_stp_bc_end3_msg_SIZE;
3560    default: if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[!] osize invalid stp step: %d\n", ctx->step);
3561    }
3562    return 0;
3563  }
3564  
3565  int toprf_update_stp_peer_msg(const TOPRF_Update_STPState *ctx, const uint8_t *base, const size_t base_size, const uint8_t peer, const uint8_t **msg, size_t *len) {
3566    if(peer>=ctx->n) return -1;
3567    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
3568  
3569    switch(ctx->prev) {
3570    case TOPRF_Update_STP_Broadcast_NPKs: {
3571      *msg = base;
3572      *len = toprfupdate_peer_init_msg_SIZE * ctx->n + sizeof(TOPRF_Update_Message);
3573      break;
3574    }
3575    case TOPRF_Update_STP_Route_Noise_Handshakes1: {
3576      *msg = base + peer * toprfupdate_peer_ake1_msg_SIZE * ctx->n;
3577      *len = toprfupdate_peer_ake1_msg_SIZE * ctx->n;
3578      break;
3579    }
3580    case TOPRF_Update_STP_Route_Noise_Handshakes2: {
3581      *msg = base + peer * toprfupdate_peer_ake2_msg_SIZE * ctx->n;
3582      *len = toprfupdate_peer_ake1_msg_SIZE * ctx->n;
3583      break;
3584    }
3585    case TOPRF_Update_STP_Broadcast_DKG_Hash_Commitments: {
3586      *msg = base;
3587      *len = sizeof(TOPRF_Update_Message) + (toprfupdate_peer_dkg1_msg_SIZE(ctx) * ctx->n);
3588      break;
3589    }
3590    case TOPRF_Update_STP_Broadcast_DKG_Commitments: {
3591      *msg = base;
3592      *len = sizeof(TOPRF_Update_Message) + (toprfupdate_peer_dkg2_msg_SIZE(ctx) * ctx->n);
3593      break;
3594    }
3595    case TOPRF_Update_STP_Route_Encrypted_Shares: {
3596      *msg = base + peer * toprfupdate_peer_dkg3_msg_SIZE * ctx->n;
3597      *len = toprfupdate_peer_dkg3_msg_SIZE * ctx->n;
3598      break;
3599    }
3600    case TOPRF_Update_STP_Broadcast_Complaints: {
3601      *msg = base;
3602      *len = toprfupdate_stp_bc_verify_shares_msg_SIZE(ctx);
3603      break;
3604    }
3605    case TOPRF_Update_STP_Broadcast_DKG_Defenses: {
3606      *msg = base;
3607      *len = sizeof(TOPRF_Update_Message);
3608      uint8_t ctr1[ctx->n];
3609      memset(ctr1,0,sizeof ctr1);
3610      for(int i=0;i<ctx->p_complaints_len;i++) {
3611        const uint8_t peer = (uint8_t) ((ctx->p_complaints[i] & 0xff) - 1U);
3612        if(peer>=ctx->n) return TOPRF_Update_Err_OOB;
3613        ctr1[peer]++;
3614      }
3615      for(int i=0;i<ctx->n;i++) {
3616        if(ctr1[i]>0) {
3617          *len+=sizeof(TOPRF_Update_Message) \
3618                + (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
3619        }
3620      }
3621      break;
3622    }
3623    case TOPRF_Update_STP_Broadcast_DKG_Transcripts: {
3624      *msg = base;
3625      *len = toprfupdate_stp_bc_transcript_msg_SIZE(ctx);
3626      break;
3627    }
3628    case TOPRF_Update_STP_Route_Mult_Step1: {
3629      *msg = base;
3630      *len = sizeof(TOPRF_Update_Message) + toprfupdate_peer_mult1_msg_SIZE(ctx) * dealers;
3631      break;
3632    }
3633    case TOPRF_Update_STP_Broadcast_Mult_Commitments: {
3634      *msg = base;
3635      *len = sizeof(TOPRF_Update_Message) + toprfupdate_peer_mult_coms_msg_SIZE(ctx) * dealers;
3636      break;
3637    }
3638    case TOPRF_Update_STP_Route_Encrypted_Mult_Shares: {
3639      *msg = base + peer * toprfupdate_peer_mult2_msg_SIZE * ((ctx->t-1U)*2 + 1U);
3640      *len = toprfupdate_peer_mult2_msg_SIZE * ((ctx->t-1U)*2 + 1U);
3641      break;
3642    }
3643  
3644    case TOPRF_Update_STP_Broadcast_Mult_Complaints: {
3645      *msg = base;
3646      *len = toprfupdate_stp_bc_verify_mult_shares_msg_SIZE(ctx);
3647      break;
3648    }
3649    case TOPRF_Update_STP_Broadcast_Mult_Defenses: {
3650      *msg = base;
3651      *len = sizeof(TOPRF_Update_Message);
3652      uint8_t ctr1[dealers];
3653      memset(ctr1,0,sizeof ctr1);
3654      for(int i=0;i<ctx->p_complaints_len;i++) {
3655        const uint8_t peer = (uint8_t) ((ctx->p_complaints[i] & 0xff) - 1U);
3656        if(peer>=dealers) return TOPRF_Update_Err_OOB;
3657        ctr1[peer]++;
3658      }
3659      for(int i=0;i<dealers;i++) {
3660        if(ctr1[i]>0) {
3661          *len+=sizeof(TOPRF_Update_Message) \
3662                + (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
3663        }
3664      }
3665      break;
3666    }
3667    case TOPRF_Update_STP_Broadcast_Reconst_Mult_Shares: {
3668      *msg = base;
3669      *len = sizeof(TOPRF_Update_Message) + toprfupdate_stp_reconst_mult_shares_msg_SIZE(ctx) * ctx->n;
3670      break;
3671    }
3672  
3673    case TOPRF_Update_STP_Route_ZK_Challenge_Commitments: {
3674      *msg = base;
3675      *len = sizeof(TOPRF_Update_Message) + (toprfupdate_peer_zkp1_msg_SIZE * ctx->n);
3676      break;
3677    }
3678    case TOPRF_Update_STP_Route_ZK_commitments: {
3679      *msg = base;
3680      *len = sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp2_msg_SIZE * dealers;
3681      break;
3682    }
3683    case TOPRF_Update_STP_Broadcast_ZK_nonces: {
3684      *msg = base;
3685      *len = sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp3_msg_SIZE * ctx->n;
3686      break;
3687    }
3688    case TOPRF_Update_STP_Broadcast_ZK_Proofs: {
3689      *msg = base;
3690      *len = sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp4_msg_SIZE * dealers;
3691      break;
3692    }
3693    case TOPRF_Update_STP_Broadcast_ZK_Disclosures: {
3694      *msg = base;
3695      *len = toprfupdate_stp_bc_zkp_disclose_msg_SIZE(ctx);
3696      break;
3697    }
3698    case TOPRF_Update_STP_Broadcast_Mult_Ci: {
3699      *msg = base;
3700      *len = toprfupdate_stp_bc_mult3_msg_SIZE(ctx);
3701      break;
3702    }
3703    case TOPRF_Update_STP_Broadcast_VSPS_Disclosures: {
3704      *msg = base;
3705      *len = toprfupdate_stp_bc_vsps_disclose_msg_SIZE(ctx);
3706      break;
3707    }
3708    case TOPRF_Update_STP_Reconstruct_Delta: {
3709      *msg = base;
3710      *len = toprfupdate_stp_bc_end3_msg_SIZE;
3711      break;
3712    }
3713    default: {
3714      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[!] invalid stp step in toprf_update_stp_peer_msg\n");
3715      return 1;
3716    }
3717    }
3718  
3719    if(base+base_size < *msg + *len) {
3720      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "buffer overread detected in toprf_update_stp_peer_msg %ld\n", (base+base_size) - (*msg + *len));
3721      return 2;
3722    }
3723  
3724    return 0;
3725  }
3726  
3727  size_t toprf_update_peer_input_size(const TOPRF_Update_PeerState *ctx) {
3728    const uint8_t dealers = (uint8_t) ((ctx->t-1U)*2 + 1U);
3729    switch(ctx->step) {
3730    case TOPRF_Update_Peer_Broadcast_NPK_SIDNonce: return 0;
3731    case TOPRF_Update_Peer_Rcv_NPK_SIDNonce: return toprfupdate_peer_init_msg_SIZE * ctx->n + sizeof(TOPRF_Update_Message);
3732    case TOPRF_Update_Peer_Noise_Handshake: return toprfupdate_peer_ake1_msg_SIZE * ctx->n;
3733    case TOPRF_Update_Peer_Finish_Noise_Handshake: return toprfupdate_peer_ake2_msg_SIZE * ctx->n;
3734    case TOPRF_Update_Peer_Rcv_CHashes_Send_Commitments: return sizeof(TOPRF_Update_Message) + (toprfupdate_peer_dkg1_msg_SIZE(ctx) * ctx->n);
3735    case TOPRF_Update_Peer_Rcv_Commitments_Send_Shares: return sizeof(TOPRF_Update_Message) + (toprfupdate_peer_dkg2_msg_SIZE(ctx) * ctx->n);
3736    case TOPRF_Update_Peer_Verify_Commitments: return  ctx->n * toprfupdate_peer_dkg3_msg_SIZE;
3737    case TOPRF_Update_Peer_Finish_DKG: return 0;
3738    case TOPRF_Update_Peer_Handle_DKG_Complaints: return toprfupdate_stp_bc_verify_shares_msg_SIZE(ctx);
3739    case TOPRF_Update_Peer_Defend_DKG_Accusations: return 0;
3740    case TOPRF_Update_Peer_Check_Shares: {
3741      uint8_t ctr1[ctx->n];
3742      memset(ctr1,0,ctx->n);
3743      for(int i=0;i<ctx->p_complaints_len;i++) {
3744        const uint8_t peer = (uint8_t) ((ctx->p_complaints[i] & 0xff) - 1U);
3745        if(peer>=ctx->n) return TOPRF_Update_Err_OOB;
3746        ctr1[peer]++;
3747      }
3748      size_t ret = sizeof(TOPRF_Update_Message);
3749      for(int i=0;i<ctx->n;i++) {
3750        if(ctr1[i]>0) {
3751          ret+=sizeof(TOPRF_Update_Message) \
3752               + (1U+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
3753        }
3754      }
3755      return ret;
3756    }
3757    case TOPRF_Update_Peer_Confirm_Transcripts: return toprfupdate_stp_bc_transcript_msg_SIZE(ctx);
3758    case TOPRF_Update_Peer_Rcv_Mult_CHashes_Send_Commitments: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_mult1_msg_SIZE(ctx) * dealers;
3759    case TOPRF_Update_Peer_Send_K0P_Shares: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_mult_coms_msg_SIZE(ctx) * dealers;
3760    case TOPRF_Update_Peer_Recv_K0P_Shares: return toprfupdate_peer_mult2_msg_SIZE * dealers;
3761    case TOPRF_Update_Peer_Handle_Mult_Share_Complaints: return toprfupdate_stp_bc_verify_mult_shares_msg_SIZE(ctx);
3762    case TOPRF_Update_Peer_Defend_Mult_Accusations: return 0;
3763    case TOPRF_Update_Peer_Check_Mult_Shares: {
3764      uint8_t ctr1[dealers];
3765      memset(ctr1,0,sizeof ctr1);
3766      for(int i=0;i<ctx->p_complaints_len;i++) {
3767        const uint8_t peer = (uint8_t) ((ctx->p_complaints[i] & 0xff) - 1U);
3768        if(peer>=dealers) return TOPRF_Update_Err_OOB;
3769        ctr1[peer]++;
3770      }
3771      size_t ret = sizeof(TOPRF_Update_Message);
3772      for(int i=0;i<dealers;i++) {
3773        if(ctr1[i]>0) {
3774          ret+=sizeof(TOPRF_Update_Message) \
3775               + (1U+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE) * ctr1[i];
3776        }
3777      }
3778      return ret;
3779    }
3780    case TOPRF_Update_Peer_Disclose_Mult_Shares: return 0;
3781    case TOPRF_Update_Peer_Reconstruct_Mult_Shares: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_reconst_mult_shares_msg_SIZE(ctx) * ctx->n;
3782    case TOPRF_Update_Peer_Send_ZK_Challenge_Commitments: return 0;
3783  
3784    case TOPRF_Update_Peer_Send_ZK_Commitments: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp1_msg_SIZE * ctx->n;
3785    case TOPRF_Update_Peer_Send_ZK_nonces: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp2_msg_SIZE * dealers;
3786    case TOPRF_Update_Peer_Send_ZK_proofs: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp3_msg_SIZE * ctx->n;
3787    case TOPRF_Update_Peer_Verify_ZK_proofs: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_zkp4_msg_SIZE * dealers;
3788    case TOPRF_Update_Peer_Disclose_ZK_Cheaters: return 0;
3789    case TOPRF_Update_Peer_Reconstruct_ZK_Shares: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_zk_disclose_msg_SIZE(ctx) * ctx->n;
3790    case TOPRF_Update_Peer_Send_Mult_Ci: return 0;
3791    case TOPRF_Update_Peer_Final_VSPS_Checks: return toprfupdate_stp_bc_mult3_msg_SIZE(ctx);
3792    case TOPRF_Update_Peer_Disclose_VSPS_Cheaters: return 0;
3793    case TOPRF_Update_Peer_Reconstruct_VSPS_Shares: return sizeof(TOPRF_Update_Message) + toprfupdate_peer_vsps_disclose_msg_SIZE(ctx) * ctx->n;
3794    case TOPRF_Update_Peer_Send_k0p_Share: return 0;
3795    case TOPRF_Update_Peer_Final_OK: return toprfupdate_stp_bc_end3_msg_SIZE;
3796    default: {
3797      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[%d] peer input size invalid step\n", ctx->index);
3798    }
3799    }
3800    return 1;
3801  }
3802  
3803  size_t toprf_update_peer_output_size(const TOPRF_Update_PeerState *ctx) {
3804    switch(ctx->step) {
3805    case TOPRF_Update_Peer_Broadcast_NPK_SIDNonce: return toprfupdate_peer_init_msg_SIZE;
3806    case TOPRF_Update_Peer_Rcv_NPK_SIDNonce: return toprfupdate_peer_ake1_msg_SIZE * ctx->n;
3807    case TOPRF_Update_Peer_Noise_Handshake: return toprfupdate_peer_ake2_msg_SIZE * ctx->n;
3808    case TOPRF_Update_Peer_Finish_Noise_Handshake: return toprfupdate_peer_dkg1_msg_SIZE(ctx);
3809    case TOPRF_Update_Peer_Rcv_CHashes_Send_Commitments: return toprfupdate_peer_dkg2_msg_SIZE(ctx);
3810    case TOPRF_Update_Peer_Rcv_Commitments_Send_Shares: return ctx->n * toprfupdate_peer_dkg3_msg_SIZE;
3811    case TOPRF_Update_Peer_Verify_Commitments: return toprfupdate_peer_verify_shares_msg_SIZE(ctx);
3812    case TOPRF_Update_Peer_Handle_DKG_Complaints: return 0;
3813    case TOPRF_Update_Peer_Defend_DKG_Accusations: {
3814      if(ctx->my_p_complaints_len == 0) return 0;
3815      size_t res = sizeof(TOPRF_Update_Message) \
3816                   + ctx->my_p_complaints_len * (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE);
3817      return res;
3818    }
3819    case TOPRF_Update_Peer_Check_Shares: return toprfupdate_peer_bc_transcript_msg_SIZE;
3820    case TOPRF_Update_Peer_Finish_DKG: return toprfupdate_peer_bc_transcript_msg_SIZE;
3821    case TOPRF_Update_Peer_Confirm_Transcripts: return isdealer(ctx->index, ctx->t) * toprfupdate_peer_mult1_msg_SIZE(ctx);
3822    case TOPRF_Update_Peer_Rcv_Mult_CHashes_Send_Commitments: return isdealer(ctx->index, ctx->t) * toprfupdate_peer_mult_coms_msg_SIZE(ctx);
3823    case TOPRF_Update_Peer_Send_K0P_Shares: return isdealer(ctx->index, ctx->t) * toprfupdate_peer_mult2_msg_SIZE * ctx->n;
3824    case TOPRF_Update_Peer_Recv_K0P_Shares: return toprfupdate_peer_verify_mult_shares_msg_SIZE(ctx);
3825    case TOPRF_Update_Peer_Handle_Mult_Share_Complaints: return 0;
3826    case TOPRF_Update_Peer_Defend_Mult_Accusations: {
3827      if(ctx->my_p_complaints_len == 0) return 0;
3828      size_t res = sizeof(TOPRF_Update_Message) \
3829                   + ctx->my_p_complaints_len * (1+dkg_noise_key_SIZE+toprf_update_encrypted_shares_SIZE);
3830      return res;
3831    }
3832    case TOPRF_Update_Peer_Check_Mult_Shares: return 0;
3833    case TOPRF_Update_Peer_Disclose_Mult_Shares: {
3834      if(ctx->p_complaints_len == 0) return 0;
3835      return toprfupdate_peer_reconst_mult_shares_msg_SIZE(ctx);
3836    }
3837    case TOPRF_Update_Peer_Reconstruct_Mult_Shares:
3838    case TOPRF_Update_Peer_Send_ZK_Challenge_Commitments: return toprfupdate_peer_zkp1_msg_SIZE;
3839    case TOPRF_Update_Peer_Send_ZK_Commitments: return isdealer(ctx->index, ctx->t) * toprfupdate_peer_zkp2_msg_SIZE;
3840    case TOPRF_Update_Peer_Send_ZK_nonces: return toprfupdate_peer_zkp3_msg_SIZE;
3841    case TOPRF_Update_Peer_Send_ZK_proofs: return isdealer(ctx->index, ctx->t) * toprfupdate_peer_zkp4_msg_SIZE;
3842    case TOPRF_Update_Peer_Verify_ZK_proofs: return 0;
3843    case TOPRF_Update_Peer_Disclose_ZK_Cheaters: return toprfupdate_peer_zk_disclose_msg_SIZE(ctx);
3844    case TOPRF_Update_Peer_Reconstruct_ZK_Shares:
3845    case TOPRF_Update_Peer_Send_Mult_Ci: return toprfupdate_peer_mult3_msg_SIZE;
3846    case TOPRF_Update_Peer_Final_VSPS_Checks: return 0;
3847    case TOPRF_Update_Peer_Disclose_VSPS_Cheaters: return toprfupdate_peer_vsps_disclose_msg_SIZE(ctx);
3848    case TOPRF_Update_Peer_Reconstruct_VSPS_Shares:
3849    case TOPRF_Update_Peer_Send_k0p_Share: return toprfupdate_peer_end2_msg_SIZE;
3850    case TOPRF_Update_Peer_Final_OK: return 0;
3851    default: {
3852      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[%d] peer output size invalid step\n", ctx->index);
3853    }
3854    }
3855    return 1;
3856  }
3857  
3858  int toprf_update_stp_next(TOPRF_Update_STPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
3859    int ret = 0;
3860    if(ctx->cheater_max <= ctx->cheater_len) return TOPRF_Update_Err_CheatersFull;
3861    ctx->prev=ctx->step;
3862    switch(ctx->step) {
3863    case TOPRF_Update_STP_Broadcast_NPKs: { ret =  stp_step2_handler(ctx, input, input_len, output, output_len); break;}
3864    case TOPRF_Update_STP_Route_Noise_Handshakes1: { ret = stp_step4_handler(ctx, input, input_len, output, output_len); break;}
3865    case TOPRF_Update_STP_Route_Noise_Handshakes2: { ret = stp_step6_handler(ctx, input, input_len, output, output_len); break;}
3866  
3867    case TOPRF_Update_STP_Broadcast_DKG_Hash_Commitments: { ret = stp_dkg1_handler(ctx, input, input_len, output, output_len); break;}
3868    case TOPRF_Update_STP_Broadcast_DKG_Commitments: { ret = stp_dkg2_handler(ctx, input, input_len, output, output_len); break;}
3869    case TOPRF_Update_STP_Route_Encrypted_Shares: { ret = stp_dkg3_handler(ctx, input, input_len, output, output_len); break;}
3870  
3871    case TOPRF_Update_STP_Broadcast_Complaints: { ret = stp_verify_shares_handler(ctx, input, input_len, output, output_len); break;}
3872    case TOPRF_Update_STP_Broadcast_DKG_Defenses: { ret = stp_broadcast_defenses(ctx, input, input_len, output, output_len); break;}
3873    case TOPRF_Update_STP_Broadcast_DKG_Transcripts: { ret = stp_bc_transcript_handler(ctx, input, input_len, output, output_len); break;}
3874  
3875    case TOPRF_Update_STP_Route_Mult_Step1: { ret = stp_step25_handler(ctx, input, input_len, output, output_len); break;}
3876    case TOPRF_Update_STP_Broadcast_Mult_Commitments: { ret = stp_mult_com_handler(ctx, input, input_len, output, output_len); break;}
3877    case TOPRF_Update_STP_Route_Encrypted_Mult_Shares: { ret = stp_step27_handler(ctx, input, input_len, output, output_len); break;}
3878  
3879    case TOPRF_Update_STP_Broadcast_Mult_Complaints: { ret = stp_verify_mult_shares_handler(ctx, input, input_len, output, output_len); break;}
3880    case TOPRF_Update_STP_Broadcast_Mult_Defenses: { ret = stp_broadcast_mult_defenses(ctx, input, input_len, output, output_len); break;}
3881    case TOPRF_Update_STP_Broadcast_Reconst_Mult_Shares: { ret = stp_broadcast_reconst_mult_shares(ctx, input, input_len, output, output_len); break;}
3882  
3883    case TOPRF_Update_STP_Route_ZK_Challenge_Commitments: { ret = stp_step29_handler(ctx, input, input_len, output, output_len); break;}
3884    case TOPRF_Update_STP_Route_ZK_commitments: { ret = stp_step31_handler(ctx, input, input_len, output, output_len); break;}
3885    case TOPRF_Update_STP_Broadcast_ZK_nonces: { ret = stp_step33_handler(ctx, input, input_len, output, output_len); break;}
3886    case TOPRF_Update_STP_Broadcast_ZK_Proofs: { ret = stp_step35_handler(ctx, input, input_len, output, output_len); break;}
3887    case TOPRF_Update_STP_Broadcast_ZK_Disclosures: { ret = stp_bc_zk_disclosures(ctx, input, input_len, output, output_len); break;}
3888  
3889    case TOPRF_Update_STP_Broadcast_Mult_Ci: { ret = stp_step40_handler(ctx, input, input_len, output, output_len); break;}
3890    case TOPRF_Update_STP_Broadcast_VSPS_Disclosures: { ret = stp_bc_vsps_disclosures(ctx, input, input_len, output, output_len); break;}
3891    case TOPRF_Update_STP_Reconstruct_Delta: { ret = stp_step45_handler(ctx, input, input_len, output, output_len); break;}
3892    default: {
3893      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[!] stp next invalid step\n");
3894      return 99;
3895    }
3896    }
3897    if(ret!=0) ctx->step=99; // so that not_done reports done
3898    return ret;
3899  }
3900  
3901  int toprf_update_peer_next(TOPRF_Update_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
3902    int ret=0;
3903    if(ctx->cheater_max <= ctx->cheater_len) return TOPRF_Update_Err_CheatersFull;
3904    ctx->prev=ctx->step;
3905    switch(ctx->step) {
3906    case TOPRF_Update_Peer_Broadcast_NPK_SIDNonce: { ret = peer_step1_handler(ctx, output, output_len) ; break; }
3907    case TOPRF_Update_Peer_Rcv_NPK_SIDNonce: { ret = peer_step3_handler(ctx, input, input_len, output, output_len); break; }
3908    case TOPRF_Update_Peer_Noise_Handshake: { ret = peer_step5_handler(ctx, input, input_len, output, output_len); break; }
3909    case TOPRF_Update_Peer_Finish_Noise_Handshake: { ret = peer_dkg1_handler(ctx, input, input_len, output, output_len); break; }
3910  
3911    case TOPRF_Update_Peer_Rcv_CHashes_Send_Commitments: { ret = peer_dkg2_handler(ctx, input, input_len, output, output_len); break; }
3912    case TOPRF_Update_Peer_Rcv_Commitments_Send_Shares: { ret = peer_dkg3_handler(ctx, input, input_len, output, output_len); break; }
3913  
3914    case TOPRF_Update_Peer_Verify_Commitments: { ret = peer_verify_shares_handler(ctx, input, input_len, output, output_len); break; }
3915    case TOPRF_Update_Peer_Handle_DKG_Complaints: { ret = peer_dkg_fork(ctx, input, input_len); break; }
3916    case TOPRF_Update_Peer_Defend_DKG_Accusations: { ret = peer_defend(ctx, output, output_len); break; }
3917    case TOPRF_Update_Peer_Check_Shares: { ret = peer_check_shares(ctx, input, input_len, output, output_len); break; }
3918  
3919    case TOPRF_Update_Peer_Finish_DKG: { ret = peer_verify_vsps(ctx, output, output_len); break; }
3920    case TOPRF_Update_Peer_Confirm_Transcripts: { ret = peer_final_handler(ctx, input, input_len, output, output_len); break; }
3921  
3922    case TOPRF_Update_Peer_Rcv_Mult_CHashes_Send_Commitments: { ret = peer_mult2_handler(ctx, input, input_len, output, output_len); break; }
3923    case TOPRF_Update_Peer_Send_K0P_Shares: { ret = peer_step26_handler(ctx, input, input_len, output, output_len); break; }
3924    case TOPRF_Update_Peer_Recv_K0P_Shares: { ret = peer_step28_handler(ctx, input, input_len, output, output_len); break; }
3925  
3926    case TOPRF_Update_Peer_Handle_Mult_Share_Complaints: { ret = peer_mult_fork(ctx, input, input_len); break; }
3927    case TOPRF_Update_Peer_Defend_Mult_Accusations: { ret = peer_mult_defend(ctx, output, output_len); break; }
3928    case TOPRF_Update_Peer_Check_Mult_Shares: { ret = peer_check_mult_shares(ctx,input,input_len); break; }
3929    case TOPRF_Update_Peer_Disclose_Mult_Shares: { ret = peer_disclose_mult_shares(ctx, output, output_len); break; }
3930    case TOPRF_Update_Peer_Reconstruct_Mult_Shares: { ret = peer_reconst_mult_shares(ctx,input,input_len,output,output_len); break;}
3931  
3932    case TOPRF_Update_Peer_Send_ZK_Challenge_Commitments: { ret = peer_send_zk_chalcoms(ctx, output, output_len); break; }
3933    case TOPRF_Update_Peer_Send_ZK_Commitments: { ret = peer_step30_handler(ctx, input, input_len, output, output_len); break; }
3934    case TOPRF_Update_Peer_Send_ZK_nonces: { ret = peer_step32_handler(ctx, input, input_len, output, output_len); break; }
3935    case TOPRF_Update_Peer_Send_ZK_proofs: { ret = peer_step34_handler(ctx, input, input_len, output, output_len); break; }
3936    case TOPRF_Update_Peer_Verify_ZK_proofs: { ret = peer_step36_handler(ctx, input, input_len); break; }
3937    case TOPRF_Update_Peer_Disclose_ZK_Cheaters: { ret = peer_zkproof_disclose(ctx, output, output_len); break; }
3938    case TOPRF_Update_Peer_Reconstruct_ZK_Shares: { ret = peer_reconst_zk_shares(ctx,input,input_len,output,output_len); break;}
3939  
3940    case TOPRF_Update_Peer_Send_Mult_Ci: { ret = peer_step39_handler(ctx, output, output_len); break; }
3941    case TOPRF_Update_Peer_Final_VSPS_Checks: { ret = peer_step41_handler(ctx, input, input_len); break; }
3942    case TOPRF_Update_Peer_Disclose_VSPS_Cheaters: { ret = peer_vsps_disclose(ctx, output, output_len); break; }
3943    case TOPRF_Update_Peer_Reconstruct_VSPS_Shares: { ret = peer_reconst_vsps_shares(ctx,input,input_len,output,output_len); break;}
3944  
3945    case TOPRF_Update_Peer_Send_k0p_Share: { ret = peer_step44_handler(ctx, output, output_len); break; }
3946    case TOPRF_Update_Peer_Final_OK: { ret = peer_step46_handler(ctx, input, input_len); break; }
3947    case TOPRF_Update_Peer_Done: {
3948      // we are done
3949      ret = 0;
3950      break;
3951    }
3952    default: {
3953      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[%d] peer next invalid step\n", ctx->index);
3954      ret = 99;
3955    }
3956    }
3957    if(ret!=0) ctx->step=99; // so that not_done reports done
3958    return ret;
3959  }