/ src / tp-dkg.c
tp-dkg.c
   1  #include <stdio.h>
   2  #include <stdint.h>
   3  #include <sodium.h>
   4  #include <arpa/inet.h> //htons
   5  #include <sys/param.h> // __BYTE_ORDER __BIG_ENDIAN
   6  #include <string.h> // memcpy
   7  #include <stdarg.h> // va_{start|end}
   8  #include <stdlib.h> // free, rand
   9  
  10  #include "dkg.h"
  11  #include "tp-dkg.h"
  12  #include "utils.h"
  13  #ifdef __ZEPHYR__
  14  #include <zephyr/kernel.h>
  15  #endif
  16  
  17  /*
  18      @copyright 2024, Stefan Marsiske toprf@ctrlc.hu
  19      This file is part of liboprf.
  20  
  21      SPDX-FileCopyrightText: 2024, Marsiske Stefan
  22      SPDX-License-Identifier: LGPL-3.0-or-later
  23  
  24      liboprf is free software: you can redistribute it and/or
  25      modify it under the terms of the GNU Lesser General Public License
  26      as published by the Free Software Foundation, either version 3 of
  27      the License, or (at your option) any later version.
  28  
  29      liboprf is distributed in the hope that it will be useful,
  30      but WITHOUT ANY WARRANTY; without even the implied warranty of
  31      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  32      GNU Lesser General Public License for more details.
  33  
  34      You should have received a copy of the License
  35      along with liboprf. If not, see <http://www.gnu.org/licenses/>.
  36  */
  37  
  38  /*
  39    This file implements a high-level DKG protocol facilitated by a
  40    trusted orchestrator which connects to all participating peers in a
  41    star topology.
  42  
  43    The underlying algorithm is based on the JF-DKG (fig 1.) a variant
  44    on Pedersens DKG from the paper "Secure Distributed Key Generation
  45    for Discrete-Log Based Cryptosystems" by R. Gennaro, S. Jarecki,
  46    H. Krawczyk, and T. Rabin.
  47   */
  48  
  49  #define tpdkg_msg1_SIZE (sizeof(DKG_Message))
  50  #define tpdkg_msg2_SIZE (sizeof(DKG_Message) + crypto_sign_PUBLICKEYBYTES + crypto_scalarmult_BYTES)
  51  #define tpdkg_msg4_SIZE (sizeof(DKG_Message) + noise_xk_handshake1_SIZE)
  52  #define tpdkg_msg5_SIZE (sizeof(DKG_Message) + noise_xk_handshake2_SIZE)
  53  #define tpdkg_msg6_SIZE(ctx) (sizeof(DKG_Message) + (size_t)(crypto_core_ristretto255_BYTES * ctx->t) )
  54  #define tpdkg_msg9_SIZE(ctx) (sizeof(DKG_Message) + (size_t)(ctx->n + 1) )
  55  #define tpdkg_msg10_SIZE(ctx) (sizeof(DKG_Message) + (size_t)(ctx->n * tpdkg_msg9_SIZE(ctx)) )
  56  #define tpdkg_msg19_SIZE (sizeof(DKG_Message) + crypto_generichash_BYTES)
  57  #define tpdkg_msg20_SIZE (sizeof(DKG_Message) + 2)
  58  #define tpdkg_msg21_SIZE (sizeof(DKG_Message) + 2)
  59  
  60  size_t tpdkg_peerstate_size(void) {
  61    return sizeof(TP_DKG_PeerState);
  62  }
  63  uint8_t tpdkg_peerstate_n(const TP_DKG_PeerState *ctx) {
  64    return ctx->n;
  65  }
  66  uint8_t tpdkg_peerstate_t(const TP_DKG_PeerState *ctx) {
  67    return ctx->t;
  68  }
  69  const uint8_t* tpdkg_peerstate_sessionid(const TP_DKG_PeerState *ctx) {
  70    return ctx->sessionid;
  71  }
  72  const uint8_t* tpdkg_peerstate_lt_sk(const TP_DKG_PeerState *ctx) {
  73    return ctx->lt_sk;
  74  }
  75  const uint8_t* tpdkg_peerstate_share(const TP_DKG_PeerState *ctx) {
  76    return (const uint8_t*) &ctx->share;
  77  }
  78  int tpdkg_peerstate_step(const TP_DKG_PeerState *ctx) {
  79    return ctx->step;
  80  }
  81  
  82  size_t tpdkg_tpstate_size(void) {
  83    return sizeof(TP_DKG_TPState);
  84  }
  85  uint8_t tpdkg_tpstate_n(const TP_DKG_TPState *ctx) {
  86    return ctx->n;
  87  }
  88  uint8_t tpdkg_tpstate_t(const TP_DKG_TPState *ctx) {
  89    return ctx->t;
  90  }
  91  size_t tpdkg_tpstate_cheater_len(const TP_DKG_TPState *ctx) {
  92    return ctx->cheater_len;
  93  }
  94  const uint8_t* tpdkg_tpstate_sessionid(const TP_DKG_TPState *ctx) {
  95    return ctx->sessionid;
  96  }
  97  int tpdkg_tpstate_step(const TP_DKG_TPState *ctx) {
  98    return ctx->step;
  99  }
 100  
 101  static int tp_send_msg(uint8_t* msg_buf, const size_t msg_buf_len, const uint8_t msgno, const uint8_t from, const uint8_t to, const uint8_t *sig_sk, const uint8_t sessionid[dkg_sessionid_SIZE]) {
 102    return send_msg(msg_buf, msg_buf_len, MSG_TYPE_TRUSTED | MSG_TYPE_DKG, 0, msgno, from, to, sig_sk, sessionid);
 103  }
 104  
 105  static int tp_recv_msg(const uint8_t *msg_buf, const size_t msg_buf_len, const uint8_t msgno, const uint8_t from, const uint8_t to, const uint8_t *sig_pk, const uint8_t sessionid[dkg_sessionid_SIZE], const uint64_t ts_epsilon, uint64_t *last_ts) {
 106    return recv_msg(msg_buf, msg_buf_len, MSG_TYPE_TRUSTED | MSG_TYPE_DKG, 0, msgno, from, to, sig_pk, sessionid, ts_epsilon, last_ts);
 107  }
 108  
 109  static TP_DKG_Cheater* add_cheater(TP_DKG_TPState *ctx, const int step, const int error, const uint8_t peer, const uint8_t other_peer) {
 110    if(ctx->cheater_len >= ctx->cheater_max) return NULL;
 111    TP_DKG_Cheater *cheater = &(*ctx->cheaters)[ctx->cheater_len++];
 112    cheater->step = step;
 113    cheater->error = error;
 114    cheater->peer = peer;
 115    cheater->other_peer=other_peer;
 116    return cheater;
 117  }
 118  
 119  size_t tpdkg_tp_input_size(const TP_DKG_TPState *ctx) {
 120    size_t sizes[ctx->n];
 121    //memset(sizes,0,sizeof sizes);
 122    if(tpdkg_tp_input_sizes(ctx, sizes) == 1) {
 123      return sizes[0] * ctx->n;
 124    } else {
 125      size_t result=0;
 126      for(int i=0;i<ctx->n;i++) result+=sizes[i];
 127      return result;
 128    }
 129  }
 130  
 131  int tpdkg_tp_input_sizes(const TP_DKG_TPState *ctx, size_t *sizes) {
 132    size_t item=0;
 133    switch(ctx->step) {
 134    case 0: { item=0; break; }
 135    case 1: { item=(tpdkg_msg2_SIZE + crypto_sign_BYTES); break; }
 136    case 2: { item=tpdkg_msg4_SIZE * ctx->n; break; }
 137    case 3: { item=tpdkg_msg4_SIZE * ctx->n; break; }
 138    case 4: { item=tpdkg_msg6_SIZE(ctx); break; }
 139    case 5: { item=ctx->n * tpdkg_msg8_SIZE; break; }
 140    case 6: { item=tpdkg_msg9_SIZE(ctx); break; }
 141    case 7: {
 142      uint8_t ctr[ctx->n];
 143      memset(ctr,0,ctx->n);
 144      for(int i=0;i<ctx->complaints_len;i++) ctr[((*ctx->complaints)[i] & 0xff) - 1]++;
 145      for(int i=0;i<ctx->n;i++) {
 146        if(ctr[i]>0) {
 147          sizes[i]=sizeof(DKG_Message) + (1+dkg_noise_key_SIZE) * ctr[i];
 148        } else {
 149          sizes[i]=0;
 150        }
 151      }
 152      return 0;
 153    }
 154    case 8: { item=tpdkg_msg19_SIZE; break; }
 155    case 9: { item=tpdkg_msg21_SIZE; break; }
 156    default: {
 157      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[!] invalid tp step\n");
 158    }
 159    }
 160  
 161    for(uint8_t i=0;i<ctx->n;i++) {
 162      sizes[i] = item;
 163    }
 164    return 1;
 165  }
 166  
 167  size_t tpdkg_tp_output_size(const TP_DKG_TPState *ctx) {
 168    switch(ctx->step) {
 169    case 0: return ctx->n*tpdkg_msg1_SIZE;
 170    case 1: return tpdkg_msg2_SIZE * ctx->n + sizeof(DKG_Message);
 171    case 2: return tpdkg_msg4_SIZE * ctx->n * ctx->n;
 172    case 3: return tpdkg_msg5_SIZE * ctx->n * ctx->n;
 173    case 4: return sizeof(DKG_Message) + (tpdkg_msg6_SIZE(ctx) * ctx->n);
 174    case 5: return ctx->n * ctx->n * tpdkg_msg8_SIZE;
 175    case 6: return tpdkg_msg10_SIZE(ctx);
 176    case 7: return 0;
 177    case 8: return tpdkg_msg20_SIZE;
 178    case 9: return 0;
 179    default: if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[!] invalid tp step\n");
 180    }
 181    return 0;
 182  }
 183  
 184  int tpdkg_tp_peer_msg(const TP_DKG_TPState *ctx, const uint8_t *base, const size_t base_size, const uint8_t peer, const uint8_t **msg, size_t *len) {
 185    if(peer>=ctx->n) return -1;
 186  
 187    switch(ctx->prev) {
 188    case 0: {
 189      *msg = base + peer*tpdkg_msg1_SIZE;
 190      *len = tpdkg_msg1_SIZE;
 191      break;
 192    }
 193    case 1: {
 194      *msg = base;
 195      *len = tpdkg_msg2_SIZE * ctx->n + sizeof(DKG_Message);
 196      break;
 197    }
 198    case 2: {
 199      *msg = base + peer * tpdkg_msg4_SIZE * ctx->n;
 200      *len = tpdkg_msg4_SIZE * ctx->n;
 201      break;
 202    }
 203    case 3: {
 204      *msg = base + peer * tpdkg_msg5_SIZE * ctx->n;
 205      *len = tpdkg_msg5_SIZE * ctx->n;
 206      break;
 207    }
 208    case 4: {
 209      *msg = base;
 210      *len = sizeof(DKG_Message) + (tpdkg_msg6_SIZE(ctx) * ctx->n);
 211      break;
 212    }
 213    case 5: {
 214      *msg = base + peer * ctx->n * tpdkg_msg8_SIZE;
 215      *len = ctx->n * tpdkg_msg8_SIZE;
 216      break;
 217    }
 218    case 6: {
 219      *msg = base;
 220      *len = tpdkg_msg10_SIZE(ctx);
 221      break;
 222    }
 223    case 7: {
 224      *len = 0;
 225      *msg = NULL;
 226      break;
 227    }
 228    case 8: {
 229      *msg = base;
 230      *len = tpdkg_msg20_SIZE;
 231      break;
 232    }
 233    case 9: {
 234      *len = 0;
 235      *msg = NULL;
 236      break;
 237    }
 238    default: {
 239      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[!] invalid tp step in tpdkg_tp_peer_msg\n");
 240      return 1;
 241    }
 242    }
 243  
 244    if(base+base_size < *msg + *len) {
 245      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "buffer overread detected in tpdkg_tp_peer_msg %ld\n", (base+base_size) - (*msg + *len));
 246      return 2;
 247    }
 248  
 249    return 0;
 250  }
 251  
 252  size_t tpdkg_peer_input_size(const TP_DKG_PeerState *ctx) {
 253    switch(ctx->step) {
 254    case 0: return tpdkg_msg1_SIZE;
 255    case 1: return tpdkg_msg2_SIZE * ctx->n + sizeof(DKG_Message);
 256    case 2: return tpdkg_msg4_SIZE * ctx->n;
 257    case 3: return tpdkg_msg5_SIZE * ctx->n;
 258    case 4: return sizeof(DKG_Message) + (tpdkg_msg6_SIZE(ctx) * ctx->n);
 259    case 5: return ctx->n * tpdkg_msg8_SIZE;
 260    case 6: return tpdkg_msg10_SIZE(ctx);
 261    case 7: return 0;
 262    case 8: return 0;
 263    case 9: return tpdkg_msg20_SIZE;
 264    case 10: return 0;
 265    default: {
 266      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[%d] invalid step\n", ctx->index);
 267    }
 268    }
 269    return 1;
 270  }
 271  
 272  size_t tpdkg_peer_output_size(const TP_DKG_PeerState *ctx) {
 273    switch(ctx->step) {
 274    case 0: return tpdkg_msg2_SIZE+crypto_sign_BYTES;
 275    case 1: return tpdkg_msg4_SIZE * ctx->n;
 276    case 2: return tpdkg_msg5_SIZE * ctx->n;
 277    case 3: return tpdkg_msg6_SIZE(ctx);
 278    case 4: return ctx->n * tpdkg_msg8_SIZE;
 279    case 5: return tpdkg_msg9_SIZE(ctx);
 280    case 6: return 0;
 281    case 7: {
 282      if(ctx->complaints_len > 0) {
 283        if(ctx->my_complaints_len > 0) {
 284          return sizeof(DKG_Message) + ctx->my_complaints_len * (1+dkg_noise_key_SIZE);
 285        }
 286        return 0;
 287      }
 288      return tpdkg_msg19_SIZE;
 289    }
 290    case 8: return tpdkg_msg19_SIZE;
 291    case 9: return tpdkg_msg21_SIZE;
 292    case 10: return 0;
 293    default: {
 294      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[%d] invalid step\n", ctx->index);
 295    }
 296    }
 297    return 1;
 298  }
 299  
 300  void tpdkg_peer_set_bufs(TP_DKG_PeerState *ctx,
 301                           uint8_t (*peers_sig_pks)[][crypto_sign_PUBLICKEYBYTES],
 302                           uint8_t (*peers_noise_pks)[][crypto_scalarmult_BYTES],
 303                           Noise_XK_session_t *(*noise_outs)[],
 304                           Noise_XK_session_t *(*noise_ins)[],
 305                           TOPRF_Share (*shares)[],
 306                           TOPRF_Share (*xshares)[],
 307                           uint8_t (*commitments)[][crypto_core_ristretto255_BYTES],
 308                           uint16_t *complaints,
 309                           uint8_t *my_complaints,
 310                           uint64_t *last_ts) {
 311    ctx->peer_sig_pks = peers_sig_pks;
 312    ctx->peer_noise_pks = peers_noise_pks;
 313    ctx->noise_outs = noise_outs;
 314    ctx->noise_ins = noise_ins;
 315    ctx->shares = shares;
 316    ctx->xshares = xshares;
 317    ctx->commitments = commitments;
 318    ctx->complaints = complaints;
 319    ctx->my_complaints = my_complaints;
 320    ctx->last_ts = last_ts;
 321    for(uint8_t i=0;i<ctx->n;i++) ctx->last_ts[i]=0;
 322  }
 323  
 324  int tpdkg_tp_not_done(const TP_DKG_TPState *tp) {
 325    return tp->step<10;
 326  }
 327  
 328  int tpdkg_peer_not_done(const TP_DKG_PeerState *peer) {
 329    return peer->step<11;
 330  }
 331  
 332  void tpdkg_peer_free(TP_DKG_PeerState *ctx) {
 333    for(int i=0;i<ctx->n;i++) {
 334      if((*ctx->noise_ins)[i]!=NULL) Noise_XK_session_free((*ctx->noise_ins)[i]);
 335      if((*ctx->noise_outs)[i]!=NULL) Noise_XK_session_free((*ctx->noise_outs)[i]);
 336    }
 337    if(ctx->dev!=NULL) Noise_XK_device_free(ctx->dev);
 338  }
 339  
 340  void tpdkg_tp_set_bufs(TP_DKG_TPState *ctx,
 341                         uint8_t (*commitments)[][crypto_core_ristretto255_BYTES],
 342                         uint16_t (*complaints)[],
 343                         uint8_t (*encrypted_shares)[][tpdkg_msg8_SIZE],
 344                         TP_DKG_Cheater (*cheaters)[], const size_t cheater_max,
 345                         uint8_t (*tp_peers_sig_pks)[][crypto_sign_PUBLICKEYBYTES],
 346                         uint8_t (*peer_lt_pks)[][crypto_sign_PUBLICKEYBYTES],
 347                         uint64_t *last_ts) {
 348    ctx->commitments = commitments;
 349    ctx->complaints = complaints;
 350    ctx->encrypted_shares = encrypted_shares;
 351    ctx->cheaters = cheaters;
 352    memset(*cheaters, 0, cheater_max*sizeof(TP_DKG_Cheater));
 353    ctx->cheater_max = cheater_max;
 354    ctx->peer_sig_pks = tp_peers_sig_pks;
 355    ctx->peer_lt_pks = peer_lt_pks;
 356    ctx->last_ts = last_ts;
 357  #ifdef __ZEPHYR__
 358    uint64_t now = (uint64_t) k_uptime_get();
 359  #else
 360    uint64_t now = (uint64_t)time(NULL);
 361  #endif
 362    for(uint8_t i=0;i<ctx->n;i++) ctx->last_ts[i]=now;
 363  }
 364  
 365  int tpdkg_start_tp(TP_DKG_TPState *ctx, const uint64_t ts_epsilon,
 366               const uint8_t n, const uint8_t t,
 367               const char *proto_name, const size_t proto_name_len,
 368               const size_t msg0_len, DKG_Message *msg0) {
 369    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step 0. start protocol\x1b[0m\n");
 370    if(2>n || t>=n || n>128) return 1;
 371    if(proto_name_len<1) return 2;
 372    if(proto_name_len>1024) return 3;
 373    if(msg0_len != tpdkg_msg0_SIZE) return 4;
 374  
 375    ctx->ts_epsilon = ts_epsilon;
 376    ctx->step = 0;
 377    ctx->n = n;
 378    ctx->t = t;
 379    ctx->complaints_len = 0;
 380    ctx->cheater_len = 0;
 381  
 382    // dst hash(len(protoname) | "DKG for protocol " | protoname)
 383    crypto_generichash_state dst_state;
 384    crypto_generichash_init(&dst_state, NULL, 0, crypto_generichash_BYTES);
 385    uint16_t len=htons((uint16_t) proto_name_len+20U); // we have a guard above restricting to 1KB the proto_name_len
 386    crypto_generichash_update(&dst_state, (uint8_t*) &len, 2);
 387    crypto_generichash_update(&dst_state, (const uint8_t*) "TP DKG for protocol ", 20);
 388    crypto_generichash_update(&dst_state, (const uint8_t*) proto_name, proto_name_len);
 389    uint8_t dst[crypto_generichash_BYTES];
 390    crypto_generichash_final(&dst_state,dst,sizeof dst);
 391  
 392    // set session id
 393    randombytes_buf(&ctx->sessionid, sizeof ctx->sessionid);
 394  
 395    // generate signing key for this session
 396    crypto_sign_keypair(ctx->sig_pk, ctx->sig_sk);
 397  
 398    // data = {tp_sign_pk, dst, sessionid, n, t}
 399    uint8_t *ptr = msg0->data;
 400    memcpy(ptr, ctx->sig_pk, sizeof ctx->sig_pk);
 401    ptr+=sizeof ctx->sig_pk;
 402    memcpy(ptr, dst, sizeof dst);
 403    ptr+=sizeof dst;
 404    *ptr++ = n;
 405    *ptr++ = t;
 406  
 407    if(0!=tp_send_msg((uint8_t*) msg0, tpdkg_msg0_SIZE, 0, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return 5;
 408  
 409    // init transcript
 410    crypto_generichash_init(&ctx->transcript, NULL, 0, crypto_generichash_BYTES);
 411    crypto_generichash_update(&ctx->transcript, (const uint8_t*) "tp dkg session transcript", 25);
 412    // feed msg0 into transcript
 413    update_transcript(&ctx->transcript, (uint8_t*) msg0, msg0_len);
 414  
 415    if(liboprf_log_file!=NULL) {
 416      fprintf(liboprf_log_file,"[!] msgno: %d, from: %d to: 0x%x ", msg0->msgno, msg0->from, msg0->to);
 417      dump((uint8_t*) msg0, tpdkg_msg0_SIZE, "msg");
 418    }
 419  
 420    return 0;
 421  }
 422  
 423  int tpdkg_start_peer(TP_DKG_PeerState *ctx, const uint64_t ts_epsilon,
 424                 const uint8_t peer_lt_sk[crypto_sign_SECRETKEYBYTES],
 425                 const DKG_Message *msg0) {
 426    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[?] step 0.5 start peer\x1b[0m\n");
 427  
 428    if(liboprf_log_file!=NULL) {
 429      fprintf(liboprf_log_file,"[?] msgno: %d, from: %d to: 0x%x ", msg0->msgno, msg0->from, msg0->to);
 430      dump((const uint8_t*) msg0, tpdkg_msg0_SIZE, "msg");
 431    }
 432  
 433    ctx->ts_epsilon = ts_epsilon;
 434    ctx->tp_last_ts = 0;
 435  
 436    int ret = tp_recv_msg((const uint8_t*) msg0, tpdkg_msg0_SIZE, 0, 0, 0xff, msg0->data, msg0->sessionid, ts_epsilon, &ctx->tp_last_ts);
 437    if(0!=ret) return 64 + ret;
 438  
 439    // extract data from message
 440    memcpy(ctx->sessionid, msg0->sessionid, sizeof ctx->sessionid);
 441  
 442    const uint8_t *ptr=msg0->data;
 443    memcpy(ctx->tp_sig_pk,ptr,sizeof ctx->tp_sig_pk);
 444    ptr+=sizeof ctx->tp_sig_pk + crypto_generichash_BYTES; // also skip DST
 445    ctx->n = *ptr++;
 446    ctx->t = *ptr++;
 447  
 448    if(ctx->t < 2) return 1;
 449    if(ctx->t >= ctx->n) return 2;
 450    if(ctx->n > 128) return 3;
 451  
 452    ctx->complaints_len = 0;
 453    ctx->my_complaints_len = 0;
 454    memcpy(ctx->lt_sk, peer_lt_sk, crypto_sign_SECRETKEYBYTES);
 455  
 456    crypto_generichash_init(&ctx->transcript, NULL, 0, crypto_generichash_BYTES);
 457    crypto_generichash_update(&ctx->transcript, (const uint8_t*) "tp dkg session transcript", 25);
 458    // feed msg0 into transcript
 459    update_transcript(&ctx->transcript, (const uint8_t*) msg0, tpdkg_msg0_SIZE);
 460  
 461    ctx->dev = NULL;
 462    ctx->step = 0;
 463  
 464    return 0;
 465  }
 466  
 467  static int tp_step1_handler(const TP_DKG_TPState *ctx, uint8_t *output, const size_t output_len) {
 468    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step 1. assign peer indices\x1b[0m\n");
 469    if(output_len!=ctx->n * tpdkg_msg1_SIZE) return 2;
 470  
 471    uint8_t* ptr = output;
 472    for(uint8_t i=1;i<=ctx->n;i++,ptr+=tpdkg_msg1_SIZE) {
 473      if(0!=tp_send_msg(ptr, sizeof(DKG_Message), 1, 0, i, ctx->sig_sk, ctx->sessionid)) return 3;
 474      dkg_dump_msg(ptr, tpdkg_msg1_SIZE, 0);
 475    }
 476  
 477    return 0;
 478  }
 479  
 480  static int peer_step23_handler(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 481    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[?] step 2. receive peers index\x1b[0m\n");
 482    if(input_len != tpdkg_msg1_SIZE) return 1;
 483    if(output_len != tpdkg_msg2_SIZE+crypto_sign_BYTES) return 2;
 484  
 485    dkg_dump_msg(input, input_len, ctx->index);
 486    const DKG_Message *msg1=(const DKG_Message*) input;
 487    int ret = tp_recv_msg(input, tpdkg_msg1_SIZE, 1, 0, msg1->to, ctx->tp_sig_pk, ctx->sessionid, ctx->ts_epsilon, &ctx->tp_last_ts);
 488    if(0!=ret) return 4 + ret;
 489    if(msg1->to > 128 || msg1->to < 1) return 3;
 490    ctx->index=msg1->to;
 491  
 492    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 3. send msg2 containing ephemeral pubkey\x1b[0m\n", ctx->index);
 493  
 494    crypto_sign_keypair(ctx->sig_pk, ctx->sig_sk);
 495  
 496    randombytes_buf(ctx->noise_sk, sizeof ctx->noise_sk);
 497    crypto_scalarmult_base(ctx->noise_pk, ctx->noise_sk);
 498  
 499    uint8_t *wptr = ((DKG_Message *) output)->data;
 500    memcpy(wptr, ctx->sig_pk, sizeof ctx->sig_pk);
 501    wptr+=sizeof ctx->sig_pk;
 502    memcpy(wptr, ctx->noise_pk, sizeof ctx->noise_pk);
 503    if(0!=tp_send_msg(output, tpdkg_msg2_SIZE, 2, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return 4;
 504    // sign message with long-term key
 505    crypto_sign_detached(output+tpdkg_msg2_SIZE,NULL,output,tpdkg_msg2_SIZE,ctx->lt_sk);
 506    sodium_memzero(ctx->lt_sk,crypto_sign_SECRETKEYBYTES);
 507  
 508    dkg_dump_msg(output, output_len, ctx->index);
 509  
 510    return 0;
 511  }
 512  
 513  static int tp_step4_handler(TP_DKG_TPState *ctx, const uint8_t *msg2s, const size_t msg2s_len, uint8_t *msg3_buf, const size_t msg3_buf_len) {
 514    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step 4. broadcast msg2 containing ephemeral pubkeys of peers\x1b[0m\n");
 515    if(((tpdkg_msg2_SIZE + crypto_sign_BYTES) * ctx->n) != msg2s_len) return 1;
 516    if(msg3_buf_len != (tpdkg_msg2_SIZE * ctx->n) + sizeof(DKG_Message)) return 2;
 517  
 518    const uint8_t *ptr = msg2s;
 519    uint8_t *wptr = ((DKG_Message *) msg3_buf)->data;
 520    for(uint8_t i=0;i<ctx->n;i++,ptr+=tpdkg_msg2_SIZE+crypto_sign_BYTES) {
 521      const DKG_Message* msg = (const DKG_Message*) ptr;
 522      // verify long-term pk sig on initial message
 523      dkg_dump_msg(ptr, tpdkg_msg2_SIZE, 0);
 524  #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
 525      if(0!=crypto_sign_verify_detached(ptr+tpdkg_msg2_SIZE,ptr,tpdkg_msg2_SIZE,(*ctx->peer_lt_pks)[i])) return 3;
 526  #endif
 527      int ret = tp_recv_msg(ptr, tpdkg_msg2_SIZE, 2, i+1U, 0xff, msg->data, ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
 528      if(0!=ret) {
 529        if(add_cheater(ctx, 4, 64+ret, i+1U,0xff) == NULL) return 7;
 530        continue;
 531      }
 532  
 533      // keep copy of ephemeral signing key
 534      memcpy((*ctx->peer_sig_pks)[i], msg->data, crypto_sign_PUBLICKEYBYTES);
 535      // strip away long-term signature
 536      memcpy(wptr, ptr, tpdkg_msg2_SIZE);
 537      wptr+=tpdkg_msg2_SIZE;
 538    }
 539    if(ctx->cheater_len>0) return 6;
 540  
 541    if(0!=tp_send_msg(msg3_buf, msg3_buf_len, 3, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return 5;
 542    update_transcript(&ctx->transcript, msg3_buf, msg3_buf_len);
 543  
 544    return 0;
 545  }
 546  
 547  static int peer_step5_handler(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 548    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 5. receive peers ephemeral pubkeys, start noise sessions\x1b[0m\n", ctx->index);
 549    if(input_len != tpdkg_msg2_SIZE * ctx->n + sizeof(DKG_Message)) return 1;
 550    if(output_len != tpdkg_msg4_SIZE * ctx->n) return 2;
 551  
 552    int ret = tp_recv_msg(input, input_len, 3, 0, 0xff, ctx->tp_sig_pk, ctx->sessionid, ctx->ts_epsilon, &ctx->tp_last_ts);
 553    if(0!=ret) return 32+ret;
 554  
 555    update_transcript(&ctx->transcript, input, input_len);
 556  
 557    // create noise device
 558    uint8_t iname[13];
 559    snprintf((char*) iname, sizeof iname, "dkg peer %02x", ctx->index);
 560    uint8_t dummy[32]={0}; // the following function needs a deserialization key, which we never use.
 561  
 562    ctx->dev = Noise_XK_device_create(13, (uint8_t*) "dpkg p2p v0.1", iname, dummy, ctx->noise_sk);
 563  
 564    const DKG_Message* msg3 = (const DKG_Message*) input;
 565    const uint8_t *ptr = msg3->data;
 566    uint8_t *wptr = output;
 567    for(uint8_t i=0;i<ctx->n;i++) {
 568      const DKG_Message* msg2 = (const DKG_Message*) ptr;
 569      dkg_dump_msg(ptr, tpdkg_msg2_SIZE, ctx->index);
 570      ret = tp_recv_msg(ptr, tpdkg_msg2_SIZE, 2, i+1U, 0xff, msg2->data, ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
 571      if(0!=ret) return 64+ret;
 572      // extract peer sig and noise pk
 573      memcpy((*ctx->peer_sig_pks)[i], msg2->data, crypto_sign_PUBLICKEYBYTES);
 574      memcpy((*ctx->peer_noise_pks)[i], msg2->data + crypto_sign_PUBLICKEYBYTES, crypto_scalarmult_BYTES);
 575      ptr+=tpdkg_msg2_SIZE;
 576  
 577      DKG_Message *msg4 = (DKG_Message *) wptr;
 578      uint8_t rname[13];
 579      snprintf((char*) rname, sizeof rname, "dkg peer %02x", i+1U);
 580      dkg_init_noise_handshake(ctx->index, ctx->dev, (*ctx->peer_noise_pks)[i], rname, &(*ctx->noise_outs)[i], msg4->data);
 581      if(0!=tp_send_msg(wptr, tpdkg_msg4_SIZE, 4, ctx->index, i+1U, ctx->sig_sk, ctx->sessionid)) return 5;
 582      dkg_dump_msg(wptr, tpdkg_msg4_SIZE, ctx->index);
 583      wptr+=tpdkg_msg4_SIZE;
 584    }
 585  
 586    return 0;
 587  }
 588  
 589  static int tp_step68_handler(TP_DKG_TPState *ctx, const uint8_t *msg4s, const size_t msg4s_len, uint8_t *output, const size_t output_len) {
 590    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step %d. route p2p noise handshakes to peers\x1b[0m\n", 6 + (ctx->step - 1) * 2);
 591    if(msg4s_len != tpdkg_msg4_SIZE * ctx->n * ctx->n) return 1;
 592    if(msg4s_len != output_len) return 2;
 593  
 594    const uint8_t (*inputs)[ctx->n][ctx->n][tpdkg_msg4_SIZE] = (const uint8_t (*)[ctx->n][ctx->n][tpdkg_msg4_SIZE]) msg4s;
 595    uint8_t *wptr = output;
 596    for(uint8_t i=0;i<ctx->n;i++) {
 597      for(uint8_t j=0;j<ctx->n;j++) {
 598        if(tpdkg_msg4_SIZE != tpdkg_msg5_SIZE) {
 599          if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "tpdkg_msg4_SIZE must be equal tpdkg_msg5_SIZE for the check to be correct in tp_step68_handler\n");
 600          return 3;
 601        }
 602        int ret = tp_recv_msg((*inputs)[j][i], tpdkg_msg4_SIZE, (uint8_t) (2+ctx->step), j+1, i+1U, (*ctx->peer_sig_pks)[j], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[j]);
 603        if(0!=ret) {
 604          if(add_cheater(ctx, 6 + (ctx->step - 1) * 2, 64+ret, j+1U, i+1U) == NULL) return 7;
 605          const DKG_Message *msg = (const DKG_Message*) (*inputs)[j][i];
 606          fprintf(liboprf_log_file,"[x] msgno: %d, from: %d to: %d ", msg->msgno, msg->from, msg->to);
 607          dump((*inputs)[j][i], tpdkg_msg4_SIZE, "msg");
 608          continue;
 609        }
 610        memcpy(wptr, (*inputs)[j][i], tpdkg_msg4_SIZE);
 611        wptr+=tpdkg_msg4_SIZE;
 612      }
 613    }
 614    if(ctx->cheater_len>0) return 6;
 615  
 616    return 0;
 617  }
 618  
 619  static int peer_step7_handler(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 620    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 7. receive session requests\x1b[0m\n", ctx->index);
 621    if(input_len != tpdkg_msg4_SIZE * ctx->n) return 1;
 622    if(output_len != tpdkg_msg5_SIZE * ctx->n) return 2;
 623  
 624    const uint8_t *ptr = input;
 625    uint8_t *wptr = output;
 626    for(uint8_t i=0;i<ctx->n;i++) {
 627      DKG_Message* msg4 = (DKG_Message*) ptr;
 628      dkg_dump_msg(ptr, tpdkg_msg4_SIZE, ctx->index);
 629      int ret = tp_recv_msg(ptr, tpdkg_msg4_SIZE, 4, i+1U, ctx->index, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
 630      if(0!=ret) return 64+ret;
 631      ptr+=tpdkg_msg4_SIZE;
 632  
 633      // respond to noise handshake request
 634      DKG_Message *msg5 = (DKG_Message *) wptr;
 635      uint8_t rname[13];
 636      snprintf((char*) rname, sizeof rname, "dkg peer %02x", i+1U);
 637      dkg_respond_noise_handshake(ctx->index, ctx->dev, rname, &(*ctx->noise_ins)[i], msg4->data, msg5->data);
 638      if(0!=tp_send_msg(wptr, tpdkg_msg5_SIZE, 5, ctx->index, i+1U, ctx->sig_sk, ctx->sessionid)) return 4;
 639      dkg_dump_msg(wptr, tpdkg_msg5_SIZE, ctx->index);
 640      wptr+=tpdkg_msg5_SIZE;
 641    }
 642  
 643    return 0;
 644  }
 645  
 646  static int peer_step911_handler(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 647    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 9-11 finish session handshake, broadcast commitments\x1b[0m\n", ctx->index);
 648    if(input_len != tpdkg_msg5_SIZE * ctx->n) return 1;
 649    if(output_len != tpdkg_msg6_SIZE(ctx)) return 2;
 650  
 651    const uint8_t *ptr = input;
 652    for(uint8_t i=0;i<ctx->n;i++) {
 653      DKG_Message* msg5 = (DKG_Message*) ptr;
 654      dkg_dump_msg(ptr, tpdkg_msg5_SIZE, ctx->index);
 655      int ret = tp_recv_msg(ptr, tpdkg_msg5_SIZE, 5, i+1U, ctx->index, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
 656      if(0!=ret) return 64+ret;
 657      ptr+=tpdkg_msg5_SIZE;
 658      // process final step of noise handshake
 659      dkg_finish_noise_handshake(ctx->index, ctx->dev, &(*ctx->noise_outs)[i], msg5->data);
 660    }
 661  
 662    DKG_Message* msg6 = (DKG_Message*) output;
 663    if(0!=dkg_start(ctx->n, ctx->t, (uint8_t (*)[32]) msg6->data, *ctx->shares)) return 4;
 664    if(0!=tp_send_msg(output, tpdkg_msg6_SIZE(ctx), 6, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return 4;
 665    dkg_dump_msg(output, tpdkg_msg6_SIZE(ctx), ctx->index);
 666    if(liboprf_log_file!=NULL) {
 667      dump(msg6->data, ctx->t*crypto_core_ristretto255_BYTES, "[%d] commitments", ctx->index);
 668    }
 669  
 670    return 0;
 671  }
 672  
 673  static int tp_step12_handler(TP_DKG_TPState *ctx, const uint8_t *msg6s, const size_t msg6s_len, uint8_t *msg7_buf, const size_t msg7_buf_len) {
 674    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step 12. broadcast commitments of peers\x1b[0m\n");
 675  
 676    if((tpdkg_msg6_SIZE(ctx) * ctx->n) != msg6s_len) return 1;
 677    if(msg7_buf_len != sizeof(DKG_Message) + msg6s_len) return 2;
 678    const uint8_t *ptr = msg6s;
 679    uint8_t *wptr = ((DKG_Message *) msg7_buf)->data;
 680    for(uint8_t i=0;i<ctx->n;i++,ptr+=tpdkg_msg6_SIZE(ctx)) {
 681      const DKG_Message* msg = (const DKG_Message*) ptr;
 682      dkg_dump_msg(ptr, tpdkg_msg6_SIZE(ctx), 0);
 683      int ret = tp_recv_msg(ptr, tpdkg_msg6_SIZE(ctx), 6, i+1U, 0xff, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
 684      if(0!=ret) {
 685        if(add_cheater(ctx, 12, 64+ret, i+1U,0xff) == NULL) return 7;
 686        continue;
 687      }
 688  
 689      memcpy((*ctx->commitments)[i*ctx->t], msg->data, crypto_core_ristretto255_BYTES * ctx->t);
 690      if(liboprf_log_file!=NULL) {
 691        dump((*ctx->commitments)[i*ctx->t], crypto_core_ristretto255_BYTES * ctx->t, "[!] commitments[%d]", i+1U);
 692      }
 693  
 694      memcpy(wptr, ptr, tpdkg_msg6_SIZE(ctx));
 695      wptr+=tpdkg_msg6_SIZE(ctx);
 696    }
 697    if(ctx->cheater_len>0) return 6;
 698  
 699    if(0!=tp_send_msg(msg7_buf, msg7_buf_len, 7, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return 4;
 700    dkg_dump_msg(msg7_buf, msg7_buf_len, 0);
 701  
 702    // add broadcast msg to transcript
 703    update_transcript(&ctx->transcript, msg7_buf, msg7_buf_len);
 704  
 705    return 0;
 706  }
 707  
 708  static int peer_step13_handler(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 709    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 13. receive commitments, distribute shares via noise chans\x1b[0m\n", ctx->index);
 710    if(input_len != sizeof(DKG_Message) + (tpdkg_msg6_SIZE(ctx) * ctx->n)) return 1;
 711    if(output_len != ctx->n * tpdkg_msg8_SIZE) return 2;
 712  
 713    // verify TP message envelope
 714    const DKG_Message* msg7 = (const DKG_Message*) input;
 715    dkg_dump_msg(input, input_len, ctx->index);
 716    int ret = tp_recv_msg(input, input_len, 7, 0, 0xff, ctx->tp_sig_pk, ctx->sessionid, ctx->ts_epsilon, &ctx->tp_last_ts);
 717    if(0!=ret) return 32+ret;
 718  
 719    // add broadcast msg to transcript
 720    update_transcript(&ctx->transcript, input, input_len);
 721  
 722    const uint8_t *ptr = msg7->data;
 723    uint8_t *wptr = output;
 724    for(uint8_t i=0;i<ctx->n;i++, wptr+=tpdkg_msg8_SIZE,ptr+=tpdkg_msg6_SIZE(ctx)) {
 725      const DKG_Message* msg6 = (const DKG_Message*) ptr;
 726      dkg_dump_msg(ptr, tpdkg_msg6_SIZE(ctx), ctx->index);
 727      if(0!=tp_recv_msg(ptr, tpdkg_msg6_SIZE(ctx), 6, i+1U, 0xff, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i])) return 64+ret;
 728      // extract peer commitments
 729      memcpy((*ctx->commitments)[i*ctx->t], msg6->data, crypto_core_ristretto255_BYTES * ctx->t);
 730  
 731      DKG_Message *msg8 = (DKG_Message *) wptr;
 732  
 733      // we need to send an empty packet, so that the handshake completes
 734      // and we have a final symetric key, the key during the handshake changes, only
 735      // when the handshake completes does the key become static.
 736      // this is important, so that when there are complaints, we can disclose the key.
 737      uint8_t empty[1]={0};
 738      if(0!=dkg_noise_encrypt(empty, 0, msg8->data, noise_xk_handshake3_SIZE, &(*ctx->noise_outs)[i])) return 5;
 739  
 740  #ifdef UNITTEST_CORRUPT
 741      // corrupt all shares
 742      static int corrupted_shares = 0;
 743      uint8_t corrupted_share[sizeof(TOPRF_Share)];
 744      memcpy(corrupted_share, &(*ctx->shares)[i], sizeof(TOPRF_Share));
 745      if(i+1U != ctx->index && corrupted_shares++ < ctx->t-1) {
 746        dump(corrupted_share, sizeof(TOPRF_Share), "[%d] corrupting share_%d", ctx->index, i+1U);
 747        corrupted_share[2]^=0xff; // flip some bits
 748        dump(corrupted_share, sizeof(TOPRF_Share), "[%d] corrupted share_%d ", ctx->index, i+1U);
 749      }
 750      if(0!=dkg_noise_encrypt((uint8_t*) corrupted_share, sizeof(TOPRF_Share),
 751  #else
 752      if(0!=dkg_noise_encrypt((uint8_t*) &(*ctx->shares)[i], sizeof(TOPRF_Share),
 753  #endif // UNITTEST_CORRUPT
 754                                msg8->data + noise_xk_handshake3_SIZE, sizeof(TOPRF_Share) + crypto_secretbox_xchacha20poly1305_MACBYTES,
 755                                &(*ctx->noise_outs)[i])) return 6;
 756  
 757      // we also need to use a key-commiting mac over the encrypted share, since poly1305 is not...
 758      crypto_auth(msg8->data + noise_xk_handshake3_SIZE + sizeof(TOPRF_Share) + crypto_secretbox_xchacha20poly1305_MACBYTES,
 759                  msg8->data + noise_xk_handshake3_SIZE,
 760                  sizeof(TOPRF_Share) + crypto_secretbox_xchacha20poly1305_MACBYTES,
 761                  Noise_XK_session_get_key((*ctx->noise_outs)[i]));
 762  
 763      if(0!=tp_send_msg(wptr, tpdkg_msg8_SIZE, 8, ctx->index, i+1U, ctx->sig_sk, ctx->sessionid)) return 7;
 764      dkg_dump_msg(wptr, tpdkg_msg8_SIZE, ctx->index);
 765    }
 766  
 767    return 0;
 768  }
 769  
 770  static int tp_step14_handler(TP_DKG_TPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 771    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step 14. route shares from all peers to all peers\x1b[0m\n");
 772    if(input_len != tpdkg_msg8_SIZE * ctx->n * ctx->n) return 1;
 773    if(input_len != output_len) return 2;
 774  
 775    const uint8_t (*inputs)[ctx->n][ctx->n][tpdkg_msg8_SIZE] = (const uint8_t (*)[ctx->n][ctx->n][tpdkg_msg8_SIZE]) input;
 776    uint8_t *wptr = output;
 777    for(uint8_t i=0;i<ctx->n;i++) {
 778      for(uint8_t j=0;j<ctx->n;j++) {
 779        dkg_dump_msg((*inputs)[j][i], tpdkg_msg8_SIZE, 0);
 780        int ret = tp_recv_msg((*inputs)[j][i], tpdkg_msg8_SIZE, 8, j+1U, i+1U, (*ctx->peer_sig_pks)[j], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[j]);
 781        if(0!=ret) {
 782          if(add_cheater(ctx, 14, 64+ret, j+1U, i+1U) == NULL) return 7;
 783          continue;
 784        }
 785  
 786        memcpy(wptr, (*inputs)[j][i], tpdkg_msg8_SIZE);
 787        wptr+=tpdkg_msg8_SIZE;
 788      }
 789    }
 790    if(ctx->cheater_len>0) return 6;
 791  
 792    // keep a copy for complaint resolution.
 793    memcpy((*ctx->encrypted_shares), input, input_len);
 794  
 795    return 0;
 796  }
 797  
 798  static int peer_step15_handler(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 799    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 15. DKG step 2 - receive shares, verify commitments\x1b[0m\n", ctx->index);
 800    if(input_len != ctx->n * tpdkg_msg8_SIZE) return 1;
 801    if(output_len != tpdkg_msg9_SIZE(ctx)) return 2;
 802  
 803    const uint8_t *ptr = input;
 804    for(uint8_t i=0;i<ctx->n;i++) {
 805      const DKG_Message* msg8 = (const DKG_Message*) ptr;
 806      dkg_dump_msg(ptr, tpdkg_msg8_SIZE, ctx->index);
 807      int ret = tp_recv_msg(ptr, tpdkg_msg8_SIZE, 8, i+1U, ctx->index, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
 808      if(0!=ret) return 64+ret;
 809  
 810      // decrypt final empty handshake packet
 811      if(0!=dkg_noise_decrypt(msg8->data, noise_xk_handshake3_SIZE, NULL, 0, &(*ctx->noise_ins)[i])) return 4;
 812  
 813      if(0!=crypto_auth_verify(msg8->data + noise_xk_handshake3_SIZE + sizeof(TOPRF_Share) + crypto_secretbox_xchacha20poly1305_MACBYTES,
 814                               msg8->data + noise_xk_handshake3_SIZE,
 815                               sizeof(TOPRF_Share) + crypto_secretbox_xchacha20poly1305_MACBYTES,
 816                               Noise_XK_session_get_key((*ctx->noise_ins)[i]))) {
 817        return 5;
 818      }
 819  
 820      if(0!=dkg_noise_decrypt(msg8->data + noise_xk_handshake3_SIZE, sizeof(TOPRF_Share) + crypto_secretbox_xchacha20poly1305_MACBYTES,
 821                                (uint8_t*) &(*ctx->xshares)[i], sizeof(TOPRF_Share),
 822                                &(*ctx->noise_ins)[i])) return 6;
 823  
 824      ptr+=tpdkg_msg8_SIZE;
 825    }
 826  
 827    DKG_Message* msg9 = (DKG_Message*) output;
 828    uint8_t *fails_len = msg9->data;
 829    uint8_t *fails = msg9->data+1;
 830    memset(fails, 0, ctx->n);
 831    dkg_verify_commitments(ctx->n, ctx->t, ctx->index, ctx->commitments, *ctx->xshares, fails, fails_len);
 832  
 833  #ifdef UNITTEST_CORRUPT
 834    static int totalfails = 0;
 835    for(uint8_t i=1;i<=ctx->n;i++) {
 836      if(totalfails < ctx->t - ctx->index && *fails_len < ctx->t-1 && i != ctx->index) {
 837        // avoid duplicates
 838        int j;
 839        for(j=1;j<=msg9->data[0];j++) if(msg9->data[j]==i) break;
 840        if(j<=msg9->data[0]) continue;
 841  
 842        fails[msg9->data[0]++]=i;
 843        totalfails++;
 844      }
 845    }
 846  #endif //UNITTEST_CORRUPT
 847  
 848    if(liboprf_log_file!=NULL) {
 849      for(int j=0;j<*fails_len;j++) {
 850        fprintf(liboprf_log_file,"\x1b[0;31m[%d] failed to verify commitments from %d!\x1b[0m\n", ctx->index, fails[j]);
 851      }
 852    }
 853  
 854    if(0!=tp_send_msg(output, tpdkg_msg9_SIZE(ctx), 9, ctx->index, 0xff, ctx->sig_sk, ctx->sessionid)) return 7;
 855    dkg_dump_msg(output, tpdkg_msg9_SIZE(ctx), ctx->index);
 856  
 857    return 0;
 858  }
 859  
 860  static int tp_step16_handler(TP_DKG_TPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
 861    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step 16. broadcast complaints of peers\x1b[0m\n");
 862  
 863    if((tpdkg_msg9_SIZE(ctx) * ctx->n) != input_len) return 1;
 864    if(output_len != tpdkg_msg10_SIZE(ctx)) return 2;
 865  
 866    ctx->complaints_len = 0;
 867  
 868    const uint8_t *ptr = input;
 869    uint8_t *wptr = ((DKG_Message *) output)->data;
 870    for(uint8_t i=0;i<ctx->n;i++, ptr+=tpdkg_msg9_SIZE(ctx)) {
 871      const DKG_Message* msg = (const DKG_Message*) ptr;
 872      dkg_dump_msg(ptr, tpdkg_msg9_SIZE(ctx), 0);
 873      int ret = tp_recv_msg(ptr, tpdkg_msg9_SIZE(ctx), 9, i+1U, 0xff, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
 874      if(0!=ret) {
 875        if(add_cheater(ctx, 16, 64+ret, i+1U, 0xff) == NULL) return 6;
 876        continue;
 877      }
 878      if(msg->len - sizeof(DKG_Message) < msg->data[0]) return 4;
 879  
 880      // keep a copy all complaint pairs (complainer, complained)
 881      for(int k=0;k<msg->data[0] && (k+1)<msg->len-sizeof(DKG_Message);k++) {
 882        if(msg->data[k+1] > ctx->n || msg->data[k+1] < 1) {
 883          if(add_cheater(ctx, 16, 7, i+1U, msg->data[k+1]) == NULL) return 6;
 884          continue;
 885        }
 886        uint16_t pair=(uint16_t) (((i+1U)<<8) | msg->data[k+1]);
 887        int j=0;
 888        for(j=0;j<ctx->complaints_len;j++) if((*ctx->complaints)[j]==pair) break;
 889        if(j<ctx->complaints_len) {
 890          if(add_cheater(ctx, 16, 8, i+1U, msg->data[k+1]) == NULL) return 6;
 891          continue;
 892        }
 893        (*ctx->complaints)[ctx->complaints_len++] = pair;
 894        if(liboprf_log_file!=NULL) {
 895          fprintf(liboprf_log_file,"\x1b[0;31m[!] peer %d failed to verify commitments from peer %d!\x1b[0m\n", i+1U, msg->data[1+k]);
 896        }
 897      }
 898  
 899      memcpy(wptr, ptr, tpdkg_msg9_SIZE(ctx));
 900      wptr+=tpdkg_msg9_SIZE(ctx);
 901    }
 902    dump((uint8_t*) (*ctx->complaints), ctx->complaints_len*sizeof(uint16_t), "[!] complaints");
 903  
 904    // if more than t^2 complaints are received the protocol also fails
 905    if(ctx->complaints_len >= ctx->t * ctx->t) {
 906      if(add_cheater(ctx, 16, 6, 0xfe, 0xfe) == NULL) return 6;
 907      return 5;
 908    }
 909  
 910    if(ctx->cheater_len>0) return 5;
 911  
 912    if(0!=tp_send_msg(output, output_len, 10, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return 7;
 913    dkg_dump_msg(output, output_len, 0);
 914  
 915    // add broadcast msg to transcript
 916    update_transcript(&ctx->transcript, output, output_len);
 917  
 918    return 0;
 919  }
 920  
 921  static int peer_step17_handler(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len) {
 922    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 17. receive complaints broadcast\x1b[0m\n", ctx->index);
 923    if(input_len != tpdkg_msg10_SIZE(ctx)) return 1;
 924  
 925    // verify TP message envelope
 926    const DKG_Message* msg10 = (const DKG_Message*) input;
 927    dkg_dump_msg(input, input_len, ctx->index);
 928  
 929    int ret = tp_recv_msg(input, input_len, 10, 0, 0xff, ctx->tp_sig_pk, ctx->sessionid, ctx->ts_epsilon, &ctx->tp_last_ts);
 930    if(0!=ret) return 16+ret;
 931  
 932    // add broadcast msg to transcript
 933    update_transcript(&ctx->transcript, input, input_len);
 934  
 935    const uint8_t *ptr = msg10->data;
 936    for(uint8_t i=0;i<ctx->n;i++) {
 937      const DKG_Message* msg9 = (const DKG_Message*) ptr;
 938      dkg_dump_msg(ptr, tpdkg_msg9_SIZE(ctx), ctx->index);
 939      ret = tp_recv_msg(ptr, tpdkg_msg9_SIZE(ctx), 9, i+1U, 0xff, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
 940      if(0!=ret) return 32+ret;
 941      if(msg9->len - sizeof(DKG_Message) < msg9->data[0]) return 5;
 942  
 943      // keep a copy all complaint pairs (complainer, complained)
 944      for(int k=0;k<msg9->data[0] && (k+1)<msg9->len-sizeof(DKG_Message);k++) {
 945        uint16_t pair=(uint16_t) (((i+1U)<<8) | msg9->data[k+1]);
 946        int j=0;
 947        for(j=0;j<ctx->complaints_len;j++) if(ctx->complaints[j]==pair) break;
 948        if(j<ctx->complaints_len) continue;
 949        ctx->complaints[ctx->complaints_len++] = pair;
 950  
 951        if(msg9->data[k+1] == ctx->index) {
 952          ctx->my_complaints[ctx->my_complaints_len++] = i+1U;
 953          if(liboprf_log_file!=NULL) fprintf(liboprf_log_file,"\x1b[0;31m[%d] peer %d failed to verify commitments from peer %d!\x1b[0m\n", ctx->index, i+1U, msg9->data[1+k]);
 954        }
 955      }
 956  
 957      ptr+=tpdkg_msg9_SIZE(ctx);
 958    }
 959  
 960    if(ctx->complaints_len == 0) {
 961      ctx->prev = ctx->step;
 962      ctx->step+=1; // skip to step 19
 963    }
 964  
 965    return 0;
 966  }
 967  
 968  static int peer_step17a_handler(TP_DKG_PeerState *ctx, uint8_t *output, const size_t output_len) {
 969    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 17a. potentially broadcast contested shares\x1b[0m\n", ctx->index);
 970    if(output_len != tpdkg_peer_output_size(ctx)) return 2;
 971    if(output_len == 0) {
 972      if(liboprf_log_file!=NULL) {
 973        fprintf(liboprf_log_file,"[%d] nothing to defend against, no message to send\n", ctx->index);
 974      }
 975      return 0;
 976    }
 977  
 978    // send out all shares that belong to peers that complained.
 979    DKG_Message* msg11 = (DKG_Message*) output;
 980    uint8_t *wptr = msg11->data;
 981    for(int i=0;i<ctx->my_complaints_len;i++) {
 982      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;36m[%d] defending against complaint from %d\x1b[0m\n", ctx->index, ctx->my_complaints[i]);
 983  
 984      *wptr++ = ctx->my_complaints[i];
 985      // reveal key for noise wrapped share sent previously
 986      memcpy(wptr, Noise_XK_session_get_key((*ctx->noise_outs)[ctx->my_complaints[i]-1]), dkg_noise_key_SIZE);
 987      wptr+=dkg_noise_key_SIZE;
 988    }
 989  
 990    if(0!=tp_send_msg(output, tpdkg_peer_output_size(ctx), 11, ctx->index, 0x0, ctx->sig_sk, ctx->sessionid)) return 3;
 991    dkg_dump_msg(output, tpdkg_peer_output_size(ctx), ctx->index);
 992  
 993    // we skip to the end...
 994    ctx->step=99;
 995  
 996    return 0;
 997  }
 998  
 999  static int tp_step18_handler(TP_DKG_TPState *ctx, const uint8_t *input, const size_t input_len) {
1000    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step 18. collect keys of contested shares and verify the commitments\x1b[0m\n");
1001    if(input_len != tpdkg_tp_input_size(ctx)) return 1;
1002  
1003    unsigned int ctr[ctx->n];
1004    uint16_t complaints[ctx->complaints_len];
1005    memset(ctr,0,sizeof(ctr));
1006    for(int i=0;i<ctx->complaints_len;i++) {
1007      ctr[((*ctx->complaints)[i] & 0xff)-1]++;
1008      complaints[i] = (*ctx->complaints)[i];
1009    }
1010  
1011    uint8_t (*noisy_shares)[ctx->n][ctx->n][tpdkg_msg8_SIZE] = (uint8_t (*)[ctx->n][ctx->n][tpdkg_msg8_SIZE]) ctx->encrypted_shares;
1012  
1013    const uint8_t *ptr = input;
1014    size_t msg_len;
1015    for(uint8_t i=0;i<ctx->n;i++,ptr += msg_len) {
1016      if(ctr[i]==0) {
1017        msg_len = 0;
1018        continue; // no complaints against this peer
1019      }
1020      msg_len = sizeof(DKG_Message) + (1+dkg_noise_key_SIZE) * ctr[i];
1021  
1022      const DKG_Message* msg = (const DKG_Message*) ptr;
1023      dkg_dump_msg(ptr, msg_len, 0);
1024      int ret = tp_recv_msg(ptr, msg_len, 11, i+1U, 0, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
1025      if(0!=ret) {
1026        if(add_cheater(ctx, 18, 32+ret, i+1U, 0xfe) == NULL) return 4;
1027        continue;
1028      }
1029  
1030      // verify proofs
1031      const uint8_t *keyptr = msg->data;
1032      for(int k=0;k<ctr[i];k++,keyptr+=dkg_noise_key_SIZE) {
1033        TOPRF_Share share;
1034  
1035        const uint8_t complainer = *keyptr++;
1036        const uint8_t accused = msg->from;
1037  
1038        int j;
1039        for(j=0;j<ctx->complaints_len;j++) {
1040          if(complaints[j] == ((complainer<<8) | accused)) {
1041            complaints[j]=0xffff;
1042            break;
1043          }
1044        }
1045        if(j==ctx->complaints_len) {
1046          // accused revealed a key that was not complained about
1047          if(add_cheater(ctx, 18, 6, accused, complainer) == NULL) return 4;
1048          continue;
1049        }
1050  
1051        const uint8_t *msg8_ptr = (*noisy_shares)[accused-1][complainer-1];
1052        dkg_dump_msg(msg8_ptr, tpdkg_msg8_SIZE, 0);
1053        const DKG_Message *msg8 = (const DKG_Message *) msg8_ptr;
1054        uint64_t last_ts = ntohll(msg8->ts);
1055        ret = tp_recv_msg(msg8_ptr, tpdkg_msg8_SIZE, 8,
1056                       accused, complainer,
1057                       (*ctx->peer_sig_pks)[accused-1], ctx->sessionid,
1058                       ctx->ts_epsilon, &last_ts);
1059        if(0!=ret) {
1060          // key reveal msg_recv failure
1061          if(add_cheater(ctx, 18, 16+ret, accused, complainer) == NULL) return 4;
1062          continue;
1063        }
1064  #ifdef UNITTEST
1065        dump(keyptr, dkg_noise_key_SIZE, "[!] key_%d,%d", accused, complainer);
1066  #endif //UNITTEST
1067  
1068        // verify key committing hmac first!
1069  #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
1070        if(0!=crypto_auth_verify(msg8->data + noise_xk_handshake3_SIZE + sizeof(TOPRF_Share) + crypto_secretbox_xchacha20poly1305_MACBYTES,
1071                                 msg8->data + noise_xk_handshake3_SIZE,
1072                                 sizeof(TOPRF_Share) + crypto_secretbox_xchacha20poly1305_MACBYTES,
1073                                 keyptr)) {
1074          // failed to verify KC MAC on message
1075          if(add_cheater(ctx, 18, 3, accused, complainer) == NULL) return 4;
1076          continue;
1077        }
1078  #endif
1079  
1080        Noise_XK_error_code
1081          res0 = Noise_XK_aead_decrypt((uint8_t*)keyptr, 0, 0U, NULL, sizeof(share), (uint8_t*) &share, (uint8_t*) msg8->data + noise_xk_handshake3_SIZE);
1082        if (!(res0 == Noise_XK_CSuccess)) {
1083          // share decryption failure
1084          if(add_cheater(ctx, 18, 4, accused, complainer) == NULL) return 4;
1085          continue;
1086        }
1087  
1088        if(share.index != complainer) {
1089          // invalid share index
1090          TP_DKG_Cheater *cheater = add_cheater(ctx, 18, 5, accused, complainer);
1091          if(cheater == NULL) return 4;
1092          cheater->invalid_index = share.index;
1093          continue;
1094        }
1095  
1096        if(liboprf_log_file!=NULL) {
1097          fprintf(liboprf_log_file, "[!] checking proof of peer %d for complaint by peer %d\n", msg->from, share.index);
1098          dump((void*) &share, sizeof(TOPRF_Share), "[!] share_%d,%d", msg->from, share.index);
1099          dump((*ctx->commitments)[(msg->from-1) * ctx->t], ctx->t * crypto_core_ristretto255_BYTES, "[!] commitments_%d", msg->from);
1100        }
1101        ret = dkg_verify_commitment(ctx->n, ctx->t,
1102                                    share.index,
1103                                    msg->from,
1104                                    (const uint8_t (*)[crypto_core_ristretto255_BYTES]) (*ctx->commitments)[(msg->from-1) * ctx->t],
1105                                    share);
1106        switch(ret) {
1107        case 0: {
1108          // verified correctly
1109          if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;32m[!] complaint against %d by %d invalid, proof correct\x1b[0m\n", msg->from, share.index);
1110  
1111          if(add_cheater(ctx, 18, 128+ret, accused, complainer) == NULL) return 4;
1112          break;
1113        }
1114        case 1: {
1115          // confirmed corrupt
1116          if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;31m[!] complaint against %d by %d valid, proof incorrect\x1b[0m\n", msg->from, share.index);
1117          if(add_cheater(ctx, 18, 128+ret, accused, complainer) == NULL) return 4;
1118          break;
1119        }
1120        case -1: {
1121          // invalid input
1122          if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;31m[!] complaint against %d by %d, cannot be verified, invalid input\x1b[0m\n", msg->from, share.index);
1123  
1124          if(add_cheater(ctx, 18, 128+ret, accused, complainer) == NULL) return 4;
1125          break;
1126        }
1127        }
1128      }
1129    }
1130  
1131    for(int i=0;i<ctx->complaints_len;i++) {
1132      if(complaints[i] != 0xffff) {
1133        if(add_cheater(ctx, 18, 7, (uint8_t) (complaints[i] >> 8), (uint8_t) (complaints[i] & 0xff)) == NULL) return 4;
1134      }
1135    }
1136  
1137    ctx->step=99; // we skip to the end
1138  
1139    return 3;
1140  }
1141  
1142   static int peer_step19_handler(TP_DKG_PeerState *ctx, uint8_t *output, const size_t output_len) {
1143    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 19. send final transcript\x1b[0m\n", ctx->index);
1144    if(output_len != tpdkg_msg19_SIZE) return 2;
1145  
1146    DKG_Message* msg20 = (DKG_Message*) output;
1147    crypto_generichash_final(&ctx->transcript, msg20->data, crypto_generichash_BYTES);
1148    if(0!=tp_send_msg(output, tpdkg_msg19_SIZE, 20, ctx->index, 0, ctx->sig_sk, ctx->sessionid)) return 3;
1149    dkg_dump_msg(output, tpdkg_msg19_SIZE, ctx->index);
1150  
1151    return 0;
1152  }
1153  
1154  static int tp_step20_handler(TP_DKG_TPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1155    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step 20. collect and verify transcripts\x1b[0m\n");
1156  
1157    if((tpdkg_msg19_SIZE * ctx->n) != input_len) return 1;
1158    if(output_len != tpdkg_msg20_SIZE) return 2;
1159  
1160    uint8_t transcript_hash[crypto_generichash_BYTES];
1161    crypto_generichash_final(&ctx->transcript, transcript_hash, crypto_generichash_BYTES);
1162  
1163    uint8_t *wptr = ((DKG_Message *) output)->data;
1164    memcpy(wptr, "OK", 2);
1165    const uint8_t *ptr = input;
1166    for(uint8_t i=0;i<ctx->n;i++, ptr+=tpdkg_msg19_SIZE) {
1167      const DKG_Message* msg = (const DKG_Message*) ptr;
1168      dkg_dump_msg(ptr, tpdkg_msg19_SIZE, 0);
1169      int ret = tp_recv_msg(ptr, tpdkg_msg19_SIZE, 20, i+1U, 0, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
1170      if(0!=ret) {
1171        if(add_cheater(ctx, 20, 1+ret, i+1U, 0) == NULL) return 4;
1172  
1173        memcpy(wptr,"NO",2);
1174        continue;
1175      }
1176  
1177      if(sodium_memcmp(transcript_hash, msg->data, sizeof(transcript_hash))!=0) {
1178        if(liboprf_log_file!=NULL) {
1179          fprintf(liboprf_log_file,"\x1b[0;31m[!] failed to verify transcript from %d!\x1b[0m\n", i);
1180        }
1181        if(add_cheater(ctx, 20, 1, i+1U, 0) == NULL) return 4;
1182        memcpy(wptr,"NO",2);
1183      }
1184    }
1185  
1186    if(0!=tp_send_msg(output, output_len, 21, 0, 0xff, ctx->sig_sk, ctx->sessionid)) return 5;
1187    dkg_dump_msg(output, output_len, 0);
1188    if(ctx->cheater_len == 0) return 0;
1189  
1190    ctx->step = 99; // we finish here
1191    return 3;
1192  }
1193  
1194  static int peer_step21_handler(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1195    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[%d] step 21. get final approval\x1b[0m\n", ctx->index);
1196    if(input_len != tpdkg_msg20_SIZE) return 1;
1197    if(output_len != tpdkg_msg21_SIZE) return 2;
1198  
1199    // verify TP message envelope
1200    const DKG_Message* msg21 = (const DKG_Message*) input;
1201    dkg_dump_msg(input, input_len, ctx->index);
1202    int ret = tp_recv_msg(input, input_len, 21, 0, 0xff, ctx->tp_sig_pk, ctx->sessionid, ctx->ts_epsilon, &ctx->tp_last_ts);
1203    if(0!=ret) return 4+ret;
1204  
1205    int fail = (memcmp(msg21->data, "OK", 2) != 0);
1206    if(!fail) {
1207      ctx->share.index=ctx->index;
1208      if(0!=dkg_finish(ctx->n,*ctx->xshares,ctx->index,&ctx->share)) return 5;
1209  
1210      DKG_Message* msg22 = (DKG_Message*) output;
1211      memcpy(msg22->data, msg21->data, 2);
1212      if(0!=tp_send_msg(output, tpdkg_msg21_SIZE, 22, ctx->index, 0, ctx->sig_sk, ctx->sessionid)) return 3;
1213      dkg_dump_msg(output, tpdkg_msg21_SIZE, ctx->index);
1214      return 0;
1215    }
1216    return 4;
1217  }
1218  
1219  static int tp_step22_handler(TP_DKG_TPState *ctx, const uint8_t *input, const size_t input_len) {
1220    if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "\x1b[0;33m[!] step 22. collect acks from peers\x1b[0m\n");
1221  
1222    if((tpdkg_msg21_SIZE * ctx->n) != input_len) return 1;
1223  
1224    const uint8_t *ptr = input;
1225    for(uint8_t i=0;i<ctx->n;i++, ptr+=tpdkg_msg21_SIZE) {
1226      const DKG_Message* msg = (const DKG_Message*) ptr;
1227      dkg_dump_msg(ptr, tpdkg_msg21_SIZE, 0);
1228      int ret = tp_recv_msg(ptr, tpdkg_msg21_SIZE, 22, i+1U, 0, (*ctx->peer_sig_pks)[i], ctx->sessionid, ctx->ts_epsilon, &ctx->last_ts[i]);
1229      if(0!=ret) {
1230        if(add_cheater(ctx, 22, 64+ret, i+1U, 0) == NULL) return 6;
1231        continue;
1232      }
1233  
1234      if(memcmp("OK", msg->data, 2)!=0) {
1235        if(liboprf_log_file!=NULL) {
1236          fprintf(liboprf_log_file,"\x1b[0;31m[!] failed to get ack from %d!\x1b[0m\n", i);
1237        }
1238      }
1239    }
1240    if(ctx->cheater_len>0) return 5;
1241  
1242    return 0;
1243  }
1244  
1245  int tpdkg_tp_next(TP_DKG_TPState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1246    int ret = 0;
1247    switch(ctx->step) {
1248    case 0: {ret = tp_step1_handler(ctx, output, output_len); break;}
1249    case 1: {ret = tp_step4_handler(ctx, input, input_len, output, output_len); break;}
1250    case 2: {ret = tp_step68_handler(ctx, input, input_len, output, output_len); break;}
1251    case 3: {ret = tp_step68_handler(ctx, input, input_len, output, output_len); break;}
1252    case 4: {ret = tp_step12_handler(ctx, input, input_len, output, output_len); break;}
1253    case 5: {ret = tp_step14_handler(ctx, input, input_len, output, output_len); break;}
1254    case 6: {
1255      ret = tp_step16_handler(ctx, input, input_len, output, output_len);
1256      ctx->prev = ctx->step;
1257      if(ctx->complaints_len == 0) {
1258        // we skip over to step 21
1259        ctx->step++;
1260      }
1261      ctx->step++;
1262      return ret;
1263    }
1264    case 7: {ret = tp_step18_handler(ctx, input, input_len); break;}
1265    case 8: {ret = tp_step20_handler(ctx, input, input_len, output, output_len); break;}
1266    case 9: {ret = tp_step22_handler(ctx, input, input_len); break;}
1267    default: {
1268      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[!] invalid step\n");
1269      return 99;
1270    }
1271    }
1272    ctx->prev=ctx->step++;
1273    if(ret!=0) ctx->step=99; // so that not_done reports done
1274    return ret;
1275  }
1276  
1277  int tpdkg_peer_next(TP_DKG_PeerState *ctx, const uint8_t *input, const size_t input_len, uint8_t *output, const size_t output_len) {
1278    int ret=0;
1279    switch(ctx->step) {
1280    case 0: {ret = peer_step23_handler(ctx, input, input_len, output, output_len); break;}
1281    case 1: {ret = peer_step5_handler(ctx, input, input_len, output, output_len); break;}
1282    case 2: {ret = peer_step7_handler(ctx, input, input_len, output, output_len); break;}
1283    case 3: {ret = peer_step911_handler(ctx, input, input_len, output, output_len); break;}
1284    case 4: {ret = peer_step13_handler(ctx, input, input_len, output, output_len); break;}
1285    case 5: {ret = peer_step15_handler(ctx, input, input_len, output, output_len); break;}
1286    case 6: {ret = peer_step17_handler(ctx, input, input_len); break;}
1287    case 7: {ret = peer_step17a_handler(ctx, output, output_len); break;}
1288    case 8: {ret = peer_step19_handler(ctx, output, output_len); break;}
1289    case 9: {ret = peer_step21_handler(ctx, input, input_len, output, output_len); break;}
1290    case 10: {
1291      // we are done
1292      ret = 0;
1293      break;
1294    }
1295    default: {
1296      if(liboprf_log_file!=NULL) fprintf(liboprf_log_file, "[%d] invalid step\n", ctx->index);
1297      ret = 99;
1298    }
1299    }
1300    ctx->prev=ctx->step++;
1301    if(ret!=0) ctx->step=99; // so that not_done reports done
1302    return ret;
1303  }
1304  
1305  uint8_t tpdkg_cheater_msg(const TP_DKG_Cheater *c, char *out, const size_t outlen) {
1306    if(c->error>65 && c->error<=70) {
1307        snprintf(out, outlen, "step %d message from peer %d for peer %d could not be validated: %s",
1308                 c->step, c->peer, c->other_peer, dkg_recv_err(c->error & 0x3f));
1309        return c->peer;
1310    }
1311    if(c->step==16) {
1312      if(c->error == 6) {
1313        snprintf(out, outlen, "more than t^2 complaints, most peers are cheating.");
1314        return 0;
1315      } else if(c->error == 7) {
1316        snprintf(out, outlen, "peer %d sent complaint about invalid peer %d.", c->peer, c->other_peer);
1317        return c->peer;
1318      } else if(c->error == 8) {
1319        snprintf(out, outlen, "peer %d sent a duplicate complaint about peer %d.", c->peer, c->other_peer);
1320        return c->peer;
1321      }
1322      snprintf(out,outlen, "invalid error code for step 16: %d", c->error);
1323      return 0;
1324    } else if(c->step==18) {
1325      if(c->error & 16) {
1326        snprintf(out, outlen, "message containing encrypted share from peer %d for peer %d could not be validated: %s",
1327                 c->peer, c->other_peer, dkg_recv_err(c->error & 0xf));
1328        return c->peer;
1329      } else if (c->error & 32) {
1330        snprintf(out, outlen, "message revealing key encrypting share from peer %d for peer %d could not be validated: %s",
1331                 c->peer, c->other_peer, dkg_recv_err(c->error & 0x1f));
1332        return c->peer;
1333      }
1334      switch(c->error) {
1335      case 3: {
1336        snprintf(out,outlen, "accused peer %d revealed a key (for peer %d) that was not complained about", c->peer, c->other_peer);
1337        return c->peer;
1338      }
1339      case 4: {
1340        snprintf(out,outlen, "verification of hmac of message from accused peer %d to complaining peer %d failed", c->peer, c->other_peer);
1341        return c->peer;
1342      }
1343      case 5: {
1344        snprintf(out,outlen, "accused peer %d sent an invalid share with index %d to complaining peer %d", c->peer, c->other_peer, c->invalid_index);
1345        return c->peer;
1346      }
1347      case 6: {
1348        snprintf(out,outlen, "accused peer %d revealed a key for happy peer %d", c->peer, c->other_peer);
1349        return c->peer;
1350      }
1351      case 7: {
1352        snprintf(out,outlen, "accused peer %d complained by peer %d was not verified", c->peer, c->other_peer);
1353        return c->peer;
1354      }
1355      case 127: {
1356        snprintf(out,outlen, "accused peer %d provided invalid parameters to complaint from peer %d", c->peer, c->other_peer);
1357        return c->peer;
1358      }
1359      case 128: {
1360        snprintf(out,outlen, "peer %d was falsely accused by peer %d", c->peer, c->other_peer);
1361        return c->other_peer;
1362      }
1363      case 129: {
1364        snprintf(out,outlen, "accused peer %d was caught cheating by peer %d", c->peer, c->other_peer);
1365        return c->peer;
1366      }
1367      default: {
1368        snprintf(out,outlen, "invalid error code for step 18: %d", c->error);
1369        return 0;
1370      }
1371      }
1372    } else if(c->step==20) {
1373      if(c->error == 1) {
1374        snprintf(out,outlen, "transcript mismatch peer %d", c->peer);
1375        return c->peer;
1376      }
1377      snprintf(out,outlen, "invalid error code for step 20: %d", c->error);
1378      return 0;
1379    }
1380    snprintf(out,outlen, "invalid step %d", c->step);
1381    return 0;
1382  }