test_helper_rsa.c (30893B)
1 /* 2 This file is part of TALER 3 (C) 2020, 2021, 2022 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file util/test_helper_rsa.c 18 * @brief Tests for RSA crypto helper 19 * @author Christian Grothoff 20 */ 21 #include "platform.h" 22 #include "taler/taler_util.h" 23 24 /** 25 * Configuration has 1 minute duration and 5 minutes lookahead, but 26 * we do not get 'revocations' for expired keys. So this must be 27 * large enough to deal with key rotation during the runtime of 28 * the benchmark. 29 */ 30 #define MAX_KEYS 1024 31 32 /** 33 * How many random key revocations should we test? 34 */ 35 #define NUM_REVOKES 3 36 37 /** 38 * How many iterations of the successful signing test should we run? 39 */ 40 #define NUM_SIGN_TESTS 5 41 42 /** 43 * How many iterations of the successful signing test should we run 44 * during the benchmark phase? 45 */ 46 #define NUM_SIGN_PERFS 100 47 48 /** 49 * How many parallel clients should we use for the parallel 50 * benchmark? (> 500 may cause problems with the max open FD number limit). 51 */ 52 #define NUM_CORES 8 53 54 /** 55 * Number of keys currently in #keys. 56 */ 57 static unsigned int num_keys; 58 59 /** 60 * Keys currently managed by the helper. 61 */ 62 struct KeyData 63 { 64 /** 65 * Validity start point. 66 */ 67 struct GNUNET_TIME_Timestamp start_time; 68 69 /** 70 * Key expires for signing at @e start_time plus this value. 71 */ 72 struct GNUNET_TIME_Relative validity_duration; 73 74 /** 75 * Hash of the public key. 76 */ 77 struct TALER_RsaPubHashP h_rsa; 78 79 /** 80 * Full public key. 81 */ 82 struct TALER_DenominationPublicKey denom_pub; 83 84 /** 85 * Is this key currently valid? 86 */ 87 bool valid; 88 89 /** 90 * Did the test driver revoke this key? 91 */ 92 bool revoked; 93 }; 94 95 /** 96 * Array of all the keys we got from the helper. 97 */ 98 static struct KeyData keys[MAX_KEYS]; 99 100 101 /** 102 * Release memory occupied by #keys. 103 */ 104 static void 105 free_keys (void) 106 { 107 for (unsigned int i = 0; i<MAX_KEYS; i++) 108 if (keys[i].valid) 109 { 110 TALER_denom_pub_free (&keys[i].denom_pub); 111 keys[i].valid = false; 112 GNUNET_assert (num_keys > 0); 113 num_keys--; 114 } 115 } 116 117 118 /** 119 * Function called with information about available keys for signing. Usually 120 * only called once per key upon connect. Also called again in case a key is 121 * being revoked, in that case with an @a end_time of zero. Stores the keys 122 * status in #keys. 123 * 124 * @param cls closure, NULL 125 * @param section_name name of the denomination type in the configuration; 126 * NULL if the key has been revoked or purged 127 * @param start_time when does the key become available for signing; 128 * zero if the key has been revoked or purged 129 * @param validity_duration how long does the key remain available for signing; 130 * zero if the key has been revoked or purged 131 * @param h_rsa hash of the @a denom_pub that is available (or was purged) 132 * @param bs_pub the public key itself, NULL if the key was revoked or purged 133 * @param sm_pub public key of the security module, NULL if the key was revoked or purged 134 * @param sm_sig signature from the security module, NULL if the key was revoked or purged 135 * The signature was already verified against @a sm_pub. 136 */ 137 static void 138 key_cb (void *cls, 139 const char *section_name, 140 struct GNUNET_TIME_Timestamp start_time, 141 struct GNUNET_TIME_Relative validity_duration, 142 const struct TALER_RsaPubHashP *h_rsa, 143 struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub, 144 const struct TALER_SecurityModulePublicKeyP *sm_pub, 145 const struct TALER_SecurityModuleSignatureP *sm_sig) 146 { 147 (void) cls; 148 (void) sm_pub; 149 (void) sm_sig; 150 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 151 "Key notification about key %s in `%s'\n", 152 GNUNET_h2s (&h_rsa->hash), 153 section_name); 154 if (0 == validity_duration.rel_value_us) 155 { 156 bool found = false; 157 158 GNUNET_break (NULL == bs_pub); 159 GNUNET_break (NULL == section_name); 160 for (unsigned int i = 0; i<MAX_KEYS; i++) 161 if (0 == GNUNET_memcmp (h_rsa, 162 &keys[i].h_rsa)) 163 { 164 keys[i].valid = false; 165 keys[i].revoked = false; 166 TALER_denom_pub_free (&keys[i].denom_pub); 167 GNUNET_assert (num_keys > 0); 168 num_keys--; 169 found = true; 170 break; 171 } 172 if (! found) 173 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 174 "Error: helper announced expiration of unknown key!\n"); 175 176 return; 177 } 178 179 GNUNET_break (NULL != bs_pub); 180 for (unsigned int i = 0; i<MAX_KEYS; i++) 181 if (! keys[i].valid) 182 { 183 keys[i].valid = true; 184 keys[i].h_rsa = *h_rsa; 185 keys[i].start_time = start_time; 186 keys[i].validity_duration = validity_duration; 187 keys[i].denom_pub.bsign_pub_key 188 = GNUNET_CRYPTO_bsign_pub_incref (bs_pub); 189 num_keys++; 190 return; 191 } 192 /* too many keys! */ 193 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 194 "Error: received %d live keys from the service!\n", 195 MAX_KEYS + 1); 196 } 197 198 199 /** 200 * Test key revocation logic. 201 * 202 * @param dh handle to the helper 203 * @return 0 on success 204 */ 205 static int 206 test_revocation (struct TALER_CRYPTO_RsaDenominationHelper *dh) 207 { 208 struct timespec req = { 209 .tv_nsec = 250000000 210 }; 211 212 for (unsigned int i = 0; i<NUM_REVOKES; i++) 213 { 214 uint32_t off; 215 216 off = GNUNET_CRYPTO_random_u32 (num_keys); 217 /* find index of key to revoke */ 218 for (unsigned int j = 0; j < MAX_KEYS; j++) 219 { 220 if (! keys[j].valid) 221 continue; 222 if (0 != off) 223 { 224 off--; 225 continue; 226 } 227 keys[j].revoked = true; 228 fprintf (stderr, 229 "Revoking key %s ...", 230 GNUNET_h2s (&keys[j].h_rsa.hash)); 231 TALER_CRYPTO_helper_rsa_revoke (dh, 232 &keys[j].h_rsa); 233 for (unsigned int k = 0; k<1000; k++) 234 { 235 TALER_CRYPTO_helper_rsa_poll (dh); 236 if (! keys[j].revoked) 237 break; 238 nanosleep (&req, NULL); 239 fprintf (stderr, "."); 240 } 241 if (keys[j].revoked) 242 { 243 fprintf (stderr, 244 "\nFAILED: timeout trying to revoke key %u\n", 245 j); 246 TALER_CRYPTO_helper_rsa_disconnect (dh); 247 return 2; 248 } 249 fprintf (stderr, "\n"); 250 break; 251 } 252 } 253 return 0; 254 } 255 256 257 /** 258 * Test signing logic. 259 * 260 * @param dh handle to the helper 261 * @return 0 on success 262 */ 263 static int 264 test_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh) 265 { 266 struct TALER_BlindedDenominationSignature ds; 267 enum TALER_ErrorCode ec; 268 bool success = false; 269 struct TALER_PlanchetMasterSecretP ps; 270 const struct TALER_ExchangeBlindingValues *alg_values 271 = TALER_denom_ewv_rsa_singleton (); 272 struct TALER_AgeCommitmentHashP ach; 273 struct TALER_CoinPubHashP c_hash; 274 struct TALER_CoinSpendPrivateKeyP coin_priv; 275 union GNUNET_CRYPTO_BlindingSecretP bks; 276 277 GNUNET_CRYPTO_random_block (&ps, 278 sizeof (ps)); 279 TALER_planchet_setup_coin_priv (&ps, 280 alg_values, 281 &coin_priv); 282 TALER_planchet_blinding_secret_create (&ps, 283 alg_values, 284 &bks); 285 GNUNET_CRYPTO_random_block (&ach, 286 sizeof(ach)); 287 288 for (unsigned int i = 0; i<MAX_KEYS; i++) 289 { 290 if (! keys[i].valid) 291 continue; 292 if (GNUNET_CRYPTO_BSA_RSA != 293 keys[i].denom_pub.bsign_pub_key->cipher) 294 continue; 295 { 296 struct TALER_PlanchetDetail pd; 297 298 GNUNET_assert (GNUNET_YES == 299 TALER_planchet_prepare (&keys[i].denom_pub, 300 alg_values, 301 &bks, 302 NULL, 303 &coin_priv, 304 &ach, 305 &c_hash, 306 &pd)); 307 { 308 struct TALER_CRYPTO_RsaSignRequest rsr = { 309 .h_rsa = &keys[i].h_rsa, 310 .msg = 311 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 312 blinded_msg, 313 .msg_size = 314 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 315 blinded_msg_size 316 }; 317 318 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 319 "Requesting signature over %u bytes with key %s\n", 320 (unsigned int) rsr.msg_size, 321 GNUNET_h2s (&rsr.h_rsa->hash)); 322 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 323 1, 324 &rsr, 325 &ds); 326 } 327 TALER_blinded_planchet_free (&pd.blinded_planchet); 328 } 329 switch (ec) 330 { 331 case TALER_EC_NONE: 332 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( 333 keys[i].start_time.abs_time), 334 >, 335 GNUNET_TIME_UNIT_SECONDS)) 336 { 337 /* key worked too early */ 338 GNUNET_break (0); 339 return 4; 340 } 341 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( 342 keys[i].start_time.abs_time), 343 >, 344 keys[i].validity_duration)) 345 { 346 /* key worked too later */ 347 GNUNET_break (0); 348 return 5; 349 } 350 { 351 struct TALER_DenominationSignature rs; 352 353 if (GNUNET_OK != 354 TALER_denom_sig_unblind (&rs, 355 &ds, 356 &bks, 357 &c_hash, 358 alg_values, 359 &keys[i].denom_pub)) 360 { 361 GNUNET_break (0); 362 return 6; 363 } 364 TALER_blinded_denom_sig_free (&ds); 365 if (GNUNET_OK != 366 TALER_denom_pub_verify (&keys[i].denom_pub, 367 &rs, 368 &c_hash)) 369 { 370 /* signature invalid */ 371 GNUNET_break (0); 372 TALER_denom_sig_free (&rs); 373 return 7; 374 } 375 TALER_denom_sig_free (&rs); 376 } 377 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 378 "Received valid signature for key %s\n", 379 GNUNET_h2s (&keys[i].h_rsa.hash)); 380 success = true; 381 break; 382 case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY: 383 /* This 'failure' is expected, we're testing also for the 384 error handling! */ 385 if ( (GNUNET_TIME_relative_is_zero ( 386 GNUNET_TIME_absolute_get_remaining ( 387 keys[i].start_time.abs_time))) && 388 (GNUNET_TIME_relative_cmp ( 389 GNUNET_TIME_absolute_get_duration ( 390 keys[i].start_time.abs_time), 391 <, 392 keys[i].validity_duration)) ) 393 { 394 /* key should have worked! */ 395 GNUNET_break (0); 396 return 6; 397 } 398 break; 399 default: 400 /* unexpected error */ 401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 402 "Unexpected error %d at %s:%u\n", 403 ec, 404 __FILE__, 405 __LINE__); 406 return 7; 407 } 408 } 409 if (! success) 410 { 411 /* no valid key for signing found, also bad */ 412 GNUNET_break (0); 413 return 16; 414 } 415 416 /* check signing does not work if the key is unknown */ 417 { 418 struct TALER_RsaPubHashP rnd; 419 struct TALER_CRYPTO_RsaSignRequest rsr = { 420 .h_rsa = &rnd, 421 .msg = "Hello", 422 .msg_size = strlen ("Hello") 423 }; 424 425 GNUNET_CRYPTO_random_block (&rnd, 426 sizeof (rnd)); 427 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 428 1, 429 &rsr, 430 &ds); 431 if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec) 432 { 433 if (TALER_EC_NONE == ec) 434 TALER_blinded_denom_sig_free (&ds); 435 GNUNET_break (0); 436 return 17; 437 } 438 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 439 "Signing with invalid key %s failed as desired\n", 440 GNUNET_h2s (&rnd.hash)); 441 } 442 return 0; 443 } 444 445 446 /** 447 * Test batch signing logic. 448 * 449 * @param dh handle to the helper 450 * @param batch_size how large should the batch be 451 * @param check_sigs also check unknown key and signatures 452 * @return 0 on success 453 */ 454 static int 455 test_batch_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh, 456 unsigned int batch_size, 457 bool check_sigs) 458 { 459 struct TALER_BlindedDenominationSignature ds[batch_size]; 460 enum TALER_ErrorCode ec; 461 bool success = false; 462 struct TALER_PlanchetMasterSecretP ps[batch_size]; 463 const struct TALER_ExchangeBlindingValues *alg_values; 464 struct TALER_AgeCommitmentHashP ach[batch_size]; 465 struct TALER_CoinPubHashP c_hash[batch_size]; 466 struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size]; 467 union GNUNET_CRYPTO_BlindingSecretP bks[batch_size]; 468 469 GNUNET_CRYPTO_random_block (&ps, 470 sizeof (ps)); 471 GNUNET_CRYPTO_random_block (&ach, 472 sizeof(ach)); 473 alg_values = TALER_denom_ewv_rsa_singleton (); 474 for (unsigned int i = 0; i<batch_size; i++) 475 { 476 TALER_planchet_setup_coin_priv (&ps[i], 477 alg_values, 478 &coin_priv[i]); 479 TALER_planchet_blinding_secret_create (&ps[i], 480 alg_values, 481 &bks[i]); 482 } 483 for (unsigned int k = 0; k<MAX_KEYS; k++) 484 { 485 if (success && ! check_sigs) 486 break; /* only do one round */ 487 if (! keys[k].valid) 488 continue; 489 if (GNUNET_CRYPTO_BSA_RSA != 490 keys[k].denom_pub.bsign_pub_key->cipher) 491 continue; 492 { 493 struct TALER_PlanchetDetail pd[batch_size]; 494 struct TALER_CRYPTO_RsaSignRequest rsr[batch_size]; 495 496 for (unsigned int i = 0; i<batch_size; i++) 497 { 498 GNUNET_assert (GNUNET_YES == 499 TALER_planchet_prepare (&keys[k].denom_pub, 500 alg_values, 501 &bks[i], 502 NULL, 503 &coin_priv[i], 504 &ach[i], 505 &c_hash[i], 506 &pd[i])); 507 rsr[i].h_rsa 508 = &keys[k].h_rsa; 509 rsr[i].msg 510 = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message. 511 blinded_msg; 512 rsr[i].msg_size 513 = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message. 514 blinded_msg_size; 515 } 516 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 517 batch_size, 518 rsr, 519 ds); 520 for (unsigned int i = 0; i<batch_size; i++) 521 { 522 if (TALER_EC_NONE == ec) 523 GNUNET_break (GNUNET_CRYPTO_BSA_RSA == 524 ds[i].blinded_sig->cipher); 525 TALER_blinded_planchet_free (&pd[i].blinded_planchet); 526 } 527 } 528 switch (ec) 529 { 530 case TALER_EC_NONE: 531 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( 532 keys[k].start_time.abs_time), 533 >, 534 GNUNET_TIME_UNIT_SECONDS)) 535 { 536 /* key worked too early */ 537 GNUNET_break (0); 538 return 4; 539 } 540 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( 541 keys[k].start_time.abs_time), 542 >, 543 keys[k].validity_duration)) 544 { 545 /* key worked too later */ 546 GNUNET_break (0); 547 return 5; 548 } 549 for (unsigned int i = 0; i<batch_size; i++) 550 { 551 struct TALER_DenominationSignature rs; 552 553 if (check_sigs) 554 { 555 if (GNUNET_OK != 556 TALER_denom_sig_unblind (&rs, 557 &ds[i], 558 &bks[i], 559 &c_hash[i], 560 alg_values, 561 &keys[k].denom_pub)) 562 { 563 GNUNET_break (0); 564 return 6; 565 } 566 } 567 TALER_blinded_denom_sig_free (&ds[i]); 568 if (check_sigs) 569 { 570 if (GNUNET_OK != 571 TALER_denom_pub_verify (&keys[k].denom_pub, 572 &rs, 573 &c_hash[i])) 574 { 575 /* signature invalid */ 576 GNUNET_break (0); 577 TALER_denom_sig_free (&rs); 578 return 7; 579 } 580 TALER_denom_sig_free (&rs); 581 } 582 } 583 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 584 "Received valid signature for key %s\n", 585 GNUNET_h2s (&keys[k].h_rsa.hash)); 586 success = true; 587 break; 588 case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY: 589 /* This 'failure' is expected, we're testing also for the 590 error handling! */ 591 for (unsigned int i = 0; i<batch_size; i++) 592 TALER_blinded_denom_sig_free (&ds[i]); 593 if ( (GNUNET_TIME_relative_is_zero ( 594 GNUNET_TIME_absolute_get_remaining ( 595 keys[k].start_time.abs_time))) && 596 (GNUNET_TIME_relative_cmp ( 597 GNUNET_TIME_absolute_get_duration ( 598 keys[k].start_time.abs_time), 599 <, 600 keys[k].validity_duration)) ) 601 { 602 /* key should have worked! */ 603 GNUNET_break (0); 604 return 6; 605 } 606 break; 607 case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN: 608 for (unsigned int i = 0; i<batch_size; i++) 609 TALER_blinded_denom_sig_free (&ds[i]); 610 break; 611 default: 612 /* unexpected error */ 613 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 614 "Unexpected error %d at %s:%u\n", 615 ec, 616 __FILE__, 617 __LINE__); 618 for (unsigned int i = 0; i<batch_size; i++) 619 TALER_blinded_denom_sig_free (&ds[i]); 620 return 7; 621 } 622 } 623 if (! success) 624 { 625 /* no valid key for signing found, also bad */ 626 GNUNET_break (0); 627 return 16; 628 } 629 630 /* check signing does not work if the key is unknown */ 631 if (check_sigs) 632 { 633 struct TALER_RsaPubHashP rnd; 634 struct TALER_CRYPTO_RsaSignRequest rsr = { 635 .h_rsa = &rnd, 636 .msg = "Hello", 637 .msg_size = strlen ("Hello") 638 }; 639 640 GNUNET_CRYPTO_random_block (&rnd, 641 sizeof (rnd)); 642 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 643 1, 644 &rsr, 645 ds); 646 if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec) 647 { 648 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 649 "Signing with invalid key returned unexpected status %d\n", 650 ec); 651 if (TALER_EC_NONE == ec) 652 TALER_blinded_denom_sig_free (ds); 653 GNUNET_break (0); 654 return 17; 655 } 656 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 657 "Signing with invalid key %s failed as desired\n", 658 GNUNET_h2s (&rnd.hash)); 659 } 660 return 0; 661 } 662 663 664 /** 665 * Benchmark signing logic. 666 * 667 * @param dh handle to the helper 668 * @return 0 on success 669 */ 670 static int 671 perf_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh, 672 const char *type) 673 { 674 struct TALER_BlindedDenominationSignature ds; 675 enum TALER_ErrorCode ec; 676 struct GNUNET_TIME_Relative duration; 677 struct TALER_PlanchetMasterSecretP ps; 678 struct TALER_CoinSpendPrivateKeyP coin_priv; 679 struct TALER_AgeCommitmentHashP ach; 680 union GNUNET_CRYPTO_BlindingSecretP bks; 681 const struct TALER_ExchangeBlindingValues *alg_values 682 = TALER_denom_ewv_rsa_singleton (); 683 684 TALER_planchet_master_setup_random (&ps); 685 TALER_planchet_setup_coin_priv (&ps, 686 alg_values, 687 &coin_priv); 688 TALER_planchet_blinding_secret_create (&ps, 689 alg_values, 690 &bks); 691 GNUNET_CRYPTO_random_block (&ach, 692 sizeof(ach)); 693 duration = GNUNET_TIME_UNIT_ZERO; 694 TALER_CRYPTO_helper_rsa_poll (dh); 695 for (unsigned int j = 0; j<NUM_SIGN_PERFS;) 696 { 697 for (unsigned int i = 0; i<MAX_KEYS; i++) 698 { 699 if (! keys[i].valid) 700 continue; 701 if (GNUNET_CRYPTO_BSA_RSA != 702 keys[i].denom_pub.bsign_pub_key->cipher) 703 continue; 704 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( 705 keys[i].start_time.abs_time), 706 >, 707 GNUNET_TIME_UNIT_SECONDS)) 708 continue; 709 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( 710 keys[i].start_time.abs_time), 711 >, 712 keys[i].validity_duration)) 713 continue; 714 { 715 struct TALER_CoinPubHashP c_hash; 716 struct TALER_PlanchetDetail pd; 717 718 GNUNET_assert (GNUNET_YES == 719 TALER_planchet_prepare (&keys[i].denom_pub, 720 alg_values, 721 &bks, 722 NULL, 723 &coin_priv, 724 &ach, 725 &c_hash, 726 &pd)); 727 /* use this key as long as it works */ 728 while (1) 729 { 730 struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get (); 731 struct GNUNET_TIME_Relative delay; 732 struct TALER_CRYPTO_RsaSignRequest rsr = { 733 .h_rsa = &keys[i].h_rsa, 734 .msg = 735 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 736 blinded_msg, 737 .msg_size = 738 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 739 blinded_msg_size 740 }; 741 742 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 743 1, 744 &rsr, 745 &ds); 746 if (TALER_EC_NONE != ec) 747 break; 748 delay = GNUNET_TIME_absolute_get_duration (start); 749 duration = GNUNET_TIME_relative_add (duration, 750 delay); 751 TALER_blinded_denom_sig_free (&ds); 752 j++; 753 if (NUM_SIGN_PERFS <= j) 754 break; 755 } 756 TALER_blinded_planchet_free (&pd.blinded_planchet); 757 } 758 } /* for i */ 759 } /* for j */ 760 fprintf (stderr, 761 "%u (%s) signature operations took %s\n", 762 (unsigned int) NUM_SIGN_PERFS, 763 type, 764 GNUNET_STRINGS_relative_time_to_string (duration, 765 GNUNET_YES)); 766 return 0; 767 } 768 769 770 /** 771 * Parallel signing logic. 772 * 773 * @param esh handle to the helper 774 * @return 0 on success 775 */ 776 static int 777 par_signing (struct GNUNET_CONFIGURATION_Handle *cfg) 778 { 779 struct GNUNET_TIME_Absolute start; 780 struct GNUNET_TIME_Relative duration; 781 pid_t pids[NUM_CORES]; 782 struct TALER_CRYPTO_RsaDenominationHelper *dh; 783 784 start = GNUNET_TIME_absolute_get (); 785 for (unsigned int i = 0; i<NUM_CORES; i++) 786 { 787 pids[i] = fork (); 788 num_keys = 0; 789 GNUNET_assert (-1 != pids[i]); 790 if (0 == pids[i]) 791 { 792 int ret; 793 794 dh = TALER_CRYPTO_helper_rsa_connect (cfg, 795 "taler-exchange", 796 &key_cb, 797 NULL); 798 GNUNET_assert (NULL != dh); 799 ret = perf_signing (dh, 800 "parallel"); 801 TALER_CRYPTO_helper_rsa_disconnect (dh); 802 free_keys (); 803 exit (ret); 804 } 805 } 806 for (unsigned int i = 0; i<NUM_CORES; i++) 807 { 808 int wstatus; 809 810 GNUNET_assert (pids[i] == 811 waitpid (pids[i], 812 &wstatus, 813 0)); 814 } 815 duration = GNUNET_TIME_absolute_get_duration (start); 816 fprintf (stderr, 817 "%u (parallel) signature operations took %s (total real time)\n", 818 (unsigned int) NUM_SIGN_PERFS * NUM_CORES, 819 GNUNET_STRINGS_relative_time_to_string (duration, 820 GNUNET_YES)); 821 return 0; 822 } 823 824 825 /** 826 * Main entry point into the test logic with the helper already running. 827 */ 828 static int 829 run_test (void) 830 { 831 struct GNUNET_CONFIGURATION_Handle *cfg; 832 struct TALER_CRYPTO_RsaDenominationHelper *dh; 833 struct timespec req = { 834 .tv_nsec = 250000000 835 }; 836 int ret; 837 838 cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ()); 839 if (GNUNET_OK != 840 GNUNET_CONFIGURATION_load (cfg, 841 "test_helper_rsa.conf")) 842 { 843 GNUNET_break (0); 844 return 77; 845 } 846 847 fprintf (stderr, 848 "Waiting for helper to start ... "); 849 for (unsigned int i = 0; i<100; i++) 850 { 851 nanosleep (&req, 852 NULL); 853 dh = TALER_CRYPTO_helper_rsa_connect (cfg, 854 "taler-exchange", 855 &key_cb, 856 NULL); 857 if (NULL != dh) 858 break; 859 fprintf (stderr, "."); 860 } 861 if (NULL == dh) 862 { 863 fprintf (stderr, 864 "\nFAILED: timeout trying to connect to helper\n"); 865 GNUNET_CONFIGURATION_destroy (cfg); 866 return 1; 867 } 868 if (0 == num_keys) 869 { 870 fprintf (stderr, 871 "\nFAILED: timeout trying to connect to helper\n"); 872 TALER_CRYPTO_helper_rsa_disconnect (dh); 873 GNUNET_CONFIGURATION_destroy (cfg); 874 return 1; 875 } 876 fprintf (stderr, 877 " Done (%u keys)\n", 878 num_keys); 879 ret = 0; 880 if (0 == ret) 881 ret = test_revocation (dh); 882 if (0 == ret) 883 ret = test_signing (dh); 884 if (0 == ret) 885 ret = test_batch_signing (dh, 886 2, 887 true); 888 if (0 == ret) 889 ret = test_batch_signing (dh, 890 64, 891 true); 892 for (unsigned int i = 0; i<4; i++) 893 { 894 static unsigned int batches[] = { 1, 4, 16, 64 }; 895 unsigned int batch_size = batches[i]; 896 struct GNUNET_TIME_Absolute start; 897 struct GNUNET_TIME_Relative duration; 898 899 start = GNUNET_TIME_absolute_get (); 900 if (0 != ret) 901 break; 902 ret = test_batch_signing (dh, 903 batch_size, 904 false); 905 duration = GNUNET_TIME_absolute_get_duration (start); 906 fprintf (stderr, 907 "%4u (batch) signature operations took %s (total real time)\n", 908 (unsigned int) batch_size, 909 GNUNET_STRINGS_relative_time_to_string (duration, 910 GNUNET_YES)); 911 } 912 if (0 == ret) 913 ret = perf_signing (dh, 914 "sequential"); 915 TALER_CRYPTO_helper_rsa_disconnect (dh); 916 free_keys (); 917 if (0 == ret) 918 ret = par_signing (cfg); 919 /* clean up our state */ 920 GNUNET_CONFIGURATION_destroy (cfg); 921 return ret; 922 } 923 924 925 int 926 main (int argc, 927 const char *const argv[]) 928 { 929 const char *loglevel = "WARNING"; 930 struct GNUNET_Process *helper; 931 char *libexec_dir; 932 char *binary_name; 933 int ret; 934 enum GNUNET_OS_ProcessStatusType type; 935 unsigned long code; 936 937 (void) argc; 938 (void) argv; 939 unsetenv ("XDG_DATA_HOME"); 940 unsetenv ("XDG_CONFIG_HOME"); 941 GNUNET_log_setup ("test-helper-rsa", 942 loglevel, 943 NULL); 944 libexec_dir = GNUNET_OS_installation_get_path (TALER_EXCHANGE_project_data (), 945 GNUNET_OS_IPK_BINDIR); 946 GNUNET_asprintf (&binary_name, 947 "%s/%s", 948 libexec_dir, 949 "taler-exchange-secmod-rsa"); 950 GNUNET_free (libexec_dir); 951 helper = GNUNET_process_create (GNUNET_OS_INHERIT_STD_ERR); 952 if (GNUNET_OK != 953 GNUNET_process_run_command_va (helper, 954 binary_name, 955 binary_name, 956 "-c", 957 "test_helper_rsa.conf", 958 "-L", 959 loglevel, 960 NULL)) 961 { 962 GNUNET_process_destroy (helper); 963 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 964 "exec", 965 binary_name); 966 GNUNET_free (binary_name); 967 return 77; 968 } 969 GNUNET_free (binary_name); 970 ret = run_test (); 971 972 GNUNET_break (GNUNET_OK == 973 GNUNET_process_kill (helper, 974 SIGTERM)); 975 if (GNUNET_OK != 976 GNUNET_process_wait (helper, 977 true, 978 &type, 979 &code)) 980 { 981 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 982 "Helper process did not die voluntarily, killing hard\n"); 983 GNUNET_break (GNUNET_OK == 984 GNUNET_process_kill (helper, 985 SIGKILL)); 986 ret = 4; 987 } 988 else if ( (GNUNET_OS_PROCESS_EXITED != type) || 989 (0 != code) ) 990 { 991 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 992 "Helper died with unexpected status %d/%d\n", 993 (int) type, 994 (int) code); 995 ret = 5; 996 } 997 GNUNET_process_destroy (helper); 998 return ret; 999 } 1000 1001 1002 /* end of test_helper_rsa.c */