test_helper_rsa.c (31001B)
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 "taler/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 (GNUNET_CRYPTO_QUALITY_WEAK, 217 num_keys); 218 /* find index of key to revoke */ 219 for (unsigned int j = 0; j < MAX_KEYS; j++) 220 { 221 if (! keys[j].valid) 222 continue; 223 if (0 != off) 224 { 225 off--; 226 continue; 227 } 228 keys[j].revoked = true; 229 fprintf (stderr, 230 "Revoking key %s ...", 231 GNUNET_h2s (&keys[j].h_rsa.hash)); 232 TALER_CRYPTO_helper_rsa_revoke (dh, 233 &keys[j].h_rsa); 234 for (unsigned int k = 0; k<1000; k++) 235 { 236 TALER_CRYPTO_helper_rsa_poll (dh); 237 if (! keys[j].revoked) 238 break; 239 nanosleep (&req, NULL); 240 fprintf (stderr, "."); 241 } 242 if (keys[j].revoked) 243 { 244 fprintf (stderr, 245 "\nFAILED: timeout trying to revoke key %u\n", 246 j); 247 TALER_CRYPTO_helper_rsa_disconnect (dh); 248 return 2; 249 } 250 fprintf (stderr, "\n"); 251 break; 252 } 253 } 254 return 0; 255 } 256 257 258 /** 259 * Test signing logic. 260 * 261 * @param dh handle to the helper 262 * @return 0 on success 263 */ 264 static int 265 test_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh) 266 { 267 struct TALER_BlindedDenominationSignature ds; 268 enum TALER_ErrorCode ec; 269 bool success = false; 270 struct TALER_PlanchetMasterSecretP ps; 271 const struct TALER_ExchangeBlindingValues *alg_values 272 = TALER_denom_ewv_rsa_singleton (); 273 struct TALER_AgeCommitmentHashP ach; 274 struct TALER_CoinPubHashP c_hash; 275 struct TALER_CoinSpendPrivateKeyP coin_priv; 276 union GNUNET_CRYPTO_BlindingSecretP bks; 277 278 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, 279 &ps, 280 sizeof (ps)); 281 TALER_planchet_setup_coin_priv (&ps, 282 alg_values, 283 &coin_priv); 284 TALER_planchet_blinding_secret_create (&ps, 285 alg_values, 286 &bks); 287 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 288 &ach, 289 sizeof(ach)); 290 291 for (unsigned int i = 0; i<MAX_KEYS; i++) 292 { 293 if (! keys[i].valid) 294 continue; 295 if (GNUNET_CRYPTO_BSA_RSA != 296 keys[i].denom_pub.bsign_pub_key->cipher) 297 continue; 298 { 299 struct TALER_PlanchetDetail pd; 300 301 GNUNET_assert (GNUNET_YES == 302 TALER_planchet_prepare (&keys[i].denom_pub, 303 alg_values, 304 &bks, 305 NULL, 306 &coin_priv, 307 &ach, 308 &c_hash, 309 &pd)); 310 { 311 struct TALER_CRYPTO_RsaSignRequest rsr = { 312 .h_rsa = &keys[i].h_rsa, 313 .msg = 314 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 315 blinded_msg, 316 .msg_size = 317 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 318 blinded_msg_size 319 }; 320 321 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 322 "Requesting signature over %u bytes with key %s\n", 323 (unsigned int) rsr.msg_size, 324 GNUNET_h2s (&rsr.h_rsa->hash)); 325 ec = TALER_CRYPTO_helper_rsa_sign (dh, 326 &rsr, 327 &ds); 328 } 329 TALER_blinded_planchet_free (&pd.blinded_planchet); 330 } 331 switch (ec) 332 { 333 case TALER_EC_NONE: 334 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( 335 keys[i].start_time.abs_time), 336 >, 337 GNUNET_TIME_UNIT_SECONDS)) 338 { 339 /* key worked too early */ 340 GNUNET_break (0); 341 return 4; 342 } 343 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( 344 keys[i].start_time.abs_time), 345 >, 346 keys[i].validity_duration)) 347 { 348 /* key worked too later */ 349 GNUNET_break (0); 350 return 5; 351 } 352 { 353 struct TALER_DenominationSignature rs; 354 355 if (GNUNET_OK != 356 TALER_denom_sig_unblind (&rs, 357 &ds, 358 &bks, 359 &c_hash, 360 alg_values, 361 &keys[i].denom_pub)) 362 { 363 GNUNET_break (0); 364 return 6; 365 } 366 TALER_blinded_denom_sig_free (&ds); 367 if (GNUNET_OK != 368 TALER_denom_pub_verify (&keys[i].denom_pub, 369 &rs, 370 &c_hash)) 371 { 372 /* signature invalid */ 373 GNUNET_break (0); 374 TALER_denom_sig_free (&rs); 375 return 7; 376 } 377 TALER_denom_sig_free (&rs); 378 } 379 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 380 "Received valid signature for key %s\n", 381 GNUNET_h2s (&keys[i].h_rsa.hash)); 382 success = true; 383 break; 384 case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY: 385 /* This 'failure' is expected, we're testing also for the 386 error handling! */ 387 if ( (GNUNET_TIME_relative_is_zero ( 388 GNUNET_TIME_absolute_get_remaining ( 389 keys[i].start_time.abs_time))) && 390 (GNUNET_TIME_relative_cmp ( 391 GNUNET_TIME_absolute_get_duration ( 392 keys[i].start_time.abs_time), 393 <, 394 keys[i].validity_duration)) ) 395 { 396 /* key should have worked! */ 397 GNUNET_break (0); 398 return 6; 399 } 400 break; 401 default: 402 /* unexpected error */ 403 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 404 "Unexpected error %d at %s:%u\n", 405 ec, 406 __FILE__, 407 __LINE__); 408 return 7; 409 } 410 } 411 if (! success) 412 { 413 /* no valid key for signing found, also bad */ 414 GNUNET_break (0); 415 return 16; 416 } 417 418 /* check signing does not work if the key is unknown */ 419 { 420 struct TALER_RsaPubHashP rnd; 421 struct TALER_CRYPTO_RsaSignRequest rsr = { 422 .h_rsa = &rnd, 423 .msg = "Hello", 424 .msg_size = strlen ("Hello") 425 }; 426 427 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 428 &rnd, 429 sizeof (rnd)); 430 ec = TALER_CRYPTO_helper_rsa_sign (dh, 431 &rsr, 432 &ds); 433 if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec) 434 { 435 if (TALER_EC_NONE == ec) 436 TALER_blinded_denom_sig_free (&ds); 437 GNUNET_break (0); 438 return 17; 439 } 440 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 441 "Signing with invalid key %s failed as desired\n", 442 GNUNET_h2s (&rnd.hash)); 443 } 444 return 0; 445 } 446 447 448 /** 449 * Test batch signing logic. 450 * 451 * @param dh handle to the helper 452 * @param batch_size how large should the batch be 453 * @param check_sigs also check unknown key and signatures 454 * @return 0 on success 455 */ 456 static int 457 test_batch_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh, 458 unsigned int batch_size, 459 bool check_sigs) 460 { 461 struct TALER_BlindedDenominationSignature ds[batch_size]; 462 enum TALER_ErrorCode ec; 463 bool success = false; 464 struct TALER_PlanchetMasterSecretP ps[batch_size]; 465 const struct TALER_ExchangeBlindingValues *alg_values; 466 struct TALER_AgeCommitmentHashP ach[batch_size]; 467 struct TALER_CoinPubHashP c_hash[batch_size]; 468 struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size]; 469 union GNUNET_CRYPTO_BlindingSecretP bks[batch_size]; 470 471 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, 472 &ps, 473 sizeof (ps)); 474 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 475 &ach, 476 sizeof(ach)); 477 alg_values = TALER_denom_ewv_rsa_singleton (); 478 for (unsigned int i = 0; i<batch_size; i++) 479 { 480 TALER_planchet_setup_coin_priv (&ps[i], 481 alg_values, 482 &coin_priv[i]); 483 TALER_planchet_blinding_secret_create (&ps[i], 484 alg_values, 485 &bks[i]); 486 } 487 for (unsigned int k = 0; k<MAX_KEYS; k++) 488 { 489 if (success && ! check_sigs) 490 break; /* only do one round */ 491 if (! keys[k].valid) 492 continue; 493 if (GNUNET_CRYPTO_BSA_RSA != 494 keys[k].denom_pub.bsign_pub_key->cipher) 495 continue; 496 { 497 struct TALER_PlanchetDetail pd[batch_size]; 498 struct TALER_CRYPTO_RsaSignRequest rsr[batch_size]; 499 500 for (unsigned int i = 0; i<batch_size; i++) 501 { 502 GNUNET_assert (GNUNET_YES == 503 TALER_planchet_prepare (&keys[k].denom_pub, 504 alg_values, 505 &bks[i], 506 NULL, 507 &coin_priv[i], 508 &ach[i], 509 &c_hash[i], 510 &pd[i])); 511 rsr[i].h_rsa 512 = &keys[k].h_rsa; 513 rsr[i].msg 514 = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message. 515 blinded_msg; 516 rsr[i].msg_size 517 = pd[i].blinded_planchet.blinded_message->details.rsa_blinded_message. 518 blinded_msg_size; 519 } 520 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 521 batch_size, 522 rsr, 523 ds); 524 for (unsigned int i = 0; i<batch_size; i++) 525 { 526 if (TALER_EC_NONE == ec) 527 GNUNET_break (GNUNET_CRYPTO_BSA_RSA == 528 ds[i].blinded_sig->cipher); 529 TALER_blinded_planchet_free (&pd[i].blinded_planchet); 530 } 531 } 532 switch (ec) 533 { 534 case TALER_EC_NONE: 535 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( 536 keys[k].start_time.abs_time), 537 >, 538 GNUNET_TIME_UNIT_SECONDS)) 539 { 540 /* key worked too early */ 541 GNUNET_break (0); 542 return 4; 543 } 544 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( 545 keys[k].start_time.abs_time), 546 >, 547 keys[k].validity_duration)) 548 { 549 /* key worked too later */ 550 GNUNET_break (0); 551 return 5; 552 } 553 for (unsigned int i = 0; i<batch_size; i++) 554 { 555 struct TALER_DenominationSignature rs; 556 557 if (check_sigs) 558 { 559 if (GNUNET_OK != 560 TALER_denom_sig_unblind (&rs, 561 &ds[i], 562 &bks[i], 563 &c_hash[i], 564 alg_values, 565 &keys[k].denom_pub)) 566 { 567 GNUNET_break (0); 568 return 6; 569 } 570 } 571 TALER_blinded_denom_sig_free (&ds[i]); 572 if (check_sigs) 573 { 574 if (GNUNET_OK != 575 TALER_denom_pub_verify (&keys[k].denom_pub, 576 &rs, 577 &c_hash[i])) 578 { 579 /* signature invalid */ 580 GNUNET_break (0); 581 TALER_denom_sig_free (&rs); 582 return 7; 583 } 584 TALER_denom_sig_free (&rs); 585 } 586 } 587 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 588 "Received valid signature for key %s\n", 589 GNUNET_h2s (&keys[k].h_rsa.hash)); 590 success = true; 591 break; 592 case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY: 593 /* This 'failure' is expected, we're testing also for the 594 error handling! */ 595 for (unsigned int i = 0; i<batch_size; i++) 596 TALER_blinded_denom_sig_free (&ds[i]); 597 if ( (GNUNET_TIME_relative_is_zero ( 598 GNUNET_TIME_absolute_get_remaining ( 599 keys[k].start_time.abs_time))) && 600 (GNUNET_TIME_relative_cmp ( 601 GNUNET_TIME_absolute_get_duration ( 602 keys[k].start_time.abs_time), 603 <, 604 keys[k].validity_duration)) ) 605 { 606 /* key should have worked! */ 607 GNUNET_break (0); 608 return 6; 609 } 610 break; 611 case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN: 612 for (unsigned int i = 0; i<batch_size; i++) 613 TALER_blinded_denom_sig_free (&ds[i]); 614 break; 615 default: 616 /* unexpected error */ 617 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 618 "Unexpected error %d at %s:%u\n", 619 ec, 620 __FILE__, 621 __LINE__); 622 for (unsigned int i = 0; i<batch_size; i++) 623 TALER_blinded_denom_sig_free (&ds[i]); 624 return 7; 625 } 626 } 627 if (! success) 628 { 629 /* no valid key for signing found, also bad */ 630 GNUNET_break (0); 631 return 16; 632 } 633 634 /* check signing does not work if the key is unknown */ 635 if (check_sigs) 636 { 637 struct TALER_RsaPubHashP rnd; 638 struct TALER_CRYPTO_RsaSignRequest rsr = { 639 .h_rsa = &rnd, 640 .msg = "Hello", 641 .msg_size = strlen ("Hello") 642 }; 643 644 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 645 &rnd, 646 sizeof (rnd)); 647 ec = TALER_CRYPTO_helper_rsa_batch_sign (dh, 648 1, 649 &rsr, 650 ds); 651 if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec) 652 { 653 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 654 "Signing with invalid key returned unexpected status %d\n", 655 ec); 656 if (TALER_EC_NONE == ec) 657 TALER_blinded_denom_sig_free (ds); 658 GNUNET_break (0); 659 return 17; 660 } 661 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 662 "Signing with invalid key %s failed as desired\n", 663 GNUNET_h2s (&rnd.hash)); 664 } 665 return 0; 666 } 667 668 669 /** 670 * Benchmark signing logic. 671 * 672 * @param dh handle to the helper 673 * @return 0 on success 674 */ 675 static int 676 perf_signing (struct TALER_CRYPTO_RsaDenominationHelper *dh, 677 const char *type) 678 { 679 struct TALER_BlindedDenominationSignature ds; 680 enum TALER_ErrorCode ec; 681 struct GNUNET_TIME_Relative duration; 682 struct TALER_PlanchetMasterSecretP ps; 683 struct TALER_CoinSpendPrivateKeyP coin_priv; 684 struct TALER_AgeCommitmentHashP ach; 685 union GNUNET_CRYPTO_BlindingSecretP bks; 686 const struct TALER_ExchangeBlindingValues *alg_values 687 = TALER_denom_ewv_rsa_singleton (); 688 689 TALER_planchet_master_setup_random (&ps); 690 TALER_planchet_setup_coin_priv (&ps, 691 alg_values, 692 &coin_priv); 693 TALER_planchet_blinding_secret_create (&ps, 694 alg_values, 695 &bks); 696 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 697 &ach, 698 sizeof(ach)); 699 duration = GNUNET_TIME_UNIT_ZERO; 700 TALER_CRYPTO_helper_rsa_poll (dh); 701 for (unsigned int j = 0; j<NUM_SIGN_PERFS;) 702 { 703 for (unsigned int i = 0; i<MAX_KEYS; i++) 704 { 705 if (! keys[i].valid) 706 continue; 707 if (GNUNET_CRYPTO_BSA_RSA != 708 keys[i].denom_pub.bsign_pub_key->cipher) 709 continue; 710 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining ( 711 keys[i].start_time.abs_time), 712 >, 713 GNUNET_TIME_UNIT_SECONDS)) 714 continue; 715 if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration ( 716 keys[i].start_time.abs_time), 717 >, 718 keys[i].validity_duration)) 719 continue; 720 { 721 struct TALER_CoinPubHashP c_hash; 722 struct TALER_PlanchetDetail pd; 723 724 GNUNET_assert (GNUNET_YES == 725 TALER_planchet_prepare (&keys[i].denom_pub, 726 alg_values, 727 &bks, 728 NULL, 729 &coin_priv, 730 &ach, 731 &c_hash, 732 &pd)); 733 /* use this key as long as it works */ 734 while (1) 735 { 736 struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get (); 737 struct GNUNET_TIME_Relative delay; 738 struct TALER_CRYPTO_RsaSignRequest rsr = { 739 .h_rsa = &keys[i].h_rsa, 740 .msg = 741 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 742 blinded_msg, 743 .msg_size = 744 pd.blinded_planchet.blinded_message->details.rsa_blinded_message. 745 blinded_msg_size 746 }; 747 748 ec = TALER_CRYPTO_helper_rsa_sign (dh, 749 &rsr, 750 &ds); 751 if (TALER_EC_NONE != ec) 752 break; 753 delay = GNUNET_TIME_absolute_get_duration (start); 754 duration = GNUNET_TIME_relative_add (duration, 755 delay); 756 TALER_blinded_denom_sig_free (&ds); 757 j++; 758 if (NUM_SIGN_PERFS <= j) 759 break; 760 } 761 TALER_blinded_planchet_free (&pd.blinded_planchet); 762 } 763 } /* for i */ 764 } /* for j */ 765 fprintf (stderr, 766 "%u (%s) signature operations took %s\n", 767 (unsigned int) NUM_SIGN_PERFS, 768 type, 769 GNUNET_STRINGS_relative_time_to_string (duration, 770 GNUNET_YES)); 771 return 0; 772 } 773 774 775 /** 776 * Parallel signing logic. 777 * 778 * @param esh handle to the helper 779 * @return 0 on success 780 */ 781 static int 782 par_signing (struct GNUNET_CONFIGURATION_Handle *cfg) 783 { 784 struct GNUNET_TIME_Absolute start; 785 struct GNUNET_TIME_Relative duration; 786 pid_t pids[NUM_CORES]; 787 struct TALER_CRYPTO_RsaDenominationHelper *dh; 788 789 start = GNUNET_TIME_absolute_get (); 790 for (unsigned int i = 0; i<NUM_CORES; i++) 791 { 792 pids[i] = fork (); 793 num_keys = 0; 794 GNUNET_assert (-1 != pids[i]); 795 if (0 == pids[i]) 796 { 797 int ret; 798 799 dh = TALER_CRYPTO_helper_rsa_connect (cfg, 800 "taler-exchange", 801 &key_cb, 802 NULL); 803 GNUNET_assert (NULL != dh); 804 ret = perf_signing (dh, 805 "parallel"); 806 TALER_CRYPTO_helper_rsa_disconnect (dh); 807 free_keys (); 808 exit (ret); 809 } 810 } 811 for (unsigned int i = 0; i<NUM_CORES; i++) 812 { 813 int wstatus; 814 815 GNUNET_assert (pids[i] == 816 waitpid (pids[i], 817 &wstatus, 818 0)); 819 } 820 duration = GNUNET_TIME_absolute_get_duration (start); 821 fprintf (stderr, 822 "%u (parallel) signature operations took %s (total real time)\n", 823 (unsigned int) NUM_SIGN_PERFS * NUM_CORES, 824 GNUNET_STRINGS_relative_time_to_string (duration, 825 GNUNET_YES)); 826 return 0; 827 } 828 829 830 /** 831 * Main entry point into the test logic with the helper already running. 832 */ 833 static int 834 run_test (void) 835 { 836 struct GNUNET_CONFIGURATION_Handle *cfg; 837 struct TALER_CRYPTO_RsaDenominationHelper *dh; 838 struct timespec req = { 839 .tv_nsec = 250000000 840 }; 841 int ret; 842 843 cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ()); 844 if (GNUNET_OK != 845 GNUNET_CONFIGURATION_load (cfg, 846 "test_helper_rsa.conf")) 847 { 848 GNUNET_break (0); 849 return 77; 850 } 851 852 fprintf (stderr, 853 "Waiting for helper to start ... "); 854 for (unsigned int i = 0; i<100; i++) 855 { 856 nanosleep (&req, 857 NULL); 858 dh = TALER_CRYPTO_helper_rsa_connect (cfg, 859 "taler-exchange", 860 &key_cb, 861 NULL); 862 if (NULL != dh) 863 break; 864 fprintf (stderr, "."); 865 } 866 if (NULL == dh) 867 { 868 fprintf (stderr, 869 "\nFAILED: timeout trying to connect to helper\n"); 870 GNUNET_CONFIGURATION_destroy (cfg); 871 return 1; 872 } 873 if (0 == num_keys) 874 { 875 fprintf (stderr, 876 "\nFAILED: timeout trying to connect to helper\n"); 877 TALER_CRYPTO_helper_rsa_disconnect (dh); 878 GNUNET_CONFIGURATION_destroy (cfg); 879 return 1; 880 } 881 fprintf (stderr, 882 " Done (%u keys)\n", 883 num_keys); 884 ret = 0; 885 if (0 == ret) 886 ret = test_revocation (dh); 887 if (0 == ret) 888 ret = test_signing (dh); 889 if (0 == ret) 890 ret = test_batch_signing (dh, 891 2, 892 true); 893 if (0 == ret) 894 ret = test_batch_signing (dh, 895 64, 896 true); 897 for (unsigned int i = 0; i<4; i++) 898 { 899 static unsigned int batches[] = { 1, 4, 16, 64 }; 900 unsigned int batch_size = batches[i]; 901 struct GNUNET_TIME_Absolute start; 902 struct GNUNET_TIME_Relative duration; 903 904 start = GNUNET_TIME_absolute_get (); 905 if (0 != ret) 906 break; 907 ret = test_batch_signing (dh, 908 batch_size, 909 false); 910 duration = GNUNET_TIME_absolute_get_duration (start); 911 fprintf (stderr, 912 "%4u (batch) signature operations took %s (total real time)\n", 913 (unsigned int) batch_size, 914 GNUNET_STRINGS_relative_time_to_string (duration, 915 GNUNET_YES)); 916 } 917 if (0 == ret) 918 ret = perf_signing (dh, 919 "sequential"); 920 TALER_CRYPTO_helper_rsa_disconnect (dh); 921 free_keys (); 922 if (0 == ret) 923 ret = par_signing (cfg); 924 /* clean up our state */ 925 GNUNET_CONFIGURATION_destroy (cfg); 926 return ret; 927 } 928 929 930 int 931 main (int argc, 932 const char *const argv[]) 933 { 934 struct GNUNET_OS_Process *helper; 935 char *libexec_dir; 936 char *binary_name; 937 int ret; 938 enum GNUNET_OS_ProcessStatusType type; 939 unsigned long code; 940 941 (void) argc; 942 (void) argv; 943 unsetenv ("XDG_DATA_HOME"); 944 unsetenv ("XDG_CONFIG_HOME"); 945 GNUNET_log_setup ("test-helper-rsa", 946 "WARNING", 947 NULL); 948 libexec_dir = GNUNET_OS_installation_get_path (TALER_EXCHANGE_project_data (), 949 GNUNET_OS_IPK_BINDIR); 950 GNUNET_asprintf (&binary_name, 951 "%s/%s", 952 libexec_dir, 953 "taler-exchange-secmod-rsa"); 954 GNUNET_free (libexec_dir); 955 helper = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR, 956 NULL, NULL, NULL, 957 binary_name, 958 binary_name, 959 "-c", 960 "test_helper_rsa.conf", 961 "-L", 962 "WARNING", 963 NULL); 964 if (NULL == helper) 965 { 966 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, 967 "exec", 968 binary_name); 969 GNUNET_free (binary_name); 970 return 77; 971 } 972 GNUNET_free (binary_name); 973 ret = run_test (); 974 975 GNUNET_OS_process_kill (helper, 976 SIGTERM); 977 if (GNUNET_OK != 978 GNUNET_OS_process_wait_status (helper, 979 &type, 980 &code)) 981 { 982 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 983 "Helper process did not die voluntarily, killing hard\n"); 984 GNUNET_OS_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_OS_process_destroy (helper); 998 return ret; 999 } 1000 1001 1002 /* end of test_helper_rsa.c */