tp-dkg.c
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include "utils.h" 5 #include "toprf.h" 6 #include "tp-dkg.h" 7 #include "dkg.h" 8 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 9 #include <unistd.h> 10 #endif 11 12 #ifdef __AFL_FUZZ_INIT 13 __AFL_FUZZ_INIT(); 14 #endif 15 16 typedef struct { 17 uint8_t index; 18 uint8_t value[crypto_core_ristretto255_BYTES]; 19 } __attribute((packed)) TOPRF_Part; 20 21 static void topart(TOPRF_Part *r, const TOPRF_Share *s) { 22 r->index=s->index; 23 crypto_scalarmult_ristretto255_base(r->value, s->value); 24 } 25 26 static void shuffle(uint8_t *array, const size_t n) { 27 if (n < 2) return; 28 srand((unsigned) time(NULL)); 29 for(unsigned i=0; i<n-1; i++) { 30 size_t j = i + (unsigned)rand() / ((unsigned)RAND_MAX / (n - i) + 1U); 31 uint8_t t = array[j]; 32 array[j] = array[i]; 33 array[i] = t; 34 } 35 } 36 37 static int verify_shares(const uint8_t n, const TOPRF_Share shares[n], const uint8_t t) { 38 uint8_t responses[t][sizeof(TOPRF_Part)]; 39 uint8_t v0[crypto_scalarmult_ristretto255_BYTES]={0}; 40 41 uint8_t indexes[n]; 42 for(uint8_t i=0;i<n;i++) indexes[i]=i; 43 if(liboprf_log_file!=NULL) { 44 fprintf(stderr, "order: "); 45 for(int i=0;i<t;i++) fprintf(stderr, "%2d, ",indexes[i]); 46 } 47 48 for(int i=0;i<t;i++) { 49 topart((TOPRF_Part *) responses[i], &shares[indexes[i]]); 50 } 51 if(toprf_thresholdmult(t, responses, v0)) return 1; 52 dump(v0,sizeof v0, "v0\t"); 53 54 for(int k=0;k<t-1;k++) { 55 uint8_t v1[crypto_scalarmult_ristretto255_BYTES]={0}; 56 shuffle(indexes,n); 57 if(liboprf_log_file!=NULL) { 58 fprintf(stderr, "order: "); 59 for(int i=0;i<t;i++) fprintf(stderr, "%2d, ",indexes[i]); 60 } 61 62 for(int i=0;i<t;i++) { 63 topart((TOPRF_Part *) responses[i], &shares[indexes[i]]); 64 } 65 66 if(toprf_thresholdmult(t, responses, v1)) return 1; 67 dump(v1,sizeof v1, "v%d\t", k+1); 68 69 if(memcmp(v0,v1,sizeof v1)!=0) { 70 fprintf(stderr,"\e[0;31mfailed to verify shares from dkg_finish!\e[0m\n"); 71 return 1; 72 } 73 } 74 return 0; 75 } 76 77 // simulate network 78 #define NETWORK_BUF_SIZE (1024*1024*16) 79 //static size_t _send(uint8_t *net, size_t *pkt_len, const uint8_t *msg, const size_t msg_len) { 80 static void _send(uint8_t *net, size_t *pkt_len, const uint8_t *msg, const size_t msg_len) { 81 if(*pkt_len+msg_len >= NETWORK_BUF_SIZE || msg_len==0 || msg == NULL) { 82 return;// 0; 83 } 84 memcpy(net+*pkt_len, msg, msg_len); 85 *pkt_len+=msg_len; 86 //return msg_len; 87 } 88 //static size_t _recv(const uint8_t *net, size_t *pkt_len, uint8_t *buf, const size_t msg_len) { 89 static void _recv(const uint8_t *net, size_t *pkt_len, uint8_t *buf, const size_t msg_len) { 90 if(*pkt_len < msg_len || msg_len == 0) { 91 return; // 0; 92 } 93 memcpy(buf, net, msg_len); 94 *pkt_len-=msg_len; 95 //return msg_len; 96 } 97 98 #ifdef FUZZ_DUMP 99 #if !defined(FUZZ_PEER) 100 static void fuzz_dump(const uint8_t step, TP_DKG_TPState *ctx, const uint8_t *buf_in, const size_t buf_in_size, const char **argv, const int argc) { 101 #else 102 static void fuzz_dump(const uint8_t step, TP_DKG_PeerState *ctx, const uint8_t *buf_in, const size_t buf_in_size, const char **argv, const int argc) { 103 #endif //!defined(FUZZ_PEER) 104 if(argc<5) { 105 fprintf(stderr, "error incorrect number of params, run as: %% %s <n> <t> <step> <output-file>\n", argv[0]); 106 exit(1); 107 } 108 if(ctx->step==step) { 109 FILE *tc = fopen(argv[4], "wb"); 110 fwrite(buf_in, 1, buf_in_size, tc); 111 fclose(tc); 112 exit(0); 113 } 114 } 115 #endif 116 117 #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) 118 #if !defined(FUZZ_PEER) 119 static int fuzz_loop(const uint8_t step, TP_DKG_TPState *tp, TP_DKG_PeerState *peers, uint8_t network_buf[][NETWORK_BUF_SIZE],size_t pkt_len[]) { 120 if(tp->step!=step) return 0; 121 122 TP_DKG_TPState checkpoint; 123 memcpy(&checkpoint, tp, sizeof(checkpoint)); 124 TP_DKG_PeerState pcheckpoints[tp->n]; 125 memcpy(&pcheckpoints, peers, sizeof(pcheckpoints)); 126 127 #ifdef __AFL_HAVE_MANUAL_CONTROL 128 __AFL_INIT(); 129 #endif 130 unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; // must be after __AFL_INIT 131 // and before __AFL_LOOP! 132 133 while (__AFL_LOOP(10000)) { 134 135 int len = __AFL_FUZZ_TESTCASE_LEN; // don't use the macro directly in a call! 136 if (len < sizeof(DKG_Message)) continue; // check for a required/useful minimum input length 137 138 // doing vla - but avoiding 0 sized ones is ugly 139 const size_t tp_out_size = tpdkg_tp_output_size(tp); 140 uint8_t tp_out_buf[tp_out_size==0?1:tp_out_size], *tp_out; 141 if(tp_out_size==0) tp_out = NULL; 142 else tp_out = tp_out_buf; 143 144 /* Setup function call, e.g. struct target *tmp = libtarget_init() */ 145 /* Call function to be fuzzed, e.g.: */ 146 int ret = tpdkg_tp_next(tp, buf, len, tp_out, tp_out_size); 147 if(0!=ret) { 148 // clean up peers 149 for(uint8_t i=0;i<tp->n;i++) tpdkg_peer_free(&peers[i]); 150 if(tp->cheater_len > 0) return 125; 151 return ret; 152 } 153 154 while(tpdkg_tp_not_done(tp)) { 155 for(uint8_t i=0;i<tp->n;i++) { 156 const uint8_t *msg; 157 size_t len; 158 if(0!=tpdkg_tp_peer_msg(tp, tp_out, tp_out_size, i, &msg, &len)) { 159 return 1; 160 } 161 _send(network_buf[i+1], &pkt_len[i+1], msg, len); 162 } 163 164 while(pkt_len[0]==0 && tpdkg_peer_not_done(&peers[1])) { 165 for(uint8_t i=0;i<tp->n;i++) { 166 // 0sized vla meh 167 const size_t peer_out_size = tpdkg_peer_output_size(&peers[i]); 168 uint8_t peers_out_buf[peer_out_size==0?1:peer_out_size], *peers_out; 169 if(peer_out_size==0) peers_out = NULL; 170 else peers_out = peers_out_buf; 171 172 // 0sized vla meh for the last time.. 173 const size_t peer_in_size = tpdkg_peer_input_size(&peers[i]); 174 uint8_t peer_in_buf[peer_in_size==0?1:peer_in_size], *peer_in; 175 if(peer_in_size==0) peer_in = NULL; 176 else peer_in = peer_in_buf; 177 178 _recv(network_buf[i+1], &pkt_len[i+1], peer_in, peer_in_size); 179 ret = tpdkg_peer_next(&peers[i], 180 peer_in, peer_in_size, 181 peers_out, peer_out_size); 182 183 if(0!=ret) { 184 // clean up peers 185 for(uint8_t i=0;i<tp->n;i++) tpdkg_peer_free(&peers[i]); 186 return ret; 187 } 188 189 _send(network_buf[0], &pkt_len[0], peers_out, peer_out_size); 190 } 191 } 192 193 // doing vla - but avoiding 0 sized ones is ugly 194 const size_t tp_out_size = tpdkg_tp_output_size(tp); 195 uint8_t tp_out_buf[tp_out_size==0?1:tp_out_size], *tp_out; 196 if(tp_out_size==0) tp_out = NULL; 197 else tp_out = tp_out_buf; 198 199 // avoiding zero-sized vla is still ugly 200 const size_t tp_in_size = tpdkg_tp_input_size(tp); 201 uint8_t tp_in_buf[tp_in_size==0?1:tp_in_size], *tp_in; 202 if(tp_in_size==0) tp_in = NULL; 203 else tp_in = tp_in_buf; 204 205 _recv(network_buf[0], &pkt_len[0], tp_in, tp_in_size); 206 207 ret = tpdkg_tp_next(tp, tp_in, tp_in_size, tp_out, tp_out_size); 208 if(0!=ret) { 209 // clean up peers 210 for(uint8_t i=0;i<tp->n;i++) tpdkg_peer_free(&peers[i]); 211 if(tp->cheater_len > 0) return 55; 212 return ret; 213 } 214 } 215 216 /* Reset state. e.g. libtarget_free(tmp) */ 217 memcpy(tp, &checkpoint, sizeof(TP_DKG_TPState)); 218 memcpy(peers, &pcheckpoints, sizeof(pcheckpoints)); 219 } 220 return 0; 221 } 222 #else // !defined(FUZZ_PEER) 223 static int fuzz_loop(const uint8_t step, TP_DKG_TPState *tp, TP_DKG_PeerState *peers, uint8_t network_buf[][NETWORK_BUF_SIZE],size_t pkt_len[]) { 224 if(peers[0].step!=step) return 0; 225 226 TP_DKG_TPState checkpoint; 227 memcpy(&checkpoint, tp, sizeof(checkpoint)); 228 TP_DKG_PeerState pcheckpoints[tp->n]; 229 memcpy(&pcheckpoints, peers, sizeof(pcheckpoints)); 230 231 #ifdef __AFL_HAVE_MANUAL_CONTROL 232 __AFL_INIT(); 233 #endif 234 unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF; // must be after __AFL_INIT 235 // and before __AFL_LOOP! 236 237 int ret; 238 while (__AFL_LOOP(10000)) { 239 240 int len = __AFL_FUZZ_TESTCASE_LEN; // don't use the macro directly in a call! 241 if (len < sizeof(DKG_Message)) continue; // check for a required/useful minimum input length 242 243 // doing vla - but avoiding 0 sized ones is ugly 244 const size_t peer_out_size = tpdkg_peer_output_size(&peers[0]); 245 uint8_t peer_out_buf[peer_out_size==0?1:peer_out_size], *peer_out; 246 if(peer_out_size==0) peer_out = NULL; 247 else peer_out = peer_out_buf; 248 249 ret = tpdkg_peer_next(&peers[0], buf, len, peer_out, peer_out_size); 250 if(ret!=0) { 251 //for(uint8_t i=0;i<tp->n;i++) tpdkg_peer_free(&peers[i]); 252 return ret; 253 } 254 _send(network_buf[0], &pkt_len[0], peer_out, peer_out_size); 255 256 for(uint8_t i=1;i<tp->n;i++) { 257 // 0sized vla meh 258 const size_t peer_out_size = tpdkg_peer_output_size(&peers[i]); 259 uint8_t peers_out_buf[peer_out_size==0?1:peer_out_size], *peers_out; 260 if(peer_out_size==0) peers_out = NULL; 261 else peers_out = peers_out_buf; 262 263 // 0sized vla meh for the last time.. 264 const size_t peer_in_size = tpdkg_peer_input_size(&peers[i]); 265 uint8_t peer_in_buf[peer_in_size==0?1:peer_in_size], *peer_in; 266 if(peer_in_size==0) peer_in = NULL; 267 else peer_in = peer_in_buf; 268 269 _recv(network_buf[i+1], &pkt_len[i+1], peer_in, peer_in_size); 270 ret = tpdkg_peer_next(&peers[i], 271 peer_in, peer_in_size, 272 peers_out, peer_out_size); 273 274 if(0!=ret) { 275 // clean up peers 276 //for(uint8_t i=0;i<tp->n;i++) tpdkg_peer_free(&peers[i]); 277 return ret; 278 } 279 _send(network_buf[0], &pkt_len[0], peers_out, peer_out_size); 280 } 281 282 while(tpdkg_tp_not_done(tp)) { 283 while(pkt_len[0]==0 && tpdkg_peer_not_done(&peers[1])) { 284 for(uint8_t i=0;i<tp->n;i++) { 285 // 0sized vla meh 286 const size_t peer_out_size = tpdkg_peer_output_size(&peers[i]); 287 uint8_t peers_out_buf[peer_out_size==0?1:peer_out_size], *peers_out; 288 if(peer_out_size==0) peers_out = NULL; 289 else peers_out = peers_out_buf; 290 291 // 0sized vla meh for the last time.. 292 const size_t peer_in_size = tpdkg_peer_input_size(&peers[i]); 293 uint8_t peer_in_buf[peer_in_size==0?1:peer_in_size], *peer_in; 294 if(peer_in_size==0) peer_in = NULL; 295 else peer_in = peer_in_buf; 296 297 _recv(network_buf[i+1], &pkt_len[i+1], peer_in, peer_in_size); 298 ret = tpdkg_peer_next(&peers[i], 299 peer_in, peer_in_size, 300 peers_out, peer_out_size); 301 302 if(0!=ret) { 303 // clean up peers 304 //for(uint8_t i=0;i<tp->n;i++) tpdkg_peer_free(&peers[i]); 305 return ret; 306 } 307 308 _send(network_buf[0], &pkt_len[0], peers_out, peer_out_size); 309 } 310 } 311 312 // doing vla - but avoiding 0 sized ones is ugly 313 const size_t tp_out_size = tpdkg_tp_output_size(tp); 314 uint8_t tp_out_buf[tp_out_size==0?1:tp_out_size], *tp_out; 315 if(tp_out_size==0) tp_out = NULL; 316 else tp_out = tp_out_buf; 317 318 // avoiding zero-sized vla is still ugly 319 const size_t tp_in_size = tpdkg_tp_input_size(tp); 320 uint8_t tp_in_buf[tp_in_size==0?1:tp_in_size], *tp_in; 321 if(tp_in_size==0) tp_in = NULL; 322 else tp_in = tp_in_buf; 323 324 _recv(network_buf[0], &pkt_len[0], tp_in, tp_in_size); 325 326 ret = tpdkg_tp_next(tp, tp_in, tp_in_size, tp_out, tp_out_size); 327 if(0!=ret) { 328 // clean up peers 329 for(uint8_t i=0;i<tp->n;i++) tpdkg_peer_free(&peers[i]); 330 if(tp->cheater_len > 0) return 55; 331 return ret; 332 } 333 334 for(uint8_t i=0;i<tp->n;i++) { 335 const uint8_t *msg; 336 size_t len; 337 if(0!=tpdkg_tp_peer_msg(tp, tp_out, tp_out_size, i, &msg, &len)) { 338 return 1; 339 } 340 _send(network_buf[i+1], &pkt_len[i+1], msg, len); 341 } 342 } 343 344 /* Reset state. e.g. libtarget_free(tmp) */ 345 memcpy(tp, &checkpoint, sizeof(TP_DKG_TPState)); 346 memcpy(peers, &pcheckpoints, sizeof(pcheckpoints)); 347 } 348 return 0; 349 } 350 #endif 351 #endif 352 353 int main(const int argc, const char **argv) { 354 int ret; 355 // enable logging 356 liboprf_log_file = stderr; 357 liboprf_debug = 1; 358 359 if(argc<3) { 360 #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(FUZZ_DUMP) 361 fprintf(stderr, "error incorrect numbers of parameters, run as: %% %s <n> <t> [<step> [<path>]]\n", argv[0]); 362 #else 363 fprintf(stderr, "error incorrect numbers of parameters, run as: %% %s <n> <t>\n", argv[0]); 364 #endif // defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(FUZZ_DUMP) 365 exit(1); 366 } 367 uint8_t n=(uint8_t)atoi(argv[1]),t=(uint8_t)atoi(argv[2]); 368 #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) || defined(FUZZ_DUMP) 369 uint8_t step=atoi(argv[3]); 370 #ifdef FUZZ_PEER 371 if(step<1 || step > 9 || step==7 || step==8) { 372 #else 373 if(step<1 || step > 9) { 374 #endif 375 fprintf(stderr, "error incorrect value for step must be 1-9 (but not 7 or 8), run as: %% %s <1-7> <output-file>\n", argv[0]); 376 exit(1); 377 } 378 #endif 379 380 // mock long-term peer keys 381 // all known by TP 382 uint8_t peer_lt_pks[n][crypto_sign_PUBLICKEYBYTES]; 383 // only known by corresponding peer 384 uint8_t peer_lt_sks[n][crypto_sign_SECRETKEYBYTES]; 385 for(uint8_t i=0;i<n;i++) { 386 crypto_sign_keypair(peer_lt_pks[i], peer_lt_sks[i]); 387 } 388 389 TP_DKG_TPState tp; 390 uint8_t msg0[tpdkg_msg0_SIZE]; 391 ret = tpdkg_start_tp(&tp, dkg_freshness_TIMEOUT, n, t, "proto test", 10, sizeof msg0, (DKG_Message*) msg0); 392 if(0!=ret) return ret; 393 394 fprintf(stderr, "allocating memory for TP\n"); 395 // set bufs 396 // we need to store these outside of the ctx, since they are 397 // variable size, and the struct can only handle one variable size 398 // entry... 399 uint8_t tp_peers_sig_pks[n][crypto_sign_PUBLICKEYBYTES]; 400 memset(tp_peers_sig_pks,0,sizeof(tp_peers_sig_pks)); 401 // tp needs to store the commitments 402 uint8_t tp_commitments[n*t][crypto_core_ristretto255_BYTES]; 403 memset(tp_commitments,0,sizeof(tp_commitments)); 404 // tp needs to store the complaints, with max n==128 this takes max 16KB of ram. 405 uint16_t tp_complaints[n*n]; 406 memset(tp_complaints,0,sizeof(tp_complaints)); 407 uint8_t noisy_shares[n*n][tpdkg_msg8_SIZE]; 408 memset(noisy_shares,0,sizeof(noisy_shares)); 409 TP_DKG_Cheater cheaters[t*t - 1]; 410 memset(cheaters,0,sizeof(cheaters)); 411 uint64_t last_ts[n]; 412 tpdkg_tp_set_bufs(&tp, &tp_commitments, &tp_complaints, &noisy_shares, &cheaters, sizeof(cheaters) / sizeof(TP_DKG_Cheater), &tp_peers_sig_pks, &peer_lt_pks, last_ts); 413 414 // only tp_out can survive for the peers in local scope of the "main protocol loop" 415 // and thus we simulate a network with this buffer 416 417 TP_DKG_PeerState peers[n]; 418 for(uint8_t i=0;i<n;i++) { 419 ret = tpdkg_start_peer(&peers[i], dkg_freshness_TIMEOUT, peer_lt_sks[i], (DKG_Message*) msg0); 420 if(0!=ret) return ret; 421 } 422 423 fprintf(stderr, "allocating memory for peers .."); 424 // now that the peer(s) know the value of N, we can allocate buffers 425 // to hold all the sig&noise keys, noise sessions, temp shares, commitments 426 uint8_t peers_sig_pks[peers[1].n][crypto_sign_PUBLICKEYBYTES]; 427 memset(peers_sig_pks, 0, sizeof(peers_sig_pks)); 428 uint8_t peers_noise_pks[peers[1].n][crypto_scalarmult_BYTES]; 429 Noise_XK_session_t *noise_outs[n][n]; 430 memset(noise_outs, 0, sizeof noise_outs); 431 Noise_XK_session_t *noise_ins[n][n]; 432 memset(noise_ins, 0, sizeof noise_ins); 433 TOPRF_Share ishares[peers[1].n][peers[1].n]; 434 memset(ishares, 0, sizeof ishares); 435 TOPRF_Share xshares[peers[1].n][peers[1].n]; 436 memset(xshares, 0, sizeof xshares); 437 uint8_t commitments[peers[1].n][peers[1].n *peers[1].t][crypto_core_ristretto255_BYTES]; 438 memset(commitments, 0, sizeof commitments); 439 uint16_t peer_complaints[peers[1].n][peers[1].n*peers[1].n]; 440 memset(peer_complaints, 0, sizeof peer_complaints); 441 uint8_t peer_my_complaints[peers[1].n][peers[1].n]; 442 memset(peer_my_complaints, 0, sizeof peer_my_complaints); 443 uint64_t peer_last_ts[n][n]; 444 memset(peer_last_ts, 0, sizeof peer_last_ts); 445 fprintf(stderr, "done\n"); 446 447 for(uint8_t i=0;i<n;i++) { 448 // in a real deployment peers do not share the same pks buffers 449 tpdkg_peer_set_bufs(&peers[i], &peers_sig_pks, &peers_noise_pks, 450 &noise_outs[i], &noise_ins[i], 451 &ishares[i], &xshares[i], 452 &commitments[i], 453 peer_complaints[i], peer_my_complaints[i], 454 peer_last_ts[i]); 455 } 456 457 458 // simulate network. 459 uint8_t network_buf[n+1][NETWORK_BUF_SIZE]; 460 size_t pkt_len[n+1]; 461 memset(pkt_len,0,sizeof pkt_len); 462 463 // this is the mainloop - normally only one tp or one peer, but here 464 // for demo purposes mixed. 465 // end condition for peers is tpdkg_peer_not_done(&peer) 466 while(tpdkg_tp_not_done(&tp)) { 467 468 // doing vla - but avoiding 0 sized ones is ugly 469 const size_t tp_out_size = tpdkg_tp_output_size(&tp); 470 uint8_t tp_out_buf[tp_out_size==0?1:tp_out_size], *tp_out; 471 if(tp_out_size==0) tp_out = NULL; 472 else tp_out = tp_out_buf; 473 474 // avoiding zero-sized vla is still ugly 475 const size_t tp_in_size = tpdkg_tp_input_size(&tp); 476 uint8_t tp_in_buf[tp_in_size==0?1:tp_in_size], *tp_in; 477 if(tp_in_size==0) tp_in = NULL; 478 else tp_in = tp_in_buf; 479 480 _recv(network_buf[0], &pkt_len[0], tp_in, tp_in_size); 481 482 #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && !defined(FUZZ_PEER) 483 ret = fuzz_loop(step, &tp, peers, network_buf, pkt_len); 484 if(0!=ret) return ret; 485 #endif 486 #if defined(FUZZ_DUMP) && !defined(FUZZ_PEER) 487 fuzz_dump(step, &tp, tp_in, tp_in_size, argv, argc); 488 #endif 489 490 ret = tpdkg_tp_next(&tp, tp_in, tp_in_size, tp_out, tp_out_size); 491 if(0!=ret) { 492 // clean up peers 493 for(uint8_t i=0;i<n;i++) tpdkg_peer_free(&peers[i]); 494 if(tp.cheater_len > 0) break; 495 return ret; 496 } 497 498 for(uint8_t i=0;i<tp.n;i++) { 499 const uint8_t *msg; 500 size_t len; 501 if(0!=tpdkg_tp_peer_msg(&tp, tp_out, tp_out_size, i, &msg, &len)) { 502 return 1; 503 } 504 _send(network_buf[i+1], &pkt_len[i+1], msg, len); 505 } 506 507 while(pkt_len[0]==0 && tpdkg_peer_not_done(&peers[1])) { 508 for(uint8_t i=0;i<n;i++) { 509 // 0sized vla meh 510 const size_t peer_out_size = tpdkg_peer_output_size(&peers[i]); 511 uint8_t peers_out_buf[peer_out_size==0?1:peer_out_size], *peers_out; 512 if(peer_out_size==0) peers_out = NULL; 513 else peers_out = peers_out_buf; 514 515 // 0sized vla meh for the last time.. 516 const size_t peer_in_size = tpdkg_peer_input_size(&peers[i]); 517 uint8_t peer_in_buf[peer_in_size==0?1:peer_in_size], *peer_in; 518 if(peer_in_size==0) peer_in = NULL; 519 else peer_in = peer_in_buf; 520 521 _recv(network_buf[i+1], &pkt_len[i+1], peer_in, peer_in_size); 522 523 #if defined(FUZZ_DUMP) && defined(FUZZ_PEER) 524 if(i==0) fuzz_dump(step, &peers[i], peer_in, peer_in_size, argv, argc); 525 #endif 526 #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZ_PEER) 527 ret = fuzz_loop(step, &tp, peers, network_buf, pkt_len); 528 if(0!=ret) return ret; 529 #endif 530 ret = tpdkg_peer_next(&peers[i], 531 peer_in, peer_in_size, 532 peers_out, peer_out_size); 533 534 if(0!=ret) { 535 // clean up peers 536 for(uint8_t i=0;i<n;i++) tpdkg_peer_free(&peers[i]); 537 return ret; 538 } 539 540 _send(network_buf[0], &pkt_len[0], peers_out, peer_out_size); 541 } 542 } 543 } 544 545 // we are done. let's check the shares... 546 TOPRF_Share shares[n]; 547 if(tp.cheater_len == 0) { 548 for(uint8_t i=0;i<n;i++) { 549 memcpy(&shares[i], (uint8_t*) &peers[i].share, sizeof(TOPRF_Share)); 550 dump((uint8_t*) &shares[i], sizeof(TOPRF_Share), "share[%d]", i+1); 551 } 552 553 if(0!=verify_shares(n, shares, t)) { 554 fprintf(stderr, "verify_shares failed\n"); 555 return 1; 556 } 557 } else { 558 int total_cheaters=0; 559 uint8_t tmp[n+1]; 560 memset(tmp,0,n+1); 561 for(int i=0;i<tp.cheater_len;i++) { 562 char err[dkg_max_err_SIZE]; 563 uint8_t p = tpdkg_cheater_msg(&(*tp.cheaters)[i], err, sizeof(err)); 564 fprintf(stderr,"\e[0;31m%s\e[0m\n", err); 565 if(p > n) return 1; 566 if(tmp[p]==0) total_cheaters++; 567 tmp[p]++; 568 } 569 fprintf(stderr, "\e[0;31m:/ dkg failed, total cheaters %d, list of cheaters:", total_cheaters); 570 for(int i=1;i<=n;i++) { 571 if(tmp[i]==0) continue; 572 fprintf(stderr," %d(%d)", i, tmp[i]); 573 } 574 fprintf(stderr, "\e[0m\n"); 575 return 1; 576 } 577 578 // clean up peers 579 for(uint8_t i=0;i<n;i++) tpdkg_peer_free(&peers[i]); 580 581 fprintf(stderr, "\e[0;32meverything correct!\e[0m\n"); 582 return 0; 583 }